diff --git a/.tool-versions b/.tool-versions index 68a7d31..90faff4 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,2 +1,2 @@ -scarb 2.4.3 -starknet-foundry 0.14.0 \ No newline at end of file +scarb 2.5.4 +starknet-foundry 0.18.0 \ No newline at end of file diff --git a/Scarb.lock b/Scarb.lock index 74f4e18..7e0ba75 100644 --- a/Scarb.lock +++ b/Scarb.lock @@ -3,12 +3,12 @@ version = 1 [[package]] name = "snforge_std" -version = "0.14.0" -source = "git+https://github.com/foundry-rs/starknet-foundry.git?tag=v0.14.0#e8cbecee4e31ed428c76d5173eaa90c8df796fe3" +version = "0.18.0" +source = "git+https://github.com/foundry-rs/starknet-foundry.git?tag=v0.18.0#48f909a56b08cbdc5ca6a21a836b0fbc6c36d55b" [[package]] name = "token_bound_accounts" -version = "0.1.0" +version = "0.3.0" dependencies = [ "snforge_std", ] diff --git a/Scarb.toml b/Scarb.toml index a3d7cda..cc74406 100644 --- a/Scarb.toml +++ b/Scarb.toml @@ -1,6 +1,6 @@ [package] name = "token_bound_accounts" -version = "0.1.0" +version = "0.3.0" # See more keys and their definitions at https://docs.swmansion.com/scarb/docs/reference/manifest @@ -9,8 +9,8 @@ sierra = true casm = true [dependencies] -starknet = "2.4.3" -snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry.git", tag = "v0.14.0" } +starknet = "2.5.4" +snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry.git", tag = "v0.18.0" } [tool.snforge] # exit_first = true \ No newline at end of file diff --git a/src/account.cairo b/src/account.cairo index 41277d0..2e4d458 100644 --- a/src/account.cairo +++ b/src/account.cairo @@ -1,3 +1,3 @@ mod account; -use account::AccountComponent; \ No newline at end of file +use account::AccountComponent; diff --git a/src/account/account.cairo b/src/account/account.cairo index bf6f4f1..0a56edf 100644 --- a/src/account/account.cairo +++ b/src/account/account.cairo @@ -63,7 +63,7 @@ mod AccountComponent { mod Errors { const LOCKED_ACCOUNT: felt252 = 'Account: account is locked!'; - const INV_TX_VERSION: felt252 = 'Account: invalid tx version'; + const INV_TX_VERSION: felt252 = 'Account: invalid tx version'; const UNAUTHORIZED: felt252 = 'Account: unauthorized'; const INV_SIG_LEN: felt252 = 'Account: invalid sig length'; const INV_SIGNATURE: felt252 = 'Account: invalid signature'; @@ -71,10 +71,8 @@ mod AccountComponent { #[embeddable_as(AccountImpl)] impl Account< - TContractState, - +HasComponent, - +Drop - > of IAccount> { + TContractState, +HasComponent, +Drop + > of IAccount> { /// @notice used for signature validation /// @param hash The message hash /// @param signature The signature to be validated @@ -85,24 +83,32 @@ mod AccountComponent { } fn __validate_deploy__( - self: @ComponentState, class_hash: felt252, contract_address_salt: felt252, + self: @ComponentState, + class_hash: felt252, + contract_address_salt: felt252, ) -> felt252 { self._validate_transaction() } - fn __validate_declare__(self: @ComponentState, class_hash: felt252) -> felt252 { + fn __validate_declare__( + self: @ComponentState, class_hash: felt252 + ) -> felt252 { self._validate_transaction() } /// @notice validate an account transaction /// @param calls an array of transactions to be executed - fn __validate__(ref self: ComponentState, mut calls: Array) -> felt252 { + fn __validate__( + ref self: ComponentState, mut calls: Array + ) -> felt252 { self._validate_transaction() } /// @notice executes a transaction /// @param calls an array of transactions to be executed - fn __execute__(ref self: ComponentState, mut calls: Array) -> Array> { + fn __execute__( + ref self: ComponentState, mut calls: Array + ) -> Array> { self._assert_only_owner(); let (lock_status, _) = self._is_locked(); assert(!lock_status, Errors::LOCKED_ACCOUNT); @@ -110,7 +116,7 @@ mod AccountComponent { let tx_info = get_tx_info().unbox(); assert(tx_info.version != 0, Errors::INV_TX_VERSION); - let retdata = self._execute_calls(calls.span()); + let retdata = self._execute_calls(calls); let hash = tx_info.transaction_hash; let response = retdata.span(); self.emit(TransactionExecuted { hash, response }); @@ -155,7 +161,9 @@ mod AccountComponent { // @notice check that account supports TBA interface // @param interface_id interface to be checked against - fn supports_interface(self: @ComponentState, interface_id: felt252) -> bool { + fn supports_interface( + self: @ComponentState, interface_id: felt252 + ) -> bool { if (interface_id == TBA_INTERFACE_ID) { return true; } else { @@ -166,25 +174,26 @@ mod AccountComponent { #[generate_trait] impl InternalImpl< - TContractState, - +HasComponent, - +Drop + TContractState, +HasComponent, +Drop > of InternalTrait { - /// @notice initializes the account by setting the initial token conrtact and token id - fn initializer(ref self: ComponentState, token_contract: ContractAddress, token_id: u256) { + fn initializer( + ref self: ComponentState, + token_contract: ContractAddress, + token_id: u256 + ) { + self.Account_token_contract.write(token_contract); + self.Account_token_id.write(token_id); - self.Account_token_contract.write(token_contract); - self.Account_token_id.write(token_id); - - let owner = self._get_owner(token_contract, token_id); - self.emit(AccountCreated { owner }); - } + let owner = self._get_owner(token_contract, token_id); + self.emit(AccountCreated { owner }); + } /// @notice check that caller is the token bound account fn _assert_only_owner(ref self: ComponentState) { let caller = get_caller_address(); - let owner = self._get_owner(self.Account_token_contract.read(), self.Account_token_id.read()); + let owner = self + ._get_owner(self.Account_token_contract.read(), self.Account_token_id.read()); assert(caller == owner, Errors::UNAUTHORIZED); } @@ -246,7 +255,8 @@ mod AccountComponent { assert(signature_length == 2_u32, Errors::INV_SIG_LEN); let caller = get_caller_address(); - let owner = self._get_owner(self.Account_token_contract.read(), self.Account_token_id.read()); + let owner = self + ._get_owner(self.Account_token_contract.read(), self.Account_token_id.read()); if (caller == owner) { return starknet::VALIDATED; } else { @@ -256,20 +266,18 @@ mod AccountComponent { /// @notice internal function for executing transactions /// @param calls An array of transactions to be executed - fn _execute_calls(ref self: ComponentState, mut calls: Span) -> Array> { + fn _execute_calls( + ref self: ComponentState, mut calls: Array + ) -> Array> { let mut result: Array> = ArrayTrait::new(); let mut calls = calls; loop { match calls.pop_front() { Option::Some(call) => { - match call_contract_syscall( - *call.to, *call.selector, call.calldata.span() - ) { + match call_contract_syscall(call.to, call.selector, call.calldata) { Result::Ok(mut retdata) => { result.append(retdata); }, - Result::Err(revert_reason) => { - panic_with_felt252('multicall_failed'); - } + Result::Err(_) => { panic_with_felt252('multicall_failed'); } } }, Option::None(_) => { break (); } diff --git a/src/interfaces.cairo b/src/interfaces.cairo index 5721060..b203692 100644 --- a/src/interfaces.cairo +++ b/src/interfaces.cairo @@ -1,4 +1,4 @@ mod IAccount; mod IERC721; mod IRegistry; -mod IUpgradeable; \ No newline at end of file +mod IUpgradeable; diff --git a/src/presets.cairo b/src/presets.cairo index 74885b0..ba35269 100644 --- a/src/presets.cairo +++ b/src/presets.cairo @@ -1,3 +1,3 @@ mod account; -use account::Account; \ No newline at end of file +use account::Account; diff --git a/src/presets/account.cairo b/src/presets/account.cairo index 94cfe07..07edf3f 100644 --- a/src/presets/account.cairo +++ b/src/presets/account.cairo @@ -1,7 +1,7 @@ //////////////////////////////// // Account contract //////////////////////////////// -#[starknet::contract] +#[starknet::contract(account)] mod Account { use starknet::ContractAddress; use starknet::ClassHash; @@ -42,7 +42,7 @@ mod Account { self.account.initializer(token_contract, token_id); } - #[external(v0)] + #[abi(embed_v0)] impl UpgradeableImpl of IUpgradeable { fn upgrade(ref self: ContractState, new_class_hash: ClassHash) { self.account._assert_only_owner(); @@ -50,5 +50,5 @@ mod Account { assert(!lock_status, AccountComponent::Errors::LOCKED_ACCOUNT); self.upgradeable._upgrade(new_class_hash); } - } + } } diff --git a/src/registry/registry.cairo b/src/registry/registry.cairo index 4b445f5..0426253 100644 --- a/src/registry/registry.cairo +++ b/src/registry/registry.cairo @@ -46,7 +46,7 @@ mod Registry { const CALLER_IS_NOT_OWNER: felt252 = 'Registry: caller is not onwer'; } - #[external(v0)] + #[abi(embed_v0)] impl IRegistryImpl of IRegistry { /// @notice deploys a new tokenbound account for an NFT /// @param implementation_hash the class hash of the reference account diff --git a/src/test_helper.cairo b/src/test_helper.cairo index 53d5b9b..57f17fb 100644 --- a/src/test_helper.cairo +++ b/src/test_helper.cairo @@ -1,4 +1,3 @@ mod hello_starknet; mod account_upgrade; mod erc721_helper; -mod registry_upgrade; \ No newline at end of file diff --git a/src/test_helper/account_upgrade.cairo b/src/test_helper/account_upgrade.cairo index a3e292c..8e86a50 100644 --- a/src/test_helper/account_upgrade.cairo +++ b/src/test_helper/account_upgrade.cairo @@ -49,7 +49,7 @@ trait IERC721 { fn token_uri(self: @TContractState, token_id: u256) -> felt252; } -#[starknet::contract] +#[starknet::contract(account)] mod UpgradedAccount { use starknet::{ get_tx_info, get_caller_address, get_contract_address, ContractAddress, account::Call, @@ -95,7 +95,7 @@ mod UpgradedAccount { } - #[external(v0)] + #[abi(embed_v0)] impl IAccountImpl of super::IUpgradedAccount { fn get_public_key(self: @ContractState) -> felt252 { self._public_key.read() @@ -134,7 +134,7 @@ mod UpgradedAccount { let tx_info = get_tx_info().unbox(); assert(tx_info.version != 0, 'invalid tx version'); - self._execute_calls(calls.span()) + self._execute_calls(calls) } fn owner( @@ -202,20 +202,16 @@ mod UpgradedAccount { } } - fn _execute_calls(ref self: ContractState, mut calls: Span) -> Array> { + fn _execute_calls(ref self: ContractState, mut calls: Array) -> Array> { let mut result: Array> = ArrayTrait::new(); let mut calls = calls; loop { match calls.pop_front() { Option::Some(call) => { - match call_contract_syscall( - *call.to, *call.selector, call.calldata.span() - ) { + match call_contract_syscall(call.to, call.selector, call.calldata) { Result::Ok(mut retdata) => { result.append(retdata); }, - Result::Err(revert_reason) => { - panic_with_felt252('multicall_failed'); - } + Result::Err(_) => { panic_with_felt252('multicall_failed'); } } }, Option::None(_) => { break (); } diff --git a/src/test_helper/erc721_helper.cairo b/src/test_helper/erc721_helper.cairo index 499525d..20036e6 100644 --- a/src/test_helper/erc721_helper.cairo +++ b/src/test_helper/erc721_helper.cairo @@ -78,7 +78,7 @@ mod ERC721 { self.symbol.write(_symbol); } - #[external(v0)] + #[abi(embed_v0)] impl ERC721Impl of super::IERC721 { fn name(self: @ContractState) -> felt252 { self.name.read() diff --git a/src/test_helper/hello_starknet.cairo b/src/test_helper/hello_starknet.cairo index da3fcd8..4e43144 100644 --- a/src/test_helper/hello_starknet.cairo +++ b/src/test_helper/hello_starknet.cairo @@ -12,7 +12,7 @@ mod HelloStarknet { balance: felt252, } - #[external(v0)] + #[abi(embed_v0)] impl HelloStarknetImpl of super::IHelloStarknet { fn increase_balance(ref self: ContractState, amount: felt252) { assert(amount != 0, 'Amount cannot be 0'); diff --git a/src/test_helper/registry_upgrade.cairo b/src/test_helper/registry_upgrade.cairo deleted file mode 100644 index 29a3da4..0000000 --- a/src/test_helper/registry_upgrade.cairo +++ /dev/null @@ -1,138 +0,0 @@ -use array::{ArrayTrait, SpanTrait}; -use starknet::{account::Call, ContractAddress, ClassHash}; - -#[starknet::interface] -trait IUpgradedRegistry { - fn create_account( - ref self: TContractState, - implementation_hash: felt252, - token_contract: ContractAddress, - token_id: u256, - salt: felt252 - ) -> ContractAddress; - fn get_account( - self: @TContractState, - implementation_hash: felt252, - token_contract: ContractAddress, - token_id: u256, - salt: felt252 - ) -> ContractAddress; - fn total_deployed_accounts( - self: @TContractState, token_contract: ContractAddress, token_id: u256 - ) -> u8; - fn upgrade(ref self: TContractState, new_class_hash: ClassHash); - fn version(self: @TContractState) -> u8; -} - -#[starknet::contract] -mod UpgradedRegistry { - use core::hash::HashStateTrait; - use starknet::{ - ContractAddress, SyscallResultTrait, syscalls::call_contract_syscall, syscalls::deploy_syscall, get_caller_address, ClassHash - }; - use pedersen::PedersenTrait; - - - #[storage] - struct Storage { - Registry_deployed_accounts: LegacyMap< - (ContractAddress, u256), u8 - >, // tracks no. of deployed accounts by registry for an NFT - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - AccountCreated: AccountCreated, - Upgraded: Upgraded - } - - #[derive(Drop, starknet::Event)] - struct AccountCreated { - account_address: ContractAddress, - token_contract: ContractAddress, - token_id: u256, - } - - #[derive(Drop, starknet::Event)] - struct Upgraded { - class_hash: ClassHash - } - - - #[external(v0)] - impl RegistryImpl of super::IUpgradedRegistry { - - fn create_account( - ref self: ContractState, - implementation_hash: felt252, - token_contract: ContractAddress, - token_id: u256, - salt: felt252 - ) -> ContractAddress { - let mut constructor_calldata: Array = array![ - token_contract.into(), token_id.low.into(), token_id.high.into() - ]; - - let class_hash: ClassHash = implementation_hash.try_into().unwrap(); - let result = deploy_syscall(class_hash, salt, constructor_calldata.span(), true); - let (account_address, _) = result.unwrap_syscall(); - - let new_deployment_index: u8 = self - .Registry_deployed_accounts - .read((token_contract, token_id)) - + 1_u8; - self.Registry_deployed_accounts.write((token_contract, token_id), new_deployment_index); - - self.emit(AccountCreated { account_address, token_contract, token_id, }); - - account_address - } - - fn get_account( - self: @ContractState, - implementation_hash: felt252, - token_contract: ContractAddress, - token_id: u256, - salt: felt252 - ) -> ContractAddress { - let constructor_calldata_hash = PedersenTrait::new(0) - .update(token_contract.into()) - .update(token_id.low.into()) - .update(token_id.high.into()) - .update(3) - .finalize(); - - let prefix: felt252 = 'STARKNET_CONTRACT_ADDRESS'; - let account_address = PedersenTrait::new(0) - .update(prefix) - .update(0) - .update(salt) - .update(implementation_hash) - .update(constructor_calldata_hash) - .update(5) - .finalize(); - - account_address.try_into().unwrap() - } - - /// @notice returns the total no. of deployed tokenbound accounts for an NFT by the registry - /// @param token_contract the contract address of the NFT - /// @param token_id the ID of the NFT - fn total_deployed_accounts( - self: @ContractState, token_contract: ContractAddress, token_id: u256 - ) -> u8 { - self.Registry_deployed_accounts.read((token_contract, token_id)) - } - - fn upgrade(ref self: ContractState, new_class_hash: ClassHash) { - assert(!new_class_hash.is_zero(), 'Class hash cannot be zero'); - starknet::replace_class_syscall(new_class_hash).unwrap_syscall(); - self.emit(Upgraded { class_hash: new_class_hash }); - } - - fn version(self: @ContractState) -> u8 { - 1_u8 - } - } -} diff --git a/src/upgradeable.cairo b/src/upgradeable.cairo index 3d4ca2e..9304e1d 100644 --- a/src/upgradeable.cairo +++ b/src/upgradeable.cairo @@ -1,3 +1,3 @@ mod upgradeable; -use upgradeable::UpgradeableComponent; \ No newline at end of file +use upgradeable::UpgradeableComponent; diff --git a/src/upgradeable/upgradeable.cairo b/src/upgradeable/upgradeable.cairo index de83cfe..b67b163 100644 --- a/src/upgradeable/upgradeable.cairo +++ b/src/upgradeable/upgradeable.cairo @@ -28,9 +28,7 @@ mod UpgradeableComponent { #[generate_trait] impl InternalImpl< - TContractState, - +HasComponent, - +Drop + TContractState, +HasComponent, +Drop > of InternalTrait { /// @notice eplaces the contract's class hash with `new_class_hash`. /// Emits an `Upgraded` event. diff --git a/tests/test_account.cairo b/tests/test_account.cairo index 3cc958b..5fbd73e 100644 --- a/tests/test_account.cairo +++ b/tests/test_account.cairo @@ -6,7 +6,7 @@ use option::OptionTrait; use integer::u256_from_felt252; use snforge_std::{ declare, start_prank, stop_prank, start_warp, stop_warp, ContractClassTrait, ContractClass, - PrintTrait, CheatTarget + CheatTarget }; use token_bound_accounts::interfaces::IAccount::IAccountDispatcher; @@ -118,7 +118,7 @@ fn test_execute() { let test_address = test_contract.deploy(@array![]).unwrap(); // craft calldata for call array - let mut calldata = array![100]; + let mut calldata = array![100].span(); let call = Call { to: test_address, selector: 1530486729947006463063166157847785599120665941190480211966374137237989315360, @@ -158,13 +158,13 @@ fn test_execute_multicall() { let call1 = Call { to: test_address, selector: 1530486729947006463063166157847785599120665941190480211966374137237989315360, - calldata: calldata + calldata: calldata.span() }; let mut calldata2 = array![200]; let call2 = Call { to: test_address, selector: 1157683809588496510300162709548024577765603117833695133799390448986300456129, - calldata: calldata2 + calldata: calldata2.span() }; // construct call array @@ -230,15 +230,14 @@ fn test_upgrade() { } #[test] -#[should_panic(expected: ( 'Account: unauthorized',))] +#[should_panic(expected: ('Account: unauthorized',))] fn test_upgrade_with_unauthorized() { - let (contract_address, erc721_contract_address) = __setup__(); + let (contract_address, _) = __setup__(); let new_class_hash = declare('UpgradedAccount').class_hash; // call upgrade function with an unauthorized address start_prank(CheatTarget::One(contract_address), ACCOUNT2.try_into().unwrap()); - // let safe_upgrade_dispatcher = IAccountSafeDispatcher { contract_address }; let safe_upgrade_dispatcher = IUpgradeableDispatcher { contract_address }; safe_upgrade_dispatcher.upgrade(new_class_hash); } @@ -269,9 +268,11 @@ fn test_locking() { } #[test] +#[feature("safe_dispatcher")] fn test_should_not_execute_when_locked() { let (contract_address, erc721_contract_address) = __setup__(); - let dispatcher = IAccountSafeDispatcher { contract_address }; + let safe_dispatcher = IAccountSafeDispatcher { contract_address }; + let dispatcher = IAccountDispatcher { contract_address }; let lock_duration = 3000_u64; // get token owner @@ -293,15 +294,15 @@ fn test_should_not_execute_when_locked() { let call = Call { to: test_address, selector: 1530486729947006463063166157847785599120665941190480211966374137237989315360, - calldata: calldata + calldata: calldata.span() }; let mut calls = array![call]; - match dispatcher.__execute__(calls) { + match safe_dispatcher.__execute__(calls) { Result::Ok(_) => panic_with_felt252('should have panicked!'), Result::Err(panic_data) => { stop_prank(CheatTarget::One(contract_address)); - panic_data.print(); + println!("panic_data: {:?}", panic_data); return (); } } @@ -311,7 +312,8 @@ fn test_should_not_execute_when_locked() { #[should_panic(expected: ('Account: account is locked!',))] fn test_should_not_upgrade_when_locked() { let (contract_address, erc721_contract_address) = __setup__(); - let dispatcher = IAccountSafeDispatcher { contract_address }; + let dispatcher = IAccountDispatcher { contract_address }; + let lock_duration = 3000_u64; // get token owner @@ -332,8 +334,9 @@ fn test_should_not_upgrade_when_locked() { } #[test] +#[feature("safe_dispatcher")] fn test_should_not_lock_if_not_owner() { - let (contract_address, erc721_contract_address) = __setup__(); + let (contract_address, _) = __setup__(); let dispatcher = IAccountSafeDispatcher { contract_address }; let lock_duration = 3000_u64; @@ -345,16 +348,18 @@ fn test_should_not_lock_if_not_owner() { Result::Err(panic_data) => { stop_prank(CheatTarget::One(contract_address)); stop_warp(CheatTarget::One(contract_address)); - panic_data.print(); + println!("panic_data: {:?}", panic_data); return (); } } } #[test] +#[feature("safe_dispatcher")] fn test_should_not_lock_if_already_locked() { let (contract_address, erc721_contract_address) = __setup__(); - let dispatcher = IAccountSafeDispatcher { contract_address }; + let safe_dispatcher = IAccountSafeDispatcher { contract_address }; + let dispatcher = IAccountDispatcher { contract_address }; let lock_duration = 3000_u64; // get token owner @@ -369,12 +374,12 @@ fn test_should_not_lock_if_already_locked() { // call the lock function again start_warp(CheatTarget::One(contract_address), 1000); - match dispatcher.lock(lock_duration) { + match safe_dispatcher.lock(lock_duration) { Result::Ok(_) => panic_with_felt252('should have panicked'), Result::Err(panic_data) => { stop_prank(CheatTarget::One(contract_address)); stop_warp(CheatTarget::One(contract_address)); - panic_data.print(); + println!("panic_data: {:?}", panic_data); return (); } } diff --git a/tests/test_registry.cairo b/tests/test_registry.cairo index 4ce7223..5be4e3c 100644 --- a/tests/test_registry.cairo +++ b/tests/test_registry.cairo @@ -4,18 +4,12 @@ use array::{ArrayTrait, SpanTrait}; use result::ResultTrait; use option::OptionTrait; use integer::u256_from_felt252; -use snforge_std::{ - declare, start_prank, stop_prank, ContractClassTrait, ContractClass, PrintTrait, CheatTarget -}; +use snforge_std::{declare, start_prank, stop_prank, ContractClassTrait, ContractClass, CheatTarget}; use token_bound_accounts::interfaces::IRegistry::IRegistryDispatcherTrait; use token_bound_accounts::interfaces::IRegistry::IRegistryDispatcher; use token_bound_accounts::registry::registry::Registry; -use token_bound_accounts::test_helper::registry_upgrade::IUpgradedRegistryDispatcher; -use token_bound_accounts::test_helper::registry_upgrade::IUpgradedRegistryDispatcherTrait; -use token_bound_accounts::test_helper::registry_upgrade::UpgradedRegistry; - use token_bound_accounts::interfaces::IUpgradeable::IUpgradeableDispatcher; use token_bound_accounts::interfaces::IUpgradeable::IUpgradeableDispatcherTrait; @@ -90,21 +84,21 @@ fn test_getting_total_deployed_accounts() { let acct_class_hash = declare('Account').class_hash; // create multiple accounts for same NFT - let account_address1 = registry_dispatcher + registry_dispatcher .create_account( class_hash_to_felt252(acct_class_hash), erc721_contract_address, u256_from_felt252(1), 3554633 ); - let account_address2 = registry_dispatcher + registry_dispatcher .create_account( class_hash_to_felt252(acct_class_hash), erc721_contract_address, u256_from_felt252(1), 363256 ); - let account_address3 = registry_dispatcher + registry_dispatcher .create_account( class_hash_to_felt252(acct_class_hash), erc721_contract_address, @@ -149,4 +143,4 @@ fn test_get_account() { // compare both addresses assert(account == account_address, 'get_account computes wrongly'); -} \ No newline at end of file +}