1use crate::{Address, Bytecode, HashMap, B256, KECCAK_EMPTY, U256};
2use bitflags::bitflags;
3use core::hash::{Hash, Hasher};
4
5pub type State = HashMap<Address, Account>;
7
8pub type TransientStorage = HashMap<(Address, U256), U256>;
10
11pub type Storage = HashMap<U256, StorageSlot>;
13
14#[derive(Debug, Clone, PartialEq, Eq, Default)]
15#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
16pub struct Account {
17 pub info: AccountInfo,
19 pub storage: Storage,
21 pub status: AccountStatus,
23}
24
25bitflags! {
27 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
28 #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
29 #[cfg_attr(feature = "serde", serde(transparent))]
30 pub struct AccountStatus: u8 {
31 const Loaded = 0b00000000;
34 const Created = 0b00000001;
37 const SelfDestructed = 0b00000010;
39 const Touched = 0b00000100;
41 const LoadedAsNotExisting = 0b0001000;
44 }
45}
46
47impl Default for AccountStatus {
48 fn default() -> Self {
49 Self::Loaded
50 }
51}
52
53impl Account {
54 pub fn new_not_existing() -> Self {
56 Self {
57 info: AccountInfo::default(),
58 storage: HashMap::new(),
59 status: AccountStatus::LoadedAsNotExisting,
60 }
61 }
62
63 pub fn mark_selfdestruct(&mut self) {
65 self.status |= AccountStatus::SelfDestructed;
66 }
67
68 pub fn unmark_selfdestruct(&mut self) {
70 self.status -= AccountStatus::SelfDestructed;
71 }
72
73 pub fn is_selfdestructed(&self) -> bool {
75 self.status.contains(AccountStatus::SelfDestructed)
76 }
77
78 pub fn mark_touch(&mut self) {
80 self.status |= AccountStatus::Touched;
81 }
82
83 pub fn unmark_touch(&mut self) {
85 self.status -= AccountStatus::Touched;
86 }
87
88 pub fn is_touched(&self) -> bool {
90 self.status.contains(AccountStatus::Touched)
91 }
92
93 pub fn mark_created(&mut self) {
95 self.status |= AccountStatus::Created;
96 }
97
98 pub fn unmark_created(&mut self) {
100 self.status -= AccountStatus::Created;
101 }
102
103 pub fn is_loaded_as_not_existing(&self) -> bool {
107 self.status.contains(AccountStatus::LoadedAsNotExisting)
108 }
109
110 pub fn is_created(&self) -> bool {
112 self.status.contains(AccountStatus::Created)
113 }
114
115 pub fn is_empty(&self) -> bool {
117 self.info.is_empty()
118 }
119
120 pub fn changed_storage_slots(&self) -> impl Iterator<Item = (&U256, &StorageSlot)> {
124 self.storage.iter().filter(|(_, slot)| slot.is_changed())
125 }
126}
127
128impl From<AccountInfo> for Account {
129 fn from(info: AccountInfo) -> Self {
130 Self {
131 info,
132 storage: HashMap::new(),
133 status: AccountStatus::Loaded,
134 }
135 }
136}
137
138#[derive(Debug, Clone, Default, PartialEq, Eq, Hash)]
140#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
141pub struct StorageSlot {
142 pub previous_or_original_value: U256,
148 pub present_value: U256,
150}
151
152impl StorageSlot {
153 pub fn new(original: U256) -> Self {
155 Self {
156 previous_or_original_value: original,
157 present_value: original,
158 }
159 }
160
161 pub fn new_changed(previous_or_original_value: U256, present_value: U256) -> Self {
163 Self {
164 previous_or_original_value,
165 present_value,
166 }
167 }
168
169 pub fn is_changed(&self) -> bool {
171 self.previous_or_original_value != self.present_value
172 }
173
174 pub fn original_value(&self) -> U256 {
176 self.previous_or_original_value
177 }
178
179 pub fn present_value(&self) -> U256 {
181 self.present_value
182 }
183}
184
185#[derive(Clone, Debug, Eq)]
187#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
188pub struct AccountInfo {
189 pub balance: U256,
191 pub nonce: u64,
193 pub code_hash: B256,
195 pub code: Option<Bytecode>,
198}
199
200impl Default for AccountInfo {
201 fn default() -> Self {
202 Self {
203 balance: U256::ZERO,
204 code_hash: KECCAK_EMPTY,
205 code: Some(Bytecode::default()),
206 nonce: 0,
207 }
208 }
209}
210
211impl PartialEq for AccountInfo {
212 fn eq(&self, other: &Self) -> bool {
213 self.balance == other.balance
214 && self.nonce == other.nonce
215 && self.code_hash == other.code_hash
216 }
217}
218
219impl Hash for AccountInfo {
220 fn hash<H: Hasher>(&self, state: &mut H) {
221 self.balance.hash(state);
222 self.nonce.hash(state);
223 self.code_hash.hash(state);
224 }
225}
226
227impl AccountInfo {
228 pub fn new(balance: U256, nonce: u64, code_hash: B256, code: Bytecode) -> Self {
229 Self {
230 balance,
231 nonce,
232 code: Some(code),
233 code_hash,
234 }
235 }
236
237 pub fn without_code(mut self) -> Self {
239 self.take_bytecode();
240 self
241 }
242
243 pub fn is_empty(&self) -> bool {
250 let code_empty = self.is_empty_code_hash() || self.code_hash == B256::ZERO;
251 code_empty && self.balance == U256::ZERO && self.nonce == 0
252 }
253
254 pub fn exists(&self) -> bool {
256 !self.is_empty()
257 }
258
259 pub fn has_no_code_and_nonce(&self) -> bool {
261 self.is_empty_code_hash() && self.nonce == 0
262 }
263
264 pub fn code_hash(&self) -> B256 {
267 self.code_hash
268 }
269
270 #[inline]
272 pub fn is_empty_code_hash(&self) -> bool {
273 self.code_hash == KECCAK_EMPTY
274 }
275
276 pub fn take_bytecode(&mut self) -> Option<Bytecode> {
278 self.code.take()
279 }
280
281 pub fn from_balance(balance: U256) -> Self {
282 AccountInfo {
283 balance,
284 ..Default::default()
285 }
286 }
287}
288
289#[cfg(test)]
290mod tests {
291 use crate::{Account, KECCAK_EMPTY, U256};
292
293 #[test]
294 fn account_is_empty_balance() {
295 let mut account = Account::default();
296 assert!(account.is_empty());
297
298 account.info.balance = U256::from(1);
299 assert!(!account.is_empty());
300
301 account.info.balance = U256::ZERO;
302 assert!(account.is_empty());
303 }
304
305 #[test]
306 fn account_is_empty_nonce() {
307 let mut account = Account::default();
308 assert!(account.is_empty());
309
310 account.info.nonce = 1;
311 assert!(!account.is_empty());
312
313 account.info.nonce = 0;
314 assert!(account.is_empty());
315 }
316
317 #[test]
318 fn account_is_empty_code_hash() {
319 let mut account = Account::default();
320 assert!(account.is_empty());
321
322 account.info.code_hash = [1; 32].into();
323 assert!(!account.is_empty());
324
325 account.info.code_hash = [0; 32].into();
326 assert!(account.is_empty());
327
328 account.info.code_hash = KECCAK_EMPTY;
329 assert!(account.is_empty());
330 }
331
332 #[test]
333 fn account_state() {
334 let mut account = Account::default();
335
336 assert!(!account.is_touched());
337 assert!(!account.is_selfdestructed());
338
339 account.mark_touch();
340 assert!(account.is_touched());
341 assert!(!account.is_selfdestructed());
342
343 account.mark_selfdestruct();
344 assert!(account.is_touched());
345 assert!(account.is_selfdestructed());
346
347 account.unmark_selfdestruct();
348 assert!(account.is_touched());
349 assert!(!account.is_selfdestructed());
350 }
351}