diff --git a/crates/vm/levm/src/hooks.rs b/crates/vm/levm/src/hooks.rs index 3fb80f014..ef0436a32 100644 --- a/crates/vm/levm/src/hooks.rs +++ b/crates/vm/levm/src/hooks.rs @@ -334,6 +334,11 @@ impl Hook for DefaultHook { Ok(()) } + /// ## Changes post execution + /// 1. Undo value transfer if the transaction was reverted + /// 2. Return unused gas + gas refunds to the sender. + /// 3. Pay coinbase fee + /// 4. Destruct addresses in selfdestruct set. fn finalize_execution( &self, vm: &mut VM, diff --git a/crates/vm/levm/src/vm.rs b/crates/vm/levm/src/vm.rs index dfeba9ef1..ad8e06118 100644 --- a/crates/vm/levm/src/vm.rs +++ b/crates/vm/levm/src/vm.rs @@ -3,7 +3,7 @@ use crate::{ call_frame::CallFrame, constants::*, db::{ - cache::{self, remove_account}, + cache::{self}, CacheDB, Database, }, environment::Environment, @@ -390,118 +390,6 @@ impl VM { } } - /// ## Changes post execution - /// 1. Undo value transfer if the transaction was reverted - /// 2. Return unused gas + gas refunds to the sender. - /// 3. Pay coinbase fee - /// 4. Destruct addresses in selfdestruct set. - fn finalize_execution( - &mut self, - initial_call_frame: &CallFrame, - report: &mut ExecutionReport, - ) -> Result<(), VMError> { - // POST-EXECUTION Changes - let sender_address = initial_call_frame.msg_sender; - let receiver_address = initial_call_frame.to; - - // 1. Undo value transfer if the transaction has reverted - if let TxResult::Revert(_) = report.result { - let existing_account = get_account(&mut self.cache, self.db.clone(), receiver_address); //TO Account - - if has_delegation(&existing_account.info)? { - // This is the case where the "to" address and the - // "signer" address are the same. We are setting the code - // and sending some balance to the "to"/"signer" - // address. - // See https://eips.ethereum.org/EIPS/eip-7702#behavior (last sentence). - - // If transaction execution results in failure (any - // exceptional condition or code reverting), setting - // delegation designations is not rolled back. - decrease_account_balance( - &mut self.cache, - self.db.clone(), - receiver_address, - initial_call_frame.msg_value, - )?; - } else { - // We remove the receiver account from the cache, like nothing changed in it's state. - remove_account(&mut self.cache, &receiver_address); - } - - increase_account_balance( - &mut self.cache, - self.db.clone(), - sender_address, - initial_call_frame.msg_value, - )?; - } - - // 2. Return unused gas + gas refunds to the sender. - let max_gas = self.env.gas_limit; - let consumed_gas = report.gas_used; - let refunded_gas = report.gas_refunded.min( - consumed_gas - .checked_div(5) - .ok_or(VMError::Internal(InternalError::UndefinedState(-1)))?, - ); - // "The max refundable proportion of gas was reduced from one half to one fifth by EIP-3529 by Buterin and Swende [2021] in the London release" - report.gas_refunded = refunded_gas; - - let gas_to_return = max_gas - .checked_sub(consumed_gas) - .and_then(|gas| gas.checked_add(refunded_gas)) - .ok_or(VMError::Internal(InternalError::UndefinedState(0)))?; - - let wei_return_amount = self - .env - .gas_price - .checked_mul(U256::from(gas_to_return)) - .ok_or(VMError::Internal(InternalError::UndefinedState(1)))?; - - increase_account_balance( - &mut self.cache, - self.db.clone(), - sender_address, - wei_return_amount, - )?; - - // 3. Pay coinbase fee - let coinbase_address = self.env.coinbase; - - let gas_to_pay_coinbase = consumed_gas - .checked_sub(refunded_gas) - .ok_or(VMError::Internal(InternalError::UndefinedState(2)))?; - - let priority_fee_per_gas = self - .env - .gas_price - .checked_sub(self.env.base_fee_per_gas) - .ok_or(VMError::GasPriceIsLowerThanBaseFee)?; - let coinbase_fee = U256::from(gas_to_pay_coinbase) - .checked_mul(priority_fee_per_gas) - .ok_or(VMError::BalanceOverflow)?; - - if coinbase_fee != U256::zero() { - increase_account_balance( - &mut self.cache, - self.db.clone(), - coinbase_address, - coinbase_fee, - )?; - }; - - // 4. Destruct addresses in selfdestruct set. - // In Cancun the only addresses destroyed are contracts created in this transaction - let selfdestruct_set = self.accrued_substate.selfdestruct_set.clone(); - for address in selfdestruct_set { - let account_to_remove = get_account_mut_vm(&mut self.cache, self.db.clone(), address)?; - *account_to_remove = Account::default(); - } - - Ok(()) - } - pub fn execute(&mut self) -> Result { let mut initial_call_frame = self .call_frames @@ -634,7 +522,9 @@ impl VM { output: Bytes::new(), }; - self.finalize_execution(initial_call_frame, &mut report)?; + for hook in self.hooks.clone() { + hook.finalize_execution(self, initial_call_frame, &mut report)?; + } report.new_state.clone_from(&self.cache); Ok(report)