revm_handler/
post_execution.rs1use crate::FrameResult;
2use context_interface::{
3 journaled_state::JournalTr,
4 result::{ExecutionResult, HaltReason, HaltReasonTr},
5 Block, Cfg, ContextTr, Database, LocalContextTr, Transaction,
6};
7use interpreter::{Gas, InitialAndFloorGas, SuccessOrHalt};
8use primitives::{hardfork::SpecId, U256};
9
10pub fn eip7623_check_gas_floor(gas: &mut Gas, init_and_floor_gas: InitialAndFloorGas) {
12 if gas.spent_sub_refunded() < init_and_floor_gas.floor_gas {
15 gas.set_spent(init_and_floor_gas.floor_gas);
16 gas.set_refund(0);
18 }
19}
20
21pub fn refund(spec: SpecId, gas: &mut Gas, eip7702_refund: i64) {
23 gas.record_refund(eip7702_refund);
24 gas.set_final_refund(spec.is_enabled_in(SpecId::LONDON));
28}
29
30#[inline]
32pub fn reimburse_caller<CTX: ContextTr>(
33 context: &mut CTX,
34 gas: &Gas,
35 additional_refund: U256,
36) -> Result<(), <CTX::Db as Database>::Error> {
37 let basefee = context.block().basefee() as u128;
38 let caller = context.tx().caller();
39 let effective_gas_price = context.tx().effective_gas_price(basefee);
40
41 context
43 .journal_mut()
44 .load_account_mut(caller)?
45 .incr_balance(
46 U256::from(
47 effective_gas_price
48 .saturating_mul((gas.remaining() + gas.refunded() as u64) as u128),
49 ) + additional_refund,
50 );
51
52 Ok(())
53}
54
55#[inline]
57pub fn reward_beneficiary<CTX: ContextTr>(
58 context: &mut CTX,
59 gas: &Gas,
60) -> Result<(), <CTX::Db as Database>::Error> {
61 let (block, tx, cfg, journal, _, _) = context.all_mut();
62 let basefee = block.basefee() as u128;
63 let effective_gas_price = tx.effective_gas_price(basefee);
64
65 let coinbase_gas_price = if cfg.spec().into().is_enabled_in(SpecId::LONDON) {
68 effective_gas_price.saturating_sub(basefee)
69 } else {
70 effective_gas_price
71 };
72
73 journal
75 .load_account_mut(block.beneficiary())?
76 .incr_balance(U256::from(coinbase_gas_price * gas.used() as u128));
77
78 Ok(())
79}
80
81pub fn output<CTX: ContextTr<Journal: JournalTr>, HALTREASON: HaltReasonTr>(
85 context: &mut CTX,
86 result: FrameResult,
89) -> ExecutionResult<HALTREASON> {
90 let gas_refunded = result.gas().refunded() as u64;
92 let gas_used = result.gas().used();
93 let output = result.output();
94 let instruction_result = result.into_interpreter_result();
95
96 let logs = context.journal_mut().take_logs();
98
99 match SuccessOrHalt::<HALTREASON>::from(instruction_result.result) {
100 SuccessOrHalt::Success(reason) => ExecutionResult::Success {
101 reason,
102 gas_used,
103 gas_refunded,
104 logs,
105 output,
106 },
107 SuccessOrHalt::Revert => ExecutionResult::Revert {
108 gas_used,
109 output: output.into_data(),
110 },
111 SuccessOrHalt::Halt(reason) => {
112 if matches!(
114 instruction_result.result,
115 interpreter::InstructionResult::PrecompileError
116 ) {
117 if let Some(message) = context.local_mut().take_precompile_error_context() {
118 return ExecutionResult::Halt {
119 reason: HALTREASON::from(HaltReason::PrecompileErrorWithContext(message)),
120 gas_used,
121 };
122 }
123 }
124 ExecutionResult::Halt { reason, gas_used }
125 }
126 flag @ (SuccessOrHalt::FatalExternalError | SuccessOrHalt::Internal(_)) => {
128 panic!(
129 "Encountered unexpected internal return flag: {flag:?} with instruction result: {instruction_result:?}"
130 )
131 }
132 }
133}