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 ResultGas::new(
14 gas.limit(),
15 gas.spent(),
16 gas.refunded() as u64,
17 init_and_floor_gas.floor_gas,
18 init_and_floor_gas.initial_gas,
19 )
20}
21
22pub fn eip7623_check_gas_floor(gas: &mut Gas, init_and_floor_gas: InitialAndFloorGas) {
24 if gas.spent_sub_refunded() < init_and_floor_gas.floor_gas {
27 gas.set_spent(init_and_floor_gas.floor_gas);
28 gas.set_refund(0);
30 }
31}
32
33pub fn refund(spec: SpecId, gas: &mut Gas, eip7702_refund: i64) {
35 gas.record_refund(eip7702_refund);
36 gas.set_final_refund(spec.is_enabled_in(SpecId::LONDON));
40}
41
42#[inline]
44pub fn reimburse_caller<CTX: ContextTr>(
45 context: &mut CTX,
46 gas: &Gas,
47 additional_refund: U256,
48) -> Result<(), <CTX::Db as Database>::Error> {
49 let basefee = context.block().basefee() as u128;
50 let caller = context.tx().caller();
51 let effective_gas_price = context.tx().effective_gas_price(basefee);
52
53 context
55 .journal_mut()
56 .load_account_mut(caller)?
57 .incr_balance(
58 U256::from(
59 effective_gas_price
60 .saturating_mul((gas.remaining() + gas.refunded() as u64) as u128),
61 ) + additional_refund,
62 );
63
64 Ok(())
65}
66
67#[inline]
69pub fn reward_beneficiary<CTX: ContextTr>(
70 context: &mut CTX,
71 gas: &Gas,
72) -> Result<(), <CTX::Db as Database>::Error> {
73 let (block, tx, cfg, journal, _, _) = context.all_mut();
74 let basefee = block.basefee() as u128;
75 let effective_gas_price = tx.effective_gas_price(basefee);
76
77 let coinbase_gas_price = if cfg.spec().into().is_enabled_in(SpecId::LONDON) {
80 effective_gas_price.saturating_sub(basefee)
81 } else {
82 effective_gas_price
83 };
84
85 journal
87 .load_account_mut(block.beneficiary())?
88 .incr_balance(U256::from(coinbase_gas_price * gas.used() as u128));
89
90 Ok(())
91}
92
93pub fn output<CTX: ContextTr<Journal: JournalTr>, HALTREASON: HaltReasonTr>(
97 context: &mut CTX,
98 result: FrameResult,
101 result_gas: ResultGas,
102) -> ExecutionResult<HALTREASON> {
103 let output = result.output();
104 let instruction_result = result.into_interpreter_result();
105
106 let logs = context.journal_mut().take_logs();
108
109 match SuccessOrHalt::<HALTREASON>::from(instruction_result.result) {
110 SuccessOrHalt::Success(reason) => ExecutionResult::Success {
111 reason,
112 gas: result_gas,
113 logs,
114 output,
115 },
116 SuccessOrHalt::Revert => ExecutionResult::Revert {
117 gas: result_gas,
118 logs,
119 output: output.into_data(),
120 },
121 SuccessOrHalt::Halt(reason) => {
122 if matches!(
124 instruction_result.result,
125 interpreter::InstructionResult::PrecompileError
126 ) {
127 if let Some(message) = context.local_mut().take_precompile_error_context() {
128 return ExecutionResult::Halt {
129 reason: HALTREASON::from(HaltReason::PrecompileErrorWithContext(message)),
130 gas: result_gas,
131 logs,
132 };
133 }
134 }
135 ExecutionResult::Halt {
136 reason,
137 gas: result_gas,
138 logs,
139 }
140 }
141 flag @ (SuccessOrHalt::FatalExternalError | SuccessOrHalt::Internal(_)) => {
143 panic!(
144 "Encountered unexpected internal return flag: {flag:?} with instruction result: {instruction_result:?}"
145 )
146 }
147 }
148}