diff --git a/evm_loader/program/src/entrypoint.rs b/evm_loader/program/src/entrypoint.rs index b52716d35..fc87401cc 100644 --- a/evm_loader/program/src/entrypoint.rs +++ b/evm_loader/program/src/entrypoint.rs @@ -376,20 +376,25 @@ fn process_instruction<'a>( let storage_info = next_account_info(account_info_iter)?; let operator_sol_info = next_account_info(account_info_iter)?; + let operator_eth_info = next_account_info(account_info_iter)?; + let user_eth_info = next_account_info(account_info_iter)?; let incinerator_info = next_account_info(account_info_iter)?; let system_info = next_account_info(account_info_iter)?; - let trx_accounts = &accounts[4..]; + let trx_accounts = &accounts[6..]; if !operator_sol_info.is_signer { return Err!(ProgramError::InvalidAccountData); } - let storage = StorageAccount::restore(storage_info, operator_sol_info)?; + + let storage = StorageAccount::restore(storage_info, operator_sol_info).map_err(|err| { + if err == ProgramError::InvalidAccountData {EvmLoaderError::StorageAccountUninitialized.into()} + else {err} + })?; storage.check_accounts(program_id, trx_accounts)?; let account_storage = ProgramAccountStorage::new(program_id, trx_accounts)?; - let mut caller_info_data = AccountData::unpack(&account_storage.get_caller_account_info().ok_or_else(||E!(ProgramError::InvalidArgument))?.data.borrow())?; match caller_info_data { AccountData::Account(ref mut acc) => { @@ -405,6 +410,30 @@ fn process_instruction<'a>( _ => return Err!(ProgramError::InvalidAccountData), }; + let executor = Machine::restore(&storage, &account_storage); + debug_print!("Executor restored"); + + let executor_state = executor.into_state(); + let used_gas = executor_state.substate().metadata().gasometer().used_gas(); + + let (gas_limit, gas_price) = storage.get_gas_params()?; + if used_gas > gas_limit { + return Err!(ProgramError::InvalidArgument); + } + let gas_price_wei = U256::from(gas_price); + let fee = U256::from(used_gas) + .checked_mul(gas_price_wei).ok_or_else(||E!(ProgramError::InvalidArgument))?; + + let caller_info= account_storage.get_caller_account_info().ok_or_else(||E!(ProgramError::InvalidArgument))?; + + token::transfer_token( + accounts, + user_eth_info, + operator_eth_info, + caller_info, + account_storage.get_caller_account().ok_or_else(||E!(ProgramError::InvalidArgument))?, + &fee)?; + payment::burn_operators_deposit( storage_info, incinerator_info, diff --git a/evm_loader/program/src/token.rs b/evm_loader/program/src/token.rs index 435081d18..442c1f198 100644 --- a/evm_loader/program/src/token.rs +++ b/evm_loader/program/src/token.rs @@ -193,4 +193,4 @@ pub fn transfer_token( invoke_signed(&instruction, accounts, &[&program_seeds[..]])?; Ok(()) -} \ No newline at end of file +} diff --git a/evm_loader/test_event.py b/evm_loader/test_event.py index 248640285..b540b21c4 100644 --- a/evm_loader/test_event.py +++ b/evm_loader/test_event.py @@ -33,8 +33,8 @@ def setUpClass(cls): if getBalance(cls.caller) == 0: print("Create caller account...") _ = cls.loader.createEtherAccount(cls.caller_ether) - cls.token.transfer(ETH_TOKEN_MINT_ID, 2000, get_associated_token_address(PublicKey(cls.caller), ETH_TOKEN_MINT_ID)) print("Done\n") + cls.token.transfer(ETH_TOKEN_MINT_ID, 2000, cls.caller_token) print('Account:', cls.acc.public_key(), bytes(cls.acc.public_key()).hex()) print("Caller:", cls.caller_ether.hex(), cls.caller_nonce, "->", cls.caller, @@ -143,6 +143,12 @@ def sol_instr_12_cancel(self, storage_account): # Operator address: AccountMeta(pubkey=self.acc.public_key(), is_signer=True, is_writable=True), + # Operator ETH address (stub for now): + AccountMeta(pubkey=get_associated_token_address(self.acc.public_key(), ETH_TOKEN_MINT_ID), + is_signer=False, is_writable=True), + # User ETH address (stub for now): + AccountMeta(pubkey=get_associated_token_address(PublicKey(self.caller), ETH_TOKEN_MINT_ID), + is_signer=False, is_writable=True), # Incenirator AccountMeta(pubkey=PublicKey(incinerator), is_signer=False, is_writable=True), # System program account: @@ -407,13 +413,16 @@ def test_caseSuccessRunOtherTransactionAfterCancel(self): storage = self.create_storage_account(sign[:8].hex()) caller_balance_before_cancel = self.token.balance(self.caller_token) + operator_balance_before_cancel = self.token.balance(get_associated_token_address(self.acc.public_key(), ETH_TOKEN_MINT_ID)) result = self.call_begin(storage, 10, msg, instruction) result = self.call_continue(storage, 10) result = self.call_cancel(storage) caller_balance_after_cancel = self.token.balance(self.caller_token) - self.assertEqual(caller_balance_after_cancel, caller_balance_before_cancel) + operator_balance_after_cancel = self.token.balance(get_associated_token_address(self.acc.public_key(), ETH_TOKEN_MINT_ID)) + self.assertNotEqual(caller_balance_after_cancel, caller_balance_before_cancel) + self.assertEqual(caller_balance_before_cancel+operator_balance_before_cancel, caller_balance_after_cancel+operator_balance_after_cancel) self.call_partial_signed(input)