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