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>,
15 pub status: AccountStatus,
17 pub previous_info: Option<AccountInfo>,
21 pub previous_status: AccountStatus,
23 pub storage: StorageWithOriginalValues,
25 pub storage_was_destroyed: bool,
31}
32
33impl TransitionAccount {
34 pub fn new_empty_eip161(storage: StorageWithOriginalValues) -> Self {
36 Self {
37 info: Some(AccountInfo::default()),
38 status: AccountStatus::InMemoryChange,
39 previous_info: None,
40 previous_status: AccountStatus::LoadedNotExisting,
41 storage,
42 storage_was_destroyed: false,
43 }
44 }
45
46 pub fn has_new_contract(&self) -> Option<(B256, &Bytecode)> {
48 let present_new_codehash = self.info.as_ref().map(|info| &info.code_hash);
49 let previous_codehash = self.previous_info.as_ref().map(|info| &info.code_hash);
50 if present_new_codehash != previous_codehash {
51 return self
52 .info
53 .as_ref()
54 .and_then(|info| info.code.as_ref().map(|c| (info.code_hash, c)));
55 }
56 None
57 }
58
59 pub fn previous_balance(&self) -> U256 {
61 self.previous_info
62 .as_ref()
63 .map(|info| info.balance)
64 .unwrap_or_default()
65 }
66
67 pub fn current_balance(&self) -> U256 {
69 self.info
70 .as_ref()
71 .map(|info| info.balance)
72 .unwrap_or_default()
73 }
74
75 pub fn update(&mut self, other: Self) {
78 self.info = other.info;
79 self.status = other.status;
80
81 if matches!(
84 other.status,
85 AccountStatus::Destroyed | AccountStatus::DestroyedAgain
86 ) {
87 self.storage = other.storage;
88 self.storage_was_destroyed = true;
89 } else {
90 for (key, slot) in other.storage.into_iter() {
92 match self.storage.entry(key) {
93 hash_map::Entry::Vacant(entry) => {
94 entry.insert(slot);
95 }
96 hash_map::Entry::Occupied(mut entry) => {
97 let value = entry.get_mut();
98 if value.original_value() == slot.present_value() {
100 entry.remove();
101 } else {
102 value.present_value = slot.present_value;
104 }
105 }
106 }
107 }
108 }
109 }
110
111 pub fn create_revert(self) -> Option<AccountRevert> {
113 let mut previous_account = self.original_bundle_account();
114 previous_account.update_and_create_revert(self)
115 }
116
117 pub fn present_bundle_account(&self) -> BundleAccount {
119 BundleAccount {
120 info: self.info.clone(),
121 original_info: self.previous_info.clone(),
122 storage: self.storage.clone(),
123 status: self.status,
124 }
125 }
126
127 fn original_bundle_account(&self) -> BundleAccount {
129 BundleAccount {
130 info: self.previous_info.clone(),
131 original_info: self.previous_info.clone(),
132 storage: StorageWithOriginalValues::default(),
133 status: self.previous_status,
134 }
135 }
136}