foundry_evm_core/backend/
snapshot.rs

1use super::JournaledState;
2use crate::Env;
3use alloy_primitives::{
4    map::{AddressHashMap, HashMap},
5    B256, U256,
6};
7use revm::state::AccountInfo;
8use serde::{Deserialize, Serialize};
9
10/// A minimal abstraction of a state at a certain point in time
11#[derive(Clone, Debug, Default, Serialize, Deserialize)]
12pub struct StateSnapshot {
13    pub accounts: AddressHashMap<AccountInfo>,
14    pub storage: AddressHashMap<HashMap<U256, U256>>,
15    pub block_hashes: HashMap<U256, B256>,
16}
17
18/// Represents a state snapshot taken during evm execution
19#[derive(Clone, Debug)]
20pub struct BackendStateSnapshot<T> {
21    pub db: T,
22    /// The journaled_state state at a specific point
23    pub journaled_state: JournaledState,
24    /// Contains the env at the time of the snapshot
25    pub env: Env,
26}
27
28impl<T> BackendStateSnapshot<T> {
29    /// Takes a new state snapshot.
30    pub fn new(db: T, journaled_state: JournaledState, env: Env) -> Self {
31        Self { db, journaled_state, env }
32    }
33
34    /// Called when this state snapshot is reverted.
35    ///
36    /// Since we want to keep all additional logs that were emitted since the snapshot was taken
37    /// we'll merge additional logs into the snapshot's `revm::JournaledState`. Additional logs are
38    /// those logs that are missing in the snapshot's journaled_state, since the current
39    /// journaled_state includes the same logs, we can simply replace use that See also
40    /// `DatabaseExt::revert`.
41    pub fn merge(&mut self, current: &JournaledState) {
42        self.journaled_state.logs.clone_from(&current.logs);
43    }
44}
45
46/// What to do when reverting a state snapshot.
47///
48/// Whether to remove the state snapshot or keep it.
49#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
50pub enum RevertStateSnapshotAction {
51    /// Remove the state snapshot after reverting.
52    #[default]
53    RevertRemove,
54    /// Keep the state snapshot after reverting.
55    RevertKeep,
56}
57
58impl RevertStateSnapshotAction {
59    /// Returns `true` if the action is to keep the state snapshot.
60    pub fn is_keep(&self) -> bool {
61        matches!(self, Self::RevertKeep)
62    }
63}