example_erc20_gas/handlers/
post_execution.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
use crate::{token_operation, TREASURY};
use revm::{
    context::Cfg,
    context_interface::{
        result::{HaltReason, HaltReasonTrait, InvalidHeader, InvalidTransaction, ResultAndState},
        Block, JournalDBError, Transaction, TransactionGetter,
    },
    handler::{EthPostExecution, EthPostExecutionContext, EthPostExecutionError, FrameResult},
    handler_interface::{InitialAndFloorGas, PostExecutionHandler},
    precompile::PrecompileErrors,
    primitives::U256,
    specification::hardfork::SpecId,
};

pub struct Erc20PostExecution<CTX, ERROR, HALTREASON = HaltReason> {
    inner: EthPostExecution<CTX, ERROR, HALTREASON>,
}

impl<CTX, ERROR, HALTREASON> Erc20PostExecution<CTX, ERROR, HALTREASON> {
    pub fn new() -> Self {
        Self {
            inner: EthPostExecution::new(),
        }
    }
}

impl<CTX, ERROR, HALTREASON> Default for Erc20PostExecution<CTX, ERROR, HALTREASON> {
    fn default() -> Self {
        Self::new()
    }
}

impl<CTX, ERROR, HALTREASON> PostExecutionHandler for Erc20PostExecution<CTX, ERROR, HALTREASON>
where
    CTX: EthPostExecutionContext,
    ERROR: EthPostExecutionError<CTX>
        + From<InvalidTransaction>
        + From<InvalidHeader>
        + From<JournalDBError<CTX>>
        + From<PrecompileErrors>,
    HALTREASON: HaltReasonTrait,
{
    type Context = CTX;
    type Error = ERROR;
    type ExecResult = FrameResult;
    type Output = ResultAndState<HALTREASON>;

    fn eip7623_check_gas_floor(
        &self,
        context: &mut Self::Context,
        exec_result: &mut Self::ExecResult,
        init_and_floor_gas: InitialAndFloorGas,
    ) {
        self.inner
            .eip7623_check_gas_floor(context, exec_result, init_and_floor_gas)
    }

    fn refund(
        &self,
        context: &mut Self::Context,
        exec_result: &mut Self::ExecResult,
        eip7702_refund: i64,
    ) {
        self.inner.refund(context, exec_result, eip7702_refund)
    }

    fn reimburse_caller(
        &self,
        context: &mut Self::Context,
        exec_result: &mut Self::ExecResult,
    ) -> Result<(), Self::Error> {
        let basefee = context.block().basefee() as u128;
        let caller = context.tx().caller();
        let effective_gas_price = context.tx().effective_gas_price(basefee);
        let gas = exec_result.gas();

        let reimbursement =
            effective_gas_price.saturating_mul((gas.remaining() + gas.refunded() as u64) as u128);
        token_operation::<CTX, ERROR>(context, TREASURY, caller, U256::from(reimbursement))?;

        Ok(())
    }

    fn reward_beneficiary(
        &self,
        context: &mut Self::Context,
        exec_result: &mut Self::ExecResult,
    ) -> Result<(), Self::Error> {
        let tx = context.tx();
        let beneficiary = context.block().beneficiary();
        let basefee = context.block().basefee() as u128;
        let effective_gas_price = tx.effective_gas_price(basefee);
        let gas = exec_result.gas();

        let coinbase_gas_price = if context.cfg().spec().into().is_enabled_in(SpecId::LONDON) {
            effective_gas_price.saturating_sub(basefee)
        } else {
            effective_gas_price
        };

        let reward =
            coinbase_gas_price.saturating_mul((gas.spent() - gas.refunded() as u64) as u128);
        token_operation::<CTX, ERROR>(context, TREASURY, beneficiary, U256::from(reward))?;

        Ok(())
    }

    fn output(
        &self,
        context: &mut Self::Context,
        result: Self::ExecResult,
    ) -> Result<Self::Output, Self::Error> {
        self.inner.output(context, result)
    }

    fn clear(&self, context: &mut Self::Context) {
        self.inner.clear(context)
    }
}