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