1#[cfg(feature = "std")]
4use alloy_primitives::{Address, B256};
5use core::ops::{Deref, DerefMut};
6#[cfg(feature = "std")]
7use evm2::{
8 bytecode::Bytecode,
9 evm::{AccountInfo, Database},
10 interpreter::Word,
11};
12#[cfg(feature = "std")]
13use reth_storage_api::EvmStateProvider;
14#[cfg(feature = "std")]
15use reth_storage_errors::provider::ProviderError;
16
17#[derive(Clone)]
19pub struct StateProviderDatabase<DB>(pub DB);
20
21impl<DB> StateProviderDatabase<DB> {
22 pub const fn new(db: DB) -> Self {
24 Self(db)
25 }
26
27 pub fn into_inner(self) -> DB {
29 self.0
30 }
31}
32
33impl<DB> core::fmt::Debug for StateProviderDatabase<DB> {
34 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
35 f.debug_struct("StateProviderDatabase").finish_non_exhaustive()
36 }
37}
38
39impl<DB> AsRef<DB> for StateProviderDatabase<DB> {
40 fn as_ref(&self) -> &DB {
41 &self.0
42 }
43}
44
45impl<DB> Deref for StateProviderDatabase<DB> {
46 type Target = DB;
47
48 fn deref(&self) -> &Self::Target {
49 &self.0
50 }
51}
52
53impl<DB> DerefMut for StateProviderDatabase<DB> {
54 fn deref_mut(&mut self) -> &mut Self::Target {
55 &mut self.0
56 }
57}
58
59#[cfg(feature = "std")]
60impl<DB> Database for StateProviderDatabase<DB>
61where
62 DB: EvmStateProvider,
63{
64 type Error = ProviderError;
65
66 fn get_account(&mut self, address: &Address) -> Result<Option<AccountInfo>, Self::Error> {
67 Ok(self.0.basic_account(address)?.map(Into::into))
68 }
69
70 fn get_code_by_hash(&mut self, code_hash: &B256) -> Result<Bytecode, Self::Error> {
71 Ok(self.0.bytecode_by_hash(code_hash)?.map(|code| code.0).unwrap_or_default())
72 }
73
74 fn get_storage(&mut self, address: &Address, key: &Word) -> Result<Word, Self::Error> {
75 Ok(self.0.storage(*address, B256::from(*key))?.unwrap_or_default())
76 }
77
78 fn get_block_hash(&mut self, number: &Word) -> Result<B256, Self::Error> {
79 let number = number.saturating_to::<u64>();
80 Ok(self.0.block_hash(number)?.unwrap_or_default())
81 }
82}
83
84#[cfg(all(test, feature = "std"))]
85mod tests {
86 use super::*;
87 use reth_storage_api::{noop::NoopProvider, StateProvider};
88
89 #[test]
90 fn missing_block_hash_returns_zero() {
91 let mut native =
92 StateProviderDatabase::new(NoopProvider::mainnet().into_evm_state_provider());
93 assert_eq!(native.get_block_hash(&Word::from(42)).unwrap(), B256::ZERO);
94 }
95}