reth_rpc/eth/helpers/
state.rs1use reth_chainspec::{ChainSpecProvider, EthereumHardforks};
4use reth_storage_api::{BlockReader, StateProviderFactory};
5use reth_transaction_pool::TransactionPool;
6
7use reth_rpc_eth_api::{
8 helpers::{EthState, LoadState, SpawnBlocking},
9 RpcNodeCoreExt,
10};
11
12use crate::EthApi;
13
14impl<Provider, Pool, Network, EvmConfig> EthState for EthApi<Provider, Pool, Network, EvmConfig>
15where
16 Self: LoadState + SpawnBlocking,
17 Provider: BlockReader,
18{
19 fn max_proof_window(&self) -> u64 {
20 self.inner.eth_proof_window()
21 }
22}
23
24impl<Provider, Pool, Network, EvmConfig> LoadState for EthApi<Provider, Pool, Network, EvmConfig>
25where
26 Self: RpcNodeCoreExt<
27 Provider: BlockReader
28 + StateProviderFactory
29 + ChainSpecProvider<ChainSpec: EthereumHardforks>,
30 Pool: TransactionPool,
31 >,
32 Provider: BlockReader,
33{
34}
35
36#[cfg(test)]
37mod tests {
38 use super::*;
39 use alloy_eips::eip1559::ETHEREUM_BLOCK_GAS_LIMIT_30M;
40 use alloy_primitives::{Address, StorageKey, U256};
41 use reth_evm_ethereum::EthEvmConfig;
42 use reth_network_api::noop::NoopNetwork;
43 use reth_provider::test_utils::{ExtendedAccount, MockEthProvider, NoopProvider};
44 use reth_rpc_eth_api::helpers::EthState;
45 use reth_rpc_eth_types::{
46 EthStateCache, FeeHistoryCache, FeeHistoryCacheConfig, GasPriceOracle,
47 };
48 use reth_rpc_server_types::constants::{
49 DEFAULT_ETH_PROOF_WINDOW, DEFAULT_MAX_SIMULATE_BLOCKS, DEFAULT_PROOF_PERMITS,
50 };
51 use reth_tasks::pool::BlockingTaskPool;
52 use reth_transaction_pool::test_utils::{testing_pool, TestPool};
53 use revm::state::FlaggedStorage;
54 use std::collections::HashMap;
55
56 fn noop_eth_api() -> EthApi<NoopProvider, TestPool, NoopNetwork, EthEvmConfig> {
57 let pool = testing_pool();
58 let evm_config = EthEvmConfig::mainnet();
59
60 let cache = EthStateCache::spawn(NoopProvider::default(), Default::default());
61 EthApi::new(
62 NoopProvider::default(),
63 pool,
64 NoopNetwork::default(),
65 cache.clone(),
66 GasPriceOracle::new(NoopProvider::default(), Default::default(), cache),
67 ETHEREUM_BLOCK_GAS_LIMIT_30M,
68 DEFAULT_MAX_SIMULATE_BLOCKS,
69 DEFAULT_ETH_PROOF_WINDOW,
70 BlockingTaskPool::build().expect("failed to build tracing pool"),
71 FeeHistoryCache::new(FeeHistoryCacheConfig::default()),
72 evm_config,
73 DEFAULT_PROOF_PERMITS,
74 )
75 }
76
77 fn mock_eth_api(
78 accounts: HashMap<Address, ExtendedAccount>,
79 ) -> EthApi<MockEthProvider, TestPool, (), EthEvmConfig> {
80 let pool = testing_pool();
81 let mock_provider = MockEthProvider::default();
82
83 let evm_config = EthEvmConfig::new(mock_provider.chain_spec());
84 mock_provider.extend_accounts(accounts);
85
86 let cache = EthStateCache::spawn(mock_provider.clone(), Default::default());
87 EthApi::new(
88 mock_provider.clone(),
89 pool,
90 (),
91 cache.clone(),
92 GasPriceOracle::new(mock_provider, Default::default(), cache),
93 ETHEREUM_BLOCK_GAS_LIMIT_30M,
94 DEFAULT_MAX_SIMULATE_BLOCKS,
95 DEFAULT_ETH_PROOF_WINDOW + 1,
96 BlockingTaskPool::build().expect("failed to build tracing pool"),
97 FeeHistoryCache::new(FeeHistoryCacheConfig::default()),
98 evm_config,
99 DEFAULT_PROOF_PERMITS,
100 )
101 }
102
103 #[tokio::test]
104 async fn test_storage() {
105 let eth_api = noop_eth_api();
107 let address = Address::random();
108 let storage = eth_api.storage_at(address, U256::ZERO.into(), None).await.unwrap();
109 assert_eq!(storage, U256::ZERO.to_be_bytes());
110
111 let storage_value = FlaggedStorage::new_from_value(1337);
113 let storage_key = StorageKey::random();
114 let storage = HashMap::from([(storage_key, storage_value)]);
115
116 let accounts =
117 HashMap::from([(address, ExtendedAccount::new(0, U256::ZERO).extend_storage(storage))]);
118 let eth_api = mock_eth_api(accounts);
119
120 let storage_key: U256 = storage_key.into();
121 let storage = eth_api.storage_at(address, storage_key.into(), None).await.unwrap();
122 assert_eq!(storage, storage_value.value.to_be_bytes());
123 }
124
125 #[tokio::test]
126 async fn test_get_account_missing() {
127 let eth_api = noop_eth_api();
128 let address = Address::random();
129 let account = eth_api.get_account(address, Default::default()).await.unwrap();
130 assert!(account.is_none());
131 }
132}