revm_handler/
pre_execution.rs1use bytecode::Bytecode;
6use context_interface::transaction::{AccessListTr, AuthorizationTr};
7use context_interface::ContextTr;
8use context_interface::{
9 journaled_state::Journal,
10 result::InvalidTransaction,
11 transaction::{Transaction, TransactionType},
12 Block, Cfg, Database,
13};
14use primitives::{BLOCKHASH_STORAGE_ADDRESS, KECCAK_EMPTY, U256};
15use specification::{eip7702, hardfork::SpecId};
16
17pub fn load_accounts<CTX: ContextTr, ERROR: From<<CTX::Db as Database>::Error>>(
18 context: &mut CTX,
19) -> Result<(), ERROR> {
20 let spec = context.cfg().spec().into();
21 context.journal().set_spec_id(spec);
23
24 if spec.is_enabled_in(SpecId::SHANGHAI) {
27 let coinbase = context.block().beneficiary();
28 context.journal().warm_account(coinbase);
29 }
30
31 if spec.is_enabled_in(SpecId::PRAGUE) {
34 context.journal().warm_account(BLOCKHASH_STORAGE_ADDRESS);
35 }
36
37 let (tx, journal) = context.tx_journal();
39 if let Some(access_list) = tx.access_list() {
40 for (address, storage) in access_list.access_list() {
41 journal.warm_account_and_storage(address, storage.map(|i| U256::from_be_bytes(i.0)))?;
42 }
43 }
44
45 Ok(())
46}
47
48#[inline]
49pub fn deduct_caller<CTX: ContextTr>(
50 context: &mut CTX,
51) -> Result<(), <CTX::Db as Database>::Error> {
52 let basefee = context.block().basefee();
53 let blob_price = context.block().blob_gasprice().unwrap_or_default();
54 let effective_gas_price = context.tx().effective_gas_price(basefee as u128);
55 let mut gas_cost = (context.tx().gas_limit() as u128).saturating_mul(effective_gas_price);
58
59 if context.tx().tx_type() == TransactionType::Eip4844 {
61 let blob_gas = context.tx().total_blob_gas() as u128;
62 gas_cost = gas_cost.saturating_add(blob_price.saturating_mul(blob_gas));
63 }
64
65 let is_call = context.tx().kind().is_call();
66 let caller = context.tx().caller();
67
68 let caller_account = context.journal().load_account(caller)?.data;
70 caller_account.info.balance = caller_account
72 .info
73 .balance
74 .saturating_sub(U256::from(gas_cost));
75
76 if is_call {
78 caller_account.info.nonce = caller_account.info.nonce.saturating_add(1);
80 }
81
82 caller_account.mark_touch();
84 Ok(())
85}
86
87#[inline]
89pub fn apply_eip7702_auth_list<
90 CTX: ContextTr,
91 ERROR: From<InvalidTransaction> + From<<CTX::Db as Database>::Error>,
92>(
93 context: &mut CTX,
94) -> Result<u64, ERROR> {
95 let spec = context.cfg().spec().into();
96 let tx = context.tx();
97 if !spec.is_enabled_in(SpecId::PRAGUE) {
98 return Ok(0);
99 }
100 if tx.tx_type() != TransactionType::Eip7702 {
102 return Ok(0);
103 }
104
105 let chain_id = context.cfg().chain_id();
106 let (tx, journal) = context.tx_journal();
107
108 let mut refunded_accounts = 0;
109 for authorization in tx.authorization_list() {
110 let auth_chain_id = authorization.chain_id();
112 if !auth_chain_id.is_zero() && auth_chain_id != U256::from(chain_id) {
113 continue;
114 }
115
116 if authorization.nonce() == u64::MAX {
118 continue;
119 }
120
121 let Some(authority) = authorization.authority() else {
124 continue;
125 };
126
127 let mut authority_acc = journal.load_account_code(authority)?;
130
131 if let Some(bytecode) = &authority_acc.info.code {
133 if !bytecode.is_empty() && !bytecode.is_eip7702() {
135 continue;
136 }
137 }
138
139 if authorization.nonce() != authority_acc.info.nonce {
141 continue;
142 }
143
144 if !authority_acc.is_empty() {
146 refunded_accounts += 1;
147 }
148
149 let address = authorization.address();
153 let (bytecode, hash) = if address.is_zero() {
154 (Bytecode::default(), KECCAK_EMPTY)
155 } else {
156 let bytecode = Bytecode::new_eip7702(address);
157 let hash = bytecode.hash_slow();
158 (bytecode, hash)
159 };
160 authority_acc.info.code_hash = hash;
161 authority_acc.info.code = Some(bytecode);
162
163 authority_acc.info.nonce = authority_acc.info.nonce.saturating_add(1);
165 authority_acc.mark_touch();
166 }
167
168 let refunded_gas =
169 refunded_accounts * (eip7702::PER_EMPTY_ACCOUNT_COST - eip7702::PER_AUTH_BASE_COST);
170
171 Ok(refunded_gas)
172}