diff --git a/Cargo.lock b/Cargo.lock index 9f4fadf97867f..e50cdafa9aa79 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -591,6 +591,16 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8ab6b55fe97976e46f91ddbed8d147d966475dc29b2032757ba47e02376fbc3" +[[package]] +name = "aurora-engine-modexp" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfacad86e9e138fca0670949eb8ed4ffdf73a55bded8887efe0863cd1a3a6f70" +dependencies = [ + "hex", + "num", +] + [[package]] name = "auto_impl" version = "1.1.0" @@ -893,9 +903,9 @@ dependencies = [ [[package]] name = "c-kzg" -version = "0.1.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac926d808fb72fe09ebf471a091d6d72918876ccf0b4989766093d2d0d24a0ef" +checksum = "32700dc7904064bb64e857d38a1766607372928e2466ee5f02a869829b3297d7" dependencies = [ "bindgen", "blst", @@ -5727,8 +5737,7 @@ dependencies = [ [[package]] name = "revm" version = "3.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f4ca8ae0345104523b4af1a8a7ea97cfa1865cdb7a7c25d23c1a18d9b48598" +source = "git+https://github.com/bluealloy/revm?rev=e17c529e51de83c938e606d7c79776fcc1a6381f#e17c529e51de83c938e606d7c79776fcc1a6381f" dependencies = [ "auto_impl", "revm-interpreter", @@ -5740,8 +5749,7 @@ dependencies = [ [[package]] name = "revm-interpreter" version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f959cafdf64a7f89b014fa73dc2325001cf654b3d9400260b212d19a2ebe3da0" +source = "git+https://github.com/bluealloy/revm?rev=e17c529e51de83c938e606d7c79776fcc1a6381f#e17c529e51de83c938e606d7c79776fcc1a6381f" dependencies = [ "revm-primitives", "serde", @@ -5750,12 +5758,11 @@ dependencies = [ [[package]] name = "revm-precompile" version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d360a88223d85709d2e95d4609eb1e19c649c47e28954bfabae5e92bb37e83e" +source = "git+https://github.com/bluealloy/revm?rev=e17c529e51de83c938e606d7c79776fcc1a6381f#e17c529e51de83c938e606d7c79776fcc1a6381f" dependencies = [ + "aurora-engine-modexp", "c-kzg", "k256", - "num", "once_cell", "revm-primitives", "ripemd", @@ -5767,8 +5774,7 @@ dependencies = [ [[package]] name = "revm-primitives" version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51187b852d9e458816a2e19c81f1dd6c924077e1a8fccd16e4f044f865f299d7" +source = "git+https://github.com/bluealloy/revm?rev=e17c529e51de83c938e606d7c79776fcc1a6381f#e17c529e51de83c938e606d7c79776fcc1a6381f" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -6273,18 +6279,18 @@ dependencies = [ [[package]] name = "secp256k1" -version = "0.27.0" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25996b82292a7a57ed3508f052cfff8640d38d32018784acd714758b43da9c8f" +checksum = "2acea373acb8c21ecb5a23741452acd2593ed44ee3d343e72baaa143bc89d0d5" dependencies = [ "secp256k1-sys", ] [[package]] name = "secp256k1-sys" -version = "0.8.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70a129b9e9efbfb223753b9163c4ab3b13cff7fd9c7f010fbac25ab4099fa07e" +checksum = "09e67c467c38fd24bd5499dc9a18183b31575c12ee549197e3e20d57aa4fe3b7" dependencies = [ "cc", ] diff --git a/Cargo.toml b/Cargo.toml index b666914ce8542..8e4a46aa4412d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -205,3 +205,6 @@ alloy-dyn-abi = { git = "https://github.com/alloy-rs/core/" } alloy-primitives = { git = "https://github.com/alloy-rs/core/" } alloy-json-abi = { git = "https://github.com/alloy-rs/core/" } alloy-sol-types = { git = "https://github.com/alloy-rs/core/" } + +revm = { git = "https://github.com/bluealloy/revm", rev = "e17c529e51de83c938e606d7c79776fcc1a6381f" } +revm-primitives = { git = "https://github.com/bluealloy/revm", rev = "e17c529e51de83c938e606d7c79776fcc1a6381f" } \ No newline at end of file diff --git a/crates/anvil/src/eth/backend/db.rs b/crates/anvil/src/eth/backend/db.rs index d848d9dea43db..ce592da13b468 100644 --- a/crates/anvil/src/eth/backend/db.rs +++ b/crates/anvil/src/eth/backend/db.rs @@ -136,7 +136,7 @@ pub trait Db: /// Deserialize and add all chain data to the backend storage fn load_state(&mut self, state: SerializableState) -> DatabaseResult { for (addr, account) in state.accounts.into_iter() { - let old_account_nonce = DatabaseRef::basic(self, addr.to_alloy()) + let old_account_nonce = DatabaseRef::basic_ref(self, addr.to_alloy()) .ok() .and_then(|acc| acc.map(|acc| acc.nonce)) .unwrap_or_default(); @@ -288,19 +288,19 @@ impl StateDb { impl DatabaseRef for StateDb { type Error = DatabaseError; - fn basic(&self, address: B160) -> DatabaseResult> { + fn basic_ref(&self, address: B160) -> DatabaseResult> { self.0.basic(address) } - fn code_by_hash(&self, code_hash: B256) -> DatabaseResult { + fn code_by_hash_ref(&self, code_hash: B256) -> DatabaseResult { self.0.code_by_hash(code_hash) } - fn storage(&self, address: B160, index: rU256) -> DatabaseResult { + fn storage_ref(&self, address: B160, index: rU256) -> DatabaseResult { self.0.storage(address, index) } - fn block_hash(&self, number: rU256) -> DatabaseResult { + fn block_hash_ref(&self, number: rU256) -> DatabaseResult { self.0.block_hash(number) } } diff --git a/crates/anvil/src/eth/backend/fork.rs b/crates/anvil/src/eth/backend/fork.rs index 7c33888937839..cc432ec22a843 100644 --- a/crates/anvil/src/eth/backend/fork.rs +++ b/crates/anvil/src/eth/backend/fork.rs @@ -122,7 +122,7 @@ impl ClientFork { self.config.read().base_fee } - pub fn block_hash(&self) -> H256 { + pub fn block_hash_ref(&self) -> H256 { self.config.read().block_hash } diff --git a/crates/anvil/src/eth/backend/genesis.rs b/crates/anvil/src/eth/backend/genesis.rs index 157f7b104e350..45374a2afa136 100644 --- a/crates/anvil/src/eth/backend/genesis.rs +++ b/crates/anvil/src/eth/backend/genesis.rs @@ -103,21 +103,21 @@ pub(crate) struct AtGenesisStateDb<'a> { impl<'a> DatabaseRef for AtGenesisStateDb<'a> { type Error = DatabaseError; - fn basic(&self, address: aAddress) -> DatabaseResult> { + fn basic_ref(&self, address: aAddress) -> DatabaseResult> { if let Some(acc) = self.accounts.get(&(address.to_ethers())).cloned() { return Ok(Some(acc)) } self.db.basic(address) } - fn code_by_hash(&self, code_hash: B256) -> DatabaseResult { + fn code_by_hash_ref(&self, code_hash: B256) -> DatabaseResult { if let Some((_, acc)) = self.accounts.iter().find(|(_, acc)| acc.code_hash == code_hash) { return Ok(acc.code.clone().unwrap_or_default()) } self.db.code_by_hash(code_hash) } - fn storage(&self, address: aAddress, index: U256) -> DatabaseResult { + fn storage_ref(&self, address: aAddress, index: U256) -> DatabaseResult { if let Some(acc) = self .genesis .as_ref() @@ -133,7 +133,7 @@ impl<'a> DatabaseRef for AtGenesisStateDb<'a> { self.db.storage(address, index) } - fn block_hash(&self, number: U256) -> DatabaseResult { + fn block_hash_ref(&self, number: U256) -> DatabaseResult { self.db.block_hash(number) } } diff --git a/crates/anvil/src/eth/backend/mem/inspector.rs b/crates/anvil/src/eth/backend/mem/inspector.rs index a4e2d0d94f4db..03e01f0d53031 100644 --- a/crates/anvil/src/eth/backend/mem/inspector.rs +++ b/crates/anvil/src/eth/backend/mem/inspector.rs @@ -8,9 +8,11 @@ use foundry_evm::{ inspectors::{LogCollector, Tracer}, revm, revm::{ - interpreter::{CallInputs, CreateInputs, Gas, InstructionResult, Interpreter}, + interpreter::{ + CallInputs, CreateInputs, Gas, InstructionResult, Interpreter, InterpreterResult, + }, primitives::{Address, Bytes, B256}, - EVMData, + EvmContext, }, }; @@ -48,29 +50,27 @@ impl Inspector { impl revm::Inspector for Inspector { #[inline] - fn initialize_interp( - &mut self, - interp: &mut Interpreter, - data: &mut EVMData<'_, DB>, - ) -> InstructionResult { + fn initialize_interp(&mut self, interp: &mut Interpreter, data: &mut EvmContext<'_, DB>) { call_inspectors!([&mut self.tracer], |inspector| { inspector.initialize_interp(interp, data); }); - InstructionResult::Continue } #[inline] - fn step(&mut self, interp: &mut Interpreter, data: &mut EVMData<'_, DB>) -> InstructionResult { + fn step( + &mut self, + interp: &mut Interpreter, + data: &mut EvmContext<'_, DB>, + ) -> InstructionResult { call_inspectors!([&mut self.tracer], |inspector| { inspector.step(interp, data); }); - InstructionResult::Continue } #[inline] fn log( &mut self, - evm_data: &mut EVMData<'_, DB>, + evm_data: &mut EvmContext<'_, DB>, address: &Address, topics: &[B256], data: &Bytes, @@ -81,22 +81,16 @@ impl revm::Inspector for Inspector { } #[inline] - fn step_end( - &mut self, - interp: &mut Interpreter, - data: &mut EVMData<'_, DB>, - eval: InstructionResult, - ) -> InstructionResult { + fn step_end(&mut self, interp: &mut Interpreter, data: &mut EvmContext<'_, DB>) { call_inspectors!([&mut self.tracer], |inspector| { - inspector.step_end(interp, data, eval); + inspector.step_end(interp, data); }); - eval } #[inline] fn call( &mut self, - data: &mut EVMData<'_, DB>, + data: &mut EvmContext<'_, DB>, call: &mut CallInputs, ) -> (InstructionResult, Gas, Bytes) { call_inspectors!([&mut self.tracer, Some(&mut self.log_collector)], |inspector| { @@ -109,45 +103,39 @@ impl revm::Inspector for Inspector { #[inline] fn call_end( &mut self, - data: &mut EVMData<'_, DB>, - inputs: &CallInputs, - remaining_gas: Gas, - ret: InstructionResult, - out: Bytes, - ) -> (InstructionResult, Gas, Bytes) { + ctx: &mut EvmContext<'_, DB>, + result: InterpreterResult, + ) -> InterpreterResult { call_inspectors!([&mut self.tracer], |inspector| { - inspector.call_end(data, inputs, remaining_gas, ret, out.clone()); + inspector.call_end(ctx, result.clone()); }); - (ret, remaining_gas, out) + result } #[inline] fn create( &mut self, - data: &mut EVMData<'_, DB>, - call: &mut CreateInputs, - ) -> (InstructionResult, Option
, Gas, Bytes) { + ctx: &mut EvmContext<'_, DB>, + inputs: &mut CreateInputs, + ) -> Option<(InterpreterResult, Option
)> { call_inspectors!([&mut self.tracer], |inspector| { - inspector.create(data, call); + inspector.create(ctx, inputs); }); - (InstructionResult::Continue, None, Gas::new(call.gas_limit), Bytes::new()) + None } #[inline] fn create_end( &mut self, - data: &mut EVMData<'_, DB>, - inputs: &CreateInputs, - status: InstructionResult, + ctx: &mut EvmContext<'_, DB>, + result: InterpreterResult, address: Option
, - gas: Gas, - retdata: Bytes, - ) -> (InstructionResult, Option
, Gas, Bytes) { + ) -> (InstructionResult, Option
) { call_inspectors!([&mut self.tracer], |inspector| { - inspector.create_end(data, inputs, status, address, gas, retdata.clone()); + inspector.create_end(ctx, result.clone(), address); }); - (status, address, gas, retdata) + (status, address) } } diff --git a/crates/cheatcodes/src/evm.rs b/crates/cheatcodes/src/evm.rs index c1cdcc1b22692..ba51f5aced8b2 100644 --- a/crates/cheatcodes/src/evm.rs +++ b/crates/cheatcodes/src/evm.rs @@ -10,7 +10,7 @@ use foundry_evm_core::backend::DatabaseExt; use foundry_utils::types::ToAlloy; use revm::{ primitives::{Account, Bytecode, SpecId, KECCAK_EMPTY}, - EVMData, + EvmContext, }; use std::{collections::HashMap, path::Path}; @@ -397,7 +397,7 @@ fn read_callers(state: &Cheatcodes, default_sender: &Address) -> Result { /// Ensures the `Account` is loaded and touched. pub(super) fn journaled_account<'a, DB: DatabaseExt>( - data: &'a mut EVMData<'_, DB>, + data: &'a mut EvmContext<'_, DB>, addr: Address, ) -> Result<&'a mut Account> { data.journaled_state.load_account(addr, data.db)?; diff --git a/crates/cheatcodes/src/evm/mapping.rs b/crates/cheatcodes/src/evm/mapping.rs index 8ff789c8e4191..f5acc4966595a 100644 --- a/crates/cheatcodes/src/evm/mapping.rs +++ b/crates/cheatcodes/src/evm/mapping.rs @@ -119,7 +119,7 @@ pub(crate) fn step(mapping_slots: &mut HashMap, interpret if interpreter.stack.peek(1) == Ok(U256::from(0x40)) { let address = interpreter.contract.address; let offset = interpreter.stack.peek(0).expect("stack size > 1").saturating_to(); - let data = interpreter.memory.slice(offset, 0x40); + let data = interpreter.shared_memory.slice(offset, 0x40); let low = B256::from_slice(&data[..0x20]); let high = B256::from_slice(&data[0x20..]); let result = keccak256(data); diff --git a/crates/cheatcodes/src/inspector.rs b/crates/cheatcodes/src/inspector.rs index 5c95cfc2fa2fd..07e10d0cbbb96 100644 --- a/crates/cheatcodes/src/inspector.rs +++ b/crates/cheatcodes/src/inspector.rs @@ -28,9 +28,11 @@ use foundry_evm_core::{ use foundry_utils::types::ToEthers; use itertools::Itertools; use revm::{ - interpreter::{opcode, CallInputs, CreateInputs, Gas, InstructionResult, Interpreter}, + interpreter::{ + opcode, CallInputs, CreateInputs, Gas, InstructionResult, Interpreter, InterpreterResult, + }, primitives::{BlockEnv, CreateScheme, TransactTo}, - EVMData, Inspector, + EvmContext, Inspector, }; use serde_json::Value; use std::{ @@ -211,7 +213,7 @@ impl Cheatcodes { fn apply_cheatcode( &mut self, - data: &mut EVMData<'_, DB>, + data: &mut EvmContext<'_, DB>, call: &CallInputs, ) -> Result { // decode the cheatcode call @@ -231,7 +233,7 @@ impl Cheatcodes { /// automatically we need to determine the new address fn allow_cheatcodes_on_create( &self, - data: &mut EVMData<'_, DB>, + data: &mut EvmContext<'_, DB>, inputs: &CreateInputs, ) { if data.journaled_state.depth > 1 && !data.db.has_cheatcode_access(inputs.caller) { @@ -255,7 +257,7 @@ impl Cheatcodes { /// /// Cleanup any previously applied cheatcodes that altered the state in such a way that revm's /// revert would run into issues. - pub fn on_revert(&mut self, data: &mut EVMData<'_, DB>) { + pub fn on_revert(&mut self, data: &mut EvmContext<'_, DB>) { trace!(deals = ?self.eth_deals.len(), "rolling back deals"); // Delay revert clean up until expected revert is handled, if set. @@ -281,11 +283,7 @@ impl Cheatcodes { impl Inspector for Cheatcodes { #[inline] - fn initialize_interp( - &mut self, - _: &mut Interpreter, - data: &mut EVMData<'_, DB>, - ) -> InstructionResult { + fn initialize_interp(&mut self, _: &mut Interpreter, data: &mut EvmContext<'_, DB>) { // When the first interpreter is initialized we've circumvented the balance and gas checks, // so we apply our actual block data with the correct fees and all. if let Some(block) = self.block.take() { @@ -294,15 +292,9 @@ impl Inspector for Cheatcodes { if let Some(gas_price) = self.gas_price.take() { data.env.tx.gas_price = gas_price; } - - InstructionResult::Continue } - fn step( - &mut self, - interpreter: &mut Interpreter, - data: &mut EVMData<'_, DB>, - ) -> InstructionResult { + fn step(&mut self, interpreter: &mut Interpreter, data: &mut EvmContext<'_, DB>) { self.pc = interpreter.program_counter(); // reset gas if gas metering is turned off @@ -448,7 +440,7 @@ impl Inspector for Cheatcodes { // If the offset being loaded is >= than the memory size, the // memory is being expanded. If none of the allowed ranges contain // [offset, offset + 32), memory has been unexpectedly mutated. - if offset >= interpreter.memory.len() as u64 && !ranges.iter().any(|range| { + if offset >= interpreter.shared_memory.len() as u64 && !ranges.iter().any(|range| { range.contains(&offset) && range.contains(&(offset + 31)) }) { disallowed_mem_write(offset, 32, interpreter, ranges); @@ -475,7 +467,7 @@ impl Inspector for Cheatcodes { range.contains(&(dest_offset + size.saturating_sub(1))) }) && ($writes || [dest_offset, (dest_offset + size).saturating_sub(1)].into_iter().any(|offset| { - offset >= interpreter.memory.len() as u64 + offset >= interpreter.shared_memory.len() as u64 }) ); @@ -519,11 +511,15 @@ impl Inspector for Cheatcodes { if let Some(mapping_slots) = &mut self.mapping_slots { mapping::step(mapping_slots, interpreter); } - - InstructionResult::Continue } - fn log(&mut self, _: &mut EVMData<'_, DB>, address: &Address, topics: &[B256], data: &Bytes) { + fn log( + &mut self, + _: &mut EvmContext<'_, DB>, + address: &Address, + topics: &[B256], + data: &Bytes, + ) { if !self.expected_emits.is_empty() { expect::handle_expect_emit(self, address, topics, data); } @@ -540,7 +536,7 @@ impl Inspector for Cheatcodes { fn call( &mut self, - data: &mut EVMData<'_, DB>, + data: &mut EvmContext<'_, DB>, call: &mut CallInputs, ) -> (InstructionResult, Gas, Bytes) { let gas = Gas::new(call.gas_limit); @@ -694,12 +690,9 @@ impl Inspector for Cheatcodes { fn call_end( &mut self, - data: &mut EVMData<'_, DB>, - call: &CallInputs, - remaining_gas: Gas, - status: InstructionResult, - retdata: Bytes, - ) -> (InstructionResult, Gas, Bytes) { + data: &mut EvmContext<'_, DB>, + result: InterpreterResult, + ) -> InterpreterResult { if call.contract == CHEATCODE_ADDRESS || call.contract == HARDHAT_CONSOLE_ADDRESS { return (status, remaining_gas, retdata) } @@ -891,9 +884,9 @@ impl Inspector for Cheatcodes { fn create( &mut self, - data: &mut EVMData<'_, DB>, - call: &mut CreateInputs, - ) -> (InstructionResult, Option
, Gas, Bytes) { + data: &mut EvmContext<'_, DB>, + inputs: &mut CreateInputs, + ) -> Option<(InterpreterResult, Option
)> { let gas = Gas::new(call.gas_limit); // allow cheatcodes from the address of the new contract @@ -970,13 +963,10 @@ impl Inspector for Cheatcodes { fn create_end( &mut self, - data: &mut EVMData<'_, DB>, - _: &CreateInputs, - status: InstructionResult, + ctx: &mut EvmContext<'_, DB>, + result: InterpreterResult, address: Option
, - remaining_gas: Gas, - retdata: Bytes, - ) -> (InstructionResult, Option
, Gas, Bytes) { + ) -> (InstructionResult, Option
) { // Clean up pranks if let Some(prank) = &self.prank { if data.journaled_state.depth() == prank.depth { @@ -1046,17 +1036,17 @@ fn disallowed_mem_write( /// Expands memory, stores a revert string, and sets the return range to the revert /// string's location in memory. fn mstore_revert_string(interpreter: &mut Interpreter, bytes: &[u8]) { - let starting_offset = interpreter.memory.len(); - interpreter.memory.resize(starting_offset + bytes.len()); - interpreter.memory.set_data(starting_offset, 0, bytes.len(), bytes); + let starting_offset = interpreter.shared_memory.len(); + interpreter.shared_memory.resize(starting_offset + bytes.len()); + interpreter.shared_memory.set_data(starting_offset, 0, bytes.len(), bytes); interpreter.return_offset = starting_offset; - interpreter.return_len = interpreter.memory.len() - starting_offset + interpreter.return_len = interpreter.shared_memory.len() - starting_offset } fn process_create( broadcast_sender: Address, bytecode: Bytes, - data: &mut EVMData<'_, DB>, + data: &mut EvmContext<'_, DB>, call: &mut CreateInputs, ) -> Result<(Bytes, Option
, u64), DB::Error> { match call.scheme { @@ -1094,7 +1084,10 @@ fn process_create( // Determines if the gas limit on a given call was manually set in the script and should therefore // not be overwritten by later estimations -fn check_if_fixed_gas_limit(data: &EVMData<'_, DB>, call_gas_limit: u64) -> bool { +fn check_if_fixed_gas_limit( + data: &EvmContext<'_, DB>, + call_gas_limit: u64, +) -> bool { // If the gas limit was not set in the source code it is set to the estimated gas left at the // time of the call, which should be rather close to configured gas limit. // TODO: Find a way to reliably make this determination. diff --git a/crates/cheatcodes/src/lib.rs b/crates/cheatcodes/src/lib.rs index e39f98f5a9623..4cd3da1e843be 100644 --- a/crates/cheatcodes/src/lib.rs +++ b/crates/cheatcodes/src/lib.rs @@ -12,7 +12,7 @@ extern crate tracing; use alloy_primitives::Address; use foundry_evm_core::backend::DatabaseExt; -use revm::EVMData; +use revm::EvmContext; use tracing::Level; pub use defs::{CheatcodeDef, Vm}; @@ -95,7 +95,7 @@ pub(crate) struct CheatsCtxt<'a, 'b, 'c, DB: DatabaseExt> { /// The cheatcodes inspector state. pub(crate) state: &'a mut Cheatcodes, /// The EVM data. - pub(crate) data: &'b mut EVMData<'c, DB>, + pub(crate) data: &'b mut EvmContext<'c, DB>, /// The original `msg.sender`. pub(crate) caller: Address, } diff --git a/crates/debugger/src/lib.rs b/crates/debugger/src/lib.rs index c6f645e8a2c07..bfa9ccd554e88 100644 --- a/crates/debugger/src/lib.rs +++ b/crates/debugger/src/lib.rs @@ -917,7 +917,6 @@ Line::from(Span::styled("[t]: stack labels | [m]: memory decoding | [shift + j/k let stack_space = Block::default() .title(format!("Memory (max expansion: {} bytes)", memory.len())) .borders(Borders::ALL); - let memory = memory.data(); let max_i = memory.len() / 32; let min_len = format!("{:x}", max_i * 32).len(); diff --git a/crates/evm/core/src/backend/fuzz.rs b/crates/evm/core/src/backend/fuzz.rs index e08266f6673d6..e57afd4f8e59d 100644 --- a/crates/evm/core/src/backend/fuzz.rs +++ b/crates/evm/core/src/backend/fuzz.rs @@ -63,7 +63,7 @@ impl<'a> FuzzBackendWrapper<'a> { // this is a new call to inspect with a new env, so even if we've cloned the backend // already, we reset the initialized state self.is_initialized = false; - match revm::evm_inner::(env, self, &mut inspector).transact() { + match revm::new_evm::(env, self, Some(&mut inspector)).transact() { Ok(result) => Ok(result), Err(e) => eyre::bail!("fuzz: failed to inspect: {:?}", e), } @@ -235,20 +235,20 @@ impl<'a> DatabaseExt for FuzzBackendWrapper<'a> { impl<'a> DatabaseRef for FuzzBackendWrapper<'a> { type Error = DatabaseError; - fn basic(&self, address: Address) -> Result, Self::Error> { - DatabaseRef::basic(self.backend.as_ref(), address) + fn basic_ref(&self, address: Address) -> Result, Self::Error> { + DatabaseRef::basic_ref(self.backend.as_ref(), address) } - fn code_by_hash(&self, code_hash: B256) -> Result { - DatabaseRef::code_by_hash(self.backend.as_ref(), code_hash) + fn code_by_hash_ref(&self, code_hash: B256) -> Result { + DatabaseRef::code_by_hash_ref(self.backend.as_ref(), code_hash) } - fn storage(&self, address: Address, index: U256) -> Result { - DatabaseRef::storage(self.backend.as_ref(), address, index) + fn storage_ref(&self, address: Address, index: U256) -> Result { + DatabaseRef::storage_ref(self.backend.as_ref(), address, index) } - fn block_hash(&self, number: U256) -> Result { - DatabaseRef::block_hash(self.backend.as_ref(), number) + fn block_hash_ref(&self, number: U256) -> Result { + DatabaseRef::block_hash_ref(self.backend.as_ref(), number) } } @@ -256,18 +256,18 @@ impl<'a> Database for FuzzBackendWrapper<'a> { type Error = DatabaseError; fn basic(&mut self, address: Address) -> Result, Self::Error> { - DatabaseRef::basic(self, address) + DatabaseRef::basic_ref(self, address) } fn code_by_hash(&mut self, code_hash: B256) -> Result { - DatabaseRef::code_by_hash(self, code_hash) + DatabaseRef::code_by_hash_ref(self, code_hash) } fn storage(&mut self, address: Address, index: U256) -> Result { - DatabaseRef::storage(self, address, index) + DatabaseRef::storage_ref(self, address, index) } fn block_hash(&mut self, number: U256) -> Result { - DatabaseRef::block_hash(self, number) + DatabaseRef::block_hash_ref(self, number) } } diff --git a/crates/evm/core/src/backend/in_memory_db.rs b/crates/evm/core/src/backend/in_memory_db.rs index 9041258593455..3681bba4a001d 100644 --- a/crates/evm/core/src/backend/in_memory_db.rs +++ b/crates/evm/core/src/backend/in_memory_db.rs @@ -29,20 +29,20 @@ impl Default for MemDb { impl DatabaseRef for MemDb { type Error = DatabaseError; - fn basic(&self, address: Address) -> Result, Self::Error> { - DatabaseRef::basic(&self.inner, address) + fn basic_ref(&self, address: Address) -> Result, Self::Error> { + DatabaseRef::basic_ref(&self.inner, address) } - fn code_by_hash(&self, code_hash: B256) -> Result { - DatabaseRef::code_by_hash(&self.inner, code_hash) + fn code_by_hash_ref(&self, code_hash: B256) -> Result { + DatabaseRef::code_by_hash_ref(&self.inner, code_hash) } - fn storage(&self, address: Address, index: U256) -> Result { - DatabaseRef::storage(&self.inner, address, index) + fn storage_ref(&self, address: Address, index: U256) -> Result { + DatabaseRef::storage_ref(&self.inner, address, index) } - fn block_hash(&self, number: U256) -> Result { - DatabaseRef::block_hash(&self.inner, number) + fn block_hash_ref(&self, number: U256) -> Result { + DatabaseRef::block_hash_ref(&self.inner, number) } } @@ -93,20 +93,20 @@ pub struct EmptyDBWrapper(EmptyDB); impl DatabaseRef for EmptyDBWrapper { type Error = DatabaseError; - fn basic(&self, _address: Address) -> Result, Self::Error> { + fn basic_ref(&self, _address: Address) -> Result, Self::Error> { // Note: this will always return `Some(AccountInfo)`, for the reason explained above Ok(Some(AccountInfo::default())) } - fn code_by_hash(&self, code_hash: B256) -> Result { - Ok(self.0.code_by_hash(code_hash)?) + fn code_by_hash_ref(&self, code_hash: B256) -> Result { + Ok(self.0.code_by_hash_ref(code_hash)?) } - fn storage(&self, address: Address, index: U256) -> Result { - Ok(self.0.storage(address, index)?) + fn storage_ref(&self, address: Address, index: U256) -> Result { + Ok(self.0.storage_ref(address, index)?) } - fn block_hash(&self, number: U256) -> Result { - Ok(self.0.block_hash(number)?) + fn block_hash_ref(&self, number: U256) -> Result { + Ok(self.0.block_hash_ref(number)?) } } @@ -144,7 +144,7 @@ mod tests { let mut db = CacheDB::new(EmptyDB::default()); let address = Address::random(); - let info = DatabaseRef::basic(&db, address).unwrap(); + let info = DatabaseRef::basic_ref(&db, address).unwrap(); assert!(info.is_none()); let mut info = info.unwrap_or_default(); info.balance = U256::from(500u64); diff --git a/crates/evm/core/src/backend/mod.rs b/crates/evm/core/src/backend/mod.rs index bdfe0a4c110ee..821f7e4ce23b5 100644 --- a/crates/evm/core/src/backend/mod.rs +++ b/crates/evm/core/src/backend/mod.rs @@ -14,6 +14,7 @@ use ethers::{ }; use foundry_common::{is_known_system_sender, SYSTEM_TRANSACTION_TYPE}; use foundry_utils::types::{ToAlloy, ToEthers}; +use itertools::Itertools; use revm::{ db::{CacheDB, DatabaseRef}, inspectors::NoOpInspector, @@ -595,7 +596,7 @@ impl Backend { bool private _failed; } */ - let value = self.storage(address, U256::ZERO).unwrap_or_default(); + let value = self.storage_ref(address, U256::ZERO).unwrap_or_default(); value.as_le_bytes()[1] != 0 } @@ -748,11 +749,11 @@ impl Backend { let test_contract = match env.tx.transact_to { TransactTo::Call(to) => to, TransactTo::Create(CreateScheme::Create) => { - revm::primitives::create_address(env.tx.caller, env.tx.nonce.unwrap_or_default()) + env.tx.caller.create(env.tx.nonce.unwrap_or_default()) } TransactTo::Create(CreateScheme::Create2 { salt }) => { let code_hash = B256::from_slice(keccak256(&env.tx.data).as_slice()); - revm::primitives::create2_address(env.tx.caller, code_hash, salt) + env.tx.caller.create2(B256::from(salt), code_hash) } }; self.set_test_contract(test_contract); @@ -769,7 +770,7 @@ impl Backend { { self.initialize(env); - match revm::evm_inner::(env, self, &mut inspector).transact() { + match revm::new_evm::(env, self, Some(&mut inspector)).transact() { Ok(res) => Ok(res), Err(e) => eyre::bail!("backend: failed while inspecting: {:?}", e), } @@ -1353,70 +1354,35 @@ impl DatabaseExt for Backend { impl DatabaseRef for Backend { type Error = DatabaseError; - fn basic(&self, address: Address) -> Result, Self::Error> { + fn basic_ref(&self, address: Address) -> Result, Self::Error> { if let Some(db) = self.active_fork_db() { - db.basic(address) - } else { - Ok(self.mem_db.basic(address)?) - } - } - - fn code_by_hash(&self, code_hash: B256) -> Result { - if let Some(db) = self.active_fork_db() { - db.code_by_hash(code_hash) - } else { - Ok(self.mem_db.code_by_hash(code_hash)?) - } - } - - fn storage(&self, address: Address, index: U256) -> Result { - if let Some(db) = self.active_fork_db() { - DatabaseRef::storage(db, address, index) - } else { - Ok(DatabaseRef::storage(&self.mem_db, address, index)?) - } - } - - fn block_hash(&self, number: U256) -> Result { - if let Some(db) = self.active_fork_db() { - db.block_hash(number) - } else { - Ok(self.mem_db.block_hash(number)?) - } - } -} - -impl<'a> DatabaseRef for &'a mut Backend { - type Error = DatabaseError; - fn basic(&self, address: Address) -> Result, Self::Error> { - if let Some(db) = self.active_fork_db() { - DatabaseRef::basic(db, address) + db.basic_ref(address) } else { - Ok(DatabaseRef::basic(&self.mem_db, address)?) + Ok(self.mem_db.basic_ref(address)?) } } - fn code_by_hash(&self, code_hash: B256) -> Result { + fn code_by_hash_ref(&self, code_hash: B256) -> Result { if let Some(db) = self.active_fork_db() { - DatabaseRef::code_by_hash(db, code_hash) + db.code_by_hash_ref(code_hash) } else { - Ok(DatabaseRef::code_by_hash(&self.mem_db, code_hash)?) + Ok(self.mem_db.code_by_hash_ref(code_hash)?) } } - fn storage(&self, address: Address, index: U256) -> Result { + fn storage_ref(&self, address: Address, index: U256) -> Result { if let Some(db) = self.active_fork_db() { - DatabaseRef::storage(db, address, index) + DatabaseRef::storage_ref(db, address, index) } else { - Ok(DatabaseRef::storage(&self.mem_db, address, index)?) + Ok(DatabaseRef::storage_ref(&self.mem_db, address, index)?) } } - fn block_hash(&self, number: U256) -> Result { + fn block_hash_ref(&self, number: U256) -> Result { if let Some(db) = self.active_fork_db() { - DatabaseRef::block_hash(db, number) + db.block_hash_ref(number) } else { - Ok(DatabaseRef::block_hash(&self.mem_db, number)?) + Ok(self.mem_db.block_hash_ref(number)?) } } } @@ -1487,7 +1453,7 @@ pub struct Fork { impl Fork { /// Returns true if the account is a contract pub fn is_contract(&self, acc: Address) -> bool { - if let Ok(Some(acc)) = self.db.basic(acc) { + if let Ok(Some(acc)) = self.db.basic_ref(acc) { if acc.code_hash != KECCAK_EMPTY { return true } @@ -1733,8 +1699,8 @@ impl BackendInner { } } JournaledState::new( - self.precompiles().len(), precompiles_spec_id_to_primitives_spec_id(self.precompile_id), + self.precompiles().addresses().into_iter().copied().collect(), ) } } diff --git a/crates/evm/core/src/debug.rs b/crates/evm/core/src/debug.rs index 3b6cab6167e30..afa977e807906 100644 --- a/crates/evm/core/src/debug.rs +++ b/crates/evm/core/src/debug.rs @@ -1,6 +1,6 @@ use crate::utils::CallKind; use alloy_primitives::{Address, U256}; -use revm::interpreter::{Memory, OpCode}; +use revm::interpreter::{OpCode, SharedMemory}; use serde::{Deserialize, Serialize}; use std::fmt::Display; @@ -114,7 +114,7 @@ pub struct DebugStep { /// Stack *prior* to running the associated opcode pub stack: Vec, /// Memory *prior* to running the associated opcode - pub memory: Memory, + pub memory: SharedMemory, /// Opcode to be executed pub instruction: Instruction, /// Optional bytes that are being pushed onto the stack @@ -132,7 +132,7 @@ impl Default for DebugStep { fn default() -> Self { Self { stack: vec![], - memory: Memory::new(), + memory: Default::default(), instruction: Instruction::OpCode(revm::interpreter::opcode::INVALID), push_bytes: None, pc: 0, diff --git a/crates/evm/core/src/fork/backend.rs b/crates/evm/core/src/fork/backend.rs index 587c3150c5673..067b07f96d832 100644 --- a/crates/evm/core/src/fork/backend.rs +++ b/crates/evm/core/src/fork/backend.rs @@ -642,7 +642,7 @@ impl SharedBackend { impl DatabaseRef for SharedBackend { type Error = DatabaseError; - fn basic(&self, address: Address) -> Result, Self::Error> { + fn basic_ref(&self, address: Address) -> Result, Self::Error> { trace!( target: "sharedbackend", "request basic {:?}", address); self.do_get_basic(address).map_err(|err| { error!(target: "sharedbackend", ?err, ?address, "Failed to send/recv `basic`"); @@ -653,11 +653,11 @@ impl DatabaseRef for SharedBackend { }) } - fn code_by_hash(&self, hash: B256) -> Result { + fn code_by_hash_ref(&self, hash: B256) -> Result { Err(DatabaseError::MissingCode(hash)) } - fn storage(&self, address: Address, index: U256) -> Result { + fn storage_ref(&self, address: Address, index: U256) -> Result { trace!( target: "sharedbackend", "request storage {:?} at {:?}", address, index); match self.do_get_storage(address, index).map_err(|err| { error!( target: "sharedbackend", ?err, ?address, ?index, "Failed to send/recv `storage`"); @@ -671,7 +671,7 @@ impl DatabaseRef for SharedBackend { } } - fn block_hash(&self, number: U256) -> Result { + fn block_hash_ref(&self, number: U256) -> Result { if number > U256::from(u64::MAX) { return Ok(KECCAK_EMPTY) } diff --git a/crates/evm/core/src/fork/database.rs b/crates/evm/core/src/fork/database.rs index 13596fee4796f..15cf91e882bb4 100644 --- a/crates/evm/core/src/fork/database.rs +++ b/crates/evm/core/src/fork/database.rs @@ -172,20 +172,20 @@ impl Database for ForkedDatabase { impl DatabaseRef for ForkedDatabase { type Error = DatabaseError; - fn basic(&self, address: Address) -> Result, Self::Error> { - self.cache_db.basic(address) + fn basic_ref(&self, address: Address) -> Result, Self::Error> { + self.cache_db.basic_ref(address) } - fn code_by_hash(&self, code_hash: B256) -> Result { - self.cache_db.code_by_hash(code_hash) + fn code_by_hash_ref(&self, code_hash: B256) -> Result { + self.cache_db.code_by_hash_ref(code_hash) } - fn storage(&self, address: Address, index: U256) -> Result { - DatabaseRef::storage(&self.cache_db, address, index) + fn storage_ref(&self, address: Address, index: U256) -> Result { + DatabaseRef::storage_ref(&self.cache_db, address, index) } - fn block_hash(&self, number: U256) -> Result { - self.cache_db.block_hash(number) + fn block_hash_ref(&self, number: U256) -> Result { + self.cache_db.block_hash_ref(number) } } @@ -218,43 +218,43 @@ impl ForkDbSnapshot { impl DatabaseRef for ForkDbSnapshot { type Error = DatabaseError; - fn basic(&self, address: Address) -> Result, Self::Error> { + fn basic_ref(&self, address: Address) -> Result, Self::Error> { match self.local.accounts.get(&address) { Some(account) => Ok(Some(account.info.clone())), None => { let mut acc = self.snapshot.accounts.get(&address).cloned(); if acc.is_none() { - acc = self.local.basic(address)?; + acc = self.local.basic_ref(address)?; } Ok(acc) } } } - fn code_by_hash(&self, code_hash: B256) -> Result { - self.local.code_by_hash(code_hash) + fn code_by_hash_ref(&self, code_hash: B256) -> Result { + self.local.code_by_hash_ref(code_hash) } - fn storage(&self, address: Address, index: U256) -> Result { + fn storage_ref(&self, address: Address, index: U256) -> Result { match self.local.accounts.get(&address) { Some(account) => match account.storage.get(&index) { Some(entry) => Ok(*entry), None => match self.get_storage(address, index) { - None => DatabaseRef::storage(&self.local, address, index), + None => DatabaseRef::storage_ref(&self.local, address, index), Some(storage) => Ok(storage), }, }, None => match self.get_storage(address, index) { - None => DatabaseRef::storage(&self.local, address, index), + None => DatabaseRef::storage_ref(&self.local, address, index), Some(storage) => Ok(storage), }, } } - fn block_hash(&self, number: U256) -> Result { + fn block_hash_ref(&self, number: U256) -> Result { match self.snapshot.block_hashes.get(&number).copied() { - None => self.local.block_hash(number), + None => self.local.block_hash_ref(number), Some(block_hash) => Ok(block_hash), } } diff --git a/crates/evm/coverage/src/inspector.rs b/crates/evm/coverage/src/inspector.rs index 3ee7ec98cce9b..53d88fb1dc6a3 100644 --- a/crates/evm/coverage/src/inspector.rs +++ b/crates/evm/coverage/src/inspector.rs @@ -2,7 +2,7 @@ use crate::{HitMap, HitMaps}; use alloy_primitives::Bytes; use revm::{ interpreter::{InstructionResult, Interpreter}, - Database, EVMData, Inspector, + Database, EvmContext, Inspector, }; #[derive(Clone, Default, Debug)] @@ -13,30 +13,18 @@ pub struct CoverageCollector { impl Inspector for CoverageCollector { #[inline] - fn initialize_interp( - &mut self, - interpreter: &mut Interpreter, - _: &mut EVMData<'_, DB>, - ) -> InstructionResult { + fn initialize_interp(&mut self, interpreter: &mut Interpreter, _: &mut EvmContext<'_, DB>) { let hash = interpreter.contract.hash; self.maps.entry(hash).or_insert_with(|| { HitMap::new(Bytes::copy_from_slice( interpreter.contract.bytecode.original_bytecode_slice(), )) }); - - InstructionResult::Continue } #[inline] - fn step( - &mut self, - interpreter: &mut Interpreter, - _: &mut EVMData<'_, DB>, - ) -> InstructionResult { + fn step(&mut self, interpreter: &mut Interpreter, _: &mut EvmContext<'_, DB>) { let hash = interpreter.contract.hash; self.maps.entry(hash).and_modify(|map| map.hit(interpreter.program_counter())); - - InstructionResult::Continue } } diff --git a/crates/evm/evm/src/executors/mod.rs b/crates/evm/evm/src/executors/mod.rs index 19b256541a7f1..a51b4336d98d5 100644 --- a/crates/evm/evm/src/executors/mod.rs +++ b/crates/evm/evm/src/executors/mod.rs @@ -27,7 +27,7 @@ use foundry_evm_coverage::HitMaps; use foundry_evm_traces::CallTraceArena; use revm::{ db::{DatabaseCommit, DatabaseRef}, - interpreter::{return_ok, CreateScheme, InstructionResult, Memory, Stack}, + interpreter::{return_ok, CreateScheme, InstructionResult, SharedMemory, Stack}, primitives::{ BlockEnv, Bytecode, Env, ExecutionResult, Output, ResultAndState, SpecId, TransactTo, TxEnv, }, diff --git a/crates/evm/evm/src/inspectors/access_list.rs b/crates/evm/evm/src/inspectors/access_list.rs index e7bf56e072920..ea0549404f13b 100644 --- a/crates/evm/evm/src/inspectors/access_list.rs +++ b/crates/evm/evm/src/inspectors/access_list.rs @@ -4,7 +4,7 @@ use foundry_utils::types::{ToAlloy, ToEthers}; use hashbrown::{HashMap, HashSet}; use revm::{ interpreter::{opcode, InstructionResult, Interpreter}, - Database, EVMData, Inspector, + Database, EvmContext, Inspector, }; /// An inspector that collects touched accounts and storage slots. @@ -51,11 +51,7 @@ impl AccessListTracer { impl Inspector for AccessListTracer { #[inline] - fn step( - &mut self, - interpreter: &mut Interpreter, - _data: &mut EVMData<'_, DB>, - ) -> InstructionResult { + fn step(&mut self, interpreter: &mut Interpreter, _data: &mut EvmContext<'_, DB>) { match interpreter.current_opcode() { opcode::SLOAD | opcode::SSTORE => { if let Ok(slot) = interpreter.stack().peek(0) { @@ -84,7 +80,6 @@ impl Inspector for AccessListTracer { } } _ => (), - } - InstructionResult::Continue + }; } } diff --git a/crates/evm/evm/src/inspectors/chisel_state.rs b/crates/evm/evm/src/inspectors/chisel_state.rs index 614cafeeb9679..b68d71c44d6c5 100644 --- a/crates/evm/evm/src/inspectors/chisel_state.rs +++ b/crates/evm/evm/src/inspectors/chisel_state.rs @@ -25,15 +25,14 @@ impl Inspector for ChiselState { fn step_end( &mut self, interp: &mut Interpreter, - _: &mut revm::EVMData<'_, DB>, + _: &mut revm::EvmContext<'_, DB>, eval: InstructionResult, - ) -> InstructionResult { + ) { // If we are at the final pc of the REPL contract execution, set the state. // Subtraction can't overflow because `pc` is always at least 1 in `step_end`. if self.final_pc == interp.program_counter() - 1 { - self.state = Some((interp.stack().clone(), interp.memory.clone(), eval)) + self.state = + Some((interp.stack().clone(), interp.memory.clone(), interp.instruction_result)) } - // Pass on [revm::Return] from arguments - eval } } diff --git a/crates/evm/evm/src/inspectors/debugger.rs b/crates/evm/evm/src/inspectors/debugger.rs index be06fc7225592..82754cd635690 100644 --- a/crates/evm/evm/src/inspectors/debugger.rs +++ b/crates/evm/evm/src/inspectors/debugger.rs @@ -9,9 +9,9 @@ use foundry_evm_core::{ use revm::{ interpreter::{ opcode::{self, spec_opcode_gas}, - CallInputs, CreateInputs, Gas, InstructionResult, Interpreter, + CallInputs, CreateInputs, Gas, InstructionResult, Interpreter, InterpreterResult, }, - EVMData, Inspector, + EvmContext, Inspector, }; /// An inspector that collects debug nodes on every step of the interpreter. @@ -45,11 +45,7 @@ impl Debugger { impl Inspector for Debugger { #[inline] - fn step( - &mut self, - interpreter: &mut Interpreter, - data: &mut EVMData<'_, DB>, - ) -> InstructionResult { + fn step(&mut self, interpreter: &mut Interpreter, data: &mut EvmContext<'_, DB>) { let pc = interpreter.program_counter(); let op = interpreter.current_opcode(); @@ -77,19 +73,17 @@ impl Inspector for Debugger { self.arena.arena[self.head].steps.push(DebugStep { pc, stack: interpreter.stack().data().clone(), - memory: interpreter.memory.clone(), + memory: interpreter.shared_memory.clone(), instruction: Instruction::OpCode(op), push_bytes, total_gas_used, }); - - InstructionResult::Continue } #[inline] fn call( &mut self, - data: &mut EVMData<'_, DB>, + data: &mut EvmContext<'_, DB>, call: &mut CallInputs, ) -> (InstructionResult, Gas, Bytes) { self.enter( @@ -113,23 +107,20 @@ impl Inspector for Debugger { #[inline] fn call_end( &mut self, - _: &mut EVMData<'_, DB>, - _: &CallInputs, - gas: Gas, - status: InstructionResult, - retdata: Bytes, - ) -> (InstructionResult, Gas, Bytes) { + ctx: &mut EvmContext<'_, DB>, + result: InterpreterResult, + ) -> InterpreterResult { self.exit(); - (status, gas, retdata) + result } #[inline] fn create( &mut self, - data: &mut EVMData<'_, DB>, - call: &mut CreateInputs, - ) -> (InstructionResult, Option
, Gas, Bytes) { + data: &mut EvmContext<'_, DB>, + inputs: &mut CreateInputs, + ) -> Option<(InterpreterResult, Option
)> { // TODO: Does this increase gas cost? if let Err(err) = data.journaled_state.load_account(call.caller, data.db) { let gas = Gas::new(call.gas_limit); @@ -149,13 +140,10 @@ impl Inspector for Debugger { #[inline] fn create_end( &mut self, - _: &mut EVMData<'_, DB>, - _: &CreateInputs, - status: InstructionResult, + ctx: &mut EvmContext<'_, DB>, + result: InterpreterResult, address: Option
, - gas: Gas, - retdata: Bytes, - ) -> (InstructionResult, Option
, Gas, Bytes) { + ) -> (InstructionResult, Option
) { self.exit(); (status, address, gas, retdata) diff --git a/crates/evm/evm/src/inspectors/logs.rs b/crates/evm/evm/src/inspectors/logs.rs index 8ad4cb648e77b..11ec48fc8592a 100644 --- a/crates/evm/evm/src/inspectors/logs.rs +++ b/crates/evm/evm/src/inspectors/logs.rs @@ -11,7 +11,7 @@ use foundry_macros::ConsoleFmt; use foundry_utils::types::ToEthers; use revm::{ interpreter::{CallInputs, Gas, InstructionResult}, - Database, EVMData, Inspector, + Database, EvmContext, Inspector, }; /// An inspector that collects logs during execution. @@ -44,7 +44,13 @@ impl LogCollector { } impl Inspector for LogCollector { - fn log(&mut self, _: &mut EVMData<'_, DB>, address: &Address, topics: &[B256], data: &Bytes) { + fn log( + &mut self, + _: &mut EvmContext<'_, DB>, + address: &Address, + topics: &[B256], + data: &Bytes, + ) { self.logs.push(Log { address: address.to_ethers(), topics: topics.iter().copied().map(|t| t.to_ethers()).collect(), @@ -55,7 +61,7 @@ impl Inspector for LogCollector { fn call( &mut self, - _: &mut EVMData<'_, DB>, + _: &mut EvmContext<'_, DB>, call: &mut CallInputs, ) -> (InstructionResult, Gas, Bytes) { if call.contract == HARDHAT_CONSOLE_ADDRESS { diff --git a/crates/evm/evm/src/inspectors/printer.rs b/crates/evm/evm/src/inspectors/printer.rs index 016e1c2e16309..b0a1a8c825d06 100644 --- a/crates/evm/evm/src/inspectors/printer.rs +++ b/crates/evm/evm/src/inspectors/printer.rs @@ -1,7 +1,9 @@ use alloy_primitives::{Address, Bytes}; use revm::{ - interpreter::{opcode, CallInputs, CreateInputs, Gas, InstructionResult, Interpreter}, - Database, EVMData, Inspector, + interpreter::{ + opcode, CallInputs, CreateInputs, Gas, InstructionResult, Interpreter, InterpreterResult, + }, + Database, EvmContext, Inspector, }; #[derive(Clone, Debug, Default)] @@ -11,7 +13,7 @@ pub struct TracePrinter; impl Inspector for TracePrinter { // get opcode by calling `interp.contract.opcode(interp.program_counter())`. // all other information can be obtained from interp. - fn step(&mut self, interp: &mut Interpreter, data: &mut EVMData<'_, DB>) -> InstructionResult { + fn step(&mut self, interp: &mut Interpreter, data: &mut EvmContext<'_, DB>) { let opcode = interp.current_opcode(); let opcode_str = opcode::OPCODE_JUMPMAP[opcode as usize]; let gas_remaining = interp.gas.remaining(); @@ -29,13 +31,11 @@ impl Inspector for TracePrinter { interp.memory.data().len(), hex::encode(interp.memory.data()), ); - - InstructionResult::Continue } fn call( &mut self, - _data: &mut EVMData<'_, DB>, + _data: &mut EvmContext<'_, DB>, inputs: &mut CallInputs, ) -> (InstructionResult, Gas, Bytes) { println!( @@ -51,9 +51,9 @@ impl Inspector for TracePrinter { fn create( &mut self, - _data: &mut EVMData<'_, DB>, + ctx: &mut EvmContext<'_, DB>, inputs: &mut CreateInputs, - ) -> (InstructionResult, Option
, Gas, Bytes) { + ) -> Option<(InterpreterResult, Option
)> { println!( "CREATE CALL: caller:{}, scheme:{:?}, value:{:?}, init_code:{:?}, gas:{:?}", inputs.caller, @@ -62,6 +62,6 @@ impl Inspector for TracePrinter { hex::encode(&inputs.init_code), inputs.gas_limit ); - (InstructionResult::Continue, None, Gas::new(0), Bytes::new()) + None } } diff --git a/crates/evm/evm/src/inspectors/stack.rs b/crates/evm/evm/src/inspectors/stack.rs index 1b63955660a41..0c83fe30ece7a 100644 --- a/crates/evm/evm/src/inspectors/stack.rs +++ b/crates/evm/evm/src/inspectors/stack.rs @@ -9,10 +9,11 @@ use foundry_evm_coverage::HitMaps; use foundry_evm_traces::CallTraceArena; use revm::{ interpreter::{ - return_revert, CallInputs, CreateInputs, Gas, InstructionResult, Interpreter, Memory, Stack, + return_revert, CallInputs, CreateInputs, Gas, InstructionResult, Interpreter, + InterpreterResult, Memory, Stack, }, primitives::{BlockEnv, Env}, - EVMData, Inspector, + EvmContext, Inspector, }; use std::{collections::BTreeMap, sync::Arc}; @@ -318,7 +319,7 @@ impl InspectorStack { fn do_call_end( &mut self, - data: &mut EVMData<'_, DB>, + data: &mut EvmContext<'_, DB>, call: &CallInputs, remaining_gas: Gas, status: InstructionResult, @@ -353,11 +354,7 @@ impl InspectorStack { } impl Inspector for InspectorStack { - fn initialize_interp( - &mut self, - interpreter: &mut Interpreter, - data: &mut EVMData<'_, DB>, - ) -> InstructionResult { + fn initialize_interp(&mut self, interpreter: &mut Interpreter, data: &mut EvmContext<'_, DB>) { call_inspectors!( [ &mut self.debugger, @@ -368,23 +365,12 @@ impl Inspector for InspectorStack { &mut self.printer ], |inspector| { - let status = inspector.initialize_interp(interpreter, data); - - // Allow inspectors to exit early - if status != InstructionResult::Continue { - return status - } + inspector.initialize_interp(interpreter, data); } ); - - InstructionResult::Continue } - fn step( - &mut self, - interpreter: &mut Interpreter, - data: &mut EVMData<'_, DB>, - ) -> InstructionResult { + fn step(&mut self, interpreter: &mut Interpreter, data: &mut EvmContext<'_, DB>) { call_inspectors!( [ &mut self.fuzzer, @@ -396,21 +382,14 @@ impl Inspector for InspectorStack { &mut self.printer ], |inspector| { - let status = inspector.step(interpreter, data); - - // Allow inspectors to exit early - if status != InstructionResult::Continue { - return status - } + inspector.step(interpreter, data); } ); - - InstructionResult::Continue } fn log( &mut self, - evm_data: &mut EVMData<'_, DB>, + evm_data: &mut EvmContext<'_, DB>, address: &Address, topics: &[B256], data: &Bytes, @@ -423,12 +402,7 @@ impl Inspector for InspectorStack { ); } - fn step_end( - &mut self, - interpreter: &mut Interpreter, - data: &mut EVMData<'_, DB>, - status: InstructionResult, - ) -> InstructionResult { + fn step_end(&mut self, interpreter: &mut Interpreter, data: &mut EvmContext<'_, DB>) { call_inspectors!( [ &mut self.debugger, @@ -439,12 +413,7 @@ impl Inspector for InspectorStack { &mut self.chisel_state ], |inspector| { - let status = inspector.step_end(interpreter, data, status); - - // Allow inspectors to exit early - if status != InstructionResult::Continue { - return status - } + inspector.step_end(interpreter, data); } ); @@ -453,7 +422,7 @@ impl Inspector for InspectorStack { fn call( &mut self, - data: &mut EVMData<'_, DB>, + data: &mut EvmContext<'_, DB>, call: &mut CallInputs, ) -> (InstructionResult, Gas, Bytes) { call_inspectors!( @@ -481,12 +450,9 @@ impl Inspector for InspectorStack { fn call_end( &mut self, - data: &mut EVMData<'_, DB>, - call: &CallInputs, - remaining_gas: Gas, - status: InstructionResult, - retdata: Bytes, - ) -> (InstructionResult, Gas, Bytes) { + data: &mut EvmContext<'_, DB>, + result: InterpreterResult, + ) -> InterpreterResult { let res = self.do_call_end(data, call, remaining_gas, status, retdata); if matches!(res.0, return_revert!()) { @@ -503,9 +469,9 @@ impl Inspector for InspectorStack { fn create( &mut self, - data: &mut EVMData<'_, DB>, + data: &mut EvmContext<'_, DB>, call: &mut CreateInputs, - ) -> (InstructionResult, Option
, Gas, Bytes) { + ) -> Option<(InterpreterResult, Option
)> { call_inspectors!( [ &mut self.debugger, @@ -516,27 +482,23 @@ impl Inspector for InspectorStack { &mut self.printer ], |inspector| { - let (status, addr, gas, retdata) = inspector.create(data, call); - + let res = inspector.create(data, call); // Allow inspectors to exit early - if status != InstructionResult::Continue { - return (status, addr, gas, retdata) + if res.is_some() { + return res } } ); - (InstructionResult::Continue, None, Gas::new(call.gas_limit), Bytes::new()) + None } fn create_end( &mut self, - data: &mut EVMData<'_, DB>, - call: &CreateInputs, - status: InstructionResult, + ctx: &mut EvmContext<'_, DB>, + result: InterpreterResult, address: Option
, - remaining_gas: Gas, - retdata: Bytes, - ) -> (InstructionResult, Option
, Gas, Bytes) { + ) -> (InstructionResult, Option
) { call_inspectors!( [ &mut self.debugger, diff --git a/crates/evm/fuzz/src/inspector.rs b/crates/evm/fuzz/src/inspector.rs index fe1b76c58a250..ec03d448b6d94 100644 --- a/crates/evm/fuzz/src/inspector.rs +++ b/crates/evm/fuzz/src/inspector.rs @@ -3,8 +3,8 @@ use alloy_primitives::Bytes; use foundry_evm_core::utils; use foundry_utils::types::ToEthers; use revm::{ - interpreter::{CallInputs, CallScheme, Gas, InstructionResult, Interpreter}, - Database, EVMData, Inspector, + interpreter::{CallInputs, CallScheme, Gas, InstructionResult, Interpreter, InterpreterResult}, + Database, EvmContext, Inspector, }; /// An inspector that can fuzz and collect data for that effect. @@ -20,23 +20,18 @@ pub struct Fuzzer { impl Inspector for Fuzzer { #[inline] - fn step( - &mut self, - interpreter: &mut Interpreter, - _: &mut EVMData<'_, DB>, - ) -> InstructionResult { + fn step(&mut self, interpreter: &mut Interpreter, _: &mut EvmContext<'_, DB>) { // We only collect `stack` and `memory` data before and after calls. if self.collect { self.collect_data(interpreter); self.collect = false; } - InstructionResult::Continue } #[inline] fn call( &mut self, - data: &mut EVMData<'_, DB>, + data: &mut EvmContext<'_, DB>, call: &mut CallInputs, ) -> (InstructionResult, Gas, Bytes) { // We don't want to override the very first call made to the test contract. @@ -54,12 +49,9 @@ impl Inspector for Fuzzer { #[inline] fn call_end( &mut self, - _: &mut EVMData<'_, DB>, - _: &CallInputs, - remaining_gas: Gas, - status: InstructionResult, - retdata: Bytes, - ) -> (InstructionResult, Gas, Bytes) { + ctx: &mut EvmContext<'_, DB>, + result: InterpreterResult, + ) -> InterpreterResult { if let Some(ref mut call_generator) = self.call_generator { call_generator.used = false; } @@ -82,9 +74,9 @@ impl Fuzzer { } // TODO: disabled for now since it's flooding the dictionary - // for index in 0..interpreter.memory.len() / 32 { + // for index in 0..interpreter.shared_memory.len() / 32 { // let mut slot = [0u8; 32]; - // slot.clone_from_slice(interpreter.memory.get_slice(index * 32, 32)); + // slot.clone_from_slice(interpreter.shared_memory.get_slice(index * 32, 32)); // state.insert(slot); // } diff --git a/crates/evm/traces/src/inspector.rs b/crates/evm/traces/src/inspector.rs index 80b34f0f14d31..120af72595b0e 100644 --- a/crates/evm/traces/src/inspector.rs +++ b/crates/evm/traces/src/inspector.rs @@ -9,9 +9,9 @@ use foundry_evm_core::{ use revm::{ interpreter::{ opcode, return_ok, CallInputs, CallScheme, CreateInputs, Gas, InstructionResult, - Interpreter, + Interpreter, InterpreterResult, }, - Database, EVMData, Inspector, JournalEntry, + Database, EvmContext, Inspector, JournalEntry, }; /// An inspector that collects call traces. @@ -74,7 +74,7 @@ impl Tracer { } } - fn start_step(&mut self, interp: &Interpreter, data: &EVMData<'_, DB>) { + fn start_step(&mut self, interp: &Interpreter, data: &EvmContext<'_, DB>) { let trace_idx = *self.trace_stack.last().expect("can't start step without starting a trace first"); let node = &mut self.traces.arena[trace_idx]; @@ -99,7 +99,7 @@ impl Tracer { fn fill_step( &mut self, interp: &Interpreter, - data: &EVMData<'_, DB>, + data: &EvmContext<'_, DB>, status: InstructionResult, ) { let (trace_idx, step_idx) = @@ -136,28 +136,21 @@ impl Tracer { impl Inspector for Tracer { #[inline] - fn step(&mut self, interp: &mut Interpreter, data: &mut EVMData<'_, DB>) -> InstructionResult { + fn step(&mut self, interp: &mut Interpreter, data: &mut EvmContext<'_, DB>) { if self.record_steps { self.start_step(interp, data); } - InstructionResult::Continue } #[inline] - fn step_end( - &mut self, - interp: &mut Interpreter, - data: &mut EVMData<'_, DB>, - status: InstructionResult, - ) -> InstructionResult { + fn step_end(&mut self, interp: &mut Interpreter, data: &mut EvmContext<'_, DB>) { if self.record_steps { - self.fill_step(interp, data, status); + self.fill_step(interp, data, interp.instruction_result); } - status } #[inline] - fn log(&mut self, _: &mut EVMData<'_, DB>, _: &Address, topics: &[B256], data: &Bytes) { + fn log(&mut self, _: &mut EvmContext<'_, DB>, _: &Address, topics: &[B256], data: &Bytes) { let node = &mut self.traces.arena[*self.trace_stack.last().expect("no ongoing trace")]; node.ordering.push(LogCallOrder::Log(node.logs.len())); let data = data.clone(); @@ -168,7 +161,7 @@ impl Inspector for Tracer { #[inline] fn call( &mut self, - data: &mut EVMData<'_, DB>, + data: &mut EvmContext<'_, DB>, inputs: &mut CallInputs, ) -> (InstructionResult, Gas, Bytes) { let (from, to) = match inputs.context.scheme { @@ -193,12 +186,9 @@ impl Inspector for Tracer { #[inline] fn call_end( &mut self, - data: &mut EVMData<'_, DB>, - _inputs: &CallInputs, - gas: Gas, - status: InstructionResult, - retdata: Bytes, - ) -> (InstructionResult, Gas, Bytes) { + data: &mut EvmContext<'_, DB>, + result: InterpreterResult, + ) -> InterpreterResult { self.fill_trace( status, gas_used(data.env.cfg.spec_id, gas.spend(), gas.refunded() as u64), @@ -212,9 +202,9 @@ impl Inspector for Tracer { #[inline] fn create( &mut self, - data: &mut EVMData<'_, DB>, + data: &mut EvmContext<'_, DB>, inputs: &mut CreateInputs, - ) -> (InstructionResult, Option
, Gas, Bytes) { + ) -> Option<(InterpreterResult, Option
)> { // TODO: Does this increase gas cost? let _ = data.journaled_state.load_account(inputs.caller, data.db); let nonce = data.journaled_state.account(inputs.caller).info.nonce; @@ -233,13 +223,10 @@ impl Inspector for Tracer { #[inline] fn create_end( &mut self, - data: &mut EVMData<'_, DB>, - _inputs: &CreateInputs, - status: InstructionResult, + data: &mut EvmContext<'_, DB>, + result: InterpreterResult, address: Option
, - gas: Gas, - retdata: Bytes, - ) -> (InstructionResult, Option
, Gas, Bytes) { + ) -> (InstructionResult, Option
) { let code = match address { Some(address) => data .journaled_state diff --git a/crates/evm/traces/src/lib.rs b/crates/evm/traces/src/lib.rs index 18c53aeace008..260bce4ad1295 100644 --- a/crates/evm/traces/src/lib.rs +++ b/crates/evm/traces/src/lib.rs @@ -14,7 +14,7 @@ use foundry_evm_core::{constants::CHEATCODE_ADDRESS, debug::Instruction, utils:: use foundry_utils::types::ToEthers; use hashbrown::HashMap; use itertools::Itertools; -use revm::interpreter::{opcode, CallContext, InstructionResult, Memory, Stack}; +use revm::interpreter::{opcode, CallContext, InstructionResult, SharedMemory, Stack}; use serde::{Deserialize, Serialize}; use std::{ collections::{BTreeMap, HashSet},