revme/cmd/blockchaintest/
post_block.rs

1use revm::{
2    context::{Block, ContextTr},
3    database::State,
4    handler::EvmTr,
5    primitives::{hardfork::SpecId, ONE_ETHER, ONE_GWEI},
6    Database, SystemCallCommitEvm,
7};
8use statetest_types::blockchain::Withdrawal;
9
10/// Post block transition that includes:
11///   * Block and uncle rewards before the Merge/Paris hardfork.
12///   * system calls
13///
14/// # Note
15///
16/// Uncle rewards are not implemented yet.
17#[inline]
18pub fn post_block_transition<
19    'a,
20    DB: Database + 'a,
21    EVM: SystemCallCommitEvm<Error: core::fmt::Debug>
22        + EvmTr<Context: ContextTr<Db = &'a mut State<DB>>>,
23>(
24    evm: &mut EVM,
25    block: impl Block,
26    withdrawals: &[Withdrawal],
27    spec: SpecId,
28) {
29    // block reward
30    let block_reward = block_reward(spec, 0);
31    if block_reward != 0 {
32        let _ = evm
33            .ctx_mut()
34            .db_mut()
35            .increment_balances(vec![(block.beneficiary(), block_reward)]);
36    }
37
38    // withdrawals
39    if spec.is_enabled_in(SpecId::SHANGHAI) {
40        for withdrawal in withdrawals {
41            evm.ctx_mut()
42                .db_mut()
43                .increment_balances(vec![(
44                    withdrawal.address,
45                    withdrawal.amount.to::<u128>().saturating_mul(ONE_GWEI),
46                )])
47                .expect("Db actions to pass");
48        }
49    }
50}
51
52/// Block reward for a block.
53#[inline]
54pub const fn block_reward(spec: SpecId, ommers: usize) -> u128 {
55    if spec.is_enabled_in(SpecId::MERGE) {
56        return 0;
57    }
58
59    let reward = if spec.is_enabled_in(SpecId::CONSTANTINOPLE) {
60        ONE_ETHER * 2
61    } else if spec.is_enabled_in(SpecId::BYZANTIUM) {
62        ONE_ETHER * 3
63    } else {
64        ONE_ETHER * 5
65    };
66
67    reward + (reward >> 5) * ommers as u128
68}