From 1b4aac2cd573640ab8dcef8c6e9d075372282bc7 Mon Sep 17 00:00:00 2001 From: joshieDo <93316087+joshieDo@users.noreply.github.com> Date: Mon, 7 Apr 2025 14:10:56 +0100 Subject: [PATCH] add TransferInspector to anvil Inspector --- crates/anvil/src/eth/backend/mem/inspector.rs | 38 +++++++++++-------- crates/anvil/src/eth/backend/mem/mod.rs | 25 ++++++------ crates/evm/evm/src/inspectors/mod.rs | 2 +- 3 files changed, 38 insertions(+), 27 deletions(-) diff --git a/crates/anvil/src/eth/backend/mem/inspector.rs b/crates/anvil/src/eth/backend/mem/inspector.rs index 9a68b70612461..988156c958f81 100644 --- a/crates/anvil/src/eth/backend/mem/inspector.rs +++ b/crates/anvil/src/eth/backend/mem/inspector.rs @@ -5,7 +5,7 @@ use alloy_primitives::{Address, Log}; use foundry_evm::{ call_inspectors, decode::decode_console_logs, - inspectors::{LogCollector, TracingInspector}, + inspectors::{LogCollector, TracingInspector, TransferInspector}, revm::{ interpreter::{ CallInputs, CallOutcome, CreateInputs, CreateOutcome, EOFCreateInputs, Interpreter, @@ -25,6 +25,8 @@ pub struct Inspector { pub tracer: Option, /// Collects all `console.sol` logs pub log_collector: Option, + /// Collects all internal ETH transfers as ERC20 transfer events. + pub transfer: Option, } impl Inspector { @@ -80,6 +82,12 @@ impl Inspector { self.tracer = Some(TracingInspector::new(TracingInspectorConfig::all().with_state_diffs())); self } + + /// Configures the `Tracer` [`revm::Inspector`] with a transfer event collector + pub fn with_transfers(mut self) -> Self { + self.transfer = Some(TransferInspector::new(false).with_logs(true)); + self + } } /// Prints the traces for the inspector @@ -132,7 +140,7 @@ impl revm::Inspector for Inspector { fn call(&mut self, ecx: &mut EvmContext, inputs: &mut CallInputs) -> Option { call_inspectors!( #[ret] - [&mut self.tracer, &mut self.log_collector], + [&mut self.tracer, &mut self.log_collector, &mut self.transfer], |inspector| inspector.call(ecx, inputs).map(Some), ); None @@ -156,11 +164,11 @@ impl revm::Inspector for Inspector { ecx: &mut EvmContext, inputs: &mut CreateInputs, ) -> Option { - if let Some(tracer) = &mut self.tracer { - if let Some(out) = tracer.create(ecx, inputs) { - return Some(out); - } - } + call_inspectors!( + #[ret] + [&mut self.tracer, &mut self.transfer], + |inspector| { inspector.create(ecx, inputs).map(Some) }, + ); None } @@ -183,11 +191,11 @@ impl revm::Inspector for Inspector { ecx: &mut EvmContext, inputs: &mut EOFCreateInputs, ) -> Option { - if let Some(tracer) = &mut self.tracer { - if let Some(out) = tracer.eofcreate(ecx, inputs) { - return Some(out); - } - } + call_inspectors!( + #[ret] + [&mut self.tracer, &mut self.transfer], + |inspector| { inspector.eofcreate(ecx, inputs).map(Some) }, + ); None } @@ -207,9 +215,9 @@ impl revm::Inspector for Inspector { #[inline] fn selfdestruct(&mut self, contract: Address, target: Address, value: U256) { - if let Some(tracer) = &mut self.tracer { - revm::Inspector::::selfdestruct(tracer, contract, target, value); - } + call_inspectors!([&mut self.tracer, &mut self.transfer], |inspector| { + revm::Inspector::::selfdestruct(inspector, contract, target, value); + },); } } diff --git a/crates/anvil/src/eth/backend/mem/mod.rs b/crates/anvil/src/eth/backend/mem/mod.rs index 761cebfea5fee..bc2d116684e75 100644 --- a/crates/anvil/src/eth/backend/mem/mod.rs +++ b/crates/anvil/src/eth/backend/mem/mod.rs @@ -106,7 +106,6 @@ use revm::{ primitives::{BlobExcessGasAndPrice, HashMap, OptimismFields, ResultAndState}, DatabaseCommit, }; -use revm_inspectors::transfer::TransferInspector; use std::{ collections::BTreeMap, io::{Read, Write}, @@ -1561,21 +1560,20 @@ impl Backend { env.block.basefee = U256::from(0); } - // transact - let ResultAndState { result, state } = if trace_transfers { + let mut inspector = self.build_inspector(); + if trace_transfers { // prepare inspector to capture transfer inside the evm so they are // recorded and included in logs - let mut inspector = TransferInspector::new(false).with_logs(true); + inspector = inspector.with_transfers(); + } + + // transact + let ResultAndState { result, state } = { let mut evm = - self.new_evm_with_inspector_ref(cache_db.as_dyn(), env, &mut inspector); + self.new_evm_with_inspector_ref(cache_db.as_dyn(), env, &mut inspector); + trace!(target: "backend", env=?evm.context.env(), spec=?evm.spec_id(), "simulate evm env"); evm.transact()? - } else { - let mut inspector = self.build_inspector(); - let mut evm = - self.new_evm_with_inspector_ref(cache_db.as_dyn(), env, &mut inspector); - trace!(target: "backend", env=?evm.context.env(),spec=?evm.spec_id(), "simulate evm env"); - evm.transact()? }; trace!(target: "backend", ?result, ?request, "simulate call"); @@ -1583,6 +1581,11 @@ impl Backend { cache_db.commit(state); gas_used += result.gas_used(); + inspector.print_logs(); + if self.print_traces { + inspector.into_print_traces(); + } + // TODO: this is likely incomplete // create the transaction from a request let from = request.from.unwrap_or_default(); diff --git a/crates/evm/evm/src/inspectors/mod.rs b/crates/evm/evm/src/inspectors/mod.rs index 41008397a1cbc..19034f41dd27d 100644 --- a/crates/evm/evm/src/inspectors/mod.rs +++ b/crates/evm/evm/src/inspectors/mod.rs @@ -5,7 +5,7 @@ pub use foundry_evm_coverage::CoverageCollector; pub use foundry_evm_fuzz::Fuzzer; pub use foundry_evm_traces::{StackSnapshotType, TracingInspector, TracingInspectorConfig}; -pub use revm_inspectors::access_list::AccessListInspector; +pub use revm_inspectors::{access_list::AccessListInspector, transfer::TransferInspector}; mod chisel_state; pub use chisel_state::ChiselState;