revm_state/
account_info.rs1use bytecode::Bytecode;
2use core::{
3 cmp::Ordering,
4 hash::{Hash, Hasher},
5};
6use primitives::{B256, KECCAK_EMPTY, U256};
7
8#[derive(Clone, Debug, Eq)]
12#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
13pub struct AccountInfo {
14 pub balance: U256,
16 pub nonce: u64,
18 pub code_hash: B256,
20 pub code: Option<Bytecode>,
27}
28
29impl Default for AccountInfo {
30 fn default() -> Self {
31 Self {
32 balance: U256::ZERO,
33 code_hash: KECCAK_EMPTY,
34 code: Some(Bytecode::default()),
35 nonce: 0,
36 }
37 }
38}
39
40impl PartialEq for AccountInfo {
41 fn eq(&self, other: &Self) -> bool {
42 self.balance == other.balance
43 && self.nonce == other.nonce
44 && self.code_hash == other.code_hash
45 }
46}
47
48impl Hash for AccountInfo {
49 fn hash<H: Hasher>(&self, state: &mut H) {
50 self.balance.hash(state);
51 self.nonce.hash(state);
52 self.code_hash.hash(state);
53 }
54}
55
56impl PartialOrd for AccountInfo {
57 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
58 Some(self.cmp(other))
59 }
60}
61
62impl Ord for AccountInfo {
63 fn cmp(&self, other: &Self) -> Ordering {
64 self.balance
65 .cmp(&other.balance)
66 .then_with(|| self.nonce.cmp(&other.nonce))
67 .then_with(|| self.code_hash.cmp(&other.code_hash))
68 }
69}
70
71impl AccountInfo {
72 #[inline]
74 pub fn new(balance: U256, nonce: u64, code_hash: B256, code: Bytecode) -> Self {
75 Self {
76 balance,
77 nonce,
78 code: Some(code),
79 code_hash,
80 }
81 }
82
83 pub fn with_code(self, code: Bytecode) -> Self {
89 Self {
90 balance: self.balance,
91 nonce: self.nonce,
92 code_hash: code.hash_slow(),
93 code: Some(code),
94 }
95 }
96
97 pub fn with_code_hash(self, code_hash: B256) -> Self {
104 Self {
105 balance: self.balance,
106 nonce: self.nonce,
107 code_hash,
108 code: None,
109 }
110 }
111
112 pub fn with_code_and_hash(self, code: Bytecode, code_hash: B256) -> Self {
119 debug_assert_eq!(code.hash_slow(), code_hash);
120 Self {
121 balance: self.balance,
122 nonce: self.nonce,
123 code_hash,
124 code: Some(code),
125 }
126 }
127
128 pub fn with_balance(mut self, balance: U256) -> Self {
130 self.balance = balance;
131 self
132 }
133
134 pub fn with_nonce(mut self, nonce: u64) -> Self {
136 self.nonce = nonce;
137 self
138 }
139
140 #[inline]
142 pub fn set_balance(&mut self, balance: U256) -> &mut Self {
143 self.balance = balance;
144 self
145 }
146
147 #[inline]
149 pub fn set_nonce(&mut self, nonce: u64) -> &mut Self {
150 self.nonce = nonce;
151 self
152 }
153
154 #[inline]
161 pub fn set_code_hash(&mut self, code_hash: B256) -> &mut Self {
162 self.code = None;
163 self.code_hash = code_hash;
164 self
165 }
166
167 #[inline]
173 pub fn set_code(&mut self, code: Bytecode) -> &mut Self {
174 self.code_hash = code.hash_slow();
175 self.code = Some(code);
176 self
177 }
178 pub fn set_code_and_hash(&mut self, code: Bytecode, code_hash: B256) {
184 self.code_hash = code_hash;
185 self.code = Some(code);
186 }
187 #[inline]
199 pub fn copy_without_code(&self) -> Self {
200 Self {
201 balance: self.balance,
202 nonce: self.nonce,
203 code_hash: self.code_hash,
204 code: None,
205 }
206 }
207
208 pub fn without_code(mut self) -> Self {
221 self.take_bytecode();
222 self
223 }
224
225 #[inline]
232 pub fn is_empty(&self) -> bool {
233 let code_empty = self.is_empty_code_hash() || self.code_hash.is_zero();
234 code_empty && self.balance.is_zero() && self.nonce == 0
235 }
236
237 #[inline]
239 pub fn exists(&self) -> bool {
240 !self.is_empty()
241 }
242
243 #[inline]
245 pub fn has_no_code_and_nonce(&self) -> bool {
246 self.is_empty_code_hash() && self.nonce == 0
247 }
248
249 #[inline]
253 pub fn code_hash(&self) -> B256 {
254 self.code_hash
255 }
256
257 #[inline]
259 pub fn is_empty_code_hash(&self) -> bool {
260 self.code_hash == KECCAK_EMPTY
261 }
262
263 #[inline]
267 pub fn take_bytecode(&mut self) -> Option<Bytecode> {
268 self.code.take()
269 }
270
271 #[inline]
274 pub fn from_balance(balance: U256) -> Self {
275 AccountInfo {
276 balance,
277 ..Default::default()
278 }
279 }
280
281 #[inline]
284 pub fn from_bytecode(bytecode: Bytecode) -> Self {
285 let hash = bytecode.hash_slow();
286
287 AccountInfo {
288 balance: U256::ZERO,
289 nonce: 1,
290 code: Some(bytecode),
291 code_hash: hash,
292 }
293 }
294}
295
296#[cfg(test)]
297mod tests {
298 use crate::AccountInfo;
299 use bytecode::Bytecode;
300 use core::cmp::Ordering;
301 use primitives::{KECCAK_EMPTY, U256};
302 use std::collections::BTreeSet;
303
304 #[test]
305 fn test_account_info_trait_consistency() {
306 let bytecode = Bytecode::default();
307 let account1 = AccountInfo {
308 balance: U256::ZERO,
309 nonce: 0,
310 code_hash: KECCAK_EMPTY,
311 code: Some(bytecode.clone()),
312 };
313
314 let account2 = AccountInfo {
315 balance: U256::ZERO,
316 nonce: 0,
317 code_hash: KECCAK_EMPTY,
318 code: None,
319 };
320
321 assert_eq!(account1, account2, "Accounts should be equal ignoring code");
322
323 assert_eq!(
324 account1.cmp(&account2),
325 Ordering::Equal,
326 "Ordering should be equal after ignoring code in Ord"
327 );
328
329 let mut set = BTreeSet::new();
330 assert!(set.insert(account1.clone()), "Inserted account1");
331 assert!(
332 !set.insert(account2.clone()),
333 "account2 not inserted (treated as duplicate)"
334 );
335
336 assert_eq!(set.len(), 1, "Set should have only one unique account");
337 assert!(set.contains(&account1), "Set contains account1");
338 assert!(
339 set.contains(&account2),
340 "Set contains account2 (since equal)"
341 );
342
343 let mut accounts = vec![account2.clone(), account1.clone()];
344 accounts.sort();
345 assert_eq!(accounts[0], accounts[1], "Sorted vec treats them as equal");
346 }
347}