diff --git a/crates/handler/src/execution.rs b/crates/handler/src/execution.rs index e79f9d4b4c..d326974642 100644 --- a/crates/handler/src/execution.rs +++ b/crates/handler/src/execution.rs @@ -31,12 +31,12 @@ pub fn create_init_frame( return_memory_offset: 0..0, })) } - TxKind::Create => FrameInput::Create(Box::new(CreateInputs { - caller: tx.caller(), - scheme: CreateScheme::Create, - value: tx.value(), - init_code: input, + TxKind::Create => FrameInput::Create(Box::new(CreateInputs::new( + tx.caller(), + CreateScheme::Create, + tx.value(), + input, gas_limit, - })), + ))), } } diff --git a/crates/interpreter/src/instructions/contract.rs b/crates/interpreter/src/instructions/contract.rs index 22a36f6629..4a360c7350 100644 --- a/crates/interpreter/src/instructions/contract.rs +++ b/crates/interpreter/src/instructions/contract.rs @@ -95,13 +95,13 @@ pub fn create( .interpreter .bytecode .set_action(InterpreterAction::NewFrame(FrameInput::Create(Box::new( - CreateInputs { - caller: context.interpreter.input.target_address(), + CreateInputs::new( + context.interpreter.input.target_address(), scheme, value, - init_code: code, + code, gas_limit, - }, + ), )))); } diff --git a/crates/interpreter/src/interpreter_action/create_inputs.rs b/crates/interpreter/src/interpreter_action/create_inputs.rs index d44ed3eac8..fe88771072 100644 --- a/crates/interpreter/src/interpreter_action/create_inputs.rs +++ b/crates/interpreter/src/interpreter_action/create_inputs.rs @@ -1,8 +1,9 @@ use context_interface::CreateScheme; +use core::cell::OnceCell; use primitives::{Address, Bytes, U256}; /// Inputs for a create call -#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)] +#[derive(Clone, Debug, Default, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct CreateInputs { /// Caller address of the EVM @@ -15,17 +16,41 @@ pub struct CreateInputs { pub init_code: Bytes, /// The gas limit of the call pub gas_limit: u64, + /// Cached created address. This is computed lazily and cached to avoid + /// redundant keccak computations when inspectors call `created_address`. + #[cfg_attr(feature = "serde", serde(skip))] + cached_address: OnceCell
, } impl CreateInputs { + /// Creates a new `CreateInputs` instance. + pub fn new( + caller: Address, + scheme: CreateScheme, + value: U256, + init_code: Bytes, + gas_limit: u64, + ) -> Self { + Self { + caller, + scheme, + value, + init_code, + gas_limit, + cached_address: OnceCell::new(), + } + } + /// Returns the address that this create call will create. + /// + /// The result is cached to avoid redundant keccak computations. pub fn created_address(&self, nonce: u64) -> Address { - match self.scheme { + *self.cached_address.get_or_init(|| match self.scheme { CreateScheme::Create => self.caller.create(nonce), CreateScheme::Create2 { salt } => self .caller .create2_from_code(salt.to_be_bytes(), &self.init_code), CreateScheme::Custom { address } => address, - } + }) } }