revm_state/account_info.rs
1use bytecode::Bytecode;
2use core::hash::{Hash, Hasher};
3use primitives::{B256, KECCAK_EMPTY, U256};
4
5/// Account information that contains balance, nonce, code hash and code
6///
7/// Code is set as optional.
8#[derive(Clone, Debug, Eq, Ord, PartialOrd)]
9#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
10pub struct AccountInfo {
11 /// Account balance.
12 pub balance: U256,
13 /// Account nonce.
14 pub nonce: u64,
15 /// Hash of the raw bytes in `code`, or [`KECCAK_EMPTY`].
16 pub code_hash: B256,
17 /// [`Bytecode`] data associated with this account.
18 ///
19 /// If [`None`], `code_hash` will be used to fetch it from the database, if code needs to be
20 /// loaded from inside `revm`.
21 ///
22 /// By default, this is `Some(Bytecode::default())`.
23 pub code: Option<Bytecode>,
24}
25
26impl Default for AccountInfo {
27 fn default() -> Self {
28 Self {
29 balance: U256::ZERO,
30 code_hash: KECCAK_EMPTY,
31 code: Some(Bytecode::default()),
32 nonce: 0,
33 }
34 }
35}
36
37impl PartialEq for AccountInfo {
38 fn eq(&self, other: &Self) -> bool {
39 self.balance == other.balance
40 && self.nonce == other.nonce
41 && self.code_hash == other.code_hash
42 }
43}
44
45impl Hash for AccountInfo {
46 fn hash<H: Hasher>(&self, state: &mut H) {
47 self.balance.hash(state);
48 self.nonce.hash(state);
49 self.code_hash.hash(state);
50 }
51}
52
53impl AccountInfo {
54 /// Creates a new [`AccountInfo`] with the given fields.
55 #[inline]
56 pub fn new(balance: U256, nonce: u64, code_hash: B256, code: Bytecode) -> Self {
57 Self {
58 balance,
59 nonce,
60 code: Some(code),
61 code_hash,
62 }
63 }
64
65 /// Creates a new [`AccountInfo`] with the given code.
66 ///
67 /// # Note
68 ///
69 /// As code hash is calculated with [`Bytecode::hash_slow`] there will be performance penalty if used frequently.
70 pub fn with_code(self, code: Bytecode) -> Self {
71 Self {
72 balance: self.balance,
73 nonce: self.nonce,
74 code_hash: code.hash_slow(),
75 code: Some(code),
76 }
77 }
78
79 /// Creates a new [`AccountInfo`] with the given code hash.
80 ///
81 /// # Note
82 ///
83 /// Resets code to `None`. Not guaranteed to maintain invariant `code` and `code_hash`. See
84 /// also [Self::with_code_and_hash].
85 pub fn with_code_hash(self, code_hash: B256) -> Self {
86 Self {
87 balance: self.balance,
88 nonce: self.nonce,
89 code_hash,
90 code: None,
91 }
92 }
93
94 /// Creates a new [`AccountInfo`] with the given code and code hash.
95 ///
96 /// # Note
97 ///
98 /// In debug mode panics if [`Bytecode::hash_slow`] called on `code` is not equivalent to
99 /// `code_hash`. See also [`Self::with_code`].
100 pub fn with_code_and_hash(self, code: Bytecode, code_hash: B256) -> Self {
101 debug_assert_eq!(code.hash_slow(), code_hash);
102 Self {
103 balance: self.balance,
104 nonce: self.nonce,
105 code_hash,
106 code: Some(code),
107 }
108 }
109
110 /// Creates a new [`AccountInfo`] with the given balance.
111 pub fn with_balance(mut self, balance: U256) -> Self {
112 self.balance = balance;
113 self
114 }
115
116 /// Creates a new [`AccountInfo`] with the given nonce.
117 pub fn with_nonce(mut self, nonce: u64) -> Self {
118 self.nonce = nonce;
119 self
120 }
121
122 /// Sets the [`AccountInfo`] `balance`.
123 #[inline]
124 pub fn set_balance(&mut self, balance: U256) -> &mut Self {
125 self.balance = balance;
126 self
127 }
128
129 /// Sets the [`AccountInfo`] `nonce`.
130 #[inline]
131 pub fn set_nonce(&mut self, nonce: u64) -> &mut Self {
132 self.nonce = nonce;
133 self
134 }
135
136 /// Sets the [`AccountInfo`] `code_hash` and clears any cached bytecode.
137 ///
138 /// # Note
139 ///
140 /// Calling this after `set_code(...)` will remove the bytecode you just set.
141 /// If you intend to mutate the code, use only `set_code`.
142 #[inline]
143 pub fn set_code_hash(&mut self, code_hash: B256) -> &mut Self {
144 self.code = None;
145 self.code_hash = code_hash;
146 self
147 }
148
149 /// Replaces the [`AccountInfo`] bytecode and recalculates `code_hash`.
150 ///
151 /// # Note
152 ///
153 /// As code hash is calculated with [`Bytecode::hash_slow`] there will be performance penalty if used frequently.
154 #[inline]
155 pub fn set_code(&mut self, code: Bytecode) -> &mut Self {
156 self.code_hash = code.hash_slow();
157 self.code = Some(code);
158 self
159 }
160 /// Sets the bytecode and its hash.
161 ///
162 /// # Note
163 ///
164 /// It is on the caller's responsibility to ensure that the bytecode hash is correct.
165 pub fn set_code_and_hash(&mut self, code: Bytecode, code_hash: B256) {
166 self.code_hash = code_hash;
167 self.code = Some(code);
168 }
169 /// Returns a copy of this account with the [`Bytecode`] removed.
170 ///
171 /// This is useful when creating journals or snapshots of the state, where it is
172 /// desirable to store the code blobs elsewhere.
173 ///
174 /// ## Note
175 ///
176 /// This is distinct from [`without_code`][Self::without_code] in that it returns
177 /// a new [`AccountInfo`] instance with the code removed.
178 ///
179 /// [`without_code`][Self::without_code] will modify and return the same instance.
180 #[inline]
181 pub fn copy_without_code(&self) -> Self {
182 Self {
183 balance: self.balance,
184 nonce: self.nonce,
185 code_hash: self.code_hash,
186 code: None,
187 }
188 }
189
190 /// Strips the [`Bytecode`] from this account and drop it.
191 ///
192 /// This is useful when creating journals or snapshots of the state, where it is
193 /// desirable to store the code blobs elsewhere.
194 ///
195 /// ## Note
196 ///
197 /// This is distinct from [`copy_without_code`][Self::copy_without_code] in that it
198 /// modifies the account in place.
199 ///
200 /// [`copy_without_code`][Self::copy_without_code]
201 /// will copy the non-code fields and return a new [`AccountInfo`] instance.
202 pub fn without_code(mut self) -> Self {
203 self.take_bytecode();
204 self
205 }
206
207 /// Returns if an account is empty.
208 ///
209 /// An account is empty if the following conditions are met.
210 /// - code hash is zero or set to the Keccak256 hash of the empty string `""`
211 /// - balance is zero
212 /// - nonce is zero
213 #[inline]
214 pub fn is_empty(&self) -> bool {
215 let code_empty = self.is_empty_code_hash() || self.code_hash.is_zero();
216 code_empty && self.balance.is_zero() && self.nonce == 0
217 }
218
219 /// Returns `true` if the account is not empty.
220 #[inline]
221 pub fn exists(&self) -> bool {
222 !self.is_empty()
223 }
224
225 /// Returns `true` if account has no nonce and code.
226 #[inline]
227 pub fn has_no_code_and_nonce(&self) -> bool {
228 self.is_empty_code_hash() && self.nonce == 0
229 }
230
231 /// Returns bytecode hash associated with this account.
232 ///
233 /// If account does not have code, it returns `KECCAK_EMPTY` hash.
234 #[inline]
235 pub fn code_hash(&self) -> B256 {
236 self.code_hash
237 }
238
239 /// Returns true if the code hash is the Keccak256 hash of the empty string `""`.
240 #[inline]
241 pub fn is_empty_code_hash(&self) -> bool {
242 self.code_hash == KECCAK_EMPTY
243 }
244
245 /// Takes bytecode from account.
246 ///
247 /// Code will be set to [None].
248 #[inline]
249 pub fn take_bytecode(&mut self) -> Option<Bytecode> {
250 self.code.take()
251 }
252
253 /// Initializes an [`AccountInfo`] with the given balance, setting all other fields to their
254 /// default values.
255 #[inline]
256 pub fn from_balance(balance: U256) -> Self {
257 AccountInfo {
258 balance,
259 ..Default::default()
260 }
261 }
262
263 /// Initializes an [`AccountInfo`] with the given bytecode, setting its balance to zero, its
264 /// nonce to `1`, and calculating the code hash from the given bytecode.
265 #[inline]
266 pub fn from_bytecode(bytecode: Bytecode) -> Self {
267 let hash = bytecode.hash_slow();
268
269 AccountInfo {
270 balance: U256::ZERO,
271 nonce: 1,
272 code: Some(bytecode),
273 code_hash: hash,
274 }
275 }
276}