diff --git a/crates/evm/core/src/backend/cow.rs b/crates/evm/core/src/backend/cow.rs index 1589c8ee8ec9..d5e09efbcd05 100644 --- a/crates/evm/core/src/backend/cow.rs +++ b/crates/evm/core/src/backend/cow.rs @@ -62,10 +62,10 @@ impl<'a> CowBackend<'a> { /// Note: in case there are any cheatcodes executed that modify the environment, this will /// update the given `env` with the new values. #[instrument(name = "inspect", level = "debug", skip_all)] - pub fn inspect( + pub fn inspect( &mut self, env: &mut EnvWithHandlerCfg, - inspector: &mut dyn InspectorExt, + inspector: &mut I, ) -> eyre::Result { // this is a new call to inspect with a new env, so even if we've cloned the backend // already, we reset the initialized state diff --git a/crates/evm/core/src/backend/mod.rs b/crates/evm/core/src/backend/mod.rs index 9d26ce287359..b72ca682b870 100644 --- a/crates/evm/core/src/backend/mod.rs +++ b/crates/evm/core/src/backend/mod.rs @@ -751,10 +751,10 @@ impl Backend { /// Note: in case there are any cheatcodes executed that modify the environment, this will /// update the given `env` with the new values. #[instrument(name = "inspect", level = "debug", skip_all)] - pub fn inspect( + pub fn inspect( &mut self, env: &mut EnvWithHandlerCfg, - inspector: &mut dyn InspectorExt, + inspector: &mut I, ) -> eyre::Result { self.initialize(env); let mut evm = crate::utils::new_evm_with_inspector(self, env.clone(), inspector); diff --git a/crates/evm/core/src/utils.rs b/crates/evm/core/src/utils.rs index d45c4b84908a..7e03bdf746ce 100644 --- a/crates/evm/core/src/utils.rs +++ b/crates/evm/core/src/utils.rs @@ -234,11 +234,11 @@ pub fn alphanet_handler_register(handler: &mut EvmHandl } /// Creates a new EVM with the given inspector. -pub fn new_evm_with_inspector<'evm, 'i, 'db>( +pub fn new_evm_with_inspector<'evm, 'i, 'db, I: InspectorExt + ?Sized>( db: &'db mut dyn DatabaseExt, env: revm::primitives::EnvWithHandlerCfg, - inspector: &'i mut dyn InspectorExt, -) -> revm::Evm<'evm, &'i mut dyn InspectorExt, &'db mut dyn DatabaseExt> { + inspector: &'i mut I, +) -> revm::Evm<'evm, &'i mut I, &'db mut dyn DatabaseExt> { let revm::primitives::EnvWithHandlerCfg { env, handler_cfg } = env; // NOTE: We could use `revm::Evm::builder()` here, but on the current patch it has some diff --git a/crates/evm/evm/src/inspectors/stack.rs b/crates/evm/evm/src/inspectors/stack.rs index c8df2c693102..ac7c31ff96a3 100644 --- a/crates/evm/evm/src/inspectors/stack.rs +++ b/crates/evm/evm/src/inspectors/stack.rs @@ -543,14 +543,14 @@ impl<'a> InspectorStackRefMut<'a> { self.in_inner_context = true; let env = EnvWithHandlerCfg::new_with_spec_id(ecx.env.clone(), ecx.spec_id()); - let res = { - let mut evm = crate::utils::new_evm_with_inspector(&mut ecx.db, env, self); + let res = self.with_stack(|inspector| { + let mut evm = crate::utils::new_evm_with_inspector(&mut ecx.db, env, inspector); let res = evm.transact(); // need to reset the env in case it was modified via cheatcodes during execution ecx.env = evm.context.evm.inner.env; res - }; + }); self.in_inner_context = false; self.inner_context_data = None; @@ -621,6 +621,25 @@ impl<'a> InspectorStackRefMut<'a> { }; (InterpreterResult { result, output, gas }, address) } + + /// Moves out of references, constructs an [`InspectorStack`] and runs the given closure with + /// it. + fn with_stack(&mut self, f: impl FnOnce(&mut InspectorStack) -> O) -> O { + let mut stack = InspectorStack { + cheatcodes: self.cheatcodes.as_deref_mut().map(std::mem::take), + inner: std::mem::take(self.inner), + }; + + let out = f(&mut stack); + + if let Some(cheats) = self.cheatcodes.as_deref_mut() { + *cheats = stack.cheatcodes.take().unwrap(); + } + + *self.inner = stack.inner; + + out + } } impl<'a> Inspector<&mut dyn DatabaseExt> for InspectorStackRefMut<'a> {