revm_context_interface/journaled_state/
account.rs1use super::entry::JournalEntryTr;
7use core::ops::Deref;
8use primitives::{Address, B256, KECCAK_EMPTY, U256};
9use state::{Account, Bytecode};
10use std::vec::Vec;
11
12#[derive(Debug, PartialEq, Eq)]
16pub struct JournaledAccount<'a, ENTRY: JournalEntryTr> {
17 address: Address,
19 account: &'a mut Account,
21 journal_entries: &'a mut Vec<ENTRY>,
23}
24
25impl<'a, ENTRY: JournalEntryTr> JournaledAccount<'a, ENTRY> {
26 #[inline]
28 pub fn into_account_ref(self) -> &'a Account {
29 self.account
30 }
31
32 #[inline]
34 pub fn new(
35 address: Address,
36 account: &'a mut Account,
37 journal_entries: &'a mut Vec<ENTRY>,
38 ) -> Self {
39 Self {
40 address,
41 account,
42 journal_entries,
43 }
44 }
45
46 #[inline]
48 pub fn balance(&self) -> &U256 {
49 &self.account.info.balance
50 }
51
52 #[inline]
54 pub fn nonce(&self) -> u64 {
55 self.account.info.nonce
56 }
57
58 #[inline]
60 pub fn code_hash(&self) -> &B256 {
61 &self.account.info.code_hash
62 }
63
64 #[inline]
66 pub fn code(&self) -> Option<&Bytecode> {
67 self.account.info.code.as_ref()
68 }
69
70 #[inline]
72 pub fn touch(&mut self) {
73 if !self.account.status.is_touched() {
74 self.account.mark_touch();
75 self.journal_entries
76 .push(ENTRY::account_touched(self.address));
77 }
78 }
79
80 #[inline]
86 pub fn set_balance(&mut self, balance: U256) {
87 self.touch();
88 if self.account.info.balance != balance {
89 self.journal_entries.push(ENTRY::balance_changed(
90 self.address,
91 self.account.info.balance,
92 ));
93 self.account.info.set_balance(balance);
94 }
95 }
96
97 #[inline]
101 pub fn incr_balance(&mut self, balance: U256) -> bool {
102 self.touch();
103 let Some(balance) = self.account.info.balance.checked_add(balance) else {
104 return false;
105 };
106 self.set_balance(balance);
107 true
108 }
109
110 #[inline]
114 pub fn decr_balance(&mut self, balance: U256) -> bool {
115 self.touch();
116 let Some(balance) = self.account.info.balance.checked_sub(balance) else {
117 return false;
118 };
119 self.set_balance(balance);
120 true
121 }
122
123 #[inline]
129 pub fn bump_nonce(&mut self) -> bool {
130 self.touch();
131 let Some(nonce) = self.account.info.nonce.checked_add(1) else {
132 return false;
133 };
134 self.account.info.set_nonce(nonce);
135 self.journal_entries
136 .push(ENTRY::nonce_changed(self.address));
137 true
138 }
139
140 #[inline]
144 pub fn set_code(&mut self, code_hash: B256, code: Bytecode) {
145 self.touch();
146 self.account.info.set_code_hash(code_hash);
147 self.account.info.set_code(code);
148 self.journal_entries.push(ENTRY::code_changed(self.address));
149 }
150
151 #[inline]
155 pub fn set_code_and_hash_slow(&mut self, code: Bytecode) {
156 let code_hash = code.hash_slow();
157 self.set_code(code_hash, code);
158 }
159
160 #[inline]
165 pub fn delegate(&mut self, address: Address) {
166 let (bytecode, hash) = if address.is_zero() {
167 (Bytecode::default(), KECCAK_EMPTY)
168 } else {
169 let bytecode = Bytecode::new_eip7702(address);
170 let hash = bytecode.hash_slow();
171 (bytecode, hash)
172 };
173 self.touch();
174 self.set_code(hash, bytecode);
175 self.bump_nonce();
176 }
177}
178
179impl<'a, ENTRY: JournalEntryTr> Deref for JournaledAccount<'a, ENTRY> {
180 type Target = Account;
181
182 fn deref(&self) -> &Self::Target {
183 self.account
184 }
185}