Skip to main content

reth_storage_api/
evm.rs

1//! State access for EVM execution.
2
3use crate::StateProvider;
4use alloc::boxed::Box;
5use alloy_primitives::{Address, BlockNumber, StorageKey, StorageValue, B256};
6use core::ops::Deref;
7use reth_primitives_traits::{Account, Bytecode};
8use reth_storage_errors::provider::ProviderResult;
9
10/// Provides the state necessary for EVM execution.
11#[auto_impl::auto_impl(&, Arc, Box)]
12pub trait EvmStateProvider {
13    /// Returns the account, or `None` if it does not exist.
14    fn basic_account(&self, address: &Address) -> ProviderResult<Option<Account>>;
15
16    /// Returns the block hash, or `None` if the block does not exist.
17    fn block_hash(&self, number: BlockNumber) -> ProviderResult<Option<B256>>;
18
19    /// Returns bytecode by its hash.
20    fn bytecode_by_hash(&self, code_hash: &B256) -> ProviderResult<Option<Bytecode>>;
21
22    /// Returns the storage value of the given account and slot.
23    fn storage(
24        &self,
25        account: Address,
26        storage_key: StorageKey,
27    ) -> ProviderResult<Option<StorageValue>>;
28}
29
30/// Type-erased provider for EVM execution.
31pub type EvmStateProviderBox = Box<dyn EvmStateProvider + Send>;
32
33/// Adapts an owned or borrowed full state provider for EVM execution.
34#[derive(Debug, Clone, Copy)]
35pub struct EvmStateProviderAdapter<P>(pub P);
36
37impl<P> Deref for EvmStateProviderAdapter<P> {
38    type Target = P;
39
40    fn deref(&self) -> &Self::Target {
41        &self.0
42    }
43}
44
45impl<P: StateProvider> EvmStateProvider for EvmStateProviderAdapter<P> {
46    fn basic_account(&self, address: &Address) -> ProviderResult<Option<Account>> {
47        self.0.basic_account(address)
48    }
49
50    fn block_hash(&self, number: BlockNumber) -> ProviderResult<Option<B256>> {
51        self.0.block_hash(number)
52    }
53
54    fn bytecode_by_hash(&self, code_hash: &B256) -> ProviderResult<Option<Bytecode>> {
55        self.0.bytecode_by_hash(code_hash)
56    }
57
58    fn storage(
59        &self,
60        account: Address,
61        storage_key: StorageKey,
62    ) -> ProviderResult<Option<StorageValue>> {
63        self.0.storage(account, storage_key)
64    }
65}
66
67#[cfg(test)]
68mod tests {
69    use super::*;
70    use crate::{noop::NoopProvider, StateProviderBox};
71    use alloc::sync::Arc;
72
73    #[test]
74    fn converts_owned_borrowed_and_boxed_state_providers() {
75        let provider = NoopProvider::default();
76        assert_reads((&provider).into_evm_state_provider());
77        assert_reads((&provider as &dyn StateProvider).into_evm_state_provider());
78        assert_reads(provider.into_evm_state_provider());
79
80        let boxed = Box::new(NoopProvider::default()) as StateProviderBox;
81        assert_reads(boxed.into_evm_state_provider());
82        assert_reads(Arc::new(NoopProvider::default()).into_evm_state_provider());
83    }
84
85    #[test]
86    fn delegates_execution_only_references_and_boxes() {
87        let provider = NoopProvider::default();
88        let adapter = (&provider).into_evm_state_provider();
89        assert_reads(&adapter as &dyn EvmStateProvider);
90        assert_reads(Box::new(adapter) as Box<dyn EvmStateProvider + '_>);
91
92        let boxed = Box::new(provider.into_evm_state_provider()) as EvmStateProviderBox;
93        assert_reads(boxed);
94        assert_reads(Arc::new(NoopProvider::default().into_evm_state_provider()));
95    }
96
97    #[test]
98    fn exposes_inner_state_provider() {
99        let provider = NoopProvider::default();
100        let adapter = (&provider).into_evm_state_provider();
101        assert_eq!(adapter.account_balance(&Address::ZERO).unwrap(), None);
102        assert!(core::ptr::eq(*adapter, &raw const provider));
103    }
104
105    fn assert_reads(provider: impl EvmStateProvider) {
106        assert_eq!(provider.basic_account(&Address::ZERO).unwrap(), None);
107        assert_eq!(provider.block_hash(1).unwrap(), None);
108        assert_eq!(provider.bytecode_by_hash(&B256::ZERO).unwrap(), None);
109        assert_eq!(provider.storage(Address::ZERO, B256::ZERO).unwrap(), None);
110    }
111}