revm/handler/mainnet/
post_execution.rs
1use crate::{
2 interpreter::{Gas, SuccessOrHalt},
3 primitives::{
4 db::Database, EVMError, ExecutionResult, ResultAndState, Spec, SpecId, SpecId::LONDON, U256,
5 },
6 Context, FrameResult,
7};
8
9#[inline]
11pub fn end<EXT, DB: Database>(
12 _context: &mut Context<EXT, DB>,
13 evm_output: Result<ResultAndState, EVMError<DB::Error>>,
14) -> Result<ResultAndState, EVMError<DB::Error>> {
15 evm_output
16}
17
18#[inline]
20pub fn clear<EXT, DB: Database>(context: &mut Context<EXT, DB>) {
21 let _ = context.evm.take_error();
23 context.evm.inner.journaled_state.clear();
24}
25
26#[inline]
28pub fn reward_beneficiary<SPEC: Spec, EXT, DB: Database>(
29 context: &mut Context<EXT, DB>,
30 gas: &Gas,
31) -> Result<(), EVMError<DB::Error>> {
32 let beneficiary = context.evm.env.block.coinbase;
33 let effective_gas_price = context.evm.env.effective_gas_price();
34
35 let coinbase_gas_price = if SPEC::enabled(LONDON) {
38 effective_gas_price.saturating_sub(context.evm.env.block.basefee)
39 } else {
40 effective_gas_price
41 };
42
43 let coinbase_account = context
44 .evm
45 .inner
46 .journaled_state
47 .load_account(beneficiary, &mut context.evm.inner.db)?;
48
49 coinbase_account.data.mark_touch();
50 coinbase_account.data.info.balance = coinbase_account
51 .data
52 .info
53 .balance
54 .saturating_add(coinbase_gas_price * U256::from(gas.spent() - gas.refunded() as u64));
55
56 Ok(())
57}
58
59pub fn refund<SPEC: Spec, EXT, DB: Database>(
60 _context: &mut Context<EXT, DB>,
61 gas: &mut Gas,
62 eip7702_refund: i64,
63) {
64 gas.record_refund(eip7702_refund);
65
66 gas.set_final_refund(SPEC::SPEC_ID.is_enabled_in(SpecId::LONDON));
70}
71
72#[inline]
73pub fn reimburse_caller<SPEC: Spec, EXT, DB: Database>(
74 context: &mut Context<EXT, DB>,
75 gas: &Gas,
76) -> Result<(), EVMError<DB::Error>> {
77 let caller = context.evm.env.tx.caller;
78 let effective_gas_price = context.evm.env.effective_gas_price();
79
80 let caller_account = context
82 .evm
83 .inner
84 .journaled_state
85 .load_account(caller, &mut context.evm.inner.db)?;
86
87 caller_account.data.info.balance =
88 caller_account.data.info.balance.saturating_add(
89 effective_gas_price * U256::from(gas.remaining() + gas.refunded() as u64),
90 );
91
92 Ok(())
93}
94
95#[inline]
97pub fn output<EXT, DB: Database>(
98 context: &mut Context<EXT, DB>,
99 result: FrameResult,
100) -> Result<ResultAndState, EVMError<DB::Error>> {
101 context.evm.take_error()?;
102 let gas_refunded = result.gas().refunded() as u64;
104 let final_gas_used = result.gas().spent() - gas_refunded;
105 let output = result.output();
106 let instruction_result = result.into_interpreter_result();
107
108 let (state, logs) = context.evm.journaled_state.finalize();
110
111 let result = match instruction_result.result.into() {
112 SuccessOrHalt::Success(reason) => ExecutionResult::Success {
113 reason,
114 gas_used: final_gas_used,
115 gas_refunded,
116 logs,
117 output,
118 },
119 SuccessOrHalt::Revert => ExecutionResult::Revert {
120 gas_used: final_gas_used,
121 output: output.into_data(),
122 },
123 SuccessOrHalt::Halt(reason) => ExecutionResult::Halt {
124 reason,
125 gas_used: final_gas_used,
126 },
127 flag @ (SuccessOrHalt::FatalExternalError | SuccessOrHalt::Internal(_)) => {
129 panic!(
130 "Encountered unexpected internal return flag: {:?} with instruction result: {:?}",
131 flag, instruction_result
132 )
133 }
134 };
135
136 Ok(ResultAndState { result, state })
137}