diff --git a/crates/interpreter/src/host.rs b/crates/interpreter/src/host.rs index 49ffbd02a6..b432209bde 100644 --- a/crates/interpreter/src/host.rs +++ b/crates/interpreter/src/host.rs @@ -1,4 +1,4 @@ -use crate::primitives::{Address, Bytecode, Env, Log, B256, U256}; +use crate::primitives::{Address, Bytes, Env, Log, B256, U256}; mod dummy; pub use dummy::DummyHost; @@ -23,7 +23,7 @@ pub trait Host { fn balance(&mut self, address: Address) -> Option<(U256, bool)>; /// Get code of `address` and if the account is cold. - fn code(&mut self, address: Address) -> Option<(Bytecode, bool)>; + fn code(&mut self, address: Address) -> Option<(Bytes, bool)>; /// Get code hash of `address` and if the account is cold. fn code_hash(&mut self, address: Address) -> Option<(B256, bool)>; diff --git a/crates/interpreter/src/host/dummy.rs b/crates/interpreter/src/host/dummy.rs index 4a069bfa63..47320b0863 100644 --- a/crates/interpreter/src/host/dummy.rs +++ b/crates/interpreter/src/host/dummy.rs @@ -1,6 +1,5 @@ -use crate::primitives::{hash_map::Entry, Bytecode, HashMap, U256}; use crate::{ - primitives::{Address, Env, Log, B256, KECCAK_EMPTY}, + primitives::{hash_map::Entry, Address, Bytes, Env, HashMap, Log, B256, KECCAK_EMPTY, U256}, Host, SStoreResult, SelfDestructResult, }; use std::vec::Vec; @@ -61,8 +60,8 @@ impl Host for DummyHost { } #[inline] - fn code(&mut self, _address: Address) -> Option<(Bytecode, bool)> { - Some((Bytecode::default(), false)) + fn code(&mut self, _address: Address) -> Option<(Bytes, bool)> { + Some((Bytes::default(), false)) } #[inline] diff --git a/crates/interpreter/src/instructions/host.rs b/crates/interpreter/src/instructions/host.rs index 0bc777c341..a25f514842 100644 --- a/crates/interpreter/src/instructions/host.rs +++ b/crates/interpreter/src/instructions/host.rs @@ -99,7 +99,7 @@ pub fn extcodecopy(interpreter: &mut Interpreter, // Note: this can't panic because we resized memory to fit. interpreter .shared_memory - .set_data(memory_offset, code_offset, len, &code.original_bytes()); + .set_data(memory_offset, code_offset, len, &code); } pub fn blockhash(interpreter: &mut Interpreter, host: &mut H) { diff --git a/crates/primitives/src/bytecode.rs b/crates/primitives/src/bytecode.rs index 232d61f66d..c5587ea651 100644 --- a/crates/primitives/src/bytecode.rs +++ b/crates/primitives/src/bytecode.rs @@ -1,7 +1,7 @@ pub mod eof; pub mod legacy; -pub use eof::Eof; +pub use eof::{Eof, EOF_MAGIC, EOF_MAGIC_BYTES, EOF_MAGIC_HASH}; pub use legacy::{JumpTable, LegacyAnalyzedBytecode}; use crate::{keccak256, Bytes, B256, KECCAK_EMPTY}; diff --git a/crates/primitives/src/bytecode/eof.rs b/crates/primitives/src/bytecode/eof.rs index 3f78bc26da..db6814b793 100644 --- a/crates/primitives/src/bytecode/eof.rs +++ b/crates/primitives/src/bytecode/eof.rs @@ -7,10 +7,20 @@ pub use body::EofBody; pub use header::EofHeader; pub use types_section::TypesSection; -use crate::Bytes; +use crate::{b256, bytes, Bytes, B256}; use core::cmp::min; use std::{vec, vec::Vec}; +/// Hash of EF00 bytes that is used for EXTCODEHASH when called from legacy bytecode. +pub const EOF_MAGIC_HASH: B256 = + b256!("9dbf3648db8210552e9c4f75c6a1c3057c0ca432043bd648be15fe7be05646f5"); + +/// EOF Magic in u16 form. +pub const EOF_MAGIC: u16 = 0xEF00; + +/// EOF magic number in array form. +pub static EOF_MAGIC_BYTES: Bytes = bytes!("ef00"); + /// EOF - Ethereum Object Format. /// /// It consist of a header, body and raw original bytes Specified in EIP. diff --git a/crates/revm/src/context.rs b/crates/revm/src/context.rs index 40107651cb..cc1fd20df9 100644 --- a/crates/revm/src/context.rs +++ b/crates/revm/src/context.rs @@ -13,7 +13,7 @@ use revm_interpreter::as_usize_saturated; use crate::{ db::{Database, EmptyDB}, interpreter::{Host, LoadAccountResult, SStoreResult, SelfDestructResult}, - primitives::{Address, Bytecode, Env, HandlerCfg, Log, B256, BLOCK_HASH_HISTORY, U256}, + primitives::{Address, Bytes, Env, HandlerCfg, Log, B256, BLOCK_HASH_HISTORY, U256}, }; use std::boxed::Box; @@ -146,7 +146,7 @@ impl Host for Context { .ok() } - fn code(&mut self, address: Address) -> Option<(Bytecode, bool)> { + fn code(&mut self, address: Address) -> Option<(Bytes, bool)> { self.evm .code(address) .map_err(|e| self.evm.error = Err(e)) diff --git a/crates/revm/src/context/inner_evm_context.rs b/crates/revm/src/context/inner_evm_context.rs index d12e90c148..3272b0e82e 100644 --- a/crates/revm/src/context/inner_evm_context.rs +++ b/crates/revm/src/context/inner_evm_context.rs @@ -10,7 +10,7 @@ use crate::{ keccak256, Account, Address, AnalysisKind, Bytecode, Bytes, CreateScheme, EVMError, Env, Eof, HashSet, Spec, SpecId::{self, *}, - B256, U256, + B256, EOF_MAGIC_BYTES, EOF_MAGIC_HASH, U256, }, FrameOrResult, JournalCheckpoint, CALL_STACK_LIMIT, }; @@ -160,21 +160,37 @@ impl InnerEvmContext { .map(|(acc, is_cold)| (acc.info.balance, is_cold)) } - /// Return account code and if address is cold loaded. + /// Return account code bytes and if address is cold loaded. + /// + /// In case of EOF account it will return `EOF_MAGIC` (0xEF00) as code. #[inline] - pub fn code(&mut self, address: Address) -> Result<(Bytecode, bool), EVMError> { + pub fn code(&mut self, address: Address) -> Result<(Bytes, bool), EVMError> { self.journaled_state .load_code(address, &mut self.db) - .map(|(a, is_cold)| (a.info.code.clone().unwrap(), is_cold)) + .map(|(a, is_cold)| { + // SAFETY: safe to unwrap as load_code will insert code if it is empty. + let code = a.info.code.as_ref().unwrap(); + if code.is_eof() { + (EOF_MAGIC_BYTES.clone(), is_cold) + } else { + (code.original_bytes().clone(), is_cold) + } + }) } /// Get code hash of address. + /// + /// In case of EOF account it will return `EOF_MAGIC_HASH` + /// (the hash of `0xEF00`). #[inline] pub fn code_hash(&mut self, address: Address) -> Result<(B256, bool), EVMError> { let (acc, is_cold) = self.journaled_state.load_code(address, &mut self.db)?; if acc.is_empty() { return Ok((B256::ZERO, is_cold)); } + if let Some(true) = acc.info.code.as_ref().map(|code| code.is_eof()) { + return Ok((EOF_MAGIC_HASH, is_cold)); + } Ok((acc.info.code_hash, is_cold)) }