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}