anvil/eth/backend/mem/
mod.rs

1//! In-memory blockchain backend.
2
3use self::state::trie_storage;
4use super::executor::new_evm_with_inspector_ref;
5use crate::{
6    config::PruneStateHistoryConfig,
7    eth::{
8        backend::{
9            cheats::CheatsManager,
10            db::{Db, MaybeFullDatabase, SerializableState},
11            executor::{ExecutedTransactions, TransactionExecutor},
12            fork::ClientFork,
13            genesis::GenesisConfig,
14            mem::{
15                state::{storage_root, trie_accounts},
16                storage::MinedTransactionReceipt,
17            },
18            notifications::{NewBlockNotification, NewBlockNotifications},
19            time::{utc_from_secs, TimeManager},
20            validate::TransactionValidator,
21        },
22        error::{BlockchainError, ErrDetail, InvalidTransactionError},
23        fees::{FeeDetails, FeeManager, MIN_SUGGESTED_PRIORITY_FEE},
24        macros::node_info,
25        pool::transactions::PoolTransaction,
26        sign::build_typed_transaction,
27        util::get_precompiles_for,
28    },
29    inject_precompiles,
30    mem::{
31        inspector::Inspector,
32        storage::{BlockchainStorage, InMemoryBlockStates, MinedBlockOutcome},
33    },
34    revm::{db::DatabaseRef, primitives::AccountInfo},
35    ForkChoice, NodeConfig, PrecompileFactory,
36};
37use alloy_chains::NamedChain;
38use alloy_consensus::{
39    transaction::Recovered, Account, BlockHeader, Header, Receipt, ReceiptWithBloom, Signed,
40    Transaction as TransactionTrait, TxEnvelope,
41};
42use alloy_eips::{eip1559::BaseFeeParams, eip4844::MAX_BLOBS_PER_BLOCK};
43use alloy_network::{
44    AnyHeader, AnyRpcBlock, AnyRpcHeader, AnyRpcTransaction, AnyTxEnvelope, AnyTxType,
45    EthereumWallet, UnknownTxEnvelope, UnknownTypedTransaction,
46};
47use alloy_primitives::{
48    address, hex, keccak256, utils::Unit, Address, Bytes, TxHash, TxKind, B256, U256, U64,
49};
50use alloy_rpc_types::{
51    anvil::Forking,
52    request::TransactionRequest,
53    serde_helpers::JsonStorageKey,
54    simulate::{SimBlock, SimCallResult, SimulatePayload, SimulatedBlock},
55    state::StateOverride,
56    trace::{
57        filter::TraceFilter,
58        geth::{
59            GethDebugBuiltInTracerType, GethDebugTracerType, GethDebugTracingCallOptions,
60            GethDebugTracingOptions, GethTrace, NoopFrame,
61        },
62        parity::LocalizedTransactionTrace,
63    },
64    AccessList, Block as AlloyBlock, BlockId, BlockNumberOrTag as BlockNumber, BlockTransactions,
65    EIP1186AccountProofResponse as AccountProof, EIP1186StorageProof as StorageProof, Filter,
66    FilteredParams, Header as AlloyHeader, Index, Log, Transaction, TransactionReceipt,
67};
68use alloy_serde::{OtherFields, WithOtherFields};
69use alloy_signer::Signature;
70use alloy_signer_local::PrivateKeySigner;
71use alloy_trie::{proof::ProofRetainer, HashBuilder, Nibbles};
72use anvil_core::eth::{
73    block::{Block, BlockInfo},
74    transaction::{
75        optimism::DepositTransaction, transaction_request_to_typed, DepositReceipt,
76        MaybeImpersonatedTransaction, PendingTransaction, ReceiptResponse, TransactionInfo,
77        TypedReceipt, TypedTransaction,
78    },
79    wallet::{Capabilities, DelegationCapability, WalletCapabilities},
80};
81use anvil_rpc::error::RpcError;
82use chrono::Datelike;
83use eyre::{Context, Result};
84use flate2::{read::GzDecoder, write::GzEncoder, Compression};
85use foundry_evm::{
86    backend::{DatabaseError, DatabaseResult, RevertStateSnapshotAction},
87    constants::DEFAULT_CREATE2_DEPLOYER_RUNTIME_CODE,
88    decode::RevertDecoder,
89    inspectors::AccessListInspector,
90    revm::{
91        db::CacheDB,
92        interpreter::InstructionResult,
93        primitives::{
94            BlockEnv, CfgEnvWithHandlerCfg, EnvWithHandlerCfg, ExecutionResult, Output, SpecId,
95            TxEnv, KECCAK_EMPTY,
96        },
97    },
98    traces::TracingInspectorConfig,
99};
100use futures::channel::mpsc::{unbounded, UnboundedSender};
101use op_alloy_consensus::{TxDeposit, DEPOSIT_TX_TYPE_ID};
102use parking_lot::{Mutex, RwLock};
103use revm::{
104    db::WrapDatabaseRef,
105    interpreter::Host,
106    primitives::{BlobExcessGasAndPrice, HashMap, OptimismFields, ResultAndState},
107    DatabaseCommit,
108};
109use revm_inspectors::transfer::TransferInspector;
110use std::{
111    collections::BTreeMap,
112    io::{Read, Write},
113    ops::Not,
114    path::PathBuf,
115    sync::Arc,
116    time::Duration,
117};
118use storage::{Blockchain, MinedTransaction, DEFAULT_HISTORY_LIMIT};
119use tokio::sync::RwLock as AsyncRwLock;
120
121pub mod cache;
122pub mod fork_db;
123pub mod in_memory_db;
124pub mod inspector;
125pub mod state;
126pub mod storage;
127
128// Gas per transaction not creating a contract.
129pub const MIN_TRANSACTION_GAS: u128 = 21000;
130// Gas per transaction creating a contract.
131pub const MIN_CREATE_GAS: u128 = 53000;
132// Executor
133pub const EXECUTOR: Address = address!("0x6634F723546eCc92277e8a2F93d4f248bf1189ea");
134pub const EXECUTOR_PK: &str = "0x502d47e1421cb9abef497096728e69f07543232b93ef24de4998e18b5fd9ba0f";
135// P256 Batch Delegation Contract: https://odyssey-explorer.ithaca.xyz/address/0x35202a6E6317F3CC3a177EeEE562D3BcDA4a6FcC
136pub const P256_DELEGATION_CONTRACT: Address =
137    address!("0x35202a6e6317f3cc3a177eeee562d3bcda4a6fcc");
138// Runtime code of the P256 delegation contract
139pub const P256_DELEGATION_RUNTIME_CODE: &[u8] = &hex!("60806040526004361015610018575b361561001657005b005b5f3560e01c806309c5eabe146100c75780630cb6aaf1146100c257806330f6a8e5146100bd5780635fce1927146100b8578063641cdfe2146100b357806376ba882d146100ae5780638d80ff0a146100a9578063972ce4bc146100a4578063a78fc2441461009f578063a82e44e01461009a5763b34893910361000e576108e1565b6108b5565b610786565b610646565b6105ba565b610529565b6103f8565b6103a2565b61034c565b6102c0565b61020b565b634e487b7160e01b5f52604160045260245ffd5b6040810190811067ffffffffffffffff8211176100fc57604052565b6100cc565b6080810190811067ffffffffffffffff8211176100fc57604052565b60a0810190811067ffffffffffffffff8211176100fc57604052565b90601f8019910116810190811067ffffffffffffffff8211176100fc57604052565b6040519061016a608083610139565b565b67ffffffffffffffff81116100fc57601f01601f191660200190565b9291926101948261016c565b916101a26040519384610139565b8294818452818301116101be578281602093845f960137010152565b5f80fd5b9080601f830112156101be578160206101dd93359101610188565b90565b60206003198201126101be576004359067ffffffffffffffff82116101be576101dd916004016101c2565b346101be57610219366101e0565b3033036102295761001690610ae6565b636f6a1b8760e11b5f5260045ffd5b634e487b7160e01b5f52603260045260245ffd5b5f54811015610284575f8080526005919091027f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5630191565b610238565b8054821015610284575f52600560205f20910201905f90565b906040516102af816100e0565b602060018294805484520154910152565b346101be5760203660031901126101be576004355f548110156101be576102e69061024c565b5060ff815416600182015491610306600360ff60028401541692016102a2565b926040519215158352602083015260028110156103385760a09260209160408401528051606084015201516080820152f35b634e487b7160e01b5f52602160045260245ffd5b346101be575f3660031901126101be576020600254604051908152f35b6004359063ffffffff821682036101be57565b6064359063ffffffff821682036101be57565b6084359063ffffffff821682036101be57565b346101be5760203660031901126101be576103bb610369565b303303610229576103cb9061024c565b50805460ff19169055005b60609060231901126101be57602490565b60609060831901126101be57608490565b346101be5760803660031901126101be57610411610369565b60205f61041d366103d6565b60015461043161042c82610a0b565b600155565b60405184810191825260e086901b6001600160e01b031916602083015261046581602484015b03601f198101835282610139565b51902060ff61047660408401610a19565b161583146104fe576104b2601b925b85813591013590604051948594859094939260ff6060936080840197845216602083015260408201520152565b838052039060015afa156104f9575f51306001600160a01b03909116036104ea576104df6100169161024c565b50805460ff19169055565b638baa579f60e01b5f5260045ffd5b610a27565b6104b2601c92610485565b60409060031901126101be57600490565b6044359060028210156101be57565b346101be5760803660031901126101be5761054336610509565b61054b61051a565b606435903033036102295761059192610580610587926040519461056e86610101565b60018652602086015260408501610a32565b36906105f3565b6060820152610a3e565b5f545f1981019081116105b55760405163ffffffff919091168152602090f35b0390f35b6109f7565b6100166105c6366101e0565b610ae6565b60409060231901126101be57604051906105e4826100e0565b60243582526044356020830152565b91908260409103126101be5760405161060b816100e0565b6020808294803584520135910152565b6084359081151582036101be57565b60a4359081151582036101be57565b359081151582036101be57565b346101be5760a03660031901126101be5760043567ffffffffffffffff81116101be576106779036906004016101c2565b610680366105cb565b61068861037c565b61069061061b565b906002546106a56106a082610a0b565b600255565b6040516106bb8161045788602083019586610b6a565b51902091610747575b6106d06106d69161024c565b50610b7b565b906106e86106e48351151590565b1590565b610738576020820151801515908161072e575b5061071f576107129260606106e493015191610ce3565b6104ea5761001690610ae6565b632572e3a960e01b5f5260045ffd5b905042115f6106fb565b637dd286d760e11b5f5260045ffd5b905f61077361045761076760209460405192839187830160209181520190565b60405191828092610b58565b039060025afa156104f9575f51906106c4565b346101be5760e03660031901126101be576107a036610509565b6107a861051a565b6064359060205f6107b8366103e7565b6001546107c761042c82610a0b565b60408051808601928352883560208401528589013591830191909152606082018790526107f78160808401610457565b51902060ff61080860408401610a19565b161583146108aa5760408051918252601b602083015282359082015290830135606082015280608081015b838052039060015afa156104f9575f51306001600160a01b03909116036104ea5761087a926105806105879261086761015b565b6001815294602086015260408501610a32565b6105b161089361088a5f54610ad8565b63ffffffff1690565b60405163ffffffff90911681529081906020820190565b610833601c92610485565b346101be575f3660031901126101be576020600154604051908152f35b359061ffff821682036101be57565b346101be5760c03660031901126101be5760043567ffffffffffffffff81116101be576109129036906004016101c2565b61091b366105cb565b906064359167ffffffffffffffff83116101be5760a060031984360301126101be576040516109498161011d565b836004013567ffffffffffffffff81116101be5761096d90600436918701016101c2565b8152602484013567ffffffffffffffff81116101be57840193366023860112156101be5760846109db916109ae610016973690602460048201359101610188565b60208501526109bf604482016108d2565b60408501526109d0606482016108d2565b606085015201610639565b60808201526109e861038f565b916109f161062a565b93610bc3565b634e487b7160e01b5f52601160045260245ffd5b5f1981146105b55760010190565b3560ff811681036101be5790565b6040513d5f823e3d90fd5b60028210156103385752565b5f54680100000000000000008110156100fc57806001610a6192015f555f610289565b610ac557610a7e82511515829060ff801983541691151516179055565b6020820151600182015560028101604083015160028110156103385761016a9360039260609260ff8019835416911617905501519101906020600191805184550151910155565b634e487b7160e01b5f525f60045260245ffd5b5f198101919082116105b557565b80519060205b828110610af857505050565b808201805160f81c600182015160601c91601581015160358201519384915f9493845f14610b4257505050506001146101be575b15610b3a5701605501610aec565b3d5f803e3d5ffd5b5f95508594506055019130811502175af1610b2c565b805191908290602001825e015f815290565b6020906101dd939281520190610b58565b90604051610b8881610101565b6060610bbe6003839560ff8154161515855260018101546020860152610bb860ff60028301541660408701610a32565b016102a2565b910152565b93909192600254610bd66106a082610a0b565b604051610bec8161045789602083019586610b6a565b51902091610c50575b6106d0610c019161024c565b91610c0f6106e48451151590565b6107385760208301518015159081610c46575b5061071f57610c399360606106e494015192610e0d565b6104ea5761016a90610ae6565b905042115f610c22565b905f610c7061045761076760209460405192839187830160209181520190565b039060025afa156104f9575f5190610bf5565b3d15610cad573d90610c948261016c565b91610ca26040519384610139565b82523d5f602084013e565b606090565b8051601f101561028457603f0190565b8051602010156102845760400190565b908151811015610284570160200190565b5f9291839260208251920151906020815191015191604051936020850195865260408501526060840152608083015260a082015260a08152610d2660c082610139565b519060145afa610d34610c83565b81610d74575b81610d43575090565b600160f81b91506001600160f81b031990610d6f90610d6190610cb2565b516001600160f81b03191690565b161490565b80516020149150610d3a565b60405190610d8f604083610139565b6015825274113a3cb832911d113bb2b130baba34371733b2ba1160591b6020830152565b9061016a6001610de3936040519485916c1131b430b63632b733b2911d1160991b6020840152602d830190610b58565b601160f91b815203601e19810185520183610139565b610e069060209392610b58565b9081520190565b92919281516025815110908115610f0a575b50610ef957610e2c610d80565b90610e596106e460208501938451610e53610e4c606089015161ffff1690565b61ffff1690565b91610f9b565b610f01576106e4610e8d610e88610457610e83610ea1956040519283916020830160209181520190565b611012565b610db3565b8351610e53610e4c604088015161ffff1690565b610ef9575f610eb96020925160405191828092610b58565b039060025afa156104f9575f610ee360209261076783519151610457604051938492888401610df9565b039060025afa156104f9576101dd915f51610ce3565b505050505f90565b50505050505f90565b610f2b9150610f1e610d616106e492610cc2565b6080850151151590610f31565b5f610e1f565b906001600160f81b0319600160f81b831601610f955780610f85575b610f8057601f60fb1b600160fb1b821601610f69575b50600190565b600160fc1b90811614610f7c575f610f63565b5f90565b505f90565b50600160fa1b8181161415610f4d565b50505f90565b80519282515f5b858110610fb457505050505050600190565b8083018084116105b5578281101561100757610fe56001600160f81b0319610fdc8488610cd2565b51169187610cd2565b516001600160f81b03191603610ffd57600101610fa2565b5050505050505f90565b505050505050505f90565b80516060929181611021575050565b9092506003600284010460021b604051937f4142434445464748494a4b4c4d4e4f505152535455565758595a616263646566601f527f6768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5f603f52602085019282860191602083019460208284010190600460038351955f85525b0191603f8351818160121c16515f538181600c1c1651600153818160061c165160025316516003535f5181520190878210156110db5760049060039061109a565b5095505f93600393604092520160405206600204809303613d3d60f01b81525203825256fea26469706673582212200ba93b78f286a25ece47e9403c47be9862f9b8b70ba1a95098667b90c47308b064736f6c634300081a0033");
140// Experimental ERC20
141pub const EXP_ERC20_CONTRACT: Address = address!("0x238c8CD93ee9F8c7Edf395548eF60c0d2e46665E");
142// Runtime code of the experimental ERC20 contract
143pub const EXP_ERC20_RUNTIME_CODE: &[u8] = &hex!("60806040526004361015610010575b005b5f3560e01c806306fdde03146106f7578063095ea7b31461068c57806318160ddd1461066757806323b872dd146105a15780632bb7c5951461050e578063313ce567146104f35780633644e5151461045557806340c10f191461043057806370a08231146103fe5780637ecebe00146103cc57806395d89b4114610366578063a9059cbb146102ea578063ad0c8fdd146102ad578063d505accf146100fb5763dd62ed3e0361000e57346100f75760403660031901126100f7576100d261075c565b6100da610772565b602052637f5e9f20600c525f5260206034600c2054604051908152f35b5f80fd5b346100f75760e03660031901126100f75761011461075c565b61011c610772565b6084359160643560443560ff851685036100f757610138610788565b60208101906e04578706572696d656e74455243323608c1b8252519020908242116102a0576040519360018060a01b03169460018060a01b03169565383775081901600e52855f5260c06020600c20958654957f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8252602082019586528660408301967fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc688528b6060850198468a528c608087019330855260a08820602e527f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9885252528688525260a082015220604e526042602c205f5260ff1660205260a43560405260c43560605260208060805f60015afa93853d5103610293577f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92594602094019055856303faf4f960a51b176040526034602c2055a3005b63ddafbaef5f526004601cfd5b631a15a3cc5f526004601cfd5b5f3660031901126100f7576103e834023481046103e814341517156102d65761000e90336107ac565b634e487b7160e01b5f52601160045260245ffd5b346100f75760403660031901126100f75761030361075c565b602435906387a211a2600c52335f526020600c2080548084116103595783900390555f526020600c20818154019055602052600c5160601c335f51602061080d5f395f51905f52602080a3602060405160018152f35b63f4d678b85f526004601cfd5b346100f7575f3660031901126100f757604051604081019080821067ffffffffffffffff8311176103b8576103b491604052600381526204558560ec1b602082015260405191829182610732565b0390f35b634e487b7160e01b5f52604160045260245ffd5b346100f75760203660031901126100f7576103e561075c565b6338377508600c525f52602080600c2054604051908152f35b346100f75760203660031901126100f75761041761075c565b6387a211a2600c525f52602080600c2054604051908152f35b346100f75760403660031901126100f75761000e61044c61075c565b602435906107ac565b346100f7575f3660031901126100f757602060a0610471610788565b828101906e04578706572696d656e74455243323608c1b8252519020604051907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8252838201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6604082015246606082015230608082015220604051908152f35b346100f7575f3660031901126100f757602060405160128152f35b346100f75760203660031901126100f7576004356387a211a2600c52335f526020600c2090815490818111610359575f80806103e88487839688039055806805345cdf77eb68f44c54036805345cdf77eb68f44c5580835282335f51602061080d5f395f51905f52602083a304818115610598575b3390f11561058d57005b6040513d5f823e3d90fd5b506108fc610583565b346100f75760603660031901126100f7576105ba61075c565b6105c2610772565b604435908260601b33602052637f5e9f208117600c526034600c20908154918219610643575b506387a211a2915017600c526020600c2080548084116103595783900390555f526020600c20818154019055602052600c5160601c9060018060a01b03165f51602061080d5f395f51905f52602080a3602060405160018152f35b82851161065a57846387a211a293039055856105e8565b6313be252b5f526004601cfd5b346100f7575f3660031901126100f75760206805345cdf77eb68f44c54604051908152f35b346100f75760403660031901126100f7576106a561075c565b60243590602052637f5e9f20600c52335f52806034600c20555f52602c5160601c337f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560205fa3602060405160018152f35b346100f7575f3660031901126100f7576103b4610712610788565b6e04578706572696d656e74455243323608c1b6020820152604051918291825b602060409281835280519182918282860152018484015e5f828201840152601f01601f1916010190565b600435906001600160a01b03821682036100f757565b602435906001600160a01b03821682036100f757565b604051906040820182811067ffffffffffffffff8211176103b857604052600f8252565b6805345cdf77eb68f44c548281019081106107ff576805345cdf77eb68f44c556387a211a2600c525f526020600c20818154019055602052600c5160601c5f5f51602061080d5f395f51905f52602080a3565b63e5cfe9575f526004601cfdfeddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa2646970667358221220fbe302881d9891005ba1448ba48547cc1cb17dea1a5c4011dfcb035de325bb1d64736f6c634300081b0033");
144
145pub type State = foundry_evm::utils::StateChangeset;
146
147/// A block request, which includes the Pool Transactions if it's Pending
148#[derive(Debug)]
149pub enum BlockRequest {
150    Pending(Vec<Arc<PoolTransaction>>),
151    Number(u64),
152}
153
154impl BlockRequest {
155    pub fn block_number(&self) -> BlockNumber {
156        match *self {
157            Self::Pending(_) => BlockNumber::Pending,
158            Self::Number(n) => BlockNumber::Number(n),
159        }
160    }
161}
162
163/// Gives access to the [revm::Database]
164#[derive(Clone)]
165pub struct Backend {
166    /// Access to [`revm::Database`] abstraction.
167    ///
168    /// This will be used in combination with [`revm::Evm`] and is responsible for feeding data to
169    /// the evm during its execution.
170    ///
171    /// At time of writing, there are two different types of `Db`:
172    ///   - [`MemDb`](crate::mem::in_memory_db::MemDb): everything is stored in memory
173    ///   - [`ForkDb`](crate::mem::fork_db::ForkedDatabase): forks off a remote client, missing
174    ///     data is retrieved via RPC-calls
175    ///
176    /// In order to commit changes to the [`revm::Database`], the [`revm::Evm`] requires mutable
177    /// access, which requires a write-lock from this `db`. In forking mode, the time during
178    /// which the write-lock is active depends on whether the `ForkDb` can provide all requested
179    /// data from memory or whether it has to retrieve it via RPC calls first. This means that it
180    /// potentially blocks for some time, even taking into account the rate limits of RPC
181    /// endpoints. Therefore the `Db` is guarded by a `tokio::sync::RwLock` here so calls that
182    /// need to read from it, while it's currently written to, don't block. E.g. a new block is
183    /// currently mined and a new [`Self::set_storage_at()`] request is being executed.
184    db: Arc<AsyncRwLock<Box<dyn Db>>>,
185    /// stores all block related data in memory.
186    blockchain: Blockchain,
187    /// Historic states of previous blocks.
188    states: Arc<RwLock<InMemoryBlockStates>>,
189    /// Env data of the chain
190    env: Arc<RwLock<EnvWithHandlerCfg>>,
191    /// This is set if this is currently forked off another client.
192    fork: Arc<RwLock<Option<ClientFork>>>,
193    /// Provides time related info, like timestamp.
194    time: TimeManager,
195    /// Contains state of custom overrides.
196    cheats: CheatsManager,
197    /// Contains fee data.
198    fees: FeeManager,
199    /// Initialised genesis.
200    genesis: GenesisConfig,
201    /// Listeners for new blocks that get notified when a new block was imported.
202    new_block_listeners: Arc<Mutex<Vec<UnboundedSender<NewBlockNotification>>>>,
203    /// Keeps track of active state snapshots at a specific block.
204    active_state_snapshots: Arc<Mutex<HashMap<U256, (u64, B256)>>>,
205    enable_steps_tracing: bool,
206    print_logs: bool,
207    print_traces: bool,
208    odyssey: bool,
209    /// How to keep history state
210    prune_state_history_config: PruneStateHistoryConfig,
211    /// max number of blocks with transactions in memory
212    transaction_block_keeper: Option<usize>,
213    node_config: Arc<AsyncRwLock<NodeConfig>>,
214    /// Slots in an epoch
215    slots_in_an_epoch: u64,
216    /// Precompiles to inject to the EVM.
217    precompile_factory: Option<Arc<dyn PrecompileFactory>>,
218    /// Prevent race conditions during mining
219    mining: Arc<tokio::sync::Mutex<()>>,
220    // === wallet === //
221    capabilities: Arc<RwLock<WalletCapabilities>>,
222    executor_wallet: Arc<RwLock<Option<EthereumWallet>>>,
223}
224
225impl Backend {
226    /// Initialises the balance of the given accounts
227    #[expect(clippy::too_many_arguments)]
228    pub async fn with_genesis(
229        db: Arc<AsyncRwLock<Box<dyn Db>>>,
230        env: Arc<RwLock<EnvWithHandlerCfg>>,
231        genesis: GenesisConfig,
232        fees: FeeManager,
233        fork: Arc<RwLock<Option<ClientFork>>>,
234        enable_steps_tracing: bool,
235        print_logs: bool,
236        print_traces: bool,
237        odyssey: bool,
238        prune_state_history_config: PruneStateHistoryConfig,
239        max_persisted_states: Option<usize>,
240        transaction_block_keeper: Option<usize>,
241        automine_block_time: Option<Duration>,
242        cache_path: Option<PathBuf>,
243        node_config: Arc<AsyncRwLock<NodeConfig>>,
244    ) -> Result<Self> {
245        // if this is a fork then adjust the blockchain storage
246        let blockchain = if let Some(fork) = fork.read().as_ref() {
247            trace!(target: "backend", "using forked blockchain at {}", fork.block_number());
248            Blockchain::forked(fork.block_number(), fork.block_hash(), fork.total_difficulty())
249        } else {
250            let env = env.read();
251            Blockchain::new(
252                &env,
253                env.handler_cfg.spec_id,
254                fees.is_eip1559().then(|| fees.base_fee()),
255                genesis.timestamp,
256                genesis.number,
257            )
258        };
259
260        let start_timestamp = if let Some(fork) = fork.read().as_ref() {
261            fork.timestamp()
262        } else {
263            genesis.timestamp
264        };
265
266        let mut states = if prune_state_history_config.is_config_enabled() {
267            // if prune state history is enabled, configure the state cache only for memory
268            prune_state_history_config
269                .max_memory_history
270                .map(|limit| InMemoryBlockStates::new(limit, 0))
271                .unwrap_or_default()
272                .memory_only()
273        } else if max_persisted_states.is_some() {
274            max_persisted_states
275                .map(|limit| InMemoryBlockStates::new(DEFAULT_HISTORY_LIMIT, limit))
276                .unwrap_or_default()
277        } else {
278            Default::default()
279        };
280
281        if let Some(cache_path) = cache_path {
282            states = states.disk_path(cache_path);
283        }
284
285        let (slots_in_an_epoch, precompile_factory) = {
286            let cfg = node_config.read().await;
287            (cfg.slots_in_an_epoch, cfg.precompile_factory.clone())
288        };
289
290        let (capabilities, executor_wallet) = if odyssey {
291            // Insert account that sponsors the delegated txs. And deploy P256 delegation contract.
292            let mut db = db.write().await;
293
294            let _ = db.set_code(
295                P256_DELEGATION_CONTRACT,
296                Bytes::from_static(P256_DELEGATION_RUNTIME_CODE),
297            );
298
299            // Insert EXP ERC20 contract
300            let _ = db.set_code(EXP_ERC20_CONTRACT, Bytes::from_static(EXP_ERC20_RUNTIME_CODE));
301
302            let init_balance = Unit::ETHER.wei().saturating_mul(U256::from(10_000)); // 10K ETH
303
304            // Add ETH
305            let _ = db.set_balance(EXP_ERC20_CONTRACT, init_balance);
306            let _ = db.set_balance(EXECUTOR, init_balance);
307
308            let mut capabilities = WalletCapabilities::default();
309
310            let chain_id = env.read().cfg.chain_id;
311            capabilities.insert(
312                chain_id,
313                Capabilities {
314                    delegation: DelegationCapability { addresses: vec![P256_DELEGATION_CONTRACT] },
315                },
316            );
317
318            let signer: PrivateKeySigner = EXECUTOR_PK.parse().unwrap();
319
320            let executor_wallet = EthereumWallet::new(signer);
321
322            (capabilities, Some(executor_wallet))
323        } else {
324            (WalletCapabilities::default(), None)
325        };
326
327        let backend = Self {
328            db,
329            blockchain,
330            states: Arc::new(RwLock::new(states)),
331            env,
332            fork,
333            time: TimeManager::new(start_timestamp),
334            cheats: Default::default(),
335            new_block_listeners: Default::default(),
336            fees,
337            genesis,
338            active_state_snapshots: Arc::new(Mutex::new(Default::default())),
339            enable_steps_tracing,
340            print_logs,
341            print_traces,
342            odyssey,
343            prune_state_history_config,
344            transaction_block_keeper,
345            node_config,
346            slots_in_an_epoch,
347            precompile_factory,
348            mining: Arc::new(tokio::sync::Mutex::new(())),
349            capabilities: Arc::new(RwLock::new(capabilities)),
350            executor_wallet: Arc::new(RwLock::new(executor_wallet)),
351        };
352
353        if let Some(interval_block_time) = automine_block_time {
354            backend.update_interval_mine_block_time(interval_block_time);
355        }
356
357        // Note: this can only fail in forking mode, in which case we can't recover
358        backend.apply_genesis().await.wrap_err("failed to create genesis")?;
359        Ok(backend)
360    }
361
362    /// Writes the CREATE2 deployer code directly to the database at the address provided.
363    pub async fn set_create2_deployer(&self, address: Address) -> DatabaseResult<()> {
364        self.set_code(address, Bytes::from_static(DEFAULT_CREATE2_DEPLOYER_RUNTIME_CODE)).await?;
365
366        Ok(())
367    }
368
369    /// Get the capabilities of the wallet.
370    ///
371    /// Currently the only capability is [`DelegationCapability`].
372    ///
373    /// [`DelegationCapability`]: anvil_core::eth::wallet::DelegationCapability
374    pub(crate) fn get_capabilities(&self) -> WalletCapabilities {
375        self.capabilities.read().clone()
376    }
377
378    /// Updates memory limits that should be more strict when auto-mine is enabled
379    pub(crate) fn update_interval_mine_block_time(&self, block_time: Duration) {
380        self.states.write().update_interval_mine_block_time(block_time)
381    }
382
383    pub(crate) fn executor_wallet(&self) -> Option<EthereumWallet> {
384        self.executor_wallet.read().clone()
385    }
386
387    /// Adds an address to the [`DelegationCapability`] of the wallet.
388    pub(crate) fn add_capability(&self, address: Address) {
389        let chain_id = self.env.read().cfg.chain_id;
390        let mut capabilities = self.capabilities.write();
391        let mut capability = capabilities.get(chain_id).cloned().unwrap_or_default();
392        capability.delegation.addresses.push(address);
393        capabilities.insert(chain_id, capability);
394    }
395
396    pub(crate) fn set_executor(&self, executor_pk: String) -> Result<Address, BlockchainError> {
397        let signer: PrivateKeySigner =
398            executor_pk.parse().map_err(|_| RpcError::invalid_params("Invalid private key"))?;
399
400        let executor = signer.address();
401        let wallet = EthereumWallet::new(signer);
402
403        *self.executor_wallet.write() = Some(wallet);
404
405        Ok(executor)
406    }
407
408    /// Applies the configured genesis settings
409    ///
410    /// This will fund, create the genesis accounts
411    async fn apply_genesis(&self) -> Result<(), DatabaseError> {
412        trace!(target: "backend", "setting genesis balances");
413
414        if self.fork.read().is_some() {
415            // fetch all account first
416            let mut genesis_accounts_futures = Vec::with_capacity(self.genesis.accounts.len());
417            for address in self.genesis.accounts.iter().copied() {
418                let db = Arc::clone(&self.db);
419
420                // The forking Database backend can handle concurrent requests, we can fetch all dev
421                // accounts concurrently by spawning the job to a new task
422                genesis_accounts_futures.push(tokio::task::spawn(async move {
423                    let db = db.read().await;
424                    let info = db.basic_ref(address)?.unwrap_or_default();
425                    Ok::<_, DatabaseError>((address, info))
426                }));
427            }
428
429            let genesis_accounts = futures::future::join_all(genesis_accounts_futures).await;
430
431            let mut db = self.db.write().await;
432
433            for res in genesis_accounts {
434                let (address, mut info) = res.unwrap()?;
435                info.balance = self.genesis.balance;
436                db.insert_account(address, info.clone());
437            }
438        } else {
439            let mut db = self.db.write().await;
440            for (account, info) in self.genesis.account_infos() {
441                db.insert_account(account, info);
442            }
443
444            // insert the new genesis hash to the database so it's available for the next block in
445            // the evm
446            db.insert_block_hash(U256::from(self.best_number()), self.best_hash());
447        }
448
449        let db = self.db.write().await;
450        // apply the genesis.json alloc
451        self.genesis.apply_genesis_json_alloc(db)?;
452        Ok(())
453    }
454
455    /// Sets the account to impersonate
456    ///
457    /// Returns `true` if the account is already impersonated
458    pub fn impersonate(&self, addr: Address) -> bool {
459        if self.cheats.impersonated_accounts().contains(&addr) {
460            return true
461        }
462        // Ensure EIP-3607 is disabled
463        let mut env = self.env.write();
464        env.cfg.disable_eip3607 = true;
465        self.cheats.impersonate(addr)
466    }
467
468    /// Removes the account that from the impersonated set
469    ///
470    /// If the impersonated `addr` is a contract then we also reset the code here
471    pub fn stop_impersonating(&self, addr: Address) {
472        self.cheats.stop_impersonating(&addr);
473    }
474
475    /// If set to true will make every account impersonated
476    pub fn auto_impersonate_account(&self, enabled: bool) {
477        self.cheats.set_auto_impersonate_account(enabled);
478    }
479
480    /// Returns the configured fork, if any
481    pub fn get_fork(&self) -> Option<ClientFork> {
482        self.fork.read().clone()
483    }
484
485    /// Returns the database
486    pub fn get_db(&self) -> &Arc<AsyncRwLock<Box<dyn Db>>> {
487        &self.db
488    }
489
490    /// Returns the `AccountInfo` from the database
491    pub async fn get_account(&self, address: Address) -> DatabaseResult<AccountInfo> {
492        Ok(self.db.read().await.basic_ref(address)?.unwrap_or_default())
493    }
494
495    /// Whether we're forked off some remote client
496    pub fn is_fork(&self) -> bool {
497        self.fork.read().is_some()
498    }
499
500    pub fn precompiles(&self) -> Vec<Address> {
501        get_precompiles_for(self.env.read().handler_cfg.spec_id)
502    }
503
504    /// Resets the fork to a fresh state
505    pub async fn reset_fork(&self, forking: Forking) -> Result<(), BlockchainError> {
506        if !self.is_fork() {
507            if let Some(eth_rpc_url) = forking.clone().json_rpc_url {
508                let mut env = self.env.read().clone();
509
510                let (db, config) = {
511                    let mut node_config = self.node_config.write().await;
512
513                    // we want to force the correct base fee for the next block during
514                    // `setup_fork_db_config`
515                    node_config.base_fee.take();
516
517                    node_config.setup_fork_db_config(eth_rpc_url, &mut env, &self.fees).await?
518                };
519
520                *self.db.write().await = Box::new(db);
521
522                let fork = ClientFork::new(config, Arc::clone(&self.db));
523
524                *self.env.write() = env;
525                *self.fork.write() = Some(fork);
526            } else {
527                return Err(RpcError::invalid_params(
528                    "Forking not enabled and RPC URL not provided to start forking",
529                )
530                .into());
531            }
532        }
533
534        if let Some(fork) = self.get_fork() {
535            let block_number =
536                forking.block_number.map(BlockNumber::from).unwrap_or(BlockNumber::Latest);
537            // reset the fork entirely and reapply the genesis config
538            fork.reset(forking.json_rpc_url.clone(), block_number).await?;
539            let fork_block_number = fork.block_number();
540            let fork_block = fork
541                .block_by_number(fork_block_number)
542                .await?
543                .ok_or(BlockchainError::BlockNotFound)?;
544            // update all settings related to the forked block
545            {
546                if let Some(fork_url) = forking.json_rpc_url {
547                    self.reset_block_number(fork_url, fork_block_number).await?;
548                } else {
549                    // If rpc url is unspecified, then update the fork with the new block number and
550                    // existing rpc url, this updates the cache path
551                    {
552                        let maybe_fork_url = { self.node_config.read().await.eth_rpc_url.clone() };
553                        if let Some(fork_url) = maybe_fork_url {
554                            self.reset_block_number(fork_url, fork_block_number).await?;
555                        }
556                    }
557
558                    let gas_limit = self.node_config.read().await.fork_gas_limit(&fork_block);
559                    let mut env = self.env.write();
560
561                    env.cfg.chain_id = fork.chain_id();
562                    env.block = BlockEnv {
563                        number: U256::from(fork_block_number),
564                        timestamp: U256::from(fork_block.header.timestamp),
565                        gas_limit: U256::from(gas_limit),
566                        difficulty: fork_block.header.difficulty,
567                        prevrandao: Some(fork_block.header.mix_hash.unwrap_or_default()),
568                        // Keep previous `coinbase` and `basefee` value
569                        coinbase: env.block.coinbase,
570                        basefee: env.block.basefee,
571                        ..env.block.clone()
572                    };
573
574                    // this is the base fee of the current block, but we need the base fee of
575                    // the next block
576                    let next_block_base_fee = self.fees.get_next_block_base_fee_per_gas(
577                        fork_block.header.gas_used as u128,
578                        gas_limit,
579                        fork_block.header.base_fee_per_gas.unwrap_or_default(),
580                    );
581
582                    self.fees.set_base_fee(next_block_base_fee);
583                }
584
585                // reset the time to the timestamp of the forked block
586                self.time.reset(fork_block.header.timestamp);
587
588                // also reset the total difficulty
589                self.blockchain.storage.write().total_difficulty = fork.total_difficulty();
590            }
591            // reset storage
592            *self.blockchain.storage.write() = BlockchainStorage::forked(
593                fork.block_number(),
594                fork.block_hash(),
595                fork.total_difficulty(),
596            );
597            self.states.write().clear();
598            self.db.write().await.clear();
599
600            self.apply_genesis().await?;
601
602            Ok(())
603        } else {
604            Err(RpcError::invalid_params("Forking not enabled").into())
605        }
606    }
607
608    async fn reset_block_number(
609        &self,
610        fork_url: String,
611        fork_block_number: u64,
612    ) -> Result<(), BlockchainError> {
613        let mut node_config = self.node_config.write().await;
614        node_config.fork_choice = Some(ForkChoice::Block(fork_block_number as i128));
615
616        let mut env = self.env.read().clone();
617        let (forked_db, client_fork_config) =
618            node_config.setup_fork_db_config(fork_url, &mut env, &self.fees).await?;
619
620        *self.db.write().await = Box::new(forked_db);
621        let fork = ClientFork::new(client_fork_config, Arc::clone(&self.db));
622        *self.fork.write() = Some(fork);
623        *self.env.write() = env;
624
625        Ok(())
626    }
627
628    /// Returns the `TimeManager` responsible for timestamps
629    pub fn time(&self) -> &TimeManager {
630        &self.time
631    }
632
633    /// Returns the `CheatsManager` responsible for executing cheatcodes
634    pub fn cheats(&self) -> &CheatsManager {
635        &self.cheats
636    }
637
638    /// Whether to skip blob validation
639    pub fn skip_blob_validation(&self, impersonator: Option<Address>) -> bool {
640        self.cheats().auto_impersonate_accounts() ||
641            impersonator
642                .is_some_and(|addr| self.cheats().impersonated_accounts().contains(&addr))
643    }
644
645    /// Returns the `FeeManager` that manages fee/pricings
646    pub fn fees(&self) -> &FeeManager {
647        &self.fees
648    }
649
650    /// The env data of the blockchain
651    pub fn env(&self) -> &Arc<RwLock<EnvWithHandlerCfg>> {
652        &self.env
653    }
654
655    /// Returns the current best hash of the chain
656    pub fn best_hash(&self) -> B256 {
657        self.blockchain.storage.read().best_hash
658    }
659
660    /// Returns the current best number of the chain
661    pub fn best_number(&self) -> u64 {
662        self.blockchain.storage.read().best_number.try_into().unwrap_or(u64::MAX)
663    }
664
665    /// Sets the block number
666    pub fn set_block_number(&self, number: U256) {
667        let mut env = self.env.write();
668        env.block.number = number;
669    }
670
671    /// Returns the client coinbase address.
672    pub fn coinbase(&self) -> Address {
673        self.env.read().block.coinbase
674    }
675
676    /// Returns the client coinbase address.
677    pub fn chain_id(&self) -> U256 {
678        U256::from(self.env.read().cfg.chain_id)
679    }
680
681    pub fn set_chain_id(&self, chain_id: u64) {
682        self.env.write().cfg.chain_id = chain_id;
683    }
684
685    /// Returns balance of the given account.
686    pub async fn current_balance(&self, address: Address) -> DatabaseResult<U256> {
687        Ok(self.get_account(address).await?.balance)
688    }
689
690    /// Returns balance of the given account.
691    pub async fn current_nonce(&self, address: Address) -> DatabaseResult<u64> {
692        Ok(self.get_account(address).await?.nonce)
693    }
694
695    /// Sets the coinbase address
696    pub fn set_coinbase(&self, address: Address) {
697        self.env.write().block.coinbase = address;
698    }
699
700    /// Sets the nonce of the given address
701    pub async fn set_nonce(&self, address: Address, nonce: U256) -> DatabaseResult<()> {
702        self.db.write().await.set_nonce(address, nonce.try_into().unwrap_or(u64::MAX))
703    }
704
705    /// Sets the balance of the given address
706    pub async fn set_balance(&self, address: Address, balance: U256) -> DatabaseResult<()> {
707        self.db.write().await.set_balance(address, balance)
708    }
709
710    /// Sets the code of the given address
711    pub async fn set_code(&self, address: Address, code: Bytes) -> DatabaseResult<()> {
712        self.db.write().await.set_code(address, code.0.into())
713    }
714
715    /// Sets the value for the given slot of the given address
716    pub async fn set_storage_at(
717        &self,
718        address: Address,
719        slot: U256,
720        val: B256,
721    ) -> DatabaseResult<()> {
722        self.db.write().await.set_storage_at(address, slot.into(), val)
723    }
724
725    /// Returns the configured specid
726    pub fn spec_id(&self) -> SpecId {
727        self.env.read().handler_cfg.spec_id
728    }
729
730    /// Returns true for post London
731    pub fn is_eip1559(&self) -> bool {
732        (self.spec_id() as u8) >= (SpecId::LONDON as u8)
733    }
734
735    /// Returns true for post Merge
736    pub fn is_eip3675(&self) -> bool {
737        (self.spec_id() as u8) >= (SpecId::MERGE as u8)
738    }
739
740    /// Returns true for post Berlin
741    pub fn is_eip2930(&self) -> bool {
742        (self.spec_id() as u8) >= (SpecId::BERLIN as u8)
743    }
744
745    /// Returns true for post Cancun
746    pub fn is_eip4844(&self) -> bool {
747        (self.spec_id() as u8) >= (SpecId::CANCUN as u8)
748    }
749
750    /// Returns true for post Prague
751    pub fn is_eip7702(&self) -> bool {
752        (self.spec_id() as u8) >= (SpecId::PRAGUE as u8)
753    }
754
755    /// Returns true if op-stack deposits are active
756    pub fn is_optimism(&self) -> bool {
757        self.env.read().handler_cfg.is_optimism
758    }
759
760    /// Returns an error if EIP1559 is not active (pre Berlin)
761    pub fn ensure_eip1559_active(&self) -> Result<(), BlockchainError> {
762        if self.is_eip1559() {
763            return Ok(());
764        }
765        Err(BlockchainError::EIP1559TransactionUnsupportedAtHardfork)
766    }
767
768    /// Returns an error if EIP1559 is not active (pre muirGlacier)
769    pub fn ensure_eip2930_active(&self) -> Result<(), BlockchainError> {
770        if self.is_eip2930() {
771            return Ok(());
772        }
773        Err(BlockchainError::EIP2930TransactionUnsupportedAtHardfork)
774    }
775
776    pub fn ensure_eip4844_active(&self) -> Result<(), BlockchainError> {
777        if self.is_eip4844() {
778            return Ok(());
779        }
780        Err(BlockchainError::EIP4844TransactionUnsupportedAtHardfork)
781    }
782
783    pub fn ensure_eip7702_active(&self) -> Result<(), BlockchainError> {
784        if self.is_eip7702() {
785            return Ok(());
786        }
787        Err(BlockchainError::EIP7702TransactionUnsupportedAtHardfork)
788    }
789
790    /// Returns an error if op-stack deposits are not active
791    pub fn ensure_op_deposits_active(&self) -> Result<(), BlockchainError> {
792        if self.is_optimism() {
793            return Ok(())
794        }
795        Err(BlockchainError::DepositTransactionUnsupported)
796    }
797
798    /// Returns the block gas limit
799    pub fn gas_limit(&self) -> u64 {
800        self.env.read().block.gas_limit.saturating_to()
801    }
802
803    /// Sets the block gas limit
804    pub fn set_gas_limit(&self, gas_limit: u64) {
805        self.env.write().block.gas_limit = U256::from(gas_limit);
806    }
807
808    /// Returns the current base fee
809    pub fn base_fee(&self) -> u64 {
810        self.fees.base_fee()
811    }
812
813    /// Returns whether the minimum suggested priority fee is enforced
814    pub fn is_min_priority_fee_enforced(&self) -> bool {
815        self.fees.is_min_priority_fee_enforced()
816    }
817
818    pub fn excess_blob_gas_and_price(&self) -> Option<BlobExcessGasAndPrice> {
819        self.fees.excess_blob_gas_and_price()
820    }
821
822    /// Sets the current basefee
823    pub fn set_base_fee(&self, basefee: u64) {
824        self.fees.set_base_fee(basefee)
825    }
826
827    /// Sets the gas price
828    pub fn set_gas_price(&self, price: u128) {
829        self.fees.set_gas_price(price)
830    }
831
832    pub fn elasticity(&self) -> f64 {
833        self.fees.elasticity()
834    }
835
836    /// Returns the total difficulty of the chain until this block
837    ///
838    /// Note: this will always be `0` in memory mode
839    /// In forking mode this will always be the total difficulty of the forked block
840    pub fn total_difficulty(&self) -> U256 {
841        self.blockchain.storage.read().total_difficulty
842    }
843
844    /// Creates a new `evm_snapshot` at the current height.
845    ///
846    /// Returns the id of the snapshot created.
847    pub async fn create_state_snapshot(&self) -> U256 {
848        let num = self.best_number();
849        let hash = self.best_hash();
850        let id = self.db.write().await.snapshot_state();
851        trace!(target: "backend", "creating snapshot {} at {}", id, num);
852        self.active_state_snapshots.lock().insert(id, (num, hash));
853        id
854    }
855
856    /// Reverts the state to the state snapshot identified by the given `id`.
857    pub async fn revert_state_snapshot(&self, id: U256) -> Result<bool, BlockchainError> {
858        let block = { self.active_state_snapshots.lock().remove(&id) };
859        if let Some((num, hash)) = block {
860            let best_block_hash = {
861                // revert the storage that's newer than the snapshot
862                let current_height = self.best_number();
863                let mut storage = self.blockchain.storage.write();
864
865                for n in ((num + 1)..=current_height).rev() {
866                    trace!(target: "backend", "reverting block {}", n);
867                    let n = U64::from(n);
868                    if let Some(hash) = storage.hashes.remove(&n) {
869                        if let Some(block) = storage.blocks.remove(&hash) {
870                            for tx in block.transactions {
871                                let _ = storage.transactions.remove(&tx.hash());
872                            }
873                        }
874                    }
875                }
876
877                storage.best_number = U64::from(num);
878                storage.best_hash = hash;
879                hash
880            };
881            let block =
882                self.block_by_hash(best_block_hash).await?.ok_or(BlockchainError::BlockNotFound)?;
883
884            let reset_time = block.header.timestamp;
885            self.time.reset(reset_time);
886
887            let mut env = self.env.write();
888            env.block = BlockEnv {
889                number: U256::from(num),
890                timestamp: U256::from(block.header.timestamp),
891                difficulty: block.header.difficulty,
892                // ensures prevrandao is set
893                prevrandao: Some(block.header.mix_hash.unwrap_or_default()),
894                gas_limit: U256::from(block.header.gas_limit),
895                // Keep previous `coinbase` and `basefee` value
896                coinbase: env.block.coinbase,
897                basefee: env.block.basefee,
898                ..Default::default()
899            };
900        }
901        Ok(self.db.write().await.revert_state(id, RevertStateSnapshotAction::RevertRemove))
902    }
903
904    pub fn list_state_snapshots(&self) -> BTreeMap<U256, (u64, B256)> {
905        self.active_state_snapshots.lock().clone().into_iter().collect()
906    }
907
908    /// Get the current state.
909    pub async fn serialized_state(
910        &self,
911        preserve_historical_states: bool,
912    ) -> Result<SerializableState, BlockchainError> {
913        let at = self.env.read().block.clone();
914        let best_number = self.blockchain.storage.read().best_number;
915        let blocks = self.blockchain.storage.read().serialized_blocks();
916        let transactions = self.blockchain.storage.read().serialized_transactions();
917        let historical_states = if preserve_historical_states {
918            Some(self.states.write().serialized_states())
919        } else {
920            None
921        };
922
923        let state = self.db.read().await.dump_state(
924            at,
925            best_number,
926            blocks,
927            transactions,
928            historical_states,
929        )?;
930        state.ok_or_else(|| {
931            RpcError::invalid_params("Dumping state not supported with the current configuration")
932                .into()
933        })
934    }
935
936    /// Write all chain data to serialized bytes buffer
937    pub async fn dump_state(
938        &self,
939        preserve_historical_states: bool,
940    ) -> Result<Bytes, BlockchainError> {
941        let state = self.serialized_state(preserve_historical_states).await?;
942        let mut encoder = GzEncoder::new(Vec::new(), Compression::default());
943        encoder
944            .write_all(&serde_json::to_vec(&state).unwrap_or_default())
945            .map_err(|_| BlockchainError::DataUnavailable)?;
946        Ok(encoder.finish().unwrap_or_default().into())
947    }
948
949    /// Apply [SerializableState] data to the backend storage.
950    pub async fn load_state(&self, state: SerializableState) -> Result<bool, BlockchainError> {
951        // load the blocks and transactions into the storage
952        self.blockchain.storage.write().load_blocks(state.blocks.clone());
953        self.blockchain.storage.write().load_transactions(state.transactions.clone());
954        // reset the block env
955        if let Some(block) = state.block.clone() {
956            self.env.write().block = block.clone();
957
958            // Set the current best block number.
959            // Defaults to block number for compatibility with existing state files.
960            let fork_num_and_hash = self.get_fork().map(|f| (f.block_number(), f.block_hash()));
961
962            if let Some((number, hash)) = fork_num_and_hash {
963                let best_number = state.best_block_number.unwrap_or(block.number.to::<U64>());
964                trace!(target: "backend", state_block_number=?best_number, fork_block_number=?number);
965                // If the state.block_number is greater than the fork block number, set best number
966                // to the state block number.
967                // Ref: https://github.com/foundry-rs/foundry/issues/9539
968                if best_number.to::<u64>() > number {
969                    self.blockchain.storage.write().best_number = best_number;
970                    let best_hash =
971                        self.blockchain.storage.read().hash(best_number.into()).ok_or_else(
972                            || {
973                                BlockchainError::RpcError(RpcError::internal_error_with(format!(
974                                    "Best hash not found for best number {best_number}",
975                                )))
976                            },
977                        )?;
978                    self.blockchain.storage.write().best_hash = best_hash;
979                } else {
980                    // If loading state file on a fork, set best number to the fork block number.
981                    // Ref: https://github.com/foundry-rs/foundry/pull/9215#issue-2618681838
982                    self.blockchain.storage.write().best_number = U64::from(number);
983                    self.blockchain.storage.write().best_hash = hash;
984                }
985            } else {
986                let best_number = state.best_block_number.unwrap_or(block.number.to::<U64>());
987                self.blockchain.storage.write().best_number = best_number;
988
989                // Set the current best block hash;
990                let best_hash =
991                    self.blockchain.storage.read().hash(best_number.into()).ok_or_else(|| {
992                        BlockchainError::RpcError(RpcError::internal_error_with(format!(
993                            "Best hash not found for best number {best_number}",
994                        )))
995                    })?;
996
997                self.blockchain.storage.write().best_hash = best_hash;
998            }
999        }
1000
1001        if !self.db.write().await.load_state(state.clone())? {
1002            return Err(RpcError::invalid_params(
1003                "Loading state not supported with the current configuration",
1004            )
1005            .into());
1006        }
1007
1008        if let Some(historical_states) = state.historical_states {
1009            self.states.write().load_states(historical_states);
1010        }
1011
1012        Ok(true)
1013    }
1014
1015    /// Deserialize and add all chain data to the backend storage
1016    pub async fn load_state_bytes(&self, buf: Bytes) -> Result<bool, BlockchainError> {
1017        let orig_buf = &buf.0[..];
1018        let mut decoder = GzDecoder::new(orig_buf);
1019        let mut decoded_data = Vec::new();
1020
1021        let state: SerializableState = serde_json::from_slice(if decoder.header().is_some() {
1022            decoder
1023                .read_to_end(decoded_data.as_mut())
1024                .map_err(|_| BlockchainError::FailedToDecodeStateDump)?;
1025            &decoded_data
1026        } else {
1027            &buf.0
1028        })
1029        .map_err(|_| BlockchainError::FailedToDecodeStateDump)?;
1030
1031        self.load_state(state).await
1032    }
1033
1034    /// Returns the environment for the next block
1035    fn next_env(&self) -> EnvWithHandlerCfg {
1036        let mut env = self.env.read().clone();
1037        // increase block number for this block
1038        env.block.number = env.block.number.saturating_add(U256::from(1));
1039        env.block.basefee = U256::from(self.base_fee());
1040        env.block.timestamp = U256::from(self.time.current_call_timestamp());
1041        env
1042    }
1043
1044    /// Creates an EVM instance with optionally injected precompiles.
1045    #[expect(clippy::type_complexity)]
1046    fn new_evm_with_inspector_ref<'i, 'db>(
1047        &self,
1048        db: &'db dyn DatabaseRef<Error = DatabaseError>,
1049        env: EnvWithHandlerCfg,
1050        inspector: &'i mut dyn revm::Inspector<
1051            WrapDatabaseRef<&'db dyn DatabaseRef<Error = DatabaseError>>,
1052        >,
1053    ) -> revm::Evm<
1054        '_,
1055        &'i mut dyn revm::Inspector<WrapDatabaseRef<&'db dyn DatabaseRef<Error = DatabaseError>>>,
1056        WrapDatabaseRef<&'db dyn DatabaseRef<Error = DatabaseError>>,
1057    > {
1058        let mut evm = new_evm_with_inspector_ref(db, env, inspector, self.odyssey);
1059        if let Some(factory) = &self.precompile_factory {
1060            inject_precompiles(&mut evm, factory.precompiles());
1061        }
1062        evm
1063    }
1064
1065    /// executes the transactions without writing to the underlying database
1066    pub async fn inspect_tx(
1067        &self,
1068        tx: Arc<PoolTransaction>,
1069    ) -> Result<
1070        (InstructionResult, Option<Output>, u64, State, Vec<revm::primitives::Log>),
1071        BlockchainError,
1072    > {
1073        let mut env = self.next_env();
1074        env.tx = tx.pending_transaction.to_revm_tx_env();
1075
1076        if env.handler_cfg.is_optimism {
1077            env.tx.optimism.enveloped_tx =
1078                Some(alloy_rlp::encode(&tx.pending_transaction.transaction.transaction).into());
1079        }
1080
1081        let db = self.db.read().await;
1082        let mut inspector = self.build_inspector();
1083        let mut evm = self.new_evm_with_inspector_ref(db.as_dyn(), env, &mut inspector);
1084        let ResultAndState { result, state } = evm.transact()?;
1085        let (exit_reason, gas_used, out, logs) = match result {
1086            ExecutionResult::Success { reason, gas_used, logs, output, .. } => {
1087                (reason.into(), gas_used, Some(output), Some(logs))
1088            }
1089            ExecutionResult::Revert { gas_used, output } => {
1090                (InstructionResult::Revert, gas_used, Some(Output::Call(output)), None)
1091            }
1092            ExecutionResult::Halt { reason, gas_used } => (reason.into(), gas_used, None, None),
1093        };
1094
1095        drop(evm);
1096        inspector.print_logs();
1097
1098        if self.print_traces {
1099            inspector.print_traces();
1100        }
1101
1102        Ok((exit_reason, out, gas_used, state, logs.unwrap_or_default()))
1103    }
1104
1105    /// Creates the pending block
1106    ///
1107    /// This will execute all transaction in the order they come but will not mine the block
1108    pub async fn pending_block(&self, pool_transactions: Vec<Arc<PoolTransaction>>) -> BlockInfo {
1109        self.with_pending_block(pool_transactions, |_, block| block).await
1110    }
1111
1112    /// Creates the pending block
1113    ///
1114    /// This will execute all transaction in the order they come but will not mine the block
1115    pub async fn with_pending_block<F, T>(
1116        &self,
1117        pool_transactions: Vec<Arc<PoolTransaction>>,
1118        f: F,
1119    ) -> T
1120    where
1121        F: FnOnce(Box<dyn MaybeFullDatabase + '_>, BlockInfo) -> T,
1122    {
1123        let db = self.db.read().await;
1124        let env = self.next_env();
1125
1126        let mut cache_db = CacheDB::new(&*db);
1127
1128        let storage = self.blockchain.storage.read();
1129
1130        let cfg_env = CfgEnvWithHandlerCfg::new(env.cfg.clone(), env.handler_cfg);
1131        let executor = TransactionExecutor {
1132            db: &mut cache_db,
1133            validator: self,
1134            pending: pool_transactions.into_iter(),
1135            block_env: env.block.clone(),
1136            cfg_env,
1137            parent_hash: storage.best_hash,
1138            gas_used: 0,
1139            blob_gas_used: 0,
1140            enable_steps_tracing: self.enable_steps_tracing,
1141            print_logs: self.print_logs,
1142            print_traces: self.print_traces,
1143            precompile_factory: self.precompile_factory.clone(),
1144            odyssey: self.odyssey,
1145        };
1146
1147        // create a new pending block
1148        let executed = executor.execute();
1149        f(Box::new(cache_db), executed.block)
1150    }
1151
1152    /// Mines a new block and stores it.
1153    ///
1154    /// this will execute all transaction in the order they come in and return all the markers they
1155    /// provide.
1156    pub async fn mine_block(
1157        &self,
1158        pool_transactions: Vec<Arc<PoolTransaction>>,
1159    ) -> MinedBlockOutcome {
1160        self.do_mine_block(pool_transactions).await
1161    }
1162
1163    async fn do_mine_block(
1164        &self,
1165        pool_transactions: Vec<Arc<PoolTransaction>>,
1166    ) -> MinedBlockOutcome {
1167        let _mining_guard = self.mining.lock().await;
1168        trace!(target: "backend", "creating new block with {} transactions", pool_transactions.len());
1169
1170        let (outcome, header, block_hash) = {
1171            let current_base_fee = self.base_fee();
1172            let current_excess_blob_gas_and_price = self.excess_blob_gas_and_price();
1173
1174            let mut env = self.env.read().clone();
1175
1176            if env.block.basefee.is_zero() {
1177                // this is an edge case because the evm fails if `tx.effective_gas_price < base_fee`
1178                // 0 is only possible if it's manually set
1179                env.cfg.disable_base_fee = true;
1180            }
1181
1182            let block_number =
1183                self.blockchain.storage.read().best_number.saturating_add(U64::from(1));
1184
1185            // increase block number for this block
1186            if is_arbitrum(env.cfg.chain_id) {
1187                // Temporary set `env.block.number` to `block_number` for Arbitrum chains.
1188                env.block.number = block_number.to();
1189            } else {
1190                env.block.number = env.block.number.saturating_add(U256::from(1));
1191            }
1192
1193            env.block.basefee = U256::from(current_base_fee);
1194            env.block.blob_excess_gas_and_price = current_excess_blob_gas_and_price;
1195
1196            // pick a random value for prevrandao
1197            env.block.prevrandao = Some(B256::random());
1198
1199            let best_hash = self.blockchain.storage.read().best_hash;
1200
1201            if self.prune_state_history_config.is_state_history_supported() {
1202                let db = self.db.read().await.current_state();
1203                // store current state before executing all transactions
1204                self.states.write().insert(best_hash, db);
1205            }
1206
1207            let (executed_tx, block_hash) = {
1208                let mut db = self.db.write().await;
1209
1210                // finally set the next block timestamp, this is done just before execution, because
1211                // there can be concurrent requests that can delay acquiring the db lock and we want
1212                // to ensure the timestamp is as close as possible to the actual execution.
1213                env.block.timestamp = U256::from(self.time.next_timestamp());
1214
1215                let executor = TransactionExecutor {
1216                    db: &mut **db,
1217                    validator: self,
1218                    pending: pool_transactions.into_iter(),
1219                    block_env: env.block.clone(),
1220                    cfg_env: CfgEnvWithHandlerCfg::new(env.cfg.clone(), env.handler_cfg),
1221                    parent_hash: best_hash,
1222                    gas_used: 0,
1223                    blob_gas_used: 0,
1224                    enable_steps_tracing: self.enable_steps_tracing,
1225                    print_logs: self.print_logs,
1226                    print_traces: self.print_traces,
1227                    odyssey: self.odyssey,
1228                    precompile_factory: self.precompile_factory.clone(),
1229                };
1230                let executed_tx = executor.execute();
1231
1232                // we also need to update the new blockhash in the db itself
1233                let block_hash = executed_tx.block.block.header.hash_slow();
1234                db.insert_block_hash(U256::from(executed_tx.block.block.header.number), block_hash);
1235
1236                (executed_tx, block_hash)
1237            };
1238
1239            // create the new block with the current timestamp
1240            let ExecutedTransactions { block, included, invalid } = executed_tx;
1241            let BlockInfo { block, transactions, receipts } = block;
1242
1243            let header = block.header.clone();
1244
1245            trace!(
1246                target: "backend",
1247                "Mined block {} with {} tx {:?}",
1248                block_number,
1249                transactions.len(),
1250                transactions.iter().map(|tx| tx.transaction_hash).collect::<Vec<_>>()
1251            );
1252            let mut storage = self.blockchain.storage.write();
1253            // update block metadata
1254            storage.best_number = block_number;
1255            storage.best_hash = block_hash;
1256            // Difficulty is removed and not used after Paris (aka TheMerge). Value is replaced with
1257            // prevrandao. https://github.com/bluealloy/revm/blob/1839b3fce8eaeebb85025576f2519b80615aca1e/crates/interpreter/src/instructions/host_env.rs#L27
1258            if !self.is_eip3675() {
1259                storage.total_difficulty =
1260                    storage.total_difficulty.saturating_add(header.difficulty);
1261            }
1262
1263            storage.blocks.insert(block_hash, block);
1264            storage.hashes.insert(block_number, block_hash);
1265
1266            node_info!("");
1267            // insert all transactions
1268            for (info, receipt) in transactions.into_iter().zip(receipts) {
1269                // log some tx info
1270                node_info!("    Transaction: {:?}", info.transaction_hash);
1271                if let Some(contract) = &info.contract_address {
1272                    node_info!("    Contract created: {contract}");
1273                }
1274                node_info!("    Gas used: {}", receipt.cumulative_gas_used());
1275                if !info.exit.is_ok() {
1276                    let r = RevertDecoder::new().decode(
1277                        info.out.as_ref().map(|b| &b[..]).unwrap_or_default(),
1278                        Some(info.exit),
1279                    );
1280                    node_info!("    Error: reverted with: {r}");
1281                }
1282                node_info!("");
1283
1284                let mined_tx = MinedTransaction {
1285                    info,
1286                    receipt,
1287                    block_hash,
1288                    block_number: block_number.to::<u64>(),
1289                };
1290                storage.transactions.insert(mined_tx.info.transaction_hash, mined_tx);
1291            }
1292
1293            // remove old transactions that exceed the transaction block keeper
1294            if let Some(transaction_block_keeper) = self.transaction_block_keeper {
1295                if storage.blocks.len() > transaction_block_keeper {
1296                    let to_clear = block_number
1297                        .to::<u64>()
1298                        .saturating_sub(transaction_block_keeper.try_into().unwrap_or(u64::MAX));
1299                    storage.remove_block_transactions_by_number(to_clear)
1300                }
1301            }
1302
1303            // we intentionally set the difficulty to `0` for newer blocks
1304            env.block.difficulty = U256::from(0);
1305
1306            // update env with new values
1307            *self.env.write() = env;
1308
1309            let timestamp = utc_from_secs(header.timestamp);
1310
1311            node_info!("    Block Number: {}", block_number);
1312            node_info!("    Block Hash: {:?}", block_hash);
1313            if timestamp.year() > 9999 {
1314                // rf2822 panics with more than 4 digits
1315                node_info!("    Block Time: {:?}\n", timestamp.to_rfc3339());
1316            } else {
1317                node_info!("    Block Time: {:?}\n", timestamp.to_rfc2822());
1318            }
1319
1320            let outcome = MinedBlockOutcome { block_number, included, invalid };
1321
1322            (outcome, header, block_hash)
1323        };
1324        let next_block_base_fee = self.fees.get_next_block_base_fee_per_gas(
1325            header.gas_used as u128,
1326            header.gas_limit as u128,
1327            header.base_fee_per_gas.unwrap_or_default(),
1328        );
1329        let next_block_excess_blob_gas = self.fees.get_next_block_blob_excess_gas(
1330            header.excess_blob_gas.map(|g| g as u128).unwrap_or_default(),
1331            header.blob_gas_used.map(|g| g as u128).unwrap_or_default(),
1332        );
1333
1334        // update next base fee
1335        self.fees.set_base_fee(next_block_base_fee);
1336        self.fees.set_blob_excess_gas_and_price(BlobExcessGasAndPrice::new(
1337            next_block_excess_blob_gas,
1338            false,
1339        ));
1340
1341        // notify all listeners
1342        self.notify_on_new_block(header, block_hash);
1343
1344        outcome
1345    }
1346
1347    /// Executes the [TransactionRequest] without writing to the DB
1348    ///
1349    /// # Errors
1350    ///
1351    /// Returns an error if the `block_number` is greater than the current height
1352    pub async fn call(
1353        &self,
1354        request: WithOtherFields<TransactionRequest>,
1355        fee_details: FeeDetails,
1356        block_request: Option<BlockRequest>,
1357        overrides: Option<StateOverride>,
1358    ) -> Result<(InstructionResult, Option<Output>, u128, State), BlockchainError> {
1359        self.with_database_at(block_request, |state, block| {
1360            let block_number = block.number.to::<u64>();
1361            let (exit, out, gas, state) = match overrides {
1362                None => self.call_with_state(state.as_dyn(), request, fee_details, block),
1363                Some(overrides) => {
1364                    let state = state::apply_state_override(overrides.into_iter().collect(), state)?;
1365                    self.call_with_state(state.as_dyn(), request, fee_details, block)
1366                },
1367            }?;
1368            trace!(target: "backend", "call return {:?} out: {:?} gas {} on block {}", exit, out, gas, block_number);
1369            Ok((exit, out, gas, state))
1370        }).await?
1371    }
1372
1373    /// ## EVM settings
1374    ///
1375    /// This modifies certain EVM settings to mirror geth's `SkipAccountChecks` when transacting requests, see also: <https://github.com/ethereum/go-ethereum/blob/380688c636a654becc8f114438c2a5d93d2db032/core/state_transition.go#L145-L148>:
1376    ///
1377    ///  - `disable_eip3607` is set to `true`
1378    ///  - `disable_base_fee` is set to `true`
1379    ///  - `nonce` is set to `None`
1380    fn build_call_env(
1381        &self,
1382        request: WithOtherFields<TransactionRequest>,
1383        fee_details: FeeDetails,
1384        block_env: BlockEnv,
1385    ) -> EnvWithHandlerCfg {
1386        let WithOtherFields::<TransactionRequest> {
1387            inner:
1388                TransactionRequest {
1389                    from,
1390                    to,
1391                    gas,
1392                    value,
1393                    input,
1394                    access_list,
1395                    blob_versioned_hashes,
1396                    authorization_list,
1397                    // nonce is always ignored for calls
1398                    nonce: _,
1399                    sidecar: _,
1400                    chain_id: _,
1401                    transaction_type: _,
1402                    .. // Rest of the gas fees related fields are taken from `fee_details`
1403                },
1404            ..
1405        } = request;
1406
1407        let FeeDetails {
1408            gas_price,
1409            max_fee_per_gas,
1410            max_priority_fee_per_gas,
1411            max_fee_per_blob_gas,
1412        } = fee_details;
1413
1414        let gas_limit = gas.unwrap_or(block_env.gas_limit.to());
1415        let mut env = self.env.read().clone();
1416        env.block = block_env;
1417        // we want to disable this in eth_call, since this is common practice used by other node
1418        // impls and providers <https://github.com/foundry-rs/foundry/issues/4388>
1419        env.cfg.disable_block_gas_limit = true;
1420
1421        // The basefee should be ignored for calls against state for
1422        // - eth_call
1423        // - eth_estimateGas
1424        // - eth_createAccessList
1425        // - tracing
1426        env.cfg.disable_base_fee = true;
1427
1428        let gas_price = gas_price.or(max_fee_per_gas).unwrap_or_else(|| {
1429            self.fees().raw_gas_price().saturating_add(MIN_SUGGESTED_PRIORITY_FEE)
1430        });
1431        let caller = from.unwrap_or_default();
1432        let to = to.as_ref().and_then(TxKind::to);
1433        let blob_hashes = blob_versioned_hashes.unwrap_or_default();
1434        env.tx =
1435            TxEnv {
1436                caller,
1437                gas_limit,
1438                gas_price: U256::from(gas_price),
1439                gas_priority_fee: max_priority_fee_per_gas.map(U256::from),
1440                max_fee_per_blob_gas: max_fee_per_blob_gas
1441                    .or_else(|| {
1442                        if !blob_hashes.is_empty() {
1443                            env.block.get_blob_gasprice()
1444                        } else {
1445                            None
1446                        }
1447                    })
1448                    .map(U256::from),
1449                transact_to: match to {
1450                    Some(addr) => TxKind::Call(*addr),
1451                    None => TxKind::Create,
1452                },
1453                value: value.unwrap_or_default(),
1454                data: input.into_input().unwrap_or_default(),
1455                chain_id: None,
1456                // set nonce to None so that the correct nonce is chosen by the EVM
1457                nonce: None,
1458                access_list: access_list.unwrap_or_default().into(),
1459                blob_hashes,
1460                optimism: OptimismFields { enveloped_tx: Some(Bytes::new()), ..Default::default() },
1461                authorization_list: authorization_list.map(Into::into),
1462            };
1463
1464        if env.block.basefee.is_zero() {
1465            // this is an edge case because the evm fails if `tx.effective_gas_price < base_fee`
1466            // 0 is only possible if it's manually set
1467            env.cfg.disable_base_fee = true;
1468        }
1469
1470        env
1471    }
1472
1473    /// Builds [`Inspector`] with the configured options.
1474    fn build_inspector(&self) -> Inspector {
1475        let mut inspector = Inspector::default();
1476
1477        if self.print_logs {
1478            inspector = inspector.with_log_collector();
1479        }
1480        if self.print_traces {
1481            inspector = inspector.with_trace_printer();
1482        }
1483
1484        inspector
1485    }
1486
1487    /// Simulates the payload by executing the calls in request.
1488    pub async fn simulate(
1489        &self,
1490        request: SimulatePayload,
1491        block_request: Option<BlockRequest>,
1492    ) -> Result<Vec<SimulatedBlock<AnyRpcBlock>>, BlockchainError> {
1493        self.with_database_at(block_request, |state, mut block_env| {
1494            let SimulatePayload {
1495                block_state_calls,
1496                trace_transfers,
1497                validation,
1498                return_full_transactions,
1499            } = request;
1500            let mut cache_db = CacheDB::new(state);
1501            let mut block_res = Vec::with_capacity(block_state_calls.len());
1502
1503            // execute the blocks
1504            for block in block_state_calls {
1505                let SimBlock { block_overrides, state_overrides, calls } = block;
1506                let mut call_res = Vec::with_capacity(calls.len());
1507                let mut log_index = 0;
1508                let mut gas_used = 0;
1509                let mut transactions = Vec::with_capacity(calls.len());
1510                // apply state overrides before executing the transactions
1511                if let Some(state_overrides) = state_overrides {
1512                    state::apply_cached_db_state_override(state_overrides, &mut cache_db)?;
1513                }
1514
1515                // apply block overrides
1516                if let Some(overrides) = block_overrides {
1517                    if let Some(number) = overrides.number {
1518                        block_env.number = number.saturating_to();
1519                    }
1520                    if let Some(difficulty) = overrides.difficulty {
1521                        block_env.difficulty = difficulty;
1522                    }
1523                    if let Some(time) = overrides.time {
1524                        block_env.timestamp = U256::from(time);
1525                    }
1526                    if let Some(gas_limit) = overrides.gas_limit {
1527                        block_env.gas_limit = U256::from(gas_limit);
1528                    }
1529                    if let Some(coinbase) = overrides.coinbase {
1530                        block_env.coinbase = coinbase;
1531                    }
1532                    if let Some(random) = overrides.random {
1533                        block_env.prevrandao = Some(random);
1534                    }
1535                    if let Some(base_fee) = overrides.base_fee {
1536                        block_env.basefee = base_fee.saturating_to();
1537                    }
1538                }
1539
1540                // execute all calls in that block
1541                for (req_idx, request) in calls.into_iter().enumerate() {
1542                    let fee_details = FeeDetails::new(
1543                        request.gas_price,
1544                        request.max_fee_per_gas,
1545                        request.max_priority_fee_per_gas,
1546                        request.max_fee_per_blob_gas,
1547                    )?
1548                    .or_zero_fees();
1549
1550                    let mut env = self.build_call_env(
1551                        WithOtherFields::new(request.clone()),
1552                        fee_details,
1553                        block_env.clone(),
1554                    );
1555
1556                    // Always disable EIP-3607
1557                    env.cfg.disable_eip3607 = true;
1558
1559                    if !validation {
1560                        env.cfg.disable_base_fee = !validation;
1561                        env.block.basefee = U256::from(0);
1562                    }
1563
1564                    // transact
1565                    let ResultAndState { result, state } = if trace_transfers {
1566                        // prepare inspector to capture transfer inside the evm so they are
1567                        // recorded and included in logs
1568                        let mut inspector = TransferInspector::new(false).with_logs(true);
1569                        let mut evm =
1570                            self.new_evm_with_inspector_ref(cache_db.as_dyn(), env, &mut inspector);
1571                        trace!(target: "backend", env=?evm.context.env(), spec=?evm.spec_id(), "simulate evm env");
1572                        evm.transact()?
1573                    } else {
1574                        let mut inspector = self.build_inspector();
1575                        let mut evm =
1576                            self.new_evm_with_inspector_ref(cache_db.as_dyn(), env, &mut inspector);
1577                        trace!(target: "backend", env=?evm.context.env(),spec=?evm.spec_id(), "simulate evm env");
1578                        evm.transact()?
1579                    };
1580                    trace!(target: "backend", ?result, ?request, "simulate call");
1581
1582                    // commit the transaction
1583                    cache_db.commit(state);
1584                    gas_used += result.gas_used();
1585
1586                    // TODO: this is likely incomplete
1587                    // create the transaction from a request
1588                    let from = request.from.unwrap_or_default();
1589                    let request =
1590                        transaction_request_to_typed(WithOtherFields::new(request)).unwrap();
1591                    let tx = build_typed_transaction(
1592                        request,
1593                        Signature::new(Default::default(), Default::default(), false),
1594                    )?;
1595                    let rpc_tx = transaction_build(
1596                        None,
1597                        MaybeImpersonatedTransaction::impersonated(tx, from),
1598                        None,
1599                        None,
1600                        Some(block_env.basefee.to()),
1601                    );
1602                    transactions.push(rpc_tx);
1603
1604                    let return_data = result.output().cloned().unwrap_or_default();
1605                    let sim_res = SimCallResult {
1606                        return_data,
1607                        gas_used: result.gas_used(),
1608                        status: result.is_success(),
1609                        error: result.is_success().not().then(|| {
1610                            alloy_rpc_types::simulate::SimulateError {
1611                                code: -3200,
1612                                message: "execution failed".to_string(),
1613                            }
1614                        }),
1615                        logs: result
1616                            .into_logs()
1617                            .into_iter()
1618                            .enumerate()
1619                            .map(|(idx, log)| Log {
1620                                inner: log,
1621                                block_number: Some(block_env.number.to()),
1622                                block_timestamp: Some(block_env.timestamp.to()),
1623                                transaction_index: Some(req_idx as u64),
1624                                log_index: Some((idx + log_index) as u64),
1625                                removed: false,
1626
1627                                block_hash: None,
1628                                transaction_hash: None,
1629                            })
1630                            .collect(),
1631                    };
1632
1633                    log_index += sim_res.logs.len();
1634                    call_res.push(sim_res);
1635                }
1636
1637                let header = Header {
1638                    logs_bloom: Default::default(),
1639                    transactions_root: Default::default(),
1640                    receipts_root: Default::default(),
1641                    parent_hash: Default::default(),
1642                    ommers_hash: Default::default(),
1643                    beneficiary: block_env.coinbase,
1644                    state_root: Default::default(),
1645                    difficulty: Default::default(),
1646                    number: block_env.number.to(),
1647                    gas_limit: block_env.gas_limit.to(),
1648                    gas_used,
1649                    timestamp: block_env.timestamp.to(),
1650                    extra_data: Default::default(),
1651                    mix_hash: Default::default(),
1652                    nonce: Default::default(),
1653                    base_fee_per_gas: Some(block_env.basefee.to()),
1654                    withdrawals_root: None,
1655                    blob_gas_used: None,
1656                    excess_blob_gas: None,
1657                    parent_beacon_block_root: None,
1658                    requests_hash: None,
1659                };
1660                let mut block = alloy_rpc_types::Block {
1661                    header: AnyRpcHeader {
1662                        hash: header.hash_slow(),
1663                        inner: header.into(),
1664                        total_difficulty: None,
1665                        size: None,
1666                    },
1667                    uncles: vec![],
1668                    transactions: BlockTransactions::Full(transactions),
1669                    withdrawals: None,
1670                };
1671
1672                if !return_full_transactions {
1673                    block.transactions.convert_to_hashes();
1674                }
1675
1676                let simulated_block = SimulatedBlock {
1677                    inner: AnyRpcBlock::new(WithOtherFields::new(block)),
1678                    calls: call_res,
1679                };
1680
1681                // update block env
1682                block_env.number += U256::from(1);
1683                block_env.timestamp += U256::from(12);
1684                block_env.basefee = U256::from(
1685                    simulated_block
1686                        .inner
1687                        .header
1688                        .next_block_base_fee(BaseFeeParams::ethereum())
1689                        .unwrap_or_default(),
1690                );
1691
1692                block_res.push(simulated_block);
1693            }
1694
1695            Ok(block_res)
1696        })
1697        .await?
1698    }
1699
1700    pub fn call_with_state(
1701        &self,
1702        state: &dyn DatabaseRef<Error = DatabaseError>,
1703        request: WithOtherFields<TransactionRequest>,
1704        fee_details: FeeDetails,
1705        block_env: BlockEnv,
1706    ) -> Result<(InstructionResult, Option<Output>, u128, State), BlockchainError> {
1707        let mut inspector = self.build_inspector();
1708
1709        let env = self.build_call_env(request, fee_details, block_env);
1710        let mut evm = self.new_evm_with_inspector_ref(state, env, &mut inspector);
1711        let ResultAndState { result, state } = evm.transact()?;
1712        let (exit_reason, gas_used, out) = match result {
1713            ExecutionResult::Success { reason, gas_used, output, .. } => {
1714                (reason.into(), gas_used, Some(output))
1715            }
1716            ExecutionResult::Revert { gas_used, output } => {
1717                (InstructionResult::Revert, gas_used, Some(Output::Call(output)))
1718            }
1719            ExecutionResult::Halt { reason, gas_used } => (reason.into(), gas_used, None),
1720        };
1721        drop(evm);
1722        inspector.print_logs();
1723
1724        if self.print_traces {
1725            inspector.into_print_traces();
1726        }
1727
1728        Ok((exit_reason, out, gas_used as u128, state))
1729    }
1730
1731    pub async fn call_with_tracing(
1732        &self,
1733        request: WithOtherFields<TransactionRequest>,
1734        fee_details: FeeDetails,
1735        block_request: Option<BlockRequest>,
1736        opts: GethDebugTracingCallOptions,
1737    ) -> Result<GethTrace, BlockchainError> {
1738        let GethDebugTracingCallOptions { tracing_options, block_overrides: _, state_overrides } =
1739            opts;
1740        let GethDebugTracingOptions { config, tracer, tracer_config, .. } = tracing_options;
1741
1742        self.with_database_at(block_request, |state, block| {
1743            let block_number = block.number;
1744
1745            let state = if let Some(overrides) = state_overrides {
1746                Box::new(state::apply_state_override(overrides, state)?)
1747                    as Box<dyn MaybeFullDatabase>
1748            } else {
1749                state
1750            };
1751
1752            if let Some(tracer) = tracer {
1753                return match tracer {
1754                    GethDebugTracerType::BuiltInTracer(tracer) => match tracer {
1755                        GethDebugBuiltInTracerType::CallTracer => {
1756                            let call_config = tracer_config
1757                                .into_call_config()
1758                                .map_err(|e| (RpcError::invalid_params(e.to_string())))?;
1759
1760                            let mut inspector = self.build_inspector().with_tracing_config(
1761                                TracingInspectorConfig::from_geth_call_config(&call_config),
1762                            );
1763
1764                            let env = self.build_call_env(request, fee_details, block);
1765                            let mut evm = self.new_evm_with_inspector_ref(
1766                                state.as_dyn(),
1767                                env,
1768                                &mut inspector,
1769                            );
1770                            let ResultAndState { result, state: _ } = evm.transact()?;
1771
1772                            drop(evm);
1773                            let tracing_inspector = inspector.tracer.expect("tracer disappeared");
1774
1775                            Ok(tracing_inspector
1776                                .into_geth_builder()
1777                                .geth_call_traces(call_config, result.gas_used())
1778                                .into())
1779                        }
1780                        GethDebugBuiltInTracerType::NoopTracer => Ok(NoopFrame::default().into()),
1781                        GethDebugBuiltInTracerType::FourByteTracer |
1782                        GethDebugBuiltInTracerType::PreStateTracer |
1783                        GethDebugBuiltInTracerType::MuxTracer |
1784                        GethDebugBuiltInTracerType::FlatCallTracer => {
1785                            Err(RpcError::invalid_params("unsupported tracer type").into())
1786                        }
1787                    },
1788
1789                    GethDebugTracerType::JsTracer(_code) => {
1790                        Err(RpcError::invalid_params("unsupported tracer type").into())
1791                    }
1792                }
1793            }
1794
1795            // defaults to StructLog tracer used since no tracer is specified
1796            let mut inspector = self
1797                .build_inspector()
1798                .with_tracing_config(TracingInspectorConfig::from_geth_config(&config));
1799
1800            let env = self.build_call_env(request, fee_details, block);
1801            let mut evm = self.new_evm_with_inspector_ref(state.as_dyn(), env, &mut inspector);
1802            let ResultAndState { result, state: _ } = evm.transact()?;
1803
1804            let (exit_reason, gas_used, out) = match result {
1805                ExecutionResult::Success { reason, gas_used, output, .. } => {
1806                    (reason.into(), gas_used, Some(output))
1807                }
1808                ExecutionResult::Revert { gas_used, output } => {
1809                    (InstructionResult::Revert, gas_used, Some(Output::Call(output)))
1810                }
1811                ExecutionResult::Halt { reason, gas_used } => (reason.into(), gas_used, None),
1812            };
1813
1814            drop(evm);
1815            let tracing_inspector = inspector.tracer.expect("tracer disappeared");
1816            let return_value = out.as_ref().map(|o| o.data().clone()).unwrap_or_default();
1817
1818            trace!(target: "backend", ?exit_reason, ?out, %gas_used, %block_number, "trace call");
1819
1820            let res = tracing_inspector
1821                .into_geth_builder()
1822                .geth_traces(gas_used, return_value, config)
1823                .into();
1824
1825            Ok(res)
1826        })
1827        .await?
1828    }
1829
1830    pub fn build_access_list_with_state(
1831        &self,
1832        state: &dyn DatabaseRef<Error = DatabaseError>,
1833        request: WithOtherFields<TransactionRequest>,
1834        fee_details: FeeDetails,
1835        block_env: BlockEnv,
1836    ) -> Result<(InstructionResult, Option<Output>, u64, AccessList), BlockchainError> {
1837        let mut inspector =
1838            AccessListInspector::new(request.access_list.clone().unwrap_or_default());
1839
1840        let env = self.build_call_env(request, fee_details, block_env);
1841        let mut evm = self.new_evm_with_inspector_ref(state, env, &mut inspector);
1842        let ResultAndState { result, state: _ } = evm.transact()?;
1843        let (exit_reason, gas_used, out) = match result {
1844            ExecutionResult::Success { reason, gas_used, output, .. } => {
1845                (reason.into(), gas_used, Some(output))
1846            }
1847            ExecutionResult::Revert { gas_used, output } => {
1848                (InstructionResult::Revert, gas_used, Some(Output::Call(output)))
1849            }
1850            ExecutionResult::Halt { reason, gas_used } => (reason.into(), gas_used, None),
1851        };
1852        drop(evm);
1853        let access_list = inspector.access_list();
1854        Ok((exit_reason, out, gas_used, access_list))
1855    }
1856
1857    /// returns all receipts for the given transactions
1858    fn get_receipts(&self, tx_hashes: impl IntoIterator<Item = TxHash>) -> Vec<TypedReceipt> {
1859        let storage = self.blockchain.storage.read();
1860        let mut receipts = vec![];
1861
1862        for hash in tx_hashes {
1863            if let Some(tx) = storage.transactions.get(&hash) {
1864                receipts.push(tx.receipt.clone());
1865            }
1866        }
1867
1868        receipts
1869    }
1870
1871    /// Returns the logs of the block that match the filter
1872    async fn logs_for_block(
1873        &self,
1874        filter: Filter,
1875        hash: B256,
1876    ) -> Result<Vec<Log>, BlockchainError> {
1877        if let Some(block) = self.blockchain.get_block_by_hash(&hash) {
1878            return Ok(self.mined_logs_for_block(filter, block));
1879        }
1880
1881        if let Some(fork) = self.get_fork() {
1882            return Ok(fork.logs(&filter).await?);
1883        }
1884
1885        Ok(Vec::new())
1886    }
1887
1888    /// Returns all `Log`s mined by the node that were emitted in the `block` and match the `Filter`
1889    fn mined_logs_for_block(&self, filter: Filter, block: Block) -> Vec<Log> {
1890        let params = FilteredParams::new(Some(filter.clone()));
1891        let mut all_logs = Vec::new();
1892        let block_hash = block.header.hash_slow();
1893        let mut block_log_index = 0u32;
1894
1895        let storage = self.blockchain.storage.read();
1896
1897        for tx in block.transactions {
1898            let Some(tx) = storage.transactions.get(&tx.hash()) else {
1899                continue;
1900            };
1901            let logs = tx.receipt.logs();
1902            let transaction_hash = tx.info.transaction_hash;
1903
1904            for log in logs {
1905                let mut is_match: bool = true;
1906                if !filter.address.is_empty() && filter.has_topics() {
1907                    if !params.filter_address(&log.address) || !params.filter_topics(log.topics()) {
1908                        is_match = false;
1909                    }
1910                } else if !filter.address.is_empty() {
1911                    if !params.filter_address(&log.address) {
1912                        is_match = false;
1913                    }
1914                } else if filter.has_topics() && !params.filter_topics(log.topics()) {
1915                    is_match = false;
1916                }
1917
1918                if is_match {
1919                    let log = Log {
1920                        inner: log.clone(),
1921                        block_hash: Some(block_hash),
1922                        block_number: Some(block.header.number),
1923                        block_timestamp: Some(block.header.timestamp),
1924                        transaction_hash: Some(transaction_hash),
1925                        transaction_index: Some(tx.info.transaction_index),
1926                        log_index: Some(block_log_index as u64),
1927                        removed: false,
1928                    };
1929                    all_logs.push(log);
1930                }
1931                block_log_index += 1;
1932            }
1933        }
1934
1935        all_logs
1936    }
1937
1938    /// Returns the logs that match the filter in the given range of blocks
1939    async fn logs_for_range(
1940        &self,
1941        filter: &Filter,
1942        mut from: u64,
1943        to: u64,
1944    ) -> Result<Vec<Log>, BlockchainError> {
1945        let mut all_logs = Vec::new();
1946
1947        // get the range that predates the fork if any
1948        if let Some(fork) = self.get_fork() {
1949            let mut to_on_fork = to;
1950
1951            if !fork.predates_fork(to) {
1952                // adjust the ranges
1953                to_on_fork = fork.block_number();
1954            }
1955
1956            if fork.predates_fork_inclusive(from) {
1957                // this data is only available on the forked client
1958                let filter = filter.clone().from_block(from).to_block(to_on_fork);
1959                all_logs = fork.logs(&filter).await?;
1960
1961                // update the range
1962                from = fork.block_number() + 1;
1963            }
1964        }
1965
1966        for number in from..=to {
1967            if let Some(block) = self.get_block(number) {
1968                all_logs.extend(self.mined_logs_for_block(filter.clone(), block));
1969            }
1970        }
1971
1972        Ok(all_logs)
1973    }
1974
1975    /// Returns the logs according to the filter
1976    pub async fn logs(&self, filter: Filter) -> Result<Vec<Log>, BlockchainError> {
1977        trace!(target: "backend", "get logs [{:?}]", filter);
1978        if let Some(hash) = filter.get_block_hash() {
1979            self.logs_for_block(filter, hash).await
1980        } else {
1981            let best = self.best_number();
1982            let to_block =
1983                self.convert_block_number(filter.block_option.get_to_block().copied()).min(best);
1984            let from_block =
1985                self.convert_block_number(filter.block_option.get_from_block().copied());
1986            if from_block > best {
1987                // requested log range does not exist yet
1988                return Ok(vec![]);
1989            }
1990
1991            self.logs_for_range(&filter, from_block, to_block).await
1992        }
1993    }
1994
1995    pub async fn block_by_hash(&self, hash: B256) -> Result<Option<AnyRpcBlock>, BlockchainError> {
1996        trace!(target: "backend", "get block by hash {:?}", hash);
1997        if let tx @ Some(_) = self.mined_block_by_hash(hash) {
1998            return Ok(tx);
1999        }
2000
2001        if let Some(fork) = self.get_fork() {
2002            return Ok(fork.block_by_hash(hash).await?);
2003        }
2004
2005        Ok(None)
2006    }
2007
2008    pub async fn block_by_hash_full(
2009        &self,
2010        hash: B256,
2011    ) -> Result<Option<AnyRpcBlock>, BlockchainError> {
2012        trace!(target: "backend", "get block by hash {:?}", hash);
2013        if let tx @ Some(_) = self.get_full_block(hash) {
2014            return Ok(tx);
2015        }
2016
2017        if let Some(fork) = self.get_fork() {
2018            return Ok(fork.block_by_hash_full(hash).await?)
2019        }
2020
2021        Ok(None)
2022    }
2023
2024    fn mined_block_by_hash(&self, hash: B256) -> Option<AnyRpcBlock> {
2025        let block = self.blockchain.get_block_by_hash(&hash)?;
2026        Some(self.convert_block(block))
2027    }
2028
2029    pub(crate) async fn mined_transactions_by_block_number(
2030        &self,
2031        number: BlockNumber,
2032    ) -> Option<Vec<AnyRpcTransaction>> {
2033        if let Some(block) = self.get_block(number) {
2034            return self.mined_transactions_in_block(&block);
2035        }
2036        None
2037    }
2038
2039    /// Returns all transactions given a block
2040    pub(crate) fn mined_transactions_in_block(
2041        &self,
2042        block: &Block,
2043    ) -> Option<Vec<AnyRpcTransaction>> {
2044        let mut transactions = Vec::with_capacity(block.transactions.len());
2045        let base_fee = block.header.base_fee_per_gas;
2046        let storage = self.blockchain.storage.read();
2047        for hash in block.transactions.iter().map(|tx| tx.hash()) {
2048            let info = storage.transactions.get(&hash)?.info.clone();
2049            let tx = block.transactions.get(info.transaction_index as usize)?.clone();
2050
2051            let tx = transaction_build(Some(hash), tx, Some(block), Some(info), base_fee);
2052            transactions.push(tx);
2053        }
2054        Some(transactions)
2055    }
2056
2057    pub async fn block_by_number(
2058        &self,
2059        number: BlockNumber,
2060    ) -> Result<Option<AnyRpcBlock>, BlockchainError> {
2061        trace!(target: "backend", "get block by number {:?}", number);
2062        if let tx @ Some(_) = self.mined_block_by_number(number) {
2063            return Ok(tx);
2064        }
2065
2066        if let Some(fork) = self.get_fork() {
2067            let number = self.convert_block_number(Some(number));
2068            if fork.predates_fork_inclusive(number) {
2069                return Ok(fork.block_by_number(number).await?)
2070            }
2071        }
2072
2073        Ok(None)
2074    }
2075
2076    pub async fn block_by_number_full(
2077        &self,
2078        number: BlockNumber,
2079    ) -> Result<Option<AnyRpcBlock>, BlockchainError> {
2080        trace!(target: "backend", "get block by number {:?}", number);
2081        if let tx @ Some(_) = self.get_full_block(number) {
2082            return Ok(tx);
2083        }
2084
2085        if let Some(fork) = self.get_fork() {
2086            let number = self.convert_block_number(Some(number));
2087            if fork.predates_fork_inclusive(number) {
2088                return Ok(fork.block_by_number_full(number).await?)
2089            }
2090        }
2091
2092        Ok(None)
2093    }
2094
2095    pub fn get_block(&self, id: impl Into<BlockId>) -> Option<Block> {
2096        let hash = match id.into() {
2097            BlockId::Hash(hash) => hash.block_hash,
2098            BlockId::Number(number) => {
2099                let storage = self.blockchain.storage.read();
2100                let slots_in_an_epoch = U64::from(self.slots_in_an_epoch);
2101                match number {
2102                    BlockNumber::Latest => storage.best_hash,
2103                    BlockNumber::Earliest => storage.genesis_hash,
2104                    BlockNumber::Pending => return None,
2105                    BlockNumber::Number(num) => *storage.hashes.get(&U64::from(num))?,
2106                    BlockNumber::Safe => {
2107                        if storage.best_number > (slots_in_an_epoch) {
2108                            *storage.hashes.get(&(storage.best_number - (slots_in_an_epoch)))?
2109                        } else {
2110                            storage.genesis_hash // treat the genesis block as safe "by definition"
2111                        }
2112                    }
2113                    BlockNumber::Finalized => {
2114                        if storage.best_number > (slots_in_an_epoch * U64::from(2)) {
2115                            *storage
2116                                .hashes
2117                                .get(&(storage.best_number - (slots_in_an_epoch * U64::from(2))))?
2118                        } else {
2119                            storage.genesis_hash
2120                        }
2121                    }
2122                }
2123            }
2124        };
2125        self.get_block_by_hash(hash)
2126    }
2127
2128    pub fn get_block_by_hash(&self, hash: B256) -> Option<Block> {
2129        self.blockchain.get_block_by_hash(&hash)
2130    }
2131
2132    pub fn mined_block_by_number(&self, number: BlockNumber) -> Option<AnyRpcBlock> {
2133        let block = self.get_block(number)?;
2134        let mut block = self.convert_block(block);
2135        block.transactions.convert_to_hashes();
2136        Some(block)
2137    }
2138
2139    pub fn get_full_block(&self, id: impl Into<BlockId>) -> Option<AnyRpcBlock> {
2140        let block = self.get_block(id)?;
2141        let transactions = self.mined_transactions_in_block(&block)?;
2142        let mut block = self.convert_block(block);
2143        block.inner.transactions = BlockTransactions::Full(transactions);
2144
2145        Some(block)
2146    }
2147
2148    /// Takes a block as it's stored internally and returns the eth api conform block format.
2149    pub fn convert_block(&self, block: Block) -> AnyRpcBlock {
2150        let size = U256::from(alloy_rlp::encode(&block).len() as u32);
2151
2152        let Block { header, transactions, .. } = block;
2153
2154        let hash = header.hash_slow();
2155        let Header { number, withdrawals_root, .. } = header;
2156
2157        let block = AlloyBlock {
2158            header: AlloyHeader {
2159                inner: AnyHeader::from(header),
2160                hash,
2161                total_difficulty: Some(self.total_difficulty()),
2162                size: Some(size),
2163            },
2164            transactions: alloy_rpc_types::BlockTransactions::Hashes(
2165                transactions.into_iter().map(|tx| tx.hash()).collect(),
2166            ),
2167            uncles: vec![],
2168            withdrawals: withdrawals_root.map(|_| Default::default()),
2169        };
2170
2171        let mut block = WithOtherFields::new(block);
2172
2173        // If Arbitrum, apply chain specifics to converted block.
2174        if is_arbitrum(self.env.read().cfg.chain_id) {
2175            // Set `l1BlockNumber` field.
2176            block.other.insert("l1BlockNumber".to_string(), number.into());
2177        }
2178
2179        AnyRpcBlock::from(block)
2180    }
2181
2182    /// Converts the `BlockNumber` into a numeric value
2183    ///
2184    /// # Errors
2185    ///
2186    /// returns an error if the requested number is larger than the current height
2187    pub async fn ensure_block_number<T: Into<BlockId>>(
2188        &self,
2189        block_id: Option<T>,
2190    ) -> Result<u64, BlockchainError> {
2191        let current = self.best_number();
2192        let requested =
2193            match block_id.map(Into::into).unwrap_or(BlockId::Number(BlockNumber::Latest)) {
2194                BlockId::Hash(hash) => {
2195                    self.block_by_hash(hash.block_hash)
2196                        .await?
2197                        .ok_or(BlockchainError::BlockNotFound)?
2198                        .header
2199                        .number
2200                }
2201                BlockId::Number(num) => match num {
2202                    BlockNumber::Latest | BlockNumber::Pending => self.best_number(),
2203                    BlockNumber::Earliest => U64::ZERO.to::<u64>(),
2204                    BlockNumber::Number(num) => num,
2205                    BlockNumber::Safe => current.saturating_sub(self.slots_in_an_epoch),
2206                    BlockNumber::Finalized => current.saturating_sub(self.slots_in_an_epoch * 2),
2207                },
2208            };
2209
2210        if requested > current {
2211            Err(BlockchainError::BlockOutOfRange(current, requested))
2212        } else {
2213            Ok(requested)
2214        }
2215    }
2216
2217    pub fn convert_block_number(&self, block: Option<BlockNumber>) -> u64 {
2218        let current = self.best_number();
2219        match block.unwrap_or(BlockNumber::Latest) {
2220            BlockNumber::Latest | BlockNumber::Pending => current,
2221            BlockNumber::Earliest => 0,
2222            BlockNumber::Number(num) => num,
2223            BlockNumber::Safe => current.saturating_sub(self.slots_in_an_epoch),
2224            BlockNumber::Finalized => current.saturating_sub(self.slots_in_an_epoch * 2),
2225        }
2226    }
2227
2228    /// Helper function to execute a closure with the database at a specific block
2229    pub async fn with_database_at<F, T>(
2230        &self,
2231        block_request: Option<BlockRequest>,
2232        f: F,
2233    ) -> Result<T, BlockchainError>
2234    where
2235        F: FnOnce(Box<dyn MaybeFullDatabase + '_>, BlockEnv) -> T,
2236    {
2237        let block_number = match block_request {
2238            Some(BlockRequest::Pending(pool_transactions)) => {
2239                let result = self
2240                    .with_pending_block(pool_transactions, |state, block| {
2241                        let block = block.block;
2242                        let block = BlockEnv {
2243                            number: U256::from(block.header.number),
2244                            coinbase: block.header.beneficiary,
2245                            timestamp: U256::from(block.header.timestamp),
2246                            difficulty: block.header.difficulty,
2247                            prevrandao: Some(block.header.mix_hash),
2248                            basefee: U256::from(block.header.base_fee_per_gas.unwrap_or_default()),
2249                            gas_limit: U256::from(block.header.gas_limit),
2250                            ..Default::default()
2251                        };
2252                        f(state, block)
2253                    })
2254                    .await;
2255                return Ok(result);
2256            }
2257            Some(BlockRequest::Number(bn)) => Some(BlockNumber::Number(bn)),
2258            None => None,
2259        };
2260        let block_number: U256 = U256::from(self.convert_block_number(block_number));
2261
2262        if block_number < self.env.read().block.number {
2263            if let Some((block_hash, block)) = self
2264                .block_by_number(BlockNumber::Number(block_number.to::<u64>()))
2265                .await?
2266                .map(|block| (block.header.hash, block))
2267            {
2268                if let Some(state) = self.states.write().get(&block_hash) {
2269                    let block = BlockEnv {
2270                        number: block_number,
2271                        coinbase: block.header.beneficiary,
2272                        timestamp: U256::from(block.header.timestamp),
2273                        difficulty: block.header.difficulty,
2274                        prevrandao: block.header.mix_hash,
2275                        basefee: U256::from(block.header.base_fee_per_gas.unwrap_or_default()),
2276                        gas_limit: U256::from(block.header.gas_limit),
2277                        ..Default::default()
2278                    };
2279                    return Ok(f(Box::new(state), block));
2280                }
2281            }
2282
2283            warn!(target: "backend", "Not historic state found for block={}", block_number);
2284            return Err(BlockchainError::BlockOutOfRange(
2285                self.env.read().block.number.to::<u64>(),
2286                block_number.to::<u64>(),
2287            ));
2288        }
2289
2290        let db = self.db.read().await;
2291        let block = self.env.read().block.clone();
2292        Ok(f(Box::new(&**db), block))
2293    }
2294
2295    pub async fn storage_at(
2296        &self,
2297        address: Address,
2298        index: U256,
2299        block_request: Option<BlockRequest>,
2300    ) -> Result<B256, BlockchainError> {
2301        self.with_database_at(block_request, |db, _| {
2302            trace!(target: "backend", "get storage for {:?} at {:?}", address, index);
2303            let val = db.storage_ref(address, index)?;
2304            Ok(val.into())
2305        })
2306        .await?
2307    }
2308
2309    /// Returns the code of the address
2310    ///
2311    /// If the code is not present and fork mode is enabled then this will try to fetch it from the
2312    /// forked client
2313    pub async fn get_code(
2314        &self,
2315        address: Address,
2316        block_request: Option<BlockRequest>,
2317    ) -> Result<Bytes, BlockchainError> {
2318        self.with_database_at(block_request, |db, _| self.get_code_with_state(&db, address)).await?
2319    }
2320
2321    pub fn get_code_with_state(
2322        &self,
2323        state: &dyn DatabaseRef<Error = DatabaseError>,
2324        address: Address,
2325    ) -> Result<Bytes, BlockchainError> {
2326        trace!(target: "backend", "get code for {:?}", address);
2327        let account = state.basic_ref(address)?.unwrap_or_default();
2328        if account.code_hash == KECCAK_EMPTY {
2329            // if the code hash is `KECCAK_EMPTY`, we check no further
2330            return Ok(Default::default());
2331        }
2332        let code = if let Some(code) = account.code {
2333            code
2334        } else {
2335            state.code_by_hash_ref(account.code_hash)?
2336        };
2337        Ok(code.bytes()[..code.len()].to_vec().into())
2338    }
2339
2340    /// Returns the balance of the address
2341    ///
2342    /// If the requested number predates the fork then this will fetch it from the endpoint
2343    pub async fn get_balance(
2344        &self,
2345        address: Address,
2346        block_request: Option<BlockRequest>,
2347    ) -> Result<U256, BlockchainError> {
2348        self.with_database_at(block_request, |db, _| self.get_balance_with_state(db, address))
2349            .await?
2350    }
2351
2352    pub async fn get_account_at_block(
2353        &self,
2354        address: Address,
2355        block_request: Option<BlockRequest>,
2356    ) -> Result<Account, BlockchainError> {
2357        self.with_database_at(block_request, |block_db, _| {
2358            let db = block_db.maybe_as_full_db().ok_or(BlockchainError::DataUnavailable)?;
2359            let account = db.get(&address).cloned().unwrap_or_default();
2360            let storage_root = storage_root(&account.storage);
2361            let code_hash = account.info.code_hash;
2362            let balance = account.info.balance;
2363            let nonce = account.info.nonce;
2364            Ok(Account { balance, nonce, code_hash, storage_root })
2365        })
2366        .await?
2367    }
2368
2369    pub fn get_balance_with_state<D>(
2370        &self,
2371        state: D,
2372        address: Address,
2373    ) -> Result<U256, BlockchainError>
2374    where
2375        D: DatabaseRef<Error = DatabaseError>,
2376    {
2377        trace!(target: "backend", "get balance for {:?}", address);
2378        Ok(state.basic_ref(address)?.unwrap_or_default().balance)
2379    }
2380
2381    /// Returns the nonce of the address
2382    ///
2383    /// If the requested number predates the fork then this will fetch it from the endpoint
2384    pub async fn get_nonce(
2385        &self,
2386        address: Address,
2387        block_request: BlockRequest,
2388    ) -> Result<u64, BlockchainError> {
2389        if let BlockRequest::Pending(pool_transactions) = &block_request {
2390            if let Some(value) = get_pool_transactions_nonce(pool_transactions, address) {
2391                return Ok(value);
2392            }
2393        }
2394        let final_block_request = match block_request {
2395            BlockRequest::Pending(_) => BlockRequest::Number(self.best_number()),
2396            BlockRequest::Number(bn) => BlockRequest::Number(bn),
2397        };
2398
2399        self.with_database_at(Some(final_block_request), |db, _| {
2400            trace!(target: "backend", "get nonce for {:?}", address);
2401            Ok(db.basic_ref(address)?.unwrap_or_default().nonce)
2402        })
2403        .await?
2404    }
2405
2406    /// Returns the traces for the given transaction
2407    pub async fn trace_transaction(
2408        &self,
2409        hash: B256,
2410    ) -> Result<Vec<LocalizedTransactionTrace>, BlockchainError> {
2411        if let Some(traces) = self.mined_parity_trace_transaction(hash) {
2412            return Ok(traces);
2413        }
2414
2415        if let Some(fork) = self.get_fork() {
2416            return Ok(fork.trace_transaction(hash).await?)
2417        }
2418
2419        Ok(vec![])
2420    }
2421
2422    /// Returns the traces for the given transaction
2423    pub(crate) fn mined_parity_trace_transaction(
2424        &self,
2425        hash: B256,
2426    ) -> Option<Vec<LocalizedTransactionTrace>> {
2427        self.blockchain.storage.read().transactions.get(&hash).map(|tx| tx.parity_traces())
2428    }
2429
2430    /// Returns the traces for the given transaction
2431    pub(crate) fn mined_transaction(&self, hash: B256) -> Option<MinedTransaction> {
2432        self.blockchain.storage.read().transactions.get(&hash).cloned()
2433    }
2434
2435    /// Returns the traces for the given block
2436    pub(crate) fn mined_parity_trace_block(
2437        &self,
2438        block: u64,
2439    ) -> Option<Vec<LocalizedTransactionTrace>> {
2440        let block = self.get_block(block)?;
2441        let mut traces = vec![];
2442        let storage = self.blockchain.storage.read();
2443        for tx in block.transactions {
2444            traces.extend(storage.transactions.get(&tx.hash())?.parity_traces());
2445        }
2446        Some(traces)
2447    }
2448
2449    /// Returns the traces for the given transaction
2450    pub async fn debug_trace_transaction(
2451        &self,
2452        hash: B256,
2453        opts: GethDebugTracingOptions,
2454    ) -> Result<GethTrace, BlockchainError> {
2455        if let Some(trace) = self.mined_geth_trace_transaction(hash, opts.clone()) {
2456            return trace;
2457        }
2458
2459        if let Some(fork) = self.get_fork() {
2460            return Ok(fork.debug_trace_transaction(hash, opts).await?)
2461        }
2462
2463        Ok(GethTrace::Default(Default::default()))
2464    }
2465
2466    fn mined_geth_trace_transaction(
2467        &self,
2468        hash: B256,
2469        opts: GethDebugTracingOptions,
2470    ) -> Option<Result<GethTrace, BlockchainError>> {
2471        self.blockchain.storage.read().transactions.get(&hash).map(|tx| tx.geth_trace(opts))
2472    }
2473
2474    /// Returns the traces for the given block
2475    pub async fn trace_block(
2476        &self,
2477        block: BlockNumber,
2478    ) -> Result<Vec<LocalizedTransactionTrace>, BlockchainError> {
2479        let number = self.convert_block_number(Some(block));
2480        if let Some(traces) = self.mined_parity_trace_block(number) {
2481            return Ok(traces);
2482        }
2483
2484        if let Some(fork) = self.get_fork() {
2485            if fork.predates_fork(number) {
2486                return Ok(fork.trace_block(number).await?)
2487            }
2488        }
2489
2490        Ok(vec![])
2491    }
2492
2493    pub async fn transaction_receipt(
2494        &self,
2495        hash: B256,
2496    ) -> Result<Option<ReceiptResponse>, BlockchainError> {
2497        if let Some(receipt) = self.mined_transaction_receipt(hash) {
2498            return Ok(Some(receipt.inner));
2499        }
2500
2501        if let Some(fork) = self.get_fork() {
2502            let receipt = fork.transaction_receipt(hash).await?;
2503            let number = self.convert_block_number(
2504                receipt.clone().and_then(|r| r.block_number).map(BlockNumber::from),
2505            );
2506
2507            if fork.predates_fork_inclusive(number) {
2508                return Ok(receipt);
2509            }
2510        }
2511
2512        Ok(None)
2513    }
2514
2515    // Returns the traces matching a given filter
2516    pub async fn trace_filter(
2517        &self,
2518        filter: TraceFilter,
2519    ) -> Result<Vec<LocalizedTransactionTrace>, BlockchainError> {
2520        let matcher = filter.matcher();
2521        let start = filter.from_block.unwrap_or(0);
2522        let end = filter.to_block.unwrap_or(self.best_number());
2523
2524        let dist = end.saturating_sub(start);
2525        if dist == 0 {
2526            return Err(BlockchainError::RpcError(RpcError::invalid_params(
2527                "invalid block range, ensure that to block is greater than from block".to_string(),
2528            )));
2529        }
2530        if dist > 300 {
2531            return Err(BlockchainError::RpcError(RpcError::invalid_params(
2532                "block range too large, currently limited to 300".to_string(),
2533            )));
2534        }
2535
2536        // Accumulate tasks for block range
2537        let mut trace_tasks = vec![];
2538        for num in start..=end {
2539            trace_tasks.push(self.trace_block(num.into()));
2540        }
2541
2542        // Execute tasks and filter traces
2543        let traces = futures::future::try_join_all(trace_tasks).await?;
2544        let filtered_traces =
2545            traces.into_iter().flatten().filter(|trace| matcher.matches(&trace.trace));
2546
2547        // Apply after and count
2548        let filtered_traces: Vec<_> = if let Some(after) = filter.after {
2549            filtered_traces.skip(after as usize).collect()
2550        } else {
2551            filtered_traces.collect()
2552        };
2553
2554        let filtered_traces: Vec<_> = if let Some(count) = filter.count {
2555            filtered_traces.into_iter().take(count as usize).collect()
2556        } else {
2557            filtered_traces
2558        };
2559
2560        Ok(filtered_traces)
2561    }
2562
2563    /// Returns all receipts of the block
2564    pub fn mined_receipts(&self, hash: B256) -> Option<Vec<TypedReceipt>> {
2565        let block = self.mined_block_by_hash(hash)?;
2566        let mut receipts = Vec::new();
2567        let storage = self.blockchain.storage.read();
2568        for tx in block.transactions.hashes() {
2569            let receipt = storage.transactions.get(&tx)?.receipt.clone();
2570            receipts.push(receipt);
2571        }
2572        Some(receipts)
2573    }
2574
2575    /// Returns all transaction receipts of the block
2576    pub fn mined_block_receipts(&self, id: impl Into<BlockId>) -> Option<Vec<ReceiptResponse>> {
2577        let mut receipts = Vec::new();
2578        let block = self.get_block(id)?;
2579
2580        for transaction in block.transactions {
2581            let receipt = self.mined_transaction_receipt(transaction.hash())?;
2582            receipts.push(receipt.inner);
2583        }
2584
2585        Some(receipts)
2586    }
2587
2588    /// Returns the transaction receipt for the given hash
2589    pub(crate) fn mined_transaction_receipt(&self, hash: B256) -> Option<MinedTransactionReceipt> {
2590        let MinedTransaction { info, receipt: tx_receipt, block_hash, .. } =
2591            self.blockchain.get_transaction_by_hash(&hash)?;
2592
2593        let index = info.transaction_index as usize;
2594        let block = self.blockchain.get_block_by_hash(&block_hash)?;
2595        let transaction = block.transactions[index].clone();
2596
2597        // Cancun specific
2598        let excess_blob_gas = block.header.excess_blob_gas;
2599        let blob_gas_price =
2600            alloy_eips::eip4844::calc_blob_gasprice(excess_blob_gas.unwrap_or_default());
2601        let blob_gas_used = transaction.blob_gas();
2602
2603        let effective_gas_price = match transaction.transaction {
2604            TypedTransaction::Legacy(t) => t.tx().gas_price,
2605            TypedTransaction::EIP2930(t) => t.tx().gas_price,
2606            TypedTransaction::EIP1559(t) => block
2607                .header
2608                .base_fee_per_gas
2609                .map_or(self.base_fee() as u128, |g| g as u128)
2610                .saturating_add(t.tx().max_priority_fee_per_gas),
2611            TypedTransaction::EIP4844(t) => block
2612                .header
2613                .base_fee_per_gas
2614                .map_or(self.base_fee() as u128, |g| g as u128)
2615                .saturating_add(t.tx().tx().max_priority_fee_per_gas),
2616            TypedTransaction::EIP7702(t) => block
2617                .header
2618                .base_fee_per_gas
2619                .map_or(self.base_fee() as u128, |g| g as u128)
2620                .saturating_add(t.tx().max_priority_fee_per_gas),
2621            TypedTransaction::Deposit(_) => 0_u128,
2622        };
2623
2624        let receipts = self.get_receipts(block.transactions.iter().map(|tx| tx.hash()));
2625        let next_log_index = receipts[..index].iter().map(|r| r.logs().len()).sum::<usize>();
2626
2627        let receipt = tx_receipt.as_receipt_with_bloom().receipt.clone();
2628        let receipt = Receipt {
2629            status: receipt.status,
2630            cumulative_gas_used: receipt.cumulative_gas_used,
2631            logs: receipt
2632                .logs
2633                .into_iter()
2634                .enumerate()
2635                .map(|(index, log)| alloy_rpc_types::Log {
2636                    inner: log,
2637                    block_hash: Some(block_hash),
2638                    block_number: Some(block.header.number),
2639                    block_timestamp: Some(block.header.timestamp),
2640                    transaction_hash: Some(info.transaction_hash),
2641                    transaction_index: Some(info.transaction_index),
2642                    log_index: Some((next_log_index + index) as u64),
2643                    removed: false,
2644                })
2645                .collect(),
2646        };
2647        let receipt_with_bloom =
2648            ReceiptWithBloom { receipt, logs_bloom: tx_receipt.as_receipt_with_bloom().logs_bloom };
2649
2650        let inner = match tx_receipt {
2651            TypedReceipt::EIP1559(_) => TypedReceipt::EIP1559(receipt_with_bloom),
2652            TypedReceipt::Legacy(_) => TypedReceipt::Legacy(receipt_with_bloom),
2653            TypedReceipt::EIP2930(_) => TypedReceipt::EIP2930(receipt_with_bloom),
2654            TypedReceipt::EIP4844(_) => TypedReceipt::EIP4844(receipt_with_bloom),
2655            TypedReceipt::EIP7702(_) => TypedReceipt::EIP7702(receipt_with_bloom),
2656            TypedReceipt::Deposit(r) => TypedReceipt::Deposit(DepositReceipt {
2657                inner: receipt_with_bloom,
2658                deposit_nonce: r.deposit_nonce,
2659                deposit_receipt_version: r.deposit_receipt_version,
2660            }),
2661        };
2662
2663        let inner = TransactionReceipt {
2664            inner,
2665            transaction_hash: info.transaction_hash,
2666            transaction_index: Some(info.transaction_index),
2667            block_number: Some(block.header.number),
2668            gas_used: info.gas_used,
2669            contract_address: info.contract_address,
2670            effective_gas_price,
2671            block_hash: Some(block_hash),
2672            from: info.from,
2673            to: info.to,
2674            blob_gas_price: Some(blob_gas_price),
2675            blob_gas_used,
2676        };
2677
2678        Some(MinedTransactionReceipt { inner, out: info.out.map(|o| o.0.into()) })
2679    }
2680
2681    /// Returns the blocks receipts for the given number
2682    pub async fn block_receipts(
2683        &self,
2684        number: BlockId,
2685    ) -> Result<Option<Vec<ReceiptResponse>>, BlockchainError> {
2686        if let Some(receipts) = self.mined_block_receipts(number) {
2687            return Ok(Some(receipts));
2688        }
2689
2690        if let Some(fork) = self.get_fork() {
2691            let number = match self.ensure_block_number(Some(number)).await {
2692                Err(_) => return Ok(None),
2693                Ok(n) => n,
2694            };
2695
2696            if fork.predates_fork_inclusive(number) {
2697                let receipts = fork.block_receipts(number).await?;
2698
2699                return Ok(receipts);
2700            }
2701        }
2702
2703        Ok(None)
2704    }
2705
2706    pub async fn transaction_by_block_number_and_index(
2707        &self,
2708        number: BlockNumber,
2709        index: Index,
2710    ) -> Result<Option<AnyRpcTransaction>, BlockchainError> {
2711        if let Some(block) = self.mined_block_by_number(number) {
2712            return Ok(self.mined_transaction_by_block_hash_and_index(block.header.hash, index));
2713        }
2714
2715        if let Some(fork) = self.get_fork() {
2716            let number = self.convert_block_number(Some(number));
2717            if fork.predates_fork(number) {
2718                return Ok(fork.transaction_by_block_number_and_index(number, index.into()).await?)
2719            }
2720        }
2721
2722        Ok(None)
2723    }
2724
2725    pub async fn transaction_by_block_hash_and_index(
2726        &self,
2727        hash: B256,
2728        index: Index,
2729    ) -> Result<Option<AnyRpcTransaction>, BlockchainError> {
2730        if let tx @ Some(_) = self.mined_transaction_by_block_hash_and_index(hash, index) {
2731            return Ok(tx);
2732        }
2733
2734        if let Some(fork) = self.get_fork() {
2735            return Ok(fork.transaction_by_block_hash_and_index(hash, index.into()).await?)
2736        }
2737
2738        Ok(None)
2739    }
2740
2741    pub fn mined_transaction_by_block_hash_and_index(
2742        &self,
2743        block_hash: B256,
2744        index: Index,
2745    ) -> Option<AnyRpcTransaction> {
2746        let (info, block, tx) = {
2747            let storage = self.blockchain.storage.read();
2748            let block = storage.blocks.get(&block_hash).cloned()?;
2749            let index: usize = index.into();
2750            let tx = block.transactions.get(index)?.clone();
2751            let info = storage.transactions.get(&tx.hash())?.info.clone();
2752            (info, block, tx)
2753        };
2754
2755        Some(transaction_build(
2756            Some(info.transaction_hash),
2757            tx,
2758            Some(&block),
2759            Some(info),
2760            block.header.base_fee_per_gas,
2761        ))
2762    }
2763
2764    pub async fn transaction_by_hash(
2765        &self,
2766        hash: B256,
2767    ) -> Result<Option<AnyRpcTransaction>, BlockchainError> {
2768        trace!(target: "backend", "transaction_by_hash={:?}", hash);
2769        if let tx @ Some(_) = self.mined_transaction_by_hash(hash) {
2770            return Ok(tx);
2771        }
2772
2773        if let Some(fork) = self.get_fork() {
2774            return fork.transaction_by_hash(hash).await.map_err(BlockchainError::AlloyForkProvider)
2775        }
2776
2777        Ok(None)
2778    }
2779
2780    pub fn mined_transaction_by_hash(&self, hash: B256) -> Option<AnyRpcTransaction> {
2781        let (info, block) = {
2782            let storage = self.blockchain.storage.read();
2783            let MinedTransaction { info, block_hash, .. } =
2784                storage.transactions.get(&hash)?.clone();
2785            let block = storage.blocks.get(&block_hash).cloned()?;
2786            (info, block)
2787        };
2788        let tx = block.transactions.get(info.transaction_index as usize)?.clone();
2789
2790        Some(transaction_build(
2791            Some(info.transaction_hash),
2792            tx,
2793            Some(&block),
2794            Some(info),
2795            block.header.base_fee_per_gas,
2796        ))
2797    }
2798
2799    /// Prove an account's existence or nonexistence in the state trie.
2800    ///
2801    /// Returns a merkle proof of the account's trie node, `account_key` == keccak(address)
2802    pub async fn prove_account_at(
2803        &self,
2804        address: Address,
2805        keys: Vec<B256>,
2806        block_request: Option<BlockRequest>,
2807    ) -> Result<AccountProof, BlockchainError> {
2808        let block_number = block_request.as_ref().map(|r| r.block_number());
2809
2810        self.with_database_at(block_request, |block_db, _| {
2811            trace!(target: "backend", "get proof for {:?} at {:?}", address, block_number);
2812            let db = block_db.maybe_as_full_db().ok_or(BlockchainError::DataUnavailable)?;
2813            let account = db.get(&address).cloned().unwrap_or_default();
2814
2815            let mut builder = HashBuilder::default()
2816                .with_proof_retainer(ProofRetainer::new(vec![Nibbles::unpack(keccak256(address))]));
2817
2818            for (key, account) in trie_accounts(db) {
2819                builder.add_leaf(key, &account);
2820            }
2821
2822            let _ = builder.root();
2823
2824            let proof = builder
2825                .take_proof_nodes()
2826                .into_nodes_sorted()
2827                .into_iter()
2828                .map(|(_, v)| v)
2829                .collect();
2830            let storage_proofs = prove_storage(&account.storage, &keys);
2831
2832            let account_proof = AccountProof {
2833                address,
2834                balance: account.info.balance,
2835                nonce: account.info.nonce,
2836                code_hash: account.info.code_hash,
2837                storage_hash: storage_root(&account.storage),
2838                account_proof: proof,
2839                storage_proof: keys
2840                    .into_iter()
2841                    .zip(storage_proofs)
2842                    .map(|(key, proof)| {
2843                        let storage_key: U256 = key.into();
2844                        let value = account.storage.get(&storage_key).cloned().unwrap_or_default();
2845                        StorageProof { key: JsonStorageKey::Hash(key), value, proof }
2846                    })
2847                    .collect(),
2848            };
2849
2850            Ok(account_proof)
2851        })
2852        .await?
2853    }
2854
2855    /// Returns a new block event stream
2856    pub fn new_block_notifications(&self) -> NewBlockNotifications {
2857        let (tx, rx) = unbounded();
2858        self.new_block_listeners.lock().push(tx);
2859        trace!(target: "backed", "added new block listener");
2860        rx
2861    }
2862
2863    /// Notifies all `new_block_listeners` about the new block
2864    fn notify_on_new_block(&self, header: Header, hash: B256) {
2865        // cleanup closed notification streams first, if the channel is closed we can remove the
2866        // sender half for the set
2867        self.new_block_listeners.lock().retain(|tx| !tx.is_closed());
2868
2869        let notification = NewBlockNotification { hash, header: Arc::new(header) };
2870
2871        self.new_block_listeners
2872            .lock()
2873            .retain(|tx| tx.unbounded_send(notification.clone()).is_ok());
2874    }
2875
2876    /// Reorg the chain to a common height and execute blocks to build new chain.
2877    ///
2878    /// The state of the chain is rewound using `rewind` to the common block, including the db,
2879    /// storage, and env.
2880    ///
2881    /// Finally, `do_mine_block` is called to create the new chain.
2882    pub async fn reorg(
2883        &self,
2884        depth: u64,
2885        tx_pairs: HashMap<u64, Vec<Arc<PoolTransaction>>>,
2886        common_block: Block,
2887    ) -> Result<(), BlockchainError> {
2888        self.rollback(common_block).await?;
2889        // Create the new reorged chain, filling the blocks with transactions if supplied
2890        for i in 0..depth {
2891            let to_be_mined = tx_pairs.get(&i).cloned().unwrap_or_else(Vec::new);
2892            let outcome = self.do_mine_block(to_be_mined).await;
2893            node_info!(
2894                "    Mined reorg block number {}. With {} valid txs and with invalid {} txs",
2895                outcome.block_number,
2896                outcome.included.len(),
2897                outcome.invalid.len()
2898            );
2899        }
2900
2901        Ok(())
2902    }
2903
2904    /// Rollback the chain to a common height.
2905    ///
2906    /// The state of the chain is rewound using `rewind` to the common block, including the db,
2907    /// storage, and env.
2908    pub async fn rollback(&self, common_block: Block) -> Result<(), BlockchainError> {
2909        // Get the database at the common block
2910        let common_state = {
2911            let mut state = self.states.write();
2912            let state_db = state
2913                .get(&common_block.header.hash_slow())
2914                .ok_or(BlockchainError::DataUnavailable)?;
2915            let db_full = state_db.maybe_as_full_db().ok_or(BlockchainError::DataUnavailable)?;
2916            db_full.clone()
2917        };
2918
2919        {
2920            // Set state to common state
2921            self.db.write().await.clear();
2922            for (address, acc) in common_state {
2923                for (key, value) in acc.storage {
2924                    self.db.write().await.set_storage_at(address, key.into(), value.into())?;
2925                }
2926                self.db.write().await.insert_account(address, acc.info);
2927            }
2928        }
2929
2930        {
2931            // Unwind the storage back to the common ancestor
2932            self.blockchain
2933                .storage
2934                .write()
2935                .unwind_to(common_block.header.number, common_block.header.hash_slow());
2936
2937            // Set environment back to common block
2938            let mut env = self.env.write();
2939            env.block.number = U256::from(common_block.header.number);
2940            env.block.timestamp = U256::from(common_block.header.timestamp);
2941            env.block.gas_limit = U256::from(common_block.header.gas_limit);
2942            env.block.difficulty = common_block.header.difficulty;
2943            env.block.prevrandao = Some(common_block.header.mix_hash);
2944
2945            self.time.reset(env.block.timestamp.to::<u64>());
2946        }
2947        Ok(())
2948    }
2949}
2950
2951/// Get max nonce from transaction pool by address
2952fn get_pool_transactions_nonce(
2953    pool_transactions: &[Arc<PoolTransaction>],
2954    address: Address,
2955) -> Option<u64> {
2956    if let Some(highest_nonce) = pool_transactions
2957        .iter()
2958        .filter(|tx| *tx.pending_transaction.sender() == address)
2959        .map(|tx| tx.pending_transaction.nonce())
2960        .max()
2961    {
2962        let tx_count = highest_nonce.saturating_add(1);
2963        return Some(tx_count)
2964    }
2965    None
2966}
2967
2968#[async_trait::async_trait]
2969impl TransactionValidator for Backend {
2970    async fn validate_pool_transaction(
2971        &self,
2972        tx: &PendingTransaction,
2973    ) -> Result<(), BlockchainError> {
2974        let address = *tx.sender();
2975        let account = self.get_account(address).await?;
2976        let env = self.next_env();
2977        Ok(self.validate_pool_transaction_for(tx, &account, &env)?)
2978    }
2979
2980    fn validate_pool_transaction_for(
2981        &self,
2982        pending: &PendingTransaction,
2983        account: &AccountInfo,
2984        env: &EnvWithHandlerCfg,
2985    ) -> Result<(), InvalidTransactionError> {
2986        let tx = &pending.transaction;
2987
2988        if let Some(tx_chain_id) = tx.chain_id() {
2989            let chain_id = self.chain_id();
2990            if chain_id.to::<u64>() != tx_chain_id {
2991                if let Some(legacy) = tx.as_legacy() {
2992                    // <https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md>
2993                    if env.handler_cfg.spec_id >= SpecId::SPURIOUS_DRAGON &&
2994                        legacy.tx().chain_id.is_none()
2995                    {
2996                        warn!(target: "backend", ?chain_id, ?tx_chain_id, "incompatible EIP155-based V");
2997                        return Err(InvalidTransactionError::IncompatibleEIP155);
2998                    }
2999                } else {
3000                    warn!(target: "backend", ?chain_id, ?tx_chain_id, "invalid chain id");
3001                    return Err(InvalidTransactionError::InvalidChainId);
3002                }
3003            }
3004        }
3005
3006        if tx.gas_limit() < MIN_TRANSACTION_GAS as u64 {
3007            warn!(target: "backend", "[{:?}] gas too low", tx.hash());
3008            return Err(InvalidTransactionError::GasTooLow);
3009        }
3010
3011        // Check gas limit, iff block gas limit is set.
3012        if !env.cfg.disable_block_gas_limit && tx.gas_limit() > env.block.gas_limit.to::<u64>() {
3013            warn!(target: "backend", "[{:?}] gas too high", tx.hash());
3014            return Err(InvalidTransactionError::GasTooHigh(ErrDetail {
3015                detail: String::from("tx.gas_limit > env.block.gas_limit"),
3016            }));
3017        }
3018
3019        // check nonce
3020        let is_deposit_tx =
3021            matches!(&pending.transaction.transaction, TypedTransaction::Deposit(_));
3022        let nonce = tx.nonce();
3023        if nonce < account.nonce && !is_deposit_tx {
3024            warn!(target: "backend", "[{:?}] nonce too low", tx.hash());
3025            return Err(InvalidTransactionError::NonceTooLow);
3026        }
3027
3028        if (env.handler_cfg.spec_id as u8) >= (SpecId::LONDON as u8) {
3029            if tx.gas_price() < env.block.basefee.to::<u128>() && !is_deposit_tx {
3030                warn!(target: "backend", "max fee per gas={}, too low, block basefee={}",tx.gas_price(),  env.block.basefee);
3031                return Err(InvalidTransactionError::FeeCapTooLow);
3032            }
3033
3034            if let (Some(max_priority_fee_per_gas), Some(max_fee_per_gas)) =
3035                (tx.essentials().max_priority_fee_per_gas, tx.essentials().max_fee_per_gas)
3036            {
3037                if max_priority_fee_per_gas > max_fee_per_gas {
3038                    warn!(target: "backend", "max priority fee per gas={}, too high, max fee per gas={}", max_priority_fee_per_gas, max_fee_per_gas);
3039                    return Err(InvalidTransactionError::TipAboveFeeCap);
3040                }
3041            }
3042        }
3043
3044        // EIP-4844 Cancun hard fork validation steps
3045        if env.spec_id() >= SpecId::CANCUN && tx.transaction.is_eip4844() {
3046            // Light checks first: see if the blob fee cap is too low.
3047            if let Some(max_fee_per_blob_gas) = tx.essentials().max_fee_per_blob_gas {
3048                if let Some(blob_gas_and_price) = &env.block.blob_excess_gas_and_price {
3049                    if max_fee_per_blob_gas < blob_gas_and_price.blob_gasprice {
3050                        warn!(target: "backend", "max fee per blob gas={}, too low, block blob gas price={}", max_fee_per_blob_gas, blob_gas_and_price.blob_gasprice);
3051                        return Err(InvalidTransactionError::BlobFeeCapTooLow);
3052                    }
3053                }
3054            }
3055
3056            // Heavy (blob validation) checks
3057            let tx = match &tx.transaction {
3058                TypedTransaction::EIP4844(tx) => tx.tx(),
3059                _ => unreachable!(),
3060            };
3061
3062            let blob_count = tx.tx().blob_versioned_hashes.len();
3063
3064            // Ensure there are blob hashes.
3065            if blob_count == 0 {
3066                return Err(InvalidTransactionError::NoBlobHashes)
3067            }
3068
3069            // Ensure the tx does not exceed the max blobs per block.
3070            if blob_count > MAX_BLOBS_PER_BLOCK {
3071                return Err(InvalidTransactionError::TooManyBlobs(blob_count))
3072            }
3073
3074            // Check for any blob validation errors if not impersonating.
3075            if !self.skip_blob_validation(Some(*pending.sender())) {
3076                if let Err(err) = tx.validate(env.cfg.kzg_settings.get()) {
3077                    return Err(InvalidTransactionError::BlobTransactionValidationError(err))
3078                }
3079            }
3080        }
3081
3082        let max_cost = tx.max_cost();
3083        let value = tx.value();
3084
3085        match &tx.transaction {
3086            TypedTransaction::Deposit(deposit_tx) => {
3087                // Deposit transactions
3088                // https://specs.optimism.io/protocol/deposits.html#execution
3089                // 1. no gas cost check required since already have prepaid gas from L1
3090                // 2. increment account balance by deposited amount before checking for sufficient
3091                //    funds `tx.value <= existing account value + deposited value`
3092                if value > account.balance + deposit_tx.mint {
3093                    warn!(target: "backend", "[{:?}] insufficient balance={}, required={} account={:?}", tx.hash(), account.balance + deposit_tx.mint, value, *pending.sender());
3094                    return Err(InvalidTransactionError::InsufficientFunds);
3095                }
3096            }
3097            _ => {
3098                // check sufficient funds: `gas * price + value`
3099                let req_funds = max_cost.checked_add(value.to()).ok_or_else(|| {
3100                    warn!(target: "backend", "[{:?}] cost too high", tx.hash());
3101                    InvalidTransactionError::InsufficientFunds
3102                })?;
3103                if account.balance < U256::from(req_funds) {
3104                    warn!(target: "backend", "[{:?}] insufficient allowance={}, required={} account={:?}", tx.hash(), account.balance, req_funds, *pending.sender());
3105                    return Err(InvalidTransactionError::InsufficientFunds);
3106                }
3107            }
3108        }
3109
3110        Ok(())
3111    }
3112
3113    fn validate_for(
3114        &self,
3115        tx: &PendingTransaction,
3116        account: &AccountInfo,
3117        env: &EnvWithHandlerCfg,
3118    ) -> Result<(), InvalidTransactionError> {
3119        self.validate_pool_transaction_for(tx, account, env)?;
3120        if tx.nonce() > account.nonce {
3121            return Err(InvalidTransactionError::NonceTooHigh);
3122        }
3123        Ok(())
3124    }
3125}
3126
3127/// Creates a `AnyRpcTransaction` as it's expected for the `eth` RPC api from storage data
3128pub fn transaction_build(
3129    tx_hash: Option<B256>,
3130    eth_transaction: MaybeImpersonatedTransaction,
3131    block: Option<&Block>,
3132    info: Option<TransactionInfo>,
3133    base_fee: Option<u64>,
3134) -> AnyRpcTransaction {
3135    if let TypedTransaction::Deposit(ref deposit_tx) = eth_transaction.transaction {
3136        let DepositTransaction {
3137            nonce,
3138            source_hash,
3139            from: deposit_from,
3140            kind,
3141            mint,
3142            gas_limit,
3143            is_system_tx,
3144            input,
3145            value,
3146        } = deposit_tx.clone();
3147
3148        let dep_tx = TxDeposit {
3149            source_hash,
3150            input,
3151            from: deposit_from,
3152            mint: Some(mint.to()),
3153            to: kind,
3154            is_system_transaction: is_system_tx,
3155            value,
3156            gas_limit,
3157        };
3158
3159        let ser = serde_json::to_value(&dep_tx).expect("could not serialize TxDeposit");
3160        let maybe_deposit_fields = OtherFields::try_from(ser);
3161
3162        match maybe_deposit_fields {
3163            Ok(mut fields) => {
3164                // Add zeroed signature fields for backwards compatibility
3165                // https://specs.optimism.io/protocol/deposits.html#the-deposited-transaction-type
3166                fields.insert("v".to_string(), serde_json::to_value("0x0").unwrap());
3167                fields.insert("r".to_string(), serde_json::to_value(B256::ZERO).unwrap());
3168                fields.insert(String::from("s"), serde_json::to_value(B256::ZERO).unwrap());
3169                fields.insert(
3170                    String::from("nonce"),
3171                    serde_json::to_value(format!("0x{nonce}")).unwrap(),
3172                );
3173
3174                let inner = UnknownTypedTransaction {
3175                    ty: AnyTxType(DEPOSIT_TX_TYPE_ID),
3176                    fields,
3177                    memo: Default::default(),
3178                };
3179
3180                let envelope = AnyTxEnvelope::Unknown(UnknownTxEnvelope {
3181                    hash: eth_transaction.hash(),
3182                    inner,
3183                });
3184
3185                let tx = Transaction {
3186                    inner: Recovered::new_unchecked(envelope, deposit_from),
3187                    block_hash: block
3188                        .as_ref()
3189                        .map(|block| B256::from(keccak256(alloy_rlp::encode(&block.header)))),
3190                    block_number: block.as_ref().map(|block| block.header.number),
3191                    transaction_index: info.as_ref().map(|info| info.transaction_index),
3192                    effective_gas_price: None,
3193                };
3194
3195                return AnyRpcTransaction::from(WithOtherFields::new(tx));
3196            }
3197            Err(_) => {
3198                error!(target: "backend", "failed to serialize deposit transaction");
3199            }
3200        }
3201    }
3202
3203    let mut transaction: Transaction = eth_transaction.clone().into();
3204
3205    let effective_gas_price = if !eth_transaction.is_dynamic_fee() {
3206        transaction.effective_gas_price(base_fee)
3207    } else if block.is_none() && info.is_none() {
3208        // transaction is not mined yet, gas price is considered just `max_fee_per_gas`
3209        transaction.max_fee_per_gas()
3210    } else {
3211        // if transaction is already mined, gas price is considered base fee + priority
3212        // fee: the effective gas price.
3213        let base_fee = base_fee.map_or(0u128, |g| g as u128);
3214        let max_priority_fee_per_gas = transaction.max_priority_fee_per_gas().unwrap_or(0);
3215
3216        base_fee.saturating_add(max_priority_fee_per_gas)
3217    };
3218
3219    transaction.effective_gas_price = Some(effective_gas_price);
3220
3221    let envelope = transaction.inner;
3222
3223    // if a specific hash was provided we update the transaction's hash
3224    // This is important for impersonated transactions since they all use the
3225    // `BYPASS_SIGNATURE` which would result in different hashes
3226    // Note: for impersonated transactions this only concerns pending transactions because
3227    // there's // no `info` yet.
3228    let hash = tx_hash.unwrap_or(*envelope.tx_hash());
3229
3230    let envelope = match envelope.into_inner() {
3231        TxEnvelope::Legacy(signed_tx) => {
3232            let (t, sig, _) = signed_tx.into_parts();
3233            let new_signed = Signed::new_unchecked(t, sig, hash);
3234            AnyTxEnvelope::Ethereum(TxEnvelope::Legacy(new_signed))
3235        }
3236        TxEnvelope::Eip1559(signed_tx) => {
3237            let (t, sig, _) = signed_tx.into_parts();
3238            let new_signed = Signed::new_unchecked(t, sig, hash);
3239            AnyTxEnvelope::Ethereum(TxEnvelope::Eip1559(new_signed))
3240        }
3241        TxEnvelope::Eip2930(signed_tx) => {
3242            let (t, sig, _) = signed_tx.into_parts();
3243            let new_signed = Signed::new_unchecked(t, sig, hash);
3244            AnyTxEnvelope::Ethereum(TxEnvelope::Eip2930(new_signed))
3245        }
3246        TxEnvelope::Eip4844(signed_tx) => {
3247            let (t, sig, _) = signed_tx.into_parts();
3248            let new_signed = Signed::new_unchecked(t, sig, hash);
3249            AnyTxEnvelope::Ethereum(TxEnvelope::Eip4844(new_signed))
3250        }
3251        TxEnvelope::Eip7702(signed_tx) => {
3252            let (t, sig, _) = signed_tx.into_parts();
3253            let new_signed = Signed::new_unchecked(t, sig, hash);
3254            AnyTxEnvelope::Ethereum(TxEnvelope::Eip7702(new_signed))
3255        }
3256    };
3257
3258    let tx = Transaction {
3259        inner: Recovered::new_unchecked(
3260            envelope,
3261            eth_transaction.recover().expect("can recover signed tx"),
3262        ),
3263        block_hash: block
3264            .as_ref()
3265            .map(|block| B256::from(keccak256(alloy_rlp::encode(&block.header)))),
3266        block_number: block.as_ref().map(|block| block.header.number),
3267        transaction_index: info.as_ref().map(|info| info.transaction_index),
3268        // deprecated
3269        effective_gas_price: Some(effective_gas_price),
3270    };
3271    AnyRpcTransaction::from(WithOtherFields::new(tx))
3272}
3273
3274/// Prove a storage key's existence or nonexistence in the account's storage trie.
3275///
3276/// `storage_key` is the hash of the desired storage key, meaning
3277/// this will only work correctly under a secure trie.
3278/// `storage_key` == keccak(key)
3279pub fn prove_storage(storage: &HashMap<U256, U256>, keys: &[B256]) -> Vec<Vec<Bytes>> {
3280    let keys: Vec<_> = keys.iter().map(|key| Nibbles::unpack(keccak256(key))).collect();
3281
3282    let mut builder = HashBuilder::default().with_proof_retainer(ProofRetainer::new(keys.clone()));
3283
3284    for (key, value) in trie_storage(storage) {
3285        builder.add_leaf(key, &value);
3286    }
3287
3288    let _ = builder.root();
3289
3290    let mut proofs = Vec::new();
3291    let all_proof_nodes = builder.take_proof_nodes();
3292
3293    for proof_key in keys {
3294        // Iterate over all proof nodes and find the matching ones.
3295        // The filtered results are guaranteed to be in order.
3296        let matching_proof_nodes =
3297            all_proof_nodes.matching_nodes_sorted(&proof_key).into_iter().map(|(_, node)| node);
3298        proofs.push(matching_proof_nodes.collect());
3299    }
3300
3301    proofs
3302}
3303
3304pub fn is_arbitrum(chain_id: u64) -> bool {
3305    if let Ok(chain) = NamedChain::try_from(chain_id) {
3306        return chain.is_arbitrum()
3307    }
3308    false
3309}