anvil/eth/backend/mem/
mod.rs

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