anvil/eth/backend/mem/
mod.rs

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