From 16d9cfab70dd58bf6b1efc9d13def77ba7b367f4 Mon Sep 17 00:00:00 2001 From: Nisheeth Barthwal Date: Sun, 22 Dec 2024 20:27:14 +0100 Subject: [PATCH] cleanup --- crates/cheatcodes/src/config.rs | 13 +-- crates/cheatcodes/src/evm.rs | 16 +-- crates/cheatcodes/src/evm/fork.rs | 4 +- crates/cheatcodes/src/evm/mock.rs | 4 +- crates/cheatcodes/src/fs.rs | 2 +- crates/cheatcodes/src/inspector.rs | 23 ++--- crates/cheatcodes/src/strategy.rs | 46 ++++++--- crates/cheatcodes/src/test.rs | 10 +- crates/chisel/src/executor.rs | 4 +- crates/cli/src/utils/mod.rs | 10 +- crates/evm/core/src/backend/cow.rs | 4 +- crates/evm/core/src/backend/mod.rs | 30 +++--- crates/evm/core/src/backend/strategy.rs | 42 +++++--- crates/evm/evm/src/executors/builder.rs | 4 +- crates/evm/evm/src/executors/mod.rs | 16 +-- crates/evm/evm/src/executors/strategy.rs | 57 ++++++----- crates/evm/evm/src/executors/trace.rs | 6 +- crates/forge/bin/cmd/test/mod.rs | 2 +- crates/forge/src/multi_runner.rs | 10 +- crates/forge/src/runner.rs | 2 +- crates/forge/tests/it/test_helpers.rs | 2 +- crates/script/src/lib.rs | 10 +- crates/script/src/runner.rs | 2 +- crates/strategy/zksync/src/backend.rs | 55 ++++++----- crates/strategy/zksync/src/cheatcode.rs | 121 +++++++++++++---------- crates/strategy/zksync/src/executor.rs | 58 ++++++----- crates/strategy/zksync/src/lib.rs | 8 +- crates/verify/src/utils.rs | 4 +- 28 files changed, 318 insertions(+), 247 deletions(-) diff --git a/crates/cheatcodes/src/config.rs b/crates/cheatcodes/src/config.rs index 9c519ee93..5a32f40c9 100644 --- a/crates/cheatcodes/src/config.rs +++ b/crates/cheatcodes/src/config.rs @@ -1,8 +1,5 @@ use super::Result; -use crate::{ - strategy::{new_evm_strategy, Strategy}, - Vm::Rpc, -}; +use crate::{strategy::CheatcodeInspectorStrategy, Vm::Rpc}; use alloy_primitives::{map::AddressHashMap, U256}; use foundry_common::{fs::normalize_path, ContractsByArtifact}; use foundry_compilers::{utils::canonicalize, ProjectPathsConfig}; @@ -57,7 +54,7 @@ pub struct CheatsConfig { /// Version of the script/test contract which is currently running. pub running_version: Option, /// The behavior strategy. - pub strategy: Strategy, + pub strategy: CheatcodeInspectorStrategy, /// Whether to enable legacy (non-reverting) assertions. pub assertions_revert: bool, /// Optional seed for the RNG algorithm. @@ -73,7 +70,7 @@ impl CheatsConfig { available_artifacts: Option, running_contract: Option, running_version: Option, - strategy: Strategy, + strategy: CheatcodeInspectorStrategy, ) -> Self { let mut allowed_paths = vec![config.root.0.clone()]; allowed_paths.extend(config.libs.clone()); @@ -234,7 +231,7 @@ impl Default for CheatsConfig { available_artifacts: Default::default(), running_contract: Default::default(), running_version: Default::default(), - strategy: new_evm_strategy(), + strategy: CheatcodeInspectorStrategy::new_evm(), assertions_revert: true, seed: None, } @@ -253,7 +250,7 @@ mod tests { None, None, None, - new_evm_strategy(), + CheatcodeInspectorStrategy::new_evm(), ) } diff --git a/crates/cheatcodes/src/evm.rs b/crates/cheatcodes/src/evm.rs index 43eb9f50b..e5d6d3db5 100644 --- a/crates/cheatcodes/src/evm.rs +++ b/crates/cheatcodes/src/evm.rs @@ -64,7 +64,7 @@ impl Cheatcode for getNonce_0Call { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { account } = self; - ccx.state.strategy.inner.clone().cheatcode_get_nonce(ccx, *account) + ccx.state.strategy.runner.clone().cheatcode_get_nonce(ccx, *account) } } @@ -350,7 +350,7 @@ impl Cheatcode for getBlobhashesCall { impl Cheatcode for rollCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { newHeight } = self; - ccx.state.strategy.inner.clone().cheatcode_roll(ccx, *newHeight) + ccx.state.strategy.runner.clone().cheatcode_roll(ccx, *newHeight) } } @@ -372,7 +372,7 @@ impl Cheatcode for txGasPriceCall { impl Cheatcode for warpCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { newTimestamp } = self; - ccx.state.strategy.inner.clone().cheatcode_warp(ccx, *newTimestamp) + ccx.state.strategy.runner.clone().cheatcode_warp(ccx, *newTimestamp) } } @@ -407,7 +407,7 @@ impl Cheatcode for dealCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { account: address, newBalance: new_balance } = *self; - ccx.state.strategy.inner.clone().cheatcode_deal(ccx, address, new_balance) + ccx.state.strategy.runner.clone().cheatcode_deal(ccx, address, new_balance) } } @@ -415,14 +415,14 @@ impl Cheatcode for etchCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { target, newRuntimeBytecode } = self; - ccx.state.strategy.inner.clone().cheatcode_etch(ccx, *target, newRuntimeBytecode) + ccx.state.strategy.runner.clone().cheatcode_etch(ccx, *target, newRuntimeBytecode) } } impl Cheatcode for resetNonceCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { account } = self; - ccx.state.strategy.inner.clone().cheatcode_reset_nonce(ccx, *account) + ccx.state.strategy.runner.clone().cheatcode_reset_nonce(ccx, *account) } } @@ -430,7 +430,7 @@ impl Cheatcode for setNonceCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { account, newNonce } = *self; - ccx.state.strategy.inner.clone().cheatcode_set_nonce(ccx, account, newNonce) + ccx.state.strategy.runner.clone().cheatcode_set_nonce(ccx, account, newNonce) } } @@ -438,7 +438,7 @@ impl Cheatcode for setNonceUnsafeCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { account, newNonce } = *self; - ccx.state.strategy.inner.clone().cheatcode_set_nonce_unsafe(ccx, account, newNonce) + ccx.state.strategy.runner.clone().cheatcode_set_nonce_unsafe(ccx, account, newNonce) } } diff --git a/crates/cheatcodes/src/evm/fork.rs b/crates/cheatcodes/src/evm/fork.rs index a1bcc9ccb..e1db17a3d 100644 --- a/crates/cheatcodes/src/evm/fork.rs +++ b/crates/cheatcodes/src/evm/fork.rs @@ -125,7 +125,7 @@ impl Cheatcode for selectForkCall { persist_caller(ccx); check_broadcast(ccx.state)?; - ccx.state.strategy.inner.zksync_select_fork_vm( + ccx.state.strategy.runner.zksync_select_fork_vm( ccx.state.strategy.context.as_mut(), ccx.ecx, *forkId, @@ -285,7 +285,7 @@ fn create_select_fork(ccx: &mut CheatsCtxt, url_or_alias: &str, block: Option Result { let Self { callee, data, returnData } = self; - ccx.state.strategy.inner.clone().cheatcode_mock_call(ccx, *callee, data, returnData) + ccx.state.strategy.runner.clone().cheatcode_mock_call(ccx, *callee, data, returnData) } } @@ -83,7 +83,7 @@ impl Cheatcode for mockCalls_1Call { impl Cheatcode for mockCallRevert_0Call { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { callee, data, revertData } = self; - ccx.state.strategy.inner.clone().cheatcode_mock_call_revert(ccx, *callee, data, revertData) + ccx.state.strategy.runner.clone().cheatcode_mock_call_revert(ccx, *callee, data, revertData) } } diff --git a/crates/cheatcodes/src/fs.rs b/crates/cheatcodes/src/fs.rs index b99ed2945..96e53704c 100644 --- a/crates/cheatcodes/src/fs.rs +++ b/crates/cheatcodes/src/fs.rs @@ -283,7 +283,7 @@ impl Cheatcode for getArtifactPathByDeployedCodeCall { impl Cheatcode for getCodeCall { fn apply(&self, state: &mut Cheatcodes) -> Result { let Self { artifactPath: path } = self; - state.strategy.inner.get_artifact_code(state, path, false) + state.strategy.runner.get_artifact_code(state, path, false) } } diff --git a/crates/cheatcodes/src/inspector.rs b/crates/cheatcodes/src/inspector.rs index 7ae10782c..ad1f757e2 100644 --- a/crates/cheatcodes/src/inspector.rs +++ b/crates/cheatcodes/src/inspector.rs @@ -7,7 +7,7 @@ use crate::{ DealRecord, GasRecord, }, script::{Broadcast, Wallets}, - strategy::Strategy, + strategy::CheatcodeInspectorStrategy, test::{ assume::AssumeNoRevert, expect::{self, ExpectedEmit, ExpectedRevert, ExpectedRevertKind}, @@ -527,7 +527,7 @@ pub struct Cheatcodes { pub wallets: Option, /// The behavior strategy. - pub strategy: Strategy, + pub strategy: CheatcodeInspectorStrategy, } impl Clone for Cheatcodes { @@ -762,7 +762,7 @@ impl Cheatcodes { if ecx_inner.journaled_state.depth() == broadcast.depth { input.set_caller(broadcast.new_origin); - self.strategy.inner.record_broadcastable_create_transactions( + self.strategy.runner.record_broadcastable_create_transactions( self.strategy.context.as_mut(), self.config.clone(), &input, @@ -802,7 +802,7 @@ impl Cheatcodes { } if let Some(result) = - self.strategy.inner.clone().zksync_try_create(self, ecx, &input, executor) + self.strategy.runner.clone().zksync_try_create(self, ecx, &input, executor) { return Some(result); } @@ -917,7 +917,7 @@ where { } } - self.strategy.inner.zksync_record_create_address(self.strategy.context.as_mut(), &outcome); + self.strategy.runner.zksync_record_create_address(self.strategy.context.as_mut(), &outcome); outcome } @@ -960,7 +960,7 @@ where { let prev = account.info.nonce; let nonce = prev.saturating_sub(1); account.info.nonce = nonce; - self.strategy.inner.zksync_sync_nonce( + self.strategy.runner.zksync_sync_nonce( self.strategy.context.as_mut(), sender, nonce, @@ -999,7 +999,7 @@ where { return None; } - self.strategy.inner.zksync_set_deployer_call_input(self.strategy.context.as_mut(), call); + self.strategy.runner.zksync_set_deployer_call_input(self.strategy.context.as_mut(), call); // Handle expected calls @@ -1133,7 +1133,7 @@ where { }) } - self.strategy.inner.record_broadcastable_call_transactions( + self.strategy.runner.record_broadcastable_call_transactions( self.strategy.context.as_mut(), self.config.clone(), call, @@ -1214,7 +1214,8 @@ where { }]); } - if let Some(result) = self.strategy.inner.clone().zksync_try_call(self, ecx, call, executor) + if let Some(result) = + self.strategy.runner.clone().zksync_try_call(self, ecx, call, executor) { return Some(result); } @@ -1276,7 +1277,7 @@ impl Inspector<&mut dyn DatabaseExt> for Cheatcodes { self.gas_metering.paused_frames.push(interpreter.gas); } - self.strategy.inner.post_initialize_interp( + self.strategy.runner.post_initialize_interp( self.strategy.context.as_mut(), interpreter, ecx, @@ -1325,7 +1326,7 @@ impl Inspector<&mut dyn DatabaseExt> for Cheatcodes { #[inline] fn step_end(&mut self, interpreter: &mut Interpreter, ecx: Ecx) { - if self.strategy.inner.pre_step_end(self.strategy.context.as_mut(), interpreter, ecx) { + if self.strategy.runner.pre_step_end(self.strategy.context.as_mut(), interpreter, ecx) { return; } diff --git a/crates/cheatcodes/src/strategy.rs b/crates/cheatcodes/src/strategy.rs index dc1928b40..42d1f6fbf 100644 --- a/crates/cheatcodes/src/strategy.rs +++ b/crates/cheatcodes/src/strategy.rs @@ -18,15 +18,19 @@ use crate::{ CheatsConfig, CheatsCtxt, Result, }; +/// Represents the context for [CheatcodeInspectorStrategy]. pub trait CheatcodeInspectorStrategyContext: Debug + Send + Sync + Any { + /// Clone the strategy context. fn new_cloned(&self) -> Box; - fn as_any_mut(&mut self) -> &mut dyn Any; + /// Alias as immutable reference of [Any]. fn as_any_ref(&self) -> &dyn Any; + /// Alias as mutable reference of [Any]. + fn as_any_mut(&mut self) -> &mut dyn Any; } impl CheatcodeInspectorStrategyContext for () { fn new_cloned(&self) -> Box { - Box::new(*self) + Box::new(()) } fn as_any_mut(&mut self) -> &mut dyn Any { @@ -38,26 +42,36 @@ impl CheatcodeInspectorStrategyContext for () { } } +/// Represents the strategy. #[derive(Debug)] -pub struct Strategy { - pub inner: Box, +pub struct CheatcodeInspectorStrategy { + /// Strategy runner. + pub runner: Box, + /// Strategy context. pub context: Box, } -pub fn new_evm_strategy() -> Strategy { - Strategy { inner: Box::new(EvmCheatcodeInspectorStrategy::default()), context: Box::new(()) } +impl CheatcodeInspectorStrategy { + pub fn new_evm() -> Self { + Self { + runner: Box::new(EvmCheatcodeInspectorStrategyRunner::default()), + context: Box::new(()), + } + } } -impl Clone for Strategy { +impl Clone for CheatcodeInspectorStrategy { fn clone(&self) -> Self { - Self { inner: self.inner.new_cloned(), context: self.context.new_cloned() } + Self { runner: self.runner.new_cloned(), context: self.context.new_cloned() } } } -pub trait CheatcodeInspectorStrategy: Debug + Send + Sync + CheatcodeInspectorStrategyExt { +pub trait CheatcodeInspectorStrategyRunner: + Debug + Send + Sync + CheatcodeInspectorStrategyExt +{ fn name(&self) -> &'static str; - fn new_cloned(&self) -> Box; + fn new_cloned(&self) -> Box; /// Get nonce. fn get_nonce(&self, ccx: &mut CheatsCtxt, address: Address) -> Result { @@ -328,14 +342,14 @@ pub trait CheatcodeInspectorStrategyExt { } #[derive(Debug, Default, Clone)] -pub struct EvmCheatcodeInspectorStrategy {} +pub struct EvmCheatcodeInspectorStrategyRunner {} -impl CheatcodeInspectorStrategy for EvmCheatcodeInspectorStrategy { +impl CheatcodeInspectorStrategyRunner for EvmCheatcodeInspectorStrategyRunner { fn name(&self) -> &'static str { "evm" } - fn new_cloned(&self) -> Box { + fn new_cloned(&self) -> Box { Box::new(self.clone()) } @@ -411,13 +425,13 @@ impl CheatcodeInspectorStrategy for EvmCheatcodeInspectorStrategy { } } -impl CheatcodeInspectorStrategyExt for EvmCheatcodeInspectorStrategy {} +impl CheatcodeInspectorStrategyExt for EvmCheatcodeInspectorStrategyRunner {} -impl Clone for Box { +impl Clone for Box { fn clone(&self) -> Self { self.new_cloned() } } -struct _ObjectSafe0(dyn CheatcodeInspectorStrategy); +struct _ObjectSafe0(dyn CheatcodeInspectorStrategyRunner); struct _ObjectSafe1(dyn CheatcodeInspectorStrategyExt); diff --git a/crates/cheatcodes/src/test.rs b/crates/cheatcodes/src/test.rs index 9c2e811b3..ae59439fc 100644 --- a/crates/cheatcodes/src/test.rs +++ b/crates/cheatcodes/src/test.rs @@ -15,7 +15,7 @@ impl Cheatcode for zkVmCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { enable } = *self; - ccx.state.strategy.inner.zksync_cheatcode_select_zk_vm( + ccx.state.strategy.runner.zksync_cheatcode_select_zk_vm( ccx.state.strategy.context.as_mut(), ccx.ecx, enable, @@ -27,14 +27,14 @@ impl Cheatcode for zkVmCall { impl Cheatcode for zkVmSkipCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { - ccx.state.strategy.inner.zksync_cheatcode_skip_zkvm(ccx.state.strategy.context.as_mut()) + ccx.state.strategy.runner.zksync_cheatcode_skip_zkvm(ccx.state.strategy.context.as_mut()) } } impl Cheatcode for zkUsePaymasterCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { paymaster_address, paymaster_input } = self; - ccx.state.strategy.inner.zksync_cheatcode_set_paymaster( + ccx.state.strategy.runner.zksync_cheatcode_set_paymaster( ccx.state.strategy.context.as_mut(), *paymaster_address, paymaster_input, @@ -47,7 +47,7 @@ impl Cheatcode for zkUseFactoryDepCall { let Self { name } = self; ccx.state .strategy - .inner + .runner .zksync_cheatcode_use_factory_deps(ccx.state.strategy.context.as_mut(), name.clone()) } } @@ -63,7 +63,7 @@ impl Cheatcode for zkRegisterContractCall { zkDeployedBytecode, } = self; - ccx.state.strategy.inner.zksync_cheatcode_register_contract( + ccx.state.strategy.runner.zksync_cheatcode_register_contract( ccx.state.strategy.context.as_mut(), name.clone(), zkBytecodeHash.0.into(), diff --git a/crates/chisel/src/executor.rs b/crates/chisel/src/executor.rs index 285d55496..4ae9a0e18 100644 --- a/crates/chisel/src/executor.rs +++ b/crates/chisel/src/executor.rs @@ -323,7 +323,7 @@ impl SessionSource { Some(backend) => backend, None => { let fork = self.config.evm_opts.get_fork(&self.config.foundry_config, env.clone()); - let backend = Backend::spawn(fork, strategy.inner.new_backend_strategy()); + let backend = Backend::spawn(fork, strategy.runner.new_backend_strategy()); self.config.backend = Some(backend.clone()); backend } @@ -339,7 +339,7 @@ impl SessionSource { None, None, Some(self.solc.version.clone()), - strategy.inner.new_cheatcode_inspector_strategy(strategy.context.as_mut()), + strategy.runner.new_cheatcode_inspector_strategy(strategy.context.as_mut()), ) .into(), ) diff --git a/crates/cli/src/utils/mod.rs b/crates/cli/src/utils/mod.rs index e06ff934a..c7025e5d9 100644 --- a/crates/cli/src/utils/mod.rs +++ b/crates/cli/src/utils/mod.rs @@ -9,8 +9,8 @@ use foundry_common::{ shell, }; use foundry_config::{Chain, Config}; -use foundry_evm::executors::strategy::{new_evm_strategy, Strategy}; -use foundry_strategy_zksync::new_zkysnc_strategy; +use foundry_evm::executors::strategy::ExecutorStrategy; +use foundry_strategy_zksync::ZksyncExecutorStrategyBuilder; use serde::de::DeserializeOwned; use std::{ ffi::OsStr, @@ -93,13 +93,13 @@ pub fn get_provider(config: &Config) -> Result { get_provider_builder(config)?.build() } -pub fn get_executor_strategy(config: &Config) -> Strategy { +pub fn get_executor_strategy(config: &Config) -> ExecutorStrategy { if config.zksync.should_compile() { info!("using zksync strategy"); - new_zkysnc_strategy() + ExecutorStrategy::new_zksync() } else { info!("using evm strategy"); - new_evm_strategy() + ExecutorStrategy::new_evm() } } diff --git a/crates/evm/core/src/backend/cow.rs b/crates/evm/core/src/backend/cow.rs index f53b6ce15..1a38ec6e8 100644 --- a/crates/evm/core/src/backend/cow.rs +++ b/crates/evm/core/src/backend/cow.rs @@ -1,6 +1,6 @@ //! A wrapper around `Backend` that is clone-on-write used for fuzzing. -use super::{strategy::Strategy, BackendError, ForkInfo}; +use super::{strategy::BackendStrategy, BackendError, ForkInfo}; use crate::{ backend::{ diagnostic::RevertDiagnostic, Backend, DatabaseExt, LocalForkId, RevertStateSnapshotAction, @@ -92,7 +92,7 @@ impl DatabaseExt for CowBackend<'_> { self.backend.to_mut().get_fork_info(id) } - fn get_strategy(&mut self) -> &mut Strategy { + fn get_strategy(&mut self) -> &mut BackendStrategy { &mut self.backend.to_mut().strategy } diff --git a/crates/evm/core/src/backend/mod.rs b/crates/evm/core/src/backend/mod.rs index 4078e7736..b712f7c70 100644 --- a/crates/evm/core/src/backend/mod.rs +++ b/crates/evm/core/src/backend/mod.rs @@ -30,7 +30,7 @@ use std::{ collections::{BTreeMap, HashSet}, time::Instant, }; -use strategy::{BackendStrategyForkInfo, Strategy}; +use strategy::{BackendStrategy, BackendStrategyForkInfo}; mod diagnostic; pub use diagnostic::RevertDiagnostic; @@ -101,7 +101,7 @@ pub trait DatabaseExt: Database + DatabaseCommit { /// and the the fork environment. fn get_fork_info(&mut self, id: LocalForkId) -> eyre::Result; - fn get_strategy(&mut self) -> &mut Strategy; + fn get_strategy(&mut self) -> &mut BackendStrategy; /// Reverts the snapshot if it exists /// @@ -459,7 +459,7 @@ struct _ObjectSafe(dyn DatabaseExt); #[must_use] pub struct Backend { /// The behavior strategy. - pub strategy: Strategy, + pub strategy: BackendStrategy, /// The access point for managing forks forks: MultiFork, @@ -511,7 +511,7 @@ impl Backend { /// /// If `fork` is `Some` this will use a `fork` database, otherwise with an in-memory /// database. - pub fn spawn(fork: Option, strategy: Strategy) -> Self { + pub fn spawn(fork: Option, strategy: BackendStrategy) -> Self { Self::new(MultiFork::spawn(), fork, strategy) } @@ -521,7 +521,7 @@ impl Backend { /// database. /// /// Prefer using [`spawn`](Self::spawn) instead. - pub fn new(forks: MultiFork, fork: Option, strategy: Strategy) -> Self { + pub fn new(forks: MultiFork, fork: Option, strategy: BackendStrategy) -> Self { trace!(target: "backend", forking_mode=?fork.is_some(), "creating executor backend"); // Note: this will take of registering the `fork` let inner = BackendInner { @@ -560,7 +560,7 @@ impl Backend { /// Creates a new instance of `Backend` with fork added to the fork database and sets the fork /// as active pub(crate) fn new_with_fork( - strategy: Strategy, + strategy: BackendStrategy, id: &ForkId, fork: Fork, journaled_state: JournaledState, @@ -933,7 +933,7 @@ impl DatabaseExt for Backend { Ok(ForkInfo { fork_type, fork_env }) } - fn get_strategy(&mut self) -> &mut Strategy { + fn get_strategy(&mut self) -> &mut BackendStrategy { &mut self.strategy } @@ -1166,7 +1166,7 @@ impl DatabaseExt for Backend { let active_fork = self.active_fork_ids.map(|(_, idx)| self.inner.get_fork(idx)); // let active_fork = self.active_fork().cloned(); - self.strategy.inner.update_fork_db( + self.strategy.runner.update_fork_db( self.strategy.context.as_mut(), BackendStrategyForkInfo { active_fork, @@ -1226,7 +1226,7 @@ impl DatabaseExt for Backend { active.journaled_state.depth = journaled_state.depth; for addr in persistent_addrs { - self.strategy.inner.merge_journaled_state_data( + self.strategy.runner.merge_journaled_state_data( self.strategy.context.as_mut(), addr, journaled_state, @@ -1244,7 +1244,7 @@ impl DatabaseExt for Backend { for (addr, acc) in journaled_state.state.iter() { if acc.is_created() { if acc.is_touched() { - self.strategy.inner.merge_journaled_state_data( + self.strategy.runner.merge_journaled_state_data( self.strategy.context.as_mut(), *addr, journaled_state, @@ -1806,7 +1806,7 @@ impl BackendInner { pub fn roll_fork( &mut self, - strategy: &mut Strategy, + strategy: &mut BackendStrategy, id: LocalForkId, new_fork_id: ForkId, backend: SharedBackend, @@ -1818,7 +1818,7 @@ impl BackendInner { // we initialize a _new_ `ForkDB` but keep the state of persistent accounts let mut new_db = ForkDB::new(backend); for addr in self.persistent_accounts.iter().copied() { - strategy.inner.merge_db_account_data( + strategy.runner.merge_db_account_data( strategy.context.as_mut(), addr, &active.db, @@ -1936,7 +1936,7 @@ fn update_env_block(env: &mut Env, block: &AnyRpcBlock) { /// state, with an inspector. #[allow(clippy::too_many_arguments)] fn commit_transaction( - strategy: &mut Strategy, + strategy: &mut BackendStrategy, tx: &Transaction, mut env: EnvWithHandlerCfg, journaled_state: &mut JournaledState, @@ -2011,7 +2011,7 @@ fn apply_state_changeset( #[allow(clippy::needless_return)] mod tests { use crate::{ - backend::{strategy::new_evm_strategy, Backend}, + backend::{strategy::BackendStrategy, Backend}, fork::CreateFork, opts::EvmOpts, }; @@ -2045,7 +2045,7 @@ mod tests { evm_opts, }; - let backend = Backend::spawn(Some(fork), new_evm_strategy()); + let backend = Backend::spawn(Some(fork), BackendStrategy::new_evm()); // some rng contract from etherscan let address: Address = "63091244180ae240c87d1f528f5f269134cb07b3".parse().unwrap(); diff --git a/crates/evm/core/src/backend/strategy.rs b/crates/evm/core/src/backend/strategy.rs index b54eab781..1cdf78f33 100644 --- a/crates/evm/core/src/backend/strategy.rs +++ b/crates/evm/core/src/backend/strategy.rs @@ -11,9 +11,13 @@ pub struct BackendStrategyForkInfo<'a> { pub target_type: ForkType, } +/// Context for [BackendStrategyRunner]. pub trait BackendStrategyContext: Debug + Send + Sync + Any { + /// Clone the strategy context. fn new_cloned(&self) -> Box; + /// Alias as immutable reference of [Any]. fn as_any_ref(&self) -> &dyn Any; + /// Alias as mutable reference of [Any]. fn as_any_mut(&mut self) -> &mut dyn Any; } @@ -31,26 +35,32 @@ impl BackendStrategyContext for () { } } +/// Strategy for [super::Backend]. #[derive(Debug)] -pub struct Strategy { - pub inner: Box, +pub struct BackendStrategy { + /// Strategy runner. + pub runner: Box, + /// Strategy context. pub context: Box, } -pub fn new_evm_strategy() -> Strategy { - Strategy { inner: Box::new(EvmBackendStrategy), context: Box::new(()) } +impl BackendStrategy { + /// Create a new instance of [BackendStrategy] + pub fn new_evm() -> Self { + Self { runner: Box::new(EvmBackendStrategyRunner), context: Box::new(()) } + } } -impl Clone for Strategy { +impl Clone for BackendStrategy { fn clone(&self) -> Self { - Self { inner: self.inner.new_cloned(), context: self.context.new_cloned() } + Self { runner: self.runner.new_cloned(), context: self.context.new_cloned() } } } -pub trait BackendStrategy: Debug + Send + Sync + BackendStrategyExt { +pub trait BackendStrategyRunner: Debug + Send + Sync + BackendStrategyRunnerExt { fn name(&self) -> &'static str; - fn new_cloned(&self) -> Box; + fn new_cloned(&self) -> Box; /// When creating or switching forks, we update the AccountInfo of the contract fn update_fork_db( @@ -81,7 +91,7 @@ pub trait BackendStrategy: Debug + Send + Sync + BackendStrategyExt { ); } -pub trait BackendStrategyExt { +pub trait BackendStrategyRunnerExt { /// Saves the storage keys for immutable variables per address. /// /// These are required during fork to help merge the persisted addresses, as they are stored @@ -97,17 +107,17 @@ pub trait BackendStrategyExt { } } -struct _ObjectSafe(dyn BackendStrategy); +struct _ObjectSafe(dyn BackendStrategyRunner); #[derive(Debug, Default, Clone, Serialize, Deserialize)] -pub struct EvmBackendStrategy; +pub struct EvmBackendStrategyRunner; -impl BackendStrategy for EvmBackendStrategy { +impl BackendStrategyRunner for EvmBackendStrategyRunner { fn name(&self) -> &'static str { "evm" } - fn new_cloned(&self) -> Box { + fn new_cloned(&self) -> Box { Box::new(self.clone()) } @@ -154,9 +164,9 @@ impl BackendStrategy for EvmBackendStrategy { } } -impl BackendStrategyExt for EvmBackendStrategy {} +impl BackendStrategyRunnerExt for EvmBackendStrategyRunner {} -impl EvmBackendStrategy { +impl EvmBackendStrategyRunner { /// Merges the state of all `accounts` from the currently active db into the given `fork` pub(crate) fn update_fork_db_contracts( &self, @@ -258,7 +268,7 @@ impl EvmBackendMergeStrategy { } } -impl Clone for Box { +impl Clone for Box { fn clone(&self) -> Self { self.new_cloned() } diff --git a/crates/evm/evm/src/executors/builder.rs b/crates/evm/evm/src/executors/builder.rs index 3dc7009df..20ac319bb 100644 --- a/crates/evm/evm/src/executors/builder.rs +++ b/crates/evm/evm/src/executors/builder.rs @@ -2,7 +2,7 @@ use crate::{executors::Executor, inspectors::InspectorStackBuilder}; use foundry_evm_core::backend::Backend; use revm::primitives::{Env, EnvWithHandlerCfg, SpecId}; -use super::strategy::Strategy; +use super::strategy::ExecutorStrategy; /// The builder that allows to configure an evm [`Executor`] which a stack of optional /// [`revm::Inspector`]s, such as [`Cheatcodes`]. @@ -76,7 +76,7 @@ impl ExecutorBuilder { /// Builds the executor as configured. #[inline] - pub fn build(self, env: Env, db: Backend, strategy: Strategy) -> Executor { + pub fn build(self, env: Env, db: Backend, strategy: ExecutorStrategy) -> Executor { let Self { mut stack, gas_limit, spec_id, legacy_assertions } = self; if stack.block.is_none() { stack.block = Some(env.block.clone()); diff --git a/crates/evm/evm/src/executors/mod.rs b/crates/evm/evm/src/executors/mod.rs index 352148fc2..061f2ac11 100644 --- a/crates/evm/evm/src/executors/mod.rs +++ b/crates/evm/evm/src/executors/mod.rs @@ -37,7 +37,7 @@ use revm::{ }, }; use std::borrow::Cow; -use strategy::Strategy; +use strategy::ExecutorStrategy; mod builder; pub use builder::ExecutorBuilder; @@ -93,7 +93,7 @@ pub struct Executor { /// Whether `failed()` should be called on the test contract to determine if the test failed. legacy_assertions: bool, - strategy: Strategy, + strategy: ExecutorStrategy, } impl Clone for Executor { @@ -124,7 +124,7 @@ impl Executor { inspector: InspectorStack, gas_limit: u64, legacy_assertions: bool, - strategy: Strategy, + strategy: ExecutorStrategy, ) -> Self { // Need to create a non-empty contract on the cheatcodes address so `extcodesize` checks // do not fail. @@ -217,7 +217,7 @@ impl Executor { /// Set the balance of an account. pub fn set_balance(&mut self, address: Address, amount: U256) -> BackendResult<()> { trace!(?address, ?amount, "setting account balance"); - self.strategy.inner.clone().set_balance(self, address, amount) + self.strategy.runner.clone().set_balance(self, address, amount) } /// Gets the balance of an account @@ -227,7 +227,7 @@ impl Executor { /// Set the nonce of an account. pub fn set_nonce(&mut self, address: Address, nonce: u64) -> BackendResult<()> { - self.strategy.inner.clone().set_nonce(self, address, nonce) + self.strategy.runner.clone().set_nonce(self, address, nonce) } /// Returns the nonce of an account. @@ -260,7 +260,7 @@ impl Executor { #[inline] pub fn set_transaction_other_fields(&mut self, other_fields: OtherFields) { - self.strategy.inner.set_inspect_context(self.strategy.context.as_mut(), other_fields); + self.strategy.runner.set_inspect_context(self.strategy.context.as_mut(), other_fields); } /// Deploys a contract and commits the new state to the underlying database. @@ -443,7 +443,7 @@ impl Executor { backend.is_initialized = false; backend.spec_id = env.spec_id(); - let result = self.strategy.inner.call_inspect( + let result = self.strategy.runner.call_inspect( self.strategy.context.as_ref(), &mut backend, &mut env, @@ -465,7 +465,7 @@ impl Executor { let backend = &mut self.backend; backend.initialize(&env); - let result_and_state = self.strategy.inner.transact_inspect( + let result_and_state = self.strategy.runner.transact_inspect( self.strategy.context.as_mut(), backend, &mut env, diff --git a/crates/evm/evm/src/executors/strategy.rs b/crates/evm/evm/src/executors/strategy.rs index 2d5fcfd84..2a88deb3b 100644 --- a/crates/evm/evm/src/executors/strategy.rs +++ b/crates/evm/evm/src/executors/strategy.rs @@ -3,9 +3,11 @@ use std::{any::Any, fmt::Debug}; use alloy_primitives::{Address, U256}; use alloy_serde::OtherFields; use eyre::{Context, Result}; -use foundry_cheatcodes::strategy::EvmCheatcodeInspectorStrategy; +use foundry_cheatcodes::strategy::{ + CheatcodeInspectorStrategy, EvmCheatcodeInspectorStrategyRunner, +}; use foundry_evm_core::{ - backend::{BackendResult, DatabaseExt}, + backend::{strategy::BackendStrategy, BackendResult, DatabaseExt}, InspectorExt, }; use foundry_zksync_compiler::DualCompiledContracts; @@ -17,8 +19,11 @@ use revm::{ use super::Executor; pub trait ExecutorStrategyContext: Debug + Send + Sync + Any { + /// Clone the strategy context. fn new_cloned(&self) -> Box; + /// Alias as immutable reference of [Any]. fn as_any_ref(&self) -> &dyn Any; + /// Alias as mutable reference of [Any]. fn as_any_mut(&mut self) -> &mut dyn Any; } @@ -37,25 +42,29 @@ impl ExecutorStrategyContext for () { } #[derive(Debug)] -pub struct Strategy { - pub inner: Box, +pub struct ExecutorStrategy { + /// Strategy runner. + pub runner: Box, + /// Strategy context. pub context: Box, } -pub fn new_evm_strategy() -> Strategy { - Strategy { inner: Box::new(EvmExecutorStrategy::default()), context: Box::new(()) } +impl ExecutorStrategy { + pub fn new_evm() -> Self { + Self { runner: Box::new(EvmExecutorStrategyRunner::default()), context: Box::new(()) } + } } -impl Clone for Strategy { +impl Clone for ExecutorStrategy { fn clone(&self) -> Self { - Self { inner: self.inner.new_cloned(), context: self.context.new_cloned() } + Self { runner: self.runner.new_cloned(), context: self.context.new_cloned() } } } -pub trait ExecutorStrategy: Debug + Send + Sync + ExecutorStrategyExt { +pub trait ExecutorStrategyRunner: Debug + Send + Sync + ExecutorStrategyExt { fn name(&self) -> &'static str; - fn new_cloned(&self) -> Box; + fn new_cloned(&self) -> Box; fn set_balance( &self, @@ -86,16 +95,18 @@ pub trait ExecutorStrategy: Debug + Send + Sync + ExecutorStrategyExt { inspector: &mut dyn InspectorExt, ) -> eyre::Result; - fn new_backend_strategy(&self) -> foundry_evm_core::backend::strategy::Strategy; + fn new_backend_strategy(&self) -> BackendStrategy; fn new_cheatcode_inspector_strategy( &self, ctx: &dyn ExecutorStrategyContext, - ) -> foundry_cheatcodes::strategy::Strategy; + ) -> foundry_cheatcodes::strategy::CheatcodeInspectorStrategy; // TODO perhaps need to create fresh strategies as well } +/// Extended trait for ZKsync. pub trait ExecutorStrategyExt { + /// Set [DualCompiledContracts] on the context. fn zksync_set_dual_compiled_contracts( &self, _ctx: &mut dyn ExecutorStrategyContext, @@ -103,6 +114,7 @@ pub trait ExecutorStrategyExt { ) { } + /// Set the fork environment on the context. fn zksync_set_fork_env( &self, _ctx: &mut dyn ExecutorStrategyContext, @@ -113,15 +125,16 @@ pub trait ExecutorStrategyExt { } } +/// Implements [ExecutorStrategyRunner] for EVM. #[derive(Debug, Default, Clone)] -pub struct EvmExecutorStrategy {} +pub struct EvmExecutorStrategyRunner {} -impl ExecutorStrategy for EvmExecutorStrategy { +impl ExecutorStrategyRunner for EvmExecutorStrategyRunner { fn name(&self) -> &'static str { "evm" } - fn new_cloned(&self) -> Box { + fn new_cloned(&self) -> Box { Box::new(self.clone()) } @@ -201,24 +214,24 @@ impl ExecutorStrategy for EvmExecutorStrategy { Ok(()) } - fn new_backend_strategy(&self) -> foundry_evm_core::backend::strategy::Strategy { - foundry_evm_core::backend::strategy::new_evm_strategy() + fn new_backend_strategy(&self) -> BackendStrategy { + BackendStrategy::new_evm() } fn new_cheatcode_inspector_strategy( &self, _ctx: &dyn ExecutorStrategyContext, - ) -> foundry_cheatcodes::strategy::Strategy { - foundry_cheatcodes::strategy::Strategy { - inner: Box::new(EvmCheatcodeInspectorStrategy::default()), + ) -> CheatcodeInspectorStrategy { + CheatcodeInspectorStrategy { + runner: Box::new(EvmCheatcodeInspectorStrategyRunner::default()), context: Box::new(()), } } } -impl ExecutorStrategyExt for EvmExecutorStrategy {} +impl ExecutorStrategyExt for EvmExecutorStrategyRunner {} -impl Clone for Box { +impl Clone for Box { fn clone(&self) -> Self { self.new_cloned() } diff --git a/crates/evm/evm/src/executors/trace.rs b/crates/evm/evm/src/executors/trace.rs index be0be748e..1b523897d 100644 --- a/crates/evm/evm/src/executors/trace.rs +++ b/crates/evm/evm/src/executors/trace.rs @@ -6,7 +6,7 @@ use foundry_evm_traces::{InternalTraceMode, TraceMode}; use revm::primitives::{Env, SpecId}; use std::ops::{Deref, DerefMut}; -use super::strategy::Strategy; +use super::strategy::ExecutorStrategy; /// A default executor with tracing enabled pub struct TracingExecutor { @@ -21,9 +21,9 @@ impl TracingExecutor { debug: bool, decode_internal: bool, alphanet: bool, - strategy: Strategy, + strategy: ExecutorStrategy, ) -> Self { - let db = Backend::spawn(fork, strategy.inner.new_backend_strategy()); + let db = Backend::spawn(fork, strategy.runner.new_backend_strategy()); let trace_mode = TraceMode::Call.with_debug(debug).with_decode_internal(if decode_internal { InternalTraceMode::Full diff --git a/crates/forge/bin/cmd/test/mod.rs b/crates/forge/bin/cmd/test/mod.rs index 96335bdc7..425c82598 100644 --- a/crates/forge/bin/cmd/test/mod.rs +++ b/crates/forge/bin/cmd/test/mod.rs @@ -368,7 +368,7 @@ impl TestArgs { // Prepare the test builder. let config = Arc::new(config); - strategy.inner.zksync_set_dual_compiled_contracts( + strategy.runner.zksync_set_dual_compiled_contracts( strategy.context.as_mut(), dual_compiled_contracts.unwrap_or_default(), ); diff --git a/crates/forge/src/multi_runner.rs b/crates/forge/src/multi_runner.rs index c716318da..0c9c7731b 100644 --- a/crates/forge/src/multi_runner.rs +++ b/crates/forge/src/multi_runner.rs @@ -18,7 +18,7 @@ use foundry_config::Config; use foundry_evm::{ backend::Backend, decode::RevertDecoder, - executors::{strategy::Strategy, ExecutorBuilder}, + executors::{strategy::ExecutorStrategy, ExecutorBuilder}, fork::CreateFork, inspectors::CheatsConfig, opts::EvmOpts, @@ -85,7 +85,7 @@ pub struct MultiContractRunner { /// Library addresses used to link contracts. pub libraries: Libraries, /// Execution strategy. - pub strategy: Strategy, + pub strategy: ExecutorStrategy, } impl MultiContractRunner { @@ -178,7 +178,7 @@ impl MultiContractRunner { trace!("running all tests"); // The DB backend that serves all the data. - let db = Backend::spawn(self.fork.take(), self.strategy.inner.new_backend_strategy()); + let db = Backend::spawn(self.fork.take(), self.strategy.runner.new_backend_strategy()); let find_timer = Instant::now(); let contracts = self.matching_contracts(filter).collect::>(); @@ -250,7 +250,7 @@ impl MultiContractRunner { Some(self.known_contracts.clone()), Some(artifact_id.name.clone()), Some(artifact_id.version.clone()), - self.strategy.inner.new_cheatcode_inspector_strategy(self.strategy.context.as_ref()), + self.strategy.runner.new_cheatcode_inspector_strategy(self.strategy.context.as_ref()), ); let trace_mode = TraceMode::default() @@ -407,7 +407,7 @@ impl MultiContractRunnerBuilder { zk_output: Option, env: revm::primitives::Env, evm_opts: EvmOpts, - strategy: Strategy, + strategy: ExecutorStrategy, ) -> Result { let mut known_contracts = ContractsByArtifact::default(); let output = output.with_stripped_file_prefixes(root); diff --git a/crates/forge/src/runner.rs b/crates/forge/src/runner.rs index 5f29c02d4..745e0c2a2 100644 --- a/crates/forge/src/runner.rs +++ b/crates/forge/src/runner.rs @@ -151,7 +151,7 @@ impl ContractRunner<'_> { // nonce. if let Some(cheatcodes) = &mut self.executor.inspector.cheatcodes { debug!("test contract deployed"); - cheatcodes.strategy.inner.base_contract_deployed(cheatcodes.strategy.context.as_mut()); + cheatcodes.strategy.runner.base_contract_deployed(cheatcodes.strategy.context.as_mut()); } // Optionally call the `setUp` function diff --git a/crates/forge/tests/it/test_helpers.rs b/crates/forge/tests/it/test_helpers.rs index beb7e4f88..3446b8ec1 100644 --- a/crates/forge/tests/it/test_helpers.rs +++ b/crates/forge/tests/it/test_helpers.rs @@ -361,7 +361,7 @@ impl ForgeTestData { let mut strategy = utils::get_executor_strategy(&zk_config); strategy - .inner + .runner .zksync_set_dual_compiled_contracts(strategy.context.as_mut(), dual_compiled_contracts); let mut builder = self.base_runner(); builder.config = Arc::new(zk_config); diff --git a/crates/script/src/lib.rs b/crates/script/src/lib.rs index 80d437744..169aa7172 100644 --- a/crates/script/src/lib.rs +++ b/crates/script/src/lib.rs @@ -598,7 +598,7 @@ impl ScriptConfig { Some(db) => db.clone(), None => { let fork = self.evm_opts.get_fork(&self.config, env.clone()); - let backend = Backend::spawn(fork, strategy.inner.new_backend_strategy()); + let backend = Backend::spawn(fork, strategy.runner.new_backend_strategy()); self.backends.insert(fork_url.clone(), backend.clone()); backend } @@ -607,7 +607,7 @@ impl ScriptConfig { // It's only really `None`, when we don't pass any `--fork-url`. And if so, there is // no need to cache it, since there won't be any onchain simulation that we'd need // to cache the backend for. - Backend::spawn(None, strategy.inner.new_backend_strategy()) + Backend::spawn(None, strategy.runner.new_backend_strategy()) }; // We need to enable tracing to decode contract names: local or external. @@ -624,13 +624,13 @@ impl ScriptConfig { if let Some((known_contracts, script_wallets, target, dual_compiled_contracts)) = cheats_data { - strategy.inner.zksync_set_dual_compiled_contracts( + strategy.runner.zksync_set_dual_compiled_contracts( strategy.context.as_mut(), dual_compiled_contracts, ); if let Some(fork_url) = &self.evm_opts.fork_url { - strategy.inner.zksync_set_fork_env(strategy.context.as_mut(), fork_url, &env)?; + strategy.runner.zksync_set_fork_env(strategy.context.as_mut(), fork_url, &env)?; } builder = builder.inspectors(|stack| { @@ -643,7 +643,7 @@ impl ScriptConfig { Some(target.name), Some(target.version), strategy - .inner + .runner .new_cheatcode_inspector_strategy(strategy.context.as_ref()), ) .into(), diff --git a/crates/script/src/runner.rs b/crates/script/src/runner.rs index cb87bffc8..22b26446d 100644 --- a/crates/script/src/runner.rs +++ b/crates/script/src/runner.rs @@ -174,7 +174,7 @@ impl ScriptRunner { // nonce. if let Some(cheatcodes) = &mut self.executor.inspector.cheatcodes { debug!("script deployed"); - cheatcodes.strategy.inner.base_contract_deployed(cheatcodes.strategy.context.as_mut()); + cheatcodes.strategy.runner.base_contract_deployed(cheatcodes.strategy.context.as_mut()); } // Optionally call the `setUp` function diff --git a/crates/strategy/zksync/src/backend.rs b/crates/strategy/zksync/src/backend.rs index 9ab91be12..76a9286ea 100644 --- a/crates/strategy/zksync/src/backend.rs +++ b/crates/strategy/zksync/src/backend.rs @@ -1,10 +1,13 @@ use std::{any::Any, collections::hash_map::Entry}; use alloy_primitives::{map::HashMap, Address, U256}; -use foundry_evm::backend::strategy::{BackendStrategyContext, BackendStrategyExt}; +use foundry_evm::backend::strategy::{ + BackendStrategy, BackendStrategyContext, BackendStrategyRunnerExt, +}; use foundry_evm_core::backend::{ strategy::{ - BackendStrategy, BackendStrategyForkInfo, EvmBackendMergeStrategy, EvmBackendStrategy, + BackendStrategyForkInfo, BackendStrategyRunner, EvmBackendMergeStrategy, + EvmBackendStrategyRunner, }, BackendInner, Fork, ForkDB, FoundryEvmInMemoryDB, }; @@ -17,6 +20,7 @@ use revm::{db::CacheDB, primitives::HashSet, DatabaseRef, JournaledState}; use serde::{Deserialize, Serialize}; use tracing::trace; +/// Context for [ZksyncBackendStrategyRunner]. #[derive(Debug, Default, Clone, Serialize, Deserialize)] pub struct ZksyncBackendStrategyContext { /// Store storage keys per contract address for immutable variables. @@ -37,32 +41,18 @@ impl BackendStrategyContext for ZksyncBackendStrategyContext { } } +/// ZKsync implementation for [BackendStrategyRunner]. #[derive(Debug, Default, Clone, Serialize, Deserialize)] -pub struct ZksyncBackendStrategy { - evm: EvmBackendStrategy, -} - -#[derive(Debug, Default, Clone, Serialize, Deserialize)] -pub struct ZkBackendInspectData { - #[serde(skip_serializing_if = "Option::is_none")] - pub factory_deps: Option>>, - - #[serde(skip_serializing_if = "Option::is_none")] - pub paymaster_data: Option, - - pub use_evm: bool, -} - -fn get_context(ctx: &mut dyn BackendStrategyContext) -> &mut ZksyncBackendStrategyContext { - ctx.as_any_mut().downcast_mut().expect("expected ZksyncBackendStrategyContext") +pub struct ZksyncBackendStrategyRunner { + evm: EvmBackendStrategyRunner, } -impl BackendStrategy for ZksyncBackendStrategy { +impl BackendStrategyRunner for ZksyncBackendStrategyRunner { fn name(&self) -> &'static str { "zk" } - fn new_cloned(&self) -> Box { + fn new_cloned(&self) -> Box { Box::new(self.clone()) } @@ -126,7 +116,7 @@ impl BackendStrategy for ZksyncBackendStrategy { } } -impl ZksyncBackendStrategy { +impl ZksyncBackendStrategyRunner { /// Merges the state of all `accounts` from the currently active db into the given `fork` pub(crate) fn update_fork_db_contracts( &self, @@ -168,7 +158,7 @@ impl ZksyncBackendStrategy { } } -impl BackendStrategyExt for ZksyncBackendStrategy { +impl BackendStrategyRunnerExt for ZksyncBackendStrategyRunner { fn zksync_save_immutable_storage( &self, ctx: &mut dyn BackendStrategyContext, @@ -183,6 +173,21 @@ impl BackendStrategyExt for ZksyncBackendStrategy { } } +/// Create ZKsync strategy for [BackendStrategy]. +pub trait ZksyncBackendStrategyBuilder { + /// Create new zksync strategy. + fn new_zksync() -> Self; +} + +impl ZksyncBackendStrategyBuilder for BackendStrategy { + fn new_zksync() -> Self { + Self { + runner: Box::new(ZksyncBackendStrategyRunner::default()), + context: Box::new(ZksyncBackendStrategyContext::default()), + } + } +} + pub(crate) struct ZksyncBackendMerge; /// Defines the zksync specific state to help during merge. @@ -359,3 +364,7 @@ impl ZksyncBackendMerge { } } } + +fn get_context(ctx: &mut dyn BackendStrategyContext) -> &mut ZksyncBackendStrategyContext { + ctx.as_any_mut().downcast_mut().expect("expected ZksyncBackendStrategyContext") +} diff --git a/crates/strategy/zksync/src/cheatcode.rs b/crates/strategy/zksync/src/cheatcode.rs index f8efc80c5..08e6b886e 100644 --- a/crates/strategy/zksync/src/cheatcode.rs +++ b/crates/strategy/zksync/src/cheatcode.rs @@ -11,7 +11,8 @@ use foundry_cheatcodes::{ journaled_account, make_acc_non_empty, strategy::{ CheatcodeInspectorStrategy, CheatcodeInspectorStrategyContext, - CheatcodeInspectorStrategyExt, EvmCheatcodeInspectorStrategy, + CheatcodeInspectorStrategyExt, CheatcodeInspectorStrategyRunner, + EvmCheatcodeInspectorStrategyRunner, }, Broadcast, BroadcastableTransaction, BroadcastableTransactions, Cheatcodes, CheatcodesExecutor, CheatsConfig, CheatsCtxt, CommonCreateInput, DealRecord, Ecx, Error, InnerEcx, Result, Vm, @@ -81,11 +82,13 @@ macro_rules! bail { }; } +/// ZKsync implementation for [CheatcodeInspectorStrategyRunner]. #[derive(Debug, Default, Clone)] -pub struct ZksyncCheatcodeInspectorStrategy { - evm: EvmCheatcodeInspectorStrategy, +pub struct ZksyncCheatcodeInspectorStrategyRunner { + evm: EvmCheatcodeInspectorStrategyRunner, } +/// Context for [ZksyncCheatcodeInspectorStrategyRunner]. #[derive(Debug, Default, Clone)] pub struct ZksyncCheatcodeInspectorStrategyContext { pub using_zk_vm: bool, @@ -202,18 +205,6 @@ impl CheatcodeInspectorStrategyContext for ZksyncCheatcodeInspectorStrategyConte } } -fn get_context( - ctx: &mut dyn CheatcodeInspectorStrategyContext, -) -> &mut ZksyncCheatcodeInspectorStrategyContext { - ctx.as_any_mut().downcast_mut().expect("expected ZksyncCheatcodeInspectorStrategyContext") -} - -fn get_context_ref( - ctx: &dyn CheatcodeInspectorStrategyContext, -) -> &ZksyncCheatcodeInspectorStrategyContext { - ctx.as_any_ref().downcast_ref().expect("expected ZksyncCheatcodeInspectorStrategyContext") -} - /// Allows overriding nonce update behavior for the tx caller in the zkEVM. /// /// Since each CREATE or CALL is executed as a separate transaction within zkEVM, we currently skip @@ -247,12 +238,12 @@ impl ZkPersistNonceUpdate { } } -impl CheatcodeInspectorStrategy for ZksyncCheatcodeInspectorStrategy { +impl CheatcodeInspectorStrategyRunner for ZksyncCheatcodeInspectorStrategyRunner { fn name(&self) -> &'static str { "zk" } - fn new_cloned(&self) -> Box { + fn new_cloned(&self) -> Box { Box::new(self.clone()) } @@ -753,7 +744,7 @@ impl CheatcodeInspectorStrategy for ZksyncCheatcodeInspectorStrategy { } } -impl CheatcodeInspectorStrategyExt for ZksyncCheatcodeInspectorStrategy { +impl CheatcodeInspectorStrategyExt for ZksyncCheatcodeInspectorStrategyRunner { fn zksync_cheatcode_skip_zkvm( &self, ctx: &mut dyn CheatcodeInspectorStrategyContext, @@ -1045,7 +1036,7 @@ impl CheatcodeInspectorStrategyExt for ZksyncCheatcodeInspectorStrategy { }) .collect::>(); let strategy = ecx.db.get_strategy(); - strategy.inner.zksync_save_immutable_storage( + strategy.runner.zksync_save_immutable_storage( strategy.context.as_mut(), addr, keys, @@ -1297,7 +1288,7 @@ impl CheatcodeInspectorStrategyExt for ZksyncCheatcodeInspectorStrategy { } } -impl ZksyncCheatcodeInspectorStrategy { +impl ZksyncCheatcodeInspectorStrategyRunner { /// Selects the appropriate VM for the fork. Options: EVM, ZK-VM. /// CALL and CREATE are handled by the selected VM. /// @@ -1506,6 +1497,58 @@ impl ZksyncCheatcodeInspectorStrategy { } } +/// Setting for migrating the database to zkEVM storage when starting in ZKsync mode. +/// The migration is performed on the DB via the inspector so must only be performed once. +#[derive(Debug, Default, Clone)] +pub enum ZkStartupMigration { + /// Defer database migration to a later execution point. + /// + /// This is required as we need to wait for some baseline deployments + /// to occur before the test/script execution is performed. + #[default] + Defer, + /// Allow database migration. + Allow, + /// Database migration has already been performed. + Done, +} + +impl ZkStartupMigration { + /// Check if startup migration is allowed. Migration is disallowed if it's to be deferred or has + /// already been performed. + pub fn is_allowed(&self) -> bool { + matches!(self, Self::Allow) + } + + /// Allow migrating the the DB to zkEVM storage. + pub fn allow(&mut self) { + *self = Self::Allow + } + + /// Mark the migration as completed. It must not be performed again. + pub fn done(&mut self) { + *self = Self::Done + } +} + +/// Create ZKsync strategy for [CheatcodeInspectorStrategy]. +pub trait ZksyncCheatcodeInspectorStrategyBuilder { + /// Create new ZKsync strategy. + fn new_zksync(dual_compiled_contracts: DualCompiledContracts, zk_env: ZkEnv) -> Self; +} + +impl ZksyncCheatcodeInspectorStrategyBuilder for CheatcodeInspectorStrategy { + fn new_zksync(dual_compiled_contracts: DualCompiledContracts, zk_env: ZkEnv) -> Self { + Self { + runner: Box::new(ZksyncCheatcodeInspectorStrategyRunner::default()), + context: Box::new(ZksyncCheatcodeInspectorStrategyContext::new( + dual_compiled_contracts, + zk_env, + )), + } + } +} + fn get_artifact_code( dual_compiled_contracts: &DualCompiledContracts, using_zk_vm: bool, @@ -1637,36 +1680,14 @@ fn get_artifact_code( maybe_bytecode.ok_or_else(|| fmt_err!("no bytecode for contract; is it abstract or unlinked?")) } -/// Setting for migrating the database to zkEVM storage when starting in ZKsync mode. -/// The migration is performed on the DB via the inspector so must only be performed once. -#[derive(Debug, Default, Clone)] -pub enum ZkStartupMigration { - /// Defer database migration to a later execution point. - /// - /// This is required as we need to wait for some baseline deployments - /// to occur before the test/script execution is performed. - #[default] - Defer, - /// Allow database migration. - Allow, - /// Database migration has already been performed. - Done, +fn get_context( + ctx: &mut dyn CheatcodeInspectorStrategyContext, +) -> &mut ZksyncCheatcodeInspectorStrategyContext { + ctx.as_any_mut().downcast_mut().expect("expected ZksyncCheatcodeInspectorStrategyContext") } -impl ZkStartupMigration { - /// Check if startup migration is allowed. Migration is disallowed if it's to be deferred or has - /// already been performed. - pub fn is_allowed(&self) -> bool { - matches!(self, Self::Allow) - } - - /// Allow migrating the the DB to zkEVM storage. - pub fn allow(&mut self) { - *self = Self::Allow - } - - /// Mark the migration as completed. It must not be performed again. - pub fn done(&mut self) { - *self = Self::Done - } +fn get_context_ref( + ctx: &dyn CheatcodeInspectorStrategyContext, +) -> &ZksyncCheatcodeInspectorStrategyContext { + ctx.as_any_ref().downcast_ref().expect("expected ZksyncCheatcodeInspectorStrategyContext") } diff --git a/crates/strategy/zksync/src/executor.rs b/crates/strategy/zksync/src/executor.rs index 824080792..191ec4145 100644 --- a/crates/strategy/zksync/src/executor.rs +++ b/crates/strategy/zksync/src/executor.rs @@ -7,7 +7,8 @@ use foundry_evm::{ backend::{BackendResult, DatabaseExt}, executors::{ strategy::{ - EvmExecutorStrategy, ExecutorStrategy, ExecutorStrategyContext, ExecutorStrategyExt, + EvmExecutorStrategyRunner, ExecutorStrategy, ExecutorStrategyContext, + ExecutorStrategyExt, ExecutorStrategyRunner, }, Executor, }, @@ -22,11 +23,11 @@ use revm::{ use zksync_types::H256; use crate::{ - backend::ZksyncBackendStrategyContext, - cheatcode::{ZksyncCheatcodeInspectorStrategyContext, ZKSYNC_TRANSACTION_OTHER_FIELDS_KEY}, - ZksyncBackendStrategy, ZksyncCheatcodeInspectorStrategy, + backend::ZksyncBackendStrategyBuilder, + cheatcode::{ZksyncCheatcodeInspectorStrategyBuilder, ZKSYNC_TRANSACTION_OTHER_FIELDS_KEY}, }; +/// Defines the context for [ZksyncExecutorStrategyRunner]. #[derive(Debug, Default, Clone)] pub struct ZksyncExecutorStrategyContext { inspect_context: Option, @@ -49,9 +50,10 @@ impl ExecutorStrategyContext for ZksyncExecutorStrategyContext { } } +/// Defines the [ExecutorStrategyRunner] strategy for ZKsync. #[derive(Debug, Default, Clone)] -pub struct ZksyncExecutorStrategy { - evm: EvmExecutorStrategy, +pub struct ZksyncExecutorStrategyRunner { + evm: EvmExecutorStrategyRunner, } fn get_context_ref(ctx: &dyn ExecutorStrategyContext) -> &ZksyncExecutorStrategyContext { @@ -62,12 +64,12 @@ fn get_context(ctx: &mut dyn ExecutorStrategyContext) -> &mut ZksyncExecutorStra ctx.as_any_mut().downcast_mut().expect("expected ZksyncExecutorStrategyContext") } -impl ExecutorStrategy for ZksyncExecutorStrategy { +impl ExecutorStrategyRunner for ZksyncExecutorStrategyRunner { fn name(&self) -> &'static str { "zk" } - fn new_cloned(&self) -> Box { + fn new_cloned(&self) -> Box { Box::new(self.clone()) } @@ -114,25 +116,19 @@ impl ExecutorStrategy for ZksyncExecutorStrategy { Ok(()) } - fn new_backend_strategy(&self) -> foundry_evm_core::backend::strategy::Strategy { - foundry_evm_core::backend::strategy::Strategy { - inner: Box::new(ZksyncBackendStrategy::default()), - context: Box::new(ZksyncBackendStrategyContext::default()), - } + fn new_backend_strategy(&self) -> foundry_evm_core::backend::strategy::BackendStrategy { + foundry_evm_core::backend::strategy::BackendStrategy::new_zksync() } fn new_cheatcode_inspector_strategy( &self, ctx: &dyn ExecutorStrategyContext, - ) -> foundry_cheatcodes::strategy::Strategy { + ) -> foundry_cheatcodes::strategy::CheatcodeInspectorStrategy { let ctx = get_context_ref(ctx); - foundry_cheatcodes::strategy::Strategy { - inner: Box::new(ZksyncCheatcodeInspectorStrategy::default()), - context: Box::new(ZksyncCheatcodeInspectorStrategyContext::new( - ctx.dual_compiled_contracts.clone(), - ctx.zk_env.clone(), - )), - } + foundry_cheatcodes::strategy::CheatcodeInspectorStrategy::new_zksync( + ctx.dual_compiled_contracts.clone(), + ctx.zk_env.clone(), + ) } fn call_inspect( @@ -187,7 +183,7 @@ impl ExecutorStrategy for ZksyncExecutorStrategy { } } -impl ExecutorStrategyExt for ZksyncExecutorStrategy { +impl ExecutorStrategyExt for ZksyncExecutorStrategyRunner { fn zksync_set_dual_compiled_contracts( &self, ctx: &mut dyn ExecutorStrategyContext, @@ -239,7 +235,7 @@ impl ExecutorStrategyExt for ZksyncExecutorStrategy { } } -/// Retrieve metadata for zksync tx +/// Retrieve metadata for ZKsync tx. pub fn get_zksync_transaction_metadata( other_fields: &OtherFields, ) -> Option { @@ -250,9 +246,17 @@ pub fn get_zksync_transaction_metadata( .flatten() } -pub fn new_zkysnc_strategy() -> foundry_evm::executors::strategy::Strategy { - foundry_evm::executors::strategy::Strategy { - inner: Box::new(ZksyncExecutorStrategy::default()), - context: Box::new(ZksyncExecutorStrategyContext::default()), +/// Create ZKsync strategy for [ExecutorStrategy]. +pub trait ZksyncExecutorStrategyBuilder { + /// Create new zksync strategy. + fn new_zksync() -> Self; +} + +impl ZksyncExecutorStrategyBuilder for ExecutorStrategy { + fn new_zksync() -> Self { + Self { + runner: Box::new(ZksyncExecutorStrategyRunner::default()), + context: Box::new(ZksyncExecutorStrategyContext::default()), + } } } diff --git a/crates/strategy/zksync/src/lib.rs b/crates/strategy/zksync/src/lib.rs index 8018e89be..344979a45 100644 --- a/crates/strategy/zksync/src/lib.rs +++ b/crates/strategy/zksync/src/lib.rs @@ -9,6 +9,8 @@ mod backend; mod cheatcode; mod executor; -pub use backend::ZksyncBackendStrategy; -pub use cheatcode::ZksyncCheatcodeInspectorStrategy; -pub use executor::{get_zksync_transaction_metadata, new_zkysnc_strategy, ZksyncExecutorStrategy}; +pub use backend::ZksyncBackendStrategyRunner; +pub use cheatcode::ZksyncCheatcodeInspectorStrategyRunner; +pub use executor::{ + get_zksync_transaction_metadata, ZksyncExecutorStrategyBuilder, ZksyncExecutorStrategyRunner, +}; diff --git a/crates/verify/src/utils.rs b/crates/verify/src/utils.rs index 60ba29715..cf83c0196 100644 --- a/crates/verify/src/utils.rs +++ b/crates/verify/src/utils.rs @@ -14,7 +14,7 @@ use foundry_compilers::artifacts::{BytecodeHash, CompactContractBytecode, EvmVer use foundry_config::Config; use foundry_evm::{ constants::DEFAULT_CREATE2_DEPLOYER, - executors::{strategy::Strategy, TracingExecutor}, + executors::{strategy::ExecutorStrategy, TracingExecutor}, opts::EvmOpts, }; use reqwest::Url; @@ -325,7 +325,7 @@ pub async fn get_tracing_executor( fork_blk_num: u64, evm_version: EvmVersion, evm_opts: EvmOpts, - strategy: Strategy, + strategy: ExecutorStrategy, ) -> Result<(Env, TracingExecutor)> { fork_config.fork_block_number = Some(fork_blk_num); fork_config.evm_version = evm_version;