anvil/eth/backend/mem/
fork_db.rs1use 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 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}