stratus/eth/primitives/
execution_account_changes.rs1use derive_more::Deref;
2use display_json::DebugAsJson;
3
4use crate::alias::RevmBytecode;
5use crate::eth::primitives::Account;
6use crate::eth::primitives::Address;
7use crate::eth::primitives::Nonce;
8use crate::eth::primitives::Wei;
9
10#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize, Default, Deref)]
11#[cfg_attr(test, derive(fake::Dummy))]
12pub struct Change<T>
13where
14 T: PartialEq + Eq + Default,
15{
16 #[deref]
17 value: T,
18 changed: bool,
19}
20
21impl<T> Change<T>
22where
23 T: PartialEq + Eq + Default,
24{
25 pub fn apply(&mut self, changed_value: T) {
30 if self.value != changed_value {
31 self.value = changed_value;
32 self.changed = true;
33 }
34 }
35
36 fn apply_original(&mut self, value: T) {
41 if !self.changed {
42 self.value = value;
43 }
44 }
45
46 pub fn is_changed(&self) -> bool {
48 self.changed
49 }
50
51 pub fn value(&self) -> &T {
53 &self.value
54 }
55}
56
57impl<T, U> From<Option<U>> for Change<T>
58where
59 T: PartialEq + Eq + Default,
60 U: Into<T>,
61{
62 fn from(value: Option<U>) -> Self {
63 match value {
64 Some(value) => Self {
65 value: value.into(),
66 changed: true,
67 },
68 None => Self {
69 changed: false,
70 ..Default::default()
71 },
72 }
73 }
74}
75
76#[derive(DebugAsJson, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize, Default)]
78#[cfg_attr(test, derive(fake::Dummy))]
79pub struct ExecutionAccountChanges {
80 pub nonce: Change<Nonce>,
81 pub balance: Change<Wei>,
82 #[cfg_attr(test, dummy(default))]
83 pub bytecode: Change<Option<RevmBytecode>>,
84}
85
86impl ExecutionAccountChanges {
87 pub fn apply_modifications(&mut self, modified_account: Account) {
89 self.nonce.apply(modified_account.nonce);
90 self.balance.apply(modified_account.balance);
91 self.bytecode.apply(modified_account.bytecode);
92 }
93
94 pub fn merge(&mut self, other: ExecutionAccountChanges) {
95 if other.nonce.is_changed() {
96 self.nonce = other.nonce;
97 }
98 if other.balance.is_changed() {
99 self.balance = other.balance;
100 }
101 if other.bytecode.is_changed() {
102 self.bytecode = other.bytecode;
103 }
104 }
105
106 pub fn apply_original(&mut self, original_account: Account) {
107 self.nonce.apply_original(original_account.nonce);
108 self.balance.apply_original(original_account.balance);
109 self.bytecode.apply_original(original_account.bytecode);
110 }
111
112 pub fn is_modified(&self) -> bool {
114 self.nonce.changed || self.balance.changed || self.bytecode.changed
115 }
116
117 pub fn to_account(self, address: Address) -> Account {
118 Account {
119 address,
120 nonce: self.nonce.value,
121 balance: self.balance.value,
122 bytecode: self.bytecode.value,
123 }
124 }
125
126 pub fn from_changed(account: Account) -> Self {
127 Self {
128 nonce: Change {
129 value: account.nonce,
130 changed: true,
131 },
132 balance: Change {
133 value: account.balance,
134 changed: true,
135 },
136 bytecode: Change {
137 value: account.bytecode,
138 changed: true,
139 },
140 }
141 }
142
143 pub fn from_unchanged(account: Account) -> Self {
144 Self {
145 nonce: Change {
146 value: account.nonce,
147 changed: false,
148 },
149 balance: Change {
150 value: account.balance,
151 changed: false,
152 },
153 bytecode: Change {
154 value: account.bytecode,
155 changed: false,
156 },
157 }
158 }
159}
160
161impl From<(Address, ExecutionAccountChanges)> for Account {
162 fn from((address, change): (Address, ExecutionAccountChanges)) -> Self {
163 Self {
164 address,
165 nonce: change.nonce.value,
166 balance: change.balance.value,
167 bytecode: change.bytecode.value,
168 }
169 }
170}