reth_evm/system_calls/
eip2935.rs1use alloc::{boxed::Box, string::ToString};
4use alloy_eips::eip2935::HISTORY_STORAGE_ADDRESS;
5
6use crate::ConfigureEvm;
7use alloy_primitives::B256;
8use reth_chainspec::EthereumHardforks;
9use reth_execution_errors::{BlockExecutionError, BlockValidationError};
10use revm::{interpreter::Host, Database, Evm};
11use revm_primitives::ResultAndState;
12
13#[inline]
26pub(crate) fn transact_blockhashes_contract_call<EvmConfig, EXT, DB>(
27 evm_config: &EvmConfig,
28 chain_spec: impl EthereumHardforks,
29 block_timestamp: u64,
30 block_number: u64,
31 parent_block_hash: B256,
32 evm: &mut Evm<'_, EXT, DB>,
33) -> Result<Option<ResultAndState>, BlockExecutionError>
34where
35 DB: Database,
36 DB::Error: core::fmt::Display,
37 EvmConfig: ConfigureEvm,
38{
39 if !chain_spec.is_prague_active_at_timestamp(block_timestamp) {
40 return Ok(None)
41 }
42
43 if block_number == 0 {
46 return Ok(None)
47 }
48
49 let previous_env = Box::new(evm.context.env().clone());
51
52 evm_config.fill_tx_env_system_contract_call(
54 &mut evm.context.evm.env,
55 alloy_eips::eip4788::SYSTEM_ADDRESS,
56 HISTORY_STORAGE_ADDRESS,
57 parent_block_hash.0.into(),
58 );
59
60 let mut res = match evm.transact() {
61 Ok(res) => res,
62 Err(e) => {
63 evm.context.evm.env = previous_env;
64 return Err(BlockValidationError::BlockHashContractCall { message: e.to_string() }.into())
65 }
66 };
67
68 res.state.remove(&alloy_eips::eip4788::SYSTEM_ADDRESS);
69 res.state.remove(&evm.block().coinbase);
70
71 evm.context.evm.env = previous_env;
73
74 Ok(Some(res))
75}