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    /// code hash
16    pub code_hash: B256,
17    /// [`Bytecode`] data associated with this account
18    ///
19    /// If [None], `code_hash` will be used to fetch it if code needs to be loaded from
20    /// inside `revm`.
21    pub code: Option<Bytecode>,
22}
23
24impl Default for AccountInfo {
25    fn default() -> Self {
26        Self {
27            balance: U256::ZERO,
28            code_hash: KECCAK_EMPTY,
29            code: Some(Bytecode::default()),
30            nonce: 0,
31        }
32    }
33}
34
35impl PartialEq for AccountInfo {
36    fn eq(&self, other: &Self) -> bool {
37        self.balance == other.balance
38            && self.nonce == other.nonce
39            && self.code_hash == other.code_hash
40    }
41}
42
43impl Hash for AccountInfo {
44    fn hash<H: Hasher>(&self, state: &mut H) {
45        self.balance.hash(state);
46        self.nonce.hash(state);
47        self.code_hash.hash(state);
48    }
49}
50
51impl AccountInfo {
52    /// Creates a new [`AccountInfo`] with the given fields.
53    #[inline]
54    pub fn new(balance: U256, nonce: u64, code_hash: B256, code: Bytecode) -> Self {
55        Self {
56            balance,
57            nonce,
58            code: Some(code),
59            code_hash,
60        }
61    }
62
63    /// Returns a copy of this account with the [`Bytecode`] removed.
64    ///
65    /// This is useful when creating journals or snapshots of the state, where it is
66    /// desirable to store the code blobs elsewhere.
67    ///
68    /// ## Note
69    ///
70    /// This is distinct from [`without_code`][Self::without_code] in that it returns
71    /// a new [`AccountInfo`] instance with the code removed.
72    ///
73    /// [`without_code`][Self::without_code] will modify and return the same instance.
74    #[inline]
75    pub fn copy_without_code(&self) -> Self {
76        Self {
77            balance: self.balance,
78            nonce: self.nonce,
79            code_hash: self.code_hash,
80            code: None,
81        }
82    }
83
84    /// Strips the [`Bytecode`] from this account and drop it.
85    ///
86    /// This is useful when creating journals or snapshots of the state, where it is
87    /// desirable to store the code blobs elsewhere.
88    ///
89    /// ## Note
90    ///
91    /// This is distinct from [`copy_without_code`][Self::copy_without_code] in that it
92    /// modifies the account in place.
93    ///
94    /// [`copy_without_code`][Self::copy_without_code]
95    /// will copy the non-code fields and return a new [`AccountInfo`] instance.
96    pub fn without_code(mut self) -> Self {
97        self.take_bytecode();
98        self
99    }
100
101    /// Returns if an account is empty.
102    ///
103    /// An account is empty if the following conditions are met.
104    /// - code hash is zero or set to the Keccak256 hash of the empty string `""`
105    /// - balance is zero
106    /// - nonce is zero
107    #[inline]
108    pub fn is_empty(&self) -> bool {
109        let code_empty = self.is_empty_code_hash() || self.code_hash.is_zero();
110        code_empty && self.balance.is_zero() && self.nonce == 0
111    }
112
113    /// Returns `true` if the account is not empty.
114    #[inline]
115    pub fn exists(&self) -> bool {
116        !self.is_empty()
117    }
118
119    /// Returns `true` if account has no nonce and code.
120    #[inline]
121    pub fn has_no_code_and_nonce(&self) -> bool {
122        self.is_empty_code_hash() && self.nonce == 0
123    }
124
125    /// Returns bytecode hash associated with this account.
126    ///
127    /// If account does not have code, it returns `KECCAK_EMPTY` hash.
128    #[inline]
129    pub fn code_hash(&self) -> B256 {
130        self.code_hash
131    }
132
133    /// Returns true if the code hash is the Keccak256 hash of the empty string `""`.
134    #[inline]
135    pub fn is_empty_code_hash(&self) -> bool {
136        self.code_hash == KECCAK_EMPTY
137    }
138
139    /// Takes bytecode from account.
140    ///
141    /// Code will be set to [None].
142    #[inline]
143    pub fn take_bytecode(&mut self) -> Option<Bytecode> {
144        self.code.take()
145    }
146
147    /// Initializes an [`AccountInfo`] with the given balance, setting all other fields to their
148    /// default values.
149    #[inline]
150    pub fn from_balance(balance: U256) -> Self {
151        AccountInfo {
152            balance,
153            ..Default::default()
154        }
155    }
156
157    /// Initializes an [`AccountInfo`] with the given bytecode, setting its balance to zero, its
158    /// nonce to `1`, and calculating the code hash from the given bytecode.
159    #[inline]
160    pub fn from_bytecode(bytecode: Bytecode) -> Self {
161        let hash = bytecode.hash_slow();
162
163        AccountInfo {
164            balance: U256::ZERO,
165            nonce: 1,
166            code: Some(bytecode),
167            code_hash: hash,
168        }
169    }
170}