From 9964483639939c08527fd6ec07e768c4abdca3de Mon Sep 17 00:00:00 2001 From: Darlington02 Date: Sat, 7 Sep 2024 05:04:07 +0100 Subject: [PATCH] chore: refactor, introduce `context` --- src/components/account/account.cairo | 80 +++++++--- src/components/presets/account_preset.cairo | 11 +- src/components/signatory/signatory.cairo | 53 +------ src/interfaces/IAccount.cairo | 5 +- src/registry/registry.cairo | 17 ++- tests/test_account_component.cairo | 159 +++++++++++++++++--- tests/test_lockable_component.cairo | 15 +- tests/test_permissionable_component.cairo | 17 ++- tests/test_signatory_component.cairo | 56 ++----- tests/test_upgradeable.cairo | 15 +- 10 files changed, 283 insertions(+), 145 deletions(-) diff --git a/src/components/account/account.cairo b/src/components/account/account.cairo index dd9729f..c8ea629 100644 --- a/src/components/account/account.cairo +++ b/src/components/account/account.cairo @@ -29,7 +29,8 @@ pub mod AccountComponent { pub struct Storage { account_token_contract: ContractAddress, // contract address of NFT account_token_id: u256, // token ID of NFT - state: u256 + context: Context, // account deployment details + state: u256 // account state } // ************************************************************************* @@ -65,6 +66,16 @@ pub mod AccountComponent { pub response: Span> } + // ************************************************************************* + // STRUCTS + // ************************************************************************* + #[derive(Copy, Drop, starknet::Store)] + struct Context { + registry: ContractAddress, + implementation_hash: felt252, + salt: felt252 + } + // ************************************************************************* // ERRORS // ************************************************************************* @@ -90,15 +101,6 @@ pub mod AccountComponent { self._get_owner(token_contract, token_id) } - /// @notice returns the root owner for nested tokenbound accounts - /// @param token_contract the contract address of the NFT - /// @param token_id the token ID of the NFT - fn get_root_owner( - self: @ComponentState, token_contract: ContractAddress, token_id: u256 - ) -> ContractAddress { - self._get_root_owner(token_contract, token_id) - } - /// @notice returns the contract address and token ID of the associated NFT fn token(self: @ComponentState) -> (ContractAddress, u256, felt252) { self._get_token() @@ -133,13 +135,20 @@ pub mod AccountComponent { fn initializer( ref self: ComponentState, token_contract: ContractAddress, - token_id: u256 + token_id: u256, + registry: ContractAddress, + implementation_hash: felt252, + salt: felt252 ) { let owner = self._get_owner(token_contract, token_id); assert(owner.is_non_zero(), Errors::UNAUTHORIZED); + // initialize account self.account_token_contract.write(token_contract); self.account_token_id.write(token_id); + self.context.write(Context { registry, implementation_hash, salt }); + + // emit event self .emit( TBACreated { @@ -208,21 +217,46 @@ pub mod AccountComponent { Serde::::deserialize(ref address).unwrap() } - /// @notice internal function for getting the root NFT owner + /// @notice internal function to retrieve deployment details of an account + fn _context(self: @ComponentState) -> (ContractAddress, felt252, felt252) { + let context = self.context.read(); + (context.registry, context.implementation_hash, context.salt) + } + + /// @notice internal function for checking if an account is a tokenbound account /// @param token_contract contract address of NFT - // @param token_id token ID of NFT - // NB: This function aims for compatibility with all contracts (snake or camel case) but do - // not work as expected on mainnet as low level calls do not return err at the moment. - // Should work for contracts which implements CamelCase but not snake_case until starknet - // v0.15. - fn _get_root_owner( - self: @ComponentState, token_contract: ContractAddress, token_id: u256 - ) -> ContractAddress { - // TODO: implement logic to get root owner + /// @param token_id token ID of NFT + fn _is_tokenbound_account( + self: @ComponentState, + account: ContractAddress, + token_contract: ContractAddress, + token_id: u256, + registry: ContractAddress, + implementation: felt252, + salt: felt252 + ) -> bool { + let constructor_calldata_hash = PedersenTrait::new(0) + .update(token_contract.into()) + .update(token_id.low.into()) + .update(token_id.high.into()) + .update(registry.into()) + .update(implementation) + .update(salt) + .update(6) + .finalize(); - 1.try_into().unwrap() - } + let prefix: felt252 = 'STARKNET_CONTRACT_ADDRESS'; + let account_address = PedersenTrait::new(0) + .update(prefix) + .update(0) + .update(salt) + .update(implementation) + .update(constructor_calldata_hash) + .update(5) + .finalize(); + account_address.try_into().unwrap() == account + } /// @notice internal transaction for returning the contract address and token ID of the NFT fn _get_token(self: @ComponentState) -> (ContractAddress, u256, felt252) { diff --git a/src/components/presets/account_preset.cairo b/src/components/presets/account_preset.cairo index 5fa7848..24386dc 100644 --- a/src/components/presets/account_preset.cairo +++ b/src/components/presets/account_preset.cairo @@ -68,8 +68,15 @@ pub mod AccountPreset { // CONSTRUCTOR // ************************************************************************* #[constructor] - fn constructor(ref self: ContractState, token_contract: ContractAddress, token_id: u256) { - self.account.initializer(token_contract, token_id); + fn constructor( + ref self: ContractState, + token_contract: ContractAddress, + token_id: u256, + registry: ContractAddress, + implementation_hash: felt252, + salt: felt252 + ) { + self.account.initializer(token_contract, token_id, registry, implementation_hash, salt); } // ************************************************************************* diff --git a/src/components/signatory/signatory.cairo b/src/components/signatory/signatory.cairo index bbc3f6c..07e8935 100644 --- a/src/components/signatory/signatory.cairo +++ b/src/components/signatory/signatory.cairo @@ -8,7 +8,7 @@ pub mod SignatoryComponent { // ************************************************************************* use starknet::{get_caller_address, get_contract_address, ContractAddress}; use token_bound_accounts::components::account::account::AccountComponent; - use token_bound_accounts::components::account::account::AccountComponent::InternalImpl; + use token_bound_accounts::components::account::account::AccountComponent::AccountImpl; use token_bound_accounts::components::permissionable::permissionable::PermissionableComponent; use token_bound_accounts::components::permissionable::permissionable::PermissionableComponent::PermissionableImpl; use token_bound_accounts::interfaces::ISRC6::{ISRC6Dispatcher, ISRC6DispatcherTrait}; @@ -45,10 +45,7 @@ pub mod SignatoryComponent { self: @ComponentState, signer: ContractAddress ) -> bool { let account = get_dep_component!(self, Account); - let (contract_address, token_id, _) = account._get_token(); - - // get owner - let owner = account._get_owner(contract_address, token_id); + let owner = account.owner(); // validate if (signer == owner) { @@ -58,31 +55,6 @@ pub mod SignatoryComponent { } } - /// @notice implements a signer validation where both NFT owner and the root owner (for - /// nested accounts) are valid signers. - /// @param signer the address to be validated - fn _base_and_root_signer_validation( - self: @ComponentState, signer: ContractAddress - ) -> bool { - let account = get_dep_component!(self, Account); - let (contract_address, token_id, _) = account._get_token(); - - // get owner - let owner = account._get_owner(contract_address, token_id); - // get root owner - let root_owner = account._get_root_owner(contract_address, token_id); - - // validate - if (signer == owner) { - return true; - } else if (signer == root_owner) { - return true; - } else { - return false; - } - } - - /// @notice implements a more complex signer validation where NFT owner, root owner, and /// permissioned addresses are valid signers. /// @param signer the address to be validated @@ -90,12 +62,7 @@ pub mod SignatoryComponent { self: @ComponentState, signer: ContractAddress ) -> bool { let account = get_dep_component!(self, Account); - let (contract_address, token_id, _) = account._get_token(); - - // get owner - let owner = account._get_owner(contract_address, token_id); - // get root owner - let root_owner = account._get_root_owner(contract_address, token_id); + let owner = account.owner(); // check if signer has permissions let permission = get_dep_component!(self, Permissionable); @@ -104,8 +71,6 @@ pub mod SignatoryComponent { // validate if (signer == owner) { return true; - } else if (signer == root_owner) { - return true; } else if (is_permissioned) { return true; } else { @@ -120,22 +85,16 @@ pub mod SignatoryComponent { self: @ComponentState, hash: felt252, signature: Span ) -> felt252 { let account = get_dep_component!(self, Account); - let (contract_address, token_id, _) = account._get_token(); - let owner = account._get_owner(contract_address, token_id); - let root_owner = account._get_root_owner(contract_address, token_id); + let owner = account.owner(); + // validate signature length let signature_length = signature.len(); assert(signature_length == 2_u32, Errors::INV_SIG_LEN); - let owner_account = ISRC6Dispatcher { contract_address: owner }; - let root_owner_account = ISRC6Dispatcher { contract_address: root_owner }; - // validate + let owner_account = ISRC6Dispatcher { contract_address: owner }; if (owner_account.is_valid_signature(hash, signature) == starknet::VALIDATED) { return starknet::VALIDATED; - } else if (root_owner_account - .is_valid_signature(hash, signature) == starknet::VALIDATED) { - return starknet::VALIDATED; } else { return Errors::INVALID_SIGNATURE; } diff --git a/src/interfaces/IAccount.cairo b/src/interfaces/IAccount.cairo index 535beab..aee759d 100644 --- a/src/interfaces/IAccount.cairo +++ b/src/interfaces/IAccount.cairo @@ -11,11 +11,8 @@ pub const TBA_INTERFACE_ID: felt252 = #[starknet::interface] pub trait IAccount { - fn token(self: @TContractState) -> (ContractAddress, u256, felt252); fn owner(self: @TContractState) -> ContractAddress; - fn get_root_owner( - self: @TContractState, token_contract: ContractAddress, token_id: u256 - ) -> ContractAddress; + fn token(self: @TContractState) -> (ContractAddress, u256, felt252); fn state(self: @TContractState) -> u256; fn supports_interface(self: @TContractState, interface_id: felt252) -> bool; } diff --git a/src/registry/registry.cairo b/src/registry/registry.cairo index 7791fc1..b2f0720 100644 --- a/src/registry/registry.cairo +++ b/src/registry/registry.cairo @@ -10,8 +10,9 @@ pub mod Registry { use core::hash::HashStateTrait; use core::pedersen::PedersenTrait; use starknet::{ - ContractAddress, get_caller_address, syscalls::{call_contract_syscall, deploy_syscall}, - class_hash::ClassHash, SyscallResultTrait, storage::Map + ContractAddress, get_caller_address, get_contract_address, + syscalls::{call_contract_syscall, deploy_syscall}, class_hash::ClassHash, + SyscallResultTrait, storage::Map }; use token_bound_accounts::interfaces::IERC721::{IERC721DispatcherTrait, IERC721Dispatcher}; @@ -72,7 +73,12 @@ pub mod Registry { assert(owner == get_caller_address(), Errors::CALLER_IS_NOT_OWNER); let mut constructor_calldata: Array = array![ - token_contract.into(), token_id.low.into(), token_id.high.into() + token_contract.into(), + token_id.low.into(), + token_id.high.into(), + get_contract_address().into(), + implementation_hash, + salt ]; let class_hash: ClassHash = implementation_hash.try_into().unwrap(); @@ -100,7 +106,10 @@ pub mod Registry { .update(token_contract.into()) .update(token_id.low.into()) .update(token_id.high.into()) - .update(3) + .update(get_contract_address().into()) + .update(implementation_hash) + .update(salt) + .update(6) .finalize(); let prefix: felt252 = 'STARKNET_CONTRACT_ADDRESS'; diff --git a/tests/test_account_component.cairo b/tests/test_account_component.cairo index f0764f9..817db22 100644 --- a/tests/test_account_component.cairo +++ b/tests/test_account_component.cairo @@ -3,12 +3,15 @@ // ************************************************************************* use starknet::{ContractAddress, account::Call}; use snforge_std::{ - declare, start_cheat_caller_address, stop_cheat_caller_address, start_cheat_transaction_hash, - start_cheat_nonce, spy_events, EventSpyAssertionsTrait, ContractClassTrait, ContractClass + declare, start_cheat_caller_address, stop_cheat_caller_address, + start_cheat_account_contract_address, stop_cheat_account_contract_address, + start_cheat_transaction_hash, start_cheat_nonce, spy_events, EventSpyAssertionsTrait, + ContractClassTrait, ContractClass }; use core::hash::HashStateTrait; use core::pedersen::PedersenTrait; +use token_bound_accounts::interfaces::IRegistry::{IRegistryDispatcherTrait, IRegistryDispatcher}; use token_bound_accounts::interfaces::IAccount::{ IAccountDispatcher, IAccountDispatcherTrait, IAccountSafeDispatcher, IAccountSafeDispatcherTrait }; @@ -17,6 +20,7 @@ use token_bound_accounts::interfaces::IExecutable::{ }; use token_bound_accounts::components::presets::account_preset::AccountPreset; use token_bound_accounts::components::account::account::AccountComponent; +use token_bound_accounts::registry::registry::Registry; use token_bound_accounts::test_helper::{ hello_starknet::{IHelloStarknetDispatcher, IHelloStarknetDispatcherTrait, HelloStarknet}, @@ -31,7 +35,9 @@ const SALT: felt252 = 123; // ************************************************************************* // SETUP // ************************************************************************* -fn __setup__() -> (ContractAddress, ContractAddress) { +fn __setup__() -> ( + ContractAddress, ContractAddress, ContractAddress, ContractClass, ContractClass +) { // deploy erc721 helper contract let erc721_contract = declare("ERC721").unwrap(); let mut erc721_constructor_calldata = array!['tokenbound', 'TBA']; @@ -40,8 +46,8 @@ fn __setup__() -> (ContractAddress, ContractAddress) { .unwrap(); // deploy recipient contract - let account_contract = declare("SimpleAccount").unwrap(); - let (recipient, _) = account_contract + let recipient_contract_class = declare("SimpleAccount").unwrap(); + let (recipient, _) = recipient_contract_class .deploy( @array![883045738439352841478194533192765345509759306772397516907181243450667673002] ) @@ -51,14 +57,31 @@ fn __setup__() -> (ContractAddress, ContractAddress) { let dispatcher = IERC721Dispatcher { contract_address: erc721_contract_address }; dispatcher.mint(recipient, 1.try_into().unwrap()); + // deploy registry contract + let registry_contract = declare("Registry").unwrap(); + let (registry_contract_address, _) = registry_contract.deploy(@array![]).unwrap(); + // deploy account contract - let account_contract = declare("AccountPreset").unwrap(); - let mut acct_constructor_calldata = array![erc721_contract_address.try_into().unwrap(), 1, 0]; - let (account_contract_address, _) = account_contract + let account_contract_class = declare("AccountPreset").unwrap(); + let mut acct_constructor_calldata = array![ + erc721_contract_address.try_into().unwrap(), + 1, + 0, + registry_contract_address.try_into().unwrap(), + account_contract_class.class_hash.into(), + 20 + ]; + let (account_contract_address, _) = account_contract_class .deploy(@acct_constructor_calldata) .unwrap(); - (account_contract_address, erc721_contract_address) + ( + account_contract_address, + erc721_contract_address, + registry_contract_address, + recipient_contract_class, + account_contract_class + ) } // ************************************************************************* @@ -66,7 +89,7 @@ fn __setup__() -> (ContractAddress, ContractAddress) { // ************************************************************************* #[test] fn test_constructor() { - let (contract_address, erc721_contract_address) = __setup__(); + let (contract_address, erc721_contract_address, _, _, _) = __setup__(); let dispatcher = IAccountDispatcher { contract_address }; let (token_contract, token_id, chain_id) = dispatcher.token(); @@ -91,9 +114,20 @@ fn test_event_is_emitted_on_initialization() { // spy on emitted events let mut spy = spy_events(); + // deploy registry contract + let registry_contract = declare("Registry").unwrap(); + let (registry_contract_address, _) = registry_contract.deploy(@array![]).unwrap(); + // deploy account contract let account_contract = declare("AccountPreset").unwrap(); - let mut acct_constructor_calldata = array![erc721_contract_address.try_into().unwrap(), 1, 0]; + let mut acct_constructor_calldata = array![ + erc721_contract_address.try_into().unwrap(), + 1, + 0, + registry_contract_address.try_into().unwrap(), + account_contract.class_hash.into(), + 20 + ]; let (account_contract_address, _) = account_contract .deploy(@acct_constructor_calldata) .unwrap(); @@ -119,7 +153,7 @@ fn test_event_is_emitted_on_initialization() { #[test] fn test_execute() { - let (contract_address, erc721_contract_address) = __setup__(); + let (contract_address, erc721_contract_address, _, _, _) = __setup__(); let dispatcher = IExecutableDispatcher { contract_address }; // deploy `HelloStarknet` contract for testing @@ -153,7 +187,7 @@ fn test_execute() { #[test] fn test_execute_multicall() { - let (contract_address, erc721_contract_address) = __setup__(); + let (contract_address, erc721_contract_address, _, _, _) = __setup__(); let dispatcher = IExecutableDispatcher { contract_address }; // deploy `HelloStarknet` contract for testing @@ -194,7 +228,7 @@ fn test_execute_multicall() { #[test] #[should_panic(expected: ('Account: unauthorized',))] fn test_execution_fails_if_invalid_signer() { - let (contract_address, _) = __setup__(); + let (contract_address, _, _, _, _) = __setup__(); let dispatcher = IExecutableDispatcher { contract_address }; // deploy `HelloStarknet` contract for testing @@ -219,7 +253,7 @@ fn test_execution_fails_if_invalid_signer() { #[test] fn test_execution_emits_event() { - let (contract_address, erc721_contract_address) = __setup__(); + let (contract_address, erc721_contract_address, _, _, _) = __setup__(); let dispatcher = IExecutableDispatcher { contract_address }; // deploy `HelloStarknet` contract for testing @@ -269,7 +303,7 @@ fn test_execution_emits_event() { #[test] fn test_execution_updates_state() { - let (contract_address, erc721_contract_address) = __setup__(); + let (contract_address, erc721_contract_address, _, _, _) = __setup__(); let dispatcher = IExecutableDispatcher { contract_address }; let account_dispatcher = IAccountDispatcher { contract_address }; @@ -307,7 +341,7 @@ fn test_execution_updates_state() { #[test] fn test_token() { - let (contract_address, erc721_contract_address) = __setup__(); + let (contract_address, erc721_contract_address, _, _, _) = __setup__(); let dispatcher = IAccountDispatcher { contract_address }; let (token_contract, token_id, chain_id) = dispatcher.token(); @@ -318,7 +352,7 @@ fn test_token() { #[test] fn test_owner() { - let (contract_address, erc721_contract_address) = __setup__(); + let (contract_address, erc721_contract_address, _, _, _) = __setup__(); let acct_dispatcher = IAccountDispatcher { contract_address: contract_address }; let token_dispatcher = IERC721Dispatcher { contract_address: erc721_contract_address }; @@ -326,3 +360,92 @@ fn test_owner() { let token_owner = token_dispatcher.ownerOf(1.try_into().unwrap()); assert(owner == token_owner, 'invalid owner'); } +// #[test] +// fn test_root_owner() { +// let (_, erc721_contract_address, registry_contract_address, simple_account_class, +// account_class) = __setup__(); + +// // deploy recipient contract +// let (recipient, _) = simple_account_class +// .deploy( +// @array![883045738439352841478194533192765345509759306772397516907181243450667673002] +// ) +// .unwrap(); + +// // mint a new token to recipient +// let dispatcher = IERC721Dispatcher { contract_address: erc721_contract_address }; +// dispatcher.mint(recipient, 1.try_into().unwrap()); + +// // deploy account 1 +// start_cheat_caller_address(registry_contract_address, recipient); +// let registry_dispatcher = IRegistryDispatcher { contract_address: registry_contract_address +// }; +// let account_1 = registry_dispatcher +// .create_account( +// account_class.class_hash.into(), +// erc721_contract_address, +// 1.try_into().unwrap(), +// 2525201, +// 'SN_SEPOLIA' +// ); +// stop_cheat_caller_address(registry_contract_address); + +// // mint a new token to account 1 +// dispatcher.mint(account_1, 2.try_into().unwrap()); + +// // deploy account 1-2 +// start_cheat_caller_address(registry_contract_address, account_1); +// let account_1_2 = registry_dispatcher +// .create_account( +// account_class.class_hash.into(), +// erc721_contract_address, +// 2.try_into().unwrap(), +// 2525202, +// 'SN_SEPOLIA' +// ); +// stop_cheat_caller_address(registry_contract_address); + +// // mint a new token to account 1-2 +// let dispatcher = IERC721Dispatcher { contract_address: erc721_contract_address }; +// dispatcher.mint(account_1_2, 3.try_into().unwrap()); + +// // deploy account 1-2-3 +// start_cheat_caller_address(registry_contract_address, account_1_2); +// let account_1_2_3 = registry_dispatcher +// .create_account( +// account_class.class_hash.into(), +// erc721_contract_address, +// 3.try_into().unwrap(), +// 2525203, +// 'SN_SEPOLIA' +// ); +// stop_cheat_caller_address(registry_contract_address); + +// println!("account_1_2_3: {:?}", account_1_2_3); +// println!("account_1_2: {:?}", account_1_2); +// println!("account_1: {:?}", account_1); +// println!("recipient: {:?}", recipient); + +// // get root owners +// start_cheat_account_contract_address(account_1_2_3, account_1_2_3); +// let root_owner_for_account_1_2_3 = IAccountDispatcher { contract_address: account_1_2_3 +// }.root_owner(erc721_contract_address, 3, 'SN_SEPOLIA'); +// stop_cheat_account_contract_address(account_1_2_3); + +// start_cheat_account_contract_address(account_1_2, account_1_2); +// let root_owner_for_account_1_2 = IAccountDispatcher { contract_address: account_1_2 +// }.root_owner(erc721_contract_address, 2, 'SN_SEPOLIA'); +// stop_cheat_account_contract_address(account_1_2); + +// start_cheat_account_contract_address(account_1, account_1); +// let root_owner_for_account_1 = IAccountDispatcher { contract_address: account_1 +// }.root_owner(erc721_contract_address, 1, 'SN_SEPOLIA'); +// stop_cheat_account_contract_address(account_1); + +// // check root owner is valid +// assert(root_owner_for_account_1_2_3 == recipient, 'invalid root owner'); +// assert(root_owner_for_account_1_2 == recipient, 'invalid root owner'); +// assert(root_owner_for_account_1 == recipient, 'invalid root owner'); +// } + + diff --git a/tests/test_lockable_component.cairo b/tests/test_lockable_component.cairo index f2fa3c4..cf2e4f0 100644 --- a/tests/test_lockable_component.cairo +++ b/tests/test_lockable_component.cairo @@ -10,6 +10,7 @@ use snforge_std::{ use core::hash::HashStateTrait; use core::pedersen::PedersenTrait; +use token_bound_accounts::interfaces::IRegistry::{IRegistryDispatcherTrait, IRegistryDispatcher}; use token_bound_accounts::interfaces::IAccount::{ IAccountDispatcher, IAccountDispatcherTrait, IAccountSafeDispatcher, IAccountSafeDispatcherTrait }; @@ -24,6 +25,7 @@ use token_bound_accounts::interfaces::IUpgradeable::{ use token_bound_accounts::components::presets::account_preset::AccountPreset; use token_bound_accounts::components::account::account::AccountComponent; use token_bound_accounts::components::lockable::lockable::LockableComponent; +use token_bound_accounts::registry::registry::Registry; use token_bound_accounts::test_helper::{ hello_starknet::{IHelloStarknetDispatcher, IHelloStarknetDispatcherTrait, HelloStarknet}, @@ -56,9 +58,20 @@ fn __setup__() -> (ContractAddress, ContractAddress) { let dispatcher = IERC721Dispatcher { contract_address: erc721_contract_address }; dispatcher.mint(recipient, 1.try_into().unwrap()); + // deploy registry contract + let registry_contract = declare("Registry").unwrap(); + let (registry_contract_address, _) = registry_contract.deploy(@array![]).unwrap(); + // deploy account contract let account_contract = declare("AccountPreset").unwrap(); - let mut acct_constructor_calldata = array![erc721_contract_address.try_into().unwrap(), 1, 0]; + let mut acct_constructor_calldata = array![ + erc721_contract_address.try_into().unwrap(), + 1, + 0, + registry_contract_address.try_into().unwrap(), + account_contract.class_hash.into(), + 20 + ]; let (account_contract_address, _) = account_contract .deploy(@acct_constructor_calldata) .unwrap(); diff --git a/tests/test_permissionable_component.cairo b/tests/test_permissionable_component.cairo index ba6b657..a855449 100644 --- a/tests/test_permissionable_component.cairo +++ b/tests/test_permissionable_component.cairo @@ -10,14 +10,13 @@ use snforge_std::{ use core::hash::HashStateTrait; use core::pedersen::PedersenTrait; +use token_bound_accounts::interfaces::IRegistry::{IRegistryDispatcherTrait, IRegistryDispatcher}; use token_bound_accounts::interfaces::IAccount::{ IAccountDispatcher, IAccountDispatcherTrait, IAccountSafeDispatcher, IAccountSafeDispatcherTrait }; - use token_bound_accounts::interfaces::IPermissionable::{ IPermissionableDispatcher, IPermissionableDispatcherTrait }; - use token_bound_accounts::interfaces::IExecutable::{ IExecutableDispatcher, IExecutableDispatcherTrait }; @@ -26,6 +25,7 @@ use token_bound_accounts::interfaces::IUpgradeable::{ }; use token_bound_accounts::components::presets::account_preset::AccountPreset; use token_bound_accounts::components::account::account::AccountComponent; +use token_bound_accounts::registry::registry::Registry; use token_bound_accounts::components::permissionable::permissionable::PermissionableComponent; @@ -63,9 +63,20 @@ fn __setup__() -> (ContractAddress, ContractAddress) { let dispatcher = IERC721Dispatcher { contract_address: erc721_contract_address }; dispatcher.mint(recipient, 1.try_into().unwrap()); + // deploy registry contract + let registry_contract = declare("Registry").unwrap(); + let (registry_contract_address, _) = registry_contract.deploy(@array![]).unwrap(); + // deploy account contract let account_contract = declare("AccountPreset").unwrap(); - let mut acct_constructor_calldata = array![erc721_contract_address.try_into().unwrap(), 1, 0]; + let mut acct_constructor_calldata = array![ + erc721_contract_address.try_into().unwrap(), + 1, + 0, + registry_contract_address.try_into().unwrap(), + account_contract.class_hash.into(), + 20 + ]; let (account_contract_address, _) = account_contract .deploy(@acct_constructor_calldata) .unwrap(); diff --git a/tests/test_signatory_component.cairo b/tests/test_signatory_component.cairo index 767d38c..56bf36d 100644 --- a/tests/test_signatory_component.cairo +++ b/tests/test_signatory_component.cairo @@ -10,16 +10,14 @@ use snforge_std::{ use core::hash::HashStateTrait; use core::pedersen::PedersenTrait; +use token_bound_accounts::interfaces::IRegistry::{IRegistryDispatcherTrait, IRegistryDispatcher}; use token_bound_accounts::interfaces::IAccount::{ IAccountDispatcher, IAccountDispatcherTrait, IAccountSafeDispatcher, IAccountSafeDispatcherTrait }; - use token_bound_accounts::interfaces::IPermissionable::{ IPermissionableDispatcher, IPermissionableDispatcherTrait }; - use token_bound_accounts::interfaces::ISignatory::{ISignatoryDispatcher, ISignatoryDispatcherTrait}; - use token_bound_accounts::interfaces::IExecutable::{ IExecutableDispatcher, IExecutableDispatcherTrait }; @@ -28,7 +26,7 @@ use token_bound_accounts::interfaces::IUpgradeable::{ }; use token_bound_accounts::components::presets::account_preset::AccountPreset; use token_bound_accounts::components::account::account::AccountComponent; - +use token_bound_accounts::registry::registry::Registry; use token_bound_accounts::components::signatory::signatory::SignatoryComponent; use token_bound_accounts::components::permissionable::permissionable::PermissionableComponent; @@ -87,9 +85,20 @@ fn __setup__() -> (ContractAddress, ContractAddress) { dispatcher.mint(recipient, 1.try_into().unwrap()); dispatcher.mint(recipient, 2.try_into().unwrap()); + // deploy registry contract + let registry_contract = declare("Registry").unwrap(); + let (registry_contract_address, _) = registry_contract.deploy(@array![]).unwrap(); + // deploy account contract let account_contract = declare("AccountPreset").unwrap(); - let mut acct_constructor_calldata = array![erc721_contract_address.try_into().unwrap(), 1, 0]; + let mut acct_constructor_calldata = array![ + erc721_contract_address.try_into().unwrap(), + 1, + 0, + registry_contract_address.try_into().unwrap(), + account_contract.class_hash.into(), + 20 + ]; let (account_contract_address, _) = account_contract .deploy(@acct_constructor_calldata) .unwrap(); @@ -139,23 +148,6 @@ fn test_is_valid_signer_for_permissioned_addresses() { stop_cheat_caller_address(contract_address); } -#[test] -fn test_is_valid_signer_for_root_owner() { - let (contract_address, _) = __setup__(); - let account_dispatcher = IAccountDispatcher { contract_address }; - let (account_contract, _, _) = account_dispatcher.token(); - - let root_owner = account_dispatcher.get_root_owner(account_contract, 1.try_into().unwrap()); - let signatory_dispatcher = ISignatoryDispatcher { contract_address: contract_address }; - - start_cheat_caller_address(contract_address, root_owner); - - let is_valid_signer = signatory_dispatcher.is_valid_signer(root_owner); - assert(is_valid_signer == true, 'should be a valid signer'); - - stop_cheat_caller_address(contract_address); -} - #[test] fn test_is_valid_signature_for_base_owner() { let (contract_address, erc721_contract_address) = __setup__(); @@ -176,23 +168,3 @@ fn test_is_valid_signature_for_base_owner() { stop_cheat_caller_address(contract_address); } -#[test] -fn test_is_valid_signature_for_root_owner() { - let (contract_address, _) = __setup__(); - let data = SIGNED_TX_DATA(); - let hash = data.transaction_hash; - let account_dispatcher = IAccountDispatcher { contract_address }; - let (account_contract, _, _) = account_dispatcher.token(); - - let root_owner = account_dispatcher.get_root_owner(account_contract, 1.try_into().unwrap()); - let signatory_dispatcher = ISignatoryDispatcher { contract_address: contract_address }; - - start_cheat_caller_address(contract_address, root_owner); - - let mut good_signature = array![data.r, data.s]; - let is_valid_signer = signatory_dispatcher.is_valid_signature(hash, good_signature.span()); - assert(is_valid_signer == 'VALID', 'should be a valid signature'); - - stop_cheat_caller_address(contract_address); -} - diff --git a/tests/test_upgradeable.cairo b/tests/test_upgradeable.cairo index 62205cd..b2d54da 100644 --- a/tests/test_upgradeable.cairo +++ b/tests/test_upgradeable.cairo @@ -9,6 +9,7 @@ use snforge_std::{ use core::hash::HashStateTrait; use core::pedersen::PedersenTrait; +use token_bound_accounts::interfaces::IRegistry::{IRegistryDispatcherTrait, IRegistryDispatcher}; use token_bound_accounts::interfaces::IAccount::{ IAccountDispatcher, IAccountDispatcherTrait, IAccountSafeDispatcher, IAccountSafeDispatcherTrait }; @@ -17,6 +18,7 @@ use token_bound_accounts::interfaces::IUpgradeable::{ }; use token_bound_accounts::components::presets::account_preset::AccountPreset; use token_bound_accounts::components::upgradeable::upgradeable::UpgradeableComponent; +use token_bound_accounts::registry::registry::Registry; use token_bound_accounts::test_helper::{ erc721_helper::{IERC721Dispatcher, IERC721DispatcherTrait, ERC721}, @@ -50,9 +52,20 @@ fn __setup__() -> (ContractAddress, ContractAddress) { let dispatcher = IERC721Dispatcher { contract_address: erc721_contract_address }; dispatcher.mint(recipient, 1.try_into().unwrap()); + // deploy registry contract + let registry_contract = declare("Registry").unwrap(); + let (registry_contract_address, _) = registry_contract.deploy(@array![]).unwrap(); + // deploy account contract let account_contract = declare("AccountPreset").unwrap(); - let mut acct_constructor_calldata = array![erc721_contract_address.try_into().unwrap(), 1, 0]; + let mut acct_constructor_calldata = array![ + erc721_contract_address.try_into().unwrap(), + 1, + 0, + registry_contract_address.try_into().unwrap(), + account_contract.class_hash.into(), + 20 + ]; let (account_contract_address, _) = account_contract .deploy(@acct_constructor_calldata) .unwrap();