foundry_evm_core/backend/
in_memory_db.rs1use crate::state_snapshot::StateSnapshots;
4use alloy_primitives::{Address, B256, U256};
5use foundry_fork_db::DatabaseError;
6use revm::{
7 Database, DatabaseCommit,
8 bytecode::Bytecode,
9 database::{CacheDB, DatabaseRef, EmptyDB},
10 primitives::HashMap as Map,
11 state::{Account, AccountInfo},
12};
13
14pub type FoundryEvmInMemoryDB = CacheDB<EmptyDBWrapper>;
18
19#[derive(Debug)]
23pub struct MemDb {
24 pub inner: FoundryEvmInMemoryDB,
25 pub state_snapshots: StateSnapshots<FoundryEvmInMemoryDB>,
26}
27
28impl Default for MemDb {
29 fn default() -> Self {
30 Self { inner: CacheDB::new(Default::default()), state_snapshots: Default::default() }
31 }
32}
33
34impl DatabaseRef for MemDb {
35 type Error = DatabaseError;
36
37 fn basic_ref(&self, address: Address) -> Result<Option<AccountInfo>, Self::Error> {
38 DatabaseRef::basic_ref(&self.inner, address)
39 }
40
41 fn code_by_hash_ref(&self, code_hash: B256) -> Result<Bytecode, Self::Error> {
42 DatabaseRef::code_by_hash_ref(&self.inner, code_hash)
43 }
44
45 fn storage_ref(&self, address: Address, index: U256) -> Result<U256, Self::Error> {
46 DatabaseRef::storage_ref(&self.inner, address, index)
47 }
48
49 fn block_hash_ref(&self, number: u64) -> Result<B256, Self::Error> {
50 DatabaseRef::block_hash_ref(&self.inner, number)
51 }
52}
53
54impl Database for MemDb {
55 type Error = DatabaseError;
56
57 fn basic(&mut self, address: Address) -> Result<Option<AccountInfo>, Self::Error> {
58 Database::basic(&mut self.inner, address)
60 }
61
62 fn code_by_hash(&mut self, code_hash: B256) -> Result<Bytecode, Self::Error> {
63 Database::code_by_hash(&mut self.inner, code_hash)
64 }
65
66 fn storage(&mut self, address: Address, index: U256) -> Result<U256, Self::Error> {
67 Database::storage(&mut self.inner, address, index)
68 }
69
70 fn block_hash(&mut self, number: u64) -> Result<B256, Self::Error> {
71 Database::block_hash(&mut self.inner, number)
72 }
73}
74
75impl DatabaseCommit for MemDb {
76 fn commit(&mut self, changes: Map<Address, Account>) {
77 DatabaseCommit::commit(&mut self.inner, changes)
78 }
79}
80
81#[derive(Clone, Debug, Default)]
99pub struct EmptyDBWrapper(EmptyDB);
100
101impl DatabaseRef for EmptyDBWrapper {
102 type Error = DatabaseError;
103
104 fn basic_ref(&self, _address: Address) -> Result<Option<AccountInfo>, Self::Error> {
105 Ok(Some(AccountInfo::default()))
107 }
108
109 fn code_by_hash_ref(&self, code_hash: B256) -> Result<Bytecode, Self::Error> {
110 Ok(self.0.code_by_hash_ref(code_hash)?)
111 }
112 fn storage_ref(&self, address: Address, index: U256) -> Result<U256, Self::Error> {
113 Ok(self.0.storage_ref(address, index)?)
114 }
115
116 fn block_hash_ref(&self, number: u64) -> Result<B256, Self::Error> {
117 Ok(self.0.block_hash_ref(number)?)
118 }
119}
120
121#[cfg(test)]
122mod tests {
123 use super::*;
124 use alloy_primitives::b256;
125
126 #[test]
130 fn cache_db_insert_basic_non_existing() {
131 let mut db = CacheDB::new(EmptyDB::default());
132 let address = Address::random();
133 let info = Database::basic(&mut db, address).unwrap();
135 assert!(info.is_none());
136
137 let mut info = info.unwrap_or_default();
138 info.balance = U256::from(500u64);
139
140 db.insert_account_info(address, info);
142
143 let info = Database::basic(&mut db, address).unwrap();
145 assert!(info.is_some());
146 }
147
148 #[test]
150 fn cache_db_insert_basic_default() {
151 let mut db = CacheDB::new(EmptyDB::default());
152 let address = Address::random();
153
154 let info = DatabaseRef::basic_ref(&db, address).unwrap();
156 assert!(info.is_none());
157 let mut info = info.unwrap_or_default();
158 info.balance = U256::from(500u64);
159
160 db.insert_account_info(address, info.clone());
162
163 let loaded = Database::basic(&mut db, address).unwrap();
164 assert!(loaded.is_some());
165 assert_eq!(loaded.unwrap(), info)
166 }
167
168 #[test]
170 fn mem_db_insert_basic_default() {
171 let mut db = MemDb::default();
172 let address = Address::from_word(b256!(
173 "0x000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa96045"
174 ));
175
176 let info = Database::basic(&mut db, address).unwrap();
177 assert!(info.is_some());
180 let mut info = info.unwrap();
181 info.balance = U256::from(500u64);
182
183 db.inner.insert_account_info(address, info.clone());
185
186 let loaded = Database::basic(&mut db, address).unwrap();
187 assert!(loaded.is_some());
188 assert_eq!(loaded.unwrap(), info)
189 }
190}