Skip to content

Commit

Permalink
Merge pull request #5 from Darlington02/main
Browse files Browse the repository at this point in the history
make registry multi-implementation compatible
  • Loading branch information
Darlington02 authored Jul 28, 2023
2 parents ca0a222 + 0523343 commit bf51e9d
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 9 deletions.
7 changes: 7 additions & 0 deletions src/interfaces/IRegistry.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
use starknet::ContractAddress;

#[starknet::interface]
trait IRegistry<TContractState> {
fn create_account(ref self: TContractState, implementation_hash: felt252, public_key: felt252, token_contract: ContractAddress, token_id: u256, salt: felt252);
fn get_account(self: @TContractState, token_contract: ContractAddress, token_id: u256) -> ContractAddress;
}
83 changes: 74 additions & 9 deletions src/registry/registry.cairo
Original file line number Diff line number Diff line change
@@ -1,9 +1,29 @@
use core::array::SpanTrait;
use starknet::ContractAddress;

#[starknet::interface]
trait IRegistry<TContractState> {
fn create_account(ref self: TContractState, implementation_hash: felt252, public_key: felt252, token_contract: ContractAddress, token_id: u256, salt: felt252);
fn get_account(self: @TContractState, token_contract: ContractAddress, token_id: u256) -> ContractAddress;
fn create_account(ref self: TContractState, implementation_hash: felt252, public_key: felt252, token_contract: ContractAddress, token_id: u256);
fn get_account(self: @TContractState, implementation_hash: felt252, public_key: felt252, token_contract: ContractAddress, token_id: u256) -> ContractAddress;
fn total_deployed_accounts(self: @TContractState, token_contract: ContractAddress, token_id: u256) -> u8;
}

#[starknet::interface]
trait IERC721<TContractState> {
fn balance_of(self: @TContractState, account: ContractAddress) -> u256;
fn owner_of(self: @TContractState, token_id: u256) -> ContractAddress;
fn transfer_from(ref self: TContractState, from: ContractAddress, to: ContractAddress, token_id: u256);
fn safe_transfer_from(
ref self: TContractState, from: ContractAddress, to: ContractAddress, token_id: u256, data: Span<felt252>
);
fn approve(ref self: TContractState, to: ContractAddress, token_id: u256);
fn set_approval_for_all(ref self: TContractState, operator: ContractAddress, approved: bool);
fn get_approved(self: @TContractState, token_id: u256) -> ContractAddress;
fn is_approved_for_all(self: @TContractState, owner: ContractAddress, operator: ContractAddress) -> bool;
// IERC721Metadata
fn name(self: @TContractState) -> felt252;
fn symbol(self: @TContractState) -> felt252;
fn token_uri(self: @TContractState, token_id: u256) -> felt252;
}

#[starknet::contract]
Expand All @@ -14,10 +34,14 @@ mod Registry {
use traits::Into;
use option::OptionTrait;
use array::ArrayTrait;

use array::SpanTrait;

use super::IERC721DispatcherTrait;
use super::IERC721Dispatcher;

#[storage]
struct Storage {
deployed_accounts: LegacyMap<(ContractAddress, u256), ContractAddress>
registry_deployed_accounts: LegacyMap<(ContractAddress, u256), u8>,
}

#[event]
Expand All @@ -41,9 +65,9 @@ mod Registry {
public_key: felt252,
token_contract: ContractAddress,
token_id: u256,
salt: felt252,
) {
assert(self.deployed_accounts.read((token_contract, token_id)).is_zero(), 'TBA_ALREADY_DEPLOYED');
let owner = IERC721Dispatcher { contract_address: token_contract }.owner_of(token_id);
assert(owner == get_caller_address(), 'CALLER_IS_NOT_OWNER');

let mut constructor_calldata: Array<felt252> = ArrayTrait::new();
constructor_calldata.append(public_key);
Expand All @@ -52,10 +76,12 @@ mod Registry {
constructor_calldata.append(token_id.high.into());

let class_hash: ClassHash = implementation_hash.try_into().unwrap();
let salt = pedersen(token_contract.into(), token_id.low.into());
let result = deploy_syscall(class_hash, salt, constructor_calldata.span(), true);
let (account_address, _) = result.unwrap_syscall();

self.deployed_accounts.write((token_contract, token_id), account_address);
let no_of_deployed_accounts: u8 = self.registry_deployed_accounts.read((token_contract, token_id));
self.registry_deployed_accounts.write((token_contract, token_id), no_of_deployed_accounts + 1_u8);

self.emit(
AccountCreated {
Expand All @@ -66,8 +92,47 @@ mod Registry {
);
}

fn get_account(self: @ContractState, token_contract: ContractAddress, token_id: u256) -> ContractAddress {
self.deployed_accounts.read((token_contract, token_id))
fn get_account(self: @ContractState, implementation_hash: felt252, public_key: felt252, token_contract: ContractAddress, token_id: u256) -> ContractAddress {
let mut constructor_calldata: Array<felt252> = ArrayTrait::new();
constructor_calldata.append(public_key);
constructor_calldata.append(token_contract.into());
constructor_calldata.append(token_id.low.into());
constructor_calldata.append(token_id.high.into());

let salt = pedersen(token_contract.into(), token_id.low.into());
let constructor_calldata_hash = self.array_hashing(constructor_calldata.span());
let account_address = pedersen(
'STARKNET_CONTRACT_ADDRESS',
0,
salt,
implementation_hash,
constructor_calldata_hash
);

account_address.try_into().unwrap()
}

fn total_deployed_accounts(self: @ContractState, token_contract: ContractAddress, token_id: u256) -> u8 {
self.registry_deployed_accounts.read((token_contract, token_id))
}
}

#[generate_trait]
impl RegistryHelperImpl of RegistryHelperTrait {
fn array_hashing(self: @ContractState, array: Span<felt252>) -> felt252 {
let mut array = array;
let mut array_hash: felt252 = 0;

loop {
match array.pop_front() {
Option::Some(item) => {
array_hash = pedersen(array_hash, *item);
},
Option::None(_) => {
break array_hash;
}
};
}
}
}
}

0 comments on commit bf51e9d

Please sign in to comment.