Skip to main content

anvil/eth/
api.rs

1use super::{
2    backend::mem::{
3        BlockRequest, DatabaseRef, GasEstimateCallOptions, MonadReplayContext,
4        sanitize_simulation_blocks,
5    },
6    preserve_simulation_request_fields,
7    tempo_consensus::{TempoCertifiedBlock, TempoConsensusState},
8};
9use crate::{
10    ClientFork, LoggingManager, Miner, MiningMode, StorageInfo,
11    eth::{
12        backend::{
13            self, db::SerializableState, mem::MIN_TRANSACTION_GAS,
14            notifications::ChainNotifications, tempo_consensus::TempoConsensusIdentity,
15            validate::TransactionValidator,
16        },
17        error::{
18            BlockchainError, FeeHistoryError, InvalidTransactionError, Result, ToRpcResponseResult,
19        },
20        fees::{
21            FeeDetails, FeeHistoryCache, FeeHistoryCacheItem, MIN_SUGGESTED_PRIORITY_FEE,
22            REWARD_PERCENTILE_RESOLUTION, create_fee_history_cache_item,
23        },
24        macros::node_info,
25        miner::FixedBlockTimeMiner,
26        pool::{
27            Pool, PoolSnapshot,
28            transactions::{
29                PoolTransaction, TransactionOrder, TransactionPriority, TxMarker, to_marker,
30            },
31        },
32        sign::Signer,
33    },
34    filter::{EthFilter, Filters, LogsFilter},
35    mem::transaction_build,
36};
37use alloy_consensus::{
38    Blob, BlockHeader, Transaction, TrieAccount, TxEip4844Variant, TxReceipt, Typed2718,
39    transaction::{Recovered, SignerRecoverable},
40};
41use alloy_dyn_abi::TypedData;
42use alloy_eips::{
43    eip2718::{EIP4844_TX_TYPE_ID, Encodable2718},
44    eip4844::DATA_GAS_PER_BLOB,
45    eip7910::{EthConfig, EthForkConfig},
46};
47use alloy_evm::overrides::{OverrideBlockHashes, apply_state_overrides};
48use alloy_network::{
49    AnyRpcBlock, AnyRpcHeader, AnyRpcTransaction, BlockResponse, Network,
50    NetworkTransactionBuilder, ReceiptResponse, TransactionBuilder, TransactionBuilder4844,
51    TransactionResponse, eip2718::Decodable2718,
52};
53use alloy_primitives::{
54    Address, B64, B256, Bytes, TxHash, TxKind, U64, U256,
55    map::{AddressSet, B256Set, HashMap, HashSet},
56};
57use alloy_rlp::{Encodable, Header, PayloadView};
58use alloy_rpc_types::{
59    AccessListResult, BlockId, BlockNumberOrTag as BlockNumber, BlockTransactions,
60    EIP1186AccountProofResponse, FeeHistory, Filter, FilteredParams, Index, Log, Work,
61    anvil::{
62        ForkedNetwork, Forking, Metadata, MineOptions, NodeEnvironment, NodeForkConfig, NodeInfo,
63    },
64    debug::ExecutionWitness,
65    erc4337::TransactionConditional,
66    pubsub::TransactionReceiptsParams,
67    request::TransactionRequest,
68    simulate::{MAX_SIMULATE_BLOCKS, SimulatePayload, SimulatedBlock},
69    state::{AccountOverride, EvmOverrides, StateOverride, StateOverridesBuilder},
70    trace::{
71        filter::TraceFilter,
72        geth::{GethDebugTracingCallOptions, GethDebugTracingOptions, GethTrace, TraceResult},
73        opcode::{BlockOpcodeGas, TransactionOpcodeGas},
74        parity::{
75            LocalizedTransactionTrace, TraceResults, TraceResultsWithTransactionHash, TraceType,
76        },
77    },
78    txpool::{TxpoolContent, TxpoolContentFrom, TxpoolInspect, TxpoolInspectSummary, TxpoolStatus},
79};
80use alloy_rpc_types_eth::{AccountInfo, Bundle, EthCallResponse, FillTransaction, StateContext};
81use alloy_rpc_types_mev::{EthCallBundle, EthCallBundleResponse};
82use alloy_serde::WithOtherFields;
83use alloy_sol_types::{SolCall, SolValue, sol};
84use anvil_core::{
85    eth::{
86        EthRequest, TempoConsensusQuery,
87        block::{Block, BlockInfo, canonical_block},
88        transaction::{MaybeImpersonatedTransaction, PendingTransaction},
89    },
90    types::{NodeBlobParams, ReorgOptions, TransactionData},
91};
92use anvil_rpc::{
93    error::{ErrorCode, RpcError},
94    response::ResponseResult,
95};
96use foundry_common::{
97    provider::redact_url,
98    tempo::{PaymentLaneClassification, PaymentLaneReason, classify_payment_lane},
99    version::{COMMIT_SHA, SEMVER_VERSION},
100};
101use foundry_evm::{decode::RevertDecoder, utils::StateChangeset};
102use foundry_primitives::{
103    FoundryNetwork, FoundryReceiptEnvelope, FoundryTransactionRequest, FoundryTxEnvelope,
104    FoundryTxReceipt, FoundryTypedTx,
105};
106use futures::{
107    StreamExt, TryFutureExt,
108    channel::{mpsc::Receiver, oneshot},
109};
110use parking_lot::{Mutex, RwLock};
111use revm::{
112    context::BlockEnv,
113    context_interface::{
114        block::BlobExcessGasAndPrice,
115        result::{HaltReason, Output},
116    },
117    database::CacheDB,
118    interpreter::{InstructionResult, SuccessOrHalt, return_ok, return_revert},
119};
120use std::{sync::Arc, time::Duration};
121use tempo_hardfork::TempoHardfork;
122use tempo_primitives::{AASigned, TEMPO_TX_TYPE_ID, transaction::FEE_PAYER_SIGNATURE_MARKER};
123use tokio::{
124    sync::mpsc::{self, UnboundedReceiver, unbounded_channel},
125    try_join,
126};
127
128#[cfg(feature = "base")]
129use base_common_consensus::Eip8130Constants;
130#[cfg(feature = "base")]
131use base_common_evm::EIP8130_TRANSACTION_TYPE;
132#[cfg(feature = "base")]
133use base_common_precompiles::NonceManagerStorage;
134#[cfg(feature = "base")]
135use base_common_rpc_types::{BaseTransactionRequest, Eip8130Nonce};
136#[cfg(feature = "base")]
137use base_execution_eip8130::{FeeCheck, IntrinsicGas};
138
139/// The client version: `anvil/v{major}.{minor}.{patch}`
140pub const CLIENT_VERSION: &str = concat!("anvil/v", env!("CARGO_PKG_VERSION"));
141
142#[derive(Clone, Copy)]
143struct TransactionFeeDefaults {
144    gas_price: u128,
145    blob_gas_price: u128,
146}
147
148/// The entry point for executing eth api RPC call - The Eth RPC interface.
149///
150/// This type is cheap to clone and can be used concurrently
151pub struct EthApi<N: Network> {
152    /// The transaction pool
153    pool: Arc<Pool<N::TxEnvelope>>,
154    /// Transaction pool state captured by `evm_snapshot`.
155    pool_snapshots: Arc<Mutex<HashMap<U256, PoolSnapshot<N::TxEnvelope>>>>,
156    /// Holds all blockchain related data
157    /// In-Memory only for now
158    pub backend: Arc<backend::mem::Backend<N>>,
159    /// Whether this node is mining
160    is_mining: bool,
161    /// available signers
162    signers: Arc<Vec<Box<dyn Signer<N>>>>,
163    /// data required for `eth_feeHistory`
164    fee_history_cache: FeeHistoryCache,
165    /// max number of items kept in fee cache
166    fee_history_limit: u64,
167    /// access to the actual miner
168    ///
169    /// This access is required in order to adjust miner settings based on requests received from
170    /// custom RPC endpoints
171    miner: Miner<N::TxEnvelope>,
172    /// allows to enabled/disable logging
173    logger: LoggingManager,
174    /// Tracks all active filters
175    filters: Filters<N>,
176    /// How transactions are ordered in the pool
177    transaction_order: Arc<RwLock<TransactionOrder>>,
178    /// Whether we're listening for RPC calls
179    net_listening: bool,
180    /// The instance ID. Changes on every reset.
181    instance_id: Arc<RwLock<B256>>,
182    /// Serializes endpoint identity reads with reset transitions.
183    lifecycle_lock: Arc<tokio::sync::RwLock<()>>,
184    /// Serializes reset preparation without blocking identity RPCs made by the target endpoint.
185    reset_lock: Arc<tokio::sync::Mutex<()>>,
186    /// Serializes automatic nonce assignment through pool insertion for each sender.
187    nonce_locks: Arc<RwLock<HashMap<Address, Arc<tokio::sync::Mutex<()>>>>>,
188}
189
190impl<N: Network> Clone for EthApi<N> {
191    fn clone(&self) -> Self {
192        Self {
193            pool: self.pool.clone(),
194            pool_snapshots: self.pool_snapshots.clone(),
195            backend: self.backend.clone(),
196            is_mining: self.is_mining,
197            signers: self.signers.clone(),
198            fee_history_cache: self.fee_history_cache.clone(),
199            fee_history_limit: self.fee_history_limit,
200            miner: self.miner.clone(),
201            logger: self.logger.clone(),
202            filters: self.filters.clone(),
203            transaction_order: self.transaction_order.clone(),
204            net_listening: self.net_listening,
205            instance_id: self.instance_id.clone(),
206            lifecycle_lock: self.lifecycle_lock.clone(),
207            reset_lock: self.reset_lock.clone(),
208            nonce_locks: self.nonce_locks.clone(),
209        }
210    }
211}
212
213// == impl EthApi<N: Network> generic methods ==
214
215impl<N: Network> EthApi<N> {
216    /// Creates a new instance
217    #[expect(clippy::too_many_arguments)]
218    pub fn new(
219        pool: Arc<Pool<N::TxEnvelope>>,
220        backend: Arc<backend::mem::Backend<N>>,
221        signers: Arc<Vec<Box<dyn Signer<N>>>>,
222        fee_history_cache: FeeHistoryCache,
223        fee_history_limit: u64,
224        miner: Miner<N::TxEnvelope>,
225        logger: LoggingManager,
226        filters: Filters<N>,
227        transactions_order: TransactionOrder,
228    ) -> Self {
229        Self {
230            pool,
231            pool_snapshots: Arc::new(Mutex::new(HashMap::default())),
232            backend,
233            is_mining: true,
234            signers,
235            fee_history_cache,
236            fee_history_limit,
237            miner,
238            logger,
239            filters,
240            net_listening: true,
241            transaction_order: Arc::new(RwLock::new(transactions_order)),
242            instance_id: Arc::new(RwLock::new(B256::random())),
243            lifecycle_lock: Arc::new(tokio::sync::RwLock::new(())),
244            reset_lock: Arc::new(tokio::sync::Mutex::new(())),
245            nonce_locks: Default::default(),
246        }
247    }
248
249    /// Returns the current gas price
250    pub fn gas_price(&self) -> u128 {
251        self.gas_price_for_base_fee(self.backend.base_fee())
252    }
253
254    /// Returns the gas price for a block with the given base fee.
255    fn gas_price_for_base_fee(&self, base_fee: u64) -> u128 {
256        if self.backend.is_eip1559() {
257            if self.backend.is_min_priority_fee_enforced() {
258                (base_fee as u128).saturating_add(self.lowest_suggestion_tip())
259            } else {
260                base_fee as u128
261            }
262        } else {
263            self.backend.fees().raw_gas_price()
264        }
265    }
266
267    /// Returns the suggested fee cap.
268    ///
269    /// Returns at least [MIN_SUGGESTED_PRIORITY_FEE]
270    fn lowest_suggestion_tip(&self) -> u128 {
271        let block_number = self.backend.best_number();
272        let cache = self.fee_history_cache.lock();
273        let latest_tip = self
274            .backend
275            .get_block_with_hash(block_number)
276            .and_then(|(_, hash)| cache.get(&block_number).filter(|item| item.block_hash == hash))
277            .and_then(|item| item.rewards.iter().copied().min());
278
279        latest_tip
280            .or_else(|| {
281                cache
282                    .iter()
283                    .filter(|(number, item)| {
284                        self.backend
285                            .get_block_with_hash(**number)
286                            .is_some_and(|(_, hash)| item.block_hash == hash)
287                    })
288                    .flat_map(|(_, item)| item.rewards.iter().copied())
289                    .min()
290            })
291            .map(|fee| fee.max(MIN_SUGGESTED_PRIORITY_FEE))
292            .unwrap_or(MIN_SUGGESTED_PRIORITY_FEE)
293    }
294
295    /// Returns true if auto mining is enabled, and false.
296    ///
297    /// Handler for ETH RPC call: `anvil_getAutomine`
298    pub fn anvil_get_auto_mine(&self) -> Result<bool> {
299        node_info!("anvil_getAutomine");
300        Ok(self.miner.is_auto_mine())
301    }
302
303    /// Returns the value of mining interval, if set.
304    ///
305    /// Handler for ETH RPC call: `anvil_getIntervalMining`.
306    pub fn anvil_get_interval_mining(&self) -> Result<Option<u64>> {
307        node_info!("anvil_getIntervalMining");
308        Ok(self.miner.get_interval())
309    }
310
311    /// Enables or disables, based on the single boolean argument, the automatic mining of new
312    /// blocks with each new transaction submitted to the network.
313    ///
314    /// Handler for ETH RPC call: `evm_setAutomine`
315    pub async fn anvil_set_auto_mine(&self, enable_automine: bool) -> Result<()> {
316        node_info!("evm_setAutomine");
317        if self.miner.is_auto_mine() {
318            if enable_automine {
319                return Ok(());
320            }
321            self.miner.set_mining_mode(MiningMode::None);
322        } else if enable_automine {
323            let listener = self.pool.add_ready_listener();
324            let window = self.backend.node_config.read().await.transaction_coalescing_window;
325            let mode = MiningMode::instant(1_000, listener).with_coalescing_window(window);
326            self.miner.set_mining_mode(mode);
327        }
328        Ok(())
329    }
330
331    /// Sets the mining behavior to interval with the given interval (seconds)
332    ///
333    /// Handler for ETH RPC call: `evm_setIntervalMining`
334    pub fn anvil_set_interval_mining(&self, secs: u64) -> Result<()> {
335        node_info!("evm_setIntervalMining");
336        let mining_mode = if secs == 0 {
337            MiningMode::None
338        } else {
339            let block_time = Duration::from_secs(secs);
340
341            // This ensures that memory limits are stricter in interval-mine mode
342            self.backend.update_interval_mine_block_time(block_time);
343
344            MiningMode::FixedBlockTime(FixedBlockTimeMiner::new(block_time))
345        };
346        self.miner.set_mining_mode(mining_mode);
347        Ok(())
348    }
349
350    /// Pauses or resumes automatic block production.
351    ///
352    /// While paused, the block time interval keeps ticking but blocks that come due are skipped,
353    /// so the next block is mined on the first tick after mining resumes. Once this returns with
354    /// `paused` set, no automatic block is mined until mining resumes.
355    ///
356    /// Handler for RPC call: `anvil_setMiningPaused`
357    pub async fn anvil_set_mining_paused(&self, paused: bool) -> Result<()> {
358        node_info!("anvil_setMiningPaused");
359        self.miner.set_paused(paused);
360        if paused {
361            // Wait for a block that is already being mined. Candidates that take the lock after
362            // this are skipped by the mining task.
363            drop(self.backend.lock_mining().await);
364        }
365        Ok(())
366    }
367
368    /// Returns `true` if automatic block production is paused.
369    ///
370    /// Handler for RPC call: `anvil_getMiningPaused`
371    pub fn anvil_get_mining_paused(&self) -> Result<bool> {
372        node_info!("anvil_getMiningPaused");
373        Ok(self.miner.is_paused())
374    }
375
376    /// Removes transactions from the pool
377    ///
378    /// Handler for RPC call: `anvil_dropTransaction`
379    pub async fn anvil_drop_transaction(&self, tx_hash: B256) -> Result<Option<B256>> {
380        node_info!("anvil_dropTransaction");
381        Ok(self.pool.drop_transaction(tx_hash).map(|tx| tx.hash()))
382    }
383
384    /// Removes all transactions from the pool
385    ///
386    /// Handler for RPC call: `anvil_dropAllTransactions`
387    pub async fn anvil_drop_all_transactions(&self) -> Result<()> {
388        node_info!("anvil_dropAllTransactions");
389        self.pool.clear();
390        Ok(())
391    }
392
393    /// Clears all transactions from the pool.
394    ///
395    /// Handler for RPC call: `debug_clearTxpool`
396    pub async fn debug_clear_txpool(&self) -> Result<()> {
397        node_info!("debug_clearTxpool");
398        self.pool.clear();
399        Ok(())
400    }
401
402    pub async fn anvil_set_chain_id(&self, chain_id: u64) -> Result<()> {
403        node_info!("anvil_setChainId");
404        self.backend.set_chain_id(chain_id);
405        #[cfg(feature = "base")]
406        self.invalidate_base_eip8130_pool();
407        Ok(())
408    }
409
410    /// Invalidates EIP-8130 admission state after out-of-band state mutation.
411    #[cfg(feature = "base")]
412    fn invalidate_base_eip8130_pool(&self) {
413        if self.backend.is_base() {
414            let _ = self.pool.clear_transaction_type(EIP8130_TRANSACTION_TYPE);
415        }
416    }
417
418    /// Modifies the balance of an account.
419    ///
420    /// Handler for RPC call: `anvil_setBalance`
421    pub async fn anvil_set_balance(&self, address: Address, balance: U256) -> Result<()> {
422        node_info!("anvil_setBalance");
423        self.backend.set_balance(address, balance).await?;
424        #[cfg(feature = "base")]
425        self.invalidate_base_eip8130_pool();
426        Ok(())
427    }
428
429    /// Sets the code of a contract.
430    ///
431    /// Handler for RPC call: `anvil_setCode`
432    pub async fn anvil_set_code(&self, address: Address, code: Bytes) -> Result<()> {
433        node_info!("anvil_setCode");
434        self.backend.set_code(address, code).await?;
435        #[cfg(feature = "base")]
436        self.invalidate_base_eip8130_pool();
437        Ok(())
438    }
439
440    /// Sets the nonce of an address.
441    ///
442    /// Handler for RPC call: `anvil_setNonce`
443    pub async fn anvil_set_nonce(&self, address: Address, nonce: U256) -> Result<()> {
444        node_info!("anvil_setNonce");
445        self.backend.set_nonce(address, nonce).await?;
446        #[cfg(feature = "base")]
447        self.invalidate_base_eip8130_pool();
448        Ok(())
449    }
450
451    /// Writes a single slot of the account's storage.
452    ///
453    /// Handler for RPC call: `anvil_setStorageAt`
454    pub async fn anvil_set_storage_at(
455        &self,
456        address: Address,
457        slot: U256,
458        val: B256,
459    ) -> Result<bool> {
460        node_info!("anvil_setStorageAt");
461        self.backend.set_storage_at(address, slot, val).await?;
462        #[cfg(feature = "base")]
463        self.invalidate_base_eip8130_pool();
464        Ok(true)
465    }
466
467    /// Enable or disable logging.
468    ///
469    /// Handler for RPC call: `anvil_setLoggingEnabled`
470    pub async fn anvil_set_logging(&self, enable: bool) -> Result<()> {
471        node_info!("anvil_setLoggingEnabled");
472        self.logger.set_enabled(enable);
473        Ok(())
474    }
475
476    /// Set the minimum gas price for the node.
477    ///
478    /// Handler for RPC call: `anvil_setMinGasPrice`
479    pub async fn anvil_set_min_gas_price(&self, gas: U256) -> Result<()> {
480        node_info!("anvil_setMinGasPrice");
481        if self.backend.is_eip1559() {
482            return Err(RpcError::invalid_params(
483                "anvil_setMinGasPrice is not supported when EIP-1559 is active",
484            )
485            .into());
486        }
487        self.backend.set_gas_price(gas.saturating_to());
488        Ok(())
489    }
490
491    /// Sets the base fee of the next block.
492    ///
493    /// Handler for RPC call: `anvil_setNextBlockBaseFeePerGas`
494    pub async fn anvil_set_next_block_base_fee_per_gas(&self, basefee: U256) -> Result<()> {
495        node_info!("anvil_setNextBlockBaseFeePerGas");
496        if !self.backend.is_eip1559() {
497            return Err(RpcError::invalid_params(
498                "anvil_setNextBlockBaseFeePerGas is only supported when EIP-1559 is active",
499            )
500            .into());
501        }
502        self.backend.set_base_fee(basefee.saturating_to());
503        Ok(())
504    }
505
506    /// Sets the coinbase address.
507    ///
508    /// Handler for RPC call: `anvil_setCoinbase`
509    pub async fn anvil_set_coinbase(&self, address: Address) -> Result<()> {
510        node_info!("anvil_setCoinbase");
511        self.backend.set_coinbase(address);
512        Ok(())
513    }
514
515    /// Sets the `prevrandao` value of the next block.
516    ///
517    /// This is a one-shot override: it applies to the next mined block only, after which anvil
518    /// resumes deriving `prevrandao` from the parent hash and block number.
519    ///
520    /// Handler for RPC call: `anvil_setNextBlockPrevRandao`
521    pub async fn anvil_set_next_block_prevrandao(&self, prevrandao: B256) -> Result<()> {
522        node_info!("anvil_setNextBlockPrevRandao");
523        self.backend.set_next_block_prevrandao(prevrandao);
524        Ok(())
525    }
526
527    /// Sets the parent beacon block root of the next block.
528    ///
529    /// This is a one-shot override: it applies to the next mined block only, after which anvil
530    /// resumes using the zero root. From Cancun the root is stored by the EIP-4788 beacon roots
531    /// contract when the block is mined.
532    ///
533    /// Handler for RPC call: `anvil_setNextBlockParentBeaconBlockRoot`
534    pub async fn anvil_set_next_block_parent_beacon_block_root(&self, root: B256) -> Result<()> {
535        node_info!("anvil_setNextBlockParentBeaconBlockRoot");
536        self.backend.set_next_block_parent_beacon_block_root(root);
537        Ok(())
538    }
539
540    /// Retrieves the Anvil node configuration params.
541    ///
542    /// Handler for RPC call: `anvil_nodeInfo`
543    pub async fn anvil_node_info(&self) -> Result<WithOtherFields<NodeInfo>> {
544        node_info!("anvil_nodeInfo");
545        let _lifecycle = self.lifecycle_lock.read().await;
546
547        let evm_env = self.backend.evm_env().read().clone();
548        let fork_config = self.backend.get_fork();
549        let tx_order = self.transaction_order.read();
550        let hard_fork = self.backend.hardfork().name();
551
552        let mut node_info = WithOtherFields::new(NodeInfo {
553            current_block_number: self.backend.best_number(),
554            current_block_timestamp: evm_env.block_env.timestamp.saturating_to(),
555            current_block_hash: self.backend.best_hash(),
556            hard_fork,
557            transaction_order: match *tx_order {
558                TransactionOrder::Fifo => "fifo".to_string(),
559                TransactionOrder::Fees => "fees".to_string(),
560            },
561            environment: NodeEnvironment {
562                base_fee: self.backend.base_fee() as u128,
563                chain_id: self.backend.chain_id().to::<u64>(),
564                gas_limit: self.backend.gas_limit(),
565                gas_price: self.gas_price(),
566            },
567            fork_config: fork_config
568                .map(|fork| {
569                    let config = fork.config.read();
570
571                    NodeForkConfig {
572                        fork_url: config.eth_rpc_url().map(redact_url),
573                        fork_block_number: Some(config.block_number),
574                        fork_retry_backoff: Some(config.backoff.as_millis()),
575                    }
576                })
577                .unwrap_or_default(),
578            // Always emit the execution profile. Older Anvil versions omitted plain Ethereum, so
579            // consumers must still treat `None` as legacy unspecified metadata.
580            network: Some(self.backend.execution_profile_name().to_string()),
581        });
582        // Forks of this node price blobs with these params, which can differ from those of the
583        // reported hardfork when this node is itself a fork.
584        node_info
585            .other
586            .insert_value(
587                "blobParams".to_string(),
588                NodeBlobParams::from(self.backend.blob_params()),
589            )
590            .map_err(|err| BlockchainError::Internal(err.to_string()))?;
591        Ok(node_info)
592    }
593
594    /// Retrieves metadata about the Anvil instance.
595    ///
596    /// Handler for RPC call: `anvil_metadata`
597    pub async fn anvil_metadata(&self) -> Result<Metadata> {
598        node_info!("anvil_metadata");
599        let _lifecycle = self.lifecycle_lock.read().await;
600        let fork_config = self.backend.get_fork();
601
602        Ok(Metadata {
603            client_version: CLIENT_VERSION.to_string(),
604            client_semver: Some(SEMVER_VERSION.to_string()),
605            client_commit_sha: Some(COMMIT_SHA.to_string()),
606            chain_id: self.backend.chain_id().to::<u64>(),
607            latest_block_hash: self.backend.best_hash(),
608            latest_block_number: self.backend.best_number(),
609            instance_id: *self.instance_id.read(),
610            forked_network: fork_config.map(|cfg| ForkedNetwork {
611                chain_id: cfg.chain_id(),
612                fork_block_number: cfg.block_number(),
613                fork_block_hash: cfg.block_hash(),
614            }),
615            snapshots: self.backend.list_state_snapshots(),
616        })
617    }
618
619    pub async fn anvil_remove_pool_transactions(&self, address: Address) -> Result<()> {
620        node_info!("anvil_removePoolTransactions");
621        self.pool.remove_transactions_by_address(address);
622        Ok(())
623    }
624
625    /// Snapshot the state of the blockchain at the current block.
626    ///
627    /// Handler for RPC call: `evm_snapshot`
628    pub async fn evm_snapshot(&self) -> Result<U256> {
629        node_info!("evm_snapshot");
630        let _lifecycle = self.lifecycle_lock.read().await;
631        let _mining = self.backend.lock_mining().await;
632        let pool = self.pool.snapshot();
633        let id = self.backend.create_state_snapshot().await;
634        self.pool_snapshots.lock().insert(id, pool);
635        Ok(id)
636    }
637
638    /// Jump forward in time by the given amount of time, in seconds.
639    ///
640    /// Handler for RPC call: `evm_increaseTime`
641    pub async fn evm_increase_time(&self, seconds: U256) -> Result<i64> {
642        node_info!("evm_increaseTime");
643        Ok(self.backend.time().increase_time(seconds.try_into().unwrap_or(u64::MAX)) as i64)
644    }
645
646    /// Similar to `evm_increaseTime` but takes the exact timestamp that you want in the next block
647    ///
648    /// Handler for RPC call: `evm_setNextBlockTimestamp`
649    pub fn evm_set_next_block_timestamp(&self, seconds: u64) -> Result<()> {
650        node_info!("evm_setNextBlockTimestamp");
651        self.backend.time().set_next_block_timestamp(seconds)
652    }
653
654    /// Sets the specific timestamp and returns the number of seconds between the given timestamp
655    /// and the current time.
656    ///
657    /// The `timestamp` is in seconds. The `evm_setTime` JSON-RPC method accepts both seconds and
658    /// milliseconds (values above 1e12 are treated as milliseconds); the RPC handler normalises
659    /// the input to seconds before calling this function.
660    ///
661    /// Handler for RPC call: `evm_setTime`
662    pub fn evm_set_time(&self, timestamp: u64) -> Result<u64> {
663        node_info!("evm_setTime");
664        let now = self.backend.time().current_wall_timestamp();
665        self.backend.time().set_time(timestamp);
666
667        // number of seconds between the given timestamp and the current time.
668        let offset = timestamp.saturating_sub(now);
669        Ok(offset)
670    }
671
672    /// Set the next block gas limit
673    ///
674    /// Handler for RPC call: `evm_setBlockGasLimit`
675    pub fn evm_set_block_gas_limit(&self, gas_limit: U256) -> Result<bool> {
676        node_info!("evm_setBlockGasLimit");
677        self.backend.set_gas_limit(gas_limit.saturating_to());
678        Ok(true)
679    }
680
681    /// Sets an interval for the block timestamp
682    ///
683    /// Handler for RPC call: `anvil_setBlockTimestampInterval`
684    pub fn evm_set_block_timestamp_interval(&self, seconds: u64) -> Result<()> {
685        node_info!("anvil_setBlockTimestampInterval");
686        self.backend.time().set_block_timestamp_interval(seconds);
687        Ok(())
688    }
689
690    /// Sets an interval for the block timestamp
691    ///
692    /// Handler for RPC call: `anvil_removeBlockTimestampInterval`
693    pub fn evm_remove_block_timestamp_interval(&self) -> Result<bool> {
694        node_info!("anvil_removeBlockTimestampInterval");
695        Ok(self.backend.time().remove_block_timestamp_interval())
696    }
697
698    /// Sets the backend rpc url
699    ///
700    /// Handler for ETH RPC call: `anvil_setRpcUrl`
701    pub async fn anvil_set_rpc_url(&self, url: String) -> Result<()> {
702        node_info!("anvil_setRpcUrl");
703        let _reset = self.reset_lock.lock().await;
704        let staged_fork = if let Some(fork) = self.backend.get_fork() {
705            let mut validation_config = self.backend.node_config.read().await.clone();
706            let (expected_identity, block_number, block_hash) = {
707                let config = fork.config.read();
708                (config.endpoint_identity, config.block_number, config.block_hash)
709            };
710            // A new URL replaces an offline discovery hint. Resolve the actual source identity so
711            // unsupported networks cannot be hidden behind the previous endpoint's hint.
712            validation_config.fork_chain_id = None;
713            let (provider, endpoint_identity) = validation_config
714                .replacement_fork_provider(
715                    &url,
716                    expected_identity,
717                    block_number,
718                    block_hash,
719                    self.instance_id(),
720                )
721                .await?;
722            Some((fork, provider, endpoint_identity))
723        } else {
724            None
725        };
726
727        let _lifecycle = self.lifecycle_lock.write().await;
728        let _mining = self.backend.lock_mining().await;
729        let mut node_config = self.backend.node_config.write().await;
730        if let Some((fork, provider, endpoint_identity)) = staged_fork {
731            let mut config = fork.config.write();
732            trace!(target: "backend", "Updated fork rpc from \"{}\" to \"{}\"", config.eth_rpc_url().map(redact_url).unwrap_or_else(|| "none".to_string()), redact_url(&url));
733            config.provider = provider;
734            config.fork_urls = vec![url.clone()];
735            config.fork_chain_id = None;
736            config.endpoint_identity = endpoint_identity;
737            node_config.fork_endpoint_is_anvil = endpoint_identity.is_authoritative();
738        }
739        // Keep node_config in sync so a subsequent URL-less fork reset uses the updated endpoint.
740        node_config.fork_urls = vec![url];
741        node_config.fork_chain_id = None;
742        Ok(())
743    }
744
745    /// Returns the number of transactions currently pending for inclusion in the next block(s), as
746    /// well as the ones that are being scheduled for future execution only.
747    /// Ref: [Here](https://geth.ethereum.org/docs/rpc/ns-txpool#txpool_status)
748    ///
749    /// Handler for ETH RPC call: `txpool_status`
750    pub async fn txpool_status(&self) -> Result<TxpoolStatus> {
751        node_info!("txpool_status");
752        Ok(self.pool.txpool_status())
753    }
754
755    /// Executes the future on a new blocking task.
756    async fn on_blocking_task<C, F, R>(&self, c: C) -> Result<R>
757    where
758        C: FnOnce(Self) -> F,
759        F: Future<Output = Result<R>> + Send + 'static,
760        R: Send + 'static,
761    {
762        let (tx, rx) = oneshot::channel();
763        let this = self.clone();
764        let f = c(this);
765        tokio::task::spawn_blocking(move || {
766            tokio::runtime::Handle::current().block_on(async move {
767                let res = f.await;
768                let _ = tx.send(res);
769            })
770        });
771        rx.await.map_err(|_| BlockchainError::Internal("blocking task panicked".to_string()))?
772    }
773
774    /// Updates the `TransactionOrder`
775    pub fn set_transaction_order(&self, order: TransactionOrder) {
776        *self.transaction_order.write() = order;
777    }
778
779    /// Returns the chain ID used for transaction
780    pub fn chain_id(&self) -> u64 {
781        self.backend.chain_id().to::<u64>()
782    }
783
784    /// Returns the configured fork, if any.
785    pub fn get_fork(&self) -> Option<ClientFork> {
786        self.backend.get_fork()
787    }
788
789    /// Returns the current instance's ID.
790    pub fn instance_id(&self) -> B256 {
791        *self.instance_id.read()
792    }
793
794    /// Resets the instance ID.
795    pub fn reset_instance_id(&self) {
796        *self.instance_id.write() = B256::random();
797    }
798
799    /// Returns the first signer that can sign for the given address
800    #[expect(clippy::borrowed_box)]
801    pub fn get_signer(&self, address: Address) -> Option<&Box<dyn Signer<N>>> {
802        self.signers.iter().find(|signer| signer.is_signer_for(address))
803    }
804
805    /// Returns a new listeners for ready transactions
806    pub fn new_ready_transactions(&self) -> Receiver<TxHash> {
807        self.pool.add_ready_listener()
808    }
809
810    /// Returns a ready-transaction stream that ends if its bounded listener overflows.
811    pub(crate) fn new_ready_transaction_subscription(&self) -> Receiver<TxHash> {
812        self.pool.add_ready_subscription_listener()
813    }
814
815    /// Returns true if forked
816    pub fn is_fork(&self) -> bool {
817        self.backend.is_fork()
818    }
819
820    /// Returns the current state root
821    pub async fn state_root(&self) -> Option<B256> {
822        self.backend.get_db().read().await.maybe_state_root()
823    }
824
825    /// Returns true if the `addr` is currently impersonated
826    pub fn is_impersonated(&self, addr: Address) -> bool {
827        self.backend.cheats().is_impersonated(addr)
828    }
829
830    /// Returns a new accessor for certain storage elements
831    pub fn storage_info(&self) -> StorageInfo<N> {
832        StorageInfo::new(Arc::clone(&self.backend))
833    }
834
835    /// Handler for RPC call: `anvil_getBlobByHash`
836    #[allow(clippy::large_stack_frames)]
837    pub fn anvil_get_blob_by_versioned_hash(
838        &self,
839        hash: B256,
840    ) -> Result<Option<alloy_consensus::Blob>> {
841        node_info!("anvil_getBlobByHash");
842        Ok(self.backend.get_blob_by_versioned_hash(hash)?)
843    }
844
845    /// Handler for RPC call: `anvil_getBlobsByBlockId`
846    pub fn anvil_get_blobs_by_block_id(
847        &self,
848        block_id: impl Into<BlockId>,
849        versioned_hashes: Vec<B256>,
850    ) -> Result<Option<Vec<Blob>>> {
851        node_info!("anvil_getBlobsByBlockId");
852        Ok(self.backend.get_blobs_by_block_id(block_id, versioned_hashes)?)
853    }
854
855    /// Returns the genesis time for the Beacon chain
856    ///
857    /// Handler for Beacon API call: `GET /eth/v1/beacon/genesis`
858    pub fn anvil_get_genesis_time(&self) -> Result<u64> {
859        node_info!("anvil_getGenesisTime");
860        Ok(self.backend.genesis_time())
861    }
862
863    /// Returns the UNIX wall time in milliseconds when the current head was installed.
864    ///
865    /// Handler for RPC call: `anvil_getLastBlockWallTime`
866    pub fn anvil_get_last_block_wall_time(&self) -> Result<u64> {
867        node_info!("anvil_getLastBlockWallTime");
868        Ok(self.backend.time().last_block_wall_time())
869    }
870
871    /// Reset the fork to a fresh forked state, and optionally update the fork config.
872    ///
873    /// If `forking` is `None` then this will disable forking entirely.
874    ///
875    /// Handler for RPC call: `anvil_reset`
876    pub async fn anvil_reset(&self, forking: Option<Forking>) -> Result<()> {
877        node_info!("anvil_reset");
878        let _reset = self.reset_lock.lock().await;
879        if let Some(forking) = forking {
880            let staged = self.backend.prepare_fork_reset(forking, self.instance_id()).await?;
881            let _lifecycle = self.lifecycle_lock.write().await;
882            // Stop an old-context block before publishing the replacement DB and environment.
883            let _mining = self.backend.lock_mining().await;
884            self.backend.commit_fork_reset(staged).await?;
885            self.reset_instance_id();
886            self.pool.clear();
887            self.pool_snapshots.lock().clear();
888            self.fee_history_cache.lock().clear();
889        } else {
890            let _lifecycle = self.lifecycle_lock.write().await;
891            // Unlike fork preparation, memory preparation snapshots live local fee state and does
892            // no remote I/O. Keep that snapshot and its publication in one lifecycle transition.
893            let _mining = self.backend.lock_mining().await;
894            let staged = self.backend.prepare_memory_reset().await?;
895            self.backend.commit_memory_reset(staged).await?;
896            self.reset_instance_id();
897            self.pool.clear();
898            self.pool_snapshots.lock().clear();
899            self.fee_history_cache.lock().clear();
900        }
901        Ok(())
902    }
903
904    /// Revert the state of the blockchain to a previous snapshot.
905    /// Takes a single parameter, which is the snapshot id to revert to.
906    ///
907    /// Handler for RPC call: `evm_revert`
908    pub async fn evm_revert(&self, id: U256) -> Result<bool>
909    where
910        N::ReceiptEnvelope: TxReceipt<Log = alloy_primitives::Log>,
911    {
912        node_info!("evm_revert");
913        let _lifecycle = self.lifecycle_lock.read().await;
914        let _mining = self.backend.lock_mining().await;
915        let reverted = self.backend.revert_state_snapshot(id).await?;
916        if reverted {
917            let pool = {
918                let mut snapshots = self.pool_snapshots.lock();
919                let pool = snapshots.remove(&id);
920                snapshots.retain(|snapshot_id, _| *snapshot_id < id);
921                pool
922            };
923            if let Some(pool) = pool {
924                self.pool.restore(pool);
925            }
926        }
927        Ok(reverted)
928    }
929
930    /// Send transactions impersonating specific account and contract addresses.
931    ///
932    /// Handler for ETH RPC call: `anvil_impersonateAccount`
933    pub async fn anvil_impersonate_account(&self, address: Address) -> Result<()> {
934        node_info!("anvil_impersonateAccount");
935        self.backend.impersonate(address);
936        Ok(())
937    }
938
939    /// Stops impersonating an account if previously set with `anvil_impersonateAccount`.
940    ///
941    /// Handler for ETH RPC call: `anvil_stopImpersonatingAccount`
942    pub async fn anvil_stop_impersonating_account(&self, address: Address) -> Result<()> {
943        node_info!("anvil_stopImpersonatingAccount");
944        self.backend.stop_impersonating(address);
945        Ok(())
946    }
947
948    /// If set to true will make every account impersonated
949    ///
950    /// Handler for ETH RPC call: `anvil_autoImpersonateAccount`
951    pub async fn anvil_auto_impersonate_account(&self, enabled: bool) -> Result<()> {
952        node_info!("anvil_autoImpersonateAccount");
953        self.backend.auto_impersonate_account(enabled);
954        Ok(())
955    }
956
957    /// Registers a new address and signature pair to impersonate.
958    pub async fn anvil_impersonate_signature(
959        &self,
960        signature: Bytes,
961        address: Address,
962    ) -> Result<()> {
963        node_info!("anvil_impersonateSignature");
964        self.backend.impersonate_signature(signature, address).await
965    }
966
967    /// Returns a new block event stream that yields Notifications when a new block was added or
968    /// when logs were removed from the canonical chain due to a reorg
969    pub fn new_block_notifications(&self) -> ChainNotifications {
970        self.backend.new_block_notifications()
971    }
972
973    /// Returns the current client version.
974    ///
975    /// Handler for ETH RPC call: `web3_clientVersion`
976    pub fn client_version(&self) -> Result<String> {
977        node_info!("web3_clientVersion");
978        Ok(CLIENT_VERSION.to_string())
979    }
980
981    /// Returns Keccak-256 (not the standardized SHA3-256) of the given data.
982    ///
983    /// Handler for ETH RPC call: `web3_sha3`
984    pub fn sha3(&self, bytes: Bytes) -> Result<String> {
985        node_info!("web3_sha3");
986        let hash = alloy_primitives::keccak256(bytes.as_ref());
987        Ok(alloy_primitives::hex::encode_prefixed(&hash[..]))
988    }
989
990    /// Returns protocol version encoded as a string (quotes are necessary).
991    ///
992    /// Handler for ETH RPC call: `eth_protocolVersion`
993    pub fn protocol_version(&self) -> Result<u64> {
994        node_info!("eth_protocolVersion");
995        Ok(1)
996    }
997
998    /// Returns the number of hashes per second that the node is mining with.
999    ///
1000    /// Handler for ETH RPC call: `eth_hashrate`
1001    pub fn hashrate(&self) -> Result<U256> {
1002        node_info!("eth_hashrate");
1003        Ok(U256::ZERO)
1004    }
1005
1006    /// Returns the client coinbase address.
1007    ///
1008    /// Handler for ETH RPC call: `eth_coinbase`
1009    pub fn author(&self) -> Result<Address> {
1010        node_info!("eth_coinbase");
1011        Ok(self.backend.coinbase())
1012    }
1013
1014    /// Returns true if client is actively mining new blocks.
1015    ///
1016    /// Handler for ETH RPC call: `eth_mining`
1017    pub fn is_mining(&self) -> Result<bool> {
1018        node_info!("eth_mining");
1019        Ok(self.is_mining)
1020    }
1021
1022    /// Returns the chain ID used for transaction signing at the
1023    /// current best block. None is returned if not
1024    /// available.
1025    ///
1026    /// Handler for ETH RPC call: `eth_chainId`
1027    pub fn eth_chain_id(&self) -> Result<Option<U64>> {
1028        node_info!("eth_chainId");
1029        Ok(Some(self.backend.chain_id().to::<U64>()))
1030    }
1031
1032    /// Returns the same as `chain_id`
1033    ///
1034    /// Handler for ETH RPC call: `eth_networkId`
1035    pub fn network_id(&self) -> Result<Option<String>> {
1036        node_info!("eth_networkId");
1037        let chain_id = self.backend.chain_id().to::<u64>();
1038        Ok(Some(format!("{chain_id}")))
1039    }
1040
1041    /// Returns true if client is actively listening for network connections.
1042    ///
1043    /// Handler for ETH RPC call: `net_listening`
1044    pub fn net_listening(&self) -> Result<bool> {
1045        node_info!("net_listening");
1046        Ok(self.net_listening)
1047    }
1048
1049    /// Returns the current gas price
1050    fn eth_gas_price(&self) -> Result<U256> {
1051        node_info!("eth_gasPrice");
1052        Ok(U256::from(self.gas_price()))
1053    }
1054
1055    /// Returns the base fee for the next block, or null before London.
1056    ///
1057    /// Handler for ETH RPC call: `eth_baseFee`
1058    pub fn base_fee(&self) -> Result<Option<U256>> {
1059        node_info!("eth_baseFee");
1060        Ok(self.backend.is_eip1559().then(|| U256::from(self.backend.base_fee())))
1061    }
1062
1063    /// Returns the excess blob gas and current blob gas price
1064    pub fn excess_blob_gas_and_price(&self) -> Result<Option<BlobExcessGasAndPrice>> {
1065        Ok(self.backend.excess_blob_gas_and_price())
1066    }
1067
1068    /// Returns a fee per gas that is an estimate of how much you can pay as a priority fee, or
1069    /// 'tip', to get a transaction included in the current block.
1070    ///
1071    /// Handler for ETH RPC call: `eth_maxPriorityFeePerGas`
1072    pub fn gas_max_priority_fee_per_gas(&self) -> Result<U256> {
1073        self.max_priority_fee_per_gas()
1074    }
1075
1076    /// Returns the base fee per blob required to send an EIP-4844 tx.
1077    ///
1078    /// Handler for ETH RPC call: `eth_blobBaseFee`
1079    pub fn blob_base_fee(&self) -> Result<U256> {
1080        Ok(U256::from(self.backend.fees().base_fee_per_blob_gas()))
1081    }
1082
1083    /// Returns the block gas limit
1084    pub fn gas_limit(&self) -> U256 {
1085        U256::from(self.backend.gas_limit())
1086    }
1087
1088    /// Returns the accounts list
1089    ///
1090    /// Handler for ETH RPC call: `eth_accounts`
1091    pub fn accounts(&self) -> Result<Vec<Address>> {
1092        node_info!("eth_accounts");
1093        let mut unique = AddressSet::default();
1094        let mut accounts: Vec<Address> = Vec::new();
1095        for signer in self.signers.iter() {
1096            accounts.extend(signer.accounts().into_iter().filter(|acc| unique.insert(*acc)));
1097        }
1098        accounts.extend(
1099            self.backend
1100                .cheats()
1101                .impersonated_accounts()
1102                .into_iter()
1103                .filter(|acc| unique.insert(*acc)),
1104        );
1105        Ok(accounts.into_iter().collect())
1106    }
1107
1108    /// Returns the number of most recent block.
1109    ///
1110    /// Handler for ETH RPC call: `eth_blockNumber`
1111    pub fn block_number(&self) -> Result<U256> {
1112        node_info!("eth_blockNumber");
1113        Ok(U256::from(self.backend.best_number()))
1114    }
1115
1116    /// Returns block with given hash.
1117    ///
1118    /// Handler for ETH RPC call: `eth_getBlockByHash`
1119    pub async fn block_by_hash(&self, hash: B256) -> Result<Option<AnyRpcBlock>> {
1120        node_info!("eth_getBlockByHash");
1121        self.backend.block_by_hash(hash).await
1122    }
1123
1124    /// Returns block header with given hash.
1125    ///
1126    /// Handler for ETH RPC call: `eth_getHeaderByHash`
1127    pub async fn header_by_hash(
1128        &self,
1129        hash: B256,
1130    ) -> Result<Option<WithOtherFields<AnyRpcHeader>>> {
1131        node_info!("eth_getHeaderByHash");
1132        Ok(self.backend.block_by_hash(hash).await?.map(|block| {
1133            let WithOtherFields { inner: block, other } = block.0;
1134            WithOtherFields { inner: block.header, other }
1135        }))
1136    }
1137
1138    /// Returns a _full_ block with given hash.
1139    ///
1140    /// Handler for ETH RPC call: `eth_getBlockByHash`
1141    pub async fn block_by_hash_full(&self, hash: B256) -> Result<Option<AnyRpcBlock>> {
1142        node_info!("eth_getBlockByHash");
1143        self.backend.block_by_hash_full(hash).await
1144    }
1145
1146    /// Returns the number of transactions in a block with given hash.
1147    ///
1148    /// Handler for ETH RPC call: `eth_getBlockTransactionCountByHash`
1149    pub async fn block_transaction_count_by_hash(&self, hash: B256) -> Result<Option<U256>> {
1150        node_info!("eth_getBlockTransactionCountByHash");
1151        let block = self.backend.block_by_hash(hash).await?;
1152        let txs = block.map(|b| match b.transactions() {
1153            BlockTransactions::Full(txs) => U256::from(txs.len()),
1154            BlockTransactions::Hashes(txs) => U256::from(txs.len()),
1155            BlockTransactions::Uncle => U256::ZERO,
1156        });
1157        Ok(txs)
1158    }
1159
1160    /// Returns the number of uncles in a block with given hash.
1161    ///
1162    /// Handler for ETH RPC call: `eth_getUncleCountByBlockHash`
1163    pub async fn block_uncles_count_by_hash(&self, hash: B256) -> Result<U256> {
1164        node_info!("eth_getUncleCountByBlockHash");
1165        let block =
1166            self.backend.block_by_hash(hash).await?.ok_or(BlockchainError::BlockNotFound)?;
1167        Ok(U256::from(block.uncles.len()))
1168    }
1169
1170    /// Returns the number of uncles in a block with given block number.
1171    ///
1172    /// Handler for ETH RPC call: `eth_getUncleCountByBlockNumber`
1173    pub async fn block_uncles_count_by_number(&self, block_number: BlockNumber) -> Result<U256> {
1174        node_info!("eth_getUncleCountByBlockNumber");
1175        let block = self
1176            .backend
1177            .block_by_number(block_number)
1178            .await?
1179            .ok_or(BlockchainError::BlockNotFound)?;
1180        Ok(U256::from(block.uncles.len()))
1181    }
1182
1183    /// Signs data via [EIP-712](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md).
1184    ///
1185    /// Handler for ETH RPC call: `eth_signTypedData`
1186    pub async fn sign_typed_data(
1187        &self,
1188        _address: Address,
1189        _data: serde_json::Value,
1190    ) -> Result<String> {
1191        node_info!("eth_signTypedData");
1192        Err(BlockchainError::RpcUnimplemented)
1193    }
1194
1195    /// Signs data via [EIP-712](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md).
1196    ///
1197    /// Handler for ETH RPC call: `eth_signTypedData_v3`
1198    pub async fn sign_typed_data_v3(
1199        &self,
1200        _address: Address,
1201        _data: serde_json::Value,
1202    ) -> Result<String> {
1203        node_info!("eth_signTypedData_v3");
1204        Err(BlockchainError::RpcUnimplemented)
1205    }
1206
1207    /// Signs data via [EIP-712](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md), and includes full support of arrays and recursive data structures.
1208    ///
1209    /// Handler for ETH RPC call: `eth_signTypedData_v4`
1210    pub async fn sign_typed_data_v4(&self, address: Address, data: &TypedData) -> Result<String> {
1211        node_info!("eth_signTypedData_v4");
1212        let signer = self.get_signer(address).ok_or(BlockchainError::NoSignerAvailable)?;
1213        let signature = signer.sign_typed_data(address, data).await?;
1214        Ok(alloy_primitives::hex::encode_prefixed(signature.as_bytes()))
1215    }
1216
1217    /// The sign method calculates an Ethereum specific signature
1218    ///
1219    /// Handler for ETH RPC call: `eth_sign`
1220    pub async fn sign(&self, address: Address, content: impl AsRef<[u8]>) -> Result<String> {
1221        node_info!("eth_sign");
1222        let signer = self.get_signer(address).ok_or(BlockchainError::NoSignerAvailable)?;
1223        let signature = signer.sign(address, content.as_ref()).await?;
1224        Ok(alloy_primitives::hex::encode_prefixed(signature.as_bytes()))
1225    }
1226
1227    /// Returns transaction at given block hash and index.
1228    ///
1229    /// Handler for ETH RPC call: `eth_getTransactionByBlockHashAndIndex`
1230    pub async fn transaction_by_block_hash_and_index(
1231        &self,
1232        hash: B256,
1233        index: Index,
1234    ) -> Result<Option<AnyRpcTransaction>> {
1235        node_info!("eth_getTransactionByBlockHashAndIndex");
1236        self.backend.transaction_by_block_hash_and_index(hash, index).await
1237    }
1238
1239    /// Returns an uncles at given block and index.
1240    ///
1241    /// Handler for ETH RPC call: `eth_getUncleByBlockHashAndIndex`
1242    pub async fn uncle_by_block_hash_and_index(
1243        &self,
1244        block_hash: B256,
1245        idx: Index,
1246    ) -> Result<Option<AnyRpcBlock>> {
1247        node_info!("eth_getUncleByBlockHashAndIndex");
1248        let number = self.backend.ensure_block_number(Some(BlockId::hash(block_hash))).await?;
1249        if let Some(fork) = self.get_fork()
1250            && fork.predates_fork_inclusive(number)
1251        {
1252            return Ok(fork.uncle_by_block_hash_and_index(block_hash, idx.into()).await?);
1253        }
1254        // It's impossible to have uncles outside of fork mode
1255        Ok(None)
1256    }
1257
1258    /// Returns an uncles at given block and index.
1259    ///
1260    /// Handler for ETH RPC call: `eth_getUncleByBlockNumberAndIndex`
1261    pub async fn uncle_by_block_number_and_index(
1262        &self,
1263        block_number: BlockNumber,
1264        idx: Index,
1265    ) -> Result<Option<AnyRpcBlock>> {
1266        node_info!("eth_getUncleByBlockNumberAndIndex");
1267        let number = self.backend.ensure_block_number(Some(BlockId::Number(block_number))).await?;
1268        if let Some(fork) = self.get_fork()
1269            && fork.predates_fork_inclusive(number)
1270        {
1271            return Ok(fork.uncle_by_block_number_and_index(number, idx.into()).await?);
1272        }
1273        // It's impossible to have uncles outside of fork mode
1274        Ok(None)
1275    }
1276
1277    /// Returns the hash of the current block, the seedHash, and the boundary condition to be met.
1278    ///
1279    /// Handler for ETH RPC call: `eth_getWork`
1280    pub fn work(&self) -> Result<Work> {
1281        node_info!("eth_getWork");
1282        Err(BlockchainError::RpcUnimplemented)
1283    }
1284
1285    /// Returns the sync status, always be fails.
1286    ///
1287    /// Handler for ETH RPC call: `eth_syncing`
1288    pub fn syncing(&self) -> Result<bool> {
1289        node_info!("eth_syncing");
1290        Ok(false)
1291    }
1292
1293    /// Returns the current configuration of the chain.
1294    /// This is useful for finding out what precompiles and system contracts are available.
1295    ///
1296    /// Note: the activation timestamp is always 0 as the configuration is set at genesis.
1297    /// Note: the `fork_id` is always `0x00000000` as this node does not participate in any forking
1298    /// on the network.
1299    /// Note: the `next` and `last` fields are always `null` as this node does not participate in
1300    /// any forking on the network.
1301    ///
1302    /// Handler for ETH RPC call: `eth_config`
1303    pub fn config(&self) -> Result<EthConfig> {
1304        node_info!("eth_config");
1305        Ok(EthConfig {
1306            current: EthForkConfig {
1307                activation_time: 0,
1308                blob_schedule: self.backend.blob_params(),
1309                chain_id: self.backend.chain_id().to::<u64>(),
1310                fork_id: Bytes::from_static(&[0; 4]),
1311                precompiles: self.backend.precompiles(),
1312                system_contracts: self.backend.system_contracts(),
1313            },
1314            next: None,
1315            last: None,
1316        })
1317    }
1318
1319    /// Used for submitting a proof-of-work solution.
1320    ///
1321    /// Handler for ETH RPC call: `eth_submitWork`
1322    pub fn submit_work(&self, _: B64, _: B256, _: B256) -> Result<bool> {
1323        node_info!("eth_submitWork");
1324        Err(BlockchainError::RpcUnimplemented)
1325    }
1326
1327    /// Used for submitting mining hashrate.
1328    ///
1329    /// Handler for ETH RPC call: `eth_submitHashrate`
1330    pub fn submit_hashrate(&self, _: U256, _: B256) -> Result<bool> {
1331        node_info!("eth_submitHashrate");
1332        Err(BlockchainError::RpcUnimplemented)
1333    }
1334
1335    /// Introduced in EIP-1559 for getting information on the appropriate priority fee to use.
1336    ///
1337    /// Handler for ETH RPC call: `eth_feeHistory`
1338    pub async fn fee_history(
1339        &self,
1340        block_count: U256,
1341        newest_block: BlockNumber,
1342        reward_percentiles: Vec<f64>,
1343    ) -> Result<FeeHistory>
1344    where
1345        N::ReceiptEnvelope: TxReceipt<Log = alloy_primitives::Log>,
1346    {
1347        node_info!("eth_feeHistory");
1348
1349        if reward_percentiles.iter().any(|p| !(0.0..=100.0).contains(p))
1350            || reward_percentiles.windows(2).any(|pair| pair[0] >= pair[1])
1351        {
1352            return Err(FeeHistoryError::InvalidRewardPercentiles.into());
1353        }
1354        if block_count.is_zero() {
1355            return Ok(FeeHistory::default());
1356        }
1357
1358        // max number of blocks in the requested range
1359
1360        let number = self.backend.convert_block_number(Some(newest_block));
1361
1362        // Snapshot the fork block once so the early return here and the pre-fork split below agree
1363        // on the same value. Reading it a second time lets an `anvil_reset` move the fork between
1364        // the reads: the newest block could clear this early return, then the split treats the
1365        // whole range as pre-fork and tacks on a stray local next-block fee.
1366        let fork = self.get_fork();
1367        let fork_block = fork.as_ref().map(|fork| fork.block_number());
1368
1369        // check if the number predates the fork, if in fork mode
1370        if let (Some(fork), Some(fork_block)) = (fork.as_ref(), fork_block) {
1371            // if we're still at the forked block we don't have any history and can't compute it
1372            // efficiently, instead we fetch it from the fork
1373            if number <= fork_block {
1374                return fork
1375                    .fee_history(
1376                        block_count.saturating_to(),
1377                        BlockNumber::Number(number),
1378                        &reward_percentiles,
1379                    )
1380                    .await
1381                    .map_err(BlockchainError::AlloyForkProvider);
1382            }
1383        }
1384
1385        const MAX_BLOCK_COUNT: u64 = 1024u64;
1386        let block_count = block_count.saturating_to::<u64>().min(MAX_BLOCK_COUNT);
1387
1388        // highest and lowest block num in the requested range
1389        let highest = number;
1390        let lowest = highest.saturating_sub(block_count.saturating_sub(1));
1391        // A local chain starts at its genesis number, so clamp the range to `[genesis, highest]`.
1392        // A newest block below genesis keeps failing as not found.
1393        let lowest = if fork.is_none() {
1394            lowest.max(self.backend.genesis_number().min(highest))
1395        } else {
1396            lowest
1397        };
1398
1399        // only support ranges that are in cache range
1400        if lowest < self.backend.best_number().saturating_sub(self.fee_history_limit) {
1401            return Err(FeeHistoryError::InvalidBlockRange.into());
1402        }
1403
1404        let mut response = FeeHistory {
1405            oldest_block: lowest,
1406            base_fee_per_gas: Vec::new(),
1407            gas_used_ratio: Vec::new(),
1408            reward: Some(Default::default()),
1409            base_fee_per_blob_gas: Default::default(),
1410            blob_gas_used_ratio: Default::default(),
1411        };
1412        let mut rewards = Vec::new();
1413
1414        // The early return above only delegates when the *newest* block predates the fork, but a
1415        // range can dip below the fork block while its newest block is post-fork. Local storage
1416        // has no pre-fork blocks, so resolving them via `backend.get_block` below would fail.
1417        // Serve the pre-fork portion from the fork provider and compute only post-fork locally.
1418        // Reuse the `fork_block` snapshot from above so this split stays consistent with the early
1419        // return; we didn't return, so `fork_block < highest` and only a crossing range splits.
1420        let local_lowest = if let (Some(fork), Some(fork_block)) = (fork.as_ref(), fork_block) {
1421            if lowest <= fork_block {
1422                let count_pre = fork_block - lowest + 1;
1423                let pre = fork
1424                    .fee_history(count_pre, BlockNumber::Number(fork_block), &reward_percentiles)
1425                    .await
1426                    .map_err(BlockchainError::AlloyForkProvider)?;
1427                merge_pre_fork_fee_history(&mut response, &mut rewards, pre, fork_block);
1428                // Compute only post-fork blocks locally; the pre-fork portion is served above.
1429                fork_block + 1
1430            } else {
1431                lowest
1432            }
1433        } else {
1434            lowest
1435        };
1436
1437        {
1438            let storage_info = self.storage_info();
1439            let blob_params = self.backend.blob_params();
1440
1441            // Snapshot the cached entries for the whole range under a single lock. The
1442            // `FeeHistoryService` populates the cache asynchronously and can lag the chain head,
1443            // so some entries may still be missing here.
1444            let cached: Vec<Option<FeeHistoryCacheItem>> = {
1445                let cache = self.fee_history_cache.lock();
1446                (local_lowest..=highest).map(|n| cache.get(&n).cloned()).collect()
1447            };
1448
1449            // Resolve the whole range into concrete items. Cache entries include their block hash
1450            // so a reset or reorg that reuses a block number cannot return data from the old
1451            // canonical chain. Compute misses and stale entries on demand without holding the
1452            // lock. A block that can't be found is a hard error rather than a silently dropped
1453            // entry, so `items` always holds exactly one entry per requested block.
1454            let mut warmed: Vec<(u64, FeeHistoryCacheItem)> = Vec::new();
1455            let mut items: Vec<FeeHistoryCacheItem> = Vec::with_capacity(cached.len());
1456            for (cached_item, n) in cached.into_iter().zip(local_lowest..=highest) {
1457                let hash = self
1458                    .backend
1459                    .block_hash_by_number(n)
1460                    .ok_or(FeeHistoryError::BlockNotFound(BlockNumber::Number(n)))?;
1461                let item = match cached_item {
1462                    Some(item) if item.block_hash == hash => item,
1463                    _ => {
1464                        let block = self
1465                            .backend
1466                            .get_block_by_hash(hash)
1467                            .ok_or(FeeHistoryError::BlockNotFound(BlockNumber::Number(n)))?;
1468                        let header = block.header;
1469                        let (item, block_number) = create_fee_history_cache_item(
1470                            hash,
1471                            &header,
1472                            &storage_info,
1473                            blob_params,
1474                        );
1475                        // The block was found above, but missing stored block/receipts make the
1476                        // helper hand back a zero-filled item. Error out rather than serve
1477                        // synthetic data for a block we already confirmed exists.
1478                        let block_number = block_number
1479                            .ok_or(FeeHistoryError::BlockNotFound(BlockNumber::Number(n)))?;
1480                        warmed.push((block_number, item.clone()));
1481                        item
1482                    }
1483                };
1484                items.push(item);
1485            }
1486
1487            // Warm the cache with the on-demand entries under a single lock, then trim to the
1488            // limit by dropping the oldest blocks so the fallback can't grow the cache unbounded.
1489            if !warmed.is_empty() {
1490                let mut cache = self.fee_history_cache.lock();
1491                for (block_number, item) in warmed {
1492                    cache.insert(block_number, item);
1493                }
1494                while cache.len() as u64 > self.fee_history_limit {
1495                    cache.pop_first();
1496                }
1497            }
1498
1499            for item in items {
1500                response.base_fee_per_gas.push(item.base_fee);
1501                response.base_fee_per_blob_gas.push(item.base_fee_per_blob_gas.unwrap_or(0));
1502                response.blob_gas_used_ratio.push(item.blob_gas_used_ratio);
1503                response.gas_used_ratio.push(item.gas_used_ratio);
1504
1505                // requested percentiles
1506                if !reward_percentiles.is_empty() {
1507                    let mut block_rewards = Vec::new();
1508                    for p in &reward_percentiles {
1509                        block_rewards.push(reward_at_percentile(&item.rewards, *p));
1510                    }
1511                    rewards.push(block_rewards);
1512                }
1513            }
1514        }
1515
1516        response.reward = Some(rewards);
1517
1518        // Both base-fee arrays include the block after the returned range. For a historical
1519        // request, use that block's header; the fee manager tracks the block after the current
1520        // chain head and would therefore append an unrelated value. Prefer an existing child even
1521        // when `highest` was the head at the start of this request, since mining can advance it.
1522        let next_number = highest
1523            .checked_add(1)
1524            .ok_or(FeeHistoryError::BlockNotFound(BlockNumber::Number(highest)))?;
1525        let (next_base_fee, next_blob_base_fee) = self
1526            .backend
1527            .fee_history_next_fees(highest)
1528            .await
1529            .ok_or(FeeHistoryError::BlockNotFound(BlockNumber::Number(next_number)))?;
1530        response.base_fee_per_gas.push(next_base_fee);
1531        response.base_fee_per_blob_gas.push(next_blob_base_fee);
1532
1533        Ok(response)
1534    }
1535
1536    /// Introduced in EIP-1159, a Geth-specific and simplified priority fee oracle.
1537    /// Leverages the already existing fee history cache.
1538    ///
1539    /// Returns a suggestion for a gas tip cap for dynamic fee transactions.
1540    ///
1541    /// Handler for ETH RPC call: `eth_maxPriorityFeePerGas`
1542    pub fn max_priority_fee_per_gas(&self) -> Result<U256> {
1543        node_info!("eth_maxPriorityFeePerGas");
1544        Ok(U256::from(self.lowest_suggestion_tip()))
1545    }
1546
1547    /// Returns code by its hash
1548    ///
1549    /// Handler for RPC call: `debug_codeByHash`
1550    pub async fn debug_code_by_hash(
1551        &self,
1552        hash: B256,
1553        block_id: Option<BlockId>,
1554    ) -> Result<Option<Bytes>> {
1555        node_info!("debug_codeByHash");
1556        self.backend.debug_code_by_hash(hash, block_id).await
1557    }
1558
1559    /// Returns the value associated with a key from the database
1560    /// Only supports bytecode lookups.
1561    ///
1562    /// Handler for RPC call: `debug_dbGet`
1563    pub async fn debug_db_get(&self, key: String) -> Result<Option<Bytes>> {
1564        node_info!("debug_dbGet");
1565        self.backend.debug_db_get(key).await
1566    }
1567
1568    /// Handles reth's no-op `debug_getModifiedAccountsByNumber` endpoint.
1569    pub fn debug_get_modified_accounts_by_number(
1570        &self,
1571        _start_number: u64,
1572        _end_number: u64,
1573    ) -> Result<()> {
1574        node_info!("debug_getModifiedAccountsByNumber");
1575        Ok(())
1576    }
1577
1578    /// Handles reth's no-op `debug_freeOSMemory` endpoint.
1579    pub fn debug_free_os_memory(&self) -> Result<()> {
1580        node_info!("debug_freeOSMemory");
1581        Ok(())
1582    }
1583
1584    /// Executes a transaction and returns requested parity trace results.
1585    ///
1586    /// Handler for RPC call: `trace_call`
1587    pub async fn trace_call(
1588        &self,
1589        request: WithOtherFields<TransactionRequest>,
1590        trace_types: HashSet<TraceType>,
1591        block_id: Option<BlockId>,
1592    ) -> Result<TraceResults>
1593    where
1594        N: Network<TxEnvelope = FoundryTxEnvelope, ReceiptEnvelope = FoundryReceiptEnvelope>,
1595    {
1596        node_info!("trace_call");
1597        let block_id = block_id.unwrap_or_default();
1598        let block_request = self.trace_block_request(block_id).await?;
1599        let inner = request.as_ref();
1600        let fees = FeeDetails::new(
1601            inner.gas_price,
1602            inner.max_fee_per_gas,
1603            inner.max_priority_fee_per_gas,
1604            inner.max_fee_per_blob_gas,
1605        )?
1606        .or_zero_fees();
1607
1608        self.backend.trace_call(request, fees, trace_types, block_request, block_id).await
1609    }
1610
1611    /// Returns traces for the transaction hash via parity's tracing endpoint
1612    ///
1613    /// Handler for RPC call: `trace_transaction`
1614    pub async fn trace_transaction(
1615        &self,
1616        tx_hash: B256,
1617    ) -> Result<Option<Vec<LocalizedTransactionTrace>>> {
1618        node_info!("trace_transaction");
1619        self.backend.trace_transaction(tx_hash).await
1620    }
1621
1622    /// Returns traces for the transaction hash via parity's tracing endpoint
1623    ///
1624    /// Handler for RPC call: `trace_block`
1625    pub async fn trace_block(&self, block: BlockNumber) -> Result<Vec<LocalizedTransactionTrace>> {
1626        node_info!("trace_block");
1627        self.backend.trace_block(block).await
1628    }
1629
1630    /// Returns filtered traces over blocks
1631    ///
1632    /// Handler for RPC call: `trace_filter`
1633    pub async fn trace_filter(
1634        &self,
1635        filter: TraceFilter,
1636    ) -> Result<Vec<LocalizedTransactionTrace>> {
1637        node_info!("trace_filter");
1638        self.backend.trace_filter(filter).await
1639    }
1640
1641    /// Returns the transaction trace at the given trace address.
1642    ///
1643    /// Handler for RPC call: `trace_get`.
1644    pub async fn trace_get(
1645        &self,
1646        hash: B256,
1647        indices: Vec<Index>,
1648    ) -> Result<Option<LocalizedTransactionTrace>> {
1649        node_info!("trace_get");
1650        self.backend.trace_get(hash, indices).await
1651    }
1652
1653    /// Replays all transactions in a block returning the requested traces for each transaction
1654    ///
1655    /// Handler for RPC call: `trace_replayBlockTransactions`
1656    pub async fn trace_replay_block_transactions(
1657        &self,
1658        block: BlockNumber,
1659        trace_types: HashSet<TraceType>,
1660    ) -> Result<Vec<TraceResultsWithTransactionHash>> {
1661        node_info!("trace_replayBlockTransactions");
1662        self.backend.trace_replay_block_transactions(block, trace_types).await
1663    }
1664
1665    /// Replays a transaction returning the requested traces.
1666    ///
1667    /// Handler for RPC call: `trace_replayTransaction`.
1668    pub async fn trace_replay_transaction(
1669        &self,
1670        transaction: B256,
1671        trace_types: HashSet<TraceType>,
1672    ) -> Result<Option<TraceResultsWithTransactionHash>> {
1673        node_info!("trace_replayTransaction");
1674        self.backend.trace_replay_transaction(transaction, trace_types).await
1675    }
1676
1677    /// Returns the block request a trace method executes against.
1678    async fn trace_block_request(
1679        &self,
1680        block_id: BlockId,
1681    ) -> Result<BlockRequest<FoundryTxEnvelope>>
1682    where
1683        N: Network<TxEnvelope = FoundryTxEnvelope>,
1684    {
1685        if block_id.is_pending() {
1686            return Ok(BlockRequest::Pending(self.pool.ready_transactions().collect()));
1687        }
1688        Ok(BlockRequest::Number(self.backend.ensure_trace_block_number(block_id).await?))
1689    }
1690}
1691
1692impl<N: Network<ReceiptEnvelope = FoundryReceiptEnvelope>> EthApi<N> {
1693    /// Returns the current state
1694    pub async fn serialized_state(
1695        &self,
1696        preserve_historical_states: bool,
1697    ) -> Result<SerializableState> {
1698        self.backend.serialized_state(preserve_historical_states).await
1699    }
1700}
1701
1702// == impl EthApi anvil endpoints ==
1703
1704impl EthApi<FoundryNetwork> {
1705    /// Returns transaction by given block number and index.
1706    ///
1707    /// Handler for ETH RPC call: `eth_getTransactionByBlockNumberAndIndex`
1708    pub async fn transaction_by_block_number_and_index(
1709        &self,
1710        block: BlockNumber,
1711        idx: Index,
1712    ) -> Result<Option<AnyRpcTransaction>> {
1713        node_info!("eth_getTransactionByBlockNumberAndIndex");
1714        if block.is_pending() {
1715            return Ok(self.pending_block_full().await?.and_then(|block| {
1716                let WithOtherFields { inner: block, .. } = block.0;
1717                block.transactions.into_transactions().nth(idx.into())
1718            }));
1719        }
1720
1721        self.backend.transaction_by_block_number_and_index(block, idx).await
1722    }
1723
1724    /// Create a buffer that represents all state on the chain, which can be loaded to separate
1725    /// process by calling `anvil_loadState`
1726    ///
1727    /// Handler for RPC call: `anvil_dumpState`
1728    pub async fn anvil_dump_state(
1729        &self,
1730        preserve_historical_states: Option<bool>,
1731    ) -> Result<Bytes> {
1732        node_info!("anvil_dumpState");
1733        self.backend.dump_state(preserve_historical_states.unwrap_or(false)).await
1734    }
1735
1736    /// Append chain state buffer to current chain. Will overwrite any conflicting addresses or
1737    /// storage.
1738    ///
1739    /// Handler for RPC call: `anvil_loadState`
1740    pub async fn anvil_load_state(&self, buf: Bytes) -> Result<bool> {
1741        node_info!("anvil_loadState");
1742        let loaded = self.backend.load_state_bytes(buf).await?;
1743        #[cfg(feature = "base")]
1744        if loaded {
1745            self.invalidate_base_eip8130_pool();
1746        }
1747        Ok(loaded)
1748    }
1749
1750    async fn block_request(
1751        &self,
1752        block_number: Option<BlockId>,
1753    ) -> Result<BlockRequest<FoundryTxEnvelope>> {
1754        let block_request = match block_number {
1755            Some(BlockId::Number(BlockNumber::Pending)) => {
1756                let pending_txs = self.pool.ready_transactions().collect();
1757                BlockRequest::Pending(pending_txs)
1758            }
1759            _ => {
1760                let number = self.backend.ensure_block_number(block_number).await?;
1761                BlockRequest::Number(number)
1762            }
1763        };
1764        Ok(block_request)
1765    }
1766
1767    /// Returns account information after replaying a block through a transaction index.
1768    ///
1769    /// Handler for RPC call: `debug_accountInfoAt`.
1770    pub async fn debug_account_info_at(
1771        &self,
1772        block_id: BlockId,
1773        tx_index: Index,
1774        address: Address,
1775    ) -> Result<Option<AccountInfo>> {
1776        node_info!("debug_accountInfoAt");
1777        self.backend.debug_account_info_at(block_id, tx_index, address).await
1778    }
1779
1780    /// Returns a best-effort execution witness for the given block, built from the full parent
1781    /// state. See [`crate::eth::backend::mem::Backend::debug_execution_witness`] for the exact
1782    /// contents and limitations.
1783    ///
1784    /// Handler for RPC call: `debug_executionWitness`.
1785    pub async fn debug_execution_witness(&self, block: BlockNumber) -> Result<ExecutionWitness> {
1786        node_info!("debug_executionWitness");
1787        self.backend.debug_execution_witness(block).await
1788    }
1789
1790    /// Returns opcode gas usage for a transaction.
1791    ///
1792    /// Handler for RPC call: `trace_transactionOpcodeGas`.
1793    pub async fn trace_transaction_opcode_gas(
1794        &self,
1795        tx_hash: B256,
1796    ) -> Result<Option<TransactionOpcodeGas>> {
1797        node_info!("trace_transactionOpcodeGas");
1798        self.backend.trace_transaction_opcode_gas(tx_hash).await
1799    }
1800
1801    /// Returns opcode gas usage for all transactions in a block.
1802    ///
1803    /// Handler for RPC call: `trace_blockOpcodeGas`.
1804    pub async fn trace_block_opcode_gas(
1805        &self,
1806        block_id: BlockId,
1807    ) -> Result<Option<BlockOpcodeGas>> {
1808        node_info!("trace_blockOpcodeGas");
1809        self.backend.trace_block_opcode_gas(block_id).await
1810    }
1811
1812    /// Traces a raw signed transaction without importing it into the mempool.
1813    ///
1814    /// Handler for RPC call: `trace_rawTransaction`.
1815    pub async fn trace_raw_transaction(
1816        &self,
1817        tx: Bytes,
1818        trace_types: HashSet<TraceType>,
1819        block_number: Option<BlockId>,
1820    ) -> Result<TraceResults> {
1821        node_info!("trace_rawTransaction");
1822
1823        let mut data = tx.as_ref();
1824        if data.is_empty() {
1825            return Err(BlockchainError::EmptyRawTransactionData);
1826        }
1827
1828        let transaction = FoundryTxEnvelope::decode_2718(&mut data)
1829            .map_err(|_| BlockchainError::FailedToDecodeSignedTransaction)?;
1830        self.ensure_typed_transaction_supported(&transaction)?;
1831
1832        #[cfg(feature = "base")]
1833        let is_eip8130 = transaction.is_eip8130();
1834        let pending_transaction = PendingTransaction::new(transaction).map_err(|error| {
1835            #[cfg(feature = "base")]
1836            if is_eip8130 {
1837                return BlockchainError::Eip8130TransactionRejected(error.to_string());
1838            }
1839            BlockchainError::RecoveryError(error)
1840        })?;
1841        let block_request = self.trace_block_request(block_number.unwrap_or_default()).await?;
1842
1843        self.backend
1844            .trace_raw_transaction(pending_transaction, trace_types, Some(block_request))
1845            .await
1846    }
1847
1848    /// Increases the balance of an account.
1849    ///
1850    /// Handler for RPC call: `anvil_addBalance`
1851    pub async fn anvil_add_balance(&self, address: Address, balance: U256) -> Result<()> {
1852        node_info!("anvil_addBalance");
1853        self.backend.add_balance(address, balance).await?;
1854        Ok(())
1855    }
1856
1857    /// Returns a local rollback ancestor, a Monad replay ancestor, or the pinned fork root.
1858    async fn rollback_block(&self, number: u64) -> Result<Option<Block>> {
1859        if let Some(block) = self.backend.get_block(number) {
1860            return Ok(Some(block));
1861        }
1862        #[cfg(feature = "monad")]
1863        if self.backend.is_monad()
1864            && let Some(block) = self.backend.monad_rollback_block(number).await?
1865        {
1866            return Ok(Some(block));
1867        }
1868
1869        let Some(fork) = self.get_fork().filter(|fork| fork.block_number() == number) else {
1870            return Ok(None);
1871        };
1872        let Some(header) = fork.root_header().await? else { return Ok(None) };
1873
1874        // Rollback only needs the header; do not publish this placeholder as a complete block.
1875        Ok(Some(Block { header, body: Default::default() }))
1876    }
1877
1878    /// Rewinds through the selected execution family's recovery path.
1879    async fn rollback_backend(
1880        &self,
1881        common_block: Block,
1882        mining_guard: &tokio::sync::MutexGuard<'_, ()>,
1883    ) -> Result<()> {
1884        #[cfg(feature = "monad")]
1885        if self.backend.is_monad() {
1886            return self.backend.rollback_monad(common_block, mining_guard).await;
1887        }
1888        self.backend.rollback(common_block, mining_guard).await
1889    }
1890
1891    /// Rollback the chain to a specific depth.
1892    ///
1893    /// e.g depth = 3
1894    ///     A  -> B  -> C  -> D  -> E
1895    ///     A  -> B
1896    ///
1897    /// Depth specifies the height to rollback the chain back to. Depth must not exceed the current
1898    /// chain height, i.e. can't rollback past the genesis block.
1899    ///
1900    /// Handler for RPC call: `anvil_rollback`
1901    pub async fn anvil_rollback(&self, depth: Option<u64>) -> Result<()> {
1902        node_info!("anvil_rollback");
1903        let _lifecycle = self.lifecycle_lock.write().await;
1904        let mining_guard = self.backend.lock_mining().await;
1905        let depth = depth.unwrap_or(1);
1906
1907        // Check reorg depth doesn't exceed current chain height
1908        let current_height = self.backend.best_number();
1909        let genesis = if self.get_fork().is_some() { 0 } else { self.backend.genesis_number() };
1910        let common_height = current_height.checked_sub(depth).filter(|h| *h >= genesis).ok_or(
1911            BlockchainError::RpcError(RpcError::invalid_params(format!(
1912                "Rollback depth must not exceed current chain height: current height {current_height}, depth {depth}, genesis {genesis}"
1913            ))),
1914        )?;
1915
1916        // Get the common ancestor block
1917        let common_block =
1918            self.rollback_block(common_height).await?.ok_or(BlockchainError::BlockNotFound)?;
1919
1920        self.rollback_backend(common_block, &mining_guard).await?;
1921        Ok(())
1922    }
1923
1924    /// Estimates the gas usage of the `request` with the state.
1925    ///
1926    /// This will execute the transaction request and find the best gas limit via binary search.
1927    fn do_estimate_gas_with_state(
1928        &self,
1929        mut request: FoundryTransactionRequest,
1930        state: &dyn DatabaseRef,
1931        block_env: BlockEnv,
1932        monad_context: Option<MonadReplayContext>,
1933    ) -> Result<u128> {
1934        // A blob request may carry only its sidecar. Take its versioned hashes first, so that the
1935        // funds check and every execution below price the blob fee.
1936        if request.as_ref().blob_versioned_hashes.is_none() {
1937            request.as_mut().populate_blob_hashes();
1938        }
1939        let inner = request.as_ref();
1940        let fees = FeeDetails::new(
1941            inner.gas_price,
1942            inner.max_fee_per_gas,
1943            inner.max_priority_fee_per_gas,
1944            inner.max_fee_per_blob_gas,
1945        )?
1946        .or_zero_fees();
1947
1948        #[cfg(feature = "base")]
1949        if self.backend.is_base() && request.is_base() {
1950            self.backend.ensure_base_eip8130_active_at(block_env.timestamp.saturating_to())?;
1951            let gas_limit = block_env.gas_limit;
1952            let result = self
1953                .backend
1954                .call_with_state_typed_gas_limit(
1955                    state,
1956                    request,
1957                    fees,
1958                    block_env,
1959                    GasEstimateCallOptions::new(gas_limit, false, monad_context),
1960                )
1961                .try_into()?;
1962            return match result {
1963                GasEstimationCallResult::Success(gas) => Ok(gas),
1964                GasEstimationCallResult::OutOfGas => {
1965                    Err(InvalidTransactionError::BasicOutOfGas(u128::from(gas_limit)).into())
1966                }
1967                GasEstimationCallResult::Revert(output) => {
1968                    Err(InvalidTransactionError::Revert(output).into())
1969                }
1970                GasEstimationCallResult::EvmError(error) => Err(BlockchainError::EvmError(error)),
1971            };
1972        }
1973
1974        // get the highest possible gas limit, either the request's set value or the currently
1975        // configured gas limit
1976        let mut highest_gas_limit = inner.gas.map_or(block_env.gas_limit.into(), |g| g as u128);
1977
1978        // Tempo AA transactions pay fees in ERC-20 tokens, not ETH. Only treat requests as
1979        // Tempo AA in Tempo mode, otherwise `feeToken` should not bypass ETH funds checks.
1980        let is_tempo_aa_tx = self.backend.is_tempo() && request.is_tempo();
1981        let is_tempo_keychain = matches!(
1982            &request,
1983            FoundryTransactionRequest::Tempo(request) if request.key_id.is_some()
1984        );
1985        let disable_fee_charge = is_tempo_keychain || inner.from.is_none();
1986
1987        // Requests without a sender historically estimate value transfers without requiring the
1988        // default caller to hold ETH. Fund only the simulation overlay so the execution probe
1989        // preserves that behavior, including transfers that need new-account state gas.
1990        let mut funded_state;
1991        let state = if !is_tempo_aa_tx
1992            && inner.from.is_none()
1993            && let Some(value) = inner.value
1994            && !value.is_zero()
1995        {
1996            funded_state = CacheDB::new(state);
1997            let mut caller = state.basic_ref(Address::ZERO)?.unwrap_or_default();
1998            caller.balance = caller.balance.max(value);
1999            funded_state.insert_account_info(Address::ZERO, caller);
2000            &funded_state as &dyn DatabaseRef
2001        } else {
2002            state
2003        };
2004
2005        let gas_price = fees.gas_price.unwrap_or_default();
2006        // Check transfer value before any fast path, and cap gas limit by sender balance when the
2007        // request has a non-zero gas price. Only enforce this for explicit senders: calls without
2008        // `from` historically estimate against the default caller and must not be capped by the
2009        // zero address balance.
2010        if !is_tempo_aa_tx && let Some(from) = inner.from {
2011            let mut available_funds = self.backend.get_balance_with_state(state, from)?;
2012            if let Some(value) = inner.value {
2013                if value > available_funds {
2014                    return Err(InvalidTransactionError::InsufficientFunds.into());
2015                }
2016                // safe: value <= available_funds
2017                available_funds -= value;
2018            }
2019            if gas_price > 0 {
2020                // Blob gas is paid on top of execution gas, so reserve its maximum cost first. Like
2021                // the call itself, pay no blob fee when no cap is given.
2022                if inner.minimal_tx_type().is_eip4844()
2023                    && let Some(hashes) = &inner.blob_versioned_hashes
2024                {
2025                    let max_fee_per_blob_gas = fees.max_fee_per_blob_gas.unwrap_or_default();
2026                    let blob_gas = U256::from(hashes.len() as u64 * DATA_GAS_PER_BLOB);
2027                    let blob_cost = blob_gas.saturating_mul(U256::from(max_fee_per_blob_gas));
2028                    if blob_cost >= available_funds {
2029                        return Err(InvalidTransactionError::InsufficientFunds.into());
2030                    }
2031                    available_funds -= blob_cost;
2032                }
2033                // amount of gas the sender can afford with the `gas_price`
2034                let allowance =
2035                    available_funds.checked_div(U256::from(gas_price)).unwrap_or_default();
2036                highest_gas_limit = std::cmp::min(highest_gas_limit, allowance.saturating_to());
2037            }
2038        }
2039
2040        // If the request is a simple native token transfer we can optimize
2041        // We assume it's a transfer if we have no input data.
2042        // Skip this optimization for Tempo mode since native ETH transfers are not allowed
2043        // and Tempo AA transactions have higher intrinsic gas costs (~46k).
2044        if !self.backend.is_tempo() {
2045            let to = inner.to.as_ref().and_then(TxKind::to);
2046
2047            // check certain fields to see if the request could be a simple transfer
2048            let maybe_transfer = (inner.input.input().is_none()
2049                || inner.input.input().is_some_and(|data| data.is_empty()))
2050                && inner.authorization_list.is_none()
2051                && inner.access_list.is_none()
2052                && inner.blob_versioned_hashes.is_none();
2053
2054            if maybe_transfer
2055                && let Some(to) = to
2056                && !self.backend.is_precompile(to, &block_env)
2057                && let Ok(target_code) = self.backend.get_code_with_state(&state, *to)
2058                && target_code.as_ref().is_empty()
2059            {
2060                // Execute the transfer to account for fork-dependent gas costs and validation.
2061                // With no bytecode or authorizations, a successful run receives no refunds and
2062                // its gas used is the exact gas required. A new-account state charge can make
2063                // this probe fail, in which case estimation continues below.
2064                let probe = self.backend.call_with_state_typed_gas_limit(
2065                    &state,
2066                    request.clone(),
2067                    fees.clone(),
2068                    block_env.clone(),
2069                    GasEstimateCallOptions::new(
2070                        highest_gas_limit.min(MIN_TRANSACTION_GAS) as u64,
2071                        disable_fee_charge,
2072                        monad_context.clone(),
2073                    ),
2074                );
2075                if let Ok(GasEstimationCallResult::Success(gas)) = probe.try_into() {
2076                    return Ok(gas);
2077                }
2078            }
2079        }
2080
2081        // execute the call without writing to db
2082        let ethres = self.backend.call_with_state_typed_gas_limit(
2083            &state,
2084            request.clone(),
2085            fees.clone(),
2086            block_env.clone(),
2087            GasEstimateCallOptions::new(
2088                highest_gas_limit as u64,
2089                disable_fee_charge,
2090                monad_context.clone(),
2091            ),
2092        );
2093
2094        let gas_used = match ethres.try_into()? {
2095            GasEstimationCallResult::Success(gas) => Ok(gas),
2096            GasEstimationCallResult::OutOfGas => {
2097                Err(InvalidTransactionError::BasicOutOfGas(highest_gas_limit).into())
2098            }
2099            GasEstimationCallResult::Revert(output) => {
2100                Err(InvalidTransactionError::Revert(output).into())
2101            }
2102            GasEstimationCallResult::EvmError(err) => {
2103                warn!(target: "node", "estimation failed due to {:?}", err);
2104                Err(BlockchainError::EvmError(err))
2105            }
2106        }?;
2107
2108        // at this point we know the call succeeded but want to find the _best_ (lowest) gas the
2109        // transaction succeeds with. we find this by doing a binary search over the
2110        // possible range NOTE: this is the gas the transaction used, which is less than the
2111        // transaction requires to succeed
2112
2113        // Gas used is a lower bound on the gas required. Keep it inside the search interval so
2114        // exact-cost transactions, including Amsterdam calls below 21,000 gas, are considered.
2115        let mut lowest_gas_limit = gas_used.saturating_sub(1);
2116
2117        // pick a point that's close to the estimated gas
2118        let mut mid_gas_limit =
2119            std::cmp::min(gas_used * 3, (highest_gas_limit + lowest_gas_limit) / 2);
2120
2121        // Binary search for the ideal gas limit
2122        while lowest_gas_limit + 1 < highest_gas_limit {
2123            let ethres = self.backend.call_with_state_typed_gas_limit(
2124                &state,
2125                request.clone(),
2126                fees.clone(),
2127                block_env.clone(),
2128                GasEstimateCallOptions::new(
2129                    mid_gas_limit as u64,
2130                    disable_fee_charge,
2131                    monad_context.clone(),
2132                ),
2133            );
2134
2135            match ethres.try_into()? {
2136                GasEstimationCallResult::Success(_) => {
2137                    // If the transaction succeeded, we can set a ceiling for the highest gas limit
2138                    // at the current midpoint, as spending any more gas would
2139                    // make no sense (as the TX would still succeed).
2140                    highest_gas_limit = mid_gas_limit;
2141                }
2142                GasEstimationCallResult::OutOfGas
2143                | GasEstimationCallResult::Revert(_)
2144                | GasEstimationCallResult::EvmError(_) => {
2145                    // If the transaction failed, we can set a floor for the lowest gas limit at the
2146                    // current midpoint, as spending any less gas would make no
2147                    // sense (as the TX would still revert due to lack of gas).
2148                    //
2149                    // We don't care about the reason here, as we known that transaction is correct
2150                    // as it succeeded earlier
2151                    lowest_gas_limit = mid_gas_limit;
2152                }
2153            };
2154            // new midpoint
2155            mid_gas_limit = (highest_gas_limit + lowest_gas_limit) / 2;
2156        }
2157
2158        trace!(target : "node", "Estimated Gas for call {:?}", highest_gas_limit);
2159
2160        Ok(highest_gas_limit)
2161    }
2162
2163    /// Executes the [EthRequest] and returns an RPC [ResponseResult].
2164    #[allow(clippy::large_stack_frames)]
2165    pub async fn execute(&self, request: EthRequest) -> ResponseResult {
2166        trace!(target: "rpc::api", "executing eth request");
2167        // Fork reset and RPC URL replacement take the write lock internally after their fallible
2168        // remote staging work. Memory reset takes it before staging because it snapshots live
2169        // state. Identity, snapshot, and chain-rewind methods also lock internally to keep direct
2170        // API callers safe without recursively acquiring this fair RwLock. Consensus queries
2171        // snapshot their source under the backend DB lock before any upstream I/O.
2172        let _lifecycle = if matches!(
2173            &request,
2174            EthRequest::Reset(_)
2175                | EthRequest::SetRpcUrl(_)
2176                | EthRequest::NodeInfo(_)
2177                | EthRequest::AnvilMetadata(_)
2178                | EthRequest::EvmSnapshot(_)
2179                | EthRequest::EvmRevert(_)
2180                | EthRequest::Reorg(_)
2181                | EthRequest::Rollback(_)
2182                | EthRequest::ConsensusGetFinalization(_)
2183                | EthRequest::ConsensusGetLatest(_)
2184        ) {
2185            None
2186        } else {
2187            Some(self.lifecycle_lock.read().await)
2188        };
2189        match request {
2190            EthRequest::EthProtocolVersion(()) => self.protocol_version().to_rpc_result(),
2191            EthRequest::Web3ClientVersion(()) => self.client_version().to_rpc_result(),
2192            EthRequest::Web3Sha3(content) => self.sha3(content).to_rpc_result(),
2193            EthRequest::EthGetAccount(addr, block) => {
2194                self.get_account(addr, block).await.to_rpc_result()
2195            }
2196            EthRequest::EthGetAccountInfo(addr, block) => {
2197                self.get_account_info(addr, block).await.to_rpc_result()
2198            }
2199            EthRequest::EthGetBalance(addr, block) => {
2200                self.balance(addr, block).await.to_rpc_result()
2201            }
2202            EthRequest::EthGetTransactionByHash(hash) => {
2203                self.transaction_by_hash(hash).await.to_rpc_result()
2204            }
2205            EthRequest::EthPendingTransactions(_) => {
2206                self.pending_transactions().await.to_rpc_result()
2207            }
2208            EthRequest::EthSendTransaction(request) => {
2209                self.send_transaction(*request).await.to_rpc_result()
2210            }
2211            EthRequest::EthResend(request, gas_price, gas_limit) => {
2212                self.resend_transaction(*request, gas_price, gas_limit).await.to_rpc_result()
2213            }
2214            EthRequest::EthSendTransactionSync(request) => {
2215                self.send_transaction_sync(*request).await.to_rpc_result()
2216            }
2217            EthRequest::EthChainId(_) => self.eth_chain_id().to_rpc_result(),
2218            EthRequest::EthNetworkId(_) => self.network_id().to_rpc_result(),
2219            EthRequest::NetListening(_) => self.net_listening().to_rpc_result(),
2220            EthRequest::EthHashrate(()) => self.hashrate().to_rpc_result(),
2221            EthRequest::EthGasPrice(_) => self.eth_gas_price().to_rpc_result(),
2222            EthRequest::EthBaseFee(_) => self.base_fee().to_rpc_result(),
2223            EthRequest::EthMaxPriorityFeePerGas(_) => {
2224                self.gas_max_priority_fee_per_gas().to_rpc_result()
2225            }
2226            EthRequest::EthBlobBaseFee(_) => self.blob_base_fee().to_rpc_result(),
2227            EthRequest::EthAccounts(_) => self.accounts().to_rpc_result(),
2228            EthRequest::EthBlockNumber(_) => self.block_number().to_rpc_result(),
2229            EthRequest::EthCoinbase(()) => self.author().to_rpc_result(),
2230            EthRequest::EthGetStorageAt(addr, slot, block) => {
2231                self.storage_at(addr, slot, block).await.to_rpc_result()
2232            }
2233            EthRequest::EthGetStorageValues(requests, block) => {
2234                self.storage_values(requests, block).await.to_rpc_result()
2235            }
2236            EthRequest::EthGetBlockByHash(hash, full) => {
2237                if full {
2238                    self.block_by_hash_full(hash).await.to_rpc_result()
2239                } else {
2240                    self.block_by_hash(hash).await.to_rpc_result()
2241                }
2242            }
2243            EthRequest::EthGetHeaderByHash(hash) => self.header_by_hash(hash).await.to_rpc_result(),
2244            EthRequest::EthGetBlockByNumber(num, full) => {
2245                if full {
2246                    self.block_by_number_full(num).await.to_rpc_result()
2247                } else {
2248                    self.block_by_number(num).await.to_rpc_result()
2249                }
2250            }
2251            EthRequest::EthGetHeaderByNumber(num) => {
2252                self.header_by_number(num).await.to_rpc_result()
2253            }
2254            EthRequest::EthGetBlockAccessList(block_id) => {
2255                self.block_access_list(block_id).await.to_rpc_result()
2256            }
2257            EthRequest::EthGetBlockAccessListByBlockHash(block_hash) => {
2258                self.block_access_list_by_hash(block_hash).await.to_rpc_result()
2259            }
2260            EthRequest::EthGetBlockAccessListByBlockNumber(block_number) => {
2261                self.block_access_list_by_number(block_number).await.to_rpc_result()
2262            }
2263            EthRequest::EthGetBlockAccessListRaw(block_id) => {
2264                self.block_access_list_raw(block_id).await.to_rpc_result()
2265            }
2266            EthRequest::EthGetTransactionCount(params) => {
2267                let (address, block, nonce_key) = params.into_parts();
2268                #[cfg(feature = "base")]
2269                {
2270                    self.transaction_count_with_key(address, block, nonce_key).await.to_rpc_result()
2271                }
2272                #[cfg(not(feature = "base"))]
2273                {
2274                    if nonce_key.is_some() {
2275                        return ResponseResult::Error(RpcError::invalid_params(
2276                            "nonce-key transaction counts require Base support",
2277                        ));
2278                    }
2279                    self.transaction_count(address, block).await.to_rpc_result()
2280                }
2281            }
2282            EthRequest::EthGetTransactionCountByHash(hash) => {
2283                self.block_transaction_count_by_hash(hash).await.to_rpc_result()
2284            }
2285            EthRequest::EthGetTransactionCountByNumber(num) => {
2286                self.block_transaction_count_by_number(num).await.to_rpc_result()
2287            }
2288            EthRequest::EthGetUnclesCountByHash(hash) => {
2289                self.block_uncles_count_by_hash(hash).await.to_rpc_result()
2290            }
2291            EthRequest::EthGetUnclesCountByNumber(num) => {
2292                self.block_uncles_count_by_number(num).await.to_rpc_result()
2293            }
2294            EthRequest::EthGetCodeAt(addr, block) => {
2295                self.get_code(addr, block).await.to_rpc_result()
2296            }
2297            EthRequest::EthGetProof(addr, keys, block) => {
2298                self.get_proof(addr, keys, block).await.to_rpc_result()
2299            }
2300            EthRequest::EthSign(addr, content) => self.sign(addr, content).await.to_rpc_result(),
2301            EthRequest::PersonalSign(content, addr) => {
2302                self.sign(addr, content).await.to_rpc_result()
2303            }
2304            EthRequest::EthSignTransaction(request) => {
2305                self.sign_transaction(*request).await.to_rpc_result()
2306            }
2307            EthRequest::EthSignTypedData(addr, data) => {
2308                self.sign_typed_data(addr, data).await.to_rpc_result()
2309            }
2310            EthRequest::EthSignTypedDataV3(addr, data) => {
2311                self.sign_typed_data_v3(addr, data).await.to_rpc_result()
2312            }
2313            EthRequest::EthSignTypedDataV4(addr, data) => {
2314                self.sign_typed_data_v4(addr, &data).await.to_rpc_result()
2315            }
2316            EthRequest::EthSendRawTransaction(tx) => {
2317                self.send_raw_transaction(tx).await.to_rpc_result()
2318            }
2319            EthRequest::EthSendRawTransactionSync(tx, timeout_ms) => {
2320                self.send_raw_transaction_sync(tx, timeout_ms).await.to_rpc_result()
2321            }
2322            EthRequest::EthSendRawTransactionConditional(tx, condition) => {
2323                self.send_raw_transaction_conditional(tx, condition).await.to_rpc_result()
2324            }
2325            EthRequest::EthSignRawTransaction(tx) => {
2326                self.sign_raw_transaction(tx).await.to_rpc_result()
2327            }
2328            EthRequest::AnvilClassifyTransaction(tx) => {
2329                self.anvil_classify_transaction(tx).to_rpc_result()
2330            }
2331            EthRequest::EthCall(call, block, state_override, block_overrides) => self
2332                .call(call, block, EvmOverrides::new(state_override, block_overrides))
2333                .await
2334                .to_rpc_result(),
2335            EthRequest::EthCallMany(bundles, state_context, state_override) => {
2336                self.call_many(bundles, state_context, state_override).await.to_rpc_result()
2337            }
2338            EthRequest::EthCallBundle(bundle) => self.call_bundle(bundle).await.to_rpc_result(),
2339            EthRequest::EthSimulateV1(simulation, block) => {
2340                self.simulate_v1_raw(simulation, block).await.to_rpc_result()
2341            }
2342            EthRequest::EthCreateAccessList(call, block, state_override) => {
2343                self.create_access_list(call, block, state_override).await.to_rpc_result()
2344            }
2345            EthRequest::EthEstimateGas(call, block, state_override, block_overrides) => self
2346                .estimate_gas(call, block, EvmOverrides::new(state_override, block_overrides))
2347                .await
2348                .to_rpc_result(),
2349            EthRequest::EthFillTransaction(request) => {
2350                self.fill_transaction(request).await.to_rpc_result()
2351            }
2352            EthRequest::EthGetRawTransactionByHash(hash) => {
2353                self.raw_transaction(hash).await.to_rpc_result()
2354            }
2355            EthRequest::GetBlobByHash(hash) => {
2356                self.anvil_get_blob_by_versioned_hash(hash).to_rpc_result()
2357            }
2358            EthRequest::GetBlobByTransactionHash(hash) => {
2359                self.anvil_get_blob_by_tx_hash(hash).to_rpc_result()
2360            }
2361            EthRequest::GetGenesisTime(()) => self.anvil_get_genesis_time().to_rpc_result(),
2362            EthRequest::GetLastBlockWallTime(()) => {
2363                self.anvil_get_last_block_wall_time().to_rpc_result()
2364            }
2365            EthRequest::EthGetRawTransactionByBlockHashAndIndex(hash, index) => {
2366                self.raw_transaction_by_block_hash_and_index(hash, index).await.to_rpc_result()
2367            }
2368            EthRequest::EthGetRawTransactionByBlockNumberAndIndex(num, index) => {
2369                self.raw_transaction_by_block_number_and_index(num, index).await.to_rpc_result()
2370            }
2371            EthRequest::EthGetTransactionByBlockHashAndIndex(hash, index) => {
2372                self.transaction_by_block_hash_and_index(hash, index).await.to_rpc_result()
2373            }
2374            EthRequest::EthGetTransactionByBlockNumberAndIndex(num, index) => {
2375                self.transaction_by_block_number_and_index(num, index).await.to_rpc_result()
2376            }
2377            EthRequest::EthGetTransactionReceipt(tx) => {
2378                self.transaction_receipt(tx).await.to_rpc_result()
2379            }
2380            EthRequest::EthGetBlockReceipts(number) => {
2381                self.block_receipts(number).await.to_rpc_result()
2382            }
2383            EthRequest::EthGetUncleByBlockHashAndIndex(hash, index) => {
2384                self.uncle_by_block_hash_and_index(hash, index).await.to_rpc_result()
2385            }
2386            EthRequest::EthGetUncleByBlockNumberAndIndex(num, index) => {
2387                self.uncle_by_block_number_and_index(num, index).await.to_rpc_result()
2388            }
2389            EthRequest::EthGetLogs(filter) => self.logs(filter).await.to_rpc_result(),
2390            EthRequest::EthGetWork(_) => self.work().to_rpc_result(),
2391            EthRequest::EthSyncing(_) => self.syncing().to_rpc_result(),
2392            EthRequest::EthConfig(_) => self.config().to_rpc_result(),
2393            EthRequest::EthSubmitWork(nonce, pow, digest) => {
2394                self.submit_work(nonce, pow, digest).to_rpc_result()
2395            }
2396            EthRequest::EthSubmitHashRate(rate, id) => {
2397                self.submit_hashrate(rate, id).to_rpc_result()
2398            }
2399            EthRequest::EthFeeHistory(count, newest, reward_percentiles) => {
2400                self.fee_history(count, newest, reward_percentiles).await.to_rpc_result()
2401            }
2402            // non eth-standard rpc calls
2403            EthRequest::DebugGetRawTransaction(hash) => {
2404                self.raw_transaction(hash).await.to_rpc_result()
2405            }
2406            EthRequest::DebugGetRawReceipts(block) => {
2407                self.raw_receipts(block).await.to_rpc_result()
2408            }
2409            EthRequest::DebugGetRawTransactions(block) => {
2410                self.raw_transactions(block).await.to_rpc_result()
2411            }
2412            EthRequest::DebugGetRawHeader(block) => self.raw_header(block).await.to_rpc_result(),
2413            EthRequest::DebugGetRawBlock(block) => self.raw_block(block).await.to_rpc_result(),
2414            // non eth-standard rpc calls
2415            EthRequest::DebugClearTxpool(_) => self.debug_clear_txpool().await.to_rpc_result(),
2416            // non eth-standard rpc calls
2417            EthRequest::DebugTraceTransaction(tx, opts) => {
2418                self.debug_trace_transaction(tx, opts).await.to_rpc_result()
2419            }
2420            // non eth-standard rpc calls
2421            EthRequest::DebugTraceCall(tx, block, opts) => {
2422                self.debug_trace_call(tx, block, opts).await.to_rpc_result()
2423            }
2424            EthRequest::DebugCodeByHash(hash, block) => {
2425                self.debug_code_by_hash(hash, block).await.to_rpc_result()
2426            }
2427            EthRequest::DebugDbGet(key) => self.debug_db_get(key).await.to_rpc_result(),
2428            EthRequest::DebugGetModifiedAccountsByNumber(start_number, end_number) => {
2429                self.debug_get_modified_accounts_by_number(start_number, end_number).to_rpc_result()
2430            }
2431            EthRequest::DebugFreeOsMemory(()) => self.debug_free_os_memory().to_rpc_result(),
2432            EthRequest::DebugAccountInfoAt(block_id, tx_index, address) => {
2433                self.debug_account_info_at(block_id, tx_index, address).await.to_rpc_result()
2434            }
2435            EthRequest::DebugExecutionWitness(block) => {
2436                self.debug_execution_witness(block).await.to_rpc_result()
2437            }
2438            EthRequest::DebugTraceBlock(rlp_block, opts) => {
2439                self.debug_trace_block(rlp_block, opts).await.to_rpc_result()
2440            }
2441            EthRequest::DebugTraceBlockByHash(block_hash, opts) => {
2442                self.debug_trace_block_by_hash(block_hash, opts).await.to_rpc_result()
2443            }
2444            EthRequest::DebugTraceBlockByNumber(block_number, opts) => {
2445                self.debug_trace_block_by_number(block_number, opts).await.to_rpc_result()
2446            }
2447            EthRequest::TraceCall(tx, trace_types, block) => {
2448                self.trace_call(tx, trace_types, block).await.to_rpc_result()
2449            }
2450            EthRequest::TraceTransaction(tx) => self.trace_transaction(tx).await.to_rpc_result(),
2451            EthRequest::TraceBlock(block) => self.trace_block(block).await.to_rpc_result(),
2452            EthRequest::TraceFilter(filter) => self.trace_filter(filter).await.to_rpc_result(),
2453            EthRequest::TraceGet(hash, indices) => {
2454                self.trace_get(hash, indices).await.to_rpc_result()
2455            }
2456            EthRequest::TraceReplayBlockTransactions(block, trace_types) => {
2457                self.trace_replay_block_transactions(block, trace_types).await.to_rpc_result()
2458            }
2459            EthRequest::TraceReplayTransaction(transaction, trace_types) => {
2460                self.trace_replay_transaction(transaction, trace_types).await.to_rpc_result()
2461            }
2462            EthRequest::TraceTransactionOpcodeGas(tx_hash) => {
2463                self.trace_transaction_opcode_gas(tx_hash).await.to_rpc_result()
2464            }
2465            EthRequest::TraceBlockOpcodeGas(block_id) => {
2466                self.trace_block_opcode_gas(block_id).await.to_rpc_result()
2467            }
2468            EthRequest::TraceRawTransaction(tx, trace_types, block_number) => {
2469                self.trace_raw_transaction(tx, trace_types, block_number).await.to_rpc_result()
2470            }
2471            EthRequest::TraceCallMany(calls, block_number) => {
2472                self.trace_call_many(calls, block_number).await.to_rpc_result()
2473            }
2474            EthRequest::ImpersonateAccount(addr) => {
2475                self.anvil_impersonate_account(addr).await.to_rpc_result()
2476            }
2477            EthRequest::StopImpersonatingAccount(addr) => {
2478                self.anvil_stop_impersonating_account(addr).await.to_rpc_result()
2479            }
2480            EthRequest::AutoImpersonateAccount(enable) => {
2481                self.anvil_auto_impersonate_account(enable).await.to_rpc_result()
2482            }
2483            EthRequest::ImpersonateSignature(signature, address) => {
2484                self.anvil_impersonate_signature(signature, address).await.to_rpc_result()
2485            }
2486            EthRequest::GetAutoMine(()) => self.anvil_get_auto_mine().to_rpc_result(),
2487            EthRequest::Mine(blocks, interval) => {
2488                self.anvil_mine(blocks, interval).await.to_rpc_result()
2489            }
2490            EthRequest::SetAutomine(enabled) => {
2491                self.anvil_set_auto_mine(enabled).await.to_rpc_result()
2492            }
2493            EthRequest::SetIntervalMining(interval) => {
2494                self.anvil_set_interval_mining(interval).to_rpc_result()
2495            }
2496            EthRequest::GetIntervalMining(()) => self.anvil_get_interval_mining().to_rpc_result(),
2497            EthRequest::SetMiningPaused(paused) => {
2498                self.anvil_set_mining_paused(paused).await.to_rpc_result()
2499            }
2500            EthRequest::GetMiningPaused(()) => self.anvil_get_mining_paused().to_rpc_result(),
2501            EthRequest::DropTransaction(tx) => {
2502                self.anvil_drop_transaction(tx).await.to_rpc_result()
2503            }
2504            EthRequest::DropAllTransactions() => {
2505                self.anvil_drop_all_transactions().await.to_rpc_result()
2506            }
2507            EthRequest::Reset(fork) => {
2508                self.anvil_reset(fork.and_then(|p| p.params)).await.to_rpc_result()
2509            }
2510            EthRequest::SetBalance(addr, val) => {
2511                self.anvil_set_balance(addr, val).await.to_rpc_result()
2512            }
2513            EthRequest::AddBalance(addr, val) => {
2514                self.anvil_add_balance(addr, val).await.to_rpc_result()
2515            }
2516            EthRequest::DealERC20(addr, token_addr, val) => {
2517                self.anvil_deal_erc20(addr, token_addr, val).await.to_rpc_result()
2518            }
2519            EthRequest::DealTIP20(addr, token_addr, val) => {
2520                self.anvil_deal_tip20(addr, token_addr, val).await.to_rpc_result()
2521            }
2522            EthRequest::SetERC20Allowance(owner, spender, token_addr, val) => self
2523                .anvil_set_erc20_allowance(owner, spender, token_addr, val)
2524                .await
2525                .to_rpc_result(),
2526            EthRequest::SetCode(addr, code) => {
2527                self.anvil_set_code(addr, code).await.to_rpc_result()
2528            }
2529            EthRequest::SetNonce(addr, nonce) => {
2530                self.anvil_set_nonce(addr, nonce).await.to_rpc_result()
2531            }
2532            EthRequest::SetStorageAt(addr, slot, val) => {
2533                self.anvil_set_storage_at(addr, slot, val).await.to_rpc_result()
2534            }
2535            EthRequest::SetCoinbase(addr) => self.anvil_set_coinbase(addr).await.to_rpc_result(),
2536            EthRequest::SetNextBlockPrevRandao(prevrandao) => {
2537                self.anvil_set_next_block_prevrandao(prevrandao).await.to_rpc_result()
2538            }
2539            EthRequest::SetNextBlockParentBeaconBlockRoot(root) => {
2540                self.anvil_set_next_block_parent_beacon_block_root(root).await.to_rpc_result()
2541            }
2542            EthRequest::SetChainId(id) => self.anvil_set_chain_id(id).await.to_rpc_result(),
2543            EthRequest::SetLogging(log) => self.anvil_set_logging(log).await.to_rpc_result(),
2544            EthRequest::SetMinGasPrice(gas) => {
2545                self.anvil_set_min_gas_price(gas).await.to_rpc_result()
2546            }
2547            EthRequest::SetNextBlockBaseFeePerGas(gas) => {
2548                self.anvil_set_next_block_base_fee_per_gas(gas).await.to_rpc_result()
2549            }
2550            EthRequest::DumpState(preserve_historical_states) => self
2551                .anvil_dump_state(preserve_historical_states.and_then(|s| s.params))
2552                .await
2553                .to_rpc_result(),
2554            EthRequest::LoadState(buf) => self.anvil_load_state(buf).await.to_rpc_result(),
2555            EthRequest::NodeInfo(_) => self.anvil_node_info().await.to_rpc_result(),
2556            EthRequest::AnvilMetadata(_) => self.anvil_metadata().await.to_rpc_result(),
2557            EthRequest::EvmSnapshot(_) => self.evm_snapshot().await.to_rpc_result(),
2558            EthRequest::EvmRevert(id) => self.evm_revert(id).await.to_rpc_result(),
2559            EthRequest::EvmIncreaseTime(time) => self.evm_increase_time(time).await.to_rpc_result(),
2560            EthRequest::EvmSetNextBlockTimeStamp(time) => {
2561                if time >= U256::from(u64::MAX) {
2562                    return ResponseResult::Error(RpcError::invalid_params(
2563                        "The timestamp is too big",
2564                    ));
2565                }
2566                let time = time.to::<u64>();
2567                self.evm_set_next_block_timestamp(time).to_rpc_result()
2568            }
2569            EthRequest::EvmSetTime(timestamp) => {
2570                if timestamp >= U256::from(u64::MAX) {
2571                    return ResponseResult::Error(RpcError::invalid_params(
2572                        "The timestamp is too big",
2573                    ));
2574                }
2575                // evm_setTime accepts either seconds or milliseconds for Ganache compatibility.
2576                // Timestamps above 1e12 are interpreted as milliseconds and converted to
2577                // seconds; below that threshold they are treated as seconds directly.
2578                let raw = timestamp.to::<u64>();
2579                let time = if raw > 1_000_000_000_000 {
2580                    Duration::from_millis(raw).as_secs()
2581                } else {
2582                    raw
2583                };
2584                self.evm_set_time(time).to_rpc_result()
2585            }
2586            EthRequest::EvmSetBlockGasLimit(gas_limit) => {
2587                self.evm_set_block_gas_limit(gas_limit).to_rpc_result()
2588            }
2589            EthRequest::EvmSetBlockTimeStampInterval(time) => {
2590                self.evm_set_block_timestamp_interval(time).to_rpc_result()
2591            }
2592            EthRequest::EvmRemoveBlockTimeStampInterval(()) => {
2593                self.evm_remove_block_timestamp_interval().to_rpc_result()
2594            }
2595            EthRequest::EvmMine(mine) => {
2596                self.evm_mine(mine.and_then(|p| p.params)).await.to_rpc_result()
2597            }
2598            EthRequest::EvmMineDetailed(mine) => {
2599                self.evm_mine_detailed(mine.and_then(|p| p.params)).await.to_rpc_result()
2600            }
2601            EthRequest::SetRpcUrl(url) => self.anvil_set_rpc_url(url).await.to_rpc_result(),
2602            EthRequest::EthSendUnsignedTransaction(tx) => {
2603                self.eth_send_unsigned_transaction(*tx).await.to_rpc_result()
2604            }
2605            EthRequest::EthNewFilter(filter) => self.new_filter(filter).await.to_rpc_result(),
2606            EthRequest::EthGetFilterChanges(id) => self.get_filter_changes(&id).await,
2607            EthRequest::EthNewBlockFilter(_) => self.new_block_filter().await.to_rpc_result(),
2608            EthRequest::EthNewPendingTransactionFilter(full) => {
2609                self.new_pending_transaction_filter(full.unwrap_or(false)).await.to_rpc_result()
2610            }
2611            EthRequest::EthGetFilterLogs(id) => self.get_filter_logs(&id).await.to_rpc_result(),
2612            EthRequest::EthUninstallFilter(id) => self.uninstall_filter(&id).await.to_rpc_result(),
2613            EthRequest::TxPoolStatus(_) => self.txpool_status().await.to_rpc_result(),
2614            EthRequest::TxPoolInspect(_) => self.txpool_inspect().await.to_rpc_result(),
2615            EthRequest::TxPoolContent(_) => self.txpool_content().await.to_rpc_result(),
2616            EthRequest::TxPoolContentFrom(from) => {
2617                self.txpool_content_from(from).await.to_rpc_result()
2618            }
2619            EthRequest::ErigonGetHeaderByNumber(num) => {
2620                self.erigon_get_header_by_number(num).await.to_rpc_result()
2621            }
2622            EthRequest::OtsGetApiLevel(_) => self.ots_get_api_level().await.to_rpc_result(),
2623            EthRequest::OtsGetInternalOperations(hash) => {
2624                self.ots_get_internal_operations(hash).await.to_rpc_result()
2625            }
2626            EthRequest::OtsHasCode(addr, num) => self.ots_has_code(addr, num).await.to_rpc_result(),
2627            EthRequest::OtsTraceTransaction(hash) => {
2628                self.ots_trace_transaction(hash).await.to_rpc_result()
2629            }
2630            EthRequest::OtsGetTransactionError(hash) => {
2631                self.ots_get_transaction_error(hash).await.to_rpc_result()
2632            }
2633            EthRequest::OtsGetBlockDetails(num) => {
2634                self.ots_get_block_details(num).await.to_rpc_result()
2635            }
2636            EthRequest::OtsGetBlockDetailsByHash(hash) => {
2637                self.ots_get_block_details_by_hash(hash).await.to_rpc_result()
2638            }
2639            EthRequest::OtsGetBlockTransactions(num, page, page_size) => {
2640                self.ots_get_block_transactions(num, page, page_size).await.to_rpc_result()
2641            }
2642            EthRequest::OtsSearchTransactionsBefore(address, num, page_size) => {
2643                self.ots_search_transactions_before(address, num, page_size).await.to_rpc_result()
2644            }
2645            EthRequest::OtsSearchTransactionsAfter(address, num, page_size) => {
2646                self.ots_search_transactions_after(address, num, page_size).await.to_rpc_result()
2647            }
2648            EthRequest::OtsGetTransactionBySenderAndNonce(address, nonce) => {
2649                self.ots_get_transaction_by_sender_and_nonce(address, nonce).await.to_rpc_result()
2650            }
2651            EthRequest::EthGetTransactionBySenderAndNonce(sender, nonce) => {
2652                self.transaction_by_sender_and_nonce(sender, nonce).await.to_rpc_result()
2653            }
2654            EthRequest::OtsGetContractCreator(address) => {
2655                self.ots_get_contract_creator(address).await.to_rpc_result()
2656            }
2657            EthRequest::RemovePoolTransactions(address) => {
2658                self.anvil_remove_pool_transactions(address).await.to_rpc_result()
2659            }
2660            EthRequest::Reorg(reorg_options) => {
2661                self.anvil_reorg(reorg_options).await.to_rpc_result()
2662            }
2663            EthRequest::Rollback(depth) => self.anvil_rollback(depth).await.to_rpc_result(),
2664            EthRequest::SetFeeToken(user, token) => {
2665                self.anvil_set_fee_token(user, token).await.to_rpc_result()
2666            }
2667            EthRequest::SetValidatorFeeToken(validator, token) => {
2668                self.anvil_set_validator_fee_token(validator, token).await.to_rpc_result()
2669            }
2670            EthRequest::SetFeeAmmLiquidity(user_token, validator_token, amount) => self
2671                .anvil_set_fee_amm_liquidity(user_token, validator_token, amount)
2672                .await
2673                .to_rpc_result(),
2674            EthRequest::ConsensusGetFinalization(query) => {
2675                self.consensus_get_finalization(query).await.to_rpc_result()
2676            }
2677            EthRequest::ConsensusGetLatest(()) => self.consensus_get_latest().await.to_rpc_result(),
2678            EthRequest::TempoConsensusIdentity(()) => {
2679                self.anvil_tempo_consensus_identity().await.to_rpc_result()
2680            }
2681            EthRequest::TempoRotateConsensusIdentity(()) => {
2682                self.anvil_tempo_rotate_consensus_identity().await.to_rpc_result()
2683            }
2684        }
2685    }
2686
2687    fn sign_request(&self, from: &Address, typed_tx: FoundryTypedTx) -> Result<FoundryTxEnvelope> {
2688        match typed_tx {
2689            #[cfg(feature = "optimism")]
2690            FoundryTypedTx::Deposit(_) => return Ok(typed_tx.into_impersonated()),
2691            _ => {
2692                for signer in self.signers.iter() {
2693                    if signer.accounts().contains(from) {
2694                        return signer.sign_transaction_from(from, typed_tx);
2695                    }
2696                }
2697            }
2698        }
2699        Err(BlockchainError::NoSignerAvailable)
2700    }
2701
2702    async fn inner_raw_transaction(&self, hash: B256) -> Result<Option<Bytes>> {
2703        match self.pool.get_transaction(hash) {
2704            Some(tx) => Ok(Some(tx.transaction.encoded_2718().into())),
2705            None => match self.backend.transaction_by_hash(hash).await? {
2706                Some(tx) => encode_rpc_transaction(&tx).map(Some),
2707                None => Ok(None),
2708            },
2709        }
2710    }
2711
2712    /// Returns balance of the given account.
2713    ///
2714    /// Handler for ETH RPC call: `eth_getBalance`
2715    pub async fn balance(&self, address: Address, block_number: Option<BlockId>) -> Result<U256> {
2716        node_info!("eth_getBalance");
2717        let block_request = self.block_request(block_number).await?;
2718
2719        // check if the number predates the fork, if in fork mode
2720        if let BlockRequest::Number(number) = block_request
2721            && let Some(fork) = self.get_fork()
2722            && fork.predates_fork(number)
2723        {
2724            return Ok(fork.get_balance(address, number).await?);
2725        }
2726
2727        self.backend.get_balance(address, Some(block_request)).await
2728    }
2729
2730    /// Returns the ethereum account.
2731    ///
2732    /// Handler for ETH RPC call: `eth_getAccount`
2733    pub async fn get_account(
2734        &self,
2735        address: Address,
2736        block_number: Option<BlockId>,
2737    ) -> Result<TrieAccount> {
2738        node_info!("eth_getAccount");
2739        let block_request = self.block_request(block_number).await?;
2740
2741        // check if the number predates the fork, if in fork mode
2742        if let BlockRequest::Number(number) = block_request
2743            && let Some(fork) = self.get_fork()
2744            && fork.predates_fork(number)
2745        {
2746            return Ok(fork.get_account(address, number).await?);
2747        }
2748
2749        self.backend.get_account_at_block(address, Some(block_request)).await
2750    }
2751
2752    /// Returns the account information including balance, nonce, code and storage
2753    ///
2754    /// Note: This isn't support by all providers
2755    pub async fn get_account_info(
2756        &self,
2757        address: Address,
2758        block_number: Option<BlockId>,
2759    ) -> Result<alloy_rpc_types::eth::AccountInfo> {
2760        node_info!("eth_getAccountInfo");
2761
2762        let block_request = self.block_request(block_number).await?;
2763        if let BlockRequest::Number(number) = block_request
2764            && let Some(fork) = self.get_fork()
2765        {
2766            trace!(target: "node", "get_account_info: fork block {}, requested block {number}", fork.block_number());
2767            if block_number.is_some_and(|block| !block.is_latest())
2768                && fork.predates_fork_inclusive(number)
2769            {
2770                if fork.requires_account_info() {
2771                    return Ok(fork.get_account_info(address, number).await?);
2772                }
2773                let balance = fork.get_balance(address, number).map_err(BlockchainError::from);
2774                let code = fork.get_code(address, number).map_err(BlockchainError::from);
2775                let nonce = fork.get_nonce(address, number).map_err(BlockchainError::from);
2776                let (balance, code, nonce) = try_join!(balance, code, nonce)?;
2777                return Ok(alloy_rpc_types::eth::AccountInfo { balance, nonce, code });
2778            }
2779        }
2780
2781        self.backend.get_account_info_at_block(address, Some(block_request)).await
2782    }
2783    /// Returns content of the storage at given address.
2784    ///
2785    /// Handler for ETH RPC call: `eth_getStorageAt`
2786    pub async fn storage_at(
2787        &self,
2788        address: Address,
2789        index: U256,
2790        block_number: Option<BlockId>,
2791    ) -> Result<B256> {
2792        node_info!("eth_getStorageAt");
2793        let block_request = self.block_request(block_number).await?;
2794
2795        // check if the number predates the fork, if in fork mode
2796        if let BlockRequest::Number(number) = block_request
2797            && let Some(fork) = self.get_fork()
2798            && fork.predates_fork(number)
2799        {
2800            return Ok(B256::from(
2801                fork.storage_at(address, index, Some(BlockNumber::Number(number))).await?,
2802            ));
2803        }
2804
2805        self.backend.storage_at(address, index, Some(block_request)).await
2806    }
2807
2808    /// Returns storage values for multiple accounts and slots in a single call.
2809    ///
2810    /// Handler for ETH RPC call: `eth_getStorageValues`
2811    pub async fn storage_values(
2812        &self,
2813        requests: HashMap<Address, Vec<B256>>,
2814        block_number: Option<BlockId>,
2815    ) -> Result<HashMap<Address, Vec<B256>>> {
2816        node_info!("eth_getStorageValues");
2817
2818        if requests.is_empty() {
2819            return Err(RpcError::invalid_params("empty request").into());
2820        }
2821
2822        let total_slots: usize = requests.values().map(|s| s.len()).sum();
2823        if total_slots > 1024 {
2824            return Err(BlockchainError::RpcError(RpcError::invalid_params(format!(
2825                "total slot count {total_slots} exceeds limit 1024"
2826            ))));
2827        }
2828
2829        let block_request = self.block_request(block_number).await?;
2830
2831        // check if the number predates the fork, if in fork mode
2832        if let BlockRequest::Number(number) = block_request
2833            && let Some(fork) = self.get_fork()
2834            && fork.predates_fork(number)
2835        {
2836            let mut result: HashMap<Address, Vec<B256>> = HashMap::default();
2837            for (address, slots) in requests {
2838                let mut values = Vec::with_capacity(slots.len());
2839                for slot in &slots {
2840                    let val = fork
2841                        .storage_at(address, (*slot).into(), Some(BlockNumber::Number(number)))
2842                        .await?;
2843                    values.push(B256::from(val));
2844                }
2845                result.insert(address, values);
2846            }
2847            return Ok(result);
2848        }
2849
2850        self.backend.storage_values(requests, Some(block_request)).await
2851    }
2852
2853    /// Returns block with given number.
2854    ///
2855    /// Handler for ETH RPC call: `eth_getBlockByNumber`
2856    pub async fn block_by_number(&self, number: BlockNumber) -> Result<Option<AnyRpcBlock>> {
2857        node_info!("eth_getBlockByNumber");
2858        if number.is_pending() {
2859            return Ok(Some(self.pending_block().await?));
2860        }
2861
2862        self.backend.block_by_number(number).await
2863    }
2864
2865    /// Returns block header with given number.
2866    ///
2867    /// Handler for ETH RPC call: `eth_getHeaderByNumber`
2868    pub async fn header_by_number(
2869        &self,
2870        number: BlockNumber,
2871    ) -> Result<Option<WithOtherFields<AnyRpcHeader>>> {
2872        node_info!("eth_getHeaderByNumber");
2873        if number.is_pending() {
2874            let WithOtherFields { inner: block, other } = self.pending_block().await?.0;
2875            return Ok(Some(WithOtherFields { inner: block.header, other }));
2876        }
2877
2878        Ok(self.backend.block_by_number(number).await?.map(|block| {
2879            let WithOtherFields { inner: block, other } = block.0;
2880            WithOtherFields { inner: block.header, other }
2881        }))
2882    }
2883
2884    /// Returns a _full_ block with given number
2885    ///
2886    /// Handler for ETH RPC call: `eth_getBlockByNumber`
2887    pub async fn block_by_number_full(&self, number: BlockNumber) -> Result<Option<AnyRpcBlock>> {
2888        node_info!("eth_getBlockByNumber");
2889        if number.is_pending() {
2890            return self.pending_block_full().await;
2891        }
2892        self.backend.block_by_number_full(number).await
2893    }
2894
2895    /// Returns the EIP-7928 block access list for a block.
2896    ///
2897    /// Handler for ETH RPC call: `eth_getBlockAccessList`
2898    pub async fn block_access_list(&self, block_id: BlockId) -> Result<Option<serde_json::Value>> {
2899        node_info!("eth_getBlockAccessList");
2900        let block_request = self.block_request(Some(block_id)).await?;
2901        let BlockRequest::Number(number) = block_request else { return Ok(None) };
2902
2903        if let Some(fork) = self.get_fork()
2904            && fork.predates_fork_inclusive(number)
2905        {
2906            return Ok(fork.block_access_list(block_id).await?);
2907        }
2908
2909        let block_access_list = match block_id {
2910            BlockId::Hash(hash) => self.backend.block_access_list_by_hash(hash.block_hash),
2911            BlockId::Number(_) => self.backend.block_access_list_by_number(number),
2912        };
2913        Ok(block_access_list
2914            .map(|bal| serde_json::to_value(bal).expect("BAL serialization is infallible")))
2915    }
2916
2917    /// Returns the EIP-7928 block access list for a block hash.
2918    ///
2919    /// Handler for ETH RPC call: `eth_getBlockAccessListByBlockHash`
2920    pub async fn block_access_list_by_hash(
2921        &self,
2922        block_hash: B256,
2923    ) -> Result<Option<serde_json::Value>> {
2924        node_info!("eth_getBlockAccessListByBlockHash");
2925        if let Some(block_access_list) = self.backend.block_access_list_by_hash(block_hash) {
2926            return Ok(Some(
2927                serde_json::to_value(block_access_list).expect("BAL serialization is infallible"),
2928            ));
2929        }
2930
2931        let Some(fork) = self.get_fork() else { return Ok(None) };
2932
2933        // Only blocks we know to be mined after the fork point are guaranteed to be unknown
2934        // upstream. Anything else, including hashes we cannot resolve locally, is left to the fork.
2935        if let Some(block) = self.backend.get_block_by_hash(block_hash)
2936            && !fork.predates_fork_inclusive(block.header.number)
2937        {
2938            return Ok(None);
2939        }
2940
2941        Ok(fork.block_access_list_by_hash(block_hash).await?)
2942    }
2943
2944    /// Returns the EIP-7928 block access list for a block number.
2945    ///
2946    /// Handler for ETH RPC call: `eth_getBlockAccessListByBlockNumber`
2947    pub async fn block_access_list_by_number(
2948        &self,
2949        block_number: BlockNumber,
2950    ) -> Result<Option<serde_json::Value>> {
2951        node_info!("eth_getBlockAccessListByBlockNumber");
2952        let block_request = self.block_request(Some(BlockId::Number(block_number))).await?;
2953        let BlockRequest::Number(number) = block_request else { return Ok(None) };
2954
2955        if let Some(fork) = self.get_fork()
2956            && fork.predates_fork_inclusive(number)
2957        {
2958            return Ok(fork.block_access_list_by_number(block_number).await?);
2959        }
2960
2961        Ok(self
2962            .backend
2963            .block_access_list_by_number(number)
2964            .map(|bal| serde_json::to_value(bal).expect("BAL serialization is infallible")))
2965    }
2966
2967    /// Returns the raw EIP-7928 block access list for a block.
2968    ///
2969    /// Handler for ETH RPC call: `eth_getBlockAccessListRaw`
2970    pub async fn block_access_list_raw(&self, block_id: BlockId) -> Result<Option<Bytes>> {
2971        node_info!("eth_getBlockAccessListRaw");
2972        let block_request = self.block_request(Some(block_id)).await?;
2973        let BlockRequest::Number(number) = block_request else { return Ok(None) };
2974
2975        if let Some(fork) = self.get_fork()
2976            && fork.predates_fork_inclusive(number)
2977        {
2978            return Ok(fork.block_access_list_raw(block_id).await?);
2979        }
2980
2981        let block_access_list = match block_id {
2982            BlockId::Hash(hash) => self.backend.block_access_list_by_hash(hash.block_hash),
2983            BlockId::Number(_) => self.backend.block_access_list_by_number(number),
2984        };
2985        Ok(block_access_list.map(|bal| {
2986            let mut encoded = Vec::new();
2987            alloy_rlp::encode_list(&bal, &mut encoded);
2988            encoded.into()
2989        }))
2990    }
2991
2992    /// Returns the number of transactions sent from given address at given time (block number).
2993    ///
2994    /// Also checks the pending transactions if `block_number` is
2995    /// `BlockId::Number(BlockNumber::Pending)`
2996    ///
2997    /// Handler for ETH RPC call: `eth_getTransactionCount`
2998    pub async fn transaction_count(
2999        &self,
3000        address: Address,
3001        block_number: Option<BlockId>,
3002    ) -> Result<U256> {
3003        node_info!("eth_getTransactionCount");
3004        self.get_transaction_count(address, block_number).await.map(U256::from)
3005    }
3006
3007    /// Returns a protocol or EIP-8130 channel nonce.
3008    #[cfg(feature = "base")]
3009    pub async fn transaction_count_with_key(
3010        &self,
3011        address: Address,
3012        block_number: Option<BlockId>,
3013        nonce_key: Option<U256>,
3014    ) -> Result<U256> {
3015        let Some(nonce_key) = nonce_key else {
3016            return self.transaction_count(address, block_number).await;
3017        };
3018        if nonce_key.is_zero() {
3019            return self.transaction_count(address, block_number).await;
3020        }
3021
3022        let block_request = self.block_request(block_number).await?;
3023        let timestamp = self.backend.block_request_timestamp(&block_request).await?;
3024        self.backend.ensure_base_eip8130_active_at(timestamp)?;
3025        if nonce_key == Eip8130Constants::NONCE_KEY_MAX {
3026            return Err(RpcError::invalid_params(
3027                "nonce_key NONCE_KEY_MAX selects the expiring-nonce channel which has no \
3028                 per-channel counter",
3029            )
3030            .into());
3031        }
3032        let slot = NonceManagerStorage::nonce_slot(address, nonce_key)
3033            .map_err(|error| RpcError::invalid_params(error.to_string()))?;
3034        let word = self
3035            .backend
3036            .storage_at(NonceManagerStorage::ADDRESS, slot, Some(block_request))
3037            .await?;
3038        Ok(Eip8130Nonce::decode_channel_nonce(word.into()))
3039    }
3040
3041    /// Returns the number of transactions in a block with given block number.
3042    ///
3043    /// Handler for ETH RPC call: `eth_getBlockTransactionCountByNumber`
3044    pub async fn block_transaction_count_by_number(
3045        &self,
3046        block_number: BlockNumber,
3047    ) -> Result<Option<U256>> {
3048        node_info!("eth_getBlockTransactionCountByNumber");
3049        if block_number.is_pending() {
3050            let txs = self.pool.ready_transactions().collect();
3051            let block = self.backend.pending_block(txs).await?;
3052            return Ok(Some(U256::from(block.block.body.transactions.len())));
3053        }
3054
3055        let block = self.backend.block_by_number(block_number).await?;
3056        let txs = block.map(|b| match b.transactions() {
3057            BlockTransactions::Full(txs) => U256::from(txs.len()),
3058            BlockTransactions::Hashes(txs) => U256::from(txs.len()),
3059            BlockTransactions::Uncle => U256::ZERO,
3060        });
3061        Ok(txs)
3062    }
3063
3064    /// Returns the code at given address at given time (block number).
3065    ///
3066    /// Handler for ETH RPC call: `eth_getCode`
3067    pub async fn get_code(&self, address: Address, block_number: Option<BlockId>) -> Result<Bytes> {
3068        node_info!("eth_getCode");
3069        let block_request = self.block_request(block_number).await?;
3070        // check if the number predates the fork, if in fork mode
3071        if let BlockRequest::Number(number) = block_request
3072            && let Some(fork) = self.get_fork()
3073            && fork.predates_fork(number)
3074        {
3075            return Ok(fork.get_code(address, number).await?);
3076        }
3077        self.backend.get_code(address, Some(block_request)).await
3078    }
3079
3080    /// Returns the account and storage values of the specified account including the Merkle-proof.
3081    /// This call can be used to verify that the data you are pulling from is not tampered with.
3082    ///
3083    /// Handler for ETH RPC call: `eth_getProof`
3084    pub async fn get_proof(
3085        &self,
3086        address: Address,
3087        keys: Vec<B256>,
3088        block_number: Option<BlockId>,
3089    ) -> Result<EIP1186AccountProofResponse> {
3090        node_info!("eth_getProof");
3091        let block_request = self.block_request(block_number).await?;
3092
3093        // If we're in forking mode, or still on the forked block (no blocks mined yet) then we can
3094        // delegate the call.
3095        if let BlockRequest::Number(number) = block_request
3096            && let Some(fork) = self.get_fork()
3097            && fork.predates_fork_inclusive(number)
3098        {
3099            return Ok(fork.get_proof(address, keys, Some(number.into())).await?);
3100        }
3101
3102        let proof = self.backend.prove_account_at(address, keys, Some(block_request)).await?;
3103        Ok(proof)
3104    }
3105
3106    /// Signs a transaction
3107    ///
3108    /// Handler for ETH RPC call: `eth_signTransaction`
3109    pub async fn sign_transaction(
3110        &self,
3111        request: WithOtherFields<TransactionRequest>,
3112    ) -> Result<String> {
3113        node_info!("eth_signTransaction");
3114        let request = self.parse_transaction_request(request)?;
3115
3116        let from = request.from().map(Ok).unwrap_or_else(|| {
3117            self.accounts()?.first().copied().ok_or(BlockchainError::NoSignerAvailable)
3118        })?;
3119
3120        let nonce = self.request_nonce_for_transaction(&request, from).await?;
3121
3122        let request = self.build_tx_request(request, nonce).await?;
3123
3124        let signed_transaction = self.sign_request(&from, request)?.encoded_2718();
3125        Ok(alloy_primitives::hex::encode_prefixed(signed_transaction))
3126    }
3127
3128    /// Sends a transaction
3129    ///
3130    /// Handler for ETH RPC call: `eth_sendTransaction`
3131    pub async fn send_transaction(
3132        &self,
3133        request: WithOtherFields<TransactionRequest>,
3134    ) -> Result<TxHash> {
3135        node_info!("eth_sendTransaction");
3136        let request = self.parse_transaction_request(request)?;
3137
3138        let from = request.from().map(Ok).unwrap_or_else(|| {
3139            self.accounts()?.first().copied().ok_or(BlockchainError::NoSignerAvailable)
3140        })?;
3141        // Keep nonce selection and pool insertion atomic with respect to other requests from
3142        // this sender. Explicit nonces retain the pool's normal replacement behavior.
3143        let _nonce_guard = if request.nonce().is_none() {
3144            let lock = self.nonce_locks.write().entry(from).or_default().clone();
3145            Some(lock.lock_owned().await)
3146        } else {
3147            None
3148        };
3149        let nonce = self.request_nonce_for_transaction(&request, from).await?;
3150
3151        let typed_tx = self.build_tx_request(request, nonce).await?;
3152
3153        // if the sender is currently impersonated we need to "bypass" signing
3154        let pending_transaction = if self.is_impersonated(from) {
3155            let transaction = typed_tx.into_impersonated();
3156            self.ensure_typed_transaction_supported(&transaction)?;
3157            trace!(target : "node", ?from, "eth_sendTransaction: impersonating");
3158            PendingTransaction::with_impersonated(transaction, from)
3159        } else {
3160            let transaction = self.sign_request(&from, typed_tx)?;
3161            self.ensure_typed_transaction_supported(&transaction)?;
3162            PendingTransaction::new(transaction)?
3163        };
3164        self.add_pending_transaction(pending_transaction).await
3165    }
3166
3167    /// Resends a pending transaction with an updated gas price or gas limit.
3168    ///
3169    /// Handler for ETH RPC call: `eth_resend`
3170    pub async fn resend_transaction(
3171        &self,
3172        request: WithOtherFields<TransactionRequest>,
3173        gas_price: Option<U256>,
3174        gas_limit: Option<U64>,
3175    ) -> Result<TxHash> {
3176        node_info!("eth_resend");
3177        let mut request = self.parse_transaction_request(request)?;
3178
3179        let from = request.from().map(Ok).unwrap_or_else(|| {
3180            self.accounts()?.first().copied().ok_or(BlockchainError::NoSignerAvailable)
3181        })?;
3182        let nonce = request.nonce().ok_or_else(|| {
3183            BlockchainError::InvalidTransactionRequest(
3184                "missing transaction nonce in transaction spec".to_string(),
3185            )
3186        })?;
3187
3188        if !self.pool.contains_sender_nonce(from, nonce) {
3189            return Err(BlockchainError::TransactionNotFound);
3190        }
3191
3192        if let Some(gas_price) = gas_price.filter(|gas_price| !gas_price.is_zero()) {
3193            request.set_gas_price(gas_price.saturating_to());
3194        }
3195
3196        if let Some(gas_limit) = gas_limit.filter(|gas_limit| *gas_limit != U64::ZERO) {
3197            request.set_gas_limit(gas_limit.to());
3198        }
3199
3200        let typed_tx = self.build_tx_request(request, nonce).await?;
3201
3202        let pending_transaction = if self.is_impersonated(from) {
3203            let transaction = typed_tx.into_impersonated();
3204            self.ensure_typed_transaction_supported(&transaction)?;
3205            trace!(target : "node", ?from, "eth_resend: impersonating");
3206            PendingTransaction::with_impersonated(transaction, from)
3207        } else {
3208            let transaction = self.sign_request(&from, typed_tx)?;
3209            self.ensure_typed_transaction_supported(&transaction)?;
3210            PendingTransaction::new(transaction)?
3211        };
3212
3213        self.add_pending_transaction(pending_transaction).await
3214    }
3215
3216    /// Waits for a transaction to be included in a block and returns its receipt (no timeout).
3217    async fn await_transaction_inclusion(&self, hash: TxHash) -> Result<FoundryTxReceipt> {
3218        let mut stream = self.new_block_notifications();
3219        // Check if the transaction is already included before listening for new blocks.
3220        if let Some(receipt) = self.backend.transaction_receipt(hash).await? {
3221            return Ok(receipt);
3222        }
3223        while let Some(notification) = stream.next().await {
3224            if let Some(new_block) = notification.as_new_block()
3225                && let Some(block) = self.backend.get_block_by_hash(new_block.hash)
3226                && block.body.transactions.iter().any(|tx| tx.hash() == hash)
3227                && let Some(receipt) = self.backend.transaction_receipt(hash).await?
3228            {
3229                return Ok(receipt);
3230            }
3231        }
3232
3233        Err(BlockchainError::Message("Failed to await transaction inclusion".to_string()))
3234    }
3235
3236    fn transaction_confirmation_timeout(timeout_ms: Option<u64>) -> Duration {
3237        const TIMEOUT_DURATION: Duration = Duration::from_secs(30);
3238        timeout_ms
3239            .filter(|timeout_ms| *timeout_ms > 0)
3240            .map(Duration::from_millis)
3241            .map(|timeout| timeout.min(TIMEOUT_DURATION))
3242            .unwrap_or(TIMEOUT_DURATION)
3243    }
3244
3245    /// Waits for a transaction to be included in a block and returns its receipt, with timeout.
3246    async fn check_transaction_inclusion(
3247        &self,
3248        hash: TxHash,
3249        timeout_ms: Option<u64>,
3250    ) -> Result<FoundryTxReceipt> {
3251        let timeout_duration = Self::transaction_confirmation_timeout(timeout_ms);
3252        tokio::time::timeout(timeout_duration, self.await_transaction_inclusion(hash))
3253            .await
3254            .unwrap_or_else(|_elapsed| {
3255                Err(BlockchainError::TransactionConfirmationTimeout {
3256                    hash,
3257                    duration: timeout_duration,
3258                })
3259            })
3260    }
3261
3262    /// Sends a transaction and waits for receipt
3263    ///
3264    /// Handler for ETH RPC call: `eth_sendTransactionSync`
3265    pub async fn send_transaction_sync(
3266        &self,
3267        request: WithOtherFields<TransactionRequest>,
3268    ) -> Result<FoundryTxReceipt> {
3269        node_info!("eth_sendTransactionSync");
3270        let hash = self.send_transaction(request).await?;
3271
3272        let receipt = self.check_transaction_inclusion(hash, None).await?;
3273
3274        Ok(receipt)
3275    }
3276
3277    /// Sends signed transaction, returning its hash.
3278    ///
3279    /// Handler for ETH RPC call: `eth_sendRawTransaction`
3280    pub async fn send_raw_transaction(&self, tx: Bytes) -> Result<TxHash> {
3281        node_info!("eth_sendRawTransaction");
3282        if tx.is_empty() {
3283            return Err(BlockchainError::EmptyRawTransactionData);
3284        }
3285
3286        // Built-in Tempo fee payer: raw transactions submitted in the fee payer service encoding
3287        // or carrying the sponsorship placeholder ask the node to sponsor them before submission
3288        // (the sign-and-relay mode of the fee payer service contract).
3289        let service_encoded = if self.backend.is_tempo() {
3290            normalize_fee_payer_service_encoding(tx.as_ref())
3291        } else {
3292            None
3293        };
3294        let raw = service_encoded.map(Bytes::from).unwrap_or(tx);
3295
3296        let transaction = if raw.first() == Some(&EIP4844_TX_TYPE_ID) {
3297            // Pooled EIP-4844 decoding uses large stack frames for inline blobs. Isolate it from
3298            // the already-large RPC dispatcher without increasing every worker's stack.
3299            let raw = raw.clone();
3300            tokio::task::spawn_blocking(move || FoundryTxEnvelope::decode_2718(&mut raw.as_ref()))
3301                .await
3302                .map_err(|_| {
3303                    BlockchainError::Internal("transaction decoding task panicked".into())
3304                })?
3305        } else {
3306            FoundryTxEnvelope::decode_2718(&mut raw.as_ref())
3307        }
3308        .map_err(|_| BlockchainError::FailedToDecodeSignedTransaction)?;
3309
3310        self.ensure_typed_transaction_supported(&transaction)?;
3311
3312        let transaction = match transaction {
3313            FoundryTxEnvelope::Tempo(aa_tx)
3314                if self.backend.is_tempo()
3315                    && aa_tx.tx().fee_payer_signature == Some(FEE_PAYER_SIGNATURE_MARKER) =>
3316            {
3317                FoundryTxEnvelope::Tempo(self.sponsor_sign_tempo_transaction(aa_tx).await?)
3318            }
3319            transaction => transaction,
3320        };
3321
3322        if self.backend.is_tempo() && TempoHardfork::from(self.backend.hardfork()).is_t5() {
3323            let classification = classify_payment_lane(raw.as_ref());
3324            trace!(target: "node", tx = ?transaction.hash(), ?classification, "classified transaction lane");
3325        }
3326
3327        #[cfg(feature = "base")]
3328        let is_eip8130 = transaction.is_eip8130();
3329        let pending_transaction = PendingTransaction::new(transaction).map_err(|error| {
3330            #[cfg(feature = "base")]
3331            if is_eip8130 {
3332                return BlockchainError::Eip8130TransactionRejected(error.to_string());
3333            }
3334            BlockchainError::RecoveryError(error)
3335        })?;
3336
3337        self.add_pending_transaction(pending_transaction).await
3338    }
3339
3340    /// Sends a signed transaction with an ignored transaction condition.
3341    ///
3342    /// Handler for ETH RPC call: `eth_sendRawTransactionConditional`
3343    pub async fn send_raw_transaction_conditional(
3344        &self,
3345        tx: Bytes,
3346        _condition: TransactionConditional,
3347    ) -> Result<TxHash> {
3348        node_info!("eth_sendRawTransactionConditional");
3349        self.send_raw_transaction(tx).await
3350    }
3351
3352    /// Classifies a raw transaction with the active Anvil Tempo/T5 payment-lane classifier.
3353    pub fn anvil_classify_transaction(&self, tx: Bytes) -> Result<PaymentLaneClassification> {
3354        node_info!("anvil_classifyTransaction");
3355        let mut data = tx.as_ref();
3356        if data.is_empty() {
3357            return Err(BlockchainError::EmptyRawTransactionData);
3358        }
3359
3360        FoundryTxEnvelope::decode_2718(&mut data)
3361            .map_err(|_| BlockchainError::FailedToDecodeSignedTransaction)?;
3362
3363        Ok(self.classify_transaction_lane(tx.as_ref()))
3364    }
3365
3366    fn classify_transaction_lane(&self, raw: &[u8]) -> PaymentLaneClassification {
3367        if !self.backend.is_tempo() {
3368            return PaymentLaneClassification::general(PaymentLaneReason::NotTempo);
3369        }
3370
3371        if !TempoHardfork::from(self.backend.hardfork()).is_t5() {
3372            return PaymentLaneClassification::general(PaymentLaneReason::T5NotActive);
3373        }
3374
3375        classify_payment_lane(raw)
3376    }
3377
3378    /// Sends signed transaction, returning its receipt.
3379    ///
3380    /// Handler for ETH RPC call: `eth_sendRawTransactionSync`
3381    pub async fn send_raw_transaction_sync(
3382        &self,
3383        tx: Bytes,
3384        timeout_ms: Option<u64>,
3385    ) -> Result<FoundryTxReceipt> {
3386        node_info!("eth_sendRawTransactionSync");
3387
3388        let hash = self.send_raw_transaction(tx).await?;
3389        let receipt = self.check_transaction_inclusion(hash, timeout_ms).await?;
3390
3391        Ok(receipt)
3392    }
3393
3394    /// Signs a raw Tempo transaction as the node's fee payer (sponsor) and returns the fully
3395    /// signed raw transaction without broadcasting it.
3396    ///
3397    /// This is the sign-only mode of the Tempo fee payer service contract, so
3398    /// `cast send --sponsor-url` and the tempo SDK relay transport can point directly at this
3399    /// node. Only available on Tempo networks.
3400    ///
3401    /// Handler for ETH RPC call: `eth_signRawTransaction`
3402    pub async fn sign_raw_transaction(&self, tx: Bytes) -> Result<Bytes> {
3403        node_info!("eth_signRawTransaction");
3404        if !self.backend.is_tempo() {
3405            return Err(BlockchainError::RpcUnimplemented);
3406        }
3407
3408        if tx.is_empty() {
3409            return Err(BlockchainError::EmptyRawTransactionData);
3410        }
3411
3412        // Fee payer service clients submit the request in the service encoding, which carries a
3413        // `0x00` placeholder in the fee payer signature field.
3414        let service_encoded = normalize_fee_payer_service_encoding(tx.as_ref());
3415        let mut data = service_encoded.as_deref().unwrap_or(tx.as_ref());
3416
3417        let transaction = FoundryTxEnvelope::decode_2718(&mut data)
3418            .map_err(|_| BlockchainError::FailedToDecodeSignedTransaction)?;
3419
3420        let FoundryTxEnvelope::Tempo(aa_tx) = transaction else {
3421            return Err(RpcError::invalid_params(
3422                "only Tempo (0x76) transactions can be fee-payer signed",
3423            )
3424            .into());
3425        };
3426
3427        let signed = self.sponsor_sign_tempo_transaction(aa_tx).await?;
3428        Ok(FoundryTxEnvelope::Tempo(signed).encoded_2718().into())
3429    }
3430
3431    /// Fills the sponsor-owned fields of a sender-signed Tempo AA transaction.
3432    ///
3433    /// Mirrors the hosted Tempo fee payer service: the node's fee payer account selects the fee
3434    /// token when the sender left it open and signs the fee payer digest. Only the fee token and
3435    /// fee payer signature are touched, so the sender signature stays valid.
3436    async fn sponsor_sign_tempo_transaction(&self, tx: AASigned) -> Result<AASigned> {
3437        // The sender must have signed in the sponsored state (fee payer placeholder set): the
3438        // sender signature commits to whether a fee payer is present, so sponsoring a
3439        // transaction signed without the placeholder would invalidate it.
3440        match tx.tx().fee_payer_signature {
3441            Some(FEE_PAYER_SIGNATURE_MARKER) => {}
3442            Some(_) => {
3443                return Err(
3444                    RpcError::invalid_params("transaction is already fee-payer signed").into()
3445                );
3446            }
3447            None => {
3448                return Err(RpcError::invalid_params(
3449                    "transaction does not request sponsorship; sign it with the fee payer \
3450                     signature placeholder",
3451                )
3452                .into());
3453            }
3454        }
3455
3456        let sender = tx.recover_signer().map_err(|_| {
3457            BlockchainError::RpcError(RpcError::invalid_params(
3458                "transaction must be signed by the sender before fee-payer signing",
3459            ))
3460        })?;
3461
3462        let Some(sponsor) = self.backend.tempo_fee_payer().await else {
3463            return Err(RpcError::invalid_params("no Tempo fee payer account available").into());
3464        };
3465        if sponsor == sender {
3466            return Err(RpcError::invalid_params(format!(
3467                "Tempo fee payer {sponsor} must not equal the transaction sender"
3468            ))
3469            .into());
3470        }
3471        let signer = self.get_signer(sponsor).ok_or(BlockchainError::NoSignerAvailable)?;
3472
3473        let (mut tx, sender_signature, _) = tx.into_parts();
3474        // The fee payer digest commits to the fee token, so it must be resolved first. The
3475        // service encoding omits the sender's fee token preference, letting the sponsor pick the
3476        // token it pays with.
3477        if tx.fee_token.is_none() {
3478            tx.fee_token = Some(self.backend.tempo_user_fee_token(sponsor).await?);
3479        }
3480        let digest = tx.fee_payer_signature_hash(sender);
3481        tx.fee_payer_signature = Some(signer.sign_hash(sponsor, digest).await?);
3482
3483        Ok(tx.into_signed(sender_signature))
3484    }
3485
3486    /// Call contract, returning the output data.
3487    ///
3488    /// Handler for ETH RPC call: `eth_call`
3489    pub async fn call(
3490        &self,
3491        request: WithOtherFields<TransactionRequest>,
3492        block_number: Option<BlockId>,
3493        overrides: EvmOverrides,
3494    ) -> Result<Bytes> {
3495        node_info!("eth_call");
3496        let block_request = self.block_request(block_number).await?;
3497        // check if the number predates the fork, if in fork mode
3498        if let BlockRequest::Number(number) = block_request
3499            && let Some(fork) = self.get_fork()
3500            && fork.predates_fork(number)
3501        {
3502            if overrides.has_state() || overrides.has_block() {
3503                return Err(BlockchainError::EvmOverrideError(
3504                    "not available on past forked blocks".to_string(),
3505                ));
3506            }
3507            return Ok(fork.call_raw(&request, Some(number.into())).await?);
3508        }
3509
3510        #[cfg(feature = "base")]
3511        if self.backend.is_base()
3512            && serde_json::to_value(&request)
3513                .and_then(serde_json::from_value::<BaseTransactionRequest>)
3514                .is_ok_and(|request| request.as_eip8130().is_some())
3515        {
3516            let timestamp = self.backend.block_request_timestamp(&block_request).await?;
3517            self.backend.ensure_base_eip8130_active_at(timestamp)?;
3518        }
3519
3520        let fees = FeeDetails::new(
3521            request.gas_price,
3522            request.max_fee_per_gas,
3523            request.max_priority_fee_per_gas,
3524            request.max_fee_per_blob_gas,
3525        )?
3526        .or_zero_fees();
3527        // this can be blocking for a bit, especially in forking mode
3528        // <https://github.com/foundry-rs/foundry/issues/6036>
3529        self.on_blocking_task(|this| async move {
3530            let (exit, out, gas, _) =
3531                this.backend.call(request, fees, Some(block_request), overrides).await?;
3532            trace!(target : "node", "Call status {:?}, gas {}", exit, gas);
3533
3534            ensure_return_ok(exit, &out)
3535        })
3536        .await
3537    }
3538
3539    pub async fn call_many(
3540        &self,
3541        bundles: Vec<Bundle<WithOtherFields<TransactionRequest>>>,
3542        state_context: Option<StateContext>,
3543        state_override: Option<StateOverride>,
3544    ) -> Result<Vec<Vec<EthCallResponse>>> {
3545        node_info!("eth_callMany");
3546        let StateContext { transaction_index, block_number } = state_context.unwrap_or_default();
3547        if transaction_index.is_some_and(|index| index.index().is_some()) {
3548            return Err(BlockchainError::RpcError(RpcError::invalid_params(
3549                "transactionIndex is not supported for eth_callMany yet".to_string(),
3550            )));
3551        }
3552
3553        let block_request = self.block_request(block_number).await?;
3554        if let BlockRequest::Number(number) = block_request
3555            && let Some(fork) = self.get_fork()
3556            && fork.predates_fork(number)
3557        {
3558            return Ok(fork
3559                .call_many(
3560                    bundles,
3561                    Some(StateContext { transaction_index, block_number: Some(number.into()) }),
3562                    state_override,
3563                )
3564                .await?);
3565        }
3566
3567        self.on_blocking_task(|this| async move {
3568            this.backend.call_many(bundles, Some(block_request), state_override).await
3569        })
3570        .await
3571    }
3572
3573    /// Simulates a bundle of signed transactions against the requested state.
3574    ///
3575    /// Handler for ETH RPC call: `eth_callBundle`.
3576    pub async fn call_bundle(&self, bundle: EthCallBundle) -> Result<EthCallBundleResponse> {
3577        node_info!("eth_callBundle");
3578        if bundle.txs.is_empty() {
3579            return Err(BlockchainError::RpcError(RpcError::invalid_params(
3580                "bundle missing txs".to_string(),
3581            )));
3582        }
3583        if bundle.block_number == 0 {
3584            return Err(BlockchainError::RpcError(RpcError::invalid_params(
3585                "bundle missing blockNumber".to_string(),
3586            )));
3587        }
3588
3589        let block_request = self.block_request(Some(bundle.state_block_number.into())).await?;
3590        if let BlockRequest::Number(number) = block_request
3591            && let Some(fork) = self.get_fork()
3592            && fork.predates_fork(number)
3593        {
3594            return Ok(fork.call_bundle(bundle).await?);
3595        }
3596
3597        let transactions = bundle
3598            .txs
3599            .iter()
3600            .map(|raw| {
3601                let mut data = raw.as_ref();
3602                if data.is_empty() {
3603                    return Err(BlockchainError::EmptyRawTransactionData);
3604                }
3605                let transaction = FoundryTxEnvelope::decode_2718(&mut data)
3606                    .map_err(|_| BlockchainError::FailedToDecodeSignedTransaction)?;
3607                self.ensure_typed_transaction_supported(&transaction)?;
3608                PendingTransaction::new(transaction).map_err(Into::into)
3609            })
3610            .collect::<Result<Vec<_>>>()?;
3611
3612        self.on_blocking_task(|this| async move {
3613            this.backend.call_bundle(bundle, transactions, Some(block_request)).await
3614        })
3615        .await
3616    }
3617
3618    pub async fn simulate_v1(
3619        &self,
3620        request: SimulatePayload,
3621        block_number: Option<BlockId>,
3622    ) -> Result<Vec<SimulatedBlock<AnyRpcBlock>>> {
3623        self.simulate_v1_raw(preserve_simulation_request_fields(request), block_number).await
3624    }
3625
3626    pub(crate) async fn simulate_v1_raw(
3627        &self,
3628        mut request: SimulatePayload<WithOtherFields<TransactionRequest>>,
3629        block_number: Option<BlockId>,
3630    ) -> Result<Vec<SimulatedBlock<AnyRpcBlock>>> {
3631        const DEFAULT_BLOCK_INTERVAL_SECS: u64 = 12;
3632
3633        node_info!("eth_simulateV1");
3634        if request.block_state_calls.is_empty() {
3635            return Err(BlockchainError::RpcError(RpcError::invalid_params("empty input")));
3636        }
3637        if request.block_state_calls.len() > MAX_SIMULATE_BLOCKS as usize {
3638            return Err(BlockchainError::RpcError(RpcError {
3639                code: ErrorCode::ServerError(-38026),
3640                message: "too many blocks".into(),
3641                data: None,
3642            }));
3643        }
3644        let block_id = block_number;
3645        let block_request =
3646            self.block_request(block_number).await.map_err(|error| match error {
3647                BlockchainError::BlockOutOfRange(_, _) | BlockchainError::BlockNotFound => {
3648                    BlockchainError::RpcError(RpcError {
3649                        code: ErrorCode::ServerError(-32000),
3650                        message: "header not found".into(),
3651                        data: None,
3652                    })
3653                }
3654                error => error,
3655            })?;
3656        let block_interval = self.backend.time().block_timestamp_interval().unwrap_or_else(|| {
3657            self.miner
3658                .block_interval()
3659                .map(|duration| {
3660                    duration
3661                        .as_secs()
3662                        .saturating_add(u64::from(duration.subsec_nanos() != 0))
3663                        .max(1)
3664                })
3665                .unwrap_or(DEFAULT_BLOCK_INTERVAL_SECS)
3666        });
3667
3668        // check if the number predates the fork, if in fork mode
3669        if let BlockRequest::Number(number) = block_request
3670            && let Some(fork) = self.get_fork()
3671            && fork.predates_fork(number)
3672        {
3673            let block_id = match block_id {
3674                Some(BlockId::Hash(hash)) => BlockId::Hash(hash),
3675                _ => number.into(),
3676            };
3677            let base_block = fork.fetch_block(block_id).await?.ok_or_else(|| {
3678                BlockchainError::RpcError(RpcError {
3679                    code: ErrorCode::ServerError(-32000),
3680                    message: "header not found".into(),
3681                    data: None,
3682                })
3683            })?;
3684            request.block_state_calls = sanitize_simulation_blocks(
3685                request.block_state_calls,
3686                base_block.header.number(),
3687                base_block.header.timestamp(),
3688                block_interval,
3689            )?;
3690            return Ok(fork.simulate_v1(&request, Some(base_block.header.hash.into())).await?);
3691        }
3692
3693        // this can be blocking for a bit, especially in forking mode
3694        // <https://github.com/foundry-rs/foundry/issues/6036>
3695        self.on_blocking_task(|this| async move {
3696            let simulated_blocks =
3697                this.backend.simulate_raw(request, Some(block_request), block_interval).await?;
3698            trace!(target : "node", "Simulate status {:?}", simulated_blocks);
3699
3700            Ok(simulated_blocks)
3701        })
3702        .await
3703    }
3704
3705    /// This method creates an EIP2930 type accessList based on a given Transaction. The accessList
3706    /// contains all storage slots and addresses read and written by the transaction, except for the
3707    /// sender account and the precompiles.
3708    ///
3709    /// It returns list of addresses and storage keys used by the transaction, plus the gas
3710    /// consumed when the access list is added. That is, it gives you the list of addresses and
3711    /// storage keys that will be used by that transaction, plus the gas consumed if the access
3712    /// list is included. Like eth_estimateGas, this is an estimation; the list could change
3713    /// when the transaction is actually mined. Adding an accessList to your transaction does
3714    /// not necessary result in lower gas usage compared to a transaction without an access
3715    /// list.
3716    ///
3717    /// Handler for ETH RPC call: `eth_createAccessList`
3718    pub async fn create_access_list(
3719        &self,
3720        request: WithOtherFields<TransactionRequest>,
3721        block_number: Option<BlockId>,
3722        state_override: Option<StateOverride>,
3723    ) -> Result<AccessListResult> {
3724        node_info!("eth_createAccessList");
3725        let block_request = self.block_request(block_number).await?;
3726        // check if the number predates the fork, if in fork mode
3727        if let BlockRequest::Number(number) = block_request
3728            && let Some(fork) = self.get_fork()
3729            && fork.predates_fork(number)
3730        {
3731            if state_override.is_some() {
3732                return Err(BlockchainError::EvmOverrideError(
3733                    "not available on past forked blocks".to_string(),
3734                ));
3735            }
3736            return Ok(fork.create_access_list_raw(&request, Some(number.into())).await?);
3737        }
3738        let typed_request = self.parse_transaction_request(request.clone())?;
3739
3740        #[cfg(feature = "base")]
3741        if self.backend.is_base()
3742            && serde_json::to_value(&request)
3743                .and_then(serde_json::from_value::<BaseTransactionRequest>)
3744                .is_ok_and(|request| request.as_eip8130().is_some())
3745        {
3746            let timestamp = self.backend.block_request_timestamp(&block_request).await?;
3747            self.backend.ensure_base_eip8130_active_at(timestamp)?;
3748            return Err(BlockchainError::InvalidTransactionRequest(
3749                "eth_createAccessList does not support EIP-8130 transaction requests".to_string(),
3750            ));
3751        }
3752
3753        self.backend
3754            .with_database_at_and_context(Some(block_request), |state, block_env, monad_context| {
3755                let mut cache_db = CacheDB::new(&*state);
3756                if let Some(state_override) = state_override {
3757                    apply_state_overrides(state_override.into_iter().collect(), &mut cache_db)?;
3758                }
3759
3760                let (_, _, _, access_list) =
3761                    self.backend.build_access_list_with_state_and_context(
3762                        &cache_db,
3763                        request.clone(),
3764                        FeeDetails::zero(),
3765                        block_env.clone(),
3766                        monad_context.clone(),
3767                    )?;
3768
3769                // Re-execute with the access list applied to get the post-AL gas usage.
3770                // EVM failures (including reverts) are surfaced in the result's `error`
3771                // field per the execution-apis `eth_createAccessList` spec, so callers
3772                // can still inspect the traced slots when execution fails.
3773                let (exit, _, gas_used, _) = self.backend.call_with_state_typed_access_list(
3774                    &cache_db,
3775                    typed_request,
3776                    FeeDetails::zero(),
3777                    block_env,
3778                    access_list.clone(),
3779                    monad_context,
3780                )?;
3781
3782                Ok(AccessListResult {
3783                    access_list,
3784                    gas_used: U256::from(gas_used),
3785                    error: execution_error(exit),
3786                })
3787            })
3788            .await
3789    }
3790
3791    /// Estimate gas needed for execution of given contract.
3792    /// If no block parameter is given, it will use the pending block by default
3793    ///
3794    /// Handler for ETH RPC call: `eth_estimateGas`
3795    pub async fn estimate_gas(
3796        &self,
3797        request: WithOtherFields<TransactionRequest>,
3798        block_number: Option<BlockId>,
3799        overrides: EvmOverrides,
3800    ) -> Result<U256> {
3801        node_info!("eth_estimateGas");
3802        self.do_estimate_gas(request, block_number.or_else(|| Some(BlockId::pending())), overrides)
3803            .await
3804            .map(U256::from)
3805    }
3806
3807    /// Fills a transaction request with default values for missing fields.
3808    ///
3809    /// This method populates missing transaction fields like nonce, gas limit,
3810    /// chain ID, and fee parameters with appropriate defaults.
3811    ///
3812    /// Handler for ETH RPC call: `eth_fillTransaction`
3813    pub async fn fill_transaction(
3814        &self,
3815        request: WithOtherFields<TransactionRequest>,
3816    ) -> Result<FillTransaction<AnyRpcTransaction>> {
3817        node_info!("eth_fillTransaction");
3818        let mut request = self.parse_transaction_request(request)?;
3819
3820        let from = match request.from() {
3821            Some(from) => from,
3822            None => self.accounts()?.first().copied().ok_or(BlockchainError::NoSignerAvailable)?,
3823        };
3824
3825        let nonce = self.request_nonce_for_transaction(&request, from).await?;
3826
3827        // Prefill gas limit with estimated gas and bubble up estimation errors directly.
3828        if request.gas_limit().is_none() {
3829            let estimated_gas =
3830                self.do_estimate_gas_typed(request.clone(), Some(BlockId::pending())).await?;
3831            request.set_gas_limit(estimated_gas as u64);
3832        }
3833
3834        let typed_tx = self.build_tx_request(request, nonce).await?;
3835        let tx = typed_tx.into_impersonated();
3836
3837        let raw = tx.encoded_2718().into();
3838
3839        let mut tx =
3840            transaction_build(None, MaybeImpersonatedTransaction::new(tx), None, None, None);
3841
3842        // Set the correct `from` address (overrides the recovered zero address from dummy
3843        // signature)
3844        tx.0.inner.inner = Recovered::new_unchecked(tx.0.inner.inner.into_inner(), from);
3845
3846        Ok(FillTransaction { raw, tx })
3847    }
3848
3849    /// Handler for RPC call: `anvil_getBlobsByTransactionHash`
3850    pub fn anvil_get_blob_by_tx_hash(&self, hash: B256) -> Result<Option<Vec<Blob>>> {
3851        node_info!("anvil_getBlobsByTransactionHash");
3852        Ok(self.backend.get_blob_by_tx_hash(hash)?)
3853    }
3854
3855    /// Get transaction by its hash.
3856    ///
3857    /// This will check the storage for a matching transaction, if no transaction exists in storage
3858    /// this will also scan the mempool for a matching pending transaction
3859    ///
3860    /// Handler for ETH RPC call: `eth_getTransactionByHash`
3861    pub async fn transaction_by_hash(&self, hash: B256) -> Result<Option<AnyRpcTransaction>> {
3862        node_info!("eth_getTransactionByHash");
3863        let mut tx =
3864            self.pool.get_transaction(hash).map(|pending| self.build_pool_transaction(pending));
3865        if tx.is_none() {
3866            tx = self.backend.transaction_by_hash(hash).await?
3867        }
3868
3869        Ok(tx)
3870    }
3871
3872    fn build_pool_transaction(
3873        &self,
3874        pending: PendingTransaction<FoundryTxEnvelope>,
3875    ) -> AnyRpcTransaction {
3876        let from = *pending.sender();
3877        let tx = transaction_build(
3878            Some(*pending.hash()),
3879            pending.transaction,
3880            None,
3881            None,
3882            Some(self.backend.base_fee()),
3883        );
3884
3885        let WithOtherFields { inner: mut tx, other } = tx.0;
3886        // we set the from field here explicitly to the set sender of the pending transaction,
3887        // in case the transaction is impersonated.
3888        tx.inner = Recovered::new_unchecked(tx.inner.into_inner(), from);
3889
3890        AnyRpcTransaction(WithOtherFields { inner: tx, other })
3891    }
3892
3893    /// Returns all ready transactions from the local pending pool.
3894    ///
3895    /// Handler for ETH RPC call: `eth_pendingTransactions`
3896    pub async fn pending_transactions(&self) -> Result<Vec<AnyRpcTransaction>> {
3897        node_info!("eth_pendingTransactions");
3898        Ok(self
3899            .pool
3900            .ready_transactions()
3901            .map(|pending| self.build_pool_transaction(pending.pending_transaction.clone()))
3902            .collect())
3903    }
3904
3905    /// Returns the transaction by sender and nonce.
3906    ///
3907    /// This will check the mempool for pending transactions first, then perform a binary search
3908    /// over mined blocks to find the transaction.
3909    ///
3910    /// Handler for ETH RPC call: `eth_getTransactionBySenderAndNonce`
3911    pub async fn transaction_by_sender_and_nonce(
3912        &self,
3913        sender: Address,
3914        nonce: U256,
3915    ) -> Result<Option<AnyRpcTransaction>> {
3916        node_info!("eth_getTransactionBySenderAndNonce");
3917
3918        // check pending txs first
3919        for pending_tx in self.pool.ready_transactions().chain(self.pool.pending_transactions()) {
3920            if U256::from(pending_tx.pending_transaction.nonce()) == nonce
3921                && *pending_tx.pending_transaction.sender() == sender
3922            {
3923                let tx = transaction_build(
3924                    Some(*pending_tx.pending_transaction.hash()),
3925                    pending_tx.pending_transaction.transaction.clone(),
3926                    None,
3927                    None,
3928                    Some(self.backend.base_fee()),
3929                );
3930
3931                let WithOtherFields { inner: mut tx, other } = tx.0;
3932                // we set the from field here explicitly to the set sender of the pending
3933                // transaction, in case the transaction is impersonated.
3934                let from = *pending_tx.pending_transaction.sender();
3935                tx.inner = Recovered::new_unchecked(tx.inner.into_inner(), from);
3936
3937                return Ok(Some(AnyRpcTransaction(WithOtherFields { inner: tx, other })));
3938            }
3939        }
3940
3941        let highest_nonce = self.transaction_count(sender, None).await?.saturating_to::<u64>();
3942        let target_nonce = nonce.saturating_to::<u64>();
3943
3944        // if the nonce is higher or equal to the highest nonce, the transaction doesn't exist
3945        if target_nonce >= highest_nonce {
3946            return Ok(None);
3947        }
3948
3949        // no mined blocks yet
3950        let latest_block = self.backend.best_number();
3951        let first_block = if self.get_fork().is_some() { 0 } else { self.backend.genesis_number() };
3952        if latest_block <= first_block {
3953            return Ok(None);
3954        }
3955
3956        // binary search for the block containing the transaction
3957        let mut low = first_block + 1;
3958        let mut high = latest_block;
3959
3960        while low <= high {
3961            let mid = low + (high - low) / 2;
3962            let mid_nonce =
3963                self.transaction_count(sender, Some(mid.into())).await?.saturating_to::<u64>();
3964
3965            if mid_nonce > target_nonce {
3966                high = mid - 1;
3967            } else {
3968                low = mid + 1;
3969            }
3970        }
3971
3972        // search in the target block
3973        let target_block = low;
3974        if target_block <= latest_block
3975            && let Some(txs) =
3976                self.backend.mined_transactions_by_block_number(target_block.into()).await
3977        {
3978            for tx in txs {
3979                if tx.from() == sender && tx.nonce() == target_nonce {
3980                    return Ok(Some(tx));
3981                }
3982            }
3983        }
3984
3985        Ok(None)
3986    }
3987
3988    /// Returns transaction receipt by transaction hash.
3989    ///
3990    /// Handler for ETH RPC call: `eth_getTransactionReceipt`
3991    pub async fn transaction_receipt(&self, hash: B256) -> Result<Option<FoundryTxReceipt>> {
3992        node_info!("eth_getTransactionReceipt");
3993        self.backend.transaction_receipt(hash).await
3994    }
3995
3996    /// Returns block receipts by block number.
3997    ///
3998    /// Handler for ETH RPC call: `eth_getBlockReceipts`
3999    pub async fn block_receipts(&self, number: BlockId) -> Result<Option<Vec<FoundryTxReceipt>>> {
4000        node_info!("eth_getBlockReceipts");
4001        if number == BlockId::pending() {
4002            let transactions = self.pool.ready_transactions().collect::<Vec<_>>();
4003            return Ok(Some(self.backend.pending_block_receipts(transactions).await?));
4004        }
4005
4006        self.backend.block_receipts(number).await
4007    }
4008
4009    /// Returns logs matching given filter object.
4010    ///
4011    /// Handler for ETH RPC call: `eth_getLogs`
4012    pub async fn logs(&self, filter: Filter) -> Result<Vec<Log>> {
4013        node_info!("eth_getLogs");
4014        let best = self.backend.best_number();
4015        let to_block =
4016            self.backend.convert_block_number_at(filter.block_option.get_to_block().copied(), best);
4017        if to_block > best {
4018            return Err(BlockchainError::BlockOutOfRange(best, to_block));
4019        }
4020        self.backend.logs(filter).await
4021    }
4022
4023    /// Creates a filter object, based on filter options, to notify when the state changes (logs).
4024    ///
4025    /// Handler for ETH RPC call: `eth_newFilter`
4026    pub async fn new_filter(&self, filter: Filter) -> Result<String> {
4027        node_info!("eth_newFilter");
4028        // Valid future ranges have no historic logs to seed yet.
4029        let historic = match filter.block_option.get_from_block() {
4030            Some(BlockNumber::Number(from))
4031                if *from > self.backend.best_number()
4032                    && filter.block_option.get_to_block().is_none_or(|to| {
4033                        to.is_latest() || to.as_number().is_some_and(|to| to >= *from)
4034                    }) =>
4035            {
4036                vec![]
4037            }
4038            Some(_) => self.backend.logs(filter.clone()).await?,
4039            None => vec![],
4040        };
4041        let filter = EthFilter::Logs(Box::new(LogsFilter {
4042            blocks: self.new_block_notifications(),
4043            storage: self.storage_info(),
4044            filter: FilteredParams::new(Some(filter)),
4045            historic: Some(historic),
4046        }));
4047        Ok(self.filters.add_filter(filter).await)
4048    }
4049
4050    /// Creates a filter in the node, to notify when a new block arrives.
4051    ///
4052    /// Handler for ETH RPC call: `eth_newBlockFilter`
4053    pub async fn new_block_filter(&self) -> Result<String> {
4054        node_info!("eth_newBlockFilter");
4055        let filter = EthFilter::Blocks(self.new_block_notifications());
4056        Ok(self.filters.add_filter(filter).await)
4057    }
4058
4059    /// Creates a filter in the node, to notify when new pending transactions arrive.
4060    ///
4061    /// Handler for ETH RPC call: `eth_newPendingTransactionFilter`
4062    pub async fn new_pending_transaction_filter(&self, full: bool) -> Result<String> {
4063        node_info!("eth_newPendingTransactionFilter");
4064        let filter = if full {
4065            EthFilter::FullPendingTransactions(self.full_pending_transactions_filter())
4066        } else {
4067            EthFilter::PendingTransactions(self.new_ready_transactions())
4068        };
4069        Ok(self.filters.add_filter(filter).await)
4070    }
4071
4072    /// Polling method for a filter, which returns an array of logs which occurred since last poll.
4073    ///
4074    /// Handler for ETH RPC call: `eth_getFilterChanges`
4075    pub async fn get_filter_changes(&self, id: &str) -> ResponseResult {
4076        node_info!("eth_getFilterChanges");
4077        self.filters.get_filter_changes(id).await
4078    }
4079
4080    /// Returns an array of all logs matching filter with given id.
4081    ///
4082    /// Handler for ETH RPC call: `eth_getFilterLogs`
4083    pub async fn get_filter_logs(&self, id: &str) -> Result<Vec<Log>> {
4084        node_info!("eth_getFilterLogs");
4085        if let Some(filter) = self.filters.get_log_filter(id).await {
4086            self.backend.logs(filter).await
4087        } else {
4088            Err(BlockchainError::FilterNotFound)
4089        }
4090    }
4091
4092    /// Handler for ETH RPC call: `eth_uninstallFilter`
4093    pub async fn uninstall_filter(&self, id: &str) -> Result<bool> {
4094        node_info!("eth_uninstallFilter");
4095        Ok(self.filters.uninstall_filter(id).await.is_some())
4096    }
4097
4098    /// Returns EIP-2718 encoded raw transaction
4099    ///
4100    /// Handler for RPC call: `debug_getRawTransaction`
4101    pub async fn raw_transaction(&self, hash: B256) -> Result<Option<Bytes>> {
4102        node_info!("debug_getRawTransaction");
4103        self.inner_raw_transaction(hash).await
4104    }
4105
4106    /// Returns EIP-2718 encoded raw receipts for the block.
4107    ///
4108    /// Handler for RPC call: `debug_getRawReceipts`.
4109    pub async fn raw_receipts(&self, block: BlockId) -> Result<Vec<Bytes>> {
4110        node_info!("debug_getRawReceipts");
4111
4112        // In fork mode, serve pre-fork blocks from the upstream provider.
4113        if let BlockRequest::Number(number) = self.block_request(Some(block)).await?
4114            && let Some(fork) = self.get_fork()
4115            && fork.predates_fork_inclusive(number)
4116        {
4117            let receipts = fork.block_receipts(number).await?.unwrap_or_default();
4118            return Ok(receipts
4119                .into_iter()
4120                .map(|receipt| {
4121                    receipt.0.inner.inner.map_logs(|log| log.inner).encoded_2718().into()
4122                })
4123                .collect());
4124        }
4125
4126        let block = self.backend.get_block(block).ok_or(BlockchainError::BlockNotFound)?;
4127        let receipts = self
4128            .backend
4129            .mined_receipts(block.header.hash_slow())
4130            .ok_or(BlockchainError::BlockNotFound)?;
4131        Ok(receipts.into_iter().map(|receipt| receipt.encoded_2718().into()).collect())
4132    }
4133
4134    /// Returns EIP-2718 encoded raw transactions for the block.
4135    ///
4136    /// Handler for RPC call: `debug_getRawTransactions`.
4137    pub async fn raw_transactions(&self, block: BlockId) -> Result<Vec<Bytes>> {
4138        node_info!("debug_getRawTransactions");
4139
4140        if let Some(block) = self.backend.get_block(block) {
4141            return Ok(block
4142                .body
4143                .transactions
4144                .into_iter()
4145                .map(|tx| tx.into_inner().into_canonical().encoded_2718().into())
4146                .collect());
4147        }
4148
4149        // In fork mode, serve pre-fork blocks from the upstream provider. Genuinely unknown or
4150        // out-of-range blocks yield an empty result, mirroring reth; transport errors propagate.
4151        let Some(fork) = self.get_fork() else {
4152            return Ok(Vec::new());
4153        };
4154        let block = match block {
4155            BlockId::Number(BlockNumber::Pending) => None,
4156            BlockId::Number(number) => {
4157                let number = self.backend.convert_block_number(Some(number));
4158                if !fork.predates_fork_inclusive(number) {
4159                    return Ok(Vec::new());
4160                }
4161                fork.block_by_number_full(number).await?
4162            }
4163            BlockId::Hash(hash) => fork
4164                .block_by_hash_full(hash.block_hash)
4165                .await?
4166                .filter(|block| fork.predates_fork_inclusive(block.header().number())),
4167        };
4168        let Some(block) = block else {
4169            return Ok(Vec::new());
4170        };
4171        let BlockTransactions::Full(txs) = block.transactions() else {
4172            return Err(BlockchainError::Internal(
4173                "fork provider returned a non-full block for a full block request".to_string(),
4174            ));
4175        };
4176        txs.iter().map(encode_rpc_transaction).collect()
4177    }
4178
4179    /// Returns RLP encoded raw block header.
4180    ///
4181    /// Handler for RPC call: `debug_getRawHeader`.
4182    pub async fn raw_header(&self, block: BlockId) -> Result<Bytes> {
4183        node_info!("debug_getRawHeader");
4184        let block = self.backend.get_block(block).ok_or(BlockchainError::BlockNotFound)?;
4185        Ok(alloy_rlp::encode(&block.header).into())
4186    }
4187
4188    /// Returns RLP encoded raw block.
4189    ///
4190    /// Handler for RPC call: `debug_getRawBlock`.
4191    pub async fn raw_block(&self, block: BlockId) -> Result<Bytes> {
4192        node_info!("debug_getRawBlock");
4193        let block = self.backend.get_block(block).ok_or(BlockchainError::BlockNotFound)?;
4194        Ok(alloy_rlp::encode(canonical_block(block)).into())
4195    }
4196
4197    /// Returns EIP-2718 encoded raw transaction by block hash and index
4198    ///
4199    /// Handler for RPC call: `eth_getRawTransactionByBlockHashAndIndex`
4200    pub async fn raw_transaction_by_block_hash_and_index(
4201        &self,
4202        block_hash: B256,
4203        index: Index,
4204    ) -> Result<Option<Bytes>> {
4205        node_info!("eth_getRawTransactionByBlockHashAndIndex");
4206        match self.backend.transaction_by_block_hash_and_index(block_hash, index).await? {
4207            Some(tx) => self.inner_raw_transaction(tx.tx_hash()).await,
4208            None => Ok(None),
4209        }
4210    }
4211
4212    /// Returns EIP-2718 encoded raw transaction by block number and index
4213    ///
4214    /// Handler for RPC call: `eth_getRawTransactionByBlockNumberAndIndex`
4215    pub async fn raw_transaction_by_block_number_and_index(
4216        &self,
4217        block_number: BlockNumber,
4218        index: Index,
4219    ) -> Result<Option<Bytes>> {
4220        node_info!("eth_getRawTransactionByBlockNumberAndIndex");
4221        match self.transaction_by_block_number_and_index(block_number, index).await? {
4222            Some(tx) => self.inner_raw_transaction(tx.tx_hash()).await,
4223            None => Ok(None),
4224        }
4225    }
4226
4227    /// Returns traces for the transaction hash for geth's tracing endpoint
4228    ///
4229    /// Handler for RPC call: `debug_traceTransaction`
4230    pub async fn debug_trace_transaction(
4231        &self,
4232        tx_hash: B256,
4233        opts: GethDebugTracingOptions,
4234    ) -> Result<GethTrace> {
4235        node_info!("debug_traceTransaction");
4236        self.backend.debug_trace_transaction(tx_hash, opts).await
4237    }
4238
4239    /// Returns traces for all transactions in an RLP-encoded block.
4240    ///
4241    /// Handler for RPC call: `debug_traceBlock`
4242    pub async fn debug_trace_block(
4243        &self,
4244        rlp_block: Bytes,
4245        opts: GethDebugTracingOptions,
4246    ) -> Result<Vec<TraceResult>> {
4247        node_info!("debug_traceBlock");
4248        self.backend.debug_trace_block(rlp_block, opts).await
4249    }
4250
4251    /// Returns traces for all transactions in a block by hash.
4252    ///
4253    /// Handler for RPC call: `debug_traceBlockByHash`
4254    pub async fn debug_trace_block_by_hash(
4255        &self,
4256        block_hash: B256,
4257        opts: GethDebugTracingOptions,
4258    ) -> Result<Vec<TraceResult>> {
4259        node_info!("debug_traceBlockByHash");
4260        self.backend.debug_trace_block_by_hash(block_hash, opts).await
4261    }
4262
4263    /// Returns traces for all transactions in a block by number.
4264    ///
4265    /// Handler for RPC call: `debug_traceBlockByNumber`
4266    pub async fn debug_trace_block_by_number(
4267        &self,
4268        block_number: BlockNumber,
4269        opts: GethDebugTracingOptions,
4270    ) -> Result<Vec<TraceResult>> {
4271        node_info!("debug_traceBlockByNumber");
4272        self.backend.debug_trace_block_by_number(block_number, opts).await
4273    }
4274
4275    /// Returns traces for the transaction for geth's tracing endpoint
4276    ///
4277    /// Handler for RPC call: `debug_traceCall`
4278    pub async fn debug_trace_call(
4279        &self,
4280        request: WithOtherFields<TransactionRequest>,
4281        block_number: Option<BlockId>,
4282        opts: GethDebugTracingCallOptions,
4283    ) -> Result<GethTrace> {
4284        node_info!("debug_traceCall");
4285        let block_request = self.block_request(block_number).await?;
4286        let fees = FeeDetails::new(
4287            request.gas_price,
4288            request.max_fee_per_gas,
4289            request.max_priority_fee_per_gas,
4290            request.max_fee_per_blob_gas,
4291        )?
4292        .or_zero_fees();
4293
4294        let result: std::result::Result<GethTrace, BlockchainError> =
4295            self.backend.call_with_tracing(request, fees, Some(block_request), opts).await;
4296        result
4297    }
4298
4299    /// Traces calls sequentially on top of the same block.
4300    ///
4301    /// Handler for RPC call: `trace_callMany`.
4302    pub async fn trace_call_many(
4303        &self,
4304        calls: Vec<(WithOtherFields<TransactionRequest>, HashSet<TraceType>)>,
4305        block_number: Option<BlockId>,
4306    ) -> Result<Vec<TraceResults>> {
4307        node_info!("trace_callMany");
4308        let block_request = self.trace_block_request(block_number.unwrap_or_default()).await?;
4309
4310        self.backend.trace_call_many(calls, Some(block_request)).await
4311    }
4312}
4313
4314// == impl EthApi anvil endpoints ==
4315
4316impl EthApi<FoundryNetwork> {
4317    /// Mines a series of blocks.
4318    ///
4319    /// Handler for ETH RPC call: `anvil_mine`
4320    pub async fn anvil_mine(&self, num_blocks: Option<U256>, interval: Option<U256>) -> Result<()> {
4321        node_info!("anvil_mine");
4322        let interval = interval.map(|i| i.saturating_to::<u64>());
4323        let pin_timestamp = interval == Some(0);
4324        let blocks = num_blocks.unwrap_or(U256::ONE);
4325        if blocks.is_zero() {
4326            return Ok(());
4327        }
4328
4329        self.on_blocking_task(|this| async move {
4330            // mine all the blocks
4331            for _ in 0..blocks.saturating_to::<u64>() {
4332                // If we have an interval, jump forwards in time to the "next" timestamp
4333                let pending_increase =
4334                    interval.map(|interval| this.backend.time().apply_time_increase(interval));
4335                if let Err(error) = this.mine_one_with_timestamp_pinning(pin_timestamp).await {
4336                    if let Some(pending) = pending_increase {
4337                        this.backend.time().revert_time_increase(pending);
4338                    }
4339                    return Err(error);
4340                }
4341            }
4342            Ok(())
4343        })
4344        .await?;
4345
4346        Ok(())
4347    }
4348
4349    /// Helper function to find the storage slot for an ERC20 function call by testing slots
4350    /// from an access list until one produces the expected result.
4351    ///
4352    /// Rather than trying to reverse-engineer the storage layout, this function uses a
4353    /// "trial and error" approach: try overriding each slot that the function accesses,
4354    /// and see which one actually affects the function's return value.
4355    ///
4356    /// ## Parameters
4357    /// - `token_address`: The ERC20 token contract address
4358    /// - `calldata`: The encoded function call (e.g., `balanceOf(user)` or `allowance(owner,
4359    ///   spender)`)
4360    /// - `expected_value`: The value we want to set (balance or allowance amount)
4361    ///
4362    /// ## Returns
4363    /// The storage slot (B256) that contains the target ERC20 data, or an error if no slot is
4364    /// found.
4365    async fn find_erc20_storage_slot(
4366        &self,
4367        token_address: Address,
4368        calldata: Bytes,
4369        expected_value: U256,
4370    ) -> Result<B256> {
4371        let tx = TransactionRequest::default().with_to(token_address).with_input(calldata.clone());
4372
4373        // first collect all the slots that are used by the function call
4374        let access_list_result =
4375            self.create_access_list(WithOtherFields::new(tx.clone()), None, None).await?;
4376        let access_list = access_list_result.access_list;
4377
4378        // iterate over all the accessed slots and try to find the one that contains the
4379        // target value by overriding the slot and checking the function call result
4380        for item in access_list.0 {
4381            if item.address != token_address {
4382                continue;
4383            };
4384            for slot in &item.storage_keys {
4385                let account_override = AccountOverride::default()
4386                    .with_state_diff(std::iter::once((*slot, B256::from(expected_value))));
4387
4388                let state_override = StateOverridesBuilder::default()
4389                    .append(token_address, account_override)
4390                    .build();
4391
4392                let evm_override = EvmOverrides::state(Some(state_override));
4393
4394                let Ok(result) =
4395                    self.call(WithOtherFields::new(tx.clone()), None, evm_override).await
4396                else {
4397                    // overriding this slot failed
4398                    continue;
4399                };
4400
4401                let Ok(result_value) = U256::abi_decode(&result) else {
4402                    // response returned something other than a U256
4403                    continue;
4404                };
4405
4406                if result_value == expected_value {
4407                    return Ok(*slot);
4408                }
4409            }
4410        }
4411
4412        Err(BlockchainError::Message("Unable to find storage slot".to_string()))
4413    }
4414
4415    /// Deals ERC20 tokens to a address
4416    ///
4417    /// Handler for RPC call: `anvil_dealERC20`
4418    pub async fn anvil_deal_erc20(
4419        &self,
4420        address: Address,
4421        token_address: Address,
4422        balance: U256,
4423    ) -> Result<()> {
4424        node_info!("anvil_dealERC20");
4425
4426        if self.backend.is_tempo()
4427            && self.backend.try_set_tip20_balance(address, token_address, balance).await?
4428        {
4429            return Ok(());
4430        }
4431
4432        sol! {
4433            #[sol(rpc)]
4434            contract IERC20 {
4435                function balanceOf(address target) external view returns (uint256);
4436            }
4437        }
4438
4439        let calldata = IERC20::balanceOfCall { target: address }.abi_encode().into();
4440
4441        // Find the storage slot that contains the balance
4442        let slot =
4443            self.find_erc20_storage_slot(token_address, calldata, balance).await.map_err(|_| {
4444                BlockchainError::Message("Unable to set ERC20 balance, no slot found".to_string())
4445            })?;
4446
4447        // Set the storage slot to the desired balance
4448        self.anvil_set_storage_at(token_address, slot.into(), balance.into()).await?;
4449
4450        Ok(())
4451    }
4452
4453    /// Deals TIP-20 tokens to an address.
4454    ///
4455    /// Handler for RPC call: `anvil_dealTIP20`.
4456    pub async fn anvil_deal_tip20(
4457        &self,
4458        address: Address,
4459        token_address: Address,
4460        balance: U256,
4461    ) -> Result<()> {
4462        node_info!("anvil_dealTIP20");
4463        self.ensure_tempo_mode()?;
4464        self.backend.set_tip20_balance(address, token_address, balance).await?;
4465        Ok(())
4466    }
4467
4468    /// Sets the ERC20 allowance for a spender
4469    ///
4470    /// Handler for RPC call: `anvil_set_erc20_allowance`
4471    pub async fn anvil_set_erc20_allowance(
4472        &self,
4473        owner: Address,
4474        spender: Address,
4475        token_address: Address,
4476        amount: U256,
4477    ) -> Result<()> {
4478        node_info!("anvil_setERC20Allowance");
4479
4480        sol! {
4481            #[sol(rpc)]
4482            contract IERC20 {
4483                function allowance(address owner, address spender) external view returns (uint256);
4484            }
4485        }
4486
4487        let calldata = IERC20::allowanceCall { owner, spender }.abi_encode().into();
4488
4489        // Find the storage slot that contains the allowance
4490        let slot =
4491            self.find_erc20_storage_slot(token_address, calldata, amount).await.map_err(|_| {
4492                BlockchainError::Message("Unable to set ERC20 allowance, no slot found".to_string())
4493            })?;
4494
4495        // Set the storage slot to the desired allowance
4496        self.anvil_set_storage_at(token_address, slot.into(), amount.into()).await?;
4497
4498        Ok(())
4499    }
4500
4501    /// Recognizes a canonical Monad protocol envelope without requiring its reserved sender to be
4502    /// globally impersonated or recoverable from the envelope signature.
4503    #[cfg(feature = "monad")]
4504    fn monad_protocol_reorg_transaction(
4505        &self,
4506        transaction: FoundryTxEnvelope,
4507    ) -> Option<PendingTransaction<FoundryTxEnvelope>> {
4508        if !self.backend.is_monad() {
4509            return None;
4510        }
4511
4512        let pending = PendingTransaction::with_sender(
4513            MaybeImpersonatedTransaction::new(transaction),
4514            monad_revm::staking::constants::SYSTEM_ADDRESS,
4515        );
4516        let tx_env: revm::context::TxEnv = crate::eth::backend::executor::build_tx_env_for_pending(
4517            &pending,
4518            self.backend.cheats(),
4519        );
4520        foundry_evm::core::evm::protocol_system_call(&tx_env)
4521            .is_ok_and(|call| call.is_some())
4522            .then_some(pending)
4523    }
4524
4525    /// Reorg the chain to a specific depth and mine new blocks back to the canonical height.
4526    ///
4527    /// e.g depth = 3
4528    ///     A  -> B  -> C  -> D  -> E
4529    ///     A  -> B  -> C' -> D' -> E'
4530    ///
4531    /// Depth specifies the height to reorg the chain back to. Depth must not exceed the current
4532    /// chain height, i.e. can't reorg past the genesis block.
4533    ///
4534    /// Optionally supply a list of transaction and block pairs that will populate the reorged
4535    /// blocks. The maximum block number of the pairs must not exceed the specified depth.
4536    ///
4537    /// Handler for RPC call: `anvil_reorg`
4538    pub async fn anvil_reorg(&self, options: ReorgOptions) -> Result<()> {
4539        node_info!("anvil_reorg");
4540        let _lifecycle = self.lifecycle_lock.write().await;
4541        let mining_guard = self.backend.lock_mining().await;
4542        let depth = options.depth;
4543        let mut tx_block_pairs = options.tx_block_pairs;
4544
4545        if let Some((_, num)) = tx_block_pairs.iter().find(|(_, num)| *num >= depth) {
4546            // A reorg of depth 0 mines no blocks, so there is nowhere to place the transactions.
4547            let Some(last_block) = depth.checked_sub(1) else {
4548                return Err(BlockchainError::RpcError(RpcError::invalid_params(
4549                    "Reorg depth must be at least 1 to include transactions",
4550                )));
4551            };
4552            return Err(BlockchainError::RpcError(RpcError::invalid_params(format!(
4553                "Block number for reorg tx will exceed the reorged chain height. Block number {num} must not exceed (depth-1) {last_block}"
4554            ))));
4555        }
4556        tx_block_pairs.sort_by_key(|a| a.1);
4557
4558        // Check reorg depth doesn't exceed current chain height
4559        let current_height = self.backend.best_number();
4560        let genesis = if self.get_fork().is_some() { 0 } else { self.backend.genesis_number() };
4561        let common_height = current_height.checked_sub(depth).filter(|h| *h >= genesis).ok_or(
4562            BlockchainError::RpcError(RpcError::invalid_params(format!(
4563                "Reorg depth must not exceed current chain height: current height {current_height}, depth {depth}, genesis {genesis}"
4564            ))),
4565        )?;
4566
4567        // Get the common ancestor block
4568        let common_block =
4569            self.rollback_block(common_height).await?.ok_or(BlockchainError::BlockNotFound)?;
4570
4571        #[cfg(feature = "monad")]
4572        let fee_defaults = if self.backend.is_monad() {
4573            self.backend
4574                .monad_rollback_fee_defaults(&common_block, self.lowest_suggestion_tip())
4575                .await
4576                .map(|(gas_price, blob_gas_price)| TransactionFeeDefaults {
4577                    gas_price,
4578                    blob_gas_price,
4579                })
4580        } else {
4581            None
4582        };
4583        #[cfg(not(feature = "monad"))]
4584        let fee_defaults = None;
4585        // Price fee-less transactions for the blocks mined on top of the common block, not for the
4586        // head that is about to be discarded.
4587        let fee_defaults = fee_defaults.or_else(|| {
4588            let (base_fee, blob_fees) = self.backend.next_block_fees_after(&common_block.header);
4589            Some(TransactionFeeDefaults {
4590                gas_price: self.gas_price_for_base_fee(base_fee),
4591                blob_gas_price: self
4592                    .backend
4593                    .fees()
4594                    .blob_params()
4595                    .calc_blob_fee(blob_fees.excess_blob_gas),
4596            })
4597        });
4598
4599        // Convert the transaction requests to pool transactions if they exist, otherwise use empty
4600        // hashmap
4601        let block_pool_txs = if tx_block_pairs.is_empty() {
4602            HashMap::default()
4603        } else {
4604            // Manage nonces for each signer
4605            // address -> cumulative nonce
4606            let mut nonces: HashMap<Address, u64> = HashMap::default();
4607
4608            let mut txs: HashMap<u64, Vec<Arc<PoolTransaction<FoundryTxEnvelope>>>> =
4609                HashMap::default();
4610            for pair in tx_block_pairs {
4611                let (tx_data, block_index) = pair;
4612
4613                let pending = match tx_data {
4614                    TransactionData::Raw(bytes) => {
4615                        let mut data = bytes.as_ref();
4616                        let decoded = FoundryTxEnvelope::decode_2718(&mut data)
4617                            .map_err(|_| BlockchainError::FailedToDecodeSignedTransaction)?;
4618                        if matches!(&decoded, FoundryTxEnvelope::Celo(_)) {
4619                            self.ensure_typed_transaction_supported(&decoded)?;
4620                        }
4621                        let protocol_pending = {
4622                            #[cfg(feature = "monad")]
4623                            {
4624                                self.monad_protocol_reorg_transaction(decoded.clone())
4625                            }
4626                            #[cfg(not(feature = "monad"))]
4627                            {
4628                                None
4629                            }
4630                        };
4631                        if let Some(pending) = protocol_pending {
4632                            pending
4633                        } else {
4634                            PendingTransaction::new(decoded)?
4635                        }
4636                    }
4637
4638                    TransactionData::JSON(request) => {
4639                        let request = if request.transaction_type
4640                            == Some(foundry_primitives::CIP64_TX_TYPE)
4641                            || request
4642                                .other
4643                                .get("feeCurrency")
4644                                .is_some_and(|value| !value.is_null())
4645                        {
4646                            self.parse_transaction_request(request)?
4647                        } else {
4648                            request.inner.into()
4649                        };
4650                        let from = request.from().map(Ok).unwrap_or_else(|| {
4651                            self.accounts()?
4652                                .first()
4653                                .copied()
4654                                .ok_or(BlockchainError::NoSignerAvailable)
4655                        })?;
4656
4657                        // Get the nonce at the common block
4658                        let curr_nonce = nonces.entry(from).or_insert(
4659                            self.get_transaction_count(
4660                                from,
4661                                Some(common_block.header.number().into()),
4662                            )
4663                            .await?,
4664                        );
4665
4666                        // Build typed transaction request
4667                        let typed_tx = self
4668                            .build_tx_request_with_fee_defaults(request, *curr_nonce, fee_defaults)
4669                            .await?;
4670
4671                        // Increment nonce
4672                        *curr_nonce += 1;
4673
4674                        let protocol_pending = {
4675                            #[cfg(feature = "monad")]
4676                            {
4677                                if from == monad_revm::staking::constants::SYSTEM_ADDRESS {
4678                                    self.monad_protocol_reorg_transaction(
4679                                        typed_tx.clone().into_impersonated(),
4680                                    )
4681                                } else {
4682                                    None
4683                                }
4684                            }
4685                            #[cfg(not(feature = "monad"))]
4686                            {
4687                                None
4688                            }
4689                        };
4690                        if let Some(pending) = protocol_pending {
4691                            pending
4692                        } else if self.is_impersonated(from) {
4693                            let transaction = typed_tx.into_impersonated();
4694                            self.ensure_typed_transaction_supported(&transaction)?;
4695                            PendingTransaction::with_impersonated(transaction, from)
4696                        } else {
4697                            let transaction = self.sign_request(&from, typed_tx)?;
4698                            self.ensure_typed_transaction_supported(&transaction)?;
4699                            PendingTransaction::new(transaction)?
4700                        }
4701                    }
4702                };
4703
4704                let pooled = PoolTransaction::new(pending).with_replay();
4705                txs.entry(block_index).or_default().push(Arc::new(pooled));
4706            }
4707
4708            txs
4709        };
4710
4711        self.rollback_backend(common_block, &mining_guard).await?;
4712        self.backend.reorg(depth, block_pool_txs, &mining_guard).await?;
4713        Ok(())
4714    }
4715
4716    /// Mine blocks, instantly.
4717    ///
4718    /// Handler for RPC call: `evm_mine`
4719    ///
4720    /// This will mine the blocks regardless of the configured mining mode.
4721    /// **Note**: ganache returns `0x0` here as placeholder for additional meta-data in the future.
4722    pub async fn evm_mine(&self, opts: Option<MineOptions>) -> Result<String> {
4723        node_info!("evm_mine");
4724
4725        self.do_evm_mine(opts).await?;
4726
4727        Ok("0x0".to_string())
4728    }
4729
4730    /// Mine blocks, instantly and return the mined blocks.
4731    ///
4732    /// Handler for RPC call: `evm_mine_detailed`
4733    ///
4734    /// This will mine the blocks regardless of the configured mining mode.
4735    ///
4736    /// **Note**: This behaves exactly as [Self::evm_mine] but returns different output, for
4737    /// compatibility reasons, this is a separate call since `evm_mine` is not an anvil original.
4738    /// and `ganache` may change the `0x0` placeholder.
4739    pub async fn evm_mine_detailed(&self, opts: Option<MineOptions>) -> Result<Vec<AnyRpcBlock>> {
4740        node_info!("evm_mine_detailed");
4741
4742        let mined_blocks = self.do_evm_mine(opts).await?;
4743
4744        let mut blocks = Vec::with_capacity(mined_blocks as usize);
4745
4746        let latest = self.backend.best_number();
4747        for offset in (0..mined_blocks).rev() {
4748            let block_num = latest - offset;
4749            if let Some(mut block) =
4750                self.backend.block_by_number_full(BlockNumber::Number(block_num)).await?
4751            {
4752                let block_txs = match block.transactions_mut() {
4753                    BlockTransactions::Full(txs) => txs,
4754                    BlockTransactions::Hashes(_) | BlockTransactions::Uncle => unreachable!(),
4755                };
4756                for tx in block_txs.iter_mut() {
4757                    if let Some(receipt) = self.backend.mined_transaction_receipt(tx.tx_hash())
4758                        && let Some(output) = receipt.out
4759                    {
4760                        // insert revert reason if failure
4761                        if !receipt.inner.as_ref().status()
4762                            && let Some(reason) = RevertDecoder::new().maybe_decode(&output, None)
4763                        {
4764                            tx.other.insert(
4765                                "revertReason".to_string(),
4766                                serde_json::to_value(reason).expect("Infallible"),
4767                            );
4768                        }
4769                        tx.other.insert(
4770                            "output".to_string(),
4771                            serde_json::to_value(output).expect("Infallible"),
4772                        );
4773                    }
4774                }
4775                block.transactions = BlockTransactions::Full(block_txs.clone());
4776                blocks.push(block);
4777            }
4778        }
4779
4780        Ok(blocks)
4781    }
4782
4783    /// Execute a transaction regardless of signature status
4784    ///
4785    /// Handler for ETH RPC call: `eth_sendUnsignedTransaction`
4786    pub async fn eth_send_unsigned_transaction(
4787        &self,
4788        request: WithOtherFields<TransactionRequest>,
4789    ) -> Result<TxHash> {
4790        node_info!("eth_sendUnsignedTransaction");
4791        let request = self.parse_transaction_request(request)?;
4792        // either use the impersonated account of the request's `from` field
4793        let from = request.from().ok_or(BlockchainError::NoSignerAvailable)?;
4794
4795        let nonce = self.request_nonce_for_transaction(&request, from).await?;
4796
4797        let typed_tx = self.build_tx_request(request, nonce).await?;
4798
4799        let transaction = typed_tx.into_impersonated();
4800
4801        self.ensure_typed_transaction_supported(&transaction)?;
4802
4803        let pending_transaction = PendingTransaction::with_impersonated(transaction, from);
4804
4805        self.add_pending_transaction(pending_transaction).await
4806    }
4807
4808    /// Returns a summary of all the transactions currently pending for inclusion in the next
4809    /// block(s), as well as the ones that are being scheduled for future execution only.
4810    ///
4811    /// See [here](https://geth.ethereum.org/docs/rpc/ns-txpool#txpool_inspect) for more details
4812    ///
4813    /// Handler for ETH RPC call: `txpool_inspect`
4814    pub async fn txpool_inspect(&self) -> Result<TxpoolInspect> {
4815        node_info!("txpool_inspect");
4816        let mut inspect = TxpoolInspect::default();
4817
4818        fn convert(tx: Arc<PoolTransaction<FoundryTxEnvelope>>) -> TxpoolInspectSummary {
4819            let tx = &tx.pending_transaction.transaction;
4820            let to = tx.to();
4821            let gas_price = tx.max_fee_per_gas();
4822            let value = tx.value();
4823            let gas = tx.gas_limit();
4824            TxpoolInspectSummary { to, value, gas, gas_price }
4825        }
4826
4827        // Note: naming differs geth vs anvil:
4828        //
4829        // _Pending transactions_ are transactions that are ready to be processed and included in
4830        // the block. _Queued transactions_ are transactions where the transaction nonce is
4831        // not in sequence. The transaction nonce is an incrementing number for each transaction
4832        // with the same From address.
4833        for pending in self.pool.ready_transactions() {
4834            let entry = inspect.pending.entry(*pending.pending_transaction.sender()).or_default();
4835            let key = txpool_transaction_key(&pending.pending_transaction);
4836            entry.insert(key, convert(pending));
4837        }
4838        for queued in self.pool.pending_transactions() {
4839            let entry = inspect.queued.entry(*queued.pending_transaction.sender()).or_default();
4840            let key = txpool_transaction_key(&queued.pending_transaction);
4841            entry.insert(key, convert(queued));
4842        }
4843        Ok(inspect)
4844    }
4845
4846    /// Returns the details of all transactions currently pending for inclusion in the next
4847    /// block(s), as well as the ones that are being scheduled for future execution only.
4848    ///
4849    /// See [here](https://geth.ethereum.org/docs/rpc/ns-txpool#txpool_content) for more details
4850    ///
4851    /// Handler for ETH RPC call: `txpool_content`
4852    pub async fn txpool_content(&self) -> Result<TxpoolContent<AnyRpcTransaction>> {
4853        node_info!("txpool_content");
4854        self.build_txpool_content(None)
4855    }
4856
4857    /// Builds the txpool content, optionally filtered to a single sender.
4858    ///
4859    /// When `filter` is `Some`, only transactions from that sender are converted, avoiding the
4860    /// cost of building RPC transactions for unrelated senders.
4861    fn build_txpool_content(
4862        &self,
4863        filter: Option<Address>,
4864    ) -> Result<TxpoolContent<AnyRpcTransaction>> {
4865        let mut content = TxpoolContent::<AnyRpcTransaction>::default();
4866        fn convert(tx: Arc<PoolTransaction<FoundryTxEnvelope>>) -> Result<AnyRpcTransaction> {
4867            let from = *tx.pending_transaction.sender();
4868            let tx = transaction_build(
4869                Some(tx.hash()),
4870                tx.pending_transaction.transaction.clone(),
4871                None,
4872                None,
4873                None,
4874            );
4875
4876            let WithOtherFields { inner: mut tx, other } = tx.0;
4877
4878            // we set the from field here explicitly to the set sender of the pending transaction,
4879            // in case the transaction is impersonated.
4880            tx.inner = Recovered::new_unchecked(tx.inner.into_inner(), from);
4881
4882            let tx = AnyRpcTransaction(WithOtherFields { inner: tx, other });
4883
4884            Ok(tx)
4885        }
4886
4887        for pending in self.pool.ready_transactions() {
4888            let sender = *pending.pending_transaction.sender();
4889            if filter.is_some_and(|from| from != sender) {
4890                continue;
4891            }
4892            let entry = content.pending.entry(sender).or_default();
4893            let key = txpool_transaction_key(&pending.pending_transaction);
4894            entry.insert(key, convert(pending)?);
4895        }
4896        for queued in self.pool.pending_transactions() {
4897            let sender = *queued.pending_transaction.sender();
4898            if filter.is_some_and(|from| from != sender) {
4899                continue;
4900            }
4901            let entry = content.queued.entry(sender).or_default();
4902            let key = txpool_transaction_key(&queued.pending_transaction);
4903            entry.insert(key, convert(queued)?);
4904        }
4905
4906        Ok(content)
4907    }
4908
4909    /// Returns the details of all transactions currently pending for inclusion in the next
4910    /// block(s), as well as the ones that are being scheduled for future execution only, filtered
4911    /// by sender.
4912    ///
4913    /// See [here](https://geth.ethereum.org/docs/rpc/ns-txpool#txpool_contentFrom) for more details
4914    ///
4915    /// Handler for ETH RPC call: `txpool_contentFrom`
4916    pub async fn txpool_content_from(
4917        &self,
4918        from: Address,
4919    ) -> Result<TxpoolContentFrom<AnyRpcTransaction>> {
4920        node_info!("txpool_contentFrom");
4921        let mut content = self.build_txpool_content(Some(from))?;
4922        Ok(content.remove_from(&from))
4923    }
4924}
4925
4926impl EthApi<FoundryNetwork> {
4927    /// Executes the `evm_mine` and returns the number of blocks mined
4928    async fn do_evm_mine(&self, opts: Option<MineOptions>) -> Result<u64> {
4929        let mut blocks_to_mine = 1u64;
4930
4931        if let Some(opts) = opts {
4932            let timestamp = match opts {
4933                MineOptions::Timestamp(timestamp) => timestamp,
4934                MineOptions::Options { timestamp, blocks } => {
4935                    if let Some(blocks) = blocks {
4936                        blocks_to_mine = blocks;
4937                    }
4938                    timestamp
4939                }
4940            };
4941            if let Some(timestamp) = timestamp {
4942                // timestamp was explicitly provided to be the next timestamp
4943                self.evm_set_next_block_timestamp(timestamp)?;
4944            }
4945        }
4946
4947        // this can be blocking for a bit, especially in forking mode
4948        // <https://github.com/foundry-rs/foundry/issues/6036>
4949        self.on_blocking_task(|this| async move {
4950            // mine all the blocks
4951            for _ in 0..blocks_to_mine {
4952                this.mine_one().await?;
4953            }
4954            Ok(())
4955        })
4956        .await?;
4957
4958        Ok(blocks_to_mine)
4959    }
4960
4961    async fn do_estimate_gas(
4962        &self,
4963        request: WithOtherFields<TransactionRequest>,
4964        block_number: Option<BlockId>,
4965        overrides: EvmOverrides,
4966    ) -> Result<u128> {
4967        let block_request = self.block_request(block_number).await?;
4968        // check if the number predates the fork, if in fork mode
4969        if let BlockRequest::Number(number) = block_request
4970            && let Some(fork) = self.get_fork()
4971            && fork.predates_fork(number)
4972        {
4973            if overrides.has_state() || overrides.has_block() {
4974                return Err(BlockchainError::EvmOverrideError(
4975                    "not available on past forked blocks".to_string(),
4976                ));
4977            }
4978            return Ok(fork.estimate_gas_raw(&request, Some(number.into())).await?);
4979        }
4980
4981        // this can be blocking for a bit, especially in forking mode
4982        // <https://github.com/foundry-rs/foundry/issues/6036>
4983        self.on_blocking_task(|this| async move {
4984            let request = this.parse_transaction_request(request)?;
4985            this.backend
4986                .with_database_at_and_context(
4987                    Some(block_request),
4988                    |state, mut block, monad_context| {
4989                        let mut cache_db = CacheDB::new(&*state);
4990                        if let Some(state_overrides) = overrides.state {
4991                            apply_state_overrides(
4992                                state_overrides.into_iter().collect(),
4993                                &mut cache_db,
4994                            )?;
4995                        }
4996                        if let Some(block_overrides) = overrides.block {
4997                            cache_db.apply_block_overrides(*block_overrides, &mut block);
4998                        }
4999                        this.do_estimate_gas_with_state(request, &cache_db, block, monad_context)
5000                    },
5001                )
5002                .await
5003        })
5004        .await
5005    }
5006
5007    async fn do_estimate_gas_typed(
5008        &self,
5009        request: FoundryTransactionRequest,
5010        block_number: Option<BlockId>,
5011    ) -> Result<u128> {
5012        let block_request = self.block_request(block_number).await?;
5013        self.on_blocking_task(|this| async move {
5014            this.backend
5015                .with_database_at_and_context(Some(block_request), |state, block, monad_context| {
5016                    this.do_estimate_gas_with_state(request, &state, block, monad_context)
5017                })
5018                .await
5019        })
5020        .await
5021    }
5022
5023    /// Returns the priority of the transaction based on the current `TransactionOrder`
5024    fn transaction_priority(&self, tx: &FoundryTxEnvelope) -> TransactionPriority {
5025        self.transaction_order.read().priority(tx)
5026    }
5027
5028    /// Returns a listener for pending transactions, yielding full transactions
5029    pub fn full_pending_transactions(&self) -> UnboundedReceiver<AnyRpcTransaction> {
5030        let (tx, rx) = unbounded_channel();
5031        let mut hashes = self.new_ready_transaction_subscription();
5032
5033        let this = self.clone();
5034
5035        tokio::spawn(async move {
5036            while let Some(hash) = hashes.next().await {
5037                if let Ok(Some(txn)) = this.transaction_by_hash(hash).await
5038                    && tx.send(txn).is_err()
5039                {
5040                    break;
5041                }
5042            }
5043        });
5044
5045        rx
5046    }
5047
5048    /// Returns a bounded stream of full pending transactions for poll-based filters.
5049    ///
5050    /// Unlike [`Self::full_pending_transactions`], this applies backpressure via a bounded channel,
5051    /// so an unpolled filter cannot buffer transactions without bound.
5052    pub fn full_pending_transactions_filter(&self) -> mpsc::Receiver<AnyRpcTransaction> {
5053        // Mirror the pool's ready-listener buffer so a full filter is bounded like a hash filter.
5054        let (tx, rx) = mpsc::channel(2048);
5055        let mut hashes = self.new_ready_transactions();
5056        let this = self.clone();
5057
5058        tokio::spawn(async move {
5059            while let Some(hash) = hashes.next().await {
5060                if let Ok(Some(txn)) = this.transaction_by_hash(hash).await
5061                    && tx.send(txn).await.is_err()
5062                {
5063                    break;
5064                }
5065            }
5066        });
5067
5068        rx
5069    }
5070
5071    /// Returns a listener for new block receipts.
5072    pub fn transaction_receipts_subscription(
5073        &self,
5074        filter: TransactionReceiptsParams,
5075    ) -> UnboundedReceiver<Vec<FoundryTxReceipt>> {
5076        let (tx, rx) = unbounded_channel();
5077        let mut blocks = self.new_block_notifications();
5078        let this = self.clone();
5079
5080        tokio::spawn(async move {
5081            // Precompute the hash filter once.
5082            let hash_filter = filter
5083                .transaction_hashes
5084                .filter(|hashes| !hashes.is_empty())
5085                .map(|hashes| hashes.into_iter().collect::<B256Set>());
5086
5087            loop {
5088                let notification = tokio::select! {
5089                    biased;
5090                    // Exit when the subscriber unsubscribes, even while awaiting the next block.
5091                    _ = tx.closed() => break,
5092                    maybe_block = blocks.next() => match maybe_block {
5093                        Some(block) => block,
5094                        None => break,
5095                    },
5096                };
5097
5098                let Some(block) = notification.as_new_block() else {
5099                    continue;
5100                };
5101
5102                let receipts = match this.block_receipts(BlockId::hash(block.hash)).await {
5103                    Ok(Some(mut receipts)) => {
5104                        if let Some(hashes) = &hash_filter {
5105                            receipts.retain(|receipt| hashes.contains(&receipt.transaction_hash()));
5106                        }
5107                        receipts
5108                    }
5109                    Ok(None) => continue,
5110                    Err(err) => {
5111                        trace!(target: "node", %err, "failed to build block receipts for subscription");
5112                        continue;
5113                    }
5114                };
5115
5116                if receipts.is_empty() {
5117                    continue;
5118                }
5119
5120                if tx.send(receipts).is_err() {
5121                    break;
5122                }
5123            }
5124        });
5125
5126        rx
5127    }
5128
5129    /// Mines exactly one block
5130    pub async fn mine_one(&self) -> Result<()> {
5131        self.mine_one_with_timestamp_pinning(false).await
5132    }
5133
5134    async fn mine_one_with_timestamp_pinning(&self, pin_timestamp: bool) -> Result<()> {
5135        let _mining = self.backend.lock_mining().await;
5136        let transactions = self.pool.ready_transactions().collect::<Vec<_>>();
5137        let outcome = self.backend.mine_block_locked(transactions, pin_timestamp).await?;
5138
5139        trace!(target: "node", blocknumber = ?outcome.block_number, "mined block");
5140        if self.pool.on_mined_block(outcome) {
5141            self.miner.retry_ready_transactions();
5142        }
5143        Ok(())
5144    }
5145
5146    /// Returns the pending block with tx hashes
5147    async fn pending_block(&self) -> Result<AnyRpcBlock> {
5148        let transactions = self.pool.ready_transactions().collect::<Vec<_>>();
5149        let info = self.backend.pending_block(transactions).await?;
5150        Ok(self.backend.convert_block(info.block))
5151    }
5152
5153    /// Returns the full pending block with `Transaction` objects
5154    async fn pending_block_full(&self) -> Result<Option<AnyRpcBlock>> {
5155        let transactions = self.pool.ready_transactions().collect::<Vec<_>>();
5156        let BlockInfo { block, transactions, receipts: _ } =
5157            self.backend.pending_block(transactions).await?;
5158
5159        let mut partial_block = self.backend.convert_block(block.clone());
5160
5161        let mut block_transactions = Vec::with_capacity(block.body.transactions.len());
5162        let base_fee = self.backend.base_fee();
5163
5164        for info in transactions {
5165            let Some(tx) = block.body.transactions.get(info.transaction_index as usize).cloned()
5166            else {
5167                return Ok(None);
5168            };
5169
5170            let tx = transaction_build(
5171                Some(info.transaction_hash),
5172                tx,
5173                Some(&block),
5174                Some(info),
5175                Some(base_fee),
5176            );
5177            block_transactions.push(tx);
5178        }
5179
5180        partial_block.transactions = BlockTransactions::from(block_transactions);
5181
5182        Ok(Some(partial_block))
5183    }
5184
5185    /// Prepares transaction request by filling missing fields using Anvil's API, then attempts
5186    /// to build a [`FoundryTypedTx`].
5187    async fn build_tx_request(
5188        &self,
5189        request: FoundryTransactionRequest,
5190        nonce: u64,
5191    ) -> Result<FoundryTypedTx> {
5192        self.build_tx_request_with_fee_defaults(request, nonce, None).await
5193    }
5194
5195    async fn build_tx_request_with_fee_defaults(
5196        &self,
5197        mut request: FoundryTransactionRequest,
5198        nonce: u64,
5199        fee_defaults: Option<TransactionFeeDefaults>,
5200    ) -> Result<FoundryTypedTx> {
5201        let from = request.from().or(self.accounts()?.first().copied());
5202        if let Some(from) = from {
5203            request.set_from(from);
5204        }
5205
5206        // Fill common fields for all tx types
5207        request.chain_id().is_none().then(|| request.set_chain_id(self.chain_id()));
5208        request.nonce().is_none().then(|| request.set_nonce(nonce));
5209        let is_tempo_batch =
5210            matches!(&request, FoundryTransactionRequest::Tempo(tx) if !tx.calls.is_empty());
5211        if request.kind().is_none() && !is_tempo_batch {
5212            request.set_kind(TxKind::default());
5213        }
5214        if request.gas_limit().is_none() {
5215            let fallback_gas_limit = {
5216                let evm_env = self.backend.evm_env().read();
5217                self.backend.fallback_tx_gas_limit(&evm_env)
5218            };
5219            let estimated_gas = self
5220                .do_estimate_gas_typed(request.clone(), None)
5221                .await
5222                .map(|v| v as u64)
5223                .unwrap_or_else(|_| {
5224                    if is_simple_transfer_request(request.as_ref()) {
5225                        MIN_TRANSACTION_GAS as u64
5226                    } else {
5227                        fallback_gas_limit
5228                    }
5229                });
5230            request.set_gas_limit(estimated_gas);
5231        }
5232
5233        // Fill missing tx type specific fields
5234        if let Err((tx_type, _)) = request.missing_keys() {
5235            let gas_price = || fee_defaults.map_or_else(|| self.gas_price(), |fees| fees.gas_price);
5236            if tx_type.is_legacy() || tx_type.is_eip2930() {
5237                request.gas_price().is_none().then(|| request.set_gas_price(gas_price()));
5238            }
5239            if tx_type.is_eip2930() {
5240                request
5241                    .access_list()
5242                    .is_none()
5243                    .then(|| request.set_access_list(Default::default()));
5244            }
5245            if tx_type.is_eip1559()
5246                || tx_type.is_eip4844()
5247                || tx_type.is_eip7702()
5248                || tx_type.is_tempo()
5249                || tx_type.is_celo()
5250            {
5251                request
5252                    .max_fee_per_gas()
5253                    .is_none()
5254                    .then(|| request.set_max_fee_per_gas(gas_price()));
5255                request
5256                    .max_priority_fee_per_gas()
5257                    .is_none()
5258                    .then(|| request.set_max_priority_fee_per_gas(MIN_SUGGESTED_PRIORITY_FEE));
5259            }
5260            if tx_type.is_eip4844() {
5261                request.as_ref().max_fee_per_blob_gas().is_none().then(|| {
5262                    let blob_gas_price = fee_defaults.map_or_else(
5263                        || self.backend.fees().get_next_block_blob_base_fee_per_gas(),
5264                        |fees| fees.blob_gas_price,
5265                    );
5266                    request.as_mut().set_max_fee_per_blob_gas(blob_gas_price)
5267                });
5268            }
5269        }
5270
5271        match request
5272            .build_unsigned()
5273            .map_err(|e| BlockchainError::InvalidTransactionRequest(e.to_string()))?
5274        {
5275            FoundryTypedTx::Eip4844(TxEip4844Variant::TxEip4844(_))
5276                if !self.backend.skip_blob_validation(from) =>
5277            {
5278                // If blob validation is not skipped, reject TxEip4844 variant without sidecar.
5279                Err(BlockchainError::FailedToDecodeTransaction)
5280            }
5281            res => Ok(res),
5282        }
5283    }
5284
5285    /// Returns the nonce of the `address` depending on the `block_number`
5286    async fn get_transaction_count(
5287        &self,
5288        address: Address,
5289        block_number: Option<BlockId>,
5290    ) -> Result<u64> {
5291        let block_request = self.block_request(block_number).await?;
5292
5293        if let BlockRequest::Number(number) = block_request
5294            && let Some(fork) = self.get_fork()
5295            && fork.predates_fork(number)
5296        {
5297            return Ok(fork.get_nonce(address, number).await?);
5298        }
5299
5300        self.backend.get_nonce(address, block_request).await
5301    }
5302
5303    /// Returns the nonce for this request
5304    ///
5305    /// If the nonce field of the `request` is `None`, this accounts for pending transactions from
5306    /// the sender.
5307    async fn request_nonce(&self, request: &TransactionRequest, from: Address) -> Result<u64> {
5308        if let Some(nonce) = request.nonce {
5309            Ok(nonce)
5310        } else {
5311            self.get_transaction_count(from, Some(BlockId::pending())).await
5312        }
5313    }
5314
5315    /// Adds the given transaction to the pool
5316    async fn add_pending_transaction(
5317        &self,
5318        pending_transaction: PendingTransaction<FoundryTxEnvelope>,
5319    ) -> Result<TxHash> {
5320        let _mining = self.backend.lock_mining().await;
5321        self.backend.validate_pool_transaction(&pending_transaction).await?;
5322
5323        let from = *pending_transaction.sender();
5324        #[cfg(feature = "base")]
5325        let base_markers = self.eip8130_nonce_markers(&pending_transaction).await?;
5326        #[cfg(not(feature = "base"))]
5327        let base_markers = None;
5328
5329        let markers = if base_markers.is_some() {
5330            base_markers
5331        } else {
5332            self.tempo_nonce_markers(&pending_transaction).await?
5333        };
5334        let (requires, provides) = if let Some(markers) = markers {
5335            markers
5336        } else {
5337            let nonce = pending_transaction.transaction.nonce();
5338            let on_chain_nonce = self.backend.current_nonce(from).await?;
5339            (required_marker(nonce, on_chain_nonce, from), vec![to_marker(nonce, from)])
5340        };
5341
5342        debug_assert!(requires != provides);
5343        let priority = self.transaction_priority(&pending_transaction.transaction);
5344        let pool_transaction =
5345            PoolTransaction { requires, provides, pending_transaction, priority, is_replay: false };
5346        let tx = self.pool.add_transaction(pool_transaction)?;
5347        trace!(target: "node", "Added transaction: [{:?}] sender={:?}", tx.hash(), from);
5348        Ok(*tx.hash())
5349    }
5350
5351    /// Returns Tempo lane/replay markers when the transaction does not use the protocol nonce.
5352    async fn tempo_nonce_markers(
5353        &self,
5354        pending: &PendingTransaction<FoundryTxEnvelope>,
5355    ) -> Result<Option<(Vec<TxMarker>, Vec<TxMarker>)>> {
5356        let FoundryTxEnvelope::Tempo(signed) = pending.transaction.as_ref() else {
5357            return Ok(None);
5358        };
5359        let tx = signed.tx();
5360        if tx.nonce_key.is_zero() {
5361            return Ok(None);
5362        }
5363        if tx.nonce_key == U256::MAX {
5364            return Ok(Some((Vec::new(), vec![pending.hash().to_vec()])));
5365        }
5366
5367        let state_nonce = self.backend.tempo_nonce(*pending.sender(), tx.nonce_key, None).await?;
5368        if tx.nonce < state_nonce {
5369            return Err(InvalidTransactionError::NonceTooLow.into());
5370        }
5371
5372        let requires = if tx.nonce == state_nonce {
5373            Vec::new()
5374        } else {
5375            vec![tempo_nonce_marker(*pending.sender(), tx.nonce_key, tx.nonce - 1)]
5376        };
5377        let provides = vec![tempo_nonce_marker(*pending.sender(), tx.nonce_key, tx.nonce)];
5378        Ok(Some((requires, provides)))
5379    }
5380
5381    /// Returns Base EIP-8130 channel/replay markers when the transaction does not use the
5382    /// protocol nonce lane.
5383    #[cfg(feature = "base")]
5384    async fn eip8130_nonce_markers(
5385        &self,
5386        pending: &PendingTransaction<FoundryTxEnvelope>,
5387    ) -> Result<Option<(Vec<TxMarker>, Vec<TxMarker>)>> {
5388        if let FoundryTxEnvelope::Eip8130(signed) = pending.transaction.as_ref() {
5389            let tx = signed.tx();
5390            let now = self.backend.eip8130_pool_timestamp_ms();
5391            signed
5392                .validate_admission_static(self.backend.chain_id().to())
5393                .map_err(|error| BlockchainError::Eip8130TransactionRejected(error.to_string()))?;
5394            signed
5395                .validate_timestamp(now)
5396                .map_err(|error| BlockchainError::Eip8130TransactionRejected(error.to_string()))?;
5397            if tx.nonce_key.is_zero() {
5398                let state_nonce = self.backend.current_nonce(*pending.sender()).await?;
5399                if tx.nonce_sequence < state_nonce {
5400                    return Err(InvalidTransactionError::NonceTooLow.into());
5401                }
5402                let provides = vec![to_marker(tx.nonce_sequence, *pending.sender())];
5403                self.ensure_eip8130_replacement_price(pending, &provides)?;
5404                self.ensure_eip8130_payer_reservation(pending, &provides).await?;
5405                return Ok(None);
5406            }
5407            if tx.nonce_key == Eip8130Constants::NONCE_KEY_MAX {
5408                let replay_id = tx.replay_id(*pending.sender());
5409                let slot = NonceManagerStorage::expiring_nonce_seen_slot(replay_id);
5410                let word =
5411                    self.backend.storage_at(NonceManagerStorage::ADDRESS, slot, None).await?;
5412                let recorded_expiry = (Into::<U256>::into(word) & U256::from(u64::MAX)).to::<u64>();
5413                if recorded_expiry > now {
5414                    return Err(BlockchainError::Eip8130TransactionRejected(
5415                        "expiring nonce replay has already been recorded".to_string(),
5416                    ));
5417                }
5418                let provides = vec![eip8130_replay_marker(replay_id)];
5419                self.ensure_eip8130_replacement_price(pending, &provides)?;
5420                self.ensure_eip8130_payer_reservation(pending, &provides).await?;
5421                return Ok(Some((Vec::new(), provides)));
5422            }
5423
5424            let slot = NonceManagerStorage::nonce_slot(*pending.sender(), tx.nonce_key)
5425                .map_err(|error| BlockchainError::InvalidTransactionRequest(error.to_string()))?;
5426            let word = self.backend.storage_at(NonceManagerStorage::ADDRESS, slot, None).await?;
5427            let state_nonce = Eip8130Nonce::decode_channel_nonce(word.into()).to::<u64>();
5428            if tx.nonce_sequence < state_nonce {
5429                return Err(InvalidTransactionError::NonceTooLow.into());
5430            }
5431
5432            let requires = if tx.nonce_sequence == state_nonce {
5433                Vec::new()
5434            } else {
5435                vec![eip8130_channel_marker(*pending.sender(), tx.nonce_key, tx.nonce_sequence - 1)]
5436            };
5437            let provides =
5438                vec![eip8130_channel_marker(*pending.sender(), tx.nonce_key, tx.nonce_sequence)];
5439            self.ensure_eip8130_replacement_price(pending, &provides)?;
5440            self.ensure_eip8130_payer_reservation(pending, &provides).await?;
5441            return Ok(Some((requires, provides)));
5442        }
5443
5444        Ok(None)
5445    }
5446
5447    /// Enforces Base's default ten-percent EIP-8130 replacement price bump.
5448    #[cfg(feature = "base")]
5449    fn ensure_eip8130_replacement_price(
5450        &self,
5451        pending: &PendingTransaction<FoundryTxEnvelope>,
5452        provides: &[TxMarker],
5453    ) -> Result<()> {
5454        let Some(existing) = self.pool.transaction_with_markers(*pending.sender(), provides) else {
5455            return Ok(());
5456        };
5457        let FoundryTxEnvelope::Eip8130(incoming) = pending.transaction.as_ref() else {
5458            return Ok(());
5459        };
5460        let FoundryTxEnvelope::Eip8130(current) = existing.pending_transaction.transaction.as_ref()
5461        else {
5462            return Ok(());
5463        };
5464
5465        const PRICE_BUMP_PERCENT: u128 = 10;
5466        let bumped =
5467            |price: u128| price.saturating_mul(100 + PRICE_BUMP_PERCENT).saturating_add(99) / 100;
5468        if incoming.tx().max_fee_per_gas < bumped(current.tx().max_fee_per_gas)
5469            || incoming.tx().max_priority_fee_per_gas
5470                < bumped(current.tx().max_priority_fee_per_gas)
5471        {
5472            return Err(
5473                crate::eth::error::PoolError::ReplacementUnderpriced(*pending.hash()).into()
5474            );
5475        }
5476        Ok(())
5477    }
5478
5479    /// Reserves each payer's maximum EIP-8130 fee across pending transactions.
5480    #[cfg(feature = "base")]
5481    async fn ensure_eip8130_payer_reservation(
5482        &self,
5483        pending: &PendingTransaction<FoundryTxEnvelope>,
5484        replacing_markers: &[TxMarker],
5485    ) -> Result<()> {
5486        let FoundryTxEnvelope::Eip8130(incoming) = pending.transaction.as_ref() else {
5487            return Ok(());
5488        };
5489        let payer = incoming.tx().payer.unwrap_or(*pending.sender());
5490        let incoming_cost = FeeCheck::max_fee_charge(
5491            incoming.tx().gas_limit,
5492            IntrinsicGas::max_payer_auth_cost(incoming)
5493                .map_err(|error| BlockchainError::Eip8130TransactionRejected(error.to_string()))?,
5494            incoming.tx().max_fee_per_gas,
5495        );
5496        let mut reserved = U256::ZERO;
5497        for pooled in self.pool.all_transactions() {
5498            if pooled.provides == replacing_markers {
5499                continue;
5500            }
5501            let FoundryTxEnvelope::Eip8130(signed) =
5502                pooled.pending_transaction.transaction.as_ref()
5503            else {
5504                continue;
5505            };
5506            if signed.tx().payer.unwrap_or(*pooled.pending_transaction.sender()) != payer {
5507                continue;
5508            }
5509            let payer_auth = IntrinsicGas::max_payer_auth_cost(signed)
5510                .map_err(|error| BlockchainError::Eip8130TransactionRejected(error.to_string()))?;
5511            reserved = reserved.saturating_add(FeeCheck::max_fee_charge(
5512                signed.tx().gas_limit,
5513                payer_auth,
5514                signed.tx().max_fee_per_gas,
5515            ));
5516        }
5517        let balance = self.backend.get_account(payer).await?.balance;
5518        let required = reserved.saturating_add(incoming_cost);
5519        if balance < required {
5520            return Err(BlockchainError::Eip8130TransactionRejected(format!(
5521                "gas payer balance {balance} is below pending reservation {required}"
5522            )));
5523        }
5524        Ok(())
5525    }
5526
5527    /// additional validation against hardfork
5528    fn ensure_typed_transaction_supported(&self, tx: &FoundryTxEnvelope) -> Result<()> {
5529        match &tx {
5530            FoundryTxEnvelope::Eip2930(_) => self.backend.ensure_eip2930_active(),
5531            FoundryTxEnvelope::Eip1559(_) => self.backend.ensure_eip1559_active(),
5532            FoundryTxEnvelope::Eip4844(_) => self.backend.ensure_eip4844_active(),
5533            FoundryTxEnvelope::Eip7702(_) => self.backend.ensure_eip7702_active(),
5534            #[cfg(any(feature = "base", feature = "optimism"))]
5535            FoundryTxEnvelope::Deposit(_) => self.backend.ensure_deposits_active(),
5536            #[cfg(feature = "optimism")]
5537            FoundryTxEnvelope::PostExec(_) => Err(BlockchainError::InvalidTransactionRequest(
5538                "not implemented for post-exec tx".to_string(),
5539            )),
5540            #[cfg(feature = "base")]
5541            FoundryTxEnvelope::Eip8130(_) => self.backend.ensure_base_eip8130_submission_active(),
5542            FoundryTxEnvelope::Celo(_) => self.backend.ensure_cip64_active(),
5543            FoundryTxEnvelope::Legacy(_) => Ok(()),
5544            FoundryTxEnvelope::Tempo(_) => self.backend.ensure_tempo_active(),
5545        }
5546    }
5547
5548    /// Sets the fee token for a user address.
5549    ///
5550    /// Handler for RPC call: `anvil_setFeeToken`
5551    ///
5552    /// Only supported when running in Tempo mode (`--tempo`).
5553    pub async fn anvil_set_fee_token(&self, user: Address, token: Address) -> Result<()> {
5554        node_info!("anvil_setFeeToken");
5555        self.ensure_tempo_mode()?;
5556        self.backend.set_fee_token(user, token).await?;
5557        Ok(())
5558    }
5559
5560    /// Sets the fee token for a validator address.
5561    ///
5562    /// Handler for RPC call: `anvil_setValidatorFeeToken`
5563    ///
5564    /// Only supported when running in Tempo mode (`--tempo`).
5565    pub async fn anvil_set_validator_fee_token(
5566        &self,
5567        validator: Address,
5568        token: Address,
5569    ) -> Result<()> {
5570        node_info!("anvil_setValidatorFeeToken");
5571        self.ensure_tempo_mode()?;
5572        self.backend.set_validator_fee_token(validator, token).await?;
5573        Ok(())
5574    }
5575
5576    /// Mints FeeAMM liquidity for a token pair.
5577    ///
5578    /// Handler for RPC call: `anvil_setFeeAmmLiquidity`
5579    ///
5580    /// Only supported when running in Tempo mode (`--tempo`).
5581    pub async fn anvil_set_fee_amm_liquidity(
5582        &self,
5583        user_token: Address,
5584        validator_token: Address,
5585        amount: U256,
5586    ) -> Result<()> {
5587        node_info!("anvil_setFeeAmmLiquidity");
5588        self.ensure_tempo_mode()?;
5589        self.backend.set_fee_amm_liquidity(user_token, validator_token, amount).await?;
5590        Ok(())
5591    }
5592
5593    /// Ensures anvil runs in Tempo mode (`--tempo`), the RPC method is unavailable otherwise.
5594    fn ensure_tempo_mode(&self) -> Result<()> {
5595        if self.backend.is_tempo() { Ok(()) } else { Err(BlockchainError::RpcUnimplemented) }
5596    }
5597
5598    fn parse_transaction_request(
5599        &self,
5600        request: WithOtherFields<TransactionRequest>,
5601    ) -> Result<FoundryTransactionRequest> {
5602        self.backend.parse_transaction_request(request)
5603    }
5604
5605    async fn request_nonce_for_transaction(
5606        &self,
5607        request: &FoundryTransactionRequest,
5608        from: Address,
5609    ) -> Result<u64> {
5610        if let FoundryTransactionRequest::Tempo(request) = request
5611            && let Some(nonce_key) = request.nonce_key.filter(|key| !key.is_zero())
5612        {
5613            if let Some(nonce) = request.nonce() {
5614                return Ok(nonce);
5615            }
5616            let nonce = self.backend.tempo_nonce(from, nonce_key, None).await?;
5617            return Ok(nonce);
5618        }
5619        self.request_nonce(request.as_ref(), from).await
5620    }
5621
5622    /// Returns a local Tempo finalization or history at or before the pinned fork root.
5623    ///
5624    /// Handler for `consensus_getFinalization`; unavailable on non-Tempo networks.
5625    /// Local signing leaves genesis and fork anchors unsigned. Historical fork queries use the
5626    /// upstream committee; `latest` never advances past the pinned root without local mining.
5627    /// Local `latest` uses the retained complete body; height queries require a matching stored
5628    /// body. Returns JSON-RPC error code 503 if the requested certificate or a complete block
5629    /// matching its commitments is unavailable.
5630    pub async fn consensus_get_finalization(
5631        &self,
5632        query: TempoConsensusQuery,
5633    ) -> Result<TempoCertifiedBlock> {
5634        node_info!("consensus_getFinalization");
5635        let height = match query {
5636            TempoConsensusQuery::Latest => None,
5637            TempoConsensusQuery::Height(height) => Some(height),
5638        };
5639        self.backend.tempo_finalization(height).await
5640    }
5641
5642    /// Returns the latest local or pinned upstream finalization, with `notarized: null` as on
5643    /// Tempo.
5644    ///
5645    /// Handler for `consensus_getLatest`; unavailable on non-Tempo networks.
5646    /// Returns `finalized: null` for unsigned standalone history. A fork queries its pinned root
5647    /// until local mining produces a certificate, preserving upstream errors.
5648    /// Returns JSON-RPC error code 503 if a certificate exists but its complete block is
5649    /// unavailable or no longer matches its commitments, including after rollback to a pruned
5650    /// body.
5651    pub async fn consensus_get_latest(&self) -> Result<TempoConsensusState> {
5652        node_info!("consensus_getLatest");
5653        let finalized = self.backend.tempo_latest_finalization().await?;
5654        Ok(TempoConsensusState { finalized, notarized: None })
5655    }
5656
5657    /// Returns the public local development committee on Tempo networks.
5658    ///
5659    /// Handler for `anvil_tempoConsensusIdentity`.
5660    pub async fn anvil_tempo_consensus_identity(&self) -> Result<TempoConsensusIdentity> {
5661        node_info!("anvil_tempoConsensusIdentity");
5662        self.backend.tempo_consensus_identity().await
5663    }
5664
5665    /// Schedules a new identity for the epoch following the next block's epoch.
5666    ///
5667    /// Handler for `anvil_tempoRotateConsensusIdentity`; unavailable on non-Tempo networks.
5668    pub async fn anvil_tempo_rotate_consensus_identity(&self) -> Result<TempoConsensusIdentity> {
5669        node_info!("anvil_tempoRotateConsensusIdentity");
5670        self.backend.tempo_rotate_consensus_identity().await
5671    }
5672}
5673
5674fn is_simple_transfer_request(request: &TransactionRequest) -> bool {
5675    request.to.as_ref().and_then(TxKind::to).is_some()
5676        && (request.input.input().is_none()
5677            || request.input.input().is_some_and(|data| data.is_empty()))
5678        && request.authorization_list.is_none()
5679        && request.access_list.is_none()
5680        && request.blob_versioned_hashes.is_none()
5681}
5682
5683fn required_marker(provided_nonce: u64, on_chain_nonce: u64, from: Address) -> Vec<TxMarker> {
5684    if provided_nonce == on_chain_nonce {
5685        return Vec::new();
5686    }
5687    let prev_nonce = provided_nonce.saturating_sub(1);
5688    if on_chain_nonce <= prev_nonce { vec![to_marker(prev_nonce, from)] } else { Vec::new() }
5689}
5690
5691fn tempo_nonce_marker(sender: Address, nonce_key: U256, nonce: u64) -> TxMarker {
5692    let mut marker = b"tempo-nonce".to_vec();
5693    marker.extend_from_slice(sender.as_slice());
5694    marker.extend_from_slice(&nonce_key.to_be_bytes::<32>());
5695    marker.extend_from_slice(&nonce.to_be_bytes());
5696    marker
5697}
5698
5699#[cfg(feature = "base")]
5700fn eip8130_channel_marker(sender: Address, nonce_key: U256, nonce_sequence: u64) -> TxMarker {
5701    let mut marker = b"base-eip8130-channel".to_vec();
5702    marker.extend_from_slice(sender.as_slice());
5703    marker.extend_from_slice(&nonce_key.to_be_bytes::<32>());
5704    marker.extend_from_slice(&nonce_sequence.to_be_bytes());
5705    marker
5706}
5707
5708#[cfg(feature = "base")]
5709fn eip8130_replay_marker(replay_id: B256) -> TxMarker {
5710    let mut marker = b"base-eip8130-replay".to_vec();
5711    marker.extend_from_slice(replay_id.as_slice());
5712    marker
5713}
5714
5715/// Rewrites the Tempo fee payer service encoding of a raw transaction into the standard envelope
5716/// encoding.
5717///
5718/// Fee payer service clients submit sponsorship requests with a `0x00` placeholder in the fee
5719/// payer signature field (and the fee token left empty for the sponsor to fill), which the
5720/// standard envelope decoder rejects. The placeholder is rewritten to the standard encoding of
5721/// [`FEE_PAYER_SIGNATURE_MARKER`], preserving the sponsored signing state the sender committed
5722/// to. Returns the normalized raw transaction when the input carries the placeholder and `None`
5723/// for any other encoding.
5724fn normalize_fee_payer_service_encoding(raw: &[u8]) -> Option<Vec<u8>> {
5725    let (tx_type, mut encoded_fields) = raw.split_first()?;
5726    if *tx_type != TEMPO_TX_TYPE_ID {
5727        return None;
5728    }
5729    let PayloadView::List(fields) = Header::decode_raw(&mut encoded_fields).ok()? else {
5730        return None;
5731    };
5732    if !encoded_fields.is_empty() {
5733        return None;
5734    }
5735    // The fee payer signature is the twelfth field of a Tempo AA transaction.
5736    if fields.get(11).is_none_or(|field| *field != [0x00]) {
5737        return None;
5738    }
5739
5740    // The standard encoding of the marker signature, mirroring the fee payer signature closure of
5741    // `TempoTransaction::rlp_encode_fields_default`.
5742    let marker = FEE_PAYER_SIGNATURE_MARKER;
5743    let mut marker_field = Vec::new();
5744    Header { list: true, payload_length: marker.rlp_rs_len() + marker.v().length() }
5745        .encode(&mut marker_field);
5746    marker.write_rlp_vrs(&mut marker_field, marker.v());
5747
5748    let mut payload = Vec::new();
5749    for (index, field) in fields.into_iter().enumerate() {
5750        if index == 11 {
5751            payload.extend_from_slice(&marker_field);
5752        } else {
5753            payload.extend_from_slice(field);
5754        }
5755    }
5756    let mut normalized = vec![TEMPO_TX_TYPE_ID];
5757    Header { list: true, payload_length: payload.len() }.encode(&mut normalized);
5758    normalized.extend_from_slice(&payload);
5759    Some(normalized)
5760}
5761
5762/// EIP-2718 encodes a transaction held in its JSON-RPC form, reporting the types anvil cannot
5763/// encode as [`BlockchainError::UnsupportedTransactionEncoding`].
5764fn encode_rpc_transaction(transaction: &AnyRpcTransaction) -> Result<Bytes> {
5765    FoundryTxEnvelope::encode_rpc_2718(transaction)
5766        .map_err(|_| BlockchainError::UnsupportedTransactionEncoding(transaction.ty()))
5767}
5768
5769fn txpool_transaction_key(pending_transaction: &PendingTransaction<FoundryTxEnvelope>) -> String {
5770    match pending_transaction.transaction.as_ref() {
5771        #[cfg(feature = "base")]
5772        FoundryTxEnvelope::Eip8130(signed) if !signed.tx().nonce_key.is_zero() => {
5773            if signed.tx().nonce_key == Eip8130Constants::NONCE_KEY_MAX {
5774                return signed.tx().replay_id(*pending_transaction.sender()).to_string();
5775            }
5776            format!("{}:{}", signed.tx().nonce_key, signed.tx().nonce_sequence)
5777        }
5778        FoundryTxEnvelope::Tempo(tx) if !tx.tx().nonce_key.is_zero() => {
5779            let tx = tx.tx();
5780            format!("{}:{}", tx.nonce_key, tx.nonce)
5781        }
5782        _ => pending_transaction.nonce().to_string(),
5783    }
5784}
5785
5786fn convert_transact_out(out: &Option<Output>) -> Bytes {
5787    out.as_ref().map(Output::data).cloned().unwrap_or_default()
5788}
5789
5790/// Returns an error if the `exit` code is _not_ ok
5791fn ensure_return_ok(exit: InstructionResult, out: &Option<Output>) -> Result<Bytes> {
5792    let out = convert_transact_out(out);
5793    match exit {
5794        return_ok!() => Ok(out),
5795        return_revert!() => Err(InvalidTransactionError::Revert(Some(out)).into()),
5796        reason => Err(BlockchainError::EvmError(reason)),
5797    }
5798}
5799
5800/// Maps an EVM exit code to the optional `error` string reported in
5801/// `eth_createAccessList` results.
5802fn execution_error(exit: InstructionResult) -> Option<String> {
5803    match SuccessOrHalt::<HaltReason>::from(exit) {
5804        SuccessOrHalt::Success(_) => None,
5805        SuccessOrHalt::Revert => Some("execution reverted".to_string()),
5806        SuccessOrHalt::Halt(reason) => Some(reason.to_string()),
5807        SuccessOrHalt::FatalExternalError => Some("fatal external error".to_string()),
5808        SuccessOrHalt::Internal(_) => Some("internal EVM error".to_string()),
5809    }
5810}
5811
5812/// Keeps result of a call to revm EVM used for gas estimation
5813enum GasEstimationCallResult {
5814    Success(u128),
5815    OutOfGas,
5816    Revert(Option<Bytes>),
5817    EvmError(InstructionResult),
5818}
5819
5820/// Converts the result of a call to revm EVM into a [`GasEstimationCallResult`].
5821///
5822/// Expected to stay up to date with: <https://github.com/bluealloy/revm/blob/main/crates/interpreter/src/instruction_result.rs>
5823impl TryFrom<Result<(InstructionResult, Option<Output>, u128, StateChangeset)>>
5824    for GasEstimationCallResult
5825{
5826    type Error = BlockchainError;
5827
5828    fn try_from(
5829        res: Result<(InstructionResult, Option<Output>, u128, StateChangeset)>,
5830    ) -> Result<Self> {
5831        match res {
5832            // Exceptional case: init used too much gas, treated as out of gas error
5833            Err(BlockchainError::InvalidTransaction(InvalidTransactionError::GasTooHigh(_))) => {
5834                Ok(Self::OutOfGas)
5835            }
5836            // Tempo intrinsic gas errors come through as Message variants
5837            Err(BlockchainError::Message(ref msg))
5838                if msg.contains("insufficient gas for intrinsic cost") =>
5839            {
5840                Ok(Self::OutOfGas)
5841            }
5842            Err(err) => Err(err),
5843            Ok((exit, output, gas, _)) => match exit {
5844                return_ok!() => Ok(Self::Success(gas)),
5845
5846                // Revert opcodes:
5847                InstructionResult::Revert => {
5848                    Ok(Self::Revert(Some(output.map(|o| o.into_data()).unwrap_or_default())))
5849                }
5850                InstructionResult::CallTooDeep
5851                | InstructionResult::OutOfFunds
5852                | InstructionResult::CreateInitCodeStartingEF00
5853                | InstructionResult::InvalidEOFInitCode
5854                | InstructionResult::InvalidExtDelegateCallTarget => Ok(Self::EvmError(exit)),
5855
5856                // Out of gas errors:
5857                InstructionResult::OutOfGas
5858                | InstructionResult::MemoryOOG
5859                | InstructionResult::MemoryLimitOOG
5860                | InstructionResult::PrecompileOOG
5861                | InstructionResult::InvalidOperandOOG
5862                | InstructionResult::ReentrancySentryOOG => Ok(Self::OutOfGas),
5863
5864                // Other errors:
5865                InstructionResult::OpcodeNotFound
5866                | InstructionResult::CallNotAllowedInsideStatic
5867                | InstructionResult::StateChangeDuringStaticCall
5868                | InstructionResult::InvalidFEOpcode
5869                | InstructionResult::InvalidJump
5870                | InstructionResult::NotActivated
5871                | InstructionResult::StackUnderflow
5872                | InstructionResult::StackOverflow
5873                | InstructionResult::OutOfOffset
5874                | InstructionResult::CreateCollision
5875                | InstructionResult::OverflowPayment
5876                | InstructionResult::PrecompileError
5877                | InstructionResult::NonceOverflow
5878                | InstructionResult::CreateContractSizeLimit
5879                | InstructionResult::CreateContractStartingWithEF
5880                | InstructionResult::CreateInitCodeSizeLimit
5881                | InstructionResult::InvalidImmediateEncoding
5882                | InstructionResult::FatalExternalError => Ok(Self::EvmError(exit)),
5883            },
5884        }
5885    }
5886}
5887
5888/// Appends the upstream part of a fee-history range that crosses the fork boundary.
5889fn merge_pre_fork_fee_history(
5890    response: &mut FeeHistory,
5891    rewards: &mut Vec<Vec<u128>>,
5892    pre: FeeHistory,
5893    fork_block: u64,
5894) {
5895    // Upstream may return fewer blocks than requested when its available history starts later.
5896    response.oldest_block = pre.oldest_block;
5897    let count = fork_block.checked_sub(pre.oldest_block).map_or(0, |count| count.saturating_add(1))
5898        as usize;
5899
5900    // Base-fee arrays include a trailing next-block entry. The caller computes that block locally.
5901    response.base_fee_per_gas.extend(pre.base_fee_per_gas.into_iter().take(count));
5902    response.gas_used_ratio.extend(pre.gas_used_ratio.into_iter().take(count));
5903    if let Some(reward) = pre.reward {
5904        rewards.extend(reward.into_iter().take(count));
5905    }
5906
5907    // EIP-4844 fields may be omitted for pre-Cancun blocks. Pad to the actual returned count.
5908    response.base_fee_per_blob_gas.extend(pre.base_fee_per_blob_gas.into_iter().take(count));
5909    response.base_fee_per_blob_gas.resize(count, 0);
5910    response.blob_gas_used_ratio.extend(pre.blob_gas_used_ratio.into_iter().take(count));
5911    response.blob_gas_used_ratio.resize(count, 0.0);
5912}
5913
5914fn reward_at_percentile(rewards: &[u128], percentile: f64) -> u128 {
5915    let index = (percentile * REWARD_PERCENTILE_RESOLUTION).round() as usize;
5916    rewards.get(index).copied().unwrap_or_default()
5917}
5918
5919#[cfg(test)]
5920mod tests {
5921    use super::*;
5922    use crate::{NodeConfig, spawn};
5923
5924    #[cfg(feature = "base")]
5925    #[tokio::test(flavor = "multi_thread")]
5926    async fn base_requests_are_rejected_without_execution() {
5927        let (api, _handle) = spawn(NodeConfig::test()).await;
5928        for request in [serde_json::json!({ "type": "0x79" }), serde_json::json!({ "calls": [[]] })]
5929        {
5930            let request = serde_json::from_value(request).unwrap();
5931            assert!(matches!(
5932                api.parse_transaction_request(request),
5933                Err(BlockchainError::BaseTransactionUnsupported)
5934            ));
5935        }
5936    }
5937
5938    #[tokio::test(flavor = "multi_thread")]
5939    async fn set_rpc_url_installs_context_equivalent_identity_with_new_instance() {
5940        let genesis_timestamp = 1_700_000_000u64;
5941        let (_origin_api, origin_handle) =
5942            spawn(NodeConfig::test().with_genesis_timestamp(Some(genesis_timestamp))).await;
5943        let (api, _handle) =
5944            spawn(NodeConfig::test().with_eth_rpc_url(Some(origin_handle.http_endpoint()))).await;
5945        let (target_api, target_handle) =
5946            spawn(NodeConfig::test().with_genesis_timestamp(Some(genesis_timestamp))).await;
5947        let target_url = target_handle.http_endpoint();
5948        let fork = api.backend.get_fork().unwrap();
5949        let identity_before = fork.config.read().endpoint_identity;
5950
5951        api.anvil_set_rpc_url(target_url.clone()).await.unwrap();
5952
5953        let fork = api.backend.get_fork().unwrap();
5954        let config = fork.config.read();
5955        assert!(config.endpoint_identity.context_eq(identity_before));
5956        assert_ne!(config.endpoint_identity.instance_id, identity_before.instance_id);
5957        assert_eq!(config.endpoint_identity.instance_id, Some(target_api.instance_id()));
5958        assert_eq!(config.eth_rpc_url(), Some(target_url.as_str()));
5959    }
5960
5961    #[tokio::test(flavor = "multi_thread")]
5962    async fn memory_reset_stages_live_fees_after_active_mining() {
5963        let (api, _handle) = spawn(NodeConfig::test()).await;
5964        api.backend.set_base_fee(123);
5965
5966        // Model an in-flight miner that publishes its final fee update before completing. Reset
5967        // must wait to snapshot that state until mining finishes.
5968        let mining = api.backend.lock_mining().await;
5969        let reset_api = api.clone();
5970        let reset = tokio::spawn(async move { reset_api.anvil_reset(None).await });
5971
5972        tokio::time::timeout(Duration::from_secs(5), async {
5973            while api.lifecycle_lock.try_read().is_ok() {
5974                tokio::task::yield_now().await;
5975            }
5976        })
5977        .await
5978        .unwrap();
5979
5980        api.backend.set_base_fee(456);
5981        drop(mining);
5982        tokio::time::timeout(Duration::from_secs(5), reset).await.unwrap().unwrap().unwrap();
5983
5984        assert_eq!(api.backend.evm_env().read().block_env.basefee, 456);
5985        assert_eq!(api.base_fee().unwrap(), Some(U256::from(crate::eth::fees::INITIAL_BASE_FEE)));
5986    }
5987
5988    // Regression test for <https://github.com/foundry-rs/foundry/issues/13680>.
5989    #[tokio::test(flavor = "multi_thread")]
5990    async fn fee_history_is_complete_when_cache_entries_are_missing() {
5991        let (api, _handle) = spawn(NodeConfig::test()).await;
5992        let count = 10u64;
5993        api.anvil_mine(Some(U256::from(count)), None).await.unwrap();
5994
5995        // Wait until the asynchronous service has consumed all block notifications, then clear
5996        // its cache. With no notifications left to repopulate it, this deterministically exercises
5997        // the RPC handler's fallback for canonical blocks whose cache entries are absent.
5998        tokio::time::timeout(Duration::from_secs(5), async {
5999            loop {
6000                if (1..=count).all(|number| api.fee_history_cache.lock().contains_key(&number)) {
6001                    break;
6002                }
6003                tokio::task::yield_now().await;
6004            }
6005        })
6006        .await
6007        .unwrap();
6008        api.fee_history_cache.lock().clear();
6009
6010        let fee_history =
6011            api.fee_history(U256::from(count), BlockNumber::Latest, vec![50.0]).await.unwrap();
6012
6013        assert_eq!(fee_history.oldest_block, 1);
6014        assert_eq!(fee_history.gas_used_ratio.len(), count as usize);
6015        assert_eq!(fee_history.blob_gas_used_ratio.len(), count as usize);
6016        assert_eq!(fee_history.base_fee_per_gas.len(), count as usize + 1);
6017        assert_eq!(fee_history.base_fee_per_blob_gas.len(), count as usize + 1);
6018        let rewards = fee_history.reward.unwrap();
6019        assert_eq!(rewards.len(), count as usize);
6020        assert!(rewards.iter().all(|reward| reward.len() == 1));
6021    }
6022
6023    #[tokio::test(flavor = "multi_thread")]
6024    async fn fee_history_rejects_invalid_reward_percentiles() {
6025        let (api, _handle) = spawn(NodeConfig::test()).await;
6026
6027        for percentiles in [vec![-0.5], vec![100.5], vec![50.0, 25.0], vec![50.0, 50.0]] {
6028            let err =
6029                api.fee_history(U256::ONE, BlockNumber::Latest, percentiles).await.unwrap_err();
6030            assert!(matches!(
6031                err,
6032                BlockchainError::FeeHistory(FeeHistoryError::InvalidRewardPercentiles)
6033            ));
6034        }
6035
6036        for percentiles in [vec![], vec![0.0, 100.0]] {
6037            api.fee_history(U256::ONE, BlockNumber::Latest, percentiles).await.unwrap();
6038        }
6039    }
6040
6041    #[test]
6042    fn fractional_reward_percentiles_use_cache_resolution() {
6043        let rewards = (0..=200).collect::<Vec<_>>();
6044
6045        assert_eq!(reward_at_percentile(&rewards, 0.0), 0);
6046        assert_eq!(reward_at_percentile(&rewards, 0.5), 1);
6047        assert_eq!(reward_at_percentile(&rewards, 1.0), 2);
6048        assert_eq!(reward_at_percentile(&rewards, 100.0), 200);
6049    }
6050
6051    #[test]
6052    fn shortened_pre_fork_fee_history_uses_upstream_start() {
6053        let requested_lowest = 4;
6054        let fork_block = 10;
6055        let pre = FeeHistory {
6056            oldest_block: 5,
6057            base_fee_per_gas: vec![1; 7],
6058            gas_used_ratio: vec![0.0; 6],
6059            reward: Some(vec![vec![]; 6]),
6060            base_fee_per_blob_gas: vec![],
6061            blob_gas_used_ratio: vec![],
6062        };
6063
6064        let mut response = FeeHistory { oldest_block: requested_lowest, ..Default::default() };
6065        let mut rewards = Vec::new();
6066
6067        merge_pre_fork_fee_history(&mut response, &mut rewards, pre, fork_block);
6068
6069        assert_eq!(response.oldest_block, 5);
6070        assert_eq!(response.gas_used_ratio.len(), 6);
6071        assert_eq!(response.base_fee_per_gas.len(), 6);
6072        assert_eq!(response.blob_gas_used_ratio.len(), 6);
6073        assert_eq!(response.base_fee_per_blob_gas.len(), 6);
6074        assert_eq!(rewards.len(), 6);
6075    }
6076}