use reth_interfaces::Error; use reth_primitives::{H160, H256, KECCAK_EMPTY, U256}; use reth_provider::StateProvider; use revm::{ db::{CacheDB, DatabaseRef}, primitives::{AccountInfo, Bytecode}, }; /// SubState of database. Uses revm internal cache with binding to reth StateProvider trait. pub type SubState = CacheDB>; /// Wrapper around StateProvider that implements revm database trait #[derive(Debug, Clone)] pub struct State(pub DB); impl State { /// Create new State with generic StateProvider. pub fn new(db: DB) -> Self { Self(db) } /// Return inner state reference pub fn state(&self) -> &DB { &self.0 } /// Return inner state mutable reference pub fn state_mut(&mut self) -> &mut DB { &mut self.0 } /// Consume State and return inner StateProvider. pub fn into_inner(self) -> DB { self.0 } } impl DatabaseRef for State { type Error = Error; fn basic(&self, address: H160) -> Result, Self::Error> { Ok(self.0.basic_account(address)?.map(|account| AccountInfo { balance: account.balance, nonce: account.nonce, code_hash: account.bytecode_hash.unwrap_or(KECCAK_EMPTY), code: None, })) } fn code_by_hash(&self, code_hash: H256) -> Result { let bytecode = self.0.bytecode_by_hash(code_hash)?; if let Some(bytecode) = bytecode { Ok(bytecode.with_code_hash(code_hash).0) } else { Ok(Bytecode::new()) } } fn storage(&self, address: H160, index: U256) -> Result { let index = H256(index.to_be_bytes()); let ret = self.0.storage(address, index)?.unwrap_or_default(); Ok(ret) } fn block_hash(&self, number: U256) -> Result { // Note: this unwrap is potentially unsafe Ok(self.0.block_hash(number.try_into().unwrap())?.unwrap_or_default()) } }