Skip to main content

anvil/eth/backend/mem/
fork_db.rs

1use crate::eth::backend::db::{
2    Db, MaybeForkedDatabase, MaybeFullDatabase, SerializableAccountRecord, SerializableBlock,
3    SerializableHistoricalStates, SerializableState, SerializableTransaction, StateDb,
4    cache_block_hash,
5};
6use alloy_network::Network;
7use alloy_primitives::{Address, B256, U256, map::AddressMap};
8use alloy_rpc_types::BlockId;
9use foundry_evm::{
10    backend::{
11        BlockchainDb, DatabaseResult, RevertStateSnapshotAction, SharedBackend, StateSnapshot,
12    },
13    fork::database::ForkDbStateSnapshot,
14};
15use revm::{
16    context::BlockEnv,
17    database::{Database, DbAccount},
18    state::AccountInfo,
19};
20
21pub use foundry_evm::fork::database::ForkedDatabase;
22
23impl<N: Network> MaybeFullDatabase for SharedBackend<N> {
24    fn clear_into_state_snapshot(&mut self) -> StateSnapshot {
25        StateSnapshot::default()
26    }
27
28    fn read_as_state_snapshot(&self) -> StateSnapshot {
29        StateSnapshot::default()
30    }
31
32    fn clear(&mut self) {}
33
34    fn init_from_state_snapshot(&mut self, _state_snapshot: StateSnapshot) {}
35}
36
37impl<N: Network> Db for ForkedDatabase<N> {
38    fn insert_account(&mut self, address: Address, account: AccountInfo) {
39        self.database_mut().insert_account(address, account)
40    }
41
42    fn set_storage_at(&mut self, address: Address, slot: B256, val: B256) -> DatabaseResult<()> {
43        // this ensures the account is loaded first
44        let _ = Database::basic(self, address)?;
45        self.database_mut().set_storage_at(address, slot, val)
46    }
47
48    fn insert_block_hash(&mut self, number: U256, hash: B256) {
49        cache_block_hash(&mut self.database_mut().cache.block_hashes, number, hash);
50    }
51
52    fn set_block_hashes(&mut self, block_hashes: Vec<(U256, B256)>) {
53        self.database_mut().cache.block_hashes = block_hashes.into_iter().collect();
54    }
55
56    fn dump_state(
57        &self,
58        at: BlockEnv,
59        best_number: u64,
60        blocks: Vec<SerializableBlock>,
61        transactions: Vec<SerializableTransaction>,
62        historical_states: Option<SerializableHistoricalStates>,
63    ) -> DatabaseResult<Option<SerializableState>> {
64        let mut db = self.database().clone();
65        let accounts = self
66            .database()
67            .cache
68            .accounts
69            .clone()
70            .into_iter()
71            .map(|(k, v)| -> DatabaseResult<_> {
72                let code = if let Some(code) = v.info.code {
73                    code
74                } else {
75                    db.code_by_hash(v.info.code_hash())?
76                };
77                Ok((
78                    k,
79                    SerializableAccountRecord {
80                        nonce: v.info.nonce,
81                        balance: v.info.balance,
82                        code: code.original_bytes(),
83                        storage: v.storage.into_iter().map(|(k, v)| (k.into(), v.into())).collect(),
84                    },
85                ))
86            })
87            .collect::<Result<_, _>>()?;
88        Ok(Some(SerializableState {
89            block: Some(at),
90            accounts,
91            best_block_number: Some(best_number),
92            blocks,
93            transactions,
94            #[cfg(feature = "monad")]
95            monad_block_participants: Default::default(),
96            #[cfg(feature = "monad")]
97            monad_block_replay_profiles: Default::default(),
98            historical_states,
99        }))
100    }
101
102    fn snapshot_state(&mut self) -> U256 {
103        self.insert_state_snapshot()
104    }
105
106    fn revert_state(&mut self, id: U256, action: RevertStateSnapshotAction) -> bool {
107        self.revert_state_snapshot(id, action)
108    }
109
110    fn delete_state_snapshot(&mut self, id: U256) -> bool {
111        self.state_snapshots().lock().remove_at(id).is_some()
112    }
113
114    fn current_state(&self) -> StateDb {
115        StateDb::new(self.create_state_snapshot())
116    }
117}
118
119impl<N: Network> MaybeFullDatabase for ForkedDatabase<N> {
120    fn maybe_as_full_db(&self) -> Option<&AddressMap<DbAccount>> {
121        Some(&self.database().cache.accounts)
122    }
123
124    fn maybe_as_full_db_mut(&mut self) -> Option<&mut AddressMap<DbAccount>> {
125        Some(&mut self.database_mut().cache.accounts)
126    }
127
128    fn maybe_full_db(&self) -> Option<AddressMap<DbAccount>> {
129        None
130    }
131
132    fn clear_into_state_snapshot(&mut self) -> StateSnapshot {
133        let db = self.inner().db();
134        let accounts = std::mem::take(&mut *db.accounts.write());
135        let storage = std::mem::take(&mut *db.storage.write());
136        let block_hashes = std::mem::take(&mut *db.block_hashes.write());
137        StateSnapshot { accounts, storage, block_hashes }
138    }
139
140    fn read_as_state_snapshot(&self) -> StateSnapshot {
141        let db = self.inner().db();
142        let accounts = db.accounts.read().clone();
143        let storage = db.storage.read().clone();
144        let block_hashes = db.block_hashes.read().clone();
145        StateSnapshot { accounts, storage, block_hashes }
146    }
147
148    fn clear(&mut self) {
149        self.flush_cache();
150        self.clear_into_state_snapshot();
151    }
152
153    fn init_from_state_snapshot(&mut self, state_snapshot: StateSnapshot) {
154        let db = self.inner().db();
155        let StateSnapshot { accounts, storage, block_hashes } = state_snapshot;
156        *db.accounts.write() = accounts;
157        *db.storage.write() = storage;
158        *db.block_hashes.write() = block_hashes;
159    }
160}
161
162impl<N: Network> MaybeFullDatabase for ForkDbStateSnapshot<N> {
163    fn maybe_as_full_db(&self) -> Option<&AddressMap<DbAccount>> {
164        Some(&self.local.cache.accounts)
165    }
166
167    fn maybe_full_db(&self) -> Option<AddressMap<DbAccount>> {
168        None
169    }
170
171    fn clear_into_state_snapshot(&mut self) -> StateSnapshot {
172        let mut state_snapshot = std::mem::take(&mut self.state_snapshot);
173        let local_state_snapshot = self.local.clear_into_state_snapshot();
174        state_snapshot.accounts.extend(local_state_snapshot.accounts);
175        state_snapshot.storage.extend(local_state_snapshot.storage);
176        state_snapshot.block_hashes.extend(local_state_snapshot.block_hashes);
177        state_snapshot
178    }
179
180    fn read_as_state_snapshot(&self) -> StateSnapshot {
181        let mut state_snapshot = self.state_snapshot.clone();
182        let local_state_snapshot = self.local.read_as_state_snapshot();
183        state_snapshot.accounts.extend(local_state_snapshot.accounts);
184        state_snapshot.storage.extend(local_state_snapshot.storage);
185        state_snapshot.block_hashes.extend(local_state_snapshot.block_hashes);
186        state_snapshot
187    }
188
189    fn clear(&mut self) {
190        std::mem::take(&mut self.state_snapshot);
191        self.local.clear()
192    }
193
194    fn init_from_state_snapshot(&mut self, state_snapshot: StateSnapshot) {
195        self.state_snapshot = state_snapshot;
196    }
197}
198
199impl<N: Network> MaybeForkedDatabase for ForkedDatabase<N> {
200    fn maybe_reset(&mut self, urls: Vec<String>, block_number: BlockId) -> Result<(), String> {
201        self.reset(urls, block_number)
202    }
203
204    fn maybe_flush_cache(&self) -> Result<(), String> {
205        self.flush_cache();
206        Ok(())
207    }
208
209    fn maybe_inner(&self) -> Result<&BlockchainDb, String> {
210        Ok(self.inner())
211    }
212}