diff --git a/src/custom_journaled_state.rs b/src/custom_journaled_state.rs deleted file mode 100644 index b07a346..0000000 --- a/src/custom_journaled_state.rs +++ /dev/null @@ -1,779 +0,0 @@ -//! Based on https://github.com/bluealloy/revm/blob/17c4543ef559ef4011fa6c155bc981b1f504f33c/crates/context/src/journaled_state.rs - -use std::{collections::hash_map::Entry, convert::Infallible}; - -use revm::{ - context_interface::{ - host::{SStoreResult, SelfDestructResult}, - journaled_state::{AccountLoad, Eip7702CodeLoad, JournalCheckpoint, StateLoad, TransferError}, - }, - specification::hardfork::{SpecId, CANCUN, SPURIOUS_DRAGON}, - state::{Account, EvmState, EvmStorageSlot, TransientStorage}, - Database, JournalEntry, -}; -use revm_bytecode::Bytecode; -use revm_database::InMemoryDB; -use revm_primitives::{Address, HashMap, HashSet, Log, B256, KECCAK_EMPTY, PRECOMPILE3, U256}; - -/// Custom journaled state where the database not part of the journaled state. -/// This is necessary to be able to mutably borrow both the database and the journaled state at the same time. -/// Based on [`revm::JournaledState`]. -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct CustomJournaledState { - /// The current state - pub state: EvmState, - /// Transient storage that is discarded after every transaction. - /// - /// See [EIP-1153](https://eips.ethereum.org/EIPS/eip-1153). - pub transient_storage: TransientStorage, - /// Emitted logs - pub logs: Vec, - /// The current call stack depth - pub depth: usize, - /// The journal of state changes, one for each call - pub journal: Vec>, - /// The spec ID for the EVM - /// - /// This spec is used for two things: - /// - /// - [EIP-161]: Prior to this EIP, Ethereum had separate definitions for empty and non-existing accounts. - /// - [EIP-6780]: `SELFDESTRUCT` only in same transaction - /// - /// [EIP-161]: https://eips.ethereum.org/EIPS/eip-161 - /// [EIP-6780]: https://eips.ethereum.org/EIPS/eip-6780 - pub spec: SpecId, - /// Warm loaded addresses are used to check if loaded address - /// should be considered cold or warm loaded when the account - /// is first accessed. - /// - /// Note that this not include newly loaded accounts, account and storage - /// is considered warm if it is found in the `State`. - pub warm_preloaded_addresses: HashSet
, -} - -impl CustomJournaledState { - pub fn new(spec: SpecId) -> Self { - Self { - state: HashMap::default(), - transient_storage: TransientStorage::default(), - logs: Vec::new(), - journal: vec![vec![]], - depth: 0, - spec, - warm_preloaded_addresses: HashSet::default(), - } - } - - /// Return reference to state. - #[inline] - pub fn state(&mut self) -> &mut EvmState { - &mut self.state - } - - /// Sets SpecId. - #[inline] - pub fn set_spec_id(&mut self, spec: SpecId) { - self.spec = spec; - } - - /// Mark account as touched as only touched accounts will be added to state. - /// This is especially important for state clear where touched empty accounts needs to - /// be removed from state. - #[inline] - pub fn touch(&mut self, address: &Address) { - if let Some(account) = self.state.get_mut(address) { - Self::touch_account(self.journal.last_mut().unwrap(), address, account); - } - } - - /// Mark account as touched. - #[inline] - fn touch_account(journal: &mut Vec, address: &Address, account: &mut Account) { - if !account.is_touched() { - journal.push(JournalEntry::AccountTouched { address: *address }); - account.mark_touch(); - } - } - - /// Returns the _loaded_ [Account] for the given address. - /// - /// This assumes that the account has already been loaded. - /// - /// # Panics - /// - /// Panics if the account has not been loaded and is missing from the state set. - #[inline] - pub fn account(&self, address: Address) -> &Account { - self.state.get(&address).expect("Account expected to be loaded") // Always assume that acc is already loaded - } - - /// Set code and its hash to the account. - /// - /// Note: Assume account is warm and that hash is calculated from code. - #[inline] - pub fn set_code_with_hash(&mut self, address: Address, code: Bytecode, hash: B256) { - let account = self.state.get_mut(&address).unwrap(); - Self::touch_account(self.journal.last_mut().unwrap(), &address, account); - - self.journal - .last_mut() - .unwrap() - .push(JournalEntry::CodeChange { address }); - - account.info.code_hash = hash; - account.info.code = Some(code); - } - - /// Use it only if you know that acc is warm. - /// - /// Assume account is warm. - #[inline] - pub fn set_code(&mut self, address: Address, code: Bytecode) { - let hash = code.hash_slow(); - self.set_code_with_hash(address, code, hash) - } - - #[inline] - pub fn inc_nonce(&mut self, address: Address) -> Option { - let account = self.state.get_mut(&address).unwrap(); - // Check if nonce is going to overflow. - if account.info.nonce == u64::MAX { - return None; - } - Self::touch_account(self.journal.last_mut().unwrap(), &address, account); - self.journal - .last_mut() - .unwrap() - .push(JournalEntry::NonceChange { address }); - - account.info.nonce += 1; - - Some(account.info.nonce) - } - - /// Transfers balance from two accounts. Returns error if sender balance is not enough. - #[inline] - pub fn transfer( - &mut self, - database: &mut InMemoryDB, - from: &Address, - to: &Address, - balance: U256, - ) -> Result, Infallible> { - if balance.is_zero() { - self.load_account(database, *to)?; - let _ = self.load_account(database, *to)?; - let to_account = self.state.get_mut(to).unwrap(); - Self::touch_account(self.journal.last_mut().unwrap(), to, to_account); - return Ok(None); - } - // load accounts - self.load_account(database, *from)?; - self.load_account(database, *to)?; - - // sub balance from - let from_account = &mut self.state.get_mut(from).unwrap(); - Self::touch_account(self.journal.last_mut().unwrap(), from, from_account); - let from_balance = &mut from_account.info.balance; - - let Some(from_balance_incr) = from_balance.checked_sub(balance) else { - return Ok(Some(TransferError::OutOfFunds)); - }; - *from_balance = from_balance_incr; - - // add balance to - let to_account = &mut self.state.get_mut(to).unwrap(); - Self::touch_account(self.journal.last_mut().unwrap(), to, to_account); - let to_balance = &mut to_account.info.balance; - let Some(to_balance_decr) = to_balance.checked_add(balance) else { - return Ok(Some(TransferError::OverflowPayment)); - }; - *to_balance = to_balance_decr; - // Overflow of U256 balance is not possible to happen on mainnet. We don't bother to return funds from from_acc. - - self.journal.last_mut().unwrap().push(JournalEntry::BalanceTransfer { - from: *from, - to: *to, - balance, - }); - - Ok(None) - } - - /// Creates account or returns false if collision is detected. - /// - /// There are few steps done: - /// 1. Make created account warm loaded (AccessList) and this should be done before subroutine checkpoint is - /// created. - /// 2. Check if there is collision of newly created account with existing one. - /// 3. Mark created account as created. - /// 4. Add fund to created account - /// 5. Increment nonce of created account if SpuriousDragon is active - /// 6. Decrease balance of caller account. - /// - /// # Panics - /// - /// Panics if the caller is not loaded inside of the EVM state. - /// This is should have been done inside `create_inner`. - #[inline] - pub fn create_account_checkpoint( - &mut self, - caller: Address, - target_address: Address, - balance: U256, - spec_id: SpecId, - ) -> Result { - // Enter subroutine - let checkpoint = self.checkpoint(); - - // Fetch balance of caller. - let caller_acc = self.state.get_mut(&caller).unwrap(); - // Check if caller has enough balance to send to the created contract. - if caller_acc.info.balance < balance { - self.checkpoint_revert(checkpoint); - return Err(TransferError::OutOfFunds); - } - - // Newly created account is present, as we just loaded it. - let target_acc = self.state.get_mut(&target_address).unwrap(); - let last_journal = self.journal.last_mut().unwrap(); - - // New account can be created if: - // Bytecode is not empty. - // Nonce is not zero - // Account is not precompile. - if target_acc.info.code_hash != KECCAK_EMPTY || target_acc.info.nonce != 0 { - self.checkpoint_revert(checkpoint); - return Err(TransferError::CreateCollision); - } - - // set account status to created. - target_acc.mark_created(); - - // this entry will revert set nonce. - last_journal.push(JournalEntry::AccountCreated { - address: target_address, - }); - target_acc.info.code = None; - // EIP-161: State trie clearing (invariant-preserving alternative) - if spec_id.is_enabled_in(SPURIOUS_DRAGON) { - // nonce is going to be reset to zero in AccountCreated journal entry. - target_acc.info.nonce = 1; - } - - // touch account. This is important as for pre SpuriousDragon account could be - // saved even empty. - Self::touch_account(last_journal, &target_address, target_acc); - - // Add balance to created account, as we already have target here. - let Some(new_balance) = target_acc.info.balance.checked_add(balance) else { - self.checkpoint_revert(checkpoint); - return Err(TransferError::OverflowPayment); - }; - target_acc.info.balance = new_balance; - - // safe to decrement for the caller as balance check is already done. - self.state.get_mut(&caller).unwrap().info.balance -= balance; - - // add journal entry of transferred balance - last_journal.push(JournalEntry::BalanceTransfer { - from: caller, - to: target_address, - balance, - }); - - Ok(checkpoint) - } - - /// Reverts all changes that happened in given journal entries. - #[inline] - fn journal_revert( - state: &mut EvmState, - transient_storage: &mut TransientStorage, - journal_entries: Vec, - is_spurious_dragon_enabled: bool, - ) { - for entry in journal_entries.into_iter().rev() { - match entry { - JournalEntry::AccountWarmed { address } => { - state.get_mut(&address).unwrap().mark_cold(); - } - JournalEntry::AccountTouched { address } => { - if is_spurious_dragon_enabled && address == PRECOMPILE3 { - continue; - } - // remove touched status - state.get_mut(&address).unwrap().unmark_touch(); - } - JournalEntry::AccountDestroyed { - address, - target, - was_destroyed, - had_balance, - } => { - let account = state.get_mut(&address).unwrap(); - // set previous state of selfdestructed flag, as there could be multiple - // selfdestructs in one transaction. - if was_destroyed { - // flag is still selfdestructed - account.mark_selfdestruct(); - } else { - // flag that is not selfdestructed - account.unmark_selfdestruct(); - } - account.info.balance += had_balance; - - if address != target { - let target = state.get_mut(&target).unwrap(); - target.info.balance -= had_balance; - } - } - JournalEntry::BalanceTransfer { from, to, balance } => { - // we don't need to check overflow and underflow when adding and subtracting the balance. - let from = state.get_mut(&from).unwrap(); - from.info.balance += balance; - let to = state.get_mut(&to).unwrap(); - to.info.balance -= balance; - } - JournalEntry::NonceChange { address } => { - state.get_mut(&address).unwrap().info.nonce -= 1; - } - JournalEntry::AccountCreated { address } => { - let account = &mut state.get_mut(&address).unwrap(); - account.unmark_created(); - account.storage.values_mut().for_each(|slot| slot.mark_cold()); - account.info.nonce = 0; - } - JournalEntry::StorageWarmed { address, key } => { - state - .get_mut(&address) - .unwrap() - .storage - .get_mut(&key) - .unwrap() - .mark_cold(); - } - JournalEntry::StorageChanged { - address, - key, - had_value, - } => { - state - .get_mut(&address) - .unwrap() - .storage - .get_mut(&key) - .unwrap() - .present_value = had_value; - } - JournalEntry::TransientStorageChange { - address, - key, - had_value, - } => { - let tkey = (address, key); - if had_value.is_zero() { - // if previous value is zero, remove it - transient_storage.remove(&tkey); - } else { - // if not zero, reinsert old value to transient storage. - transient_storage.insert(tkey, had_value); - } - } - JournalEntry::CodeChange { address } => { - let acc = state.get_mut(&address).unwrap(); - acc.info.code_hash = KECCAK_EMPTY; - acc.info.code = None; - } - } - } - } - - /// Makes a checkpoint that in case of Revert can bring back state to this point. - #[inline] - pub fn checkpoint(&mut self) -> JournalCheckpoint { - let checkpoint = JournalCheckpoint { - log_i: self.logs.len(), - journal_i: self.journal.len(), - }; - self.depth += 1; - self.journal.push(Default::default()); - checkpoint - } - - /// Commits the checkpoint. - #[inline] - pub fn checkpoint_commit(&mut self) { - self.depth -= 1; - } - - /// Reverts all changes to state until given checkpoint. - #[inline] - pub fn checkpoint_revert(&mut self, checkpoint: JournalCheckpoint) { - let is_spurious_dragon_enabled = self.spec.is_enabled_in(SPURIOUS_DRAGON); - let state = &mut self.state; - let transient_storage = &mut self.transient_storage; - self.depth -= 1; - // iterate over last N journals sets and revert our global state - let leng = self.journal.len(); - self.journal - .iter_mut() - .rev() - .take(leng - checkpoint.journal_i) - .for_each(|cs| { - Self::journal_revert(state, transient_storage, std::mem::take(cs), is_spurious_dragon_enabled) - }); - - self.logs.truncate(checkpoint.log_i); - self.journal.truncate(checkpoint.journal_i); - } - - /// Performs selfdestruct action. - /// Transfers balance from address to target. Check if target exist/is_cold - /// - /// Note: Balance will be lost if address and target are the same BUT when - /// current spec enables Cancun, this happens only when the account associated to address - /// is created in the same tx - /// - /// # References: - /// * - /// * - /// * - #[inline] - pub fn selfdestruct( - &mut self, - database: &mut InMemoryDB, - address: Address, - target: Address, - ) -> Result, Infallible> { - let spec = self.spec; - let account_load = self.load_account(database, target)?; - let is_cold = account_load.is_cold; - let is_empty = account_load.state_clear_aware_is_empty(spec); - - if address != target { - // Both accounts are loaded before this point, `address` as we execute its contract. - // and `target` at the beginning of the function. - let acc_balance = self.state.get_mut(&address).unwrap().info.balance; - - let target_account = self.state.get_mut(&target).unwrap(); - Self::touch_account(self.journal.last_mut().unwrap(), &target, target_account); - target_account.info.balance += acc_balance; - } - - let acc = self.state.get_mut(&address).unwrap(); - let balance = acc.info.balance; - let previously_destroyed = acc.is_selfdestructed(); - let is_cancun_enabled = self.spec.is_enabled_in(CANCUN); - - // EIP-6780 (Cancun hard-fork): selfdestruct only if contract is created in the same tx - let journal_entry = if acc.is_created() || !is_cancun_enabled { - acc.mark_selfdestruct(); - acc.info.balance = U256::ZERO; - Some(JournalEntry::AccountDestroyed { - address, - target, - was_destroyed: previously_destroyed, - had_balance: balance, - }) - } else if address != target { - acc.info.balance = U256::ZERO; - Some(JournalEntry::BalanceTransfer { - from: address, - to: target, - balance, - }) - } else { - // State is not changed: - // * if we are after Cancun upgrade and - // * Selfdestruct account that is created in the same transaction and - // * Specify the target is same as selfdestructed account. The balance stays unchanged. - None - }; - - if let Some(entry) = journal_entry { - self.journal.last_mut().unwrap().push(entry); - }; - - Ok(StateLoad { - data: SelfDestructResult { - had_value: !balance.is_zero(), - target_exists: !is_empty, - previously_destroyed, - }, - is_cold, - }) - } - - /// Initial load of account. This load will not be tracked inside journal - #[inline] - pub fn initial_account_load( - &mut self, - database: &mut InMemoryDB, - address: Address, - storage_keys: impl IntoIterator, - ) -> Result<&mut Account, Infallible> { - // load or get account. - let account = match self.state.entry(address) { - Entry::Occupied(entry) => entry.into_mut(), - Entry::Vacant(vac) => vac.insert( - database - .basic(address)? - .map(|i| i.into()) - .unwrap_or(Account::new_not_existing()), - ), - }; - // preload storages. - for storage_key in storage_keys.into_iter() { - if let Entry::Vacant(entry) = account.storage.entry(storage_key) { - let storage = database.storage(address, storage_key)?; - entry.insert(EvmStorageSlot::new(storage)); - } - } - Ok(account) - } - - /// Loads account into memory. return if it is cold or warm accessed - #[inline] - pub fn load_account( - &mut self, - database: &mut InMemoryDB, - address: Address, - ) -> Result, Infallible> { - self.load_account_optional(database, address, false) - } - - #[inline] - pub fn load_account_delegated( - &mut self, - database: &mut InMemoryDB, - address: Address, - ) -> Result { - let spec = self.spec; - let account = self.load_code(database, address)?; - let is_empty = account.state_clear_aware_is_empty(spec); - - let mut account_load = AccountLoad { - is_empty, - load: Eip7702CodeLoad::new_not_delegated((), account.is_cold), - }; - // load delegate code if account is EIP-7702 - if let Some(Bytecode::Eip7702(code)) = &account.info.code { - let address = code.address(); - let delegate_account = self.load_account(database, address)?; - account_load.load.set_delegate_load(delegate_account.is_cold); - } - - Ok(account_load) - } - - pub fn load_code( - &mut self, - database: &mut InMemoryDB, - address: Address, - ) -> Result, Infallible> { - self.load_account_optional(database, address, true) - } - - /// Loads code - #[inline] - pub fn load_account_optional( - &mut self, - database: &mut InMemoryDB, - address: Address, - load_code: bool, - ) -> Result, Infallible> { - let load = match self.state.entry(address) { - Entry::Occupied(entry) => { - let account = entry.into_mut(); - let is_cold = account.mark_warm(); - StateLoad { data: account, is_cold } - } - Entry::Vacant(vac) => { - let account = if let Some(account) = database.basic(address)? { - account.into() - } else { - Account::new_not_existing() - }; - - // precompiles are warm loaded so we need to take that into account - let is_cold = !self.warm_preloaded_addresses.contains(&address); - - StateLoad { - data: vac.insert(account), - is_cold, - } - } - }; - // journal loading of cold account. - if load.is_cold { - self.journal - .last_mut() - .unwrap() - .push(JournalEntry::AccountWarmed { address }); - } - if load_code { - let info = &mut load.data.info; - if info.code.is_none() { - if info.code_hash == KECCAK_EMPTY { - let empty = Bytecode::default(); - info.code = Some(empty); - } else { - let code = database.code_by_hash(info.code_hash)?; - info.code = Some(code); - } - } - } - - Ok(load) - } - - /// Loads storage slot. - /// - /// # Panics - /// - /// Panics if the account is not present in the state. - #[inline] - pub fn sload( - &mut self, - database: &mut InMemoryDB, - address: Address, - key: U256, - ) -> Result, Infallible> { - // assume acc is warm - let account = self.state.get_mut(&address).unwrap(); - // only if account is created in this tx we can assume that storage is empty. - let is_newly_created = account.is_created(); - let (value, is_cold) = match account.storage.entry(key) { - Entry::Occupied(occ) => { - let slot = occ.into_mut(); - let is_cold = slot.mark_warm(); - (slot.present_value, is_cold) - } - Entry::Vacant(vac) => { - // if storage was cleared, we don't need to ping db. - let value = if is_newly_created { - U256::ZERO - } else { - database.storage(address, key)? - }; - - vac.insert(EvmStorageSlot::new(value)); - - (value, true) - } - }; - - if is_cold { - // add it to journal as cold loaded. - self.journal - .last_mut() - .unwrap() - .push(JournalEntry::StorageWarmed { address, key }); - } - - Ok(StateLoad::new(value, is_cold)) - } - - /// Stores storage slot. - /// - /// And returns (original,present,new) slot value. - /// - /// **Note**: Account should already be present in our state. - #[inline] - pub fn sstore( - &mut self, - database: &mut InMemoryDB, - address: Address, - key: U256, - new: U256, - ) -> Result, Infallible> { - // assume that acc exists and load the slot. - let present = self.sload(database, address, key)?; - let acc = self.state.get_mut(&address).unwrap(); - - // if there is no original value in dirty return present value, that is our original. - let slot = acc.storage.get_mut(&key).unwrap(); - - // new value is same as present, we don't need to do anything - if present.data == new { - return Ok(StateLoad::new( - SStoreResult { - original_value: slot.original_value(), - present_value: present.data, - new_value: new, - }, - present.is_cold, - )); - } - - self.journal.last_mut().unwrap().push(JournalEntry::StorageChanged { - address, - key, - had_value: present.data, - }); - // insert value into present state. - slot.present_value = new; - Ok(StateLoad::new( - SStoreResult { - original_value: slot.original_value(), - present_value: present.data, - new_value: new, - }, - present.is_cold, - )) - } - - /// Read transient storage tied to the account. - /// - /// EIP-1153: Transient storage opcodes - #[inline] - pub fn tload(&mut self, address: Address, key: U256) -> U256 { - self.transient_storage.get(&(address, key)).copied().unwrap_or_default() - } - - /// Store transient storage tied to the account. - /// - /// If values is different add entry to the journal - /// so that old state can be reverted if that action is needed. - /// - /// EIP-1153: Transient storage opcodes - #[inline] - pub fn tstore(&mut self, address: Address, key: U256, new: U256) { - let had_value = if new.is_zero() { - // if new values is zero, remove entry from transient storage. - // if previous values was some insert it inside journal. - // If it is none nothing should be inserted. - self.transient_storage.remove(&(address, key)) - } else { - // insert values - let previous_value = self.transient_storage.insert((address, key), new).unwrap_or_default(); - - // check if previous value is same - if previous_value != new { - // if it is different, insert previous values inside journal. - Some(previous_value) - } else { - None - } - }; - - if let Some(had_value) = had_value { - // insert in journal only if value was changed. - self.journal - .last_mut() - .unwrap() - .push(JournalEntry::TransientStorageChange { - address, - key, - had_value, - }); - } - } - - /// Pushes log into subroutine. - #[inline] - pub fn log(&mut self, log: Log) { - self.logs.push(log); - } -} diff --git a/src/lib.rs b/src/lib.rs index 82ce5fb..9a8f4ac 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,8 +6,6 @@ //! cheatcodes that proved difficult to implement with the new interface. //! Both of these cheatcodes initiate transactions from a call step in the cheatcode inspector. -pub mod custom_journaled_state; - use std::{convert::Infallible, fmt::Debug}; use revm::{ @@ -23,7 +21,7 @@ use revm::{ precompile::{Address, B256}, specification::hardfork::SpecId, state::{Account, EvmState, TransientStorage}, - Context, Database, DatabaseCommit, Evm, JournalEntry, + Context, Database, DatabaseCommit, Evm, JournalEntry, JournaledState, }; use revm_bytecode::Bytecode; use revm_database::InMemoryDB; @@ -34,15 +32,12 @@ use revm_inspector::{ use revm_interpreter::{interpreter::EthInterpreter, CallInputs, CallOutcome}; use revm_primitives::{Log, U256}; -use crate::custom_journaled_state::CustomJournaledState; - /// Backend for cheatcodes. /// The problematic cheatcodes are only supported in fork mode, so we'll omit the non-fork behavior of the `Backend`. #[derive(Clone, Debug)] pub struct Backend { /// In fork mode, Foundry stores (`JournaledState`, `Database`) pairs for each fork. - db: InMemoryDB, - journaled_state: CustomJournaledState, + journaled_state: JournaledState, /// Counters to be able to assert that we mutated the object that we expected to mutate. method_with_inspector_counter: usize, method_without_inspector_counter: usize, @@ -51,8 +46,7 @@ pub struct Backend { impl Backend { pub fn new(spec: SpecId, db: InMemoryDB) -> Self { Self { - db, - journaled_state: CustomJournaledState::new(spec), + journaled_state: JournaledState::new(spec, db), method_with_inspector_counter: 0, method_without_inspector_counter: 0, } @@ -69,15 +63,15 @@ impl Journal for Backend { } fn db(&self) -> &Self::Database { - &self.db + &self.journaled_state.database } fn db_mut(&mut self) -> &mut Self::Database { - &mut self.db + &mut self.journaled_state.database } fn sload(&mut self, address: Address, key: U256) -> Result, ::Error> { - self.journaled_state.sload(&mut self.db, address, key) + self.journaled_state.sload(address, key) } fn sstore( @@ -86,7 +80,7 @@ impl Journal for Backend { key: U256, value: U256, ) -> Result, ::Error> { - self.journaled_state.sstore(&mut self.db, address, key, value) + self.journaled_state.sstore(address, key, value) } fn tload(&mut self, address: Address, key: U256) -> U256 { @@ -102,7 +96,7 @@ impl Journal for Backend { } fn selfdestruct(&mut self, address: Address, target: Address) -> Result, Infallible> { - self.journaled_state.selfdestruct(&mut self.db, address, target) + self.journaled_state.selfdestruct(address, target) } fn warm_account(&mut self, address: Address) { @@ -120,8 +114,7 @@ impl Journal for Backend { address: Address, storage_keys: impl IntoIterator, ) -> Result<(), ::Error> { - self.journaled_state - .initial_account_load(&mut self.db, address, storage_keys)?; + self.journaled_state.initial_account_load(address, storage_keys)?; Ok(()) } @@ -131,7 +124,7 @@ impl Journal for Backend { fn transfer(&mut self, from: &Address, to: &Address, balance: U256) -> Result, Infallible> { // TODO : Handle instruction result - self.journaled_state.transfer(&mut self.db, from, to, balance) + self.journaled_state.transfer(from, to, balance) } fn touch_account(&mut self, address: Address) { @@ -143,15 +136,15 @@ impl Journal for Backend { } fn load_account(&mut self, address: Address) -> Result, Infallible> { - self.journaled_state.load_account(&mut self.db, address) + self.journaled_state.load_account(address) } fn load_account_code(&mut self, address: Address) -> Result, Infallible> { - self.journaled_state.load_code(&mut self.db, address) + self.journaled_state.load_code(address) } fn load_account_delegated(&mut self, address: Address) -> Result { - self.journaled_state.load_account_delegated(&mut self.db, address) + self.journaled_state.load_account_delegated(address) } fn checkpoint(&mut self) -> JournalCheckpoint { @@ -193,13 +186,14 @@ impl Journal for Backend { } fn finalize(&mut self) -> Result::Error> { - let CustomJournaledState { + let JournaledState { state, transient_storage, logs, depth, journal, // kept, see [Self::new] + database: _, spec: _, warm_preloaded_addresses: _, } = &mut self.journaled_state; @@ -470,8 +464,11 @@ where let result = evm.transact()?; // Persist the changes to the original backend. - backend.db.commit(result.state); - update_state(&mut backend.journaled_state.state, &mut backend.db)?; + backend.journaled_state.database.commit(result.state); + update_state( + &mut backend.journaled_state.state, + &mut backend.journaled_state.database, + )?; Ok(()) }