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::AddressMap,
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: AddressMap<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 use revm::database::InMemoryDB;
126
127 #[test]
131 fn cache_db_insert_basic_non_existing() {
132 let mut db = InMemoryDB::default();
133 let address = Address::random();
134 let info = Database::basic(&mut db, address).unwrap();
136 assert!(info.is_none());
137
138 let mut info = info.unwrap_or_default();
139 info.balance = U256::from(500u64);
140
141 db.insert_account_info(address, info);
143
144 let info = Database::basic(&mut db, address).unwrap();
146 assert!(info.is_some());
147 }
148
149 #[test]
151 fn cache_db_insert_basic_default() {
152 let mut db = InMemoryDB::default();
153 let address = Address::random();
154
155 let info = DatabaseRef::basic_ref(&db, address).unwrap();
157 assert!(info.is_none());
158 let mut info = info.unwrap_or_default();
159 info.balance = U256::from(500u64);
160
161 db.insert_account_info(address, info.clone());
163
164 let loaded = Database::basic(&mut db, address).unwrap();
165 assert!(loaded.is_some());
166 assert_eq!(loaded.unwrap(), info)
167 }
168
169 #[test]
171 fn mem_db_insert_basic_default() {
172 let mut db = MemDb::default();
173 let address = Address::from_word(b256!(
174 "0x000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa96045"
175 ));
176
177 let info = Database::basic(&mut db, address).unwrap();
178 assert!(info.is_some());
181 let mut info = info.unwrap();
182 info.balance = U256::from(500u64);
183
184 db.inner.insert_account_info(address, info.clone());
186
187 let loaded = Database::basic(&mut db, address).unwrap();
188 assert!(loaded.is_some());
189 assert_eq!(loaded.unwrap(), info)
190 }
191}