diff --git a/crates/interpreter/src/interpreter/contract.rs b/crates/interpreter/src/interpreter/contract.rs index 434c1c7156..fff51af9da 100644 --- a/crates/interpreter/src/interpreter/contract.rs +++ b/crates/interpreter/src/interpreter/contract.rs @@ -1,7 +1,7 @@ use super::analysis::{to_analysed, BytecodeLocked}; use crate::primitives::{Bytecode, Bytes, B160, U256}; use crate::CallContext; -use revm_primitives::{Env, TransactTo}; +use revm_primitives::{Env, TransactTo, B256}; #[derive(Clone, Default)] pub struct Contract { @@ -10,6 +10,8 @@ pub struct Contract { /// Bytecode contains contract code, size of original code, analysis with gas block and jump table. /// Note that current code is extended with push padding and STOP at end. pub bytecode: BytecodeLocked, + /// Bytecode hash. + pub hash: B256, /// Contract address pub address: B160, /// Caller of the EVM. @@ -19,12 +21,20 @@ pub struct Contract { } impl Contract { - pub fn new(input: Bytes, bytecode: Bytecode, address: B160, caller: B160, value: U256) -> Self { + pub fn new( + input: Bytes, + bytecode: Bytecode, + hash: B256, + address: B160, + caller: B160, + value: U256, + ) -> Self { let bytecode = to_analysed(bytecode).try_into().expect("it is analyzed"); Self { input, bytecode, + hash, address, caller, value, @@ -32,7 +42,7 @@ impl Contract { } /// Create new contract from environment - pub fn new_env(env: &Env, bytecode: Bytecode) -> Self { + pub fn new_env(env: &Env, bytecode: Bytecode, hash: B256) -> Self { let contract_address = match env.tx.transact_to { TransactTo::Call(caller) => caller, TransactTo::Create(..) => B160::zero(), @@ -40,6 +50,7 @@ impl Contract { Self::new( env.tx.data.clone(), bytecode, + hash, contract_address, env.tx.caller, env.tx.value, @@ -50,10 +61,16 @@ impl Contract { self.bytecode.jump_map().is_valid(possition) } - pub fn new_with_context(input: Bytes, bytecode: Bytecode, call_context: &CallContext) -> Self { + pub fn new_with_context( + input: Bytes, + bytecode: Bytecode, + hash: B256, + call_context: &CallContext, + ) -> Self { Self::new( input, bytecode, + hash, call_context.address, call_context.caller, call_context.apparent_value, diff --git a/crates/revm/src/evm_impl.rs b/crates/revm/src/evm_impl.rs index 2f98118d7c..c5a45c4501 100644 --- a/crates/revm/src/evm_impl.rs +++ b/crates/revm/src/evm_impl.rs @@ -396,9 +396,12 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB, } }; + let bytecode = Bytecode::new_raw(inputs.init_code.clone()); + let contract = Box::new(Contract::new( Bytes::new(), - Bytecode::new_raw(inputs.init_code.clone()), + bytecode, + code_hash, created_address, inputs.caller, inputs.value, @@ -598,14 +601,23 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB, fn prepare_call(&mut self, inputs: &CallInputs) -> Result { let gas = Gas::new(inputs.gas_limit); - // Load account and get code. Account is now hot. - let Some((bytecode, _)) = self.code(inputs.contract) else { - return Err(CallResult { - result: InstructionResult::FatalExternalError, - gas, - return_value: Bytes::new(), - }); + let account = match self + .data + .journaled_state + .load_code(inputs.contract, self.data.db) + { + Ok((account, _)) => account, + Err(e) => { + self.data.error = Some(e); + return Err(CallResult { + result: InstructionResult::FatalExternalError, + gas, + return_value: Bytes::new(), + }); + } }; + let code_hash = account.info.code_hash(); + let bytecode = account.info.code.clone().unwrap_or_default(); // Check depth if self.data.journaled_state.depth() > CALL_STACK_LIMIT { @@ -643,6 +655,7 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB, let contract = Box::new(Contract::new_with_context( inputs.input.clone(), bytecode, + code_hash, &inputs.context, ));