reth_evm/system_calls/
eip7251.rs

1//! [EIP-7251](https://eips.ethereum.org/EIPS/eip-7251) system call implementation.
2use crate::ConfigureEvm;
3use alloc::{boxed::Box, format};
4use alloy_eips::eip7251::CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS;
5use alloy_primitives::Bytes;
6use reth_execution_errors::{BlockExecutionError, BlockValidationError};
7use revm::{interpreter::Host, Database, Evm};
8use revm_primitives::{ExecutionResult, ResultAndState};
9
10/// Applies the post-block call to the EIP-7251 consolidation requests contract.
11///
12/// If Prague is not active at the given timestamp, then this is a no-op, and an empty vector is
13/// returned. Otherwise, the consolidation requests are returned.
14///
15/// Note: this does not commit the state changes to the database, it only transact the call.
16#[inline]
17pub(crate) fn transact_consolidation_requests_contract_call<EvmConfig, EXT, DB>(
18    evm_config: &EvmConfig,
19    evm: &mut Evm<'_, EXT, DB>,
20) -> Result<ResultAndState, BlockExecutionError>
21where
22    DB: Database,
23    DB::Error: core::fmt::Display,
24    EvmConfig: ConfigureEvm,
25{
26    // get previous env
27    let previous_env = Box::new(evm.context.env().clone());
28
29    // Fill transaction environment with the EIP-7251 consolidation requests contract message data.
30    //
31    // This requirement for the consolidation requests contract call defined by
32    // [EIP-7251](https://eips.ethereum.org/EIPS/eip-7251) is:
33    //
34    // At the end of processing any execution block where block.timestamp >= FORK_TIMESTAMP (i.e.
35    // after processing all transactions and after performing the block body requests validations)
36    // clienst software MUST [..] call the contract as `SYSTEM_ADDRESS` and empty input data to
37    // trigger the system subroutine execute.
38    evm_config.fill_tx_env_system_contract_call(
39        &mut evm.context.evm.env,
40        alloy_eips::eip7002::SYSTEM_ADDRESS,
41        CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS,
42        Bytes::new(),
43    );
44
45    let mut res = match evm.transact() {
46        Ok(res) => res,
47        Err(e) => {
48            evm.context.evm.env = previous_env;
49            return Err(BlockValidationError::ConsolidationRequestsContractCall {
50                message: format!("execution failed: {e}"),
51            }
52            .into())
53        }
54    };
55
56    // cleanup the state
57    res.state.remove(&alloy_eips::eip7002::SYSTEM_ADDRESS);
58    res.state.remove(&evm.block().coinbase);
59
60    // re-set the previous env
61    evm.context.evm.env = previous_env;
62
63    Ok(res)
64}
65
66/// Calls the consolidation requests system contract, and returns the requests from the execution
67/// output.
68#[inline]
69pub(crate) fn post_commit(result: ExecutionResult) -> Result<Bytes, BlockExecutionError> {
70    match result {
71        ExecutionResult::Success { output, .. } => Ok(output.into_data()),
72        ExecutionResult::Revert { output, .. } => {
73            Err(BlockValidationError::ConsolidationRequestsContractCall {
74                message: format!("execution reverted: {output}"),
75            }
76            .into())
77        }
78        ExecutionResult::Halt { reason, .. } => {
79            Err(BlockValidationError::ConsolidationRequestsContractCall {
80                message: format!("execution halted: {reason:?}"),
81            }
82            .into())
83        }
84    }
85}