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]
87 pub fn unsafe_mark_cold(&mut self) {
88 self.account.mark_cold();
89 }
90
91 #[inline]
97 pub fn set_balance(&mut self, balance: U256) {
98 self.touch();
99 if self.account.info.balance != balance {
100 self.journal_entries.push(ENTRY::balance_changed(
101 self.address,
102 self.account.info.balance,
103 ));
104 self.account.info.set_balance(balance);
105 }
106 }
107
108 #[inline]
112 pub fn incr_balance(&mut self, balance: U256) -> bool {
113 self.touch();
114 let Some(balance) = self.account.info.balance.checked_add(balance) else {
115 return false;
116 };
117 self.set_balance(balance);
118 true
119 }
120
121 #[inline]
125 pub fn decr_balance(&mut self, balance: U256) -> bool {
126 self.touch();
127 let Some(balance) = self.account.info.balance.checked_sub(balance) else {
128 return false;
129 };
130 self.set_balance(balance);
131 true
132 }
133
134 #[inline]
140 pub fn bump_nonce(&mut self) -> bool {
141 self.touch();
142 let Some(nonce) = self.account.info.nonce.checked_add(1) else {
143 return false;
144 };
145 self.account.info.set_nonce(nonce);
146 self.journal_entries.push(ENTRY::nonce_bumped(self.address));
147 true
148 }
149
150 #[inline]
154 pub fn set_nonce(&mut self, nonce: u64) {
155 self.touch();
156 let previous_nonce = self.account.info.nonce;
157 self.account.info.set_nonce(nonce);
158 self.journal_entries
159 .push(ENTRY::nonce_changed(self.address, previous_nonce));
160 }
161
162 #[inline]
167 pub fn unsafe_set_nonce(&mut self, nonce: u64) {
168 self.account.info.set_nonce(nonce);
169 }
170
171 #[inline]
175 pub fn set_code(&mut self, code_hash: B256, code: Bytecode) {
176 self.touch();
177 self.account.info.set_code_hash(code_hash);
178 self.account.info.set_code(code);
179 self.journal_entries.push(ENTRY::code_changed(self.address));
180 }
181
182 #[inline]
186 pub fn set_code_and_hash_slow(&mut self, code: Bytecode) {
187 let code_hash = code.hash_slow();
188 self.set_code(code_hash, code);
189 }
190
191 #[inline]
196 pub fn delegate(&mut self, address: Address) {
197 let (bytecode, hash) = if address.is_zero() {
198 (Bytecode::default(), KECCAK_EMPTY)
199 } else {
200 let bytecode = Bytecode::new_eip7702(address);
201 let hash = bytecode.hash_slow();
202 (bytecode, hash)
203 };
204 self.touch();
205 self.set_code(hash, bytecode);
206 self.bump_nonce();
207 }
208}
209
210impl<'a, ENTRY: JournalEntryTr> Deref for JournaledAccount<'a, ENTRY> {
211 type Target = Account;
212
213 fn deref(&self) -> &Self::Target {
214 self.account
215 }
216}