reth_rpc/eth/helpers/
state.rs

1//! Contains RPC handler implementations specific to state.
2
3use reth_chainspec::EthereumHardforks;
4use reth_provider::{BlockReader, ChainSpecProvider, 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;
40    use alloy_primitives::{Address, StorageKey, U256};
41    use reth_chainspec::MAINNET;
42    use reth_evm_ethereum::EthEvmConfig;
43    use reth_network_api::noop::NoopNetwork;
44    use reth_provider::test_utils::{ExtendedAccount, MockEthProvider, NoopProvider};
45    use reth_rpc_eth_api::helpers::EthState;
46    use reth_rpc_eth_types::{
47        EthStateCache, FeeHistoryCache, FeeHistoryCacheConfig, GasPriceOracle,
48    };
49    use reth_rpc_server_types::constants::{
50        DEFAULT_ETH_PROOF_WINDOW, DEFAULT_MAX_SIMULATE_BLOCKS, DEFAULT_PROOF_PERMITS,
51    };
52    use reth_tasks::pool::BlockingTaskPool;
53    use reth_transaction_pool::test_utils::{testing_pool, TestPool};
54    use revm_primitives::FlaggedStorage;
55    use std::collections::HashMap;
56
57    fn noop_eth_api() -> EthApi<NoopProvider, TestPool, NoopNetwork, EthEvmConfig> {
58        let pool = testing_pool();
59        let evm_config = EthEvmConfig::new(MAINNET.clone());
60
61        let cache = EthStateCache::spawn(NoopProvider::default(), Default::default());
62        EthApi::new(
63            NoopProvider::default(),
64            pool,
65            NoopNetwork::default(),
66            cache.clone(),
67            GasPriceOracle::new(NoopProvider::default(), Default::default(), cache),
68            ETHEREUM_BLOCK_GAS_LIMIT,
69            DEFAULT_MAX_SIMULATE_BLOCKS,
70            DEFAULT_ETH_PROOF_WINDOW,
71            BlockingTaskPool::build().expect("failed to build tracing pool"),
72            FeeHistoryCache::new(FeeHistoryCacheConfig::default()),
73            evm_config,
74            DEFAULT_PROOF_PERMITS,
75        )
76    }
77
78    fn mock_eth_api(
79        accounts: HashMap<Address, ExtendedAccount>,
80    ) -> EthApi<MockEthProvider, TestPool, (), EthEvmConfig> {
81        let pool = testing_pool();
82        let mock_provider = MockEthProvider::default();
83
84        let evm_config = EthEvmConfig::new(mock_provider.chain_spec());
85        mock_provider.extend_accounts(accounts);
86
87        let cache = EthStateCache::spawn(mock_provider.clone(), Default::default());
88        EthApi::new(
89            mock_provider.clone(),
90            pool,
91            (),
92            cache.clone(),
93            GasPriceOracle::new(mock_provider, Default::default(), cache),
94            ETHEREUM_BLOCK_GAS_LIMIT,
95            DEFAULT_MAX_SIMULATE_BLOCKS,
96            DEFAULT_ETH_PROOF_WINDOW + 1,
97            BlockingTaskPool::build().expect("failed to build tracing pool"),
98            FeeHistoryCache::new(FeeHistoryCacheConfig::default()),
99            evm_config,
100            DEFAULT_PROOF_PERMITS,
101        )
102    }
103
104    #[tokio::test]
105    async fn test_storage() {
106        // === Noop ===
107        let eth_api = noop_eth_api();
108        let address = Address::random();
109        let storage = eth_api.storage_at(address, U256::ZERO.into(), None).await.unwrap();
110        assert_eq!(storage, U256::ZERO.to_be_bytes());
111
112        // === Mock ===
113        let storage_value = FlaggedStorage::new_from_value(1337);
114        let storage_key = StorageKey::random();
115        let storage = HashMap::from([(storage_key, storage_value)]);
116
117        let accounts =
118            HashMap::from([(address, ExtendedAccount::new(0, U256::ZERO).extend_storage(storage))]);
119        let eth_api = mock_eth_api(accounts);
120
121        let storage_key: U256 = storage_key.into();
122        let storage = eth_api.storage_at(address, storage_key.into(), None).await.unwrap();
123        assert_eq!(storage, storage_value.value.to_be_bytes());
124    }
125
126    #[tokio::test]
127    async fn test_get_account_missing() {
128        let eth_api = noop_eth_api();
129        let address = Address::random();
130        let account = eth_api.get_account(address, Default::default()).await.unwrap();
131        assert!(account.is_none());
132    }
133}