1use crate::primitives::alloy_primitives::{BlockNumber, StorageKey};
2use alloy_primitives::{Address, B256, U256};
3use core::ops::{Deref, DerefMut};
4use reth_primitives_traits::Account;
5use reth_storage_api::{AccountReader, BlockHashReader, StateProvider};
6use reth_storage_errors::provider::{ProviderError, ProviderResult};
7use revm::{
8 bytecode::Bytecode,
9 state::{AccountInfo, FlaggedStorage},
10 Database, DatabaseRef,
11};
12
13pub trait EvmStateProvider: Send + Sync {
17 fn basic_account(&self, address: &Address) -> ProviderResult<Option<Account>>;
21
22 fn block_hash(&self, number: BlockNumber) -> ProviderResult<Option<B256>>;
25
26 fn bytecode_by_hash(
28 &self,
29 code_hash: &B256,
30 ) -> ProviderResult<Option<reth_primitives_traits::Bytecode>>;
31
32 fn storage(
34 &self,
35 account: Address,
36 storage_key: StorageKey,
37 ) -> ProviderResult<Option<FlaggedStorage>>;
38}
39
40impl<T: StateProvider> EvmStateProvider for T {
42 fn basic_account(&self, address: &Address) -> ProviderResult<Option<Account>> {
43 <T as AccountReader>::basic_account(self, address)
44 }
45
46 fn block_hash(&self, number: BlockNumber) -> ProviderResult<Option<B256>> {
47 <T as BlockHashReader>::block_hash(self, number)
48 }
49
50 fn bytecode_by_hash(
51 &self,
52 code_hash: &B256,
53 ) -> ProviderResult<Option<reth_primitives_traits::Bytecode>> {
54 <T as StateProvider>::bytecode_by_hash(self, code_hash)
55 }
56
57 fn storage(
58 &self,
59 account: Address,
60 storage_key: StorageKey,
61 ) -> ProviderResult<Option<FlaggedStorage>> {
62 <T as reth_storage_api::StateProvider>::storage(self, account, storage_key)
63 }
64}
65
66#[derive(Debug, Clone)]
69pub struct StateProviderDatabase<DB>(pub DB);
70
71impl<DB> StateProviderDatabase<DB> {
72 pub const fn new(db: DB) -> Self {
74 Self(db)
75 }
76
77 pub fn into_inner(self) -> DB {
79 self.0
80 }
81}
82
83impl<DB> AsRef<DB> for StateProviderDatabase<DB> {
84 fn as_ref(&self) -> &DB {
85 self
86 }
87}
88
89impl<DB> Deref for StateProviderDatabase<DB> {
90 type Target = DB;
91
92 fn deref(&self) -> &Self::Target {
93 &self.0
94 }
95}
96
97impl<DB> DerefMut for StateProviderDatabase<DB> {
98 fn deref_mut(&mut self) -> &mut Self::Target {
99 &mut self.0
100 }
101}
102
103impl<DB: EvmStateProvider> Database for StateProviderDatabase<DB> {
104 type Error = ProviderError;
105
106 fn basic(&mut self, address: Address) -> Result<Option<AccountInfo>, Self::Error> {
111 self.basic_ref(address)
112 }
113
114 fn code_by_hash(&mut self, code_hash: B256) -> Result<Bytecode, Self::Error> {
118 self.code_by_hash_ref(code_hash)
119 }
120
121 fn storage(&mut self, address: Address, index: U256) -> Result<FlaggedStorage, Self::Error> {
125 self.storage_ref(address, index)
126 }
127
128 fn block_hash(&mut self, number: u64) -> Result<B256, Self::Error> {
133 self.block_hash_ref(number)
134 }
135}
136
137impl<DB: EvmStateProvider> DatabaseRef for StateProviderDatabase<DB> {
138 type Error = <Self as Database>::Error;
139
140 fn basic_ref(&self, address: Address) -> Result<Option<AccountInfo>, Self::Error> {
145 Ok(self.basic_account(&address)?.map(Into::into))
146 }
147
148 fn code_by_hash_ref(&self, code_hash: B256) -> Result<Bytecode, Self::Error> {
152 Ok(self.bytecode_by_hash(&code_hash)?.unwrap_or_default().0)
153 }
154
155 fn storage_ref(&self, address: Address, index: U256) -> Result<FlaggedStorage, Self::Error> {
159 Ok(self.0.storage(address, B256::new(index.to_be_bytes()))?.unwrap_or_default())
160 }
161
162 fn block_hash_ref(&self, number: u64) -> Result<B256, Self::Error> {
166 Ok(self.0.block_hash(number)?.unwrap_or_default())
168 }
169}