Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 21 additions & 4 deletions crates/interpreter/src/interpreter/contract.rs
Original file line number Diff line number Diff line change
@@ -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 {
Expand All @@ -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.
Expand All @@ -19,27 +21,36 @@ 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,
}
}

/// 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(),
};
Self::new(
env.tx.data.clone(),
bytecode,
hash,
contract_address,
env.tx.caller,
env.tx.value,
Expand All @@ -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,
Expand Down
29 changes: 21 additions & 8 deletions crates/revm/src/evm_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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<PreparedCall, CallResult> {
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 {
Expand Down Expand Up @@ -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,
));

Expand Down