1#[derive(Clone, Copy, Default, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
18#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
19pub enum AccountStatus {
20 #[default]
22 LoadedNotExisting,
23 Loaded,
25 LoadedEmptyEIP161,
27 InMemoryChange,
29 Changed,
31 Destroyed,
33 DestroyedChanged,
35 DestroyedAgain,
37}
38
39impl AccountStatus {
40 pub fn is_not_modified(&self) -> bool {
42 matches!(
43 self,
44 Self::LoadedNotExisting | Self::Loaded | Self::LoadedEmptyEIP161
45 )
46 }
47
48 pub fn was_destroyed(&self) -> bool {
51 matches!(
52 self,
53 Self::Destroyed | Self::DestroyedChanged | Self::DestroyedAgain
54 )
55 }
56
57 pub fn is_storage_known(&self) -> bool {
59 matches!(
60 self,
61 Self::LoadedNotExisting
62 | Self::InMemoryChange
63 | Self::Destroyed
64 | Self::DestroyedChanged
65 | Self::DestroyedAgain
66 )
67 }
68
69 pub fn is_modified_and_not_destroyed(&self) -> bool {
73 matches!(self, Self::Changed | Self::InMemoryChange)
74 }
75
76 pub fn on_created(&self) -> Self {
78 match self {
79 Self::DestroyedAgain
81 | Self::Destroyed
82 | Self::DestroyedChanged => Self::DestroyedChanged,
83 Self::LoadedNotExisting
85 | Self::LoadedEmptyEIP161
87 | Self::Loaded
88 | Self::Changed
89 | Self::InMemoryChange => {
90 Self::InMemoryChange
94 }
95 }
96 }
97
98 pub fn on_touched_empty_post_eip161(&self) -> Self {
104 match self {
105 Self::LoadedNotExisting => Self::LoadedNotExisting,
107 Self::InMemoryChange | Self::Destroyed | Self::LoadedEmptyEIP161 => Self::Destroyed,
109 Self::DestroyedAgain | Self::DestroyedChanged => Self::DestroyedAgain,
111 Self::Loaded | Self::Changed => {
113 unreachable!("Wrong state transition, touch empty is not possible from {self:?}");
114 }
115 }
116 }
117
118 pub fn on_touched_created_pre_eip161(&self, had_no_info: bool) -> Option<Self> {
125 match self {
126 Self::LoadedEmptyEIP161 => None,
127 Self::DestroyedChanged => {
128 if had_no_info {
129 None
130 } else {
131 Some(Self::DestroyedChanged)
132 }
133 }
134 Self::Destroyed | Self::DestroyedAgain => Some(Self::DestroyedChanged),
135 Self::InMemoryChange | Self::LoadedNotExisting => Some(Self::InMemoryChange),
136 Self::Loaded | Self::Changed => {
137 unreachable!("Wrong state transition, touch crate is not possible from {self:?}")
138 }
139 }
140 }
141
142 pub fn on_changed(&self, had_no_nonce_and_code: bool) -> Self {
144 match self {
145 Self::LoadedNotExisting => Self::InMemoryChange,
148 Self::LoadedEmptyEIP161 => Self::InMemoryChange,
152 Self::Loaded => {
154 if had_no_nonce_and_code {
155 Self::InMemoryChange
157 } else {
158 Self::Changed
160 }
161 }
162
163 Self::Changed => Self::Changed,
166 Self::InMemoryChange => Self::InMemoryChange,
167 Self::DestroyedChanged => Self::DestroyedChanged,
168
169 Self::Destroyed | Self::DestroyedAgain => Self::DestroyedChanged,
172 }
173 }
174
175 pub fn on_selfdestructed(&self) -> Self {
177 match self {
178 Self::LoadedNotExisting => Self::LoadedNotExisting,
180 Self::DestroyedChanged | Self::DestroyedAgain | Self::Destroyed => Self::DestroyedAgain,
184
185 _ => Self::Destroyed,
187 }
188 }
189
190 pub fn transition(&mut self, other: Self) {
203 *self = match (self.was_destroyed(), other.was_destroyed()) {
204 (true, false) => Self::DestroyedChanged,
205 (false, false) if *self == Self::InMemoryChange => Self::InMemoryChange,
206 _ => other,
207 };
208 }
209}
210
211#[cfg(test)]
212mod test {
213
214 use super::*;
215
216 #[test]
217 fn test_account_status() {
218 assert!(AccountStatus::Loaded.is_not_modified());
220 assert!(AccountStatus::LoadedEmptyEIP161.is_not_modified());
221 assert!(AccountStatus::LoadedNotExisting.is_not_modified());
222 assert!(!AccountStatus::Changed.is_not_modified());
223 assert!(!AccountStatus::InMemoryChange.is_not_modified());
224 assert!(!AccountStatus::Destroyed.is_not_modified());
225 assert!(!AccountStatus::DestroyedChanged.is_not_modified());
226 assert!(!AccountStatus::DestroyedAgain.is_not_modified());
227
228 assert!(!AccountStatus::LoadedEmptyEIP161.is_storage_known());
230 assert!(AccountStatus::LoadedNotExisting.is_storage_known());
231 assert!(AccountStatus::InMemoryChange.is_storage_known());
232 assert!(AccountStatus::Destroyed.is_storage_known());
233 assert!(AccountStatus::DestroyedChanged.is_storage_known());
234 assert!(AccountStatus::DestroyedAgain.is_storage_known());
235 assert!(!AccountStatus::Loaded.is_storage_known());
236 assert!(!AccountStatus::Changed.is_storage_known());
237
238 assert!(!AccountStatus::LoadedEmptyEIP161.was_destroyed());
240 assert!(!AccountStatus::LoadedNotExisting.was_destroyed());
241 assert!(!AccountStatus::InMemoryChange.was_destroyed());
242 assert!(AccountStatus::Destroyed.was_destroyed());
243 assert!(AccountStatus::DestroyedChanged.was_destroyed());
244 assert!(AccountStatus::DestroyedAgain.was_destroyed());
245 assert!(!AccountStatus::Loaded.was_destroyed());
246 assert!(!AccountStatus::Changed.was_destroyed());
247
248 assert!(AccountStatus::Changed.is_modified_and_not_destroyed());
250 assert!(AccountStatus::InMemoryChange.is_modified_and_not_destroyed());
251 assert!(!AccountStatus::Loaded.is_modified_and_not_destroyed());
252 assert!(!AccountStatus::LoadedEmptyEIP161.is_modified_and_not_destroyed());
253 assert!(!AccountStatus::LoadedNotExisting.is_modified_and_not_destroyed());
254 assert!(!AccountStatus::Destroyed.is_modified_and_not_destroyed());
255 assert!(!AccountStatus::DestroyedChanged.is_modified_and_not_destroyed());
256 assert!(!AccountStatus::DestroyedAgain.is_modified_and_not_destroyed());
257 }
258
259 #[test]
260 fn test_on_created() {
261 assert_eq!(
262 AccountStatus::Destroyed.on_created(),
263 AccountStatus::DestroyedChanged
264 );
265 assert_eq!(
266 AccountStatus::DestroyedAgain.on_created(),
267 AccountStatus::DestroyedChanged
268 );
269 assert_eq!(
270 AccountStatus::DestroyedChanged.on_created(),
271 AccountStatus::DestroyedChanged
272 );
273
274 assert_eq!(
275 AccountStatus::LoadedNotExisting.on_created(),
276 AccountStatus::InMemoryChange
277 );
278 assert_eq!(
279 AccountStatus::Loaded.on_created(),
280 AccountStatus::InMemoryChange
281 );
282 assert_eq!(
283 AccountStatus::LoadedEmptyEIP161.on_created(),
284 AccountStatus::InMemoryChange
285 );
286 assert_eq!(
287 AccountStatus::Changed.on_created(),
288 AccountStatus::InMemoryChange
289 );
290 assert_eq!(
291 AccountStatus::InMemoryChange.on_created(),
292 AccountStatus::InMemoryChange
293 );
294 }
295
296 #[test]
297 fn test_on_touched_empty_post_eip161() {
298 assert_eq!(
299 AccountStatus::LoadedNotExisting.on_touched_empty_post_eip161(),
300 AccountStatus::LoadedNotExisting
301 );
302 assert_eq!(
303 AccountStatus::InMemoryChange.on_touched_empty_post_eip161(),
304 AccountStatus::Destroyed
305 );
306 assert_eq!(
307 AccountStatus::Destroyed.on_touched_empty_post_eip161(),
308 AccountStatus::Destroyed
309 );
310 assert_eq!(
311 AccountStatus::LoadedEmptyEIP161.on_touched_empty_post_eip161(),
312 AccountStatus::Destroyed
313 );
314 assert_eq!(
315 AccountStatus::DestroyedAgain.on_touched_empty_post_eip161(),
316 AccountStatus::DestroyedAgain
317 );
318 assert_eq!(
319 AccountStatus::DestroyedChanged.on_touched_empty_post_eip161(),
320 AccountStatus::DestroyedAgain
321 );
322 }
323
324 #[test]
325 fn test_on_touched_created_pre_eip161() {
326 assert_eq!(
327 AccountStatus::LoadedEmptyEIP161.on_touched_created_pre_eip161(true),
328 None
329 );
330 assert_eq!(
331 AccountStatus::LoadedEmptyEIP161.on_touched_created_pre_eip161(false),
332 None
333 );
334
335 assert_eq!(
336 AccountStatus::DestroyedChanged.on_touched_created_pre_eip161(true),
337 None
338 );
339 assert_eq!(
340 AccountStatus::DestroyedChanged.on_touched_created_pre_eip161(false),
341 Some(AccountStatus::DestroyedChanged)
342 );
343
344 assert_eq!(
345 AccountStatus::Destroyed.on_touched_created_pre_eip161(true),
346 Some(AccountStatus::DestroyedChanged)
347 );
348 assert_eq!(
349 AccountStatus::Destroyed.on_touched_created_pre_eip161(false),
350 Some(AccountStatus::DestroyedChanged)
351 );
352
353 assert_eq!(
354 AccountStatus::DestroyedAgain.on_touched_created_pre_eip161(true),
355 Some(AccountStatus::DestroyedChanged)
356 );
357 assert_eq!(
358 AccountStatus::DestroyedAgain.on_touched_created_pre_eip161(false),
359 Some(AccountStatus::DestroyedChanged)
360 );
361
362 assert_eq!(
363 AccountStatus::InMemoryChange.on_touched_created_pre_eip161(true),
364 Some(AccountStatus::InMemoryChange)
365 );
366 assert_eq!(
367 AccountStatus::InMemoryChange.on_touched_created_pre_eip161(false),
368 Some(AccountStatus::InMemoryChange)
369 );
370
371 assert_eq!(
372 AccountStatus::LoadedNotExisting.on_touched_created_pre_eip161(true),
373 Some(AccountStatus::InMemoryChange)
374 );
375 assert_eq!(
376 AccountStatus::LoadedNotExisting.on_touched_created_pre_eip161(false),
377 Some(AccountStatus::InMemoryChange)
378 );
379 }
380
381 #[test]
382 fn test_on_changed() {
383 assert_eq!(
384 AccountStatus::LoadedNotExisting.on_changed(true),
385 AccountStatus::InMemoryChange
386 );
387 assert_eq!(
388 AccountStatus::LoadedNotExisting.on_changed(false),
389 AccountStatus::InMemoryChange
390 );
391
392 assert_eq!(
393 AccountStatus::LoadedEmptyEIP161.on_changed(true),
394 AccountStatus::InMemoryChange
395 );
396 assert_eq!(
397 AccountStatus::LoadedEmptyEIP161.on_changed(false),
398 AccountStatus::InMemoryChange
399 );
400
401 assert_eq!(
402 AccountStatus::Loaded.on_changed(true),
403 AccountStatus::InMemoryChange
404 );
405 assert_eq!(
406 AccountStatus::Loaded.on_changed(false),
407 AccountStatus::Changed
408 );
409
410 assert_eq!(
411 AccountStatus::Changed.on_changed(true),
412 AccountStatus::Changed
413 );
414 assert_eq!(
415 AccountStatus::Changed.on_changed(false),
416 AccountStatus::Changed
417 );
418
419 assert_eq!(
420 AccountStatus::InMemoryChange.on_changed(true),
421 AccountStatus::InMemoryChange
422 );
423 assert_eq!(
424 AccountStatus::InMemoryChange.on_changed(false),
425 AccountStatus::InMemoryChange
426 );
427
428 assert_eq!(
429 AccountStatus::DestroyedChanged.on_changed(true),
430 AccountStatus::DestroyedChanged
431 );
432 assert_eq!(
433 AccountStatus::DestroyedChanged.on_changed(false),
434 AccountStatus::DestroyedChanged
435 );
436
437 assert_eq!(
438 AccountStatus::Destroyed.on_changed(true),
439 AccountStatus::DestroyedChanged
440 );
441 assert_eq!(
442 AccountStatus::Destroyed.on_changed(false),
443 AccountStatus::DestroyedChanged
444 );
445
446 assert_eq!(
447 AccountStatus::DestroyedAgain.on_changed(true),
448 AccountStatus::DestroyedChanged
449 );
450 assert_eq!(
451 AccountStatus::DestroyedAgain.on_changed(false),
452 AccountStatus::DestroyedChanged
453 );
454 }
455
456 #[test]
457 fn test_on_selfdestructed() {
458 assert_eq!(
459 AccountStatus::LoadedNotExisting.on_selfdestructed(),
460 AccountStatus::LoadedNotExisting
461 );
462
463 assert_eq!(
464 AccountStatus::DestroyedChanged.on_selfdestructed(),
465 AccountStatus::DestroyedAgain
466 );
467 assert_eq!(
468 AccountStatus::DestroyedAgain.on_selfdestructed(),
469 AccountStatus::DestroyedAgain
470 );
471 assert_eq!(
472 AccountStatus::Destroyed.on_selfdestructed(),
473 AccountStatus::DestroyedAgain
474 );
475
476 assert_eq!(
477 AccountStatus::Loaded.on_selfdestructed(),
478 AccountStatus::Destroyed
479 );
480 assert_eq!(
481 AccountStatus::LoadedEmptyEIP161.on_selfdestructed(),
482 AccountStatus::Destroyed
483 );
484 assert_eq!(
485 AccountStatus::InMemoryChange.on_selfdestructed(),
486 AccountStatus::Destroyed
487 );
488 assert_eq!(
489 AccountStatus::Changed.on_selfdestructed(),
490 AccountStatus::Destroyed
491 );
492 }
493
494 #[test]
495 fn test_transition() {
496 let mut status = AccountStatus::Destroyed;
497 status.transition(AccountStatus::Loaded);
498 assert_eq!(status, AccountStatus::DestroyedChanged);
499
500 let mut status = AccountStatus::DestroyedChanged;
501 status.transition(AccountStatus::InMemoryChange);
502 assert_eq!(status, AccountStatus::DestroyedChanged);
503
504 let mut status = AccountStatus::DestroyedAgain;
505 status.transition(AccountStatus::Changed);
506 assert_eq!(status, AccountStatus::DestroyedChanged);
507
508 let mut status = AccountStatus::InMemoryChange;
509 status.transition(AccountStatus::Loaded);
510 assert_eq!(status, AccountStatus::InMemoryChange);
511
512 let mut status = AccountStatus::InMemoryChange;
513 status.transition(AccountStatus::Changed);
514 assert_eq!(status, AccountStatus::InMemoryChange);
515
516 let mut status = AccountStatus::Loaded;
517 status.transition(AccountStatus::Changed);
518 assert_eq!(status, AccountStatus::Changed);
519
520 let mut status = AccountStatus::LoadedNotExisting;
521 status.transition(AccountStatus::InMemoryChange);
522 assert_eq!(status, AccountStatus::InMemoryChange);
523
524 let mut status = AccountStatus::LoadedEmptyEIP161;
525 status.transition(AccountStatus::Loaded);
526 assert_eq!(status, AccountStatus::Loaded);
527
528 let mut status = AccountStatus::Destroyed;
529 status.transition(AccountStatus::DestroyedChanged);
530 assert_eq!(status, AccountStatus::DestroyedChanged);
531
532 let mut status = AccountStatus::DestroyedAgain;
533 status.transition(AccountStatus::Destroyed);
534 assert_eq!(status, AccountStatus::Destroyed);
535
536 let mut status = AccountStatus::Loaded;
537 status.transition(AccountStatus::Destroyed);
538 assert_eq!(status, AccountStatus::Destroyed);
539
540 let mut status = AccountStatus::Changed;
541 status.transition(AccountStatus::DestroyedAgain);
542 assert_eq!(status, AccountStatus::DestroyedAgain);
543 }
544}