From 471e4ac317858b3419faaee58ade30c0671021e0 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Thu, 3 Oct 2024 02:02:55 +0200 Subject: [PATCH] chore: use dyn DatabaseExt everywhere (#8924) * wip * feat: use `dyn DatabaseExt` (#9010) * wip * clean up * fix * clippy * doc * fix imports * chore: simplify InspectorExt by making it lifetime-generic * fmt * chore: remove unnecessary casts and lifetimes * chore: more unused lifetimes (clippy) --------- Co-authored-by: DaniPopes <57450786+DaniPopes@users.noreply.github.com> --------- Co-authored-by: Arsenii Kulikov --- crates/anvil/src/eth/backend/executor.rs | 42 ++- crates/anvil/src/eth/backend/mem/inspector.rs | 15 - crates/anvil/src/eth/backend/mem/mod.rs | 14 +- crates/cheatcodes/src/evm.rs | 156 +++++---- crates/cheatcodes/src/evm/fork.rs | 86 ++--- crates/cheatcodes/src/evm/mock.rs | 14 +- crates/cheatcodes/src/evm/prank.rs | 14 +- crates/cheatcodes/src/fs.rs | 13 +- crates/cheatcodes/src/inspector.rs | 299 +++++++----------- crates/cheatcodes/src/inspector/utils.rs | 33 +- crates/cheatcodes/src/lib.rs | 59 ++-- crates/cheatcodes/src/script.rs | 28 +- crates/cheatcodes/src/test.rs | 15 +- crates/cheatcodes/src/test/assert.rs | 20 +- crates/cheatcodes/src/test/assume.rs | 4 +- crates/cheatcodes/src/test/expect.rs | 46 +-- crates/cheatcodes/src/utils.rs | 22 +- crates/evm/core/src/backend/cow.rs | 16 +- crates/evm/core/src/backend/mod.rs | 30 +- crates/evm/core/src/lib.rs | 12 +- crates/evm/core/src/utils.rs | 75 +---- crates/evm/evm/src/inspectors/logs.rs | 4 +- crates/evm/evm/src/inspectors/stack.rs | 111 ++++--- 23 files changed, 499 insertions(+), 629 deletions(-) diff --git a/crates/anvil/src/eth/backend/executor.rs b/crates/anvil/src/eth/backend/executor.rs index d92d60a87440..3221620ef0e8 100644 --- a/crates/anvil/src/eth/backend/executor.rs +++ b/crates/anvil/src/eth/backend/executor.rs @@ -28,8 +28,9 @@ use foundry_evm::{ }, }, traces::CallTraceNode, + utils::alphanet_handler_register, }; -use revm::primitives::MAX_BLOB_GAS_PER_BLOCK; +use revm::{db::WrapDatabaseRef, primitives::MAX_BLOB_GAS_PER_BLOCK}; use std::sync::Arc; /// Represents an executed transaction (transacted on the DB) @@ -303,7 +304,7 @@ impl<'a, 'b, DB: Db + ?Sized, V: TransactionValidator> Iterator let nonce = account.nonce; // records all call and step traces - let mut inspector = Inspector::default().with_tracing().with_alphanet(self.alphanet); + let mut inspector = Inspector::default().with_tracing(); if self.enable_steps_tracing { inspector = inspector.with_steps_tracing(); } @@ -312,8 +313,7 @@ impl<'a, 'b, DB: Db + ?Sized, V: TransactionValidator> Iterator } let exec_result = { - let mut evm = - foundry_evm::utils::new_evm_with_inspector(&mut *self.db, env, &mut inspector); + let mut evm = new_evm_with_inspector(&mut *self.db, env, &mut inspector, self.alphanet); if let Some(factory) = &self.precompile_factory { inject_precompiles(&mut evm, factory.precompiles()); } @@ -396,3 +396,37 @@ fn build_logs_bloom(logs: Vec, bloom: &mut Bloom) { } } } + +/// Creates a database with given database and inspector, optionally enabling alphanet features. +pub fn new_evm_with_inspector( + db: DB, + env: EnvWithHandlerCfg, + inspector: &mut dyn revm::Inspector, + alphanet: bool, +) -> revm::Evm<'_, &mut dyn revm::Inspector, DB> { + let EnvWithHandlerCfg { env, handler_cfg } = env; + + let mut handler = revm::Handler::new(handler_cfg); + + handler.append_handler_register_plain(revm::inspector_handle_register); + if alphanet { + handler.append_handler_register_plain(alphanet_handler_register); + } + + let context = revm::Context::new(revm::EvmContext::new_with_env(db, env), inspector); + + revm::Evm::new(context, handler) +} + +/// Creates a new EVM with the given inspector and wraps the database in a `WrapDatabaseRef`. +pub fn new_evm_with_inspector_ref<'a, DB>( + db: DB, + env: EnvWithHandlerCfg, + inspector: &mut dyn revm::Inspector>, + alphanet: bool, +) -> revm::Evm<'a, &mut dyn revm::Inspector>, WrapDatabaseRef> +where + DB: revm::DatabaseRef, +{ + new_evm_with_inspector(WrapDatabaseRef(db), env, inspector, alphanet) +} diff --git a/crates/anvil/src/eth/backend/mem/inspector.rs b/crates/anvil/src/eth/backend/mem/inspector.rs index b354a9a5c123..e590d57e35bb 100644 --- a/crates/anvil/src/eth/backend/mem/inspector.rs +++ b/crates/anvil/src/eth/backend/mem/inspector.rs @@ -14,7 +14,6 @@ use foundry_evm::{ EvmContext, }, traces::TracingInspectorConfig, - InspectorExt, }; /// The [`revm::Inspector`] used when transacting in the evm @@ -23,8 +22,6 @@ pub struct Inspector { pub tracer: Option, /// collects all `console.sol` logs pub log_collector: Option, - /// Whether to enable Alphanet support - pub alphanet: bool, } impl Inspector { @@ -59,12 +56,6 @@ impl Inspector { self.log_collector = Some(Default::default()); self } - - /// Enables Alphanet features - pub fn with_alphanet(mut self, yes: bool) -> Self { - self.alphanet = yes; - self - } } impl revm::Inspector for Inspector { @@ -176,12 +167,6 @@ impl revm::Inspector for Inspector { } } -impl InspectorExt for Inspector { - fn is_alphanet(&self) -> bool { - self.alphanet - } -} - /// Prints all the logs pub fn print_logs(logs: &[Log]) { for log in decode_console_logs(logs) { diff --git a/crates/anvil/src/eth/backend/mem/mod.rs b/crates/anvil/src/eth/backend/mem/mod.rs index ea36696f2748..dbf22fbebe7f 100644 --- a/crates/anvil/src/eth/backend/mem/mod.rs +++ b/crates/anvil/src/eth/backend/mem/mod.rs @@ -1,6 +1,7 @@ //! In-memory blockchain backend. use self::state::trie_storage; +use super::executor::new_evm_with_inspector_ref; use crate::{ config::PruneStateHistoryConfig, eth::{ @@ -32,6 +33,7 @@ use crate::{ revm::{db::DatabaseRef, primitives::AccountInfo}, ForkChoice, NodeConfig, PrecompileFactory, }; +use alloy_chains::NamedChain; use alloy_consensus::{Account, Header, Receipt, ReceiptWithBloom}; use alloy_eips::eip4844::MAX_BLOBS_PER_BLOCK; use alloy_primitives::{keccak256, Address, Bytes, TxHash, TxKind, B256, U256, U64}; @@ -64,8 +66,6 @@ use anvil_core::eth::{ utils::meets_eip155, }; use anvil_rpc::error::RpcError; - -use alloy_chains::NamedChain; use flate2::{read::GzDecoder, write::GzEncoder, Compression}; use foundry_evm::{ backend::{DatabaseError, DatabaseResult, RevertStateSnapshotAction}, @@ -81,8 +81,6 @@ use foundry_evm::{ }, }, traces::TracingInspectorConfig, - utils::new_evm_with_inspector_ref, - InspectorExt, }; use futures::channel::mpsc::{unbounded, UnboundedSender}; use parking_lot::{Mutex, RwLock}; @@ -864,15 +862,15 @@ impl Backend { &self, db: &'db dyn DatabaseRef, env: EnvWithHandlerCfg, - inspector: &'i mut dyn InspectorExt< + inspector: &'i mut dyn revm::Inspector< WrapDatabaseRef<&'db dyn DatabaseRef>, >, ) -> revm::Evm< '_, - &'i mut dyn InspectorExt>>, + &'i mut dyn revm::Inspector>>, WrapDatabaseRef<&'db dyn DatabaseRef>, > { - let mut evm = new_evm_with_inspector_ref(db, env, inspector); + let mut evm = new_evm_with_inspector_ref(db, env, inspector, self.alphanet); if let Some(factory) = &self.precompile_factory { inject_precompiles(&mut evm, factory.precompiles()); } @@ -1269,7 +1267,7 @@ impl Backend { /// Builds [`Inspector`] with the configured options fn build_inspector(&self) -> Inspector { - let mut inspector = Inspector::default().with_alphanet(self.alphanet); + let mut inspector = Inspector::default(); if self.print_logs { inspector = inspector.with_log_collector(); diff --git a/crates/cheatcodes/src/evm.rs b/crates/cheatcodes/src/evm.rs index 7d4a23d6126b..f9671430dc08 100644 --- a/crates/cheatcodes/src/evm.rs +++ b/crates/cheatcodes/src/evm.rs @@ -1,7 +1,8 @@ //! Implementations of [`Evm`](spec::Group::Evm) cheatcodes. use crate::{ - BroadcastableTransaction, Cheatcode, Cheatcodes, CheatcodesExecutor, CheatsCtxt, Result, Vm::*, + inspector::InnerEcx, BroadcastableTransaction, Cheatcode, Cheatcodes, CheatcodesExecutor, + CheatsCtxt, Result, Vm::*, }; use alloy_consensus::TxEnvelope; use alloy_genesis::{Genesis, GenesisAccount}; @@ -14,10 +15,7 @@ use foundry_evm_core::{ constants::{CALLER, CHEATCODE_ADDRESS, HARDHAT_CONSOLE_ADDRESS, TEST_CONTRACT_ADDRESS}, }; use rand::Rng; -use revm::{ - primitives::{Account, Bytecode, SpecId, KECCAK_EMPTY}, - InnerEvmContext, -}; +use revm::primitives::{Account, Bytecode, SpecId, KECCAK_EMPTY}; use std::{ collections::{BTreeMap, HashMap}, path::Path, @@ -85,21 +83,21 @@ impl Cheatcode for addrCall { } impl Cheatcode for getNonce_0Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { account } = self; get_nonce(ccx, account) } } impl Cheatcode for getNonce_1Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { wallet } = self; get_nonce(ccx, &wallet.addr) } } impl Cheatcode for loadCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { target, slot } = *self; ensure_not_precompile!(&target, ccx); ccx.ecx.load_account(target)?; @@ -136,7 +134,7 @@ impl Cheatcode for loadCall { } impl Cheatcode for loadAllocsCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { pathToAllocsJson } = self; let path = Path::new(pathToAllocsJson); @@ -162,7 +160,7 @@ impl Cheatcode for loadAllocsCall { } impl Cheatcode for dumpStateCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { pathToStateJson } = self; let path = Path::new(pathToStateJson); @@ -282,7 +280,7 @@ impl Cheatcode for lastCallGasCall { } impl Cheatcode for chainIdCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { newChainId } = self; ensure!(*newChainId <= U256::from(u64::MAX), "chain ID must be less than 2^64 - 1"); ccx.ecx.env.cfg.chain_id = newChainId.to(); @@ -291,7 +289,7 @@ impl Cheatcode for chainIdCall { } impl Cheatcode for coinbaseCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { newCoinbase } = self; ccx.ecx.env.block.coinbase = *newCoinbase; Ok(Default::default()) @@ -299,7 +297,7 @@ impl Cheatcode for coinbaseCall { } impl Cheatcode for difficultyCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { newDifficulty } = self; ensure!( ccx.ecx.spec_id() < SpecId::MERGE, @@ -312,7 +310,7 @@ impl Cheatcode for difficultyCall { } impl Cheatcode for feeCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { newBasefee } = self; ccx.ecx.env.block.basefee = *newBasefee; Ok(Default::default()) @@ -320,7 +318,7 @@ impl Cheatcode for feeCall { } impl Cheatcode for prevrandao_0Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { newPrevrandao } = self; ensure!( ccx.ecx.spec_id() >= SpecId::MERGE, @@ -333,7 +331,7 @@ impl Cheatcode for prevrandao_0Call { } impl Cheatcode for prevrandao_1Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { newPrevrandao } = self; ensure!( ccx.ecx.spec_id() >= SpecId::MERGE, @@ -346,7 +344,7 @@ impl Cheatcode for prevrandao_1Call { } impl Cheatcode for blobhashesCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { hashes } = self; ensure!( ccx.ecx.spec_id() >= SpecId::CANCUN, @@ -359,7 +357,7 @@ impl Cheatcode for blobhashesCall { } impl Cheatcode for getBlobhashesCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self {} = self; ensure!( ccx.ecx.spec_id() >= SpecId::CANCUN, @@ -371,7 +369,7 @@ impl Cheatcode for getBlobhashesCall { } impl Cheatcode for rollCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { newHeight } = self; ccx.ecx.env.block.number = *newHeight; Ok(Default::default()) @@ -379,14 +377,14 @@ impl Cheatcode for rollCall { } impl Cheatcode for getBlockNumberCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self {} = self; Ok(ccx.ecx.env.block.number.abi_encode()) } } impl Cheatcode for txGasPriceCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { newGasPrice } = self; ccx.ecx.env.tx.gas_price = *newGasPrice; Ok(Default::default()) @@ -394,7 +392,7 @@ impl Cheatcode for txGasPriceCall { } impl Cheatcode for warpCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { newTimestamp } = self; ccx.ecx.env.block.timestamp = *newTimestamp; Ok(Default::default()) @@ -402,14 +400,14 @@ impl Cheatcode for warpCall { } impl Cheatcode for getBlockTimestampCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self {} = self; Ok(ccx.ecx.env.block.timestamp.abi_encode()) } } impl Cheatcode for blobBaseFeeCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { newBlobBaseFee } = self; ensure!( ccx.ecx.spec_id() >= SpecId::CANCUN, @@ -422,14 +420,14 @@ impl Cheatcode for blobBaseFeeCall { } impl Cheatcode for getBlobBaseFeeCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self {} = self; Ok(ccx.ecx.env.block.get_blob_excess_gas().unwrap_or(0).abi_encode()) } } impl Cheatcode for dealCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { account: address, newBalance: new_balance } = *self; let account = journaled_account(ccx.ecx, address)?; let old_balance = std::mem::replace(&mut account.info.balance, new_balance); @@ -440,7 +438,7 @@ impl Cheatcode for dealCall { } impl Cheatcode for etchCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { target, newRuntimeBytecode } = self; ensure_not_precompile!(target, ccx); ccx.ecx.load_account(*target)?; @@ -451,7 +449,7 @@ impl Cheatcode for etchCall { } impl Cheatcode for resetNonceCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { account } = self; let account = journaled_account(ccx.ecx, *account)?; // Per EIP-161, EOA nonces start at 0, but contract nonces @@ -466,7 +464,7 @@ impl Cheatcode for resetNonceCall { } impl Cheatcode for setNonceCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { account, newNonce } = *self; let account = journaled_account(ccx.ecx, account)?; // nonce must increment only @@ -482,7 +480,7 @@ impl Cheatcode for setNonceCall { } impl Cheatcode for setNonceUnsafeCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { account, newNonce } = *self; let account = journaled_account(ccx.ecx, account)?; account.info.nonce = newNonce; @@ -491,7 +489,7 @@ impl Cheatcode for setNonceUnsafeCall { } impl Cheatcode for storeCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { target, slot, value } = *self; ensure_not_precompile!(&target, ccx); // ensure the account is touched @@ -502,7 +500,7 @@ impl Cheatcode for storeCall { } impl Cheatcode for coolCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { target } = self; if let Some(account) = ccx.ecx.journaled_state.state.get_mut(target) { account.unmark_touch(); @@ -513,28 +511,28 @@ impl Cheatcode for coolCall { } impl Cheatcode for readCallersCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self {} = self; read_callers(ccx.state, &ccx.ecx.env.tx.caller) } } impl Cheatcode for snapshotValue_0Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { name, value } = self; inner_value_snapshot(ccx, None, Some(name.clone()), value.to_string()) } } impl Cheatcode for snapshotValue_1Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { group, name, value } = self; inner_value_snapshot(ccx, Some(group.clone()), Some(name.clone()), value.to_string()) } } impl Cheatcode for snapshotGasLastCall_0Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { name } = self; let Some(last_call_gas) = &ccx.state.gas_metering.last_call_gas else { bail!("no external call was made yet"); @@ -544,7 +542,7 @@ impl Cheatcode for snapshotGasLastCall_0Call { } impl Cheatcode for snapshotGasLastCall_1Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { name, group } = self; let Some(last_call_gas) = &ccx.state.gas_metering.last_call_gas else { bail!("no external call was made yet"); @@ -559,35 +557,35 @@ impl Cheatcode for snapshotGasLastCall_1Call { } impl Cheatcode for startSnapshotGas_0Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { name } = self; inner_start_gas_snapshot(ccx, None, Some(name.clone())) } } impl Cheatcode for startSnapshotGas_1Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { group, name } = self; inner_start_gas_snapshot(ccx, Some(group.clone()), Some(name.clone())) } } impl Cheatcode for stopSnapshotGas_0Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self {} = self; inner_stop_gas_snapshot(ccx, None, None) } } impl Cheatcode for stopSnapshotGas_1Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { name } = self; inner_stop_gas_snapshot(ccx, None, Some(name.clone())) } } impl Cheatcode for stopSnapshotGas_2Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { group, name } = self; inner_stop_gas_snapshot(ccx, Some(group.clone()), Some(name.clone())) } @@ -595,14 +593,14 @@ impl Cheatcode for stopSnapshotGas_2Call { // Deprecated in favor of `snapshotStateCall` impl Cheatcode for snapshotCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self {} = self; inner_snapshot_state(ccx) } } impl Cheatcode for snapshotStateCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self {} = self; inner_snapshot_state(ccx) } @@ -610,14 +608,14 @@ impl Cheatcode for snapshotStateCall { // Deprecated in favor of `revertToStateCall` impl Cheatcode for revertToCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { snapshotId } = self; inner_revert_to_state(ccx, *snapshotId) } } impl Cheatcode for revertToStateCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { snapshotId } = self; inner_revert_to_state(ccx, *snapshotId) } @@ -625,14 +623,14 @@ impl Cheatcode for revertToStateCall { // Deprecated in favor of `revertToStateAndDeleteCall` impl Cheatcode for revertToAndDeleteCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { snapshotId } = self; inner_revert_to_state_and_delete(ccx, *snapshotId) } } impl Cheatcode for revertToStateAndDeleteCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { snapshotId } = self; inner_revert_to_state_and_delete(ccx, *snapshotId) } @@ -640,14 +638,14 @@ impl Cheatcode for revertToStateAndDeleteCall { // Deprecated in favor of `deleteStateSnapshotCall` impl Cheatcode for deleteSnapshotCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { snapshotId } = self; inner_delete_state_snapshot(ccx, *snapshotId) } } impl Cheatcode for deleteStateSnapshotCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { snapshotId } = self; inner_delete_state_snapshot(ccx, *snapshotId) } @@ -655,14 +653,14 @@ impl Cheatcode for deleteStateSnapshotCall { // Deprecated in favor of `deleteStateSnapshotsCall` impl Cheatcode for deleteSnapshotsCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self {} = self; inner_delete_state_snapshots(ccx) } } impl Cheatcode for deleteStateSnapshotsCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self {} = self; inner_delete_state_snapshots(ccx) } @@ -684,11 +682,7 @@ impl Cheatcode for stopAndReturnStateDiffCall { } impl Cheatcode for broadcastRawTransactionCall { - fn apply_full( - &self, - ccx: &mut CheatsCtxt, - executor: &mut E, - ) -> Result { + fn apply_full(&self, ccx: &mut CheatsCtxt, executor: &mut dyn CheatcodesExecutor) -> Result { let mut data = self.data.as_ref(); let tx = TxEnvelope::decode(&mut data) .map_err(|err| fmt_err!("failed to decode RLP-encoded transaction: {err}"))?; @@ -697,7 +691,7 @@ impl Cheatcode for broadcastRawTransactionCall { tx.clone().into(), &ccx.ecx.env, &mut ccx.ecx.journaled_state, - &mut executor.get_inspector(ccx.state), + &mut *executor.get_inspector(ccx.state), )?; if ccx.state.broadcast.is_some() { @@ -712,7 +706,7 @@ impl Cheatcode for broadcastRawTransactionCall { } impl Cheatcode for setBlockhashCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { blockNumber, blockHash } = *self; ensure!( blockNumber <= ccx.ecx.env.block.number, @@ -725,16 +719,16 @@ impl Cheatcode for setBlockhashCall { } } -pub(super) fn get_nonce(ccx: &mut CheatsCtxt, address: &Address) -> Result { +pub(super) fn get_nonce(ccx: &mut CheatsCtxt, address: &Address) -> Result { let account = ccx.ecx.journaled_state.load_account(*address, &mut ccx.ecx.db)?; Ok(account.info.nonce.abi_encode()) } -fn inner_snapshot_state(ccx: &mut CheatsCtxt) -> Result { +fn inner_snapshot_state(ccx: &mut CheatsCtxt) -> Result { Ok(ccx.ecx.db.snapshot_state(&ccx.ecx.journaled_state, &ccx.ecx.env).abi_encode()) } -fn inner_revert_to_state(ccx: &mut CheatsCtxt, snapshot_id: U256) -> Result { +fn inner_revert_to_state(ccx: &mut CheatsCtxt, snapshot_id: U256) -> Result { let result = if let Some(journaled_state) = ccx.ecx.db.revert_state( snapshot_id, &ccx.ecx.journaled_state, @@ -750,10 +744,7 @@ fn inner_revert_to_state(ccx: &mut CheatsCtxt, snapshot_id: Ok(result.abi_encode()) } -fn inner_revert_to_state_and_delete( - ccx: &mut CheatsCtxt, - snapshot_id: U256, -) -> Result { +fn inner_revert_to_state_and_delete(ccx: &mut CheatsCtxt, snapshot_id: U256) -> Result { let result = if let Some(journaled_state) = ccx.ecx.db.revert_state( snapshot_id, &ccx.ecx.journaled_state, @@ -769,21 +760,18 @@ fn inner_revert_to_state_and_delete( Ok(result.abi_encode()) } -fn inner_delete_state_snapshot( - ccx: &mut CheatsCtxt, - snapshot_id: U256, -) -> Result { +fn inner_delete_state_snapshot(ccx: &mut CheatsCtxt, snapshot_id: U256) -> Result { let result = ccx.ecx.db.delete_state_snapshot(snapshot_id); Ok(result.abi_encode()) } -fn inner_delete_state_snapshots(ccx: &mut CheatsCtxt) -> Result { +fn inner_delete_state_snapshots(ccx: &mut CheatsCtxt) -> Result { ccx.ecx.db.delete_state_snapshots(); Ok(Default::default()) } -fn inner_value_snapshot( - ccx: &mut CheatsCtxt, +fn inner_value_snapshot( + ccx: &mut CheatsCtxt, group: Option, name: Option, value: String, @@ -795,8 +783,8 @@ fn inner_value_snapshot( Ok(Default::default()) } -fn inner_last_gas_snapshot( - ccx: &mut CheatsCtxt, +fn inner_last_gas_snapshot( + ccx: &mut CheatsCtxt, group: Option, name: Option, value: u64, @@ -808,8 +796,8 @@ fn inner_last_gas_snapshot( Ok(value.abi_encode()) } -fn inner_start_gas_snapshot( - ccx: &mut CheatsCtxt, +fn inner_start_gas_snapshot( + ccx: &mut CheatsCtxt, group: Option, name: Option, ) -> Result { @@ -835,8 +823,8 @@ fn inner_start_gas_snapshot( Ok(Default::default()) } -fn inner_stop_gas_snapshot( - ccx: &mut CheatsCtxt, +fn inner_stop_gas_snapshot( + ccx: &mut CheatsCtxt, group: Option, name: Option, ) -> Result { @@ -886,8 +874,8 @@ fn inner_stop_gas_snapshot( } // Derives the snapshot group and name from the provided group and name or the running contract. -fn derive_snapshot_name( - ccx: &CheatsCtxt, +fn derive_snapshot_name( + ccx: &CheatsCtxt, group: Option, name: Option, ) -> (String, String) { @@ -947,10 +935,10 @@ fn read_callers(state: &Cheatcodes, default_sender: &Address) -> Result { } /// Ensures the `Account` is loaded and touched. -pub(super) fn journaled_account( - ecx: &mut InnerEvmContext, +pub(super) fn journaled_account<'a>( + ecx: InnerEcx<'a, '_, '_>, addr: Address, -) -> Result<&mut Account> { +) -> Result<&'a mut Account> { ecx.load_account(addr)?; ecx.journaled_state.touch(&addr); Ok(ecx.journaled_state.state.get_mut(&addr).expect("account is loaded")) diff --git a/crates/cheatcodes/src/evm/fork.rs b/crates/cheatcodes/src/evm/fork.rs index a8cc830009fe..84fda7883c7d 100644 --- a/crates/cheatcodes/src/evm/fork.rs +++ b/crates/cheatcodes/src/evm/fork.rs @@ -1,4 +1,4 @@ -use crate::{Cheatcode, Cheatcodes, CheatsCtxt, DatabaseExt, Result, Vm::*}; +use crate::{Cheatcode, Cheatcodes, CheatcodesExecutor, CheatsCtxt, DatabaseExt, Result, Vm::*}; use alloy_dyn_abi::DynSolValue; use alloy_primitives::{B256, U256}; use alloy_provider::Provider; @@ -8,7 +8,7 @@ use foundry_common::provider::ProviderBuilder; use foundry_evm_core::fork::CreateFork; impl Cheatcode for activeForkCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self {} = self; ccx.ecx .db @@ -19,49 +19,49 @@ impl Cheatcode for activeForkCall { } impl Cheatcode for createFork_0Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { urlOrAlias } = self; create_fork(ccx, urlOrAlias, None) } } impl Cheatcode for createFork_1Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { urlOrAlias, blockNumber } = self; create_fork(ccx, urlOrAlias, Some(blockNumber.saturating_to())) } } impl Cheatcode for createFork_2Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { urlOrAlias, txHash } = self; create_fork_at_transaction(ccx, urlOrAlias, txHash) } } impl Cheatcode for createSelectFork_0Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { urlOrAlias } = self; create_select_fork(ccx, urlOrAlias, None) } } impl Cheatcode for createSelectFork_1Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { urlOrAlias, blockNumber } = self; create_select_fork(ccx, urlOrAlias, Some(blockNumber.saturating_to())) } } impl Cheatcode for createSelectFork_2Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { urlOrAlias, txHash } = self; create_select_fork_at_transaction(ccx, urlOrAlias, txHash) } } impl Cheatcode for rollFork_0Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { blockNumber } = self; persist_caller(ccx); ccx.ecx.db.roll_fork( @@ -75,7 +75,7 @@ impl Cheatcode for rollFork_0Call { } impl Cheatcode for rollFork_1Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { txHash } = self; persist_caller(ccx); ccx.ecx.db.roll_fork_to_transaction( @@ -89,7 +89,7 @@ impl Cheatcode for rollFork_1Call { } impl Cheatcode for rollFork_2Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { forkId, blockNumber } = self; persist_caller(ccx); ccx.ecx.db.roll_fork( @@ -103,7 +103,7 @@ impl Cheatcode for rollFork_2Call { } impl Cheatcode for rollFork_3Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { forkId, txHash } = self; persist_caller(ccx); ccx.ecx.db.roll_fork_to_transaction( @@ -117,7 +117,7 @@ impl Cheatcode for rollFork_3Call { } impl Cheatcode for selectForkCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { forkId } = self; persist_caller(ccx); check_broadcast(ccx.state)?; @@ -128,11 +128,7 @@ impl Cheatcode for selectForkCall { } impl Cheatcode for transact_0Call { - fn apply_full( - &self, - ccx: &mut CheatsCtxt, - executor: &mut E, - ) -> Result { + fn apply_full(&self, ccx: &mut CheatsCtxt, executor: &mut dyn CheatcodesExecutor) -> Result { let Self { txHash } = *self; ccx.ecx.db.transact( None, @@ -146,25 +142,21 @@ impl Cheatcode for transact_0Call { } impl Cheatcode for transact_1Call { - fn apply_full( - &self, - ccx: &mut CheatsCtxt, - executor: &mut E, - ) -> Result { + fn apply_full(&self, ccx: &mut CheatsCtxt, executor: &mut dyn CheatcodesExecutor) -> Result { let Self { forkId, txHash } = *self; ccx.ecx.db.transact( Some(forkId), txHash, &mut ccx.ecx.env, &mut ccx.ecx.journaled_state, - &mut executor.get_inspector(ccx.state), + &mut *executor.get_inspector(ccx.state), )?; Ok(Default::default()) } } impl Cheatcode for allowCheatcodesCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { account } = self; ccx.ecx.db.allow_cheatcode_access(*account); Ok(Default::default()) @@ -172,7 +164,7 @@ impl Cheatcode for allowCheatcodesCall { } impl Cheatcode for makePersistent_0Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { account } = self; ccx.ecx.db.add_persistent_account(*account); Ok(Default::default()) @@ -180,7 +172,7 @@ impl Cheatcode for makePersistent_0Call { } impl Cheatcode for makePersistent_1Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { account0, account1 } = self; ccx.ecx.db.add_persistent_account(*account0); ccx.ecx.db.add_persistent_account(*account1); @@ -189,7 +181,7 @@ impl Cheatcode for makePersistent_1Call { } impl Cheatcode for makePersistent_2Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { account0, account1, account2 } = self; ccx.ecx.db.add_persistent_account(*account0); ccx.ecx.db.add_persistent_account(*account1); @@ -199,7 +191,7 @@ impl Cheatcode for makePersistent_2Call { } impl Cheatcode for makePersistent_3Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { accounts } = self; for account in accounts { ccx.ecx.db.add_persistent_account(*account); @@ -209,7 +201,7 @@ impl Cheatcode for makePersistent_3Call { } impl Cheatcode for revokePersistent_0Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { account } = self; ccx.ecx.db.remove_persistent_account(account); Ok(Default::default()) @@ -217,7 +209,7 @@ impl Cheatcode for revokePersistent_0Call { } impl Cheatcode for revokePersistent_1Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { accounts } = self; for account in accounts { ccx.ecx.db.remove_persistent_account(account); @@ -227,14 +219,14 @@ impl Cheatcode for revokePersistent_1Call { } impl Cheatcode for isPersistentCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { account } = self; Ok(ccx.ecx.db.is_persistent(account).abi_encode()) } } impl Cheatcode for rpc_0Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { method, params } = self; let url = ccx.ecx.db.active_fork_url().ok_or_else(|| fmt_err!("no active fork URL found"))?; @@ -251,7 +243,7 @@ impl Cheatcode for rpc_1Call { } impl Cheatcode for eth_getLogsCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { fromBlock, toBlock, target, topics } = self; let (Ok(from_block), Ok(to_block)) = (u64::try_from(fromBlock), u64::try_from(toBlock)) else { @@ -293,11 +285,7 @@ impl Cheatcode for eth_getLogsCall { } /// Creates and then also selects the new fork -fn create_select_fork( - ccx: &mut CheatsCtxt, - url_or_alias: &str, - block: Option, -) -> Result { +fn create_select_fork(ccx: &mut CheatsCtxt, url_or_alias: &str, block: Option) -> Result { check_broadcast(ccx.state)?; let fork = create_fork_request(ccx, url_or_alias, block)?; @@ -306,19 +294,15 @@ fn create_select_fork( } /// Creates a new fork -fn create_fork( - ccx: &mut CheatsCtxt, - url_or_alias: &str, - block: Option, -) -> Result { +fn create_fork(ccx: &mut CheatsCtxt, url_or_alias: &str, block: Option) -> Result { let fork = create_fork_request(ccx, url_or_alias, block)?; let id = ccx.ecx.db.create_fork(fork)?; Ok(id.abi_encode()) } /// Creates and then also selects the new fork at the given transaction -fn create_select_fork_at_transaction( - ccx: &mut CheatsCtxt, +fn create_select_fork_at_transaction( + ccx: &mut CheatsCtxt, url_or_alias: &str, transaction: &B256, ) -> Result { @@ -335,8 +319,8 @@ fn create_select_fork_at_transaction( } /// Creates a new fork at the given transaction -fn create_fork_at_transaction( - ccx: &mut CheatsCtxt, +fn create_fork_at_transaction( + ccx: &mut CheatsCtxt, url_or_alias: &str, transaction: &B256, ) -> Result { @@ -346,8 +330,8 @@ fn create_fork_at_transaction( } /// Creates the request object for a new fork request -fn create_fork_request( - ccx: &mut CheatsCtxt, +fn create_fork_request( + ccx: &mut CheatsCtxt, url_or_alias: &str, block: Option, ) -> Result { @@ -380,7 +364,7 @@ fn check_broadcast(state: &Cheatcodes) -> Result<()> { // Applies to create, select and roll forks actions. // https://github.com/foundry-rs/foundry/issues/8004 #[inline] -fn persist_caller(ccx: &mut CheatsCtxt) { +fn persist_caller(ccx: &mut CheatsCtxt) { ccx.ecx.db.add_persistent_account(ccx.caller); } diff --git a/crates/cheatcodes/src/evm/mock.rs b/crates/cheatcodes/src/evm/mock.rs index 01a02c5c21c9..ab858c612da6 100644 --- a/crates/cheatcodes/src/evm/mock.rs +++ b/crates/cheatcodes/src/evm/mock.rs @@ -1,6 +1,6 @@ -use crate::{Cheatcode, Cheatcodes, CheatsCtxt, DatabaseExt, Result, Vm::*}; +use crate::{inspector::InnerEcx, Cheatcode, Cheatcodes, CheatsCtxt, Result, Vm::*}; use alloy_primitives::{Address, Bytes, U256}; -use revm::{interpreter::InstructionResult, primitives::Bytecode, InnerEvmContext}; +use revm::{interpreter::InstructionResult, primitives::Bytecode}; use std::cmp::Ordering; /// Mocked call data. @@ -47,7 +47,7 @@ impl Cheatcode for clearMockedCallsCall { } impl Cheatcode for mockCall_0Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { callee, data, returnData } = self; let _ = make_acc_non_empty(callee, ccx.ecx)?; @@ -57,7 +57,7 @@ impl Cheatcode for mockCall_0Call { } impl Cheatcode for mockCall_1Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { callee, msgValue, data, returnData } = self; ccx.ecx.load_account(*callee)?; mock_call(ccx.state, callee, data, Some(msgValue), returnData, InstructionResult::Return); @@ -66,7 +66,7 @@ impl Cheatcode for mockCall_1Call { } impl Cheatcode for mockCallRevert_0Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { callee, data, revertData } = self; let _ = make_acc_non_empty(callee, ccx.ecx)?; @@ -76,7 +76,7 @@ impl Cheatcode for mockCallRevert_0Call { } impl Cheatcode for mockCallRevert_1Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { callee, msgValue, data, revertData } = self; let _ = make_acc_non_empty(callee, ccx.ecx)?; @@ -111,7 +111,7 @@ fn mock_call( // Etches a single byte onto the account if it is empty to circumvent the `extcodesize` // check Solidity might perform. -fn make_acc_non_empty(callee: &Address, ecx: &mut InnerEvmContext) -> Result { +fn make_acc_non_empty(callee: &Address, ecx: InnerEcx) -> Result { let acc = ecx.load_account(*callee)?; let empty_bytecode = acc.info.code.as_ref().map_or(true, Bytecode::is_empty); diff --git a/crates/cheatcodes/src/evm/prank.rs b/crates/cheatcodes/src/evm/prank.rs index fe5418b3157f..a310e28e515b 100644 --- a/crates/cheatcodes/src/evm/prank.rs +++ b/crates/cheatcodes/src/evm/prank.rs @@ -1,4 +1,4 @@ -use crate::{Cheatcode, Cheatcodes, CheatsCtxt, DatabaseExt, Result, Vm::*}; +use crate::{Cheatcode, Cheatcodes, CheatsCtxt, Result, Vm::*}; use alloy_primitives::Address; /// Prank information. @@ -45,28 +45,28 @@ impl Prank { } impl Cheatcode for prank_0Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { msgSender } = self; prank(ccx, msgSender, None, true) } } impl Cheatcode for startPrank_0Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { msgSender } = self; prank(ccx, msgSender, None, false) } } impl Cheatcode for prank_1Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { msgSender, txOrigin } = self; prank(ccx, msgSender, Some(txOrigin), true) } } impl Cheatcode for startPrank_1Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { msgSender, txOrigin } = self; prank(ccx, msgSender, Some(txOrigin), false) } @@ -80,8 +80,8 @@ impl Cheatcode for stopPrankCall { } } -fn prank( - ccx: &mut CheatsCtxt, +fn prank( + ccx: &mut CheatsCtxt, new_caller: &Address, new_origin: Option<&Address>, single_call: bool, diff --git a/crates/cheatcodes/src/fs.rs b/crates/cheatcodes/src/fs.rs index 4185b2d79997..f36c8d6fe8f8 100644 --- a/crates/cheatcodes/src/fs.rs +++ b/crates/cheatcodes/src/fs.rs @@ -9,7 +9,6 @@ use alloy_sol_types::SolValue; use dialoguer::{Input, Password}; use foundry_common::fs; use foundry_config::fs_permissions::FsAccessKind; -use foundry_evm_core::backend::DatabaseExt; use revm::interpreter::CreateInputs; use semver::Version; use std::{ @@ -293,11 +292,7 @@ impl Cheatcode for getDeployedCodeCall { } impl Cheatcode for deployCode_0Call { - fn apply_full( - &self, - ccx: &mut CheatsCtxt, - executor: &mut E, - ) -> Result { + fn apply_full(&self, ccx: &mut CheatsCtxt, executor: &mut dyn CheatcodesExecutor) -> Result { let Self { artifactPath: path } = self; let bytecode = get_artifact_code(ccx.state, path, false)?; let address = executor @@ -319,11 +314,7 @@ impl Cheatcode for deployCode_0Call { } impl Cheatcode for deployCode_1Call { - fn apply_full( - &self, - ccx: &mut CheatsCtxt, - executor: &mut E, - ) -> Result { + fn apply_full(&self, ccx: &mut CheatsCtxt, executor: &mut dyn CheatcodesExecutor) -> Result { let Self { artifactPath: path, constructorArgs } = self; let mut bytecode = get_artifact_code(ccx.state, path, false)?.to_vec(); bytecode.extend_from_slice(constructorArgs); diff --git a/crates/cheatcodes/src/inspector.rs b/crates/cheatcodes/src/inspector.rs index 3ef5859ec36b..fe8834d5f5a8 100644 --- a/crates/cheatcodes/src/inspector.rs +++ b/crates/cheatcodes/src/inspector.rs @@ -17,8 +17,8 @@ use crate::{ }, }, utils::IgnoredTraces, - CheatsConfig, CheatsCtxt, DynCheatcode, Error, Result, Vm, - Vm::AccountAccess, + CheatsConfig, CheatsCtxt, DynCheatcode, Error, Result, + Vm::{self, AccountAccess}, }; use alloy_primitives::{ hex, @@ -31,7 +31,7 @@ use foundry_common::{evm::Breakpoints, TransactionMaybeSigned, SELECTOR_LEN}; use foundry_config::Config; use foundry_evm_core::{ abi::Vm::stopExpectSafeMemoryCall, - backend::{DatabaseExt, RevertDiagnostic}, + backend::{DatabaseError, DatabaseExt, RevertDiagnostic}, constants::{CHEATCODE_ADDRESS, HARDHAT_CONSOLE_ADDRESS, MAGIC_ASSUME}, utils::new_evm_with_existing_context, InspectorExt, @@ -62,6 +62,9 @@ use std::{ mod utils; +pub type Ecx<'a, 'b, 'c> = &'a mut EvmContext<&'b mut (dyn DatabaseExt + 'c)>; +pub type InnerEcx<'a, 'b, 'c> = &'a mut InnerEvmContext<&'b mut (dyn DatabaseExt + 'c)>; + /// Helper trait for obtaining complete [revm::Inspector] instance from mutable reference to /// [Cheatcodes]. /// @@ -70,71 +73,30 @@ mod utils; pub trait CheatcodesExecutor { /// Core trait method accepting mutable reference to [Cheatcodes] and returning /// [revm::Inspector]. - fn get_inspector<'a, DB: DatabaseExt>( - &'a mut self, - cheats: &'a mut Cheatcodes, - ) -> impl InspectorExt + 'a; - - /// Constructs [revm::Evm] and runs a given closure with it. - fn with_evm( - &mut self, - ccx: &mut CheatsCtxt, - f: F, - ) -> Result> - where - F: for<'a, 'b> FnOnce( - &mut revm::Evm< - '_, - &'b mut dyn InspectorExt<&'a mut dyn DatabaseExt>, - &'a mut dyn DatabaseExt, - >, - ) -> Result>, - { - let mut inspector = self.get_inspector(ccx.state); - let error = std::mem::replace(&mut ccx.ecx.error, Ok(())); - let l1_block_info = std::mem::take(&mut ccx.ecx.l1_block_info); - - let inner = revm::InnerEvmContext { - env: ccx.ecx.env.clone(), - journaled_state: std::mem::replace( - &mut ccx.ecx.journaled_state, - revm::JournaledState::new(Default::default(), Default::default()), - ), - db: &mut ccx.ecx.db as &mut dyn DatabaseExt, - error, - l1_block_info, - }; - - let mut evm = new_evm_with_existing_context(inner, &mut inspector as _); - - let res = f(&mut evm)?; - - ccx.ecx.journaled_state = evm.context.evm.inner.journaled_state; - ccx.ecx.env = evm.context.evm.inner.env; - ccx.ecx.l1_block_info = evm.context.evm.inner.l1_block_info; - ccx.ecx.error = evm.context.evm.inner.error; - - Ok(res) - } + fn get_inspector<'a>(&'a mut self, cheats: &'a mut Cheatcodes) -> Box; /// Obtains [revm::Evm] instance and executes the given CREATE frame. - fn exec_create( + fn exec_create( &mut self, inputs: CreateInputs, - ccx: &mut CheatsCtxt, - ) -> Result> { - self.with_evm(ccx, |evm| { + ccx: &mut CheatsCtxt, + ) -> Result> { + with_evm(self, ccx, |evm| { evm.context.evm.inner.journaled_state.depth += 1; // Handle EOF bytecode - let first_frame_or_result = if evm.handler.cfg.spec_id.is_enabled_in(SpecId::PRAGUE_EOF) - && inputs.scheme == CreateScheme::Create && inputs.init_code.starts_with(&EOF_MAGIC_BYTES) + let first_frame_or_result = if evm.handler.cfg.spec_id.is_enabled_in(SpecId::PRAGUE_EOF) && + inputs.scheme == CreateScheme::Create && + inputs.init_code.starts_with(&EOF_MAGIC_BYTES) { evm.handler.execution().eofcreate( &mut evm.context, - Box::new(EOFCreateInputs::new(inputs.caller, inputs.value, inputs.gas_limit, EOFCreateKind::Tx { - initdata: inputs.init_code, - })), + Box::new(EOFCreateInputs::new( + inputs.caller, + inputs.value, + inputs.gas_limit, + EOFCreateKind::Tx { initdata: inputs.init_code }, + )), )? } else { evm.handler.execution().create(&mut evm.context, Box::new(inputs))? @@ -158,8 +120,8 @@ pub trait CheatcodesExecutor { }) } - fn console_log(&mut self, ccx: &mut CheatsCtxt, message: String) { - self.get_inspector::(ccx.state).console_log(message); + fn console_log(&mut self, ccx: &mut CheatsCtxt, message: String) { + self.get_inspector(ccx.state).console_log(message); } /// Returns a mutable reference to the tracing inspector if it is available. @@ -168,17 +130,53 @@ pub trait CheatcodesExecutor { } } +/// Constructs [revm::Evm] and runs a given closure with it. +fn with_evm( + executor: &mut E, + ccx: &mut CheatsCtxt, + f: F, +) -> Result> +where + E: CheatcodesExecutor + ?Sized, + F: for<'a, 'b> FnOnce( + &mut revm::Evm<'_, &'b mut dyn InspectorExt, &'a mut dyn DatabaseExt>, + ) -> Result>, +{ + let mut inspector = executor.get_inspector(ccx.state); + let error = std::mem::replace(&mut ccx.ecx.error, Ok(())); + let l1_block_info = std::mem::take(&mut ccx.ecx.l1_block_info); + + let inner = revm::InnerEvmContext { + env: ccx.ecx.env.clone(), + journaled_state: std::mem::replace( + &mut ccx.ecx.journaled_state, + revm::JournaledState::new(Default::default(), Default::default()), + ), + db: &mut ccx.ecx.db as &mut dyn DatabaseExt, + error, + l1_block_info, + }; + + let mut evm = new_evm_with_existing_context(inner, &mut *inspector); + + let res = f(&mut evm)?; + + ccx.ecx.journaled_state = evm.context.evm.inner.journaled_state; + ccx.ecx.env = evm.context.evm.inner.env; + ccx.ecx.l1_block_info = evm.context.evm.inner.l1_block_info; + ccx.ecx.error = evm.context.evm.inner.error; + + Ok(res) +} + /// Basic implementation of [CheatcodesExecutor] that simply returns the [Cheatcodes] instance as an /// inspector. #[derive(Debug, Default, Clone, Copy)] struct TransparentCheatcodesExecutor; impl CheatcodesExecutor for TransparentCheatcodesExecutor { - fn get_inspector<'a, DB: DatabaseExt>( - &'a mut self, - cheats: &'a mut Cheatcodes, - ) -> impl InspectorExt + 'a { - cheats + fn get_inspector<'a>(&'a mut self, cheats: &'a mut Cheatcodes) -> Box { + Box::new(cheats) } } @@ -306,13 +304,7 @@ impl ArbitraryStorage { /// Saves arbitrary storage value for a given address: /// - store value in changed values cache. /// - update account's storage with given value. - pub fn save( - &mut self, - ecx: &mut InnerEvmContext, - address: Address, - slot: U256, - data: U256, - ) { + pub fn save(&mut self, ecx: InnerEcx, address: Address, slot: U256, data: U256) { self.values.get_mut(&address).expect("missing arbitrary address entry").insert(slot, data); if let Ok(mut account) = ecx.load_account(address) { account.storage.insert(slot, EvmStorageSlot::new(data)); @@ -324,13 +316,7 @@ impl ArbitraryStorage { /// existing value. /// - if no value was yet generated for given slot, then save new value in cache and update both /// source and target storages. - pub fn copy( - &mut self, - ecx: &mut InnerEvmContext, - target: Address, - slot: U256, - new_value: U256, - ) -> U256 { + pub fn copy(&mut self, ecx: InnerEcx, target: Address, slot: U256, new_value: U256) -> U256 { let source = self.copies.get(&target).expect("missing arbitrary copy target entry"); let storage_cache = self.values.get_mut(source).expect("missing arbitrary source storage"); let value = match storage_cache.get(&slot) { @@ -535,11 +521,11 @@ impl Cheatcodes { } /// Decodes the input data and applies the cheatcode. - fn apply_cheatcode( + fn apply_cheatcode( &mut self, - ecx: &mut EvmContext, + ecx: Ecx, call: &CallInputs, - executor: &mut E, + executor: &mut dyn CheatcodesExecutor, ) -> Result { // decode the cheatcode call let decoded = Vm::VmCalls::abi_decode(&call.input, false).map_err(|e| { @@ -578,12 +564,7 @@ impl Cheatcodes { /// /// There may be cheatcodes in the constructor of the new contract, in order to allow them /// automatically we need to determine the new address. - fn allow_cheatcodes_on_create( - &self, - ecx: &mut InnerEvmContext, - caller: Address, - created_address: Address, - ) { + fn allow_cheatcodes_on_create(&self, ecx: InnerEcx, caller: Address, created_address: Address) { if ecx.journaled_state.depth <= 1 || ecx.db.has_cheatcode_access(&caller) { ecx.db.allow_cheatcode_access(created_address); } @@ -593,7 +574,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, ecx: &mut EvmContext) { + pub fn on_revert(&mut self, ecx: Ecx) { trace!(deals=?self.eth_deals.len(), "rolling back deals"); // Delay revert clean up until expected revert is handled, if set. @@ -617,14 +598,9 @@ impl Cheatcodes { } // common create functionality for both legacy and EOF. - fn create_common( - &mut self, - ecx: &mut EvmContext, - mut input: Input, - ) -> Option + fn create_common(&mut self, ecx: Ecx, mut input: Input) -> Option where - DB: DatabaseExt, - Input: CommonCreateInput, + Input: CommonCreateInput, { let ecx = &mut ecx.inner; let gas = Gas::new(input.gas_limit()); @@ -717,14 +693,8 @@ impl Cheatcodes { } // common create_end functionality for both legacy and EOF. - fn create_end_common( - &mut self, - ecx: &mut EvmContext, - mut outcome: CreateOutcome, - ) -> CreateOutcome - where - DB: DatabaseExt, - { + fn create_end_common(&mut self, ecx: Ecx, mut outcome: CreateOutcome) -> CreateOutcome +where { let ecx = &mut ecx.inner; // Clean up pranks @@ -831,9 +801,9 @@ impl Cheatcodes { outcome } - pub fn call_with_executor( + pub fn call_with_executor( &mut self, - ecx: &mut EvmContext, + ecx: Ecx, call: &mut CallInputs, executor: &mut impl CheatcodesExecutor, ) -> Option { @@ -1127,9 +1097,9 @@ impl Cheatcodes { } } -impl Inspector for Cheatcodes { +impl Inspector<&mut dyn DatabaseExt> for Cheatcodes { #[inline] - fn initialize_interp(&mut self, interpreter: &mut Interpreter, ecx: &mut EvmContext) { + fn initialize_interp(&mut self, interpreter: &mut Interpreter, ecx: Ecx) { // 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() { @@ -1146,7 +1116,7 @@ impl Inspector for Cheatcodes { } #[inline] - fn step(&mut self, interpreter: &mut Interpreter, ecx: &mut EvmContext) { + fn step(&mut self, interpreter: &mut Interpreter, ecx: Ecx) { self.pc = interpreter.program_counter(); // `pauseGasMetering`: pause / resume interpreter gas. @@ -1186,7 +1156,7 @@ impl Inspector for Cheatcodes { } #[inline] - fn step_end(&mut self, interpreter: &mut Interpreter, ecx: &mut EvmContext) { + fn step_end(&mut self, interpreter: &mut Interpreter, ecx: Ecx) { if self.gas_metering.paused { self.meter_gas_end(interpreter); } @@ -1201,7 +1171,7 @@ impl Inspector for Cheatcodes { } } - fn log(&mut self, interpreter: &mut Interpreter, _ecx: &mut EvmContext, log: &Log) { + fn log(&mut self, interpreter: &mut Interpreter, _ecx: Ecx, log: &Log) { if !self.expected_emits.is_empty() { expect::handle_expect_emit(self, log, interpreter); } @@ -1216,16 +1186,11 @@ impl Inspector for Cheatcodes { } } - fn call(&mut self, ecx: &mut EvmContext, inputs: &mut CallInputs) -> Option { + fn call(&mut self, ecx: Ecx, inputs: &mut CallInputs) -> Option { Self::call_with_executor(self, ecx, inputs, &mut TransparentCheatcodesExecutor) } - fn call_end( - &mut self, - ecx: &mut EvmContext, - call: &CallInputs, - mut outcome: CallOutcome, - ) -> CallOutcome { + fn call_end(&mut self, ecx: Ecx, call: &CallInputs, mut outcome: CallOutcome) -> CallOutcome { let ecx = &mut ecx.inner; let cheatcode_call = call.target_address == CHEATCODE_ADDRESS || call.target_address == HARDHAT_CONSOLE_ADDRESS; @@ -1521,34 +1486,26 @@ impl Inspector for Cheatcodes { outcome } - fn create( - &mut self, - ecx: &mut EvmContext, - call: &mut CreateInputs, - ) -> Option { + fn create(&mut self, ecx: Ecx, call: &mut CreateInputs) -> Option { self.create_common(ecx, call) } fn create_end( &mut self, - ecx: &mut EvmContext, + ecx: Ecx, _call: &CreateInputs, outcome: CreateOutcome, ) -> CreateOutcome { self.create_end_common(ecx, outcome) } - fn eofcreate( - &mut self, - ecx: &mut EvmContext, - call: &mut EOFCreateInputs, - ) -> Option { + fn eofcreate(&mut self, ecx: Ecx, call: &mut EOFCreateInputs) -> Option { self.create_common(ecx, call) } fn eofcreate_end( &mut self, - ecx: &mut EvmContext, + ecx: Ecx, _call: &EOFCreateInputs, outcome: CreateOutcome, ) -> CreateOutcome { @@ -1556,12 +1513,8 @@ impl Inspector for Cheatcodes { } } -impl InspectorExt for Cheatcodes { - fn should_use_create2_factory( - &mut self, - ecx: &mut EvmContext, - inputs: &mut CreateInputs, - ) -> bool { +impl InspectorExt for Cheatcodes { + fn should_use_create2_factory(&mut self, ecx: Ecx, inputs: &mut CreateInputs) -> bool { if let CreateScheme::Create2 { .. } = inputs.scheme { let target_depth = if let Some(prank) = &self.prank { prank.depth @@ -1592,11 +1545,7 @@ impl Cheatcodes { } #[cold] - fn meter_gas_record( - &mut self, - interpreter: &mut Interpreter, - ecx: &mut EvmContext, - ) { + fn meter_gas_record(&mut self, interpreter: &mut Interpreter, ecx: Ecx) { if matches!(interpreter.instruction_result, InstructionResult::Continue) { self.gas_metering.gas_records.iter_mut().for_each(|record| { if ecx.journaled_state.depth() == record.depth { @@ -1652,11 +1601,7 @@ impl Cheatcodes { /// cache) from mapped source address to the target address. /// - generates arbitrary value and saves it in target address storage. #[cold] - fn arbitrary_storage_end( - &mut self, - interpreter: &mut Interpreter, - ecx: &mut EvmContext, - ) { + fn arbitrary_storage_end(&mut self, interpreter: &mut Interpreter, ecx: Ecx) { let (key, target_address) = if interpreter.current_opcode() == op::SLOAD { (try_or_return!(interpreter.stack().peek(0)), interpreter.contract().target_address) } else { @@ -1706,11 +1651,7 @@ impl Cheatcodes { } #[cold] - fn record_state_diffs( - &mut self, - interpreter: &mut Interpreter, - ecx: &mut EvmContext, - ) { + fn record_state_diffs(&mut self, interpreter: &mut Interpreter, ecx: Ecx) { let Some(account_accesses) = &mut self.recorded_account_diffs_stack else { return }; match interpreter.current_opcode() { op::SELFDESTRUCT => { @@ -2057,10 +1998,7 @@ fn disallowed_mem_write( // 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( - ecx: &InnerEvmContext, - call_gas_limit: u64, -) -> bool { +fn check_if_fixed_gas_limit(ecx: InnerEcx, 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. @@ -2130,44 +2068,25 @@ fn append_storage_access( } /// Dispatches the cheatcode call to the appropriate function. -fn apply_dispatch( +fn apply_dispatch( calls: &Vm::VmCalls, - ccx: &mut CheatsCtxt, - executor: &mut E, + ccx: &mut CheatsCtxt, + executor: &mut dyn CheatcodesExecutor, ) -> Result { - // TODO: Replace with `::apply_full` once it's object-safe. - macro_rules! dispatch { - ($($variant:ident),*) => { - match calls { - $(Vm::VmCalls::$variant(cheat) => crate::Cheatcode::apply_full(cheat, ccx, executor),)* - } - }; - } - let cheat = calls_as_dyn_cheatcode(calls); + + let _guard = debug_span!(target: "cheatcodes", "apply", id = %cheat.id()).entered(); + trace!(target: "cheatcodes", cheat = ?cheat.as_debug(), "applying"); + if let spec::Status::Deprecated(replacement) = *cheat.status() { ccx.state.deprecated.insert(cheat.signature(), replacement); } - let _guard = trace_span_and_call(cheat); - let mut result = vm_calls!(dispatch); - fill_and_trace_return(cheat, &mut result); - result -} -/// Helper function to check if frame execution will exit. -fn will_exit(ir: InstructionResult) -> bool { - !matches!(ir, InstructionResult::Continue | InstructionResult::CallOrCreate) -} + // Apply the cheatcode. + let mut result = cheat.dyn_apply(ccx, executor); -fn trace_span_and_call(cheat: &dyn DynCheatcode) -> tracing::span::EnteredSpan { - let span = debug_span!(target: "cheatcodes", "apply", id = %cheat.id()); - let entered = span.entered(); - trace!(target: "cheatcodes", cheat = ?cheat.as_debug(), "applying"); - entered -} - -fn fill_and_trace_return(cheat: &dyn DynCheatcode, result: &mut Result) { - if let Err(e) = result { + // Format the error message to include the cheatcode name. + if let Err(e) = &mut result { if e.is_str() { let name = cheat.name(); // Skip showing the cheatcode name for: @@ -2178,13 +2097,16 @@ fn fill_and_trace_return(cheat: &dyn DynCheatcode, result: &mut Result) { } } } + trace!( target: "cheatcodes", - return = %match result { + return = %match &result { Ok(b) => hex::encode(b), Err(e) => e.to_string(), } ); + + result } fn calls_as_dyn_cheatcode(calls: &Vm::VmCalls) -> &dyn DynCheatcode { @@ -2197,3 +2119,8 @@ fn calls_as_dyn_cheatcode(calls: &Vm::VmCalls) -> &dyn DynCheatcode { } vm_calls!(as_dyn) } + +/// Helper function to check if frame execution will exit. +fn will_exit(ir: InstructionResult) -> bool { + !matches!(ir, InstructionResult::Continue | InstructionResult::CallOrCreate) +} diff --git a/crates/cheatcodes/src/inspector/utils.rs b/crates/cheatcodes/src/inspector/utils.rs index dfccd4b55552..a0d7820aa3e2 100644 --- a/crates/cheatcodes/src/inspector/utils.rs +++ b/crates/cheatcodes/src/inspector/utils.rs @@ -1,13 +1,10 @@ +use super::InnerEcx; use crate::inspector::Cheatcodes; use alloy_primitives::{Address, Bytes, U256}; -use foundry_evm_core::backend::DatabaseExt; -use revm::{ - interpreter::{CreateInputs, CreateScheme, EOFCreateInputs, EOFCreateKind}, - InnerEvmContext, -}; +use revm::interpreter::{CreateInputs, CreateScheme, EOFCreateInputs, EOFCreateKind}; /// Common behaviour of legacy and EOF create inputs. -pub(crate) trait CommonCreateInput { +pub(crate) trait CommonCreateInput { fn caller(&self) -> Address; fn gas_limit(&self) -> u64; fn value(&self) -> U256; @@ -15,15 +12,11 @@ pub(crate) trait CommonCreateInput { fn scheme(&self) -> Option; fn set_caller(&mut self, caller: Address); fn log_debug(&self, cheatcode: &mut Cheatcodes, scheme: &CreateScheme); - fn allow_cheatcodes( - &self, - cheatcodes: &mut Cheatcodes, - ecx: &mut InnerEvmContext, - ) -> Address; + fn allow_cheatcodes(&self, cheatcodes: &mut Cheatcodes, ecx: InnerEcx) -> Address; fn computed_created_address(&self) -> Option
; } -impl CommonCreateInput for &mut CreateInputs { +impl CommonCreateInput for &mut CreateInputs { fn caller(&self) -> Address { self.caller } @@ -49,11 +42,7 @@ impl CommonCreateInput for &mut CreateInputs { }; debug!(target: "cheatcodes", tx=?cheatcode.broadcastable_transactions.back().unwrap(), "broadcastable {kind}"); } - fn allow_cheatcodes( - &self, - cheatcodes: &mut Cheatcodes, - ecx: &mut InnerEvmContext, - ) -> Address { + fn allow_cheatcodes(&self, cheatcodes: &mut Cheatcodes, ecx: InnerEcx) -> Address { let old_nonce = ecx .journaled_state .state @@ -69,7 +58,7 @@ impl CommonCreateInput for &mut CreateInputs { } } -impl CommonCreateInput for &mut EOFCreateInputs { +impl CommonCreateInput for &mut EOFCreateInputs { fn caller(&self) -> Address { self.caller } @@ -94,13 +83,9 @@ impl CommonCreateInput for &mut EOFCreateInputs { fn log_debug(&self, cheatcode: &mut Cheatcodes, _scheme: &CreateScheme) { debug!(target: "cheatcodes", tx=?cheatcode.broadcastable_transactions.back().unwrap(), "broadcastable eofcreate"); } - fn allow_cheatcodes( - &self, - cheatcodes: &mut Cheatcodes, - ecx: &mut InnerEvmContext, - ) -> Address { + fn allow_cheatcodes(&self, cheatcodes: &mut Cheatcodes, ecx: InnerEcx) -> Address { let created_address = - <&mut EOFCreateInputs as CommonCreateInput>::computed_created_address(self) + <&mut EOFCreateInputs as CommonCreateInput>::computed_created_address(self) .unwrap_or_default(); cheatcodes.allow_cheatcodes_on_create(ecx, self.caller, created_address); created_address diff --git a/crates/cheatcodes/src/lib.rs b/crates/cheatcodes/src/lib.rs index 50bd54701919..a257289916cd 100644 --- a/crates/cheatcodes/src/lib.rs +++ b/crates/cheatcodes/src/lib.rs @@ -70,7 +70,7 @@ pub(crate) trait Cheatcode: CheatcodeDef + DynCheatcode { /// /// Implement this function if you need access to the EVM data. #[inline(always)] - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { self.apply(ccx.state) } @@ -78,58 +78,69 @@ pub(crate) trait Cheatcode: CheatcodeDef + DynCheatcode { /// /// Implement this function if you need access to the executor. #[inline(always)] - fn apply_full( - &self, - ccx: &mut CheatsCtxt, - executor: &mut E, - ) -> Result { + fn apply_full(&self, ccx: &mut CheatsCtxt, executor: &mut dyn CheatcodesExecutor) -> Result { let _ = executor; self.apply_stateful(ccx) } } pub(crate) trait DynCheatcode { - fn name(&self) -> &'static str; - fn id(&self) -> &'static str; - fn signature(&self) -> &'static str; - fn status(&self) -> &Status<'static>; - fn as_debug(&self) -> &dyn std::fmt::Debug; -} + fn cheatcode(&self) -> &'static spec::Cheatcode<'static>; -impl DynCheatcode for T { fn name(&self) -> &'static str { - T::CHEATCODE.func.signature.split('(').next().unwrap() + self.cheatcode().func.signature.split('(').next().unwrap() } + fn id(&self) -> &'static str { - T::CHEATCODE.func.id + self.cheatcode().func.id } + fn signature(&self) -> &'static str { - T::CHEATCODE.func.signature + self.cheatcode().func.signature } + fn status(&self) -> &Status<'static> { - &T::CHEATCODE.status + &self.cheatcode().status } + + fn as_debug(&self) -> &dyn std::fmt::Debug; + + fn dyn_apply(&self, ccx: &mut CheatsCtxt, executor: &mut dyn CheatcodesExecutor) -> Result; +} + +impl DynCheatcode for T { + #[inline] + fn cheatcode(&self) -> &'static spec::Cheatcode<'static> { + Self::CHEATCODE + } + + #[inline] fn as_debug(&self) -> &dyn std::fmt::Debug { self } + + #[inline] + fn dyn_apply(&self, ccx: &mut CheatsCtxt, executor: &mut dyn CheatcodesExecutor) -> Result { + self.apply_full(ccx, executor) + } } /// The cheatcode context, used in `Cheatcode`. -pub struct CheatsCtxt<'cheats, 'evm, DB: DatabaseExt> { +pub struct CheatsCtxt<'cheats, 'evm, 'db, 'db2> { /// The cheatcodes inspector state. pub(crate) state: &'cheats mut Cheatcodes, /// The EVM data. - pub(crate) ecx: &'evm mut InnerEvmContext, + pub(crate) ecx: &'evm mut InnerEvmContext<&'db mut (dyn DatabaseExt + 'db2)>, /// The precompiles context. - pub(crate) precompiles: &'evm mut ContextPrecompiles, + pub(crate) precompiles: &'evm mut ContextPrecompiles<&'db mut (dyn DatabaseExt + 'db2)>, /// The original `msg.sender`. pub(crate) caller: Address, /// Gas limit of the current cheatcode call. pub(crate) gas_limit: u64, } -impl<'cheats, 'evm, DB: DatabaseExt> std::ops::Deref for CheatsCtxt<'cheats, 'evm, DB> { - type Target = InnerEvmContext; +impl<'db, 'db2> std::ops::Deref for CheatsCtxt<'_, '_, 'db, 'db2> { + type Target = InnerEvmContext<&'db mut (dyn DatabaseExt + 'db2)>; #[inline(always)] fn deref(&self) -> &Self::Target { @@ -137,14 +148,14 @@ impl<'cheats, 'evm, DB: DatabaseExt> std::ops::Deref for CheatsCtxt<'cheats, 'ev } } -impl<'cheats, 'evm, DB: DatabaseExt> std::ops::DerefMut for CheatsCtxt<'cheats, 'evm, DB> { +impl std::ops::DerefMut for CheatsCtxt<'_, '_, '_, '_> { #[inline(always)] fn deref_mut(&mut self) -> &mut Self::Target { &mut *self.ecx } } -impl<'cheats, 'evm, DB: DatabaseExt> CheatsCtxt<'cheats, 'evm, DB> { +impl CheatsCtxt<'_, '_, '_, '_> { #[inline] pub(crate) fn is_precompile(&self, address: &Address) -> bool { self.precompiles.contains(address) diff --git a/crates/cheatcodes/src/script.rs b/crates/cheatcodes/src/script.rs index 82eef2354994..93d5aaaf8d34 100644 --- a/crates/cheatcodes/src/script.rs +++ b/crates/cheatcodes/src/script.rs @@ -1,6 +1,6 @@ //! Implementations of [`Scripting`](spec::Group::Scripting) cheatcodes. -use crate::{Cheatcode, CheatsCtxt, DatabaseExt, Result, Vm::*}; +use crate::{Cheatcode, CheatsCtxt, Result, Vm::*}; use alloy_primitives::{Address, B256, U256}; use alloy_signer_local::PrivateKeySigner; use foundry_wallets::{multi_wallet::MultiWallet, WalletSigner}; @@ -8,49 +8,49 @@ use parking_lot::Mutex; use std::sync::Arc; impl Cheatcode for broadcast_0Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self {} = self; broadcast(ccx, None, true) } } impl Cheatcode for broadcast_1Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { signer } = self; broadcast(ccx, Some(signer), true) } } impl Cheatcode for broadcast_2Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { privateKey } = self; broadcast_key(ccx, privateKey, true) } } impl Cheatcode for startBroadcast_0Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self {} = self; broadcast(ccx, None, false) } } impl Cheatcode for startBroadcast_1Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { signer } = self; broadcast(ccx, Some(signer), false) } } impl Cheatcode for startBroadcast_2Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { privateKey } = self; broadcast_key(ccx, privateKey, false) } } impl Cheatcode for stopBroadcastCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self {} = self; let Some(broadcast) = ccx.state.broadcast.take() else { bail!("no broadcast in progress to stop"); @@ -123,11 +123,7 @@ impl ScriptWallets { } /// Sets up broadcasting from a script using `new_origin` as the sender. -fn broadcast( - ccx: &mut CheatsCtxt, - new_origin: Option<&Address>, - single_call: bool, -) -> Result { +fn broadcast(ccx: &mut CheatsCtxt, new_origin: Option<&Address>, single_call: bool) -> Result { ensure!( ccx.state.prank.is_none(), "you have an active prank; broadcasting and pranks are not compatible" @@ -166,11 +162,7 @@ fn broadcast( /// Sets up broadcasting from a script with the sender derived from `private_key`. /// Adds this private key to `state`'s `script_wallets` vector to later be used for signing /// if broadcast is successful. -fn broadcast_key( - ccx: &mut CheatsCtxt, - private_key: &U256, - single_call: bool, -) -> Result { +fn broadcast_key(ccx: &mut CheatsCtxt, private_key: &U256, single_call: bool) -> Result { let wallet = super::crypto::parse_wallet(private_key)?; let new_origin = wallet.address(); diff --git a/crates/cheatcodes/src/test.rs b/crates/cheatcodes/src/test.rs index cc91dba45b23..bd723c9312ea 100644 --- a/crates/cheatcodes/src/test.rs +++ b/crates/cheatcodes/src/test.rs @@ -1,26 +1,25 @@ //! Implementations of [`Testing`](spec::Group::Testing) cheatcodes. -use chrono::DateTime; -use std::env; - -use crate::{Cheatcode, Cheatcodes, CheatsCtxt, DatabaseExt, Result, Vm::*}; +use crate::{Cheatcode, Cheatcodes, CheatsCtxt, Result, Vm::*}; use alloy_primitives::Address; use alloy_sol_types::SolValue; +use chrono::DateTime; use foundry_evm_core::constants::MAGIC_SKIP; +use std::env; pub(crate) mod assert; pub(crate) mod assume; pub(crate) mod expect; impl Cheatcode for breakpoint_0Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { char } = self; breakpoint(ccx.state, &ccx.caller, char, true) } } impl Cheatcode for breakpoint_1Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { char, value } = self; breakpoint(ccx.state, &ccx.caller, char, *value) } @@ -71,14 +70,14 @@ impl Cheatcode for sleepCall { } impl Cheatcode for skip_0Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { skipTest } = *self; skip_1Call { skipTest, reason: String::new() }.apply_stateful(ccx) } } impl Cheatcode for skip_1Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { skipTest, reason } = self; if *skipTest { // Skip should not work if called deeper than at test level. diff --git a/crates/cheatcodes/src/test/assert.rs b/crates/cheatcodes/src/test/assert.rs index 4ab97c031e5a..5161716fae56 100644 --- a/crates/cheatcodes/src/test/assert.rs +++ b/crates/cheatcodes/src/test/assert.rs @@ -2,7 +2,7 @@ use crate::{CheatcodesExecutor, CheatsCtxt, Result, Vm::*}; use alloy_primitives::{hex, I256, U256}; use foundry_evm_core::{ abi::{format_units_int, format_units_uint}, - backend::{DatabaseExt, GLOBAL_FAIL_SLOT}, + backend::GLOBAL_FAIL_SLOT, constants::CHEATCODE_ADDRESS, }; use itertools::Itertools; @@ -169,10 +169,10 @@ impl EqRelAssertionError { type ComparisonResult<'a, T> = Result, ComparisonAssertionError<'a, T>>; -fn handle_assertion_result( +fn handle_assertion_result( result: core::result::Result, ERR>, - ccx: &mut CheatsCtxt, - executor: &mut E, + ccx: &mut CheatsCtxt, + executor: &mut dyn CheatcodesExecutor, error_formatter: impl Fn(&ERR) -> String, error_msg: Option<&str>, format_error: bool, @@ -224,10 +224,10 @@ macro_rules! impl_assertions { }; (@impl $no_error:ident, $with_error:ident, ($($arg:ident),*), $body:expr, $error_formatter:expr, $format_error:literal) => { impl crate::Cheatcode for $no_error { - fn apply_full( + fn apply_full( &self, - ccx: &mut CheatsCtxt, - executor: &mut E, + ccx: &mut CheatsCtxt, + executor: &mut dyn CheatcodesExecutor, ) -> Result { let Self { $($arg),* } = self; handle_assertion_result($body, ccx, executor, $error_formatter, None, $format_error) @@ -235,10 +235,10 @@ macro_rules! impl_assertions { } impl crate::Cheatcode for $with_error { - fn apply_full( + fn apply_full( &self, - ccx: &mut CheatsCtxt, - executor: &mut E, + ccx: &mut CheatsCtxt, + executor: &mut dyn CheatcodesExecutor, ) -> Result { let Self { $($arg),*, error} = self; handle_assertion_result($body, ccx, executor, $error_formatter, Some(error), $format_error) diff --git a/crates/cheatcodes/src/test/assume.rs b/crates/cheatcodes/src/test/assume.rs index e100eeb9d1c4..a0321b5a1cd3 100644 --- a/crates/cheatcodes/src/test/assume.rs +++ b/crates/cheatcodes/src/test/assume.rs @@ -1,5 +1,5 @@ use crate::{Cheatcode, Cheatcodes, CheatsCtxt, Error, Result}; -use foundry_evm_core::{backend::DatabaseExt, constants::MAGIC_ASSUME}; +use foundry_evm_core::constants::MAGIC_ASSUME; use spec::Vm::{assumeCall, assumeNoRevertCall}; use std::fmt::Debug; @@ -21,7 +21,7 @@ impl Cheatcode for assumeCall { } impl Cheatcode for assumeNoRevertCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { ccx.state.assume_no_revert = Some(AssumeNoRevert { depth: ccx.ecx.journaled_state.depth() }); Ok(Default::default()) diff --git a/crates/cheatcodes/src/test/expect.rs b/crates/cheatcodes/src/test/expect.rs index f38776f94bfd..7a58c7ab8aa8 100644 --- a/crates/cheatcodes/src/test/expect.rs +++ b/crates/cheatcodes/src/test/expect.rs @@ -1,4 +1,4 @@ -use crate::{Cheatcode, Cheatcodes, CheatsCtxt, DatabaseExt, Error, Result, Vm::*}; +use crate::{Cheatcode, Cheatcodes, CheatsCtxt, Error, Result, Vm::*}; use alloy_primitives::{address, hex, Address, Bytes, LogData as RawLog, U256}; use alloy_sol_types::{SolError, SolValue}; use foundry_common::ContractsByArtifact; @@ -210,7 +210,7 @@ impl Cheatcode for expectCallMinGas_1Call { } impl Cheatcode for expectEmit_0Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { checkTopic1, checkTopic2, checkTopic3, checkData } = *self; expect_emit( ccx.state, @@ -223,7 +223,7 @@ impl Cheatcode for expectEmit_0Call { } impl Cheatcode for expectEmit_1Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { checkTopic1, checkTopic2, checkTopic3, checkData, emitter } = *self; expect_emit( ccx.state, @@ -236,21 +236,21 @@ impl Cheatcode for expectEmit_1Call { } impl Cheatcode for expectEmit_2Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self {} = self; expect_emit(ccx.state, ccx.ecx.journaled_state.depth(), [true; 5], None, false) } } impl Cheatcode for expectEmit_3Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { emitter } = *self; expect_emit(ccx.state, ccx.ecx.journaled_state.depth(), [true; 5], Some(emitter), false) } } impl Cheatcode for expectEmitAnonymous_0Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { checkTopic0, checkTopic1, checkTopic2, checkTopic3, checkData } = *self; expect_emit( ccx.state, @@ -263,7 +263,7 @@ impl Cheatcode for expectEmitAnonymous_0Call { } impl Cheatcode for expectEmitAnonymous_1Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { checkTopic0, checkTopic1, checkTopic2, checkTopic3, checkData, emitter } = *self; expect_emit( ccx.state, @@ -276,28 +276,28 @@ impl Cheatcode for expectEmitAnonymous_1Call { } impl Cheatcode for expectEmitAnonymous_2Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self {} = self; expect_emit(ccx.state, ccx.ecx.journaled_state.depth(), [true; 5], None, true) } } impl Cheatcode for expectEmitAnonymous_3Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { emitter } = *self; expect_emit(ccx.state, ccx.ecx.journaled_state.depth(), [true; 5], Some(emitter), true) } } impl Cheatcode for expectRevert_0Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self {} = self; expect_revert(ccx.state, None, ccx.ecx.journaled_state.depth(), false, false, None) } } impl Cheatcode for expectRevert_1Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { revertData } = self; expect_revert( ccx.state, @@ -311,7 +311,7 @@ impl Cheatcode for expectRevert_1Call { } impl Cheatcode for expectRevert_2Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { revertData } = self; expect_revert( ccx.state, @@ -325,7 +325,7 @@ impl Cheatcode for expectRevert_2Call { } impl Cheatcode for expectRevert_3Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { reverter } = self; expect_revert( ccx.state, @@ -339,7 +339,7 @@ impl Cheatcode for expectRevert_3Call { } impl Cheatcode for expectRevert_4Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { revertData, reverter } = self; expect_revert( ccx.state, @@ -353,7 +353,7 @@ impl Cheatcode for expectRevert_4Call { } impl Cheatcode for expectRevert_5Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { revertData, reverter } = self; expect_revert( ccx.state, @@ -367,7 +367,7 @@ impl Cheatcode for expectRevert_5Call { } impl Cheatcode for expectPartialRevert_0Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { revertData } = self; expect_revert( ccx.state, @@ -381,7 +381,7 @@ impl Cheatcode for expectPartialRevert_0Call { } impl Cheatcode for expectPartialRevert_1Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { revertData, reverter } = self; expect_revert( ccx.state, @@ -395,13 +395,13 @@ impl Cheatcode for expectPartialRevert_1Call { } impl Cheatcode for _expectCheatcodeRevert_0Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { expect_revert(ccx.state, None, ccx.ecx.journaled_state.depth(), true, false, None) } } impl Cheatcode for _expectCheatcodeRevert_1Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { revertData } = self; expect_revert( ccx.state, @@ -415,7 +415,7 @@ impl Cheatcode for _expectCheatcodeRevert_1Call { } impl Cheatcode for _expectCheatcodeRevert_2Call { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { revertData } = self; expect_revert( ccx.state, @@ -429,14 +429,14 @@ impl Cheatcode for _expectCheatcodeRevert_2Call { } impl Cheatcode for expectSafeMemoryCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { min, max } = *self; expect_safe_memory(ccx.state, min, max, ccx.ecx.journaled_state.depth()) } } impl Cheatcode for stopExpectSafeMemoryCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self {} = self; ccx.state.allowed_mem_writes.remove(&ccx.ecx.journaled_state.depth()); Ok(Default::default()) @@ -444,7 +444,7 @@ impl Cheatcode for stopExpectSafeMemoryCall { } impl Cheatcode for expectSafeMemoryCallCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { min, max } = *self; expect_safe_memory(ccx.state, min, max, ccx.ecx.journaled_state.depth() + 1) } diff --git a/crates/cheatcodes/src/utils.rs b/crates/cheatcodes/src/utils.rs index eb4d2f525a4f..23cc02f7ad9d 100644 --- a/crates/cheatcodes/src/utils.rs +++ b/crates/cheatcodes/src/utils.rs @@ -1,12 +1,12 @@ //! Implementations of [`Utilities`](spec::Group::Utilities) cheatcodes. -use crate::{Cheatcode, Cheatcodes, CheatsCtxt, Result, Vm::*}; +use crate::{Cheatcode, Cheatcodes, CheatcodesExecutor, CheatsCtxt, Result, Vm::*}; use alloy_dyn_abi::{DynSolType, DynSolValue}; use alloy_primitives::{map::HashMap, U256}; use alloy_sol_types::SolValue; use foundry_common::ens::namehash; -use foundry_evm_core::{backend::DatabaseExt, constants::DEFAULT_CREATE2_DEPLOYER}; -use proptest::strategy::{Strategy, ValueTree}; +use foundry_evm_core::constants::DEFAULT_CREATE2_DEPLOYER; +use proptest::prelude::Strategy; use rand::{Rng, RngCore}; /// Contains locations of traces ignored via cheatcodes. @@ -134,10 +134,10 @@ impl Cheatcode for randomBytesCall { } impl Cheatcode for pauseTracingCall { - fn apply_full( + fn apply_full( &self, - ccx: &mut crate::CheatsCtxt, - executor: &mut E, + ccx: &mut crate::CheatsCtxt, + executor: &mut dyn CheatcodesExecutor, ) -> Result { let Some(tracer) = executor.tracing_inspector().and_then(|t| t.as_ref()) else { // No tracer -> nothing to pause @@ -157,10 +157,10 @@ impl Cheatcode for pauseTracingCall { } impl Cheatcode for resumeTracingCall { - fn apply_full( + fn apply_full( &self, - ccx: &mut crate::CheatsCtxt, - executor: &mut E, + ccx: &mut crate::CheatsCtxt, + executor: &mut dyn CheatcodesExecutor, ) -> Result { let Some(tracer) = executor.tracing_inspector().and_then(|t| t.as_ref()) else { // No tracer -> nothing to unpause @@ -180,7 +180,7 @@ impl Cheatcode for resumeTracingCall { } impl Cheatcode for setArbitraryStorageCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { target } = self; ccx.state.arbitrary_storage().mark_arbitrary(target); @@ -189,7 +189,7 @@ impl Cheatcode for setArbitraryStorageCall { } impl Cheatcode for copyStorageCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { from, to } = self; ensure!( diff --git a/crates/evm/core/src/backend/cow.rs b/crates/evm/core/src/backend/cow.rs index 8156d75fbddf..1589c8ee8ec9 100644 --- a/crates/evm/core/src/backend/cow.rs +++ b/crates/evm/core/src/backend/cow.rs @@ -62,20 +62,16 @@ impl<'a> CowBackend<'a> { /// Note: in case there are any cheatcodes executed that modify the environment, this will /// update the given `env` with the new values. #[instrument(name = "inspect", level = "debug", skip_all)] - pub fn inspect<'b, I: InspectorExt<&'b mut dyn DatabaseExt>>( - &'b mut self, + pub fn inspect( + &mut self, env: &mut EnvWithHandlerCfg, - inspector: I, + inspector: &mut dyn InspectorExt, ) -> eyre::Result { // 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; self.spec_id = env.handler_cfg.spec_id; - let mut evm = crate::utils::new_evm_with_inspector( - self as &mut dyn DatabaseExt, - env.clone(), - inspector, - ); + let mut evm = crate::utils::new_evm_with_inspector(self, env.clone(), inspector); let res = evm.transact().wrap_err("backend: failed while inspecting")?; @@ -190,7 +186,7 @@ impl<'a> DatabaseExt for CowBackend<'a> { transaction: B256, env: &mut Env, journaled_state: &mut JournaledState, - inspector: &mut dyn InspectorExt, + inspector: &mut dyn InspectorExt, ) -> eyre::Result<()> { self.backend_mut(env).transact(id, transaction, env, journaled_state, inspector) } @@ -200,7 +196,7 @@ impl<'a> DatabaseExt for CowBackend<'a> { transaction: TransactionRequest, env: &Env, journaled_state: &mut JournaledState, - inspector: &mut dyn InspectorExt, + inspector: &mut dyn InspectorExt, ) -> eyre::Result<()> { self.backend_mut(env).transact_from_tx(transaction, env, journaled_state, inspector) } diff --git a/crates/evm/core/src/backend/mod.rs b/crates/evm/core/src/backend/mod.rs index 07ee7013012e..9d26ce287359 100644 --- a/crates/evm/core/src/backend/mod.rs +++ b/crates/evm/core/src/backend/mod.rs @@ -200,7 +200,7 @@ pub trait DatabaseExt: Database + DatabaseCommit { transaction: B256, env: &mut Env, journaled_state: &mut JournaledState, - inspector: &mut dyn InspectorExt, + inspector: &mut dyn InspectorExt, ) -> eyre::Result<()>; /// Executes a given TransactionRequest, commits the new state to the DB @@ -209,7 +209,7 @@ pub trait DatabaseExt: Database + DatabaseCommit { transaction: TransactionRequest, env: &Env, journaled_state: &mut JournaledState, - inspector: &mut dyn InspectorExt, + inspector: &mut dyn InspectorExt, ) -> eyre::Result<()>; /// Returns the `ForkId` that's currently used in the database, if fork mode is on @@ -751,17 +751,13 @@ impl Backend { /// Note: in case there are any cheatcodes executed that modify the environment, this will /// update the given `env` with the new values. #[instrument(name = "inspect", level = "debug", skip_all)] - pub fn inspect<'a, I: InspectorExt<&'a mut dyn DatabaseExt>>( - &'a mut self, + pub fn inspect( + &mut self, env: &mut EnvWithHandlerCfg, - inspector: I, + inspector: &mut dyn InspectorExt, ) -> eyre::Result { self.initialize(env); - let mut evm = crate::utils::new_evm_with_inspector( - self as &mut dyn DatabaseExt, - env.clone(), - inspector, - ); + let mut evm = crate::utils::new_evm_with_inspector(self, env.clone(), inspector); let res = evm.transact().wrap_err("backend: failed while inspecting")?; @@ -1229,7 +1225,7 @@ impl DatabaseExt for Backend { transaction: B256, env: &mut Env, journaled_state: &mut JournaledState, - inspector: &mut dyn InspectorExt, + inspector: &mut dyn InspectorExt, ) -> eyre::Result<()> { trace!(?maybe_id, ?transaction, "execute transaction"); let persistent_accounts = self.inner.persistent_accounts.clone(); @@ -1270,7 +1266,7 @@ impl DatabaseExt for Backend { tx: TransactionRequest, env: &Env, journaled_state: &mut JournaledState, - inspector: &mut dyn InspectorExt, + inspector: &mut dyn InspectorExt, ) -> eyre::Result<()> { trace!(?tx, "execute signed transaction"); @@ -1294,9 +1290,9 @@ impl DatabaseExt for Backend { self.commit(journaled_state.state.clone()); let res = { - let db = self.clone(); + let mut db = self.clone(); let env = self.env_with_handler_cfg(env); - let mut evm = new_evm_with_inspector(db, env, inspector); + let mut evm = new_evm_with_inspector(&mut db, env, inspector); evm.context.evm.journaled_state.depth = journaled_state.depth + 1; evm.transact()? }; @@ -1921,7 +1917,7 @@ fn commit_transaction( fork: &mut Fork, fork_id: &ForkId, persistent_accounts: &HashSet
, - inspector: &mut dyn InspectorExt, + inspector: &mut dyn InspectorExt, ) -> eyre::Result<()> { configure_tx_env(&mut env.env, tx); @@ -1930,9 +1926,9 @@ fn commit_transaction( let fork = fork.clone(); let journaled_state = journaled_state.clone(); let depth = journaled_state.depth; - let db = Backend::new_with_fork(fork_id, fork, journaled_state); + let mut db = Backend::new_with_fork(fork_id, fork, journaled_state); - let mut evm = crate::utils::new_evm_with_inspector(db, env, inspector); + let mut evm = crate::utils::new_evm_with_inspector(&mut db as _, env, inspector); // Adjust inner EVM depth to ensure that inspectors receive accurate data. evm.context.evm.inner.journaled_state.depth = depth + 1; evm.transact().wrap_err("backend: failed committing transaction")? diff --git a/crates/evm/core/src/lib.rs b/crates/evm/core/src/lib.rs index b30a36544b48..b6da4b49a5d9 100644 --- a/crates/evm/core/src/lib.rs +++ b/crates/evm/core/src/lib.rs @@ -6,7 +6,8 @@ #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] use auto_impl::auto_impl; -use revm::{inspectors::NoOpInspector, interpreter::CreateInputs, Database, EvmContext, Inspector}; +use backend::DatabaseExt; +use revm::{inspectors::NoOpInspector, interpreter::CreateInputs, EvmContext, Inspector}; use revm_inspectors::access_list::AccessListInspector; #[macro_use] @@ -32,14 +33,14 @@ pub mod utils; /// An extension trait that allows us to add additional hooks to Inspector for later use in /// handlers. #[auto_impl(&mut, Box)] -pub trait InspectorExt: Inspector { +pub trait InspectorExt: for<'a> Inspector<&'a mut dyn DatabaseExt> { /// Determines whether the `DEFAULT_CREATE2_DEPLOYER` should be used for a CREATE2 frame. /// /// If this function returns true, we'll replace CREATE2 frame with a CALL frame to CREATE2 /// factory. fn should_use_create2_factory( &mut self, - _context: &mut EvmContext, + _context: &mut EvmContext<&mut dyn DatabaseExt>, _inputs: &mut CreateInputs, ) -> bool { false @@ -54,5 +55,6 @@ pub trait InspectorExt: Inspector { } } -impl InspectorExt for NoOpInspector {} -impl InspectorExt for AccessListInspector {} +impl InspectorExt for NoOpInspector {} + +impl InspectorExt for AccessListInspector {} diff --git a/crates/evm/core/src/utils.rs b/crates/evm/core/src/utils.rs index 19782ee9da51..d45c4b84908a 100644 --- a/crates/evm/core/src/utils.rs +++ b/crates/evm/core/src/utils.rs @@ -1,5 +1,8 @@ pub use crate::ic::*; -use crate::{constants::DEFAULT_CREATE2_DEPLOYER, precompiles::ALPHANET_P256, InspectorExt}; +use crate::{ + backend::DatabaseExt, constants::DEFAULT_CREATE2_DEPLOYER, precompiles::ALPHANET_P256, + InspectorExt, +}; use alloy_json_abi::{Function, JsonAbi}; use alloy_primitives::{Address, Selector, TxKind, U256}; use alloy_provider::{ @@ -8,8 +11,8 @@ use alloy_provider::{ }; use alloy_rpc_types::Transaction; use foundry_config::NamedChain; +use foundry_fork_db::DatabaseError; use revm::{ - db::WrapDatabaseRef, handler::register::EvmHandler, interpreter::{ return_ok, CallInputs, CallOutcome, CallScheme, CallValue, CreateInputs, CreateOutcome, @@ -123,15 +126,15 @@ fn get_create2_factory_call_inputs(salt: U256, inputs: CreateInputs) -> CallInpu /// hook by inserting decoded address directly into interpreter. /// /// Should be installed after [revm::inspector_handle_register] and before any other registers. -pub fn create2_handler_register>( - handler: &mut EvmHandler<'_, I, DB>, +pub fn create2_handler_register( + handler: &mut EvmHandler<'_, I, &mut dyn DatabaseExt>, ) { let create2_overrides = Rc::>>::new(RefCell::new(Vec::new())); let create2_overrides_inner = create2_overrides.clone(); let old_handle = handler.execution.create.clone(); handler.execution.create = - Arc::new(move |ctx, mut inputs| -> Result> { + Arc::new(move |ctx, mut inputs| -> Result> { let CreateScheme::Create2 { salt } = inputs.scheme else { return old_handle(ctx, inputs); }; @@ -219,9 +222,7 @@ pub fn create2_handler_register>( } /// Adds Alphanet P256 precompile to the list of loaded precompiles. -pub fn alphanet_handler_register>( - handler: &mut EvmHandler<'_, I, DB>, -) { +pub fn alphanet_handler_register(handler: &mut EvmHandler<'_, EXT, DB>) { let prev = handler.pre_execution.load_precompiles.clone(); handler.pre_execution.load_precompiles = Arc::new(move || { let mut loaded_precompiles = prev(); @@ -233,15 +234,11 @@ pub fn alphanet_handler_register>( } /// Creates a new EVM with the given inspector. -pub fn new_evm_with_inspector<'a, DB, I>( - db: DB, +pub fn new_evm_with_inspector<'evm, 'i, 'db>( + db: &'db mut dyn DatabaseExt, env: revm::primitives::EnvWithHandlerCfg, - inspector: I, -) -> revm::Evm<'a, I, DB> -where - DB: revm::Database, - I: InspectorExt, -{ + inspector: &'i mut dyn InspectorExt, +) -> revm::Evm<'evm, &'i mut dyn InspectorExt, &'db mut dyn DatabaseExt> { let revm::primitives::EnvWithHandlerCfg { env, handler_cfg } = env; // NOTE: We could use `revm::Evm::builder()` here, but on the current patch it has some @@ -269,27 +266,10 @@ where revm::Evm::new(context, handler) } -/// Creates a new EVM with the given inspector and wraps the database in a `WrapDatabaseRef`. -pub fn new_evm_with_inspector_ref<'a, DB, I>( - db: DB, - env: revm::primitives::EnvWithHandlerCfg, - inspector: I, -) -> revm::Evm<'a, I, WrapDatabaseRef> -where - DB: revm::DatabaseRef, - I: InspectorExt>, -{ - new_evm_with_inspector(WrapDatabaseRef(db), env, inspector) -} - -pub fn new_evm_with_existing_context<'a, DB, I>( - inner: revm::InnerEvmContext, - inspector: I, -) -> revm::Evm<'a, I, DB> -where - DB: revm::Database, - I: InspectorExt, -{ +pub fn new_evm_with_existing_context<'a>( + inner: revm::InnerEvmContext<&'a mut dyn DatabaseExt>, + inspector: &'a mut dyn InspectorExt, +) -> revm::Evm<'a, &'a mut dyn InspectorExt, &'a mut dyn DatabaseExt> { let handler_cfg = HandlerCfg::new(inner.spec_id()); let mut handler = revm::Handler::new(handler_cfg); @@ -303,24 +283,3 @@ where revm::Context::new(revm::EvmContext { inner, precompiles: Default::default() }, inspector); revm::Evm::new(context, handler) } - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn build_evm() { - let mut db = revm::db::EmptyDB::default(); - - let env = Box::::default(); - let spec = SpecId::LATEST; - let handler_cfg = revm::primitives::HandlerCfg::new(spec); - let cfg = revm::primitives::EnvWithHandlerCfg::new(env, handler_cfg); - - let mut inspector = revm::inspectors::NoOpInspector; - - let mut evm = new_evm_with_inspector(&mut db, cfg, &mut inspector); - let result = evm.transact().unwrap(); - assert!(result.result.is_success()); - } -} diff --git a/crates/evm/evm/src/inspectors/logs.rs b/crates/evm/evm/src/inspectors/logs.rs index 03b677fcdf84..877101a8064f 100644 --- a/crates/evm/evm/src/inspectors/logs.rs +++ b/crates/evm/evm/src/inspectors/logs.rs @@ -60,7 +60,7 @@ impl Inspector for LogCollector { gas: Gas::new(inputs.gas_limit), }, memory_offset: inputs.return_memory_offset.clone(), - }) + }); } } @@ -68,7 +68,7 @@ impl Inspector for LogCollector { } } -impl InspectorExt for LogCollector { +impl InspectorExt for LogCollector { fn console_log(&mut self, input: String) { self.logs.push(Log::new_unchecked( HARDHAT_CONSOLE_ADDRESS, diff --git a/crates/evm/evm/src/inspectors/stack.rs b/crates/evm/evm/src/inspectors/stack.rs index fc270564133a..c8df2c693102 100644 --- a/crates/evm/evm/src/inspectors/stack.rs +++ b/crates/evm/evm/src/inspectors/stack.rs @@ -304,11 +304,8 @@ pub struct InspectorStackRefMut<'a> { } impl CheatcodesExecutor for InspectorStackInner { - fn get_inspector<'a, DB: DatabaseExt>( - &'a mut self, - cheats: &'a mut Cheatcodes, - ) -> impl InspectorExt + 'a { - InspectorStackRefMut { cheatcodes: Some(cheats), inner: self } + fn get_inspector<'a>(&'a mut self, cheats: &'a mut Cheatcodes) -> Box { + Box::new(InspectorStackRefMut { cheatcodes: Some(cheats), inner: self }) } fn tracing_inspector(&mut self) -> Option<&mut Option> { @@ -479,15 +476,15 @@ impl<'a> InspectorStackRefMut<'a> { /// Should be called on the top-level call of inner context (depth == 0 && /// self.in_inner_context) Decreases sender nonce for CALLs to keep backwards compatibility /// Updates tx.origin to the value before entering inner context - fn adjust_evm_data_for_inner_context(&mut self, ecx: &mut EvmContext) { + fn adjust_evm_data_for_inner_context(&mut self, ecx: &mut EvmContext<&mut dyn DatabaseExt>) { let inner_context_data = self.inner_context_data.as_ref().expect("should be called in inner context"); ecx.env.tx.caller = inner_context_data.original_origin; } - fn do_call_end( + fn do_call_end( &mut self, - ecx: &mut EvmContext, + ecx: &mut EvmContext<&mut dyn DatabaseExt>, inputs: &CallInputs, outcome: CallOutcome, ) -> CallOutcome { @@ -512,9 +509,9 @@ impl<'a> InspectorStackRefMut<'a> { outcome } - fn transact_inner( + fn transact_inner( &mut self, - ecx: &mut EvmContext, + ecx: &mut EvmContext<&mut dyn DatabaseExt>, transact_to: TransactTo, caller: Address, input: Bytes, @@ -547,11 +544,7 @@ impl<'a> InspectorStackRefMut<'a> { let env = EnvWithHandlerCfg::new_with_spec_id(ecx.env.clone(), ecx.spec_id()); let res = { - let mut evm = crate::utils::new_evm_with_inspector( - &mut ecx.db as &mut dyn DatabaseExt, - env, - &mut *self, - ); + let mut evm = crate::utils::new_evm_with_inspector(&mut ecx.db, env, self); let res = evm.transact(); // need to reset the env in case it was modified via cheatcodes during execution @@ -630,8 +623,12 @@ impl<'a> InspectorStackRefMut<'a> { } } -impl<'a, DB: DatabaseExt> Inspector for InspectorStackRefMut<'a> { - fn initialize_interp(&mut self, interpreter: &mut Interpreter, ecx: &mut EvmContext) { +impl<'a> Inspector<&mut dyn DatabaseExt> for InspectorStackRefMut<'a> { + fn initialize_interp( + &mut self, + interpreter: &mut Interpreter, + ecx: &mut EvmContext<&mut dyn DatabaseExt>, + ) { call_inspectors_adjust_depth!( [&mut self.coverage, &mut self.tracer, &mut self.cheatcodes, &mut self.printer], |inspector| inspector.initialize_interp(interpreter, ecx), @@ -640,7 +637,7 @@ impl<'a, DB: DatabaseExt> Inspector for InspectorStackRefMut<'a> { ); } - fn step(&mut self, interpreter: &mut Interpreter, ecx: &mut EvmContext) { + fn step(&mut self, interpreter: &mut Interpreter, ecx: &mut EvmContext<&mut dyn DatabaseExt>) { call_inspectors_adjust_depth!( [ &mut self.fuzzer, @@ -655,7 +652,11 @@ impl<'a, DB: DatabaseExt> Inspector for InspectorStackRefMut<'a> { ); } - fn step_end(&mut self, interpreter: &mut Interpreter, ecx: &mut EvmContext) { + fn step_end( + &mut self, + interpreter: &mut Interpreter, + ecx: &mut EvmContext<&mut dyn DatabaseExt>, + ) { call_inspectors_adjust_depth!( [&mut self.tracer, &mut self.cheatcodes, &mut self.chisel_state, &mut self.printer], |inspector| inspector.step_end(interpreter, ecx), @@ -664,7 +665,12 @@ impl<'a, DB: DatabaseExt> Inspector for InspectorStackRefMut<'a> { ); } - fn log(&mut self, interpreter: &mut Interpreter, ecx: &mut EvmContext, log: &Log) { + fn log( + &mut self, + interpreter: &mut Interpreter, + ecx: &mut EvmContext<&mut dyn DatabaseExt>, + log: &Log, + ) { call_inspectors_adjust_depth!( [&mut self.tracer, &mut self.log_collector, &mut self.cheatcodes, &mut self.printer], |inspector| inspector.log(interpreter, ecx, log), @@ -673,7 +679,11 @@ impl<'a, DB: DatabaseExt> Inspector for InspectorStackRefMut<'a> { ); } - fn call(&mut self, ecx: &mut EvmContext, call: &mut CallInputs) -> Option { + fn call( + &mut self, + ecx: &mut EvmContext<&mut dyn DatabaseExt>, + call: &mut CallInputs, + ) -> Option { if self.in_inner_context && ecx.journaled_state.depth == 0 { self.adjust_evm_data_for_inner_context(ecx); return None; @@ -739,7 +749,7 @@ impl<'a, DB: DatabaseExt> Inspector for InspectorStackRefMut<'a> { fn call_end( &mut self, - ecx: &mut EvmContext, + ecx: &mut EvmContext<&mut dyn DatabaseExt>, inputs: &CallInputs, outcome: CallOutcome, ) -> CallOutcome { @@ -764,7 +774,7 @@ impl<'a, DB: DatabaseExt> Inspector for InspectorStackRefMut<'a> { fn create( &mut self, - ecx: &mut EvmContext, + ecx: &mut EvmContext<&mut dyn DatabaseExt>, create: &mut CreateInputs, ) -> Option { if self.in_inner_context && ecx.journaled_state.depth == 0 { @@ -801,7 +811,7 @@ impl<'a, DB: DatabaseExt> Inspector for InspectorStackRefMut<'a> { fn create_end( &mut self, - ecx: &mut EvmContext, + ecx: &mut EvmContext<&mut dyn DatabaseExt>, call: &CreateInputs, outcome: CreateOutcome, ) -> CreateOutcome { @@ -835,7 +845,7 @@ impl<'a, DB: DatabaseExt> Inspector for InspectorStackRefMut<'a> { fn eofcreate( &mut self, - ecx: &mut EvmContext, + ecx: &mut EvmContext<&mut dyn DatabaseExt>, create: &mut EOFCreateInputs, ) -> Option { if self.in_inner_context && ecx.journaled_state.depth == 0 { @@ -877,7 +887,7 @@ impl<'a, DB: DatabaseExt> Inspector for InspectorStackRefMut<'a> { fn eofcreate_end( &mut self, - ecx: &mut EvmContext, + ecx: &mut EvmContext<&mut dyn DatabaseExt>, call: &EOFCreateInputs, outcome: CreateOutcome, ) -> CreateOutcome { @@ -911,15 +921,15 @@ impl<'a, DB: DatabaseExt> Inspector for InspectorStackRefMut<'a> { fn selfdestruct(&mut self, contract: Address, target: Address, value: U256) { call_inspectors!([&mut self.tracer, &mut self.printer], |inspector| { - Inspector::::selfdestruct(inspector, contract, target, value) + Inspector::<&mut dyn DatabaseExt>::selfdestruct(inspector, contract, target, value) }); } } -impl<'a, DB: DatabaseExt> InspectorExt for InspectorStackRefMut<'a> { +impl InspectorExt for InspectorStackRefMut<'_> { fn should_use_create2_factory( &mut self, - ecx: &mut EvmContext, + ecx: &mut EvmContext<&mut dyn DatabaseExt>, inputs: &mut CreateInputs, ) -> bool { call_inspectors_adjust_depth!( @@ -934,7 +944,7 @@ impl<'a, DB: DatabaseExt> InspectorExt for InspectorStackRefMut<'a> { } fn console_log(&mut self, input: String) { - call_inspectors!([&mut self.log_collector], |inspector| InspectorExt::::console_log( + call_inspectors!([&mut self.log_collector], |inspector| InspectorExt::console_log( inspector, input )); } @@ -944,20 +954,24 @@ impl<'a, DB: DatabaseExt> InspectorExt for InspectorStackRefMut<'a> { } } -impl Inspector for InspectorStack { +impl Inspector<&mut dyn DatabaseExt> for InspectorStack { #[inline] - fn step(&mut self, interpreter: &mut Interpreter, ecx: &mut EvmContext) { + fn step(&mut self, interpreter: &mut Interpreter, ecx: &mut EvmContext<&mut dyn DatabaseExt>) { self.as_mut().step(interpreter, ecx) } #[inline] - fn step_end(&mut self, interpreter: &mut Interpreter, ecx: &mut EvmContext) { + fn step_end( + &mut self, + interpreter: &mut Interpreter, + ecx: &mut EvmContext<&mut dyn DatabaseExt>, + ) { self.as_mut().step_end(interpreter, ecx) } fn call( &mut self, - context: &mut EvmContext, + context: &mut EvmContext<&mut dyn DatabaseExt>, inputs: &mut CallInputs, ) -> Option { self.as_mut().call(context, inputs) @@ -965,7 +979,7 @@ impl Inspector for InspectorStack { fn call_end( &mut self, - context: &mut EvmContext, + context: &mut EvmContext<&mut dyn DatabaseExt>, inputs: &CallInputs, outcome: CallOutcome, ) -> CallOutcome { @@ -974,7 +988,7 @@ impl Inspector for InspectorStack { fn create( &mut self, - context: &mut EvmContext, + context: &mut EvmContext<&mut dyn DatabaseExt>, create: &mut CreateInputs, ) -> Option { self.as_mut().create(context, create) @@ -982,7 +996,7 @@ impl Inspector for InspectorStack { fn create_end( &mut self, - context: &mut EvmContext, + context: &mut EvmContext<&mut dyn DatabaseExt>, call: &CreateInputs, outcome: CreateOutcome, ) -> CreateOutcome { @@ -991,7 +1005,7 @@ impl Inspector for InspectorStack { fn eofcreate( &mut self, - context: &mut EvmContext, + context: &mut EvmContext<&mut dyn DatabaseExt>, create: &mut EOFCreateInputs, ) -> Option { self.as_mut().eofcreate(context, create) @@ -999,30 +1013,39 @@ impl Inspector for InspectorStack { fn eofcreate_end( &mut self, - context: &mut EvmContext, + context: &mut EvmContext<&mut dyn DatabaseExt>, call: &EOFCreateInputs, outcome: CreateOutcome, ) -> CreateOutcome { self.as_mut().eofcreate_end(context, call, outcome) } - fn initialize_interp(&mut self, interpreter: &mut Interpreter, ecx: &mut EvmContext) { + fn initialize_interp( + &mut self, + interpreter: &mut Interpreter, + ecx: &mut EvmContext<&mut dyn DatabaseExt>, + ) { self.as_mut().initialize_interp(interpreter, ecx) } - fn log(&mut self, interpreter: &mut Interpreter, ecx: &mut EvmContext, log: &Log) { + fn log( + &mut self, + interpreter: &mut Interpreter, + ecx: &mut EvmContext<&mut dyn DatabaseExt>, + log: &Log, + ) { self.as_mut().log(interpreter, ecx, log) } fn selfdestruct(&mut self, contract: Address, target: Address, value: U256) { - Inspector::::selfdestruct(&mut self.as_mut(), contract, target, value) + Inspector::<&mut dyn DatabaseExt>::selfdestruct(&mut self.as_mut(), contract, target, value) } } -impl InspectorExt for InspectorStack { +impl InspectorExt for InspectorStack { fn should_use_create2_factory( &mut self, - ecx: &mut EvmContext, + ecx: &mut EvmContext<&mut dyn DatabaseExt>, inputs: &mut CreateInputs, ) -> bool { self.as_mut().should_use_create2_factory(ecx, inputs)