Skip to main content

revme/cmd/blockchaintest/
post_block.rs

1use revm::{
2    context::{Block, ContextTr, JournalTr},
3    handler::EvmTr,
4    primitives::{address, hardfork::SpecId, Address, Bytes, ONE_ETHER, ONE_GWEI, U256},
5    statetest_types::blockchain::Withdrawal,
6    Database, DatabaseCommit, SystemCallCommitEvm,
7};
8
9/// Post block transition that includes:
10///   * Block and uncle rewards before the Merge/Paris hardfork.
11///   * Withdrawals (EIP-4895)
12///   * Post-block system calls: EIP-7002 (withdrawal requests) and EIP-7251 (consolidation requests)
13///
14/// # Note
15///
16/// Uncle rewards are not implemented yet.
17#[inline]
18pub fn post_block_transition<
19    'a,
20    DB: Database + DatabaseCommit + 'a,
21    EVM: SystemCallCommitEvm<Error: core::fmt::Debug> + EvmTr<Context: ContextTr<Db = DB>>,
22>(
23    evm: &mut EVM,
24    block: impl Block,
25    withdrawals: &[Withdrawal],
26    spec: SpecId,
27) -> Result<(), EVM::Error> {
28    // block reward
29    let block_reward = block_reward(spec, 0);
30    if block_reward != 0 {
31        evm.ctx_mut()
32            .journal_mut()
33            .balance_incr(block.beneficiary(), U256::from(block_reward))
34            .expect("Db actions to pass");
35    }
36
37    // withdrawals
38    if spec.is_enabled_in(SpecId::SHANGHAI) {
39        for withdrawal in withdrawals {
40            evm.ctx_mut()
41                .journal_mut()
42                .balance_incr(
43                    withdrawal.address,
44                    withdrawal.amount.saturating_mul(U256::from(ONE_GWEI)),
45                )
46                .expect("Db actions to pass");
47        }
48    }
49
50    evm.commit_inner();
51
52    // EIP-7002: Withdrawal requests system call
53    if spec.is_enabled_in(SpecId::PRAGUE) {
54        system_call_eip7002_withdrawal_request(evm)?;
55    }
56
57    // EIP-7251: Consolidation requests system call
58    if spec.is_enabled_in(SpecId::PRAGUE) {
59        system_call_eip7251_consolidation_request(evm)?;
60    }
61
62    // EIP-8282: Builder execution requests system calls (builder deposit and
63    // builder exit), introduced in Amsterdam.
64    if spec.is_enabled_in(SpecId::AMSTERDAM) {
65        system_call_eip8282_builder_deposit_request(evm)?;
66        system_call_eip8282_builder_exit_request(evm)?;
67    }
68
69    Ok(())
70}
71
72/// Block reward for a block.
73#[inline]
74pub const fn block_reward(spec: SpecId, ommers: usize) -> u128 {
75    if spec.is_enabled_in(SpecId::MERGE) {
76        return 0;
77    }
78
79    let reward = if spec.is_enabled_in(SpecId::PETERSBURG) {
80        ONE_ETHER * 2
81    } else if spec.is_enabled_in(SpecId::BYZANTIUM) {
82        ONE_ETHER * 3
83    } else {
84        ONE_ETHER * 5
85    };
86
87    reward + (reward >> 5) * ommers as u128
88}
89
90pub const WITHDRAWAL_REQUEST_ADDRESS: Address =
91    address!("0x00000961Ef480Eb55e80D19ad83579A64c007002");
92
93/// EIP-7002: Withdrawal requests system call
94pub(crate) fn system_call_eip7002_withdrawal_request<EVM>(evm: &mut EVM) -> Result<(), EVM::Error>
95where
96    EVM: SystemCallCommitEvm<Error: core::fmt::Debug>,
97{
98    // empty data is valid for EIP-7002
99    evm.system_call_commit(WITHDRAWAL_REQUEST_ADDRESS, Bytes::new())?;
100    Ok(())
101}
102
103pub const CONSOLIDATION_REQUEST_ADDRESS: Address =
104    address!("0x0000BBdDc7CE488642fb579F8B00f3a590007251");
105
106/// EIP-7251: Consolidation requests system call
107pub(crate) fn system_call_eip7251_consolidation_request<EVM>(
108    evm: &mut EVM,
109) -> Result<(), EVM::Error>
110where
111    EVM: SystemCallCommitEvm<Error: core::fmt::Debug>,
112{
113    evm.system_call_commit(CONSOLIDATION_REQUEST_ADDRESS, Bytes::new())?;
114    Ok(())
115}
116
117pub const BUILDER_DEPOSIT_REQUEST_ADDRESS: Address =
118    address!("0x0000884d2AA32eAa155F59A2f24eFa73D9008282");
119
120/// EIP-8282: Builder deposit requests system call (request type `0x03`).
121pub(crate) fn system_call_eip8282_builder_deposit_request<EVM>(
122    evm: &mut EVM,
123) -> Result<(), EVM::Error>
124where
125    EVM: SystemCallCommitEvm<Error: core::fmt::Debug>,
126{
127    evm.system_call_commit(BUILDER_DEPOSIT_REQUEST_ADDRESS, Bytes::new())?;
128    Ok(())
129}
130
131pub const BUILDER_EXIT_REQUEST_ADDRESS: Address =
132    address!("0x000014574A74c805590AFF9499fc7A690f008282");
133
134/// EIP-8282: Builder exit requests system call (request type `0x04`).
135pub(crate) fn system_call_eip8282_builder_exit_request<EVM>(evm: &mut EVM) -> Result<(), EVM::Error>
136where
137    EVM: SystemCallCommitEvm<Error: core::fmt::Debug>,
138{
139    evm.system_call_commit(BUILDER_EXIT_REQUEST_ADDRESS, Bytes::new())?;
140    Ok(())
141}