From 44c124b19bd03ba6b4e30265b902fdd181f15ef8 Mon Sep 17 00:00:00 2001 From: JereSalo Date: Thu, 22 May 2025 17:14:47 -0300 Subject: [PATCH 1/7] fix i think, idk --- crates/vm/levm/src/utils.rs | 10 +++------- crates/vm/levm/src/vm.rs | 5 ++++- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/crates/vm/levm/src/utils.rs b/crates/vm/levm/src/utils.rs index 687d3a06b7f..5011179c2db 100644 --- a/crates/vm/levm/src/utils.rs +++ b/crates/vm/levm/src/utils.rs @@ -473,6 +473,9 @@ impl<'a> VM<'a> { // 9. Increase the nonce of authority by one. self.increment_account_nonce(authority_address) .map_err(|_| VMError::TxValidation(TxValidationError::NonceIsMax))?; + + // If delegation was successful insert target of delegation into "delegate contracts" set + self.delegate_contracts_in_tx.insert(auth_tuple.address); } self.substate.refunded_gas = refunded_gas; @@ -705,11 +708,4 @@ impl<'a> VM<'a> { } } } - - /// Checks if an address is delegation target in current transaction. - pub fn is_delegation_target(&self, address: Address) -> bool { - self.tx.authorization_list().as_ref().map_or(false, |list| { - list.iter().any(|item| item.address == address) - }) - } } diff --git a/crates/vm/levm/src/vm.rs b/crates/vm/levm/src/vm.rs index 3ff4bdde292..8834d2baf40 100644 --- a/crates/vm/levm/src/vm.rs +++ b/crates/vm/levm/src/vm.rs @@ -43,6 +43,8 @@ pub struct VM<'a> { pub substate_backups: Vec, /// Original storage values before the transaction. Used for gas calculations in SSTORE. pub storage_original_values: HashMap>, + /// All contracts addresses that have been successfully delegated in current transaction. + pub delegate_contracts_in_tx: HashSet
, } impl<'a> VM<'a> { @@ -58,6 +60,7 @@ impl<'a> VM<'a> { hooks, substate_backups: vec![], storage_original_values: HashMap::new(), + delegate_contracts_in_tx: HashSet::new(), } } @@ -169,7 +172,7 @@ impl<'a> VM<'a> { pub fn execute_precompile(&mut self) -> Result { let precompile_address = self.current_call_frame()?.code_address; - let precompile_result = match self.is_delegation_target(precompile_address) { + let precompile_result = match self.delegate_contracts_in_tx.contains(&precompile_address) { // Avoid executing precompile if it is target of a delegation in EIP-7702 transaction. true => { let gas_limit = self.current_call_frame()?.gas_limit; From 6172f79369ce028a6986e045f7f5e4291cc3902e Mon Sep 17 00:00:00 2001 From: JereSalo Date: Fri, 23 May 2025 12:43:45 -0300 Subject: [PATCH 2/7] first iteration of fixing problem --- crates/vm/levm/src/opcode_handlers/system.rs | 26 ++++++++++++-- crates/vm/levm/src/vm.rs | 38 +++++++------------- 2 files changed, 35 insertions(+), 29 deletions(-) diff --git a/crates/vm/levm/src/opcode_handlers/system.rs b/crates/vm/levm/src/opcode_handlers/system.rs index bf3e120782b..fefad9bd22d 100644 --- a/crates/vm/levm/src/opcode_handlers/system.rs +++ b/crates/vm/levm/src/opcode_handlers/system.rs @@ -2,7 +2,10 @@ use crate::{ call_frame::CallFrame, constants::{CREATE_DEPLOYMENT_FAIL, INIT_CODE_MAX_SIZE, REVERT_FOR_CALL, SUCCESS_FOR_CALL}, db::cache, - errors::{ExecutionReport, InternalError, OpcodeResult, OutOfGasError, TxResult, VMError}, + errors::{ + ExecutionReport, InternalError, OpcodeResult, OutOfGasError, PrecompileError, TxResult, + VMError, + }, gas_cost::{self, max_message_call_gas}, memory::{self, calculate_memory_size}, utils::{address_to_word, word_to_address, *}, @@ -833,8 +836,25 @@ impl<'a> VM<'a> { self.call_frames.push(new_call_frame); if self.is_precompile()? { - // Execute precompile immediately and handle result. - let report = self.execute_precompile()?; + let report = if self.delegate_contracts_in_tx.contains(&code_address) { + let result = if gas_limit > 0 { + TxResult::Success + } else { + TxResult::Revert(VMError::PrecompileError(PrecompileError::NotEnoughGas)) + }; + + ExecutionReport { + result, + gas_used: 0, + gas_refunded: self.substate.refunded_gas, + output: Bytes::new(), + logs: vec![], + } + } else { + // Execute precompile immediately and handle result. + self.execute_precompile()? + }; + self.handle_return(&report)?; } else { // Backup Substate before executing opcodes of new callframe. diff --git a/crates/vm/levm/src/vm.rs b/crates/vm/levm/src/vm.rs index 8834d2baf40..b57a231e655 100644 --- a/crates/vm/levm/src/vm.rs +++ b/crates/vm/levm/src/vm.rs @@ -4,9 +4,9 @@ use crate::{ call_frame::CallFrame, db::gen_db::GeneralizedDatabase, environment::Environment, - errors::{ExecutionReport, OpcodeResult, PrecompileError, VMError}, + errors::{ExecutionReport, OpcodeResult, VMError}, hooks::hook::Hook, - precompiles::execute_precompile, + precompiles::{execute_precompile, is_precompile}, TransientStorage, }; use bytes::Bytes; @@ -141,7 +141,7 @@ impl<'a> VM<'a> { /// Main execution loop. pub fn run_execution(&mut self) -> Result { - if self.is_precompile()? { + if is_precompile(&self.current_call_frame()?.to, self.env.config.fork) { return self.execute_precompile(); } @@ -170,29 +170,15 @@ impl<'a> VM<'a> { } pub fn execute_precompile(&mut self) -> Result { - let precompile_address = self.current_call_frame()?.code_address; - - let precompile_result = match self.delegate_contracts_in_tx.contains(&precompile_address) { - // Avoid executing precompile if it is target of a delegation in EIP-7702 transaction. - true => { - let gas_limit = self.current_call_frame()?.gas_limit; - if gas_limit == 0 { - // `pointer_to_precompile.json` tests that it should fail in a call with zero gas limit. - Err(VMError::PrecompileError(PrecompileError::NotEnoughGas)) - } else { - Ok(Bytes::new()) - } - } - // Otherwise, execute precompile - false => { - let callframe = self.current_call_frame_mut()?; - execute_precompile( - precompile_address, - &callframe.calldata, - &mut callframe.gas_used, - callframe.gas_limit, - ) - } + let callframe = self.current_call_frame_mut()?; + + let precompile_result = { + execute_precompile( + callframe.code_address, + &callframe.calldata, + &mut callframe.gas_used, + callframe.gas_limit, + ) }; let report = self.handle_precompile_result(precompile_result)?; From 37350e7195202405ba98fae11e4951f60827fe80 Mon Sep 17 00:00:00 2001 From: JereSalo Date: Fri, 23 May 2025 14:46:10 -0300 Subject: [PATCH 3/7] simpler result --- crates/vm/levm/src/opcode_handlers/system.rs | 22 ++------------------ 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/crates/vm/levm/src/opcode_handlers/system.rs b/crates/vm/levm/src/opcode_handlers/system.rs index fefad9bd22d..751b8406bb1 100644 --- a/crates/vm/levm/src/opcode_handlers/system.rs +++ b/crates/vm/levm/src/opcode_handlers/system.rs @@ -835,26 +835,8 @@ impl<'a> VM<'a> { ); self.call_frames.push(new_call_frame); - if self.is_precompile()? { - let report = if self.delegate_contracts_in_tx.contains(&code_address) { - let result = if gas_limit > 0 { - TxResult::Success - } else { - TxResult::Revert(VMError::PrecompileError(PrecompileError::NotEnoughGas)) - }; - - ExecutionReport { - result, - gas_used: 0, - gas_refunded: self.substate.refunded_gas, - output: Bytes::new(), - logs: vec![], - } - } else { - // Execute precompile immediately and handle result. - self.execute_precompile()? - }; - + if self.is_precompile()? && !self.delegate_contracts_in_tx.contains(&code_address) { + let report = self.execute_precompile()?; self.handle_return(&report)?; } else { // Backup Substate before executing opcodes of new callframe. From 49c63779d126f251b4264fb225f2eb211cac5ae8 Mon Sep 17 00:00:00 2001 From: JereSalo Date: Fri, 23 May 2025 18:03:09 -0300 Subject: [PATCH 4/7] fix delegation problem --- crates/vm/levm/src/opcode_handlers/system.rs | 22 ++++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/crates/vm/levm/src/opcode_handlers/system.rs b/crates/vm/levm/src/opcode_handlers/system.rs index 751b8406bb1..41888aed991 100644 --- a/crates/vm/levm/src/opcode_handlers/system.rs +++ b/crates/vm/levm/src/opcode_handlers/system.rs @@ -78,7 +78,7 @@ impl<'a> VM<'a> { (account.is_empty(), address_was_cold) }; - let (is_delegation, eip7702_gas_consumed, code_address, bytecode) = + let (is_delegation_7702, eip7702_gas_consumed, code_address, bytecode) = eip7702_get_code(self.db, &mut self.substate, callee)?; let gas_left = self @@ -123,7 +123,7 @@ impl<'a> VM<'a> { return_data_start_offset, return_data_size, bytecode, - is_delegation, + is_delegation_7702, ) } @@ -179,7 +179,7 @@ impl<'a> VM<'a> { let (_account_info, address_was_cold) = self.db.access_account(&mut self.substate, code_address)?; - let (is_delegation, eip7702_gas_consumed, code_address, bytecode) = + let (is_delegation_7702, eip7702_gas_consumed, code_address, bytecode) = eip7702_get_code(self.db, &mut self.substate, code_address)?; let gas_left = self @@ -223,7 +223,7 @@ impl<'a> VM<'a> { return_data_start_offset, return_data_size, bytecode, - is_delegation, + is_delegation_7702, ) } @@ -303,7 +303,7 @@ impl<'a> VM<'a> { calculate_memory_size(return_data_start_offset, return_data_size)?; let new_memory_size = new_memory_size_for_args.max(new_memory_size_for_return_data); - let (is_delegation, eip7702_gas_consumed, code_address, bytecode) = + let (is_delegation_7702, eip7702_gas_consumed, code_address, bytecode) = eip7702_get_code(self.db, &mut self.substate, code_address)?; let gas_left = self @@ -347,7 +347,7 @@ impl<'a> VM<'a> { return_data_start_offset, return_data_size, bytecode, - is_delegation, + is_delegation_7702, ) } @@ -399,7 +399,7 @@ impl<'a> VM<'a> { calculate_memory_size(return_data_start_offset, return_data_size)?; let new_memory_size = new_memory_size_for_args.max(new_memory_size_for_return_data); - let (is_delegation, eip7702_gas_consumed, _, bytecode) = + let (is_delegation_7702, eip7702_gas_consumed, _, bytecode) = eip7702_get_code(self.db, &mut self.substate, code_address)?; let gas_left = self @@ -440,7 +440,7 @@ impl<'a> VM<'a> { return_data_start_offset, return_data_size, bytecode, - is_delegation, + is_delegation_7702, ) } @@ -754,7 +754,7 @@ impl<'a> VM<'a> { ret_offset: U256, ret_size: usize, bytecode: Bytes, - is_delegation: bool, + is_delegation_7702: bool, ) -> Result { let sender_balance = self .db @@ -806,7 +806,7 @@ impl<'a> VM<'a> { self.increase_account_balance(to, value)?; } - if bytecode.is_empty() && is_delegation { + if bytecode.is_empty() && is_delegation_7702 { self.current_call_frame_mut()?.gas_used = self .current_call_frame()? .gas_used @@ -835,7 +835,7 @@ impl<'a> VM<'a> { ); self.call_frames.push(new_call_frame); - if self.is_precompile()? && !self.delegate_contracts_in_tx.contains(&code_address) { + if self.is_precompile()? && !is_delegation_7702 { let report = self.execute_precompile()?; self.handle_return(&report)?; } else { From 32e990f0421a07899f0443a996268071e2669204 Mon Sep 17 00:00:00 2001 From: JereSalo Date: Fri, 23 May 2025 18:10:09 -0300 Subject: [PATCH 5/7] precompile fix --- crates/vm/levm/src/opcode_handlers/system.rs | 7 ++----- crates/vm/levm/src/utils.rs | 10 ++-------- crates/vm/levm/src/vm.rs | 7 ++----- 3 files changed, 6 insertions(+), 18 deletions(-) diff --git a/crates/vm/levm/src/opcode_handlers/system.rs b/crates/vm/levm/src/opcode_handlers/system.rs index 41888aed991..6b48e74c4ce 100644 --- a/crates/vm/levm/src/opcode_handlers/system.rs +++ b/crates/vm/levm/src/opcode_handlers/system.rs @@ -2,10 +2,7 @@ use crate::{ call_frame::CallFrame, constants::{CREATE_DEPLOYMENT_FAIL, INIT_CODE_MAX_SIZE, REVERT_FOR_CALL, SUCCESS_FOR_CALL}, db::cache, - errors::{ - ExecutionReport, InternalError, OpcodeResult, OutOfGasError, PrecompileError, TxResult, - VMError, - }, + errors::{ExecutionReport, InternalError, OpcodeResult, OutOfGasError, TxResult, VMError}, gas_cost::{self, max_message_call_gas}, memory::{self, calculate_memory_size}, utils::{address_to_word, word_to_address, *}, @@ -835,7 +832,7 @@ impl<'a> VM<'a> { ); self.call_frames.push(new_call_frame); - if self.is_precompile()? && !is_delegation_7702 { + if self.is_precompile(&code_address) && !is_delegation_7702 { let report = self.execute_precompile()?; self.handle_return(&report)?; } else { diff --git a/crates/vm/levm/src/utils.rs b/crates/vm/levm/src/utils.rs index 5011179c2db..946c8aabdb5 100644 --- a/crates/vm/levm/src/utils.rs +++ b/crates/vm/levm/src/utils.rs @@ -473,9 +473,6 @@ impl<'a> VM<'a> { // 9. Increase the nonce of authority by one. self.increment_account_nonce(authority_address) .map_err(|_| VMError::TxValidation(TxValidationError::NonceIsMax))?; - - // If delegation was successful insert target of delegation into "delegate contracts" set - self.delegate_contracts_in_tx.insert(auth_tuple.address); } self.substate.refunded_gas = refunded_gas; @@ -608,11 +605,8 @@ impl<'a> VM<'a> { Ok(min_gas_used) } - pub fn is_precompile(&self) -> Result { - Ok(is_precompile( - &self.current_call_frame()?.code_address, - self.env.config.fork, - )) + pub fn is_precompile(&self, address: &Address) -> bool { + is_precompile(address, self.env.config.fork) } /// Backup of Substate, a copy of the current substate to restore if sub-context is reverted diff --git a/crates/vm/levm/src/vm.rs b/crates/vm/levm/src/vm.rs index b57a231e655..ddef11a2907 100644 --- a/crates/vm/levm/src/vm.rs +++ b/crates/vm/levm/src/vm.rs @@ -6,7 +6,7 @@ use crate::{ environment::Environment, errors::{ExecutionReport, OpcodeResult, VMError}, hooks::hook::Hook, - precompiles::{execute_precompile, is_precompile}, + precompiles::execute_precompile, TransientStorage, }; use bytes::Bytes; @@ -43,8 +43,6 @@ pub struct VM<'a> { pub substate_backups: Vec, /// Original storage values before the transaction. Used for gas calculations in SSTORE. pub storage_original_values: HashMap>, - /// All contracts addresses that have been successfully delegated in current transaction. - pub delegate_contracts_in_tx: HashSet
, } impl<'a> VM<'a> { @@ -60,7 +58,6 @@ impl<'a> VM<'a> { hooks, substate_backups: vec![], storage_original_values: HashMap::new(), - delegate_contracts_in_tx: HashSet::new(), } } @@ -141,7 +138,7 @@ impl<'a> VM<'a> { /// Main execution loop. pub fn run_execution(&mut self) -> Result { - if is_precompile(&self.current_call_frame()?.to, self.env.config.fork) { + if self.is_precompile(&self.current_call_frame()?.to) { return self.execute_precompile(); } From 4109e8114cb3a54ca4989a960e8d0c846b2230b4 Mon Sep 17 00:00:00 2001 From: JereSalo Date: Fri, 23 May 2025 18:12:23 -0300 Subject: [PATCH 6/7] add comment --- crates/vm/levm/src/vm.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/vm/levm/src/vm.rs b/crates/vm/levm/src/vm.rs index ddef11a2907..d2e1c07db43 100644 --- a/crates/vm/levm/src/vm.rs +++ b/crates/vm/levm/src/vm.rs @@ -166,6 +166,7 @@ impl<'a> VM<'a> { } } + /// Executes precompile and handles the output that it returns, generating a report. pub fn execute_precompile(&mut self) -> Result { let callframe = self.current_call_frame_mut()?; From f6e0fea9c86ffefd78ea139f10421e3679ce6ef7 Mon Sep 17 00:00:00 2001 From: JereSalo Date: Mon, 26 May 2025 10:13:27 -0300 Subject: [PATCH 7/7] improve fix --- crates/vm/levm/src/opcode_handlers/system.rs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/crates/vm/levm/src/opcode_handlers/system.rs b/crates/vm/levm/src/opcode_handlers/system.rs index 6b48e74c4ce..b05b6e4c519 100644 --- a/crates/vm/levm/src/opcode_handlers/system.rs +++ b/crates/vm/levm/src/opcode_handlers/system.rs @@ -803,18 +803,6 @@ impl<'a> VM<'a> { self.increase_account_balance(to, value)?; } - if bytecode.is_empty() && is_delegation_7702 { - self.current_call_frame_mut()?.gas_used = self - .current_call_frame()? - .gas_used - .checked_sub(gas_limit) - .ok_or(InternalError::GasOverflow)?; - self.current_call_frame_mut()? - .stack - .push(SUCCESS_FOR_CALL)?; - return Ok(OpcodeResult::Continue { pc_increment: 1 }); - } - let new_call_frame = CallFrame::new( msg_sender, to,