mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
84 lines
3.0 KiB
Rust
84 lines
3.0 KiB
Rust
//! [EIP-7002](https://eips.ethereum.org/EIPS/eip-7002) system call implementation.
|
|
use crate::ConfigureEvm;
|
|
use alloc::{boxed::Box, format};
|
|
use alloy_eips::eip7002::WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS;
|
|
use alloy_primitives::Bytes;
|
|
use reth_execution_errors::{BlockExecutionError, BlockValidationError};
|
|
use revm::{interpreter::Host, Database, Evm};
|
|
use revm_primitives::{ExecutionResult, ResultAndState};
|
|
|
|
/// Applies the post-block call to the EIP-7002 withdrawal requests contract.
|
|
///
|
|
/// If Prague is not active at the given timestamp, then this is a no-op.
|
|
///
|
|
/// Note: this does not commit the state changes to the database, it only transact the call.
|
|
#[inline]
|
|
pub(crate) fn transact_withdrawal_requests_contract_call<EvmConfig, EXT, DB>(
|
|
evm_config: &EvmConfig,
|
|
evm: &mut Evm<'_, EXT, DB>,
|
|
) -> Result<ResultAndState, BlockExecutionError>
|
|
where
|
|
DB: Database,
|
|
DB::Error: core::fmt::Display,
|
|
EvmConfig: ConfigureEvm,
|
|
{
|
|
// get previous env
|
|
let previous_env = Box::new(evm.context.env().clone());
|
|
|
|
// Fill transaction environment with the EIP-7002 withdrawal requests contract message data.
|
|
//
|
|
// This requirement for the withdrawal requests contract call defined by
|
|
// [EIP-7002](https://eips.ethereum.org/EIPS/eip-7002) is:
|
|
//
|
|
// At the end of processing any execution block where `block.timestamp >= FORK_TIMESTAMP` (i.e.
|
|
// after processing all transactions and after performing the block body withdrawal requests
|
|
// validations), call the contract as `SYSTEM_ADDRESS`.
|
|
evm_config.fill_tx_env_system_contract_call(
|
|
&mut evm.context.evm.env,
|
|
alloy_eips::eip7002::SYSTEM_ADDRESS,
|
|
WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS,
|
|
Bytes::new(),
|
|
);
|
|
|
|
let mut res = match evm.transact() {
|
|
Ok(res) => res,
|
|
Err(e) => {
|
|
evm.context.evm.env = previous_env;
|
|
return Err(BlockValidationError::WithdrawalRequestsContractCall {
|
|
message: format!("execution failed: {e}"),
|
|
}
|
|
.into())
|
|
}
|
|
};
|
|
|
|
// cleanup the state
|
|
res.state.remove(&alloy_eips::eip7002::SYSTEM_ADDRESS);
|
|
res.state.remove(&evm.block().coinbase);
|
|
|
|
// re-set the previous env
|
|
evm.context.evm.env = previous_env;
|
|
|
|
Ok(res)
|
|
}
|
|
|
|
/// Calls the withdrawals requests system contract, and returns the requests from the execution
|
|
/// output.
|
|
#[inline]
|
|
pub(crate) fn post_commit(result: ExecutionResult) -> Result<Bytes, BlockExecutionError> {
|
|
match result {
|
|
ExecutionResult::Success { output, .. } => Ok(output.into_data()),
|
|
ExecutionResult::Revert { output, .. } => {
|
|
Err(BlockValidationError::WithdrawalRequestsContractCall {
|
|
message: format!("execution reverted: {output}"),
|
|
}
|
|
.into())
|
|
}
|
|
ExecutionResult::Halt { reason, .. } => {
|
|
Err(BlockValidationError::WithdrawalRequestsContractCall {
|
|
message: format!("execution halted: {reason:?}"),
|
|
}
|
|
.into())
|
|
}
|
|
}
|
|
}
|