diff --git a/crates/cheatcodes/src/config.rs b/crates/cheatcodes/src/config.rs index b2d00193e..5eb4fe0d0 100644 --- a/crates/cheatcodes/src/config.rs +++ b/crates/cheatcodes/src/config.rs @@ -14,7 +14,6 @@ use foundry_evm_core::opts::EvmOpts; use semver::Version; use std::{ path::{Path, PathBuf}, - sync::{Arc, Mutex}, time::Duration, }; @@ -58,7 +57,7 @@ pub struct CheatsConfig { /// Version of the script/test contract which is currently running. pub running_version: Option, /// The behavior strategy. - pub strategy: Arc>, + pub strategy: Box, /// Whether to enable legacy (non-reverting) assertions. pub assertions_revert: bool, /// Optional seed for the RNG algorithm. @@ -74,7 +73,7 @@ impl CheatsConfig { available_artifacts: Option, running_contract: Option, running_version: Option, - strategy: Arc>, + strategy: Box, ) -> Self { let mut allowed_paths = vec![config.root.0.clone()]; allowed_paths.extend(config.libs.clone()); @@ -235,7 +234,7 @@ impl Default for CheatsConfig { available_artifacts: Default::default(), running_contract: Default::default(), running_version: Default::default(), - strategy: Arc::new(Mutex::new(EvmCheatcodeInspectorStrategy::default())), + strategy: Box::new(EvmCheatcodeInspectorStrategy::default()), assertions_revert: true, seed: None, } @@ -254,7 +253,7 @@ mod tests { None, None, None, - Arc::new(Mutex::new(EvmCheatcodeInspectorStrategy::default())), + Box::new(EvmCheatcodeInspectorStrategy::default()), ) } diff --git a/crates/cheatcodes/src/evm.rs b/crates/cheatcodes/src/evm.rs index 31e69820e..0b3b574ca 100644 --- a/crates/cheatcodes/src/evm.rs +++ b/crates/cheatcodes/src/evm.rs @@ -64,9 +64,7 @@ impl Cheatcode for getNonce_0Call { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { account } = self; - let strategy = ccx.state.strategy.clone(); - let mut guard = strategy.lock().expect("failed acquiring strategy"); - guard.cheatcode_get_nonce(ccx, *account) + ccx.with_strategy(|strategy, ccx| strategy.cheatcode_get_nonce(ccx, *account)) } } @@ -352,9 +350,7 @@ impl Cheatcode for getBlobhashesCall { impl Cheatcode for rollCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { newHeight } = self; - let strategy = ccx.state.strategy.clone(); - let mut guard = strategy.lock().expect("failed acquiring strategy"); - guard.cheatcode_roll(ccx, *newHeight) + ccx.with_strategy(|strategy, ccx| strategy.cheatcode_roll(ccx, *newHeight)) } } @@ -376,9 +372,7 @@ impl Cheatcode for txGasPriceCall { impl Cheatcode for warpCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { newTimestamp } = self; - let strategy = ccx.state.strategy.clone(); - let mut guard = strategy.lock().expect("failed acquiring strategy"); - guard.cheatcode_warp(ccx, *newTimestamp) + ccx.with_strategy(|strategy, ccx| strategy.cheatcode_warp(ccx, *newTimestamp)) } } @@ -413,9 +407,7 @@ impl Cheatcode for dealCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { account: address, newBalance: new_balance } = *self; - let strategy = ccx.state.strategy.clone(); - let mut guard = strategy.lock().expect("failed acquiring strategy"); - guard.cheatcode_deal(ccx, address, new_balance) + ccx.with_strategy(|strategy, ccx| strategy.cheatcode_deal(ccx, address, new_balance)) } } @@ -423,18 +415,14 @@ impl Cheatcode for etchCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { target, newRuntimeBytecode } = self; - let strategy = ccx.state.strategy.clone(); - let mut guard = strategy.lock().expect("failed acquiring strategy"); - guard.cheatcode_etch(ccx, *target, newRuntimeBytecode) + ccx.with_strategy(|strategy, ccx| strategy.cheatcode_etch(ccx, *target, newRuntimeBytecode)) } } impl Cheatcode for resetNonceCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { account } = self; - let strategy = ccx.state.strategy.clone(); - let mut guard = strategy.lock().expect("failed acquiring strategy"); - guard.cheatcode_reset_nonce(ccx, *account) + ccx.with_strategy(|strategy, ccx| strategy.cheatcode_reset_nonce(ccx, *account)) } } @@ -442,9 +430,7 @@ impl Cheatcode for setNonceCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { account, newNonce } = *self; - let strategy = ccx.state.strategy.clone(); - let mut guard = strategy.lock().expect("failed acquiring strategy"); - guard.cheatcode_set_nonce(ccx, account, newNonce) + ccx.with_strategy(|strategy, ccx| strategy.cheatcode_set_nonce(ccx, account, newNonce)) } } @@ -452,9 +438,9 @@ impl Cheatcode for setNonceUnsafeCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { account, newNonce } = *self; - let strategy = ccx.state.strategy.clone(); - let mut guard = strategy.lock().expect("failed acquiring strategy"); - guard.cheatcode_set_nonce_unsafe(ccx, account, newNonce) + ccx.with_strategy(|strategy, ccx| { + strategy.cheatcode_set_nonce_unsafe(ccx, account, newNonce) + }) } } diff --git a/crates/cheatcodes/src/evm/fork.rs b/crates/cheatcodes/src/evm/fork.rs index 0ad227f66..17bb9bacf 100644 --- a/crates/cheatcodes/src/evm/fork.rs +++ b/crates/cheatcodes/src/evm/fork.rs @@ -125,11 +125,7 @@ impl Cheatcode for selectForkCall { persist_caller(ccx); check_broadcast(ccx.state)?; - ccx.state - .strategy - .lock() - .expect("failed acquiring strategy") - .zksync_select_fork_vm(ccx.ecx, *forkId); + ccx.with_strategy(|strategy, ccx| strategy.zksync_select_fork_vm(ccx.ecx, *forkId)); ccx.ecx.db.select_fork(*forkId, &mut ccx.ecx.env, &mut ccx.ecx.journaled_state)?; Ok(Default::default()) @@ -285,11 +281,7 @@ fn create_select_fork(ccx: &mut CheatsCtxt, url_or_alias: &str, block: Option Result { let Self { callee, data, returnData } = self; - let strategy = ccx.state.strategy.clone(); - let mut guard = strategy.lock().expect("failed acquiring strategy"); - guard.cheatcode_mock_call(ccx, *callee, data, returnData) + ccx.with_strategy(|strategy, ccx| { + strategy.cheatcode_mock_call(ccx, *callee, data, returnData) + }) } } @@ -85,9 +85,9 @@ impl Cheatcode for mockCalls_1Call { impl Cheatcode for mockCallRevert_0Call { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { callee, data, revertData } = self; - let strategy = ccx.state.strategy.clone(); - let mut guard = strategy.lock().expect("failed acquiring strategy"); - guard.cheatcode_mock_call_revert(ccx, *callee, data, revertData) + ccx.with_strategy(|strategy, ccx| { + strategy.cheatcode_mock_call_revert(ccx, *callee, data, revertData) + }) } } diff --git a/crates/cheatcodes/src/fs.rs b/crates/cheatcodes/src/fs.rs index 7ac271664..c70133a76 100644 --- a/crates/cheatcodes/src/fs.rs +++ b/crates/cheatcodes/src/fs.rs @@ -283,9 +283,7 @@ impl Cheatcode for getArtifactPathByDeployedCodeCall { impl Cheatcode for getCodeCall { fn apply(&self, state: &mut Cheatcodes) -> Result { let Self { artifactPath: path } = self; - let strategy = state.strategy.clone(); - let guard = strategy.lock().expect("failed acquiring strategy"); - guard.get_artifact_code(state, path, false) + state.with_strategy(|strategy, state| strategy.get_artifact_code(state, path, false)) } } diff --git a/crates/cheatcodes/src/inspector.rs b/crates/cheatcodes/src/inspector.rs index e03823c26..f2fb62d14 100644 --- a/crates/cheatcodes/src/inspector.rs +++ b/crates/cheatcodes/src/inspector.rs @@ -61,7 +61,7 @@ use std::{ io::BufReader, ops::Range, path::PathBuf, - sync::{Arc, Mutex}, + sync::Arc, }; mod utils; @@ -69,6 +69,7 @@ pub use utils::CommonCreateInput; 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)>; +pub type Strategy<'a> = &'a mut dyn CheatcodeInspectorStrategyExt; /// Helper trait for obtaining complete [revm::Inspector] instance from mutable reference to /// [Cheatcodes]. @@ -527,7 +528,7 @@ pub struct Cheatcodes { pub wallets: Option, /// The behavior strategy. - pub strategy: Arc>, + pub strategy: Option>, } impl Clone for Cheatcodes { @@ -567,7 +568,7 @@ impl Clone for Cheatcodes { arbitrary_storage: self.arbitrary_storage.clone(), deprecated: self.deprecated.clone(), wallets: self.wallets.clone(), - strategy: self.strategy.lock().expect("failed acquiring strategy").new_cloned_ext(), + strategy: self.strategy.as_ref().map(|s| s.new_cloned_ext()), } } } @@ -587,7 +588,7 @@ impl Cheatcodes { Self { fs_commit: true, labels: config.labels.clone(), - strategy: config.strategy.clone(), + strategy: Some(config.strategy.clone()), config, block: Default::default(), active_delegation: Default::default(), @@ -762,16 +763,13 @@ impl Cheatcodes { if ecx_inner.journaled_state.depth() == broadcast.depth { input.set_caller(broadcast.new_origin); - self.strategy - .lock() - .expect("failed acquiring strategy") - .record_broadcastable_create_transactions( - self.config.clone(), - &input, - ecx_inner, - broadcast, - &mut self.broadcastable_transactions, - ); + self.strategy.as_mut().unwrap().record_broadcastable_create_transactions( + self.config.clone(), + &input, + ecx_inner, + broadcast, + &mut self.broadcastable_transactions, + ); input.log_debug(self, &input.scheme().unwrap_or(CreateScheme::Create)); } @@ -803,9 +801,9 @@ impl Cheatcodes { }]); } - let strategy = self.strategy.clone(); - let mut guard = strategy.lock().expect("failed acquiring strategy"); - if let Some(result) = guard.zksync_try_create(self, ecx, &input, executor) { + if let Some(result) = self.with_strategy(|strategy, cheatcodes| { + strategy.zksync_try_create(cheatcodes, ecx, &input, executor) + }) { return Some(result); } @@ -920,7 +918,7 @@ where { } self.strategy - .lock() + .as_mut() .expect("failed acquiring strategy") .zksync_record_create_address(&outcome); @@ -966,7 +964,7 @@ where { let nonce = prev.saturating_sub(1); account.info.nonce = nonce; self.strategy - .lock() + .as_mut() .expect("failed acquiring strategy") .zksync_sync_nonce(sender, nonce, ecx); @@ -1003,7 +1001,7 @@ where { } self.strategy - .lock() + .as_mut() .expect("failed acquiring strategy") .zksync_set_deployer_call_input(call); @@ -1140,7 +1138,7 @@ where { } self.strategy - .lock() + .as_mut() .expect("failed acquiring strategy") .record_broadcastable_call_transactions( self.config.clone(), @@ -1222,9 +1220,9 @@ where { }]); } - let strategy = self.strategy.clone(); - let mut guard = strategy.lock().expect("failed acquiring strategy"); - if let Some(result) = guard.zksync_try_call(self, ecx, call, executor) { + if let Some(result) = self.with_strategy(|strategy, cheatcodes| { + strategy.zksync_try_call(cheatcodes, ecx, call, executor) + }) { return Some(result); } @@ -1266,6 +1264,17 @@ where { None => false, } } + + pub fn with_strategy(&mut self, mut f: F) -> R + where + F: FnMut(Strategy, &mut Self) -> R, + { + let mut strategy = self.strategy.take(); + let result = f(strategy.as_mut().expect("failed acquiring strategy").as_mut(), self); + self.strategy = strategy; + + result + } } impl Inspector<&mut dyn DatabaseExt> for Cheatcodes { @@ -1286,7 +1295,7 @@ impl Inspector<&mut dyn DatabaseExt> for Cheatcodes { } self.strategy - .lock() + .as_mut() .expect("failed acquiring strategy") .post_initialize_interp(interpreter, ecx); } @@ -1333,11 +1342,7 @@ impl Inspector<&mut dyn DatabaseExt> for Cheatcodes { #[inline] fn step_end(&mut self, interpreter: &mut Interpreter, ecx: Ecx) { - if self - .strategy - .try_lock() - .expect("failed acquiring strategy") - .pre_step_end(interpreter, ecx) + if self.strategy.as_mut().expect("failed acquiring strategy").pre_step_end(interpreter, ecx) { return; } diff --git a/crates/cheatcodes/src/lib.rs b/crates/cheatcodes/src/lib.rs index 33dec1c33..56b6cfb43 100644 --- a/crates/cheatcodes/src/lib.rs +++ b/crates/cheatcodes/src/lib.rs @@ -17,6 +17,7 @@ extern crate tracing; use alloy_primitives::Address; use foundry_evm_core::backend::DatabaseExt; +use inspector::Strategy; use revm::{ContextPrecompiles, InnerEvmContext}; use spec::Status; @@ -174,4 +175,15 @@ impl CheatsCtxt<'_, '_, '_, '_> { pub(crate) fn is_precompile(&self, address: &Address) -> bool { self.precompiles.contains(address) } + + pub(crate) fn with_strategy(&mut self, mut f: F) -> R + where + F: FnMut(Strategy, &mut Self) -> R, + { + let mut strategy = self.state.strategy.take(); + let result = f(strategy.as_mut().expect("failed acquiring strategy").as_mut(), self); + self.state.strategy = strategy; + + result + } } diff --git a/crates/cheatcodes/src/strategy.rs b/crates/cheatcodes/src/strategy.rs index 58028025e..173457ca4 100644 --- a/crates/cheatcodes/src/strategy.rs +++ b/crates/cheatcodes/src/strategy.rs @@ -1,7 +1,4 @@ -use std::{ - fmt::Debug, - sync::{Arc, Mutex}, -}; +use std::{fmt::Debug, sync::Arc}; use alloy_primitives::{Address, Bytes, FixedBytes, TxKind, U256}; use alloy_rpc_types::{TransactionInput, TransactionRequest}; @@ -24,7 +21,8 @@ use crate::{ pub trait CheatcodeInspectorStrategy: Debug + Send + Sync { fn name(&self) -> &'static str; - fn new_cloned(&self) -> Arc>; + fn new_cloned(&self) -> Box; + /// Get nonce. fn get_nonce(&mut self, ccx: &mut CheatsCtxt, address: Address) -> Result { let account = ccx.ecx.journaled_state.load_account(address, &mut ccx.ecx.db)?; @@ -185,7 +183,7 @@ pub trait CheatcodeInspectorStrategy: Debug + Send + Sync { /// We define this in our fork pub trait CheatcodeInspectorStrategyExt: CheatcodeInspectorStrategy { - fn new_cloned_ext(&self) -> Arc>; + fn new_cloned_ext(&self) -> Box; fn zksync_cheatcode_skip_zkvm(&mut self) -> Result { Ok(Default::default()) @@ -256,8 +254,8 @@ impl CheatcodeInspectorStrategy for EvmCheatcodeInspectorStrategy { "evm" } - fn new_cloned(&self) -> Arc> { - Arc::new(Mutex::new(self.clone())) + fn new_cloned(&self) -> Box { + Box::new(self.clone()) } fn record_broadcastable_create_transactions( @@ -331,8 +329,20 @@ impl CheatcodeInspectorStrategy for EvmCheatcodeInspectorStrategy { } impl CheatcodeInspectorStrategyExt for EvmCheatcodeInspectorStrategy { - fn new_cloned_ext(&self) -> Arc> { - Arc::new(Mutex::new(self.clone())) + fn new_cloned_ext(&self) -> Box { + Box::new(self.clone()) + } +} + +impl Clone for Box { + fn clone(&self) -> Self { + self.new_cloned() + } +} + +impl Clone for Box { + fn clone(&self) -> Self { + self.new_cloned_ext() } } diff --git a/crates/cheatcodes/src/test.rs b/crates/cheatcodes/src/test.rs index 189494a2e..de3f1eb72 100644 --- a/crates/cheatcodes/src/test.rs +++ b/crates/cheatcodes/src/test.rs @@ -15,11 +15,7 @@ impl Cheatcode for zkVmCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { enable } = *self; - ccx.state - .strategy - .lock() - .expect("failed acquiring strategy") - .zksync_cheatcode_select_zk_vm(ccx.ecx, enable); + ccx.with_strategy(|strategy, ccx| strategy.zksync_cheatcode_select_zk_vm(ccx.ecx, enable)); Ok(Default::default()) } @@ -27,33 +23,23 @@ impl Cheatcode for zkVmCall { impl Cheatcode for zkVmSkipCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { - ccx.state - .strategy - .try_lock() - .expect("failed acquiring strategy") - .zksync_cheatcode_skip_zkvm() + ccx.with_strategy(|strategy, _ccx| strategy.zksync_cheatcode_skip_zkvm()) } } impl Cheatcode for zkUsePaymasterCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { paymaster_address, paymaster_input } = self; - ccx.state - .strategy - .lock() - .expect("failed acquiring strategy") - .zksync_cheatcode_set_paymaster(*paymaster_address, paymaster_input) + ccx.with_strategy(|strategy, _ccx| { + strategy.zksync_cheatcode_set_paymaster(*paymaster_address, paymaster_input) + }) } } impl Cheatcode for zkUseFactoryDepCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { name } = self; - ccx.state - .strategy - .lock() - .expect("failed acquiring strategy") - .zksync_cheatcode_use_factory_deps(name.clone()) + ccx.with_strategy(|strategy, _ccx| strategy.zksync_cheatcode_use_factory_deps(name.clone())) } } @@ -68,11 +54,8 @@ impl Cheatcode for zkRegisterContractCall { zkDeployedBytecode, } = self; - ccx.state - .strategy - .lock() - .expect("failed acquiring strategy") - .zksync_cheatcode_register_contract( + ccx.with_strategy(|strategy, _ccx| { + strategy.zksync_cheatcode_register_contract( name.clone(), zkBytecodeHash.0.into(), zkDeployedBytecode.to_vec(), @@ -81,6 +64,7 @@ impl Cheatcode for zkRegisterContractCall { evmDeployedBytecode.to_vec(), evmBytecode.to_vec(), ) + }) } } diff --git a/crates/chisel/src/executor.rs b/crates/chisel/src/executor.rs index 446d0b878..7a72c111e 100644 --- a/crates/chisel/src/executor.rs +++ b/crates/chisel/src/executor.rs @@ -10,23 +10,14 @@ use alloy_json_abi::EventParam; use alloy_primitives::{hex, Address, U256}; use core::fmt::Debug; use eyre::{Result, WrapErr}; +use foundry_cli::utils; use foundry_compilers::Artifact; use foundry_evm::{ - backend::Backend, - decode::decode_console_logs, - executors::{ - strategy::{EvmExecutorStrategy, ExecutorStrategyExt}, - ExecutorBuilder, - }, - inspectors::CheatsConfig, - traces::TraceMode, + backend::Backend, decode::decode_console_logs, executors::ExecutorBuilder, + inspectors::CheatsConfig, traces::TraceMode, }; -use foundry_strategy_zksync::ZksyncExecutorStrategy; use solang_parser::pt::{self, CodeLocation}; -use std::{ - str::FromStr, - sync::{Arc, Mutex}, -}; +use std::str::FromStr; use tracing::debug; use yansi::Paint; @@ -325,25 +316,14 @@ impl SessionSource { let env = self.config.evm_opts.evm_env().await.expect("Could not instantiate fork environment"); - let executor_strategy: Arc> = - if self.config.foundry_config.zksync.run_in_zk_mode() { - Arc::new(Mutex::new(ZksyncExecutorStrategy::default())) - } else { - Arc::new(Mutex::new(EvmExecutorStrategy::default())) - }; + let strategy = utils::get_executor_strategy(&self.config.foundry_config); // Create an in-memory backend let backend = match self.config.backend.take() { Some(backend) => backend, None => { let fork = self.config.evm_opts.get_fork(&self.config.foundry_config, env.clone()); - let backend = Backend::spawn( - fork, - executor_strategy - .lock() - .expect("failed acquiring strategy") - .new_backend_strategy(), - ); + let backend = Backend::spawn(fork, strategy.new_backend_strategy()); self.config.backend = Some(backend.clone()); backend } @@ -359,10 +339,7 @@ impl SessionSource { None, None, Some(self.solc.version.clone()), - executor_strategy - .lock() - .expect("failed acquiring strategy") - .new_cheatcode_inspector_strategy(), + strategy.new_cheatcode_inspector_strategy(), ) .into(), ) @@ -370,7 +347,7 @@ impl SessionSource { .gas_limit(self.config.evm_opts.gas_limit()) .spec(self.config.foundry_config.evm_spec_id()) .legacy_assertions(self.config.foundry_config.legacy_assertions) - .build(env, backend, executor_strategy); + .build(env, backend, strategy); // Create a [ChiselRunner] with a default balance of [U256::MAX] and // the sender [Address::zero]. diff --git a/crates/cli/src/utils/mod.rs b/crates/cli/src/utils/mod.rs index 0e22b03b1..5e4fd633c 100644 --- a/crates/cli/src/utils/mod.rs +++ b/crates/cli/src/utils/mod.rs @@ -17,7 +17,6 @@ use std::{ future::Future, path::{Path, PathBuf}, process::{Command, Output, Stdio}, - sync::{Arc, Mutex}, time::{Duration, SystemTime, UNIX_EPOCH}, }; use tracing_subscriber::prelude::*; @@ -94,13 +93,13 @@ pub fn get_provider(config: &Config) -> Result { get_provider_builder(config)?.build() } -pub fn get_executor_strategy(config: &Config) -> Arc> { +pub fn get_executor_strategy(config: &Config) -> Box { if config.zksync.should_compile() { info!("using zksync strategy"); - Arc::new(Mutex::new(ZksyncExecutorStrategy::default())) + Box::new(ZksyncExecutorStrategy::default()) } else { info!("using evm strategy"); - Arc::new(Mutex::new(EvmExecutorStrategy::default())) + Box::new(EvmExecutorStrategy::default()) } } diff --git a/crates/evm/core/src/backend/cow.rs b/crates/evm/core/src/backend/cow.rs index f58e62dcc..2f7b7bd90 100644 --- a/crates/evm/core/src/backend/cow.rs +++ b/crates/evm/core/src/backend/cow.rs @@ -17,11 +17,7 @@ use revm::{ primitives::{Account, AccountInfo, Bytecode, Env, EnvWithHandlerCfg, HashMap as Map, SpecId}, Database, DatabaseCommit, JournaledState, }; -use std::{ - borrow::Cow, - collections::BTreeMap, - sync::{Arc, Mutex}, -}; +use std::{borrow::Cow, collections::BTreeMap}; /// A wrapper around `Backend` that ensures only `revm::DatabaseRef` functions are called. /// @@ -96,8 +92,8 @@ impl DatabaseExt for CowBackend<'_> { self.backend.to_mut().get_fork_info(id) } - fn get_strategy(&mut self) -> Arc> { - self.backend.as_ref().strategy.clone() + fn get_strategy(&mut self) -> &mut dyn BackendStrategyExt { + self.backend.to_mut().strategy.as_mut() } fn snapshot_state(&mut self, journaled_state: &JournaledState, env: &Env) -> U256 { diff --git a/crates/evm/core/src/backend/mod.rs b/crates/evm/core/src/backend/mod.rs index c69309005..9c4aba6f9 100644 --- a/crates/evm/core/src/backend/mod.rs +++ b/crates/evm/core/src/backend/mod.rs @@ -28,7 +28,6 @@ use revm::{ }; use std::{ collections::{BTreeMap, HashSet}, - sync::{Arc, Mutex}, time::Instant, }; use strategy::{BackendStrategyExt, BackendStrategyForkInfo}; @@ -103,7 +102,7 @@ pub trait DatabaseExt: Database + DatabaseCommit { fn get_fork_info(&mut self, id: LocalForkId) -> eyre::Result; /// Retrieve the strategy. - fn get_strategy(&mut self) -> Arc>; + fn get_strategy(&mut self) -> &mut dyn BackendStrategyExt; /// Reverts the snapshot if it exists /// @@ -461,7 +460,7 @@ struct _ObjectSafe(dyn DatabaseExt); #[must_use] pub struct Backend { /// The behavior strategy. - pub strategy: Arc>, + pub strategy: Box, /// The access point for managing forks forks: MultiFork, @@ -497,7 +496,7 @@ pub struct Backend { impl Clone for Backend { fn clone(&self) -> Self { Self { - strategy: self.strategy.lock().expect("failed acquiring strategy").new_cloned_ext(), + strategy: self.strategy.new_cloned_ext(), forks: self.forks.clone(), mem_db: self.mem_db.clone(), fork_init_journaled_state: self.fork_init_journaled_state.clone(), @@ -513,7 +512,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: Arc>) -> Self { + pub fn spawn(fork: Option, strategy: Box) -> Self { Self::new(MultiFork::spawn(), fork, strategy) } @@ -526,7 +525,7 @@ impl Backend { pub fn new( forks: MultiFork, fork: Option, - strategy: Arc>, + strategy: Box, ) -> Self { trace!(target: "backend", forking_mode=?fork.is_some(), "creating executor backend"); // Note: this will take of registering the `fork` @@ -569,7 +568,7 @@ impl Backend { id: &ForkId, fork: Fork, journaled_state: JournaledState, - strategy: Arc>, + strategy: Box, ) -> Self { let mut backend = Self::spawn(None, strategy); let fork_ids = backend.inner.insert_new_fork(id.clone(), fork.db, journaled_state); @@ -587,7 +586,7 @@ impl Backend { active_fork_ids: None, inner: Default::default(), fork_url_type: Default::default(), - strategy: self.strategy.clone(), + strategy: self.strategy.new_cloned_ext(), } } @@ -915,7 +914,7 @@ impl Backend { &fork_id, &persistent_accounts, &mut NoOpInspector, - self.strategy.clone(), + self.strategy.as_mut(), )?; } @@ -939,8 +938,8 @@ impl DatabaseExt for Backend { Ok(ForkInfo { fork_type, fork_env }) } - fn get_strategy(&mut self) -> Arc> { - self.strategy.clone() + fn get_strategy(&mut self) -> &mut dyn BackendStrategyExt { + self.strategy.as_mut() } fn snapshot_state(&mut self, journaled_state: &JournaledState, env: &Env) -> U256 { @@ -1170,7 +1169,7 @@ impl DatabaseExt for Backend { caller_account.into() }); - self.strategy.lock().expect("failed acquiring strategy").update_fork_db( + self.strategy.update_fork_db( BackendStrategyForkInfo { active_fork: self.active_fork(), active_type: current_fork_type, @@ -1207,7 +1206,7 @@ impl DatabaseExt for Backend { let (fork_id, backend, fork_env) = self.forks.roll_fork(self.inner.ensure_fork_id(id).cloned()?, block_number)?; // this will update the local mapping - self.inner.roll_fork(id, fork_id, backend, self.strategy.clone())?; + self.inner.roll_fork(id, fork_id, backend, self.strategy.as_mut())?; if let Some((active_id, active_idx)) = self.active_fork_ids { // the currently active fork is the targeted fork of this call @@ -1229,14 +1228,11 @@ impl DatabaseExt for Backend { active.journaled_state.depth = journaled_state.depth; for addr in persistent_addrs { - self.strategy - .lock() - .expect("failed acquiring strategy") - .merge_journaled_state_data( - addr, - journaled_state, - &mut active.journaled_state, - ); + self.strategy.merge_journaled_state_data( + addr, + journaled_state, + &mut active.journaled_state, + ); } // Ensure all previously loaded accounts are present in the journaled state to @@ -1249,14 +1245,11 @@ impl DatabaseExt for Backend { for (addr, acc) in journaled_state.state.iter() { if acc.is_created() { if acc.is_touched() { - self.strategy - .lock() - .expect("failed acquiring strategy") - .merge_journaled_state_data( - *addr, - journaled_state, - &mut active.journaled_state, - ); + self.strategy.merge_journaled_state_data( + *addr, + journaled_state, + &mut active.journaled_state, + ); } } else { let _ = active.journaled_state.load_account(*addr, &mut active.db); @@ -1333,7 +1326,7 @@ impl DatabaseExt for Backend { &fork_id, &persistent_accounts, inspector, - self.strategy.clone(), + self.strategy.as_mut(), ) } @@ -1815,7 +1808,7 @@ impl BackendInner { id: LocalForkId, new_fork_id: ForkId, backend: SharedBackend, - strategy: Arc>, + strategy: &mut dyn BackendStrategyExt, ) -> eyre::Result { let fork_id = self.ensure_fork_id(id)?; let idx = self.ensure_fork_index(fork_id)?; @@ -1824,11 +1817,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.lock().expect("failed acquiring strategy").merge_db_account_data( - addr, - &active.db, - &mut new_db, - ); + strategy.merge_db_account_data(addr, &active.db, &mut new_db); } active.db = new_db; } @@ -1948,7 +1937,7 @@ fn commit_transaction( fork_id: &ForkId, persistent_accounts: &HashSet
, inspector: &mut dyn InspectorExt, - strategy: Arc>, + strategy: &mut dyn BackendStrategyExt, ) -> eyre::Result<()> { // TODO: Remove after https://github.com/foundry-rs/foundry/pull/9131 // if the tx has the blob_versioned_hashes field, we assume it's a Cancun block @@ -1963,7 +1952,8 @@ fn commit_transaction( let fork = fork.clone(); let journaled_state = journaled_state.clone(); let depth = journaled_state.depth; - let mut db = Backend::new_with_fork(fork_id, fork, journaled_state, strategy); + let mut db = + Backend::new_with_fork(fork_id, fork, journaled_state, strategy.new_cloned_ext()); 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. @@ -2015,8 +2005,6 @@ fn apply_state_changeset( #[cfg(test)] #[allow(clippy::needless_return)] mod tests { - use std::sync::{Arc, Mutex}; - use crate::{ backend::{strategy::EvmBackendStrategy, Backend}, fork::CreateFork, @@ -2052,7 +2040,7 @@ mod tests { evm_opts, }; - let backend = Backend::spawn(Some(fork), Arc::new(Mutex::new(EvmBackendStrategy))); + let backend = Backend::spawn(Some(fork), Box::new(EvmBackendStrategy)); // 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 75706d2a6..1776c03a9 100644 --- a/crates/evm/core/src/backend/strategy.rs +++ b/crates/evm/core/src/backend/strategy.rs @@ -41,7 +41,7 @@ pub trait BackendStrategy: Debug + Send + Sync { } pub trait BackendStrategyExt: BackendStrategy { - fn new_cloned_ext(&self) -> Arc>; + fn new_cloned_ext(&self) -> Box; /// Saves the storage keys for immutable variables per address. /// /// These are required during fork to help merge the persisted addresses, as they are stored @@ -101,8 +101,8 @@ impl BackendStrategy for EvmBackendStrategy { } impl BackendStrategyExt for EvmBackendStrategy { - fn new_cloned_ext(&self) -> Arc> { - Arc::new(Mutex::new(self.clone())) + fn new_cloned_ext(&self) -> Box { + Box::new(self.clone()) } } diff --git a/crates/evm/evm/src/executors/builder.rs b/crates/evm/evm/src/executors/builder.rs index 22eb0e377..b5e1d8f98 100644 --- a/crates/evm/evm/src/executors/builder.rs +++ b/crates/evm/evm/src/executors/builder.rs @@ -1,5 +1,3 @@ -use std::sync::{Arc, Mutex}; - use crate::{executors::Executor, inspectors::InspectorStackBuilder}; use foundry_evm_core::backend::Backend; use revm::primitives::{Env, EnvWithHandlerCfg, SpecId}; @@ -78,12 +76,7 @@ impl ExecutorBuilder { /// Builds the executor as configured. #[inline] - pub fn build( - self, - env: Env, - db: Backend, - strategy: Arc>, - ) -> Executor { + pub fn build(self, env: Env, db: Backend, strategy: Box) -> 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 85b1256bf..79a208821 100644 --- a/crates/evm/evm/src/executors/mod.rs +++ b/crates/evm/evm/src/executors/mod.rs @@ -36,10 +36,7 @@ use revm::{ ResultAndState, SignedAuthorization, SpecId, TxEnv, TxKind, }, }; -use std::{ - borrow::Cow, - sync::{Arc, Mutex}, -}; +use std::borrow::Cow; use strategy::ExecutorStrategyExt; mod builder; @@ -96,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: Arc>, + strategy: Option>, } impl Clone for Executor { @@ -107,7 +104,7 @@ impl Clone for Executor { inspector: self.inspector.clone(), gas_limit: self.gas_limit, legacy_assertions: self.legacy_assertions, - strategy: self.strategy.lock().expect("failed acquiring strategy").new_cloned_ext(), + strategy: self.strategy.as_ref().map(|s| s.new_cloned_ext()), } } } @@ -127,7 +124,7 @@ impl Executor { inspector: InspectorStack, gas_limit: u64, legacy_assertions: bool, - strategy: Arc>, + strategy: Box, ) -> Self { // Need to create a non-empty contract on the cheatcodes address so `extcodesize` checks // do not fail. @@ -142,7 +139,7 @@ impl Executor { }, ); - Self { backend, env, inspector, gas_limit, legacy_assertions, strategy } + Self { backend, env, inspector, gas_limit, legacy_assertions, strategy: Some(strategy) } } fn clone_with_backend(&self, backend: Backend) -> Self { @@ -153,7 +150,7 @@ impl Executor { self.inspector().clone(), self.gas_limit, self.legacy_assertions, - self.strategy.clone(), + self.strategy.as_ref().map(|s| s.new_cloned_ext()).expect("failed acquiring strategy"), ) } @@ -217,12 +214,21 @@ impl Executor { Ok(()) } + pub fn with_strategy(&mut self, mut f: F) -> R + where + F: FnMut(&mut dyn ExecutorStrategyExt, &mut Self) -> R, + { + let mut strategy = self.strategy.take(); + let result = f(strategy.as_mut().expect("failed acquiring strategy").as_mut(), self); + self.strategy = strategy; + + result + } + /// Set the balance of an account. pub fn set_balance(&mut self, address: Address, amount: U256) -> BackendResult<()> { trace!(?address, ?amount, "setting account balance"); - let strategy = self.strategy.clone(); - let mut guard = strategy.lock().expect("failed acquiring strategy"); - guard.set_balance(self, address, amount) + self.with_strategy(|strategy, executor| strategy.set_balance(executor, address, amount)) } /// Gets the balance of an account @@ -232,9 +238,7 @@ impl Executor { /// Set the nonce of an account. pub fn set_nonce(&mut self, address: Address, nonce: u64) -> BackendResult<()> { - let strategy = self.strategy.clone(); - let mut guard = strategy.lock().expect("failed acquiring strategy"); - guard.set_nonce(self, address, nonce) + self.with_strategy(|strategy, executor| strategy.set_nonce(executor, address, nonce)) } /// Returns the nonce of an account. @@ -268,7 +272,7 @@ impl Executor { #[inline] pub fn set_transaction_other_fields(&mut self, other_fields: OtherFields) { self.strategy - .try_lock() + .as_mut() .expect("failed acquiring strategy") .set_inspect_context(other_fields); } @@ -453,37 +457,42 @@ impl Executor { backend.is_initialized = false; backend.spec_id = env.spec_id(); - let result = self.strategy.lock().expect("failed acquiring strategy").call_inspect( - &mut backend, - &mut env, - &mut inspector, - )?; - - convert_executed_result(env, inspector, result, backend.has_state_snapshot_failure()) - } - - /// Execute the transaction configured in `env.tx`. - #[instrument(name = "transact", level = "debug", skip_all)] - pub fn transact_with_env(&mut self, mut env: EnvWithHandlerCfg) -> eyre::Result { - let mut inspector = self.inspector.clone(); - let backend = &mut self.backend; - backend.initialize(&env); - - let result_and_state = self + let result = self .strategy - .lock() + .as_ref() .expect("failed acquiring strategy") - .transact_inspect(backend, &mut env, &self.env, &mut inspector)?; + .new_cloned_ext() + .call_inspect(&mut backend, &mut env, &mut inspector)?; - let mut result = convert_executed_result( - env, + convert_executed_result( + env.clone(), inspector, - result_and_state, + result, backend.has_state_snapshot_failure(), - )?; + ) + } - self.commit(&mut result); - Ok(result) + /// Execute the transaction configured in `env.tx`. + #[instrument(name = "transact", level = "debug", skip_all)] + pub fn transact_with_env(&mut self, mut env: EnvWithHandlerCfg) -> eyre::Result { + self.with_strategy(|strategy, executor| { + let mut inspector = executor.inspector.clone(); + let backend = &mut executor.backend; + backend.initialize(&env); + + let result_and_state = + strategy.transact_inspect(backend, &mut env, &executor.env, &mut inspector)?; + + let mut result = convert_executed_result( + env.clone(), + inspector, + result_and_state, + backend.has_state_snapshot_failure(), + )?; + + executor.commit(&mut result); + Ok(result) + }) } /// Commit the changeset to the database and adjust `self.inspector_config` values according to diff --git a/crates/evm/evm/src/executors/strategy.rs b/crates/evm/evm/src/executors/strategy.rs index c2af8219c..4ebb03c86 100644 --- a/crates/evm/evm/src/executors/strategy.rs +++ b/crates/evm/evm/src/executors/strategy.rs @@ -1,7 +1,4 @@ -use std::{ - fmt::Debug, - sync::{Arc, Mutex}, -}; +use std::fmt::Debug; use alloy_primitives::{Address, U256}; use alloy_serde::OtherFields; @@ -25,7 +22,7 @@ use super::Executor; pub trait ExecutorStrategy: Debug + Send + Sync { fn name(&self) -> &'static str; - fn new_cloned(&self) -> Arc>; + fn new_cloned(&self) -> Box; fn set_balance( &mut self, @@ -58,14 +55,14 @@ pub trait ExecutorStrategy: Debug + Send + Sync { inspector: &mut dyn InspectorExt, ) -> eyre::Result; - fn new_backend_strategy(&self) -> Arc>; - fn new_cheatcode_inspector_strategy(&self) -> Arc>; + fn new_backend_strategy(&self) -> Box; + fn new_cheatcode_inspector_strategy(&self) -> Box; // TODO perhaps need to create fresh strategies as well } pub trait ExecutorStrategyExt: ExecutorStrategy { - fn new_cloned_ext(&self) -> Arc>; + fn new_cloned_ext(&self) -> Box; fn zksync_set_dual_compiled_contracts( &mut self, @@ -86,8 +83,8 @@ impl ExecutorStrategy for EvmExecutorStrategy { "evm" } - fn new_cloned(&self) -> Arc> { - Arc::new(Mutex::new(self.clone())) + fn new_cloned(&self) -> Box { + Box::new(self.clone()) } fn set_inspect_context(&mut self, _other_fields: OtherFields) {} @@ -159,17 +156,17 @@ impl ExecutorStrategy for EvmExecutorStrategy { Ok(()) } - fn new_backend_strategy(&self) -> Arc> { - Arc::new(Mutex::new(EvmBackendStrategy)) + fn new_backend_strategy(&self) -> Box { + Box::new(EvmBackendStrategy) } - fn new_cheatcode_inspector_strategy(&self) -> Arc> { - Arc::new(Mutex::new(EvmCheatcodeInspectorStrategy::default())) + fn new_cheatcode_inspector_strategy(&self) -> Box { + Box::new(EvmCheatcodeInspectorStrategy::default()) } } impl ExecutorStrategyExt for EvmExecutorStrategy { - fn new_cloned_ext(&self) -> Arc> { - Arc::new(Mutex::new(self.clone())) + fn new_cloned_ext(&self) -> Box { + Box::new(self.clone()) } } diff --git a/crates/evm/evm/src/executors/trace.rs b/crates/evm/evm/src/executors/trace.rs index 83a06a516..68a3c11f4 100644 --- a/crates/evm/evm/src/executors/trace.rs +++ b/crates/evm/evm/src/executors/trace.rs @@ -4,10 +4,7 @@ use foundry_config::{utils::evm_spec_id, Chain, Config}; use foundry_evm_core::{backend::Backend, fork::CreateFork, opts::EvmOpts}; use foundry_evm_traces::{InternalTraceMode, TraceMode}; use revm::primitives::{Env, SpecId}; -use std::{ - ops::{Deref, DerefMut}, - sync::{Arc, Mutex}, -}; +use std::ops::{Deref, DerefMut}; use super::strategy::ExecutorStrategyExt; @@ -24,12 +21,9 @@ impl TracingExecutor { debug: bool, decode_internal: bool, alphanet: bool, - strategy: Arc>, + strategy: Box, ) -> Self { - let db = Backend::spawn( - fork, - strategy.lock().expect("failed acquiring strategy").new_backend_strategy(), - ); + let db = Backend::spawn(fork, strategy.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 6139dc71d..384504bef 100644 --- a/crates/forge/bin/cmd/test/mod.rs +++ b/crates/forge/bin/cmd/test/mod.rs @@ -271,7 +271,7 @@ impl TestArgs { pub async fn execute_tests(mut self) -> Result { // Merge all configs. let (mut config, mut evm_opts) = self.load_config_and_evm_opts_emit_warnings()?; - let strategy = utils::get_executor_strategy(&config); + let mut strategy = utils::get_executor_strategy(&config); // Explicitly enable isolation for gas reports for more correct gas accounting. if self.gas_report { @@ -368,10 +368,7 @@ impl TestArgs { // Prepare the test builder. let config = Arc::new(config); - strategy - .lock() - .expect("failed acquiring strategy") - .zksync_set_dual_compiled_contracts(dual_compiled_contracts.unwrap_or_default()); + strategy.zksync_set_dual_compiled_contracts(dual_compiled_contracts.unwrap_or_default()); let runner = MultiContractRunnerBuilder::new(config.clone()) .set_debug(should_debug) diff --git a/crates/forge/src/multi_runner.rs b/crates/forge/src/multi_runner.rs index 2ea177733..b42f67bab 100644 --- a/crates/forge/src/multi_runner.rs +++ b/crates/forge/src/multi_runner.rs @@ -34,7 +34,7 @@ use std::{ collections::BTreeMap, fmt::Debug, path::Path, - sync::{mpsc, Arc, Mutex}, + sync::{mpsc, Arc}, time::Instant, }; @@ -85,7 +85,7 @@ pub struct MultiContractRunner { /// Library addresses used to link contracts. pub libraries: Libraries, /// Execution strategy. - pub strategy: Arc>, + pub strategy: Box, } impl MultiContractRunner { @@ -178,10 +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.lock().expect("failed acquiring strategy").new_backend_strategy(), - ); + let db = Backend::spawn(self.fork.take(), self.strategy.new_backend_strategy()); let find_timer = Instant::now(); let contracts = self.matching_contracts(filter).collect::>(); @@ -253,10 +250,7 @@ impl MultiContractRunner { Some(self.known_contracts.clone()), Some(artifact_id.name.clone()), Some(artifact_id.version.clone()), - self.strategy - .lock() - .expect("failed acquiring strategy") - .new_cheatcode_inspector_strategy(), + self.strategy.new_cheatcode_inspector_strategy(), ); let trace_mode = TraceMode::default() @@ -276,7 +270,7 @@ impl MultiContractRunner { .spec(self.evm_spec) .gas_limit(self.evm_opts.gas_limit()) .legacy_assertions(self.config.legacy_assertions) - .build(self.env.clone(), db, self.strategy.clone()); + .build(self.env.clone(), db, self.strategy.new_cloned_ext()); if !enabled!(tracing::Level::TRACE) { span_name = get_contract_name(&identifier); @@ -413,7 +407,7 @@ impl MultiContractRunnerBuilder { zk_output: Option, env: revm::primitives::Env, evm_opts: EvmOpts, - strategy: Arc>, + strategy: Box, ) -> 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 64ed52aef..067440c83 100644 --- a/crates/forge/src/runner.rs +++ b/crates/forge/src/runner.rs @@ -153,7 +153,7 @@ impl ContractRunner<'_> { debug!("test contract deployed"); cheatcodes .strategy - .try_lock() + .as_mut() .expect("failed acquiring strategy") .base_contract_deployed(); } diff --git a/crates/forge/tests/it/test_helpers.rs b/crates/forge/tests/it/test_helpers.rs index d5bbd5b37..cd80f6d52 100644 --- a/crates/forge/tests/it/test_helpers.rs +++ b/crates/forge/tests/it/test_helpers.rs @@ -36,7 +36,7 @@ use std::{ env, fmt, io::Write, path::{Path, PathBuf}, - sync::{Arc, LazyLock, Mutex}, + sync::{Arc, LazyLock}, }; type ZkProject = Project; @@ -359,11 +359,8 @@ impl ForgeTestData { test_opts.fuzz.no_zksync_reserved_addresses = zk_config.fuzz.no_zksync_reserved_addresses; let sender = zk_config.sender; - let strategy = utils::get_executor_strategy(&zk_config); - strategy - .lock() - .expect("failed acquiring strategy") - .zksync_set_dual_compiled_contracts(dual_compiled_contracts); + let mut strategy = utils::get_executor_strategy(&zk_config); + strategy.zksync_set_dual_compiled_contracts(dual_compiled_contracts); let mut builder = self.base_runner(); builder.config = Arc::new(zk_config); builder @@ -385,7 +382,7 @@ impl ForgeTestData { None, opts.local_evm_env(), opts, - Arc::new(Mutex::new(EvmExecutorStrategy::default())), + Box::new(EvmExecutorStrategy::default()), ) .unwrap() } @@ -408,7 +405,7 @@ impl ForgeTestData { None, env, opts, - Arc::new(Mutex::new(EvmExecutorStrategy::default())), + Box::new(EvmExecutorStrategy::default()), ) .unwrap() } diff --git a/crates/script/src/lib.rs b/crates/script/src/lib.rs index 089561951..c56058bc4 100644 --- a/crates/script/src/lib.rs +++ b/crates/script/src/lib.rs @@ -591,20 +591,14 @@ impl ScriptConfig { ) -> Result { trace!("preparing script runner"); let env = self.evm_opts.evm_env().await?; - let strategy = utils::get_executor_strategy(&self.config); + let mut strategy = utils::get_executor_strategy(&self.config); let db = if let Some(fork_url) = self.evm_opts.fork_url.as_ref() { match self.backends.get(fork_url) { Some(db) => db.clone(), None => { let fork = self.evm_opts.get_fork(&self.config, env.clone()); - let backend = Backend::spawn( - fork, - strategy - .try_lock() - .expect("failed acquiring strategy") - .new_backend_strategy(), - ); + let backend = Backend::spawn(fork, strategy.new_backend_strategy()); self.backends.insert(fork_url.clone(), backend.clone()); backend } @@ -613,10 +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.lock().expect("failed acquiring strategy").new_backend_strategy(), - ) + Backend::spawn(None, strategy.new_backend_strategy()) }; // We need to enable tracing to decode contract names: local or external. @@ -633,16 +624,10 @@ impl ScriptConfig { if let Some((known_contracts, script_wallets, target, dual_compiled_contracts)) = cheats_data { - strategy - .lock() - .expect("failed acquiring strategy") - .zksync_set_dual_compiled_contracts(dual_compiled_contracts); + strategy.zksync_set_dual_compiled_contracts(dual_compiled_contracts); if let Some(fork_url) = &self.evm_opts.fork_url { - strategy - .lock() - .expect("failed acquiring strategy") - .zksync_set_fork_env(fork_url, &env)?; + strategy.zksync_set_fork_env(fork_url, &env)?; } builder = builder.inspectors(|stack| { @@ -654,10 +639,7 @@ impl ScriptConfig { Some(known_contracts), Some(target.name), Some(target.version), - strategy - .lock() - .expect("failed acquiring strategy") - .new_cheatcode_inspector_strategy(), + strategy.new_cheatcode_inspector_strategy(), ) .into(), ) diff --git a/crates/script/src/runner.rs b/crates/script/src/runner.rs index 2aa586bee..20ad42cf4 100644 --- a/crates/script/src/runner.rs +++ b/crates/script/src/runner.rs @@ -176,7 +176,7 @@ impl ScriptRunner { debug!("script deployed"); cheatcodes .strategy - .try_lock() + .as_mut() .expect("failed acquiring strategy") .base_contract_deployed(); } diff --git a/crates/strategy/zksync/src/backend.rs b/crates/strategy/zksync/src/backend.rs index dede8800a..a3f829176 100644 --- a/crates/strategy/zksync/src/backend.rs +++ b/crates/strategy/zksync/src/backend.rs @@ -132,8 +132,8 @@ impl ZksyncBackendStrategy { } impl BackendStrategyExt for ZksyncBackendStrategy { - fn new_cloned_ext(&self) -> Arc> { - Arc::new(Mutex::new(self.clone())) + fn new_cloned_ext(&self) -> Box { + Box::new(self.clone()) } fn zksync_save_immutable_storage(&mut self, addr: Address, keys: HashSet) { diff --git a/crates/strategy/zksync/src/cheatcode.rs b/crates/strategy/zksync/src/cheatcode.rs index 0d8ca2d8e..9e9c5f485 100644 --- a/crates/strategy/zksync/src/cheatcode.rs +++ b/crates/strategy/zksync/src/cheatcode.rs @@ -1,8 +1,4 @@ -use std::{ - fs, - path::PathBuf, - sync::{Arc, Mutex}, -}; +use std::{fs, path::PathBuf, sync::Arc}; use alloy_json_abi::ContractObject; use alloy_primitives::{keccak256, map::HashMap, Address, Bytes, FixedBytes, TxKind, B256, U256}; @@ -227,8 +223,8 @@ impl CheatcodeInspectorStrategy for ZksyncCheatcodeInspectorStrategy { "zk" } - fn new_cloned(&self) -> Arc> { - Arc::new(Mutex::new(self.clone())) + fn new_cloned(&self) -> Box { + Box::new(self.clone()) } fn get_nonce(&mut self, ccx: &mut CheatsCtxt<'_, '_, '_, '_>, address: Address) -> Result { @@ -684,8 +680,8 @@ impl CheatcodeInspectorStrategy for ZksyncCheatcodeInspectorStrategy { } impl CheatcodeInspectorStrategyExt for ZksyncCheatcodeInspectorStrategy { - fn new_cloned_ext(&self) -> Arc> { - Arc::new(Mutex::new(self.clone())) + fn new_cloned_ext(&self) -> Box { + Box::new(self.clone()) } fn zksync_cheatcode_skip_zkvm(&mut self) -> Result { @@ -941,11 +937,7 @@ impl CheatcodeInspectorStrategyExt for ZksyncCheatcodeInspectorStrategy { .to_ru256() }) .collect::>(); - ecx.db - .get_strategy() - .lock() - .expect("failed acquiring strategy") - .zksync_save_immutable_storage(addr, keys); + ecx.db.get_strategy().zksync_save_immutable_storage(addr, keys); } } diff --git a/crates/strategy/zksync/src/executor.rs b/crates/strategy/zksync/src/executor.rs index 5c08c4182..ea868cb5a 100644 --- a/crates/strategy/zksync/src/executor.rs +++ b/crates/strategy/zksync/src/executor.rs @@ -1,5 +1,3 @@ -use std::sync::{Arc, Mutex}; - use alloy_primitives::{Address, U256}; use alloy_rpc_types::serde_helpers::OtherFields; use alloy_zksync::provider::{zksync_provider, ZksyncProvider}; @@ -41,8 +39,8 @@ impl ExecutorStrategy for ZksyncExecutorStrategy { "zk" } - fn new_cloned(&self) -> Arc> { - Arc::new(Mutex::new(self.clone())) + fn new_cloned(&self) -> Box { + Box::new(self.clone()) } fn set_inspect_context(&mut self, other_fields: OtherFields) { @@ -83,15 +81,15 @@ impl ExecutorStrategy for ZksyncExecutorStrategy { Ok(()) } - fn new_backend_strategy(&self) -> Arc> { - Arc::new(Mutex::new(ZksyncBackendStrategy::default())) + fn new_backend_strategy(&self) -> Box { + Box::new(ZksyncBackendStrategy::default()) } - fn new_cheatcode_inspector_strategy(&self) -> Arc> { - Arc::new(Mutex::new(ZksyncCheatcodeInspectorStrategy::new( + fn new_cheatcode_inspector_strategy(&self) -> Box { + Box::new(ZksyncCheatcodeInspectorStrategy::new( self.dual_compiled_contracts.clone(), self.zk_env.clone(), - ))) + )) } fn call_inspect( @@ -142,8 +140,8 @@ impl ExecutorStrategy for ZksyncExecutorStrategy { } impl ExecutorStrategyExt for ZksyncExecutorStrategy { - fn new_cloned_ext(&self) -> Arc> { - Arc::new(Mutex::new(self.clone())) + fn new_cloned_ext(&self) -> Box { + Box::new(self.clone()) } fn zksync_set_dual_compiled_contracts( diff --git a/crates/verify/src/bytecode.rs b/crates/verify/src/bytecode.rs index 5a9592b4b..e1299f49f 100644 --- a/crates/verify/src/bytecode.rs +++ b/crates/verify/src/bytecode.rs @@ -240,7 +240,7 @@ impl VerifyBytecodeArgs { gen_blk_num, etherscan_metadata.evm_version()?.unwrap_or(EvmVersion::default()), evm_opts, - strategy.clone(), + strategy.new_cloned_ext(), ) .await?; @@ -444,7 +444,7 @@ impl VerifyBytecodeArgs { simulation_block - 1, // env.fork_block_number etherscan_metadata.evm_version()?.unwrap_or(EvmVersion::default()), evm_opts, - strategy.clone(), + strategy.new_cloned_ext(), ) .await?; env.block.number = U256::from(simulation_block); diff --git a/crates/verify/src/utils.rs b/crates/verify/src/utils.rs index 51de9de19..ee562cea1 100644 --- a/crates/verify/src/utils.rs +++ b/crates/verify/src/utils.rs @@ -1,5 +1,3 @@ -use std::sync::{Arc, Mutex}; - use crate::{bytecode::VerifyBytecodeArgs, types::VerificationType}; use alloy_dyn_abi::DynSolValue; use alloy_primitives::{Address, Bytes, U256}; @@ -327,7 +325,7 @@ pub async fn get_tracing_executor( fork_blk_num: u64, evm_version: EvmVersion, evm_opts: EvmOpts, - strategy: Arc>, + strategy: Box, ) -> Result<(Env, TracingExecutor)> { fork_config.fork_block_number = Some(fork_blk_num); fork_config.evm_version = evm_version;