revm/handler/handle_types/
post_execution.rs

1// Includes.
2use crate::{
3    handler::mainnet,
4    interpreter::Gas,
5    primitives::{db::Database, EVMError, EVMResultGeneric, ResultAndState, Spec},
6    Context, FrameResult,
7};
8use std::sync::Arc;
9
10/// Reimburse the caller with ethereum it didn't spent.
11pub type ReimburseCallerHandle<'a, EXT, DB> =
12    Arc<dyn Fn(&mut Context<EXT, DB>, &Gas) -> EVMResultGeneric<(), <DB as Database>::Error> + 'a>;
13
14/// Reward beneficiary with transaction rewards.
15pub type RewardBeneficiaryHandle<'a, EXT, DB> = ReimburseCallerHandle<'a, EXT, DB>;
16
17/// Main return handle, takes state from journal and transforms internal result to external.
18pub type OutputHandle<'a, EXT, DB> = Arc<
19    dyn Fn(
20            &mut Context<EXT, DB>,
21            FrameResult,
22        ) -> Result<ResultAndState, EVMError<<DB as Database>::Error>>
23        + 'a,
24>;
25
26/// End handle, takes result and state and returns final result.
27/// This will be called after all the other handlers.
28///
29/// It is useful for catching errors and returning them in a different way.
30pub type EndHandle<'a, EXT, DB> = Arc<
31    dyn Fn(
32            &mut Context<EXT, DB>,
33            Result<ResultAndState, EVMError<<DB as Database>::Error>>,
34        ) -> Result<ResultAndState, EVMError<<DB as Database>::Error>>
35        + 'a,
36>;
37
38/// Clear handle, doesn't have output, its purpose is to clear the
39/// context. It will always be called even on failed validation.
40pub type ClearHandle<'a, EXT, DB> = Arc<dyn Fn(&mut Context<EXT, DB>) + 'a>;
41
42/// Refund handle, calculates the final refund.
43pub type RefundHandle<'a, EXT, DB> = Arc<dyn Fn(&mut Context<EXT, DB>, &mut Gas, i64) + 'a>;
44/// Handles related to post execution after the stack loop is finished.
45pub struct PostExecutionHandler<'a, EXT, DB: Database> {
46    /// Calculate final refund
47    pub refund: RefundHandle<'a, EXT, DB>,
48    /// Reimburse the caller with ethereum it didn't spend.
49    pub reimburse_caller: ReimburseCallerHandle<'a, EXT, DB>,
50    /// Reward the beneficiary with caller fee.
51    pub reward_beneficiary: RewardBeneficiaryHandle<'a, EXT, DB>,
52    /// Main return handle, returns the output of the transact.
53    pub output: OutputHandle<'a, EXT, DB>,
54    /// Called when execution ends.
55    /// End handle in comparison to output handle will be called every time after execution.
56    /// Output in case of error will not be called.
57    pub end: EndHandle<'a, EXT, DB>,
58    /// Clear handle will be called always. In comparison to end that
59    /// is called only on execution end, clear handle is called even if validation fails.
60    pub clear: ClearHandle<'a, EXT, DB>,
61}
62
63impl<'a, EXT: 'a, DB: Database + 'a> PostExecutionHandler<'a, EXT, DB> {
64    /// Creates mainnet MainHandles.
65    pub fn new<SPEC: Spec + 'a>() -> Self {
66        Self {
67            refund: Arc::new(mainnet::refund::<SPEC, EXT, DB>),
68            reimburse_caller: Arc::new(mainnet::reimburse_caller::<SPEC, EXT, DB>),
69            reward_beneficiary: Arc::new(mainnet::reward_beneficiary::<SPEC, EXT, DB>),
70            output: Arc::new(mainnet::output::<EXT, DB>),
71            end: Arc::new(mainnet::end::<EXT, DB>),
72            clear: Arc::new(mainnet::clear::<EXT, DB>),
73        }
74    }
75}
76
77impl<EXT, DB: Database> PostExecutionHandler<'_, EXT, DB> {
78    /// Calculate final refund
79    pub fn refund(&self, context: &mut Context<EXT, DB>, gas: &mut Gas, eip7702_refund: i64) {
80        (self.refund)(context, gas, eip7702_refund)
81    }
82
83    /// Reimburse the caller with gas that were not spend.
84    pub fn reimburse_caller(
85        &self,
86        context: &mut Context<EXT, DB>,
87        gas: &Gas,
88    ) -> Result<(), EVMError<DB::Error>> {
89        (self.reimburse_caller)(context, gas)
90    }
91    /// Reward beneficiary
92    pub fn reward_beneficiary(
93        &self,
94        context: &mut Context<EXT, DB>,
95        gas: &Gas,
96    ) -> Result<(), EVMError<DB::Error>> {
97        (self.reward_beneficiary)(context, gas)
98    }
99
100    /// Returns the output of transaction.
101    pub fn output(
102        &self,
103        context: &mut Context<EXT, DB>,
104        result: FrameResult,
105    ) -> Result<ResultAndState, EVMError<DB::Error>> {
106        (self.output)(context, result)
107    }
108
109    /// End handler.
110    pub fn end(
111        &self,
112        context: &mut Context<EXT, DB>,
113        end_output: Result<ResultAndState, EVMError<DB::Error>>,
114    ) -> Result<ResultAndState, EVMError<DB::Error>> {
115        (self.end)(context, end_output)
116    }
117
118    /// Clean handler.
119    pub fn clear(&self, context: &mut Context<EXT, DB>) {
120        (self.clear)(context)
121    }
122}