revm_handler/
post_execution.rs1use crate::FrameResult;
2use context::journaled_state::account::JournaledAccountTr;
3use context_interface::{
4 cfg::GasParams,
5 journaled_state::JournalTr,
6 result::{ExecutionResult, HaltReason, HaltReasonTr, ResultGas},
7 Block, Cfg, ContextTr, Database, LocalContextTr, Transaction,
8};
9use interpreter::{Gas, InitialAndFloorGas, SuccessOrHalt};
10use primitives::{hardfork::SpecId, U256};
11
12pub fn build_result_gas(
14 _is_halt: bool,
15 gas: &Gas,
16 init_and_floor_gas: InitialAndFloorGas,
17) -> ResultGas {
18 let state_gas = gas
24 .state_gas_spent()
25 .saturating_add_unsigned(init_and_floor_gas.initial_state_gas)
26 .max(0) as u64;
27
28 ResultGas::default()
29 .with_total_gas_spent(
30 gas.limit()
31 .saturating_sub(gas.remaining())
32 .saturating_sub(gas.reservoir()),
33 )
34 .with_refunded(gas.refunded() as u64)
35 .with_floor_gas(init_and_floor_gas.floor_gas())
36 .with_state_gas_spent(state_gas)
37}
38
39pub const fn eip7623_check_gas_floor(gas: &mut Gas, init_and_floor_gas: InitialAndFloorGas) {
44 let gas_used_before_refund = gas.total_gas_spent().saturating_sub(gas.reservoir());
48 let gas_used_after_refund = gas_used_before_refund.saturating_sub(gas.refunded() as u64);
49 if gas_used_after_refund < init_and_floor_gas.floor_gas() {
50 gas.set_spent(init_and_floor_gas.floor_gas());
55 gas.set_reservoir(0);
56 gas.set_refund(0);
57 }
58}
59
60pub fn refund(gas_params: &GasParams, gas: &mut Gas, eip7702_refund: i64) {
62 gas.record_refund(eip7702_refund);
63 gas.set_final_refund(gas_params.max_refund_quotient());
64}
65
66#[inline]
68pub fn reimburse_caller<CTX: ContextTr>(
69 context: &mut CTX,
70 gas: &Gas,
71 additional_refund: U256,
72) -> Result<(), <CTX::Db as Database>::Error> {
73 if context.cfg().is_fee_charge_disabled() {
76 return Ok(());
77 }
78 let basefee = context.block().basefee() as u128;
79 let caller = context.tx().caller();
80 let effective_gas_price = context.tx().effective_gas_price(basefee);
81
82 let reimbursable = gas.remaining() + gas.reservoir() + gas.refunded() as u64;
85 context
86 .journal_mut()
87 .load_account_mut(caller)?
88 .incr_balance(
89 U256::from(effective_gas_price.saturating_mul(reimbursable as u128))
90 + additional_refund,
91 );
92
93 Ok(())
94}
95
96#[inline]
98pub fn reward_beneficiary<CTX: ContextTr>(
99 context: &mut CTX,
100 gas: &Gas,
101) -> Result<(), <CTX::Db as Database>::Error> {
102 if context.cfg().is_fee_charge_disabled() {
105 return Ok(());
106 }
107 let (block, tx, cfg, journal, _, _) = context.all_mut();
108 let basefee = block.basefee() as u128;
109 let effective_gas_price = tx.effective_gas_price(basefee);
110
111 let coinbase_gas_price = if cfg.spec().into().is_enabled_in(SpecId::LONDON) {
114 effective_gas_price.saturating_sub(basefee)
115 } else {
116 effective_gas_price
117 };
118
119 let effective_used = gas.used().saturating_sub(gas.reservoir());
122 journal
123 .load_account_mut(block.beneficiary())?
124 .incr_balance(U256::from(coinbase_gas_price * effective_used as u128));
125
126 Ok(())
127}
128
129pub fn output<CTX: ContextTr<Journal: JournalTr>, HALTREASON: HaltReasonTr>(
133 context: &mut CTX,
134 result: FrameResult,
137 result_gas: ResultGas,
138) -> ExecutionResult<HALTREASON> {
139 let output = result.output();
140 let instruction_result = result.into_interpreter_result();
141
142 let logs = context.journal_mut().take_logs();
144
145 match SuccessOrHalt::<HALTREASON>::from(instruction_result.result) {
146 SuccessOrHalt::Success(reason) => ExecutionResult::Success {
147 reason,
148 gas: result_gas,
149 logs,
150 output,
151 },
152 SuccessOrHalt::Revert => ExecutionResult::Revert {
153 gas: result_gas,
154 logs,
155 output: output.into_data(),
156 },
157 SuccessOrHalt::Halt(reason) => {
158 if matches!(
160 instruction_result.result,
161 interpreter::InstructionResult::PrecompileError
162 ) {
163 if let Some(message) = context.local_mut().take_precompile_error_context() {
164 return ExecutionResult::Halt {
165 reason: HALTREASON::from(HaltReason::PrecompileErrorWithContext(message)),
166 gas: result_gas,
167 logs,
168 };
169 }
170 }
171 ExecutionResult::Halt {
172 reason,
173 gas: result_gas,
174 logs,
175 }
176 }
177 flag @ (SuccessOrHalt::FatalExternalError | SuccessOrHalt::Internal(_)) => {
179 panic!(
180 "Encountered unexpected internal return flag: {flag:?} with instruction result: {instruction_result:?}"
181 )
182 }
183 }
184}