Skip to main content

anvil/eth/
api.rs

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