revm_database/states/
transition_account.rs1use super::{AccountRevert, AccountStatus, BundleAccount, StorageWithOriginalValues};
2use bytecode::Bytecode;
3use primitives::{hash_map, B256, U256};
4use state::AccountInfo;
5
6#[derive(Clone, Debug, PartialEq, Eq, Default)]
12pub struct TransitionAccount {
13 pub info: Option<AccountInfo>,
14 pub status: AccountStatus,
15 pub previous_info: Option<AccountInfo>,
19 pub previous_status: AccountStatus,
21 pub storage: StorageWithOriginalValues,
23 pub storage_was_destroyed: bool,
29}
30
31impl TransitionAccount {
32 pub fn new_empty_eip161(storage: StorageWithOriginalValues) -> Self {
34 Self {
35 info: Some(AccountInfo::default()),
36 status: AccountStatus::InMemoryChange,
37 previous_info: None,
38 previous_status: AccountStatus::LoadedNotExisting,
39 storage,
40 storage_was_destroyed: false,
41 }
42 }
43
44 pub fn has_new_contract(&self) -> Option<(B256, &Bytecode)> {
46 let present_new_codehash = self.info.as_ref().map(|info| &info.code_hash);
47 let previous_codehash = self.previous_info.as_ref().map(|info| &info.code_hash);
48 if present_new_codehash != previous_codehash {
49 return self
50 .info
51 .as_ref()
52 .and_then(|info| info.code.as_ref().map(|c| (info.code_hash, c)));
53 }
54 None
55 }
56
57 pub fn previous_balance(&self) -> U256 {
59 self.previous_info
60 .as_ref()
61 .map(|info| info.balance)
62 .unwrap_or_default()
63 }
64
65 pub fn current_balance(&self) -> U256 {
67 self.info
68 .as_ref()
69 .map(|info| info.balance)
70 .unwrap_or_default()
71 }
72
73 pub fn update(&mut self, other: Self) {
76 self.info = other.info;
77 self.status = other.status;
78
79 if matches!(
82 other.status,
83 AccountStatus::Destroyed | AccountStatus::DestroyedAgain
84 ) {
85 self.storage = other.storage;
86 self.storage_was_destroyed = true;
87 } else {
88 for (key, slot) in other.storage.into_iter() {
90 match self.storage.entry(key) {
91 hash_map::Entry::Vacant(entry) => {
92 entry.insert(slot);
93 }
94 hash_map::Entry::Occupied(mut entry) => {
95 let value = entry.get_mut();
96 if value.original_value() == slot.present_value() {
98 entry.remove();
99 } else {
100 value.present_value = slot.present_value;
102 }
103 }
104 }
105 }
106 }
107 }
108
109 pub fn create_revert(self) -> Option<AccountRevert> {
111 let mut previous_account = self.original_bundle_account();
112 previous_account.update_and_create_revert(self)
113 }
114
115 pub fn present_bundle_account(&self) -> BundleAccount {
117 BundleAccount {
118 info: self.info.clone(),
119 original_info: self.previous_info.clone(),
120 storage: self.storage.clone(),
121 status: self.status,
122 }
123 }
124
125 fn original_bundle_account(&self) -> BundleAccount {
127 BundleAccount {
128 info: self.previous_info.clone(),
129 original_info: self.previous_info.clone(),
130 storage: StorageWithOriginalValues::default(),
131 status: self.previous_status,
132 }
133 }
134}