Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 16 additions & 31 deletions crates/evm/core/src/backend/cow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::{
};
use alloy_evm::{Evm, EvmEnv};
use alloy_genesis::GenesisAccount;
use alloy_primitives::{Address, B256, U256};
use alloy_primitives::{Address, B256, TxKind, U256};
use alloy_rpc_types::TransactionRequest;
use eyre::WrapErr;
use foundry_fork_db::DatabaseError;
Expand Down Expand Up @@ -48,15 +48,15 @@ pub struct CowBackend<'a> {
///
/// No calls on the `CowBackend` will ever persistently modify the `backend`'s state.
pub backend: Cow<'a, Backend>,
/// The [SpecId] to initialize the backend with on first mutable access.
/// Pending initialization params for the backend on first mutable access.
/// `None` means the backend has already been initialized for the current call.
spec_id: Option<SpecId>,
pending_init: Option<(SpecId, Address, TxKind)>,
}

impl<'a> CowBackend<'a> {
/// Creates a new `CowBackend` with the given `Backend`.
pub fn new_borrowed(backend: &'a Backend) -> Self {
Self { backend: Cow::Borrowed(backend), spec_id: Some(SpecId::default()) }
Self { backend: Cow::Borrowed(backend), pending_init: None }
}

/// Executes the configured transaction of the `env` without committing state changes
Expand All @@ -71,7 +71,7 @@ impl<'a> CowBackend<'a> {
) -> eyre::Result<ResultAndState> {
// this is a new call to inspect with a new env, so even if we've cloned the backend
// already, we reset the initialized state
self.spec_id = Some(env.evm_env.cfg_env.spec);
self.pending_init = Some((env.evm_env.cfg_env.spec, env.tx.caller, env.tx.kind));

let mut evm = crate::evm::new_evm_with_inspector(
self,
Expand All @@ -97,20 +97,18 @@ impl<'a> CowBackend<'a> {
/// Returns a mutable instance of the Backend.
///
/// If this is the first time this is called, the backed is cloned and initialized.
fn backend_mut(&mut self, evm_env: &EvmEnv, tx_env: &TxEnv) -> &mut Backend {
if let Some(spec_id) = self.spec_id.take() {
fn backend_mut(&mut self) -> &mut Backend {
if let Some((spec_id, caller, tx_kind)) = self.pending_init.take() {
let backend = self.backend.to_mut();
let mut env = Env { evm_env: evm_env.clone(), tx: tx_env.clone() };
env.evm_env.cfg_env.spec = spec_id;
backend.initialize(&env);
backend.initialize(spec_id, caller, tx_kind);
return backend;
}
self.backend.to_mut()
}

/// Returns a mutable instance of the Backend if it is initialized.
fn initialized_backend_mut(&mut self) -> Option<&mut Backend> {
if self.spec_id.is_none() {
if self.pending_init.is_none() {
return Some(self.backend.to_mut());
}
None
Expand All @@ -119,7 +117,7 @@ impl<'a> CowBackend<'a> {

impl DatabaseExt for CowBackend<'_> {
fn snapshot_state(&mut self, journaled_state: &JournaledState, evm_env: &EvmEnv) -> U256 {
self.backend_mut(evm_env, &TxEnv::default()).snapshot_state(journaled_state, evm_env)
self.backend_mut().snapshot_state(journaled_state, evm_env)
}

fn revert_state(
Expand All @@ -130,7 +128,7 @@ impl DatabaseExt for CowBackend<'_> {
tx_env: &mut TxEnv,
action: RevertStateSnapshotAction,
) -> Option<JournaledState> {
self.backend_mut(evm_env, tx_env).revert_state(id, journaled_state, evm_env, tx_env, action)
self.backend_mut().revert_state(id, journaled_state, evm_env, tx_env, action)
}

fn delete_state_snapshot(&mut self, id: U256) -> bool {
Expand Down Expand Up @@ -166,7 +164,7 @@ impl DatabaseExt for CowBackend<'_> {
tx_env: &mut TxEnv,
journaled_state: &mut JournaledState,
) -> eyre::Result<()> {
self.backend_mut(evm_env, tx_env).select_fork(id, evm_env, tx_env, journaled_state)
self.backend_mut().select_fork(id, evm_env, tx_env, journaled_state)
}

fn roll_fork(
Expand All @@ -177,13 +175,7 @@ impl DatabaseExt for CowBackend<'_> {
tx_env: &mut TxEnv,
journaled_state: &mut JournaledState,
) -> eyre::Result<()> {
self.backend_mut(evm_env, tx_env).roll_fork(
id,
block_number,
evm_env,
tx_env,
journaled_state,
)
self.backend_mut().roll_fork(id, block_number, evm_env, tx_env, journaled_state)
}

fn roll_fork_to_transaction(
Expand All @@ -194,7 +186,7 @@ impl DatabaseExt for CowBackend<'_> {
tx_env: &mut TxEnv,
journaled_state: &mut JournaledState,
) -> eyre::Result<()> {
self.backend_mut(evm_env, tx_env).roll_fork_to_transaction(
self.backend_mut().roll_fork_to_transaction(
id,
transaction,
evm_env,
Expand All @@ -212,14 +204,7 @@ impl DatabaseExt for CowBackend<'_> {
journaled_state: &mut JournaledState,
inspector: &mut dyn InspectorExt,
) -> eyre::Result<()> {
self.backend_mut(&evm_env, &tx_env).transact(
id,
transaction,
evm_env,
tx_env,
journaled_state,
inspector,
)
self.backend_mut().transact(id, transaction, evm_env, tx_env, journaled_state, inspector)
}

fn transact_from_tx(
Expand All @@ -230,7 +215,7 @@ impl DatabaseExt for CowBackend<'_> {
journaled_state: &mut JournaledState,
inspector: &mut dyn InspectorExt,
) -> eyre::Result<()> {
self.backend_mut(&evm_env, &tx_env).transact_from_tx(
self.backend_mut().transact_from_tx(
transaction,
evm_env,
tx_env,
Expand Down
18 changes: 8 additions & 10 deletions crates/evm/core/src/backend/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -784,18 +784,16 @@ impl Backend {
/// Initializes settings we need to keep track of.
///
/// We need to track these mainly to prevent issues when switching between different evms
pub(crate) fn initialize(&mut self, env: &Env) {
self.set_caller(env.tx.caller);
self.set_spec_id(env.evm_env.cfg_env.spec);
pub(crate) fn initialize(&mut self, spec_id: SpecId, caller: Address, tx_kind: TxKind) {
self.set_caller(caller);
self.set_spec_id(spec_id);

let test_contract = match env.tx.kind {
let test_contract = match tx_kind {
TxKind::Call(to) => to,
TxKind::Create => {
let nonce = self
.basic_ref(env.tx.caller)
.map(|b| b.unwrap_or_default().nonce)
.unwrap_or_default();
env.tx.caller.create(nonce)
let nonce =
self.basic_ref(caller).map(|b| b.unwrap_or_default().nonce).unwrap_or_default();
caller.create(nonce)
}
};
self.set_test_contract(test_contract);
Expand All @@ -811,7 +809,7 @@ impl Backend {
env: &mut Env,
inspector: I,
) -> eyre::Result<ResultAndState> {
self.initialize(env);
self.initialize(env.evm_env.cfg_env.spec, env.tx.caller, env.tx.kind);
let mut evm = crate::evm::new_evm_with_inspector(
self,
env.evm_env.to_owned(),
Expand Down
Loading