1use 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#[auto_impl::auto_impl(&, Arc, Box)]
12pub trait EvmStateProvider {
13 fn basic_account(&self, address: &Address) -> ProviderResult<Option<Account>>;
15
16 fn block_hash(&self, number: BlockNumber) -> ProviderResult<Option<B256>>;
18
19 fn bytecode_by_hash(&self, code_hash: &B256) -> ProviderResult<Option<Bytecode>>;
21
22 fn storage(
24 &self,
25 account: Address,
26 storage_key: StorageKey,
27 ) -> ProviderResult<Option<StorageValue>>;
28}
29
30pub type EvmStateProviderBox = Box<dyn EvmStateProvider + Send>;
32
33#[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}