1use super::{
2 backend::mem::{BlockRequest, DatabaseRef, State, sanitize_simulation_blocks},
3 preserve_simulation_request_fields,
4};
5use crate::{
6 ClientFork, LoggingManager, Miner, MiningMode, StorageInfo,
7 eth::{
8 backend::{
9 self,
10 db::SerializableState,
11 mem::{MIN_CREATE_GAS, MIN_TRANSACTION_GAS},
12 notifications::ChainNotifications,
13 validate::TransactionValidator,
14 },
15 error::{
16 BlockchainError, FeeHistoryError, InvalidTransactionError, Result, ToRpcResponseResult,
17 },
18 fees::{
19 FeeDetails, FeeHistoryCache, FeeHistoryCacheItem, MIN_SUGGESTED_PRIORITY_FEE,
20 create_fee_history_cache_item,
21 },
22 macros::node_info,
23 miner::FixedBlockTimeMiner,
24 pool::{
25 Pool,
26 transactions::{
27 PoolTransaction, TransactionOrder, TransactionPriority, TxMarker, to_marker,
28 },
29 },
30 sign::Signer,
31 },
32 filter::{EthFilter, Filters, LogsFilter},
33 mem::transaction_build,
34};
35use alloy_consensus::{
36 Blob, BlockHeader, Transaction, TrieAccount, TxEip4844Variant, TxReceipt,
37 transaction::Recovered,
38};
39use alloy_dyn_abi::TypedData;
40use alloy_eips::{
41 eip2718::Encodable2718,
42 eip7910::{EthConfig, EthForkConfig},
43};
44use alloy_evm::overrides::{OverrideBlockHashes, apply_state_overrides};
45use alloy_network::{
46 AnyRpcBlock, AnyRpcHeader, AnyRpcTransaction, BlockResponse, Network,
47 NetworkTransactionBuilder, ReceiptResponse, TransactionBuilder, TransactionBuilder4844,
48 TransactionResponse, eip2718::Decodable2718,
49};
50use alloy_primitives::{
51 Address, B64, B256, Bytes, TxHash, TxKind, U64, U256,
52 map::{HashMap, HashSet},
53};
54use alloy_rpc_types::{
55 AccessListResult, BlockId, BlockNumberOrTag as BlockNumber, BlockTransactions,
56 EIP1186AccountProofResponse, FeeHistory, Filter, FilteredParams, Index, Log, Work,
57 anvil::{
58 ForkedNetwork, Forking, Metadata, MineOptions, NodeEnvironment, NodeForkConfig, NodeInfo,
59 },
60 erc4337::TransactionConditional,
61 pubsub::TransactionReceiptsParams,
62 request::TransactionRequest,
63 simulate::{MAX_SIMULATE_BLOCKS, SimulatePayload, SimulatedBlock},
64 state::{AccountOverride, EvmOverrides, StateOverride, StateOverridesBuilder},
65 trace::{
66 filter::TraceFilter,
67 geth::{GethDebugTracingCallOptions, GethDebugTracingOptions, GethTrace, TraceResult},
68 opcode::{BlockOpcodeGas, TransactionOpcodeGas},
69 parity::{
70 LocalizedTransactionTrace, TraceResults, TraceResultsWithTransactionHash, TraceType,
71 },
72 },
73 txpool::{TxpoolContent, TxpoolContentFrom, TxpoolInspect, TxpoolInspectSummary, TxpoolStatus},
74};
75use alloy_rpc_types_eth::{AccountInfo, Bundle, EthCallResponse, FillTransaction, StateContext};
76use alloy_rpc_types_mev::{EthCallBundle, EthCallBundleResponse};
77use alloy_serde::WithOtherFields;
78use alloy_sol_types::{SolCall, SolValue, sol};
79use anvil_core::{
80 eth::{
81 EthRequest,
82 block::{BlockInfo, canonical_block},
83 transaction::{MaybeImpersonatedTransaction, PendingTransaction},
84 },
85 types::{ReorgOptions, TransactionData},
86};
87use anvil_rpc::{
88 error::{ErrorCode, RpcError},
89 response::ResponseResult,
90};
91use foundry_common::{
92 tempo::{PaymentLaneClassification, PaymentLaneReason, classify_payment_lane},
93 version::{COMMIT_SHA, SEMVER_VERSION},
94};
95use foundry_evm::decode::RevertDecoder;
96use foundry_primitives::{
97 FoundryNetwork, FoundryReceiptEnvelope, FoundryTransactionRequest, FoundryTxEnvelope,
98 FoundryTxReceipt, FoundryTxType, FoundryTypedTx,
99};
100use futures::{
101 StreamExt, TryFutureExt,
102 channel::{mpsc::Receiver, oneshot},
103};
104use parking_lot::RwLock;
105use revm::{
106 context::{BlockEnv, Cfg},
107 context_interface::{
108 block::BlobExcessGasAndPrice,
109 result::{HaltReason, Output},
110 },
111 database::CacheDB,
112 interpreter::{InstructionResult, SuccessOrHalt, return_ok, return_revert},
113 primitives::eip7702::PER_EMPTY_ACCOUNT_COST,
114};
115use std::{sync::Arc, time::Duration};
116use tempo_hardfork::TempoHardfork;
117use tokio::{
118 sync::mpsc::{self, UnboundedReceiver, unbounded_channel},
119 try_join,
120};
121
122pub const CLIENT_VERSION: &str = concat!("anvil/v", env!("CARGO_PKG_VERSION"));
124
125pub struct EthApi<N: Network> {
129 pool: Arc<Pool<N::TxEnvelope>>,
131 pub backend: Arc<backend::mem::Backend<N>>,
134 is_mining: bool,
136 signers: Arc<Vec<Box<dyn Signer<N>>>>,
138 fee_history_cache: FeeHistoryCache,
140 fee_history_limit: u64,
142 miner: Miner<N::TxEnvelope>,
147 logger: LoggingManager,
149 filters: Filters<N>,
151 transaction_order: Arc<RwLock<TransactionOrder>>,
153 net_listening: bool,
155 instance_id: Arc<RwLock<B256>>,
157}
158
159impl<N: Network> Clone for EthApi<N> {
160 fn clone(&self) -> Self {
161 Self {
162 pool: self.pool.clone(),
163 backend: self.backend.clone(),
164 is_mining: self.is_mining,
165 signers: self.signers.clone(),
166 fee_history_cache: self.fee_history_cache.clone(),
167 fee_history_limit: self.fee_history_limit,
168 miner: self.miner.clone(),
169 logger: self.logger.clone(),
170 filters: self.filters.clone(),
171 transaction_order: self.transaction_order.clone(),
172 net_listening: self.net_listening,
173 instance_id: self.instance_id.clone(),
174 }
175 }
176}
177
178impl<N: Network> EthApi<N> {
181 #[expect(clippy::too_many_arguments)]
183 pub fn new(
184 pool: Arc<Pool<N::TxEnvelope>>,
185 backend: Arc<backend::mem::Backend<N>>,
186 signers: Arc<Vec<Box<dyn Signer<N>>>>,
187 fee_history_cache: FeeHistoryCache,
188 fee_history_limit: u64,
189 miner: Miner<N::TxEnvelope>,
190 logger: LoggingManager,
191 filters: Filters<N>,
192 transactions_order: TransactionOrder,
193 ) -> Self {
194 Self {
195 pool,
196 backend,
197 is_mining: true,
198 signers,
199 fee_history_cache,
200 fee_history_limit,
201 miner,
202 logger,
203 filters,
204 net_listening: true,
205 transaction_order: Arc::new(RwLock::new(transactions_order)),
206 instance_id: Arc::new(RwLock::new(B256::random())),
207 }
208 }
209
210 pub fn gas_price(&self) -> u128 {
212 if self.backend.is_eip1559() {
213 if self.backend.is_min_priority_fee_enforced() {
214 (self.backend.base_fee() as u128).saturating_add(self.lowest_suggestion_tip())
215 } else {
216 self.backend.base_fee() as u128
217 }
218 } else {
219 self.backend.fees().raw_gas_price()
220 }
221 }
222
223 fn lowest_suggestion_tip(&self) -> u128 {
227 let block_number = self.backend.best_number();
228 let cache = self.fee_history_cache.lock();
229 let latest_tip = self
230 .backend
231 .get_block_with_hash(block_number)
232 .and_then(|(_, hash)| cache.get(&block_number).filter(|item| item.block_hash == hash))
233 .and_then(|item| item.rewards.iter().copied().min());
234
235 latest_tip
236 .or_else(|| {
237 cache
238 .iter()
239 .filter(|(number, item)| {
240 self.backend
241 .get_block_with_hash(**number)
242 .is_some_and(|(_, hash)| item.block_hash == hash)
243 })
244 .flat_map(|(_, item)| item.rewards.iter().copied())
245 .min()
246 })
247 .map(|fee| fee.max(MIN_SUGGESTED_PRIORITY_FEE))
248 .unwrap_or(MIN_SUGGESTED_PRIORITY_FEE)
249 }
250
251 pub fn anvil_get_auto_mine(&self) -> Result<bool> {
255 node_info!("anvil_getAutomine");
256 Ok(self.miner.is_auto_mine())
257 }
258
259 pub fn anvil_get_interval_mining(&self) -> Result<Option<u64>> {
263 node_info!("anvil_getIntervalMining");
264 Ok(self.miner.get_interval())
265 }
266
267 pub async fn anvil_set_auto_mine(&self, enable_automine: bool) -> Result<()> {
272 node_info!("evm_setAutomine");
273 if self.miner.is_auto_mine() {
274 if enable_automine {
275 return Ok(());
276 }
277 self.miner.set_mining_mode(MiningMode::None);
278 } else if enable_automine {
279 let listener = self.pool.add_ready_listener();
280 let mode = MiningMode::instant(1_000, listener);
281 self.miner.set_mining_mode(mode);
282 }
283 Ok(())
284 }
285
286 pub fn anvil_set_interval_mining(&self, secs: u64) -> Result<()> {
290 node_info!("evm_setIntervalMining");
291 let mining_mode = if secs == 0 {
292 MiningMode::None
293 } else {
294 let block_time = Duration::from_secs(secs);
295
296 self.backend.update_interval_mine_block_time(block_time);
298
299 MiningMode::FixedBlockTime(FixedBlockTimeMiner::new(block_time))
300 };
301 self.miner.set_mining_mode(mining_mode);
302 Ok(())
303 }
304
305 pub async fn anvil_drop_transaction(&self, tx_hash: B256) -> Result<Option<B256>> {
309 node_info!("anvil_dropTransaction");
310 Ok(self.pool.drop_transaction(tx_hash).map(|tx| tx.hash()))
311 }
312
313 pub async fn anvil_drop_all_transactions(&self) -> Result<()> {
317 node_info!("anvil_dropAllTransactions");
318 self.pool.clear();
319 Ok(())
320 }
321
322 pub async fn debug_clear_txpool(&self) -> Result<()> {
326 node_info!("debug_clearTxpool");
327 self.pool.clear();
328 Ok(())
329 }
330
331 pub async fn anvil_set_chain_id(&self, chain_id: u64) -> Result<()> {
332 node_info!("anvil_setChainId");
333 self.backend.set_chain_id(chain_id);
334 Ok(())
335 }
336
337 pub async fn anvil_set_balance(&self, address: Address, balance: U256) -> Result<()> {
341 node_info!("anvil_setBalance");
342 self.backend.set_balance(address, balance).await?;
343 Ok(())
344 }
345
346 pub async fn anvil_set_code(&self, address: Address, code: Bytes) -> Result<()> {
350 node_info!("anvil_setCode");
351 self.backend.set_code(address, code).await?;
352 Ok(())
353 }
354
355 pub async fn anvil_set_nonce(&self, address: Address, nonce: U256) -> Result<()> {
359 node_info!("anvil_setNonce");
360 self.backend.set_nonce(address, nonce).await?;
361 Ok(())
362 }
363
364 pub async fn anvil_set_storage_at(
368 &self,
369 address: Address,
370 slot: U256,
371 val: B256,
372 ) -> Result<bool> {
373 node_info!("anvil_setStorageAt");
374 self.backend.set_storage_at(address, slot, val).await?;
375 Ok(true)
376 }
377
378 pub async fn anvil_set_logging(&self, enable: bool) -> Result<()> {
382 node_info!("anvil_setLoggingEnabled");
383 self.logger.set_enabled(enable);
384 Ok(())
385 }
386
387 pub async fn anvil_set_min_gas_price(&self, gas: U256) -> Result<()> {
391 node_info!("anvil_setMinGasPrice");
392 if self.backend.is_eip1559() {
393 return Err(RpcError::invalid_params(
394 "anvil_setMinGasPrice is not supported when EIP-1559 is active",
395 )
396 .into());
397 }
398 self.backend.set_gas_price(gas.saturating_to());
399 Ok(())
400 }
401
402 pub async fn anvil_set_next_block_base_fee_per_gas(&self, basefee: U256) -> Result<()> {
406 node_info!("anvil_setNextBlockBaseFeePerGas");
407 if !self.backend.is_eip1559() {
408 return Err(RpcError::invalid_params(
409 "anvil_setNextBlockBaseFeePerGas is only supported when EIP-1559 is active",
410 )
411 .into());
412 }
413 self.backend.set_base_fee(basefee.saturating_to());
414 Ok(())
415 }
416
417 pub async fn anvil_set_coinbase(&self, address: Address) -> Result<()> {
421 node_info!("anvil_setCoinbase");
422 self.backend.set_coinbase(address);
423 Ok(())
424 }
425
426 pub async fn anvil_set_next_block_prevrandao(&self, prevrandao: B256) -> Result<()> {
433 node_info!("anvil_setNextBlockPrevRandao");
434 self.backend.set_next_block_prevrandao(prevrandao);
435 Ok(())
436 }
437
438 pub async fn anvil_node_info(&self) -> Result<NodeInfo> {
442 node_info!("anvil_nodeInfo");
443
444 let evm_env = self.backend.evm_env().read();
445 let fork_config = self.backend.get_fork();
446 let tx_order = self.transaction_order.read();
447 let hard_fork = self.backend.hardfork().name();
448
449 Ok(NodeInfo {
450 current_block_number: self.backend.best_number(),
451 current_block_timestamp: evm_env.block_env.timestamp.saturating_to(),
452 current_block_hash: self.backend.best_hash(),
453 hard_fork,
454 transaction_order: match *tx_order {
455 TransactionOrder::Fifo => "fifo".to_string(),
456 TransactionOrder::Fees => "fees".to_string(),
457 },
458 environment: NodeEnvironment {
459 base_fee: self.backend.base_fee() as u128,
460 chain_id: self.backend.chain_id().to::<u64>(),
461 gas_limit: self.backend.gas_limit(),
462 gas_price: self.gas_price(),
463 },
464 fork_config: fork_config
465 .map(|fork| {
466 let config = fork.config.read();
467
468 NodeForkConfig {
469 fork_url: config.eth_rpc_url().map(|s| s.to_string()),
470 fork_block_number: Some(config.block_number),
471 fork_retry_backoff: Some(config.backoff.as_millis()),
472 }
473 })
474 .unwrap_or_default(),
475 network: self.backend.is_tempo().then(|| "tempo".to_string()),
476 })
477 }
478
479 pub async fn anvil_metadata(&self) -> Result<Metadata> {
483 node_info!("anvil_metadata");
484 let fork_config = self.backend.get_fork();
485
486 Ok(Metadata {
487 client_version: CLIENT_VERSION.to_string(),
488 client_semver: Some(SEMVER_VERSION.to_string()),
489 client_commit_sha: Some(COMMIT_SHA.to_string()),
490 chain_id: self.backend.chain_id().to::<u64>(),
491 latest_block_hash: self.backend.best_hash(),
492 latest_block_number: self.backend.best_number(),
493 instance_id: *self.instance_id.read(),
494 forked_network: fork_config.map(|cfg| ForkedNetwork {
495 chain_id: cfg.chain_id(),
496 fork_block_number: cfg.block_number(),
497 fork_block_hash: cfg.block_hash(),
498 }),
499 snapshots: self.backend.list_state_snapshots(),
500 })
501 }
502
503 pub async fn anvil_remove_pool_transactions(&self, address: Address) -> Result<()> {
504 node_info!("anvil_removePoolTransactions");
505 self.pool.remove_transactions_by_address(address);
506 Ok(())
507 }
508
509 pub async fn evm_snapshot(&self) -> Result<U256> {
513 node_info!("evm_snapshot");
514 Ok(self.backend.create_state_snapshot().await)
515 }
516
517 pub async fn evm_increase_time(&self, seconds: U256) -> Result<i64> {
521 node_info!("evm_increaseTime");
522 Ok(self.backend.time().increase_time(seconds.try_into().unwrap_or(u64::MAX)) as i64)
523 }
524
525 pub fn evm_set_next_block_timestamp(&self, seconds: u64) -> Result<()> {
529 node_info!("evm_setNextBlockTimestamp");
530 self.backend.time().set_next_block_timestamp(seconds)
531 }
532
533 pub fn evm_set_time(&self, timestamp: u64) -> Result<u64> {
542 node_info!("evm_setTime");
543 let now = self.backend.time().current_call_timestamp();
544 self.backend.time().reset(timestamp);
545
546 let offset = timestamp.saturating_sub(now);
548 Ok(offset)
549 }
550
551 pub fn evm_set_block_gas_limit(&self, gas_limit: U256) -> Result<bool> {
555 node_info!("evm_setBlockGasLimit");
556 self.backend.set_gas_limit(gas_limit.saturating_to());
557 Ok(true)
558 }
559
560 pub fn evm_set_block_timestamp_interval(&self, seconds: u64) -> Result<()> {
564 node_info!("anvil_setBlockTimestampInterval");
565 self.backend.time().set_block_timestamp_interval(seconds);
566 Ok(())
567 }
568
569 pub fn evm_remove_block_timestamp_interval(&self) -> Result<bool> {
573 node_info!("anvil_removeBlockTimestampInterval");
574 Ok(self.backend.time().remove_block_timestamp_interval())
575 }
576
577 pub async fn anvil_set_rpc_url(&self, url: String) -> Result<()> {
581 node_info!("anvil_setRpcUrl");
582 if let Some(fork) = self.backend.get_fork() {
583 let urls = vec![url.clone()];
584 let config = fork.config.read().clone();
585 let (new_provider, _) = config.validated_provider_for_urls(&urls).await?;
586
587 let mut config = fork.config.write();
588 config.provider = new_provider;
589 trace!(target: "backend", "Updated fork rpc from \"{}\" to \"{}\"", config.eth_rpc_url().unwrap_or("none"), url);
590 config.fork_urls = urls;
591 }
592 let mut node_config = self.backend.node_config.write().await;
594 node_config.fork_urls = vec![url];
595 node_config.fork_chain_id = None;
596 Ok(())
597 }
598
599 pub async fn txpool_status(&self) -> Result<TxpoolStatus> {
605 node_info!("txpool_status");
606 Ok(self.pool.txpool_status())
607 }
608
609 async fn on_blocking_task<C, F, R>(&self, c: C) -> Result<R>
611 where
612 C: FnOnce(Self) -> F,
613 F: Future<Output = Result<R>> + Send + 'static,
614 R: Send + 'static,
615 {
616 let (tx, rx) = oneshot::channel();
617 let this = self.clone();
618 let f = c(this);
619 tokio::task::spawn_blocking(move || {
620 tokio::runtime::Handle::current().block_on(async move {
621 let res = f.await;
622 let _ = tx.send(res);
623 })
624 });
625 rx.await.map_err(|_| BlockchainError::Internal("blocking task panicked".to_string()))?
626 }
627
628 pub fn set_transaction_order(&self, order: TransactionOrder) {
630 *self.transaction_order.write() = order;
631 }
632
633 pub fn chain_id(&self) -> u64 {
635 self.backend.chain_id().to::<u64>()
636 }
637
638 pub fn get_fork(&self) -> Option<ClientFork> {
640 self.backend.get_fork()
641 }
642
643 pub fn instance_id(&self) -> B256 {
645 *self.instance_id.read()
646 }
647
648 pub fn reset_instance_id(&self) {
650 *self.instance_id.write() = B256::random();
651 }
652
653 #[expect(clippy::borrowed_box)]
655 pub fn get_signer(&self, address: Address) -> Option<&Box<dyn Signer<N>>> {
656 self.signers.iter().find(|signer| signer.is_signer_for(address))
657 }
658
659 pub fn new_ready_transactions(&self) -> Receiver<TxHash> {
661 self.pool.add_ready_listener()
662 }
663
664 pub fn is_fork(&self) -> bool {
666 self.backend.is_fork()
667 }
668
669 pub async fn state_root(&self) -> Option<B256> {
671 self.backend.get_db().read().await.maybe_state_root()
672 }
673
674 pub fn is_impersonated(&self, addr: Address) -> bool {
676 self.backend.cheats().is_impersonated(addr)
677 }
678
679 pub fn storage_info(&self) -> StorageInfo<N> {
681 StorageInfo::new(Arc::clone(&self.backend))
682 }
683
684 #[allow(clippy::large_stack_frames)]
686 pub fn anvil_get_blob_by_versioned_hash(
687 &self,
688 hash: B256,
689 ) -> Result<Option<alloy_consensus::Blob>> {
690 node_info!("anvil_getBlobByHash");
691 Ok(self.backend.get_blob_by_versioned_hash(hash)?)
692 }
693
694 pub fn anvil_get_blobs_by_block_id(
696 &self,
697 block_id: impl Into<BlockId>,
698 versioned_hashes: Vec<B256>,
699 ) -> Result<Option<Vec<Blob>>> {
700 node_info!("anvil_getBlobsByBlockId");
701 Ok(self.backend.get_blobs_by_block_id(block_id, versioned_hashes)?)
702 }
703
704 pub fn anvil_get_genesis_time(&self) -> Result<u64> {
708 node_info!("anvil_getGenesisTime");
709 Ok(self.backend.genesis_time())
710 }
711
712 pub async fn anvil_reset(&self, forking: Option<Forking>) -> Result<()> {
718 node_info!("anvil_reset");
719 if let Some(forking) = forking {
720 self.backend.reset_fork(forking).await?;
721 } else {
722 self.backend.reset_to_in_mem().await?;
724 }
725 self.reset_instance_id();
726 self.pool.clear();
728 Ok(())
729 }
730
731 pub async fn evm_revert(&self, id: U256) -> Result<bool> {
736 node_info!("evm_revert");
737 self.backend.revert_state_snapshot(id).await
738 }
739
740 pub async fn anvil_impersonate_account(&self, address: Address) -> Result<()> {
744 node_info!("anvil_impersonateAccount");
745 self.backend.impersonate(address);
746 Ok(())
747 }
748
749 pub async fn anvil_stop_impersonating_account(&self, address: Address) -> Result<()> {
753 node_info!("anvil_stopImpersonatingAccount");
754 self.backend.stop_impersonating(address);
755 Ok(())
756 }
757
758 pub async fn anvil_auto_impersonate_account(&self, enabled: bool) -> Result<()> {
762 node_info!("anvil_autoImpersonateAccount");
763 self.backend.auto_impersonate_account(enabled);
764 Ok(())
765 }
766
767 pub async fn anvil_impersonate_signature(
769 &self,
770 signature: Bytes,
771 address: Address,
772 ) -> Result<()> {
773 node_info!("anvil_impersonateSignature");
774 self.backend.impersonate_signature(signature, address).await
775 }
776
777 pub fn new_block_notifications(&self) -> ChainNotifications {
780 self.backend.new_block_notifications()
781 }
782
783 pub fn client_version(&self) -> Result<String> {
787 node_info!("web3_clientVersion");
788 Ok(CLIENT_VERSION.to_string())
789 }
790
791 pub fn sha3(&self, bytes: Bytes) -> Result<String> {
795 node_info!("web3_sha3");
796 let hash = alloy_primitives::keccak256(bytes.as_ref());
797 Ok(alloy_primitives::hex::encode_prefixed(&hash[..]))
798 }
799
800 pub fn protocol_version(&self) -> Result<u64> {
804 node_info!("eth_protocolVersion");
805 Ok(1)
806 }
807
808 pub fn hashrate(&self) -> Result<U256> {
812 node_info!("eth_hashrate");
813 Ok(U256::ZERO)
814 }
815
816 pub fn author(&self) -> Result<Address> {
820 node_info!("eth_coinbase");
821 Ok(self.backend.coinbase())
822 }
823
824 pub fn is_mining(&self) -> Result<bool> {
828 node_info!("eth_mining");
829 Ok(self.is_mining)
830 }
831
832 pub fn eth_chain_id(&self) -> Result<Option<U64>> {
838 node_info!("eth_chainId");
839 Ok(Some(self.backend.chain_id().to::<U64>()))
840 }
841
842 pub fn network_id(&self) -> Result<Option<String>> {
846 node_info!("eth_networkId");
847 let chain_id = self.backend.chain_id().to::<u64>();
848 Ok(Some(format!("{chain_id}")))
849 }
850
851 pub fn net_listening(&self) -> Result<bool> {
855 node_info!("net_listening");
856 Ok(self.net_listening)
857 }
858
859 fn eth_gas_price(&self) -> Result<U256> {
861 node_info!("eth_gasPrice");
862 Ok(U256::from(self.gas_price()))
863 }
864
865 pub fn base_fee(&self) -> Result<Option<U256>> {
869 node_info!("eth_baseFee");
870 Ok(self.backend.is_eip1559().then(|| U256::from(self.backend.base_fee())))
871 }
872
873 pub fn excess_blob_gas_and_price(&self) -> Result<Option<BlobExcessGasAndPrice>> {
875 Ok(self.backend.excess_blob_gas_and_price())
876 }
877
878 pub fn gas_max_priority_fee_per_gas(&self) -> Result<U256> {
883 self.max_priority_fee_per_gas()
884 }
885
886 pub fn blob_base_fee(&self) -> Result<U256> {
890 Ok(U256::from(self.backend.fees().base_fee_per_blob_gas()))
891 }
892
893 pub fn gas_limit(&self) -> U256 {
895 U256::from(self.backend.gas_limit())
896 }
897
898 pub fn accounts(&self) -> Result<Vec<Address>> {
902 node_info!("eth_accounts");
903 let mut unique = HashSet::new();
904 let mut accounts: Vec<Address> = Vec::new();
905 for signer in self.signers.iter() {
906 accounts.extend(signer.accounts().into_iter().filter(|acc| unique.insert(*acc)));
907 }
908 accounts.extend(
909 self.backend
910 .cheats()
911 .impersonated_accounts()
912 .into_iter()
913 .filter(|acc| unique.insert(*acc)),
914 );
915 Ok(accounts.into_iter().collect())
916 }
917
918 pub fn block_number(&self) -> Result<U256> {
922 node_info!("eth_blockNumber");
923 Ok(U256::from(self.backend.best_number()))
924 }
925
926 pub async fn block_by_hash(&self, hash: B256) -> Result<Option<AnyRpcBlock>> {
930 node_info!("eth_getBlockByHash");
931 self.backend.block_by_hash(hash).await
932 }
933
934 pub async fn header_by_hash(
938 &self,
939 hash: B256,
940 ) -> Result<Option<WithOtherFields<AnyRpcHeader>>> {
941 node_info!("eth_getHeaderByHash");
942 Ok(self.backend.block_by_hash(hash).await?.map(|block| {
943 let WithOtherFields { inner: block, other } = block.0;
944 WithOtherFields { inner: block.header, other }
945 }))
946 }
947
948 pub async fn block_by_hash_full(&self, hash: B256) -> Result<Option<AnyRpcBlock>> {
952 node_info!("eth_getBlockByHash");
953 self.backend.block_by_hash_full(hash).await
954 }
955
956 pub async fn block_transaction_count_by_hash(&self, hash: B256) -> Result<Option<U256>> {
960 node_info!("eth_getBlockTransactionCountByHash");
961 let block = self.backend.block_by_hash(hash).await?;
962 let txs = block.map(|b| match b.transactions() {
963 BlockTransactions::Full(txs) => U256::from(txs.len()),
964 BlockTransactions::Hashes(txs) => U256::from(txs.len()),
965 BlockTransactions::Uncle => U256::from(0),
966 });
967 Ok(txs)
968 }
969
970 pub async fn block_uncles_count_by_hash(&self, hash: B256) -> Result<U256> {
974 node_info!("eth_getUncleCountByBlockHash");
975 let block =
976 self.backend.block_by_hash(hash).await?.ok_or(BlockchainError::BlockNotFound)?;
977 Ok(U256::from(block.uncles.len()))
978 }
979
980 pub async fn block_uncles_count_by_number(&self, block_number: BlockNumber) -> Result<U256> {
984 node_info!("eth_getUncleCountByBlockNumber");
985 let block = self
986 .backend
987 .block_by_number(block_number)
988 .await?
989 .ok_or(BlockchainError::BlockNotFound)?;
990 Ok(U256::from(block.uncles.len()))
991 }
992
993 pub async fn sign_typed_data(
997 &self,
998 _address: Address,
999 _data: serde_json::Value,
1000 ) -> Result<String> {
1001 node_info!("eth_signTypedData");
1002 Err(BlockchainError::RpcUnimplemented)
1003 }
1004
1005 pub async fn sign_typed_data_v3(
1009 &self,
1010 _address: Address,
1011 _data: serde_json::Value,
1012 ) -> Result<String> {
1013 node_info!("eth_signTypedData_v3");
1014 Err(BlockchainError::RpcUnimplemented)
1015 }
1016
1017 pub async fn sign_typed_data_v4(&self, address: Address, data: &TypedData) -> Result<String> {
1021 node_info!("eth_signTypedData_v4");
1022 let signer = self.get_signer(address).ok_or(BlockchainError::NoSignerAvailable)?;
1023 let signature = signer.sign_typed_data(address, data).await?;
1024 let signature = alloy_primitives::hex::encode(signature.as_bytes());
1025 Ok(format!("0x{signature}"))
1026 }
1027
1028 pub async fn sign(&self, address: Address, content: impl AsRef<[u8]>) -> Result<String> {
1032 node_info!("eth_sign");
1033 let signer = self.get_signer(address).ok_or(BlockchainError::NoSignerAvailable)?;
1034 let signature =
1035 alloy_primitives::hex::encode(signer.sign(address, content.as_ref()).await?.as_bytes());
1036 Ok(format!("0x{signature}"))
1037 }
1038
1039 pub async fn transaction_by_block_hash_and_index(
1043 &self,
1044 hash: B256,
1045 index: Index,
1046 ) -> Result<Option<AnyRpcTransaction>> {
1047 node_info!("eth_getTransactionByBlockHashAndIndex");
1048 self.backend.transaction_by_block_hash_and_index(hash, index).await
1049 }
1050
1051 pub async fn transaction_by_block_number_and_index(
1055 &self,
1056 block: BlockNumber,
1057 idx: Index,
1058 ) -> Result<Option<AnyRpcTransaction>> {
1059 node_info!("eth_getTransactionByBlockNumberAndIndex");
1060 self.backend.transaction_by_block_number_and_index(block, idx).await
1061 }
1062
1063 pub async fn uncle_by_block_hash_and_index(
1067 &self,
1068 block_hash: B256,
1069 idx: Index,
1070 ) -> Result<Option<AnyRpcBlock>> {
1071 node_info!("eth_getUncleByBlockHashAndIndex");
1072 let number =
1073 self.backend.ensure_block_number(Some(BlockId::Hash(block_hash.into()))).await?;
1074 if let Some(fork) = self.get_fork()
1075 && fork.predates_fork_inclusive(number)
1076 {
1077 return Ok(fork.uncle_by_block_hash_and_index(block_hash, idx.into()).await?);
1078 }
1079 Ok(None)
1081 }
1082
1083 pub async fn uncle_by_block_number_and_index(
1087 &self,
1088 block_number: BlockNumber,
1089 idx: Index,
1090 ) -> Result<Option<AnyRpcBlock>> {
1091 node_info!("eth_getUncleByBlockNumberAndIndex");
1092 let number = self.backend.ensure_block_number(Some(BlockId::Number(block_number))).await?;
1093 if let Some(fork) = self.get_fork()
1094 && fork.predates_fork_inclusive(number)
1095 {
1096 return Ok(fork.uncle_by_block_number_and_index(number, idx.into()).await?);
1097 }
1098 Ok(None)
1100 }
1101
1102 pub fn work(&self) -> Result<Work> {
1106 node_info!("eth_getWork");
1107 Err(BlockchainError::RpcUnimplemented)
1108 }
1109
1110 pub fn syncing(&self) -> Result<bool> {
1114 node_info!("eth_syncing");
1115 Ok(false)
1116 }
1117
1118 pub fn config(&self) -> Result<EthConfig> {
1129 node_info!("eth_config");
1130 Ok(EthConfig {
1131 current: EthForkConfig {
1132 activation_time: 0,
1133 blob_schedule: self.backend.blob_params(),
1134 chain_id: self.backend.chain_id().to::<u64>(),
1135 fork_id: Bytes::from_static(&[0; 4]),
1136 precompiles: self.backend.precompiles(),
1137 system_contracts: self.backend.system_contracts(),
1138 },
1139 next: None,
1140 last: None,
1141 })
1142 }
1143
1144 pub fn submit_work(&self, _: B64, _: B256, _: B256) -> Result<bool> {
1148 node_info!("eth_submitWork");
1149 Err(BlockchainError::RpcUnimplemented)
1150 }
1151
1152 pub fn submit_hashrate(&self, _: U256, _: B256) -> Result<bool> {
1156 node_info!("eth_submitHashrate");
1157 Err(BlockchainError::RpcUnimplemented)
1158 }
1159
1160 pub async fn fee_history(
1164 &self,
1165 block_count: U256,
1166 newest_block: BlockNumber,
1167 reward_percentiles: Vec<f64>,
1168 ) -> Result<FeeHistory>
1169 where
1170 N::ReceiptEnvelope: TxReceipt<Log = alloy_primitives::Log>,
1171 {
1172 node_info!("eth_feeHistory");
1173 let number = self.backend.convert_block_number(Some(newest_block));
1176
1177 let fork = self.get_fork();
1182 let fork_block = fork.as_ref().map(|fork| fork.block_number());
1183
1184 if let (Some(fork), Some(fork_block)) = (fork.as_ref(), fork_block) {
1186 if number <= fork_block {
1189 return fork
1190 .fee_history(block_count.to(), BlockNumber::Number(number), &reward_percentiles)
1191 .await
1192 .map_err(BlockchainError::AlloyForkProvider);
1193 }
1194 }
1195
1196 const MAX_BLOCK_COUNT: u64 = 1024u64;
1197 let block_count = block_count.saturating_to::<u64>().min(MAX_BLOCK_COUNT);
1198
1199 let highest = number;
1201 let lowest = highest.saturating_sub(block_count.saturating_sub(1));
1202
1203 if lowest < self.backend.best_number().saturating_sub(self.fee_history_limit) {
1205 return Err(FeeHistoryError::InvalidBlockRange.into());
1206 }
1207
1208 let mut response = FeeHistory {
1209 oldest_block: lowest,
1210 base_fee_per_gas: Vec::new(),
1211 gas_used_ratio: Vec::new(),
1212 reward: Some(Default::default()),
1213 base_fee_per_blob_gas: Default::default(),
1214 blob_gas_used_ratio: Default::default(),
1215 };
1216 let mut rewards = Vec::new();
1217
1218 let local_lowest = if let (Some(fork), Some(fork_block)) = (fork.as_ref(), fork_block) {
1225 if lowest <= fork_block {
1226 let count_pre = fork_block - lowest + 1;
1227 let pre = fork
1228 .fee_history(count_pre, BlockNumber::Number(fork_block), &reward_percentiles)
1229 .await
1230 .map_err(BlockchainError::AlloyForkProvider)?;
1231 merge_pre_fork_fee_history(&mut response, &mut rewards, pre, fork_block);
1232 fork_block + 1
1234 } else {
1235 lowest
1236 }
1237 } else {
1238 lowest
1239 };
1240
1241 {
1242 let storage_info = self.storage_info();
1243 let blob_params = self.backend.blob_params();
1244
1245 let cached: Vec<Option<FeeHistoryCacheItem>> = {
1249 let cache = self.fee_history_cache.lock();
1250 (local_lowest..=highest).map(|n| cache.get(&n).cloned()).collect()
1251 };
1252
1253 let mut warmed: Vec<(u64, FeeHistoryCacheItem)> = Vec::new();
1259 let mut items: Vec<FeeHistoryCacheItem> = Vec::with_capacity(cached.len());
1260 for (cached_item, n) in cached.into_iter().zip(local_lowest..=highest) {
1261 let hash = self
1262 .backend
1263 .block_hash_by_number(n)
1264 .ok_or(FeeHistoryError::BlockNotFound(BlockNumber::Number(n)))?;
1265 let item = match cached_item {
1266 Some(item) if item.block_hash == hash => item,
1267 _ => {
1268 let block = self
1269 .backend
1270 .get_block_by_hash(hash)
1271 .ok_or(FeeHistoryError::BlockNotFound(BlockNumber::Number(n)))?;
1272 let header = block.header;
1273 let (item, block_number) = create_fee_history_cache_item(
1274 hash,
1275 &header,
1276 &storage_info,
1277 blob_params,
1278 );
1279 let block_number = block_number
1283 .ok_or(FeeHistoryError::BlockNotFound(BlockNumber::Number(n)))?;
1284 warmed.push((block_number, item.clone()));
1285 item
1286 }
1287 };
1288 items.push(item);
1289 }
1290
1291 if !warmed.is_empty() {
1294 let mut cache = self.fee_history_cache.lock();
1295 for (block_number, item) in warmed {
1296 cache.insert(block_number, item);
1297 }
1298 while cache.len() as u64 > self.fee_history_limit {
1299 cache.pop_first();
1300 }
1301 }
1302
1303 for item in items {
1304 response.base_fee_per_gas.push(item.base_fee);
1305 response.base_fee_per_blob_gas.push(item.base_fee_per_blob_gas.unwrap_or(0));
1306 response.blob_gas_used_ratio.push(item.blob_gas_used_ratio);
1307 response.gas_used_ratio.push(item.gas_used_ratio);
1308
1309 if !reward_percentiles.is_empty() {
1311 let mut block_rewards = Vec::new();
1312 let resolution_per_percentile: f64 = 2.0;
1313 for p in &reward_percentiles {
1314 let p = p.clamp(0.0, 100.0);
1315 let index = ((p.round() / 2f64) * 2f64) * resolution_per_percentile;
1316 let reward = item.rewards.get(index as usize).map_or(0, |r| *r);
1317 block_rewards.push(reward);
1318 }
1319 rewards.push(block_rewards);
1320 }
1321 }
1322 }
1323
1324 response.reward = Some(rewards);
1325
1326 let next_number = highest
1331 .checked_add(1)
1332 .ok_or(FeeHistoryError::BlockNotFound(BlockNumber::Number(highest)))?;
1333 let (next_base_fee, next_blob_base_fee) = self
1334 .backend
1335 .fee_history_next_fees(highest)
1336 .await
1337 .ok_or(FeeHistoryError::BlockNotFound(BlockNumber::Number(next_number)))?;
1338 response.base_fee_per_gas.push(next_base_fee);
1339 response.base_fee_per_blob_gas.push(next_blob_base_fee);
1340
1341 Ok(response)
1342 }
1343
1344 pub fn max_priority_fee_per_gas(&self) -> Result<U256> {
1351 node_info!("eth_maxPriorityFeePerGas");
1352 Ok(U256::from(self.lowest_suggestion_tip()))
1353 }
1354
1355 pub async fn debug_code_by_hash(
1359 &self,
1360 hash: B256,
1361 block_id: Option<BlockId>,
1362 ) -> Result<Option<Bytes>> {
1363 node_info!("debug_codeByHash");
1364 self.backend.debug_code_by_hash(hash, block_id).await
1365 }
1366
1367 pub async fn debug_db_get(&self, key: String) -> Result<Option<Bytes>> {
1372 node_info!("debug_dbGet");
1373 self.backend.debug_db_get(key).await
1374 }
1375
1376 pub fn debug_get_modified_accounts_by_number(
1378 &self,
1379 _start_number: u64,
1380 _end_number: u64,
1381 ) -> Result<()> {
1382 node_info!("debug_getModifiedAccountsByNumber");
1383 Ok(())
1384 }
1385
1386 pub fn debug_free_os_memory(&self) -> Result<()> {
1388 node_info!("debug_freeOSMemory");
1389 Ok(())
1390 }
1391
1392 pub async fn trace_call(
1396 &self,
1397 request: WithOtherFields<TransactionRequest>,
1398 mut trace_types: HashSet<TraceType>,
1399 block_id: Option<BlockId>,
1400 ) -> Result<TraceResults>
1401 where
1402 N: Network<TxEnvelope = FoundryTxEnvelope, ReceiptEnvelope = FoundryReceiptEnvelope>,
1403 {
1404 node_info!("trace_call");
1405 if trace_types.is_empty() {
1406 trace_types.insert(TraceType::Trace);
1407 }
1408
1409 let block_id = block_id.unwrap_or_default();
1410 let block_request = match &block_id {
1411 BlockId::Number(BlockNumber::Pending) => {
1412 let pending_txs = self.pool.ready_transactions().collect();
1413 BlockRequest::Pending(pending_txs)
1414 }
1415 _ => {
1416 let number = self.backend.ensure_block_number(Some(block_id)).await?;
1417 BlockRequest::Number(number)
1418 }
1419 };
1420 let inner = request.as_ref();
1421 let fees = FeeDetails::new(
1422 inner.gas_price,
1423 inner.max_fee_per_gas,
1424 inner.max_priority_fee_per_gas,
1425 inner.max_fee_per_blob_gas,
1426 )?
1427 .or_zero_fees();
1428
1429 self.backend.trace_call(request, fees, trace_types, block_request, block_id).await
1430 }
1431
1432 pub async fn trace_transaction(&self, tx_hash: B256) -> Result<Vec<LocalizedTransactionTrace>> {
1436 node_info!("trace_transaction");
1437 self.backend.trace_transaction(tx_hash).await
1438 }
1439
1440 pub async fn trace_block(&self, block: BlockNumber) -> Result<Vec<LocalizedTransactionTrace>> {
1444 node_info!("trace_block");
1445 self.backend.trace_block(block).await
1446 }
1447
1448 pub async fn trace_filter(
1452 &self,
1453 filter: TraceFilter,
1454 ) -> Result<Vec<LocalizedTransactionTrace>> {
1455 node_info!("trace_filter");
1456 self.backend.trace_filter(filter).await
1457 }
1458
1459 pub async fn trace_get(
1463 &self,
1464 hash: B256,
1465 indices: Vec<Index>,
1466 ) -> Result<Option<LocalizedTransactionTrace>> {
1467 node_info!("trace_get");
1468 self.backend.trace_get(hash, indices).await
1469 }
1470
1471 pub async fn trace_replay_block_transactions(
1475 &self,
1476 block: BlockNumber,
1477 trace_types: HashSet<TraceType>,
1478 ) -> Result<Vec<TraceResultsWithTransactionHash>> {
1479 node_info!("trace_replayBlockTransactions");
1480 self.backend.trace_replay_block_transactions(block, trace_types).await
1481 }
1482
1483 pub async fn trace_replay_transaction(
1487 &self,
1488 transaction: B256,
1489 trace_types: HashSet<TraceType>,
1490 ) -> Result<TraceResults> {
1491 node_info!("trace_replayTransaction");
1492 self.backend.trace_replay_transaction(transaction, trace_types).await
1493 }
1494}
1495
1496impl<N: Network<ReceiptEnvelope = FoundryReceiptEnvelope>> EthApi<N> {
1497 pub async fn serialized_state(
1499 &self,
1500 preserve_historical_states: bool,
1501 ) -> Result<SerializableState> {
1502 self.backend.serialized_state(preserve_historical_states).await
1503 }
1504}
1505
1506impl EthApi<FoundryNetwork> {
1509 pub async fn anvil_dump_state(
1514 &self,
1515 preserve_historical_states: Option<bool>,
1516 ) -> Result<Bytes> {
1517 node_info!("anvil_dumpState");
1518 self.backend.dump_state(preserve_historical_states.unwrap_or(false)).await
1519 }
1520
1521 pub async fn anvil_load_state(&self, buf: Bytes) -> Result<bool> {
1526 node_info!("anvil_loadState");
1527 self.backend.load_state_bytes(buf).await
1528 }
1529
1530 async fn block_request(
1531 &self,
1532 block_number: Option<BlockId>,
1533 ) -> Result<BlockRequest<FoundryTxEnvelope>> {
1534 let block_request = match block_number {
1535 Some(BlockId::Number(BlockNumber::Pending)) => {
1536 let pending_txs = self.pool.ready_transactions().collect();
1537 BlockRequest::Pending(pending_txs)
1538 }
1539 _ => {
1540 let number = self.backend.ensure_block_number(block_number).await?;
1541 BlockRequest::Number(number)
1542 }
1543 };
1544 Ok(block_request)
1545 }
1546
1547 pub async fn debug_account_info_at(
1551 &self,
1552 block_id: BlockId,
1553 tx_index: Index,
1554 address: Address,
1555 ) -> Result<Option<AccountInfo>> {
1556 node_info!("debug_accountInfoAt");
1557 self.backend.debug_account_info_at(block_id, tx_index, address).await
1558 }
1559
1560 pub async fn trace_transaction_opcode_gas(
1564 &self,
1565 tx_hash: B256,
1566 ) -> Result<Option<TransactionOpcodeGas>> {
1567 node_info!("trace_transactionOpcodeGas");
1568 self.backend.trace_transaction_opcode_gas(tx_hash).await
1569 }
1570
1571 pub async fn trace_block_opcode_gas(
1575 &self,
1576 block_id: BlockId,
1577 ) -> Result<Option<BlockOpcodeGas>> {
1578 node_info!("trace_blockOpcodeGas");
1579 self.backend.trace_block_opcode_gas(block_id).await
1580 }
1581
1582 pub async fn trace_raw_transaction(
1586 &self,
1587 tx: Bytes,
1588 trace_types: HashSet<TraceType>,
1589 block_number: Option<BlockId>,
1590 ) -> Result<TraceResults> {
1591 node_info!("trace_rawTransaction");
1592
1593 let mut data = tx.as_ref();
1594 if data.is_empty() {
1595 return Err(BlockchainError::EmptyRawTransactionData);
1596 }
1597
1598 let transaction = FoundryTxEnvelope::decode_2718(&mut data)
1599 .map_err(|_| BlockchainError::FailedToDecodeSignedTransaction)?;
1600 self.ensure_typed_transaction_supported(&transaction)?;
1601
1602 let pending_transaction = PendingTransaction::new(transaction)?;
1603 let block_request = self.block_request(block_number).await?;
1604
1605 self.backend
1606 .trace_raw_transaction(pending_transaction, trace_types, Some(block_request))
1607 .await
1608 }
1609
1610 pub async fn anvil_add_balance(&self, address: Address, balance: U256) -> Result<()> {
1614 node_info!("anvil_addBalance");
1615 let current_balance = self.backend.get_balance(address, None).await?;
1616 self.backend.set_balance(address, current_balance.saturating_add(balance)).await?;
1617 Ok(())
1618 }
1619
1620 pub async fn anvil_rollback(&self, depth: Option<u64>) -> Result<()> {
1631 node_info!("anvil_rollback");
1632 let depth = depth.unwrap_or(1);
1633
1634 let current_height = self.backend.best_number();
1636 let common_height = current_height.checked_sub(depth).ok_or(BlockchainError::RpcError(
1637 RpcError::invalid_params(format!(
1638 "Rollback depth must not exceed current chain height: current height {current_height}, depth {depth}"
1639 )),
1640 ))?;
1641
1642 let common_block =
1644 self.backend.get_block(common_height).ok_or(BlockchainError::BlockNotFound)?;
1645
1646 self.backend.rollback(common_block).await?;
1647 Ok(())
1648 }
1649
1650 fn do_estimate_gas_with_state(
1654 &self,
1655 request: FoundryTransactionRequest,
1656 state: &dyn DatabaseRef,
1657 block_env: BlockEnv,
1658 ) -> Result<u128> {
1659 let inner = request.as_ref();
1660 let fees = FeeDetails::new(
1661 inner.gas_price,
1662 inner.max_fee_per_gas,
1663 inner.max_priority_fee_per_gas,
1664 inner.max_fee_per_blob_gas,
1665 )?
1666 .or_zero_fees();
1667
1668 let mut highest_gas_limit = inner.gas.map_or(block_env.gas_limit.into(), |g| g as u128);
1671
1672 let is_tempo_aa_tx = self.backend.is_tempo() && request.is_tempo();
1675 let is_tempo_keychain = matches!(
1676 &request,
1677 FoundryTransactionRequest::Tempo(request) if request.key_id.is_some()
1678 );
1679
1680 let gas_price = fees.gas_price.unwrap_or_default();
1681 if !is_tempo_aa_tx && let Some(from) = inner.from {
1686 let mut available_funds = self.backend.get_balance_with_state(state, from)?;
1687 if let Some(value) = inner.value {
1688 if value > available_funds {
1689 return Err(InvalidTransactionError::InsufficientFunds.into());
1690 }
1691 available_funds -= value;
1693 }
1694 if gas_price > 0 {
1695 let allowance =
1697 available_funds.checked_div(U256::from(gas_price)).unwrap_or_default();
1698 highest_gas_limit = std::cmp::min(highest_gas_limit, allowance.saturating_to());
1699 }
1700 }
1701
1702 if !self.backend.is_tempo() {
1707 let to = inner.to.as_ref().and_then(TxKind::to);
1708
1709 let maybe_transfer = (inner.input.input().is_none()
1711 || inner.input.input().is_some_and(|data| data.is_empty()))
1712 && inner.authorization_list.is_none()
1713 && inner.access_list.is_none()
1714 && inner.blob_versioned_hashes.is_none();
1715
1716 if maybe_transfer
1717 && highest_gas_limit >= MIN_TRANSACTION_GAS
1718 && let Some(to) = to
1719 && let Ok(target_code) = self.backend.get_code_with_state(&state, *to)
1720 && target_code.as_ref().is_empty()
1721 {
1722 return Ok(MIN_TRANSACTION_GAS);
1723 }
1724 }
1725
1726 let ethres = self.backend.call_with_state_typed_gas_limit(
1728 &state,
1729 request.clone(),
1730 fees.clone(),
1731 block_env.clone(),
1732 highest_gas_limit as u64,
1733 is_tempo_keychain,
1734 );
1735
1736 let gas_used = match ethres.try_into()? {
1737 GasEstimationCallResult::Success(gas) => Ok(gas),
1738 GasEstimationCallResult::OutOfGas => {
1739 Err(InvalidTransactionError::BasicOutOfGas(highest_gas_limit).into())
1740 }
1741 GasEstimationCallResult::Revert(output) => {
1742 Err(InvalidTransactionError::Revert(output).into())
1743 }
1744 GasEstimationCallResult::EvmError(err) => {
1745 warn!(target: "node", "estimation failed due to {:?}", err);
1746 Err(BlockchainError::EvmError(err))
1747 }
1748 }?;
1749
1750 let mut lowest_gas_limit = determine_base_gas_by_kind(&request);
1757
1758 let mut mid_gas_limit =
1760 std::cmp::min(gas_used * 3, (highest_gas_limit + lowest_gas_limit) / 2);
1761
1762 while (highest_gas_limit - lowest_gas_limit) > 1 {
1764 let ethres = self.backend.call_with_state_typed_gas_limit(
1765 &state,
1766 request.clone(),
1767 fees.clone(),
1768 block_env.clone(),
1769 mid_gas_limit as u64,
1770 is_tempo_keychain,
1771 );
1772
1773 match ethres.try_into()? {
1774 GasEstimationCallResult::Success(_) => {
1775 highest_gas_limit = mid_gas_limit;
1779 }
1780 GasEstimationCallResult::OutOfGas
1781 | GasEstimationCallResult::Revert(_)
1782 | GasEstimationCallResult::EvmError(_) => {
1783 lowest_gas_limit = mid_gas_limit;
1790 }
1791 };
1792 mid_gas_limit = (highest_gas_limit + lowest_gas_limit) / 2;
1794 }
1795
1796 trace!(target : "node", "Estimated Gas for call {:?}", highest_gas_limit);
1797
1798 Ok(highest_gas_limit)
1799 }
1800
1801 #[allow(clippy::large_stack_frames)]
1803 pub async fn execute(&self, request: EthRequest) -> ResponseResult {
1804 trace!(target: "rpc::api", "executing eth request");
1805 let response = match request.clone() {
1806 EthRequest::EthProtocolVersion(()) => self.protocol_version().to_rpc_result(),
1807 EthRequest::Web3ClientVersion(()) => self.client_version().to_rpc_result(),
1808 EthRequest::Web3Sha3(content) => self.sha3(content).to_rpc_result(),
1809 EthRequest::EthGetAccount(addr, block) => {
1810 self.get_account(addr, block).await.to_rpc_result()
1811 }
1812 EthRequest::EthGetAccountInfo(addr, block) => {
1813 self.get_account_info(addr, block).await.to_rpc_result()
1814 }
1815 EthRequest::EthGetBalance(addr, block) => {
1816 self.balance(addr, block).await.to_rpc_result()
1817 }
1818 EthRequest::EthGetTransactionByHash(hash) => {
1819 self.transaction_by_hash(hash).await.to_rpc_result()
1820 }
1821 EthRequest::EthPendingTransactions(_) => {
1822 self.pending_transactions().await.to_rpc_result()
1823 }
1824 EthRequest::EthSendTransaction(request) => {
1825 self.send_transaction(*request).await.to_rpc_result()
1826 }
1827 EthRequest::EthResend(request, gas_price, gas_limit) => {
1828 self.resend_transaction(*request, gas_price, gas_limit).await.to_rpc_result()
1829 }
1830 EthRequest::EthSendTransactionSync(request) => {
1831 self.send_transaction_sync(*request).await.to_rpc_result()
1832 }
1833 EthRequest::EthChainId(_) => self.eth_chain_id().to_rpc_result(),
1834 EthRequest::EthNetworkId(_) => self.network_id().to_rpc_result(),
1835 EthRequest::NetListening(_) => self.net_listening().to_rpc_result(),
1836 EthRequest::EthHashrate(()) => self.hashrate().to_rpc_result(),
1837 EthRequest::EthGasPrice(_) => self.eth_gas_price().to_rpc_result(),
1838 EthRequest::EthBaseFee(_) => self.base_fee().to_rpc_result(),
1839 EthRequest::EthMaxPriorityFeePerGas(_) => {
1840 self.gas_max_priority_fee_per_gas().to_rpc_result()
1841 }
1842 EthRequest::EthBlobBaseFee(_) => self.blob_base_fee().to_rpc_result(),
1843 EthRequest::EthAccounts(_) => self.accounts().to_rpc_result(),
1844 EthRequest::EthBlockNumber(_) => self.block_number().to_rpc_result(),
1845 EthRequest::EthCoinbase(()) => self.author().to_rpc_result(),
1846 EthRequest::EthGetStorageAt(addr, slot, block) => {
1847 self.storage_at(addr, slot, block).await.to_rpc_result()
1848 }
1849 EthRequest::EthGetStorageValues(requests, block) => {
1850 self.storage_values(requests, block).await.to_rpc_result()
1851 }
1852 EthRequest::EthGetBlockByHash(hash, full) => {
1853 if full {
1854 self.block_by_hash_full(hash).await.to_rpc_result()
1855 } else {
1856 self.block_by_hash(hash).await.to_rpc_result()
1857 }
1858 }
1859 EthRequest::EthGetHeaderByHash(hash) => self.header_by_hash(hash).await.to_rpc_result(),
1860 EthRequest::EthGetBlockByNumber(num, full) => {
1861 if full {
1862 self.block_by_number_full(num).await.to_rpc_result()
1863 } else {
1864 self.block_by_number(num).await.to_rpc_result()
1865 }
1866 }
1867 EthRequest::EthGetHeaderByNumber(num) => {
1868 self.header_by_number(num).await.to_rpc_result()
1869 }
1870 EthRequest::EthGetBlockAccessList(block_id) => {
1871 self.block_access_list(block_id).await.to_rpc_result()
1872 }
1873 EthRequest::EthGetBlockAccessListByBlockHash(block_hash) => {
1874 self.block_access_list_by_hash(block_hash).await.to_rpc_result()
1875 }
1876 EthRequest::EthGetBlockAccessListByBlockNumber(block_number) => {
1877 self.block_access_list_by_number(block_number).await.to_rpc_result()
1878 }
1879 EthRequest::EthGetBlockAccessListRaw(block_id) => {
1880 self.block_access_list_raw(block_id).await.to_rpc_result()
1881 }
1882 EthRequest::EthGetTransactionCount(addr, block) => {
1883 self.transaction_count(addr, block).await.to_rpc_result()
1884 }
1885 EthRequest::EthGetTransactionCountByHash(hash) => {
1886 self.block_transaction_count_by_hash(hash).await.to_rpc_result()
1887 }
1888 EthRequest::EthGetTransactionCountByNumber(num) => {
1889 self.block_transaction_count_by_number(num).await.to_rpc_result()
1890 }
1891 EthRequest::EthGetUnclesCountByHash(hash) => {
1892 self.block_uncles_count_by_hash(hash).await.to_rpc_result()
1893 }
1894 EthRequest::EthGetUnclesCountByNumber(num) => {
1895 self.block_uncles_count_by_number(num).await.to_rpc_result()
1896 }
1897 EthRequest::EthGetCodeAt(addr, block) => {
1898 self.get_code(addr, block).await.to_rpc_result()
1899 }
1900 EthRequest::EthGetProof(addr, keys, block) => {
1901 self.get_proof(addr, keys, block).await.to_rpc_result()
1902 }
1903 EthRequest::EthSign(addr, content) => self.sign(addr, content).await.to_rpc_result(),
1904 EthRequest::PersonalSign(content, addr) => {
1905 self.sign(addr, content).await.to_rpc_result()
1906 }
1907 EthRequest::EthSignTransaction(request) => {
1908 self.sign_transaction(*request).await.to_rpc_result()
1909 }
1910 EthRequest::EthSignTypedData(addr, data) => {
1911 self.sign_typed_data(addr, data).await.to_rpc_result()
1912 }
1913 EthRequest::EthSignTypedDataV3(addr, data) => {
1914 self.sign_typed_data_v3(addr, data).await.to_rpc_result()
1915 }
1916 EthRequest::EthSignTypedDataV4(addr, data) => {
1917 self.sign_typed_data_v4(addr, &data).await.to_rpc_result()
1918 }
1919 EthRequest::EthSendRawTransaction(tx) => {
1920 self.send_raw_transaction(tx).await.to_rpc_result()
1921 }
1922 EthRequest::EthSendRawTransactionSync(tx, timeout_ms) => {
1923 self.send_raw_transaction_sync(tx, timeout_ms).await.to_rpc_result()
1924 }
1925 EthRequest::EthSendRawTransactionConditional(tx, condition) => {
1926 self.send_raw_transaction_conditional(tx, condition).await.to_rpc_result()
1927 }
1928 EthRequest::AnvilClassifyTransaction(tx) => {
1929 self.anvil_classify_transaction(tx).to_rpc_result()
1930 }
1931 EthRequest::EthCall(call, block, state_override, block_overrides) => self
1932 .call(call, block, EvmOverrides::new(state_override, block_overrides))
1933 .await
1934 .to_rpc_result(),
1935 EthRequest::EthCallMany(bundles, state_context, state_override) => {
1936 self.call_many(bundles, state_context, state_override).await.to_rpc_result()
1937 }
1938 EthRequest::EthCallBundle(bundle) => self.call_bundle(bundle).await.to_rpc_result(),
1939 EthRequest::EthSimulateV1(simulation, block) => {
1940 self.simulate_v1_raw(simulation, block).await.to_rpc_result()
1941 }
1942 EthRequest::EthCreateAccessList(call, block, state_override) => {
1943 self.create_access_list(call, block, state_override).await.to_rpc_result()
1944 }
1945 EthRequest::EthEstimateGas(call, block, state_override, block_overrides) => self
1946 .estimate_gas(call, block, EvmOverrides::new(state_override, block_overrides))
1947 .await
1948 .to_rpc_result(),
1949 EthRequest::EthFillTransaction(request) => {
1950 self.fill_transaction(request).await.to_rpc_result()
1951 }
1952 EthRequest::EthGetRawTransactionByHash(hash) => {
1953 self.raw_transaction(hash).await.to_rpc_result()
1954 }
1955 EthRequest::GetBlobByHash(hash) => {
1956 self.anvil_get_blob_by_versioned_hash(hash).to_rpc_result()
1957 }
1958 EthRequest::GetBlobByTransactionHash(hash) => {
1959 self.anvil_get_blob_by_tx_hash(hash).to_rpc_result()
1960 }
1961 EthRequest::GetGenesisTime(()) => self.anvil_get_genesis_time().to_rpc_result(),
1962 EthRequest::EthGetRawTransactionByBlockHashAndIndex(hash, index) => {
1963 self.raw_transaction_by_block_hash_and_index(hash, index).await.to_rpc_result()
1964 }
1965 EthRequest::EthGetRawTransactionByBlockNumberAndIndex(num, index) => {
1966 self.raw_transaction_by_block_number_and_index(num, index).await.to_rpc_result()
1967 }
1968 EthRequest::EthGetTransactionByBlockHashAndIndex(hash, index) => {
1969 self.transaction_by_block_hash_and_index(hash, index).await.to_rpc_result()
1970 }
1971 EthRequest::EthGetTransactionByBlockNumberAndIndex(num, index) => {
1972 self.transaction_by_block_number_and_index(num, index).await.to_rpc_result()
1973 }
1974 EthRequest::EthGetTransactionReceipt(tx) => {
1975 self.transaction_receipt(tx).await.to_rpc_result()
1976 }
1977 EthRequest::EthGetBlockReceipts(number) => {
1978 self.block_receipts(number).await.to_rpc_result()
1979 }
1980 EthRequest::EthGetUncleByBlockHashAndIndex(hash, index) => {
1981 self.uncle_by_block_hash_and_index(hash, index).await.to_rpc_result()
1982 }
1983 EthRequest::EthGetUncleByBlockNumberAndIndex(num, index) => {
1984 self.uncle_by_block_number_and_index(num, index).await.to_rpc_result()
1985 }
1986 EthRequest::EthGetLogs(filter) => self.logs(filter).await.to_rpc_result(),
1987 EthRequest::EthGetWork(_) => self.work().to_rpc_result(),
1988 EthRequest::EthSyncing(_) => self.syncing().to_rpc_result(),
1989 EthRequest::EthConfig(_) => self.config().to_rpc_result(),
1990 EthRequest::EthSubmitWork(nonce, pow, digest) => {
1991 self.submit_work(nonce, pow, digest).to_rpc_result()
1992 }
1993 EthRequest::EthSubmitHashRate(rate, id) => {
1994 self.submit_hashrate(rate, id).to_rpc_result()
1995 }
1996 EthRequest::EthFeeHistory(count, newest, reward_percentiles) => {
1997 self.fee_history(count, newest, reward_percentiles).await.to_rpc_result()
1998 }
1999 EthRequest::DebugGetRawTransaction(hash) => {
2001 self.raw_transaction(hash).await.to_rpc_result()
2002 }
2003 EthRequest::DebugGetRawReceipts(block) => {
2004 self.raw_receipts(block).await.to_rpc_result()
2005 }
2006 EthRequest::DebugGetRawTransactions(block) => {
2007 self.raw_transactions(block).await.to_rpc_result()
2008 }
2009 EthRequest::DebugGetRawHeader(block) => self.raw_header(block).await.to_rpc_result(),
2010 EthRequest::DebugGetRawBlock(block) => self.raw_block(block).await.to_rpc_result(),
2011 EthRequest::DebugClearTxpool(_) => self.debug_clear_txpool().await.to_rpc_result(),
2013 EthRequest::DebugTraceTransaction(tx, opts) => {
2015 self.debug_trace_transaction(tx, opts).await.to_rpc_result()
2016 }
2017 EthRequest::DebugTraceCall(tx, block, opts) => {
2019 self.debug_trace_call(tx, block, opts).await.to_rpc_result()
2020 }
2021 EthRequest::DebugCodeByHash(hash, block) => {
2022 self.debug_code_by_hash(hash, block).await.to_rpc_result()
2023 }
2024 EthRequest::DebugDbGet(key) => self.debug_db_get(key).await.to_rpc_result(),
2025 EthRequest::DebugGetModifiedAccountsByNumber(start_number, end_number) => {
2026 self.debug_get_modified_accounts_by_number(start_number, end_number).to_rpc_result()
2027 }
2028 EthRequest::DebugFreeOsMemory(()) => self.debug_free_os_memory().to_rpc_result(),
2029 EthRequest::DebugAccountInfoAt(block_id, tx_index, address) => {
2030 self.debug_account_info_at(block_id, tx_index, address).await.to_rpc_result()
2031 }
2032 EthRequest::DebugTraceBlock(rlp_block, opts) => {
2033 self.debug_trace_block(rlp_block, opts).await.to_rpc_result()
2034 }
2035 EthRequest::DebugTraceBlockByHash(block_hash, opts) => {
2036 self.debug_trace_block_by_hash(block_hash, opts).await.to_rpc_result()
2037 }
2038 EthRequest::DebugTraceBlockByNumber(block_number, opts) => {
2039 self.debug_trace_block_by_number(block_number, opts).await.to_rpc_result()
2040 }
2041 EthRequest::TraceCall(tx, trace_types, block) => {
2042 self.trace_call(tx, trace_types, block).await.to_rpc_result()
2043 }
2044 EthRequest::TraceTransaction(tx) => self.trace_transaction(tx).await.to_rpc_result(),
2045 EthRequest::TraceBlock(block) => self.trace_block(block).await.to_rpc_result(),
2046 EthRequest::TraceFilter(filter) => self.trace_filter(filter).await.to_rpc_result(),
2047 EthRequest::TraceGet(hash, indices) => {
2048 self.trace_get(hash, indices).await.to_rpc_result()
2049 }
2050 EthRequest::TraceReplayBlockTransactions(block, trace_types) => {
2051 self.trace_replay_block_transactions(block, trace_types).await.to_rpc_result()
2052 }
2053 EthRequest::TraceReplayTransaction(transaction, trace_types) => {
2054 self.trace_replay_transaction(transaction, trace_types).await.to_rpc_result()
2055 }
2056 EthRequest::TraceTransactionOpcodeGas(tx_hash) => {
2057 self.trace_transaction_opcode_gas(tx_hash).await.to_rpc_result()
2058 }
2059 EthRequest::TraceBlockOpcodeGas(block_id) => {
2060 self.trace_block_opcode_gas(block_id).await.to_rpc_result()
2061 }
2062 EthRequest::TraceRawTransaction(tx, trace_types, block_number) => {
2063 self.trace_raw_transaction(tx, trace_types, block_number).await.to_rpc_result()
2064 }
2065 EthRequest::TraceCallMany(calls, block_number) => {
2066 self.trace_call_many(calls, block_number).await.to_rpc_result()
2067 }
2068 EthRequest::ImpersonateAccount(addr) => {
2069 self.anvil_impersonate_account(addr).await.to_rpc_result()
2070 }
2071 EthRequest::StopImpersonatingAccount(addr) => {
2072 self.anvil_stop_impersonating_account(addr).await.to_rpc_result()
2073 }
2074 EthRequest::AutoImpersonateAccount(enable) => {
2075 self.anvil_auto_impersonate_account(enable).await.to_rpc_result()
2076 }
2077 EthRequest::ImpersonateSignature(signature, address) => {
2078 self.anvil_impersonate_signature(signature, address).await.to_rpc_result()
2079 }
2080 EthRequest::GetAutoMine(()) => self.anvil_get_auto_mine().to_rpc_result(),
2081 EthRequest::Mine(blocks, interval) => {
2082 self.anvil_mine(blocks, interval).await.to_rpc_result()
2083 }
2084 EthRequest::SetAutomine(enabled) => {
2085 self.anvil_set_auto_mine(enabled).await.to_rpc_result()
2086 }
2087 EthRequest::SetIntervalMining(interval) => {
2088 self.anvil_set_interval_mining(interval).to_rpc_result()
2089 }
2090 EthRequest::GetIntervalMining(()) => self.anvil_get_interval_mining().to_rpc_result(),
2091 EthRequest::DropTransaction(tx) => {
2092 self.anvil_drop_transaction(tx).await.to_rpc_result()
2093 }
2094 EthRequest::DropAllTransactions() => {
2095 self.anvil_drop_all_transactions().await.to_rpc_result()
2096 }
2097 EthRequest::Reset(fork) => {
2098 self.anvil_reset(fork.and_then(|p| p.params)).await.to_rpc_result()
2099 }
2100 EthRequest::SetBalance(addr, val) => {
2101 self.anvil_set_balance(addr, val).await.to_rpc_result()
2102 }
2103 EthRequest::AddBalance(addr, val) => {
2104 self.anvil_add_balance(addr, val).await.to_rpc_result()
2105 }
2106 EthRequest::DealERC20(addr, token_addr, val) => {
2107 self.anvil_deal_erc20(addr, token_addr, val).await.to_rpc_result()
2108 }
2109 EthRequest::DealTIP20(addr, token_addr, val) => {
2110 self.anvil_deal_tip20(addr, token_addr, val).await.to_rpc_result()
2111 }
2112 EthRequest::SetERC20Allowance(owner, spender, token_addr, val) => self
2113 .anvil_set_erc20_allowance(owner, spender, token_addr, val)
2114 .await
2115 .to_rpc_result(),
2116 EthRequest::SetCode(addr, code) => {
2117 self.anvil_set_code(addr, code).await.to_rpc_result()
2118 }
2119 EthRequest::SetNonce(addr, nonce) => {
2120 self.anvil_set_nonce(addr, nonce).await.to_rpc_result()
2121 }
2122 EthRequest::SetStorageAt(addr, slot, val) => {
2123 self.anvil_set_storage_at(addr, slot, val).await.to_rpc_result()
2124 }
2125 EthRequest::SetCoinbase(addr) => self.anvil_set_coinbase(addr).await.to_rpc_result(),
2126 EthRequest::SetNextBlockPrevRandao(prevrandao) => {
2127 self.anvil_set_next_block_prevrandao(prevrandao).await.to_rpc_result()
2128 }
2129 EthRequest::SetChainId(id) => self.anvil_set_chain_id(id).await.to_rpc_result(),
2130 EthRequest::SetLogging(log) => self.anvil_set_logging(log).await.to_rpc_result(),
2131 EthRequest::SetMinGasPrice(gas) => {
2132 self.anvil_set_min_gas_price(gas).await.to_rpc_result()
2133 }
2134 EthRequest::SetNextBlockBaseFeePerGas(gas) => {
2135 self.anvil_set_next_block_base_fee_per_gas(gas).await.to_rpc_result()
2136 }
2137 EthRequest::DumpState(preserve_historical_states) => self
2138 .anvil_dump_state(preserve_historical_states.and_then(|s| s.params))
2139 .await
2140 .to_rpc_result(),
2141 EthRequest::LoadState(buf) => self.anvil_load_state(buf).await.to_rpc_result(),
2142 EthRequest::NodeInfo(_) => self.anvil_node_info().await.to_rpc_result(),
2143 EthRequest::AnvilMetadata(_) => self.anvil_metadata().await.to_rpc_result(),
2144 EthRequest::EvmSnapshot(_) => self.evm_snapshot().await.to_rpc_result(),
2145 EthRequest::EvmRevert(id) => self.evm_revert(id).await.to_rpc_result(),
2146 EthRequest::EvmIncreaseTime(time) => self.evm_increase_time(time).await.to_rpc_result(),
2147 EthRequest::EvmSetNextBlockTimeStamp(time) => {
2148 if time >= U256::from(u64::MAX) {
2149 return ResponseResult::Error(RpcError::invalid_params(
2150 "The timestamp is too big",
2151 ));
2152 }
2153 let time = time.to::<u64>();
2154 self.evm_set_next_block_timestamp(time).to_rpc_result()
2155 }
2156 EthRequest::EvmSetTime(timestamp) => {
2157 if timestamp >= U256::from(u64::MAX) {
2158 return ResponseResult::Error(RpcError::invalid_params(
2159 "The timestamp is too big",
2160 ));
2161 }
2162 let raw = timestamp.to::<u64>();
2166 let time = if raw > 1_000_000_000_000 {
2167 Duration::from_millis(raw).as_secs()
2168 } else {
2169 raw
2170 };
2171 self.evm_set_time(time).to_rpc_result()
2172 }
2173 EthRequest::EvmSetBlockGasLimit(gas_limit) => {
2174 self.evm_set_block_gas_limit(gas_limit).to_rpc_result()
2175 }
2176 EthRequest::EvmSetBlockTimeStampInterval(time) => {
2177 self.evm_set_block_timestamp_interval(time).to_rpc_result()
2178 }
2179 EthRequest::EvmRemoveBlockTimeStampInterval(()) => {
2180 self.evm_remove_block_timestamp_interval().to_rpc_result()
2181 }
2182 EthRequest::EvmMine(mine) => {
2183 self.evm_mine(mine.and_then(|p| p.params)).await.to_rpc_result()
2184 }
2185 EthRequest::EvmMineDetailed(mine) => {
2186 self.evm_mine_detailed(mine.and_then(|p| p.params)).await.to_rpc_result()
2187 }
2188 EthRequest::SetRpcUrl(url) => self.anvil_set_rpc_url(url).await.to_rpc_result(),
2189 EthRequest::EthSendUnsignedTransaction(tx) => {
2190 self.eth_send_unsigned_transaction(*tx).await.to_rpc_result()
2191 }
2192 EthRequest::EthNewFilter(filter) => self.new_filter(filter).await.to_rpc_result(),
2193 EthRequest::EthGetFilterChanges(id) => self.get_filter_changes(&id).await,
2194 EthRequest::EthNewBlockFilter(_) => self.new_block_filter().await.to_rpc_result(),
2195 EthRequest::EthNewPendingTransactionFilter(full) => {
2196 self.new_pending_transaction_filter(full.unwrap_or(false)).await.to_rpc_result()
2197 }
2198 EthRequest::EthGetFilterLogs(id) => self.get_filter_logs(&id).await.to_rpc_result(),
2199 EthRequest::EthUninstallFilter(id) => self.uninstall_filter(&id).await.to_rpc_result(),
2200 EthRequest::TxPoolStatus(_) => self.txpool_status().await.to_rpc_result(),
2201 EthRequest::TxPoolInspect(_) => self.txpool_inspect().await.to_rpc_result(),
2202 EthRequest::TxPoolContent(_) => self.txpool_content().await.to_rpc_result(),
2203 EthRequest::TxPoolContentFrom(from) => {
2204 self.txpool_content_from(from).await.to_rpc_result()
2205 }
2206 EthRequest::ErigonGetHeaderByNumber(num) => {
2207 self.erigon_get_header_by_number(num).await.to_rpc_result()
2208 }
2209 EthRequest::OtsGetApiLevel(_) => self.ots_get_api_level().await.to_rpc_result(),
2210 EthRequest::OtsGetInternalOperations(hash) => {
2211 self.ots_get_internal_operations(hash).await.to_rpc_result()
2212 }
2213 EthRequest::OtsHasCode(addr, num) => self.ots_has_code(addr, num).await.to_rpc_result(),
2214 EthRequest::OtsTraceTransaction(hash) => {
2215 self.ots_trace_transaction(hash).await.to_rpc_result()
2216 }
2217 EthRequest::OtsGetTransactionError(hash) => {
2218 self.ots_get_transaction_error(hash).await.to_rpc_result()
2219 }
2220 EthRequest::OtsGetBlockDetails(num) => {
2221 self.ots_get_block_details(num).await.to_rpc_result()
2222 }
2223 EthRequest::OtsGetBlockDetailsByHash(hash) => {
2224 self.ots_get_block_details_by_hash(hash).await.to_rpc_result()
2225 }
2226 EthRequest::OtsGetBlockTransactions(num, page, page_size) => {
2227 self.ots_get_block_transactions(num, page, page_size).await.to_rpc_result()
2228 }
2229 EthRequest::OtsSearchTransactionsBefore(address, num, page_size) => {
2230 self.ots_search_transactions_before(address, num, page_size).await.to_rpc_result()
2231 }
2232 EthRequest::OtsSearchTransactionsAfter(address, num, page_size) => {
2233 self.ots_search_transactions_after(address, num, page_size).await.to_rpc_result()
2234 }
2235 EthRequest::OtsGetTransactionBySenderAndNonce(address, nonce) => {
2236 self.ots_get_transaction_by_sender_and_nonce(address, nonce).await.to_rpc_result()
2237 }
2238 EthRequest::EthGetTransactionBySenderAndNonce(sender, nonce) => {
2239 self.transaction_by_sender_and_nonce(sender, nonce).await.to_rpc_result()
2240 }
2241 EthRequest::OtsGetContractCreator(address) => {
2242 self.ots_get_contract_creator(address).await.to_rpc_result()
2243 }
2244 EthRequest::RemovePoolTransactions(address) => {
2245 self.anvil_remove_pool_transactions(address).await.to_rpc_result()
2246 }
2247 EthRequest::Reorg(reorg_options) => {
2248 self.anvil_reorg(reorg_options).await.to_rpc_result()
2249 }
2250 EthRequest::Rollback(depth) => self.anvil_rollback(depth).await.to_rpc_result(),
2251 EthRequest::SetFeeToken(user, token) => {
2252 self.anvil_set_fee_token(user, token).await.to_rpc_result()
2253 }
2254 EthRequest::SetValidatorFeeToken(validator, token) => {
2255 self.anvil_set_validator_fee_token(validator, token).await.to_rpc_result()
2256 }
2257 EthRequest::SetFeeAmmLiquidity(user_token, validator_token, amount) => self
2258 .anvil_set_fee_amm_liquidity(user_token, validator_token, amount)
2259 .await
2260 .to_rpc_result(),
2261 };
2262
2263 if let ResponseResult::Error(err) = &response {
2264 node_info!("\nRPC request failed:");
2265 node_info!(" Request: {:?}", request);
2266 node_info!(" Error: {}\n", err);
2267 }
2268
2269 response
2270 }
2271
2272 fn sign_request(&self, from: &Address, typed_tx: FoundryTypedTx) -> Result<FoundryTxEnvelope> {
2273 match typed_tx {
2274 #[cfg(feature = "optimism")]
2275 FoundryTypedTx::Deposit(_) => return Ok(typed_tx.into_impersonated()),
2276 _ => {
2277 for signer in self.signers.iter() {
2278 if signer.accounts().contains(from) {
2279 return signer.sign_transaction_from(from, typed_tx);
2280 }
2281 }
2282 }
2283 }
2284 Err(BlockchainError::NoSignerAvailable)
2285 }
2286
2287 async fn inner_raw_transaction(&self, hash: B256) -> Result<Option<Bytes>> {
2288 match self.pool.get_transaction(hash) {
2289 Some(tx) => Ok(Some(tx.transaction.encoded_2718().into())),
2290 None => match self.backend.transaction_by_hash(hash).await? {
2291 Some(tx) => Ok(Some(tx.as_ref().encoded_2718().into())),
2292 None => Ok(None),
2293 },
2294 }
2295 }
2296
2297 pub async fn balance(&self, address: Address, block_number: Option<BlockId>) -> Result<U256> {
2301 node_info!("eth_getBalance");
2302 let block_request = self.block_request(block_number).await?;
2303
2304 if let BlockRequest::Number(number) = block_request
2306 && let Some(fork) = self.get_fork()
2307 && fork.predates_fork(number)
2308 {
2309 return Ok(fork.get_balance(address, number).await?);
2310 }
2311
2312 self.backend.get_balance(address, Some(block_request)).await
2313 }
2314
2315 pub async fn get_account(
2319 &self,
2320 address: Address,
2321 block_number: Option<BlockId>,
2322 ) -> Result<TrieAccount> {
2323 node_info!("eth_getAccount");
2324 let block_request = self.block_request(block_number).await?;
2325
2326 if let BlockRequest::Number(number) = block_request
2328 && let Some(fork) = self.get_fork()
2329 && fork.predates_fork(number)
2330 {
2331 return Ok(fork.get_account(address, number).await?);
2332 }
2333
2334 self.backend.get_account_at_block(address, Some(block_request)).await
2335 }
2336
2337 pub async fn get_account_info(
2341 &self,
2342 address: Address,
2343 block_number: Option<BlockId>,
2344 ) -> Result<alloy_rpc_types::eth::AccountInfo> {
2345 node_info!("eth_getAccountInfo");
2346
2347 if let Some(fork) = self.get_fork() {
2348 let block_request = self.block_request(block_number).await?;
2349 if let BlockRequest::Number(number) = block_request {
2351 trace!(target: "node", "get_account_info: fork block {}, requested block {number}", fork.block_number());
2352 return if fork.predates_fork(number) {
2353 let balance = fork.get_balance(address, number).map_err(BlockchainError::from);
2356 let code = fork.get_code(address, number).map_err(BlockchainError::from);
2357 let nonce = self.get_transaction_count(address, Some(number.into()));
2358 let (balance, code, nonce) = try_join!(balance, code, nonce)?;
2359
2360 Ok(alloy_rpc_types::eth::AccountInfo { balance, nonce, code })
2361 } else {
2362 let account_info = self.backend.get_account(address).await?;
2365 let code = self.backend.get_code(address, Some(block_request)).await?;
2366 Ok(alloy_rpc_types::eth::AccountInfo {
2367 balance: account_info.balance,
2368 nonce: account_info.nonce,
2369 code,
2370 })
2371 };
2372 }
2373 }
2374
2375 let account = self.get_account(address, block_number);
2376 let code = self.get_code(address, block_number);
2377 let (account, code) = try_join!(account, code)?;
2378 Ok(alloy_rpc_types::eth::AccountInfo {
2379 balance: account.balance,
2380 nonce: account.nonce,
2381 code,
2382 })
2383 }
2384 pub async fn storage_at(
2388 &self,
2389 address: Address,
2390 index: U256,
2391 block_number: Option<BlockId>,
2392 ) -> Result<B256> {
2393 node_info!("eth_getStorageAt");
2394 let block_request = self.block_request(block_number).await?;
2395
2396 if let BlockRequest::Number(number) = block_request
2398 && let Some(fork) = self.get_fork()
2399 && fork.predates_fork(number)
2400 {
2401 return Ok(B256::from(
2402 fork.storage_at(address, index, Some(BlockNumber::Number(number))).await?,
2403 ));
2404 }
2405
2406 self.backend.storage_at(address, index, Some(block_request)).await
2407 }
2408
2409 pub async fn storage_values(
2413 &self,
2414 requests: HashMap<Address, Vec<B256>>,
2415 block_number: Option<BlockId>,
2416 ) -> Result<HashMap<Address, Vec<B256>>> {
2417 node_info!("eth_getStorageValues");
2418
2419 let total_slots: usize = requests.values().map(|s| s.len()).sum();
2420 if total_slots > 1024 {
2421 return Err(BlockchainError::RpcError(RpcError::invalid_params(format!(
2422 "total slot count {total_slots} exceeds limit 1024"
2423 ))));
2424 }
2425
2426 let block_request = self.block_request(block_number).await?;
2427
2428 if let BlockRequest::Number(number) = block_request
2430 && let Some(fork) = self.get_fork()
2431 && fork.predates_fork(number)
2432 {
2433 let mut result: HashMap<Address, Vec<B256>> = HashMap::default();
2434 for (address, slots) in requests {
2435 let mut values = Vec::with_capacity(slots.len());
2436 for slot in &slots {
2437 let val = fork
2438 .storage_at(address, (*slot).into(), Some(BlockNumber::Number(number)))
2439 .await?;
2440 values.push(B256::from(val));
2441 }
2442 result.insert(address, values);
2443 }
2444 return Ok(result);
2445 }
2446
2447 self.backend.storage_values(requests, Some(block_request)).await
2448 }
2449
2450 pub async fn block_by_number(&self, number: BlockNumber) -> Result<Option<AnyRpcBlock>> {
2454 node_info!("eth_getBlockByNumber");
2455 if number == BlockNumber::Pending {
2456 return Ok(Some(self.pending_block().await));
2457 }
2458
2459 self.backend.block_by_number(number).await
2460 }
2461
2462 pub async fn header_by_number(
2466 &self,
2467 number: BlockNumber,
2468 ) -> Result<Option<WithOtherFields<AnyRpcHeader>>> {
2469 node_info!("eth_getHeaderByNumber");
2470 if number == BlockNumber::Pending {
2471 let WithOtherFields { inner: block, other } = self.pending_block().await.0;
2472 return Ok(Some(WithOtherFields { inner: block.header, other }));
2473 }
2474
2475 Ok(self.backend.block_by_number(number).await?.map(|block| {
2476 let WithOtherFields { inner: block, other } = block.0;
2477 WithOtherFields { inner: block.header, other }
2478 }))
2479 }
2480
2481 pub async fn block_by_number_full(&self, number: BlockNumber) -> Result<Option<AnyRpcBlock>> {
2485 node_info!("eth_getBlockByNumber");
2486 if number == BlockNumber::Pending {
2487 return Ok(self.pending_block_full().await);
2488 }
2489 self.backend.block_by_number_full(number).await
2490 }
2491
2492 pub async fn block_access_list(&self, block_id: BlockId) -> Result<Option<serde_json::Value>> {
2496 node_info!("eth_getBlockAccessList");
2497 let block_request = self.block_request(Some(block_id)).await?;
2498 let BlockRequest::Number(number) = block_request else { return Ok(None) };
2499
2500 if let Some(fork) = self.get_fork()
2501 && fork.predates_fork_inclusive(number)
2502 {
2503 return Ok(fork.block_access_list(block_id).await?);
2504 }
2505
2506 Ok(None)
2507 }
2508
2509 pub async fn block_access_list_by_hash(
2513 &self,
2514 block_hash: B256,
2515 ) -> Result<Option<serde_json::Value>> {
2516 node_info!("eth_getBlockAccessListByBlockHash");
2517 if let Some(fork) = self.get_fork() {
2518 return Ok(fork.block_access_list_by_hash(block_hash).await?);
2519 }
2520 Ok(None)
2521 }
2522
2523 pub async fn block_access_list_by_number(
2527 &self,
2528 block_number: BlockNumber,
2529 ) -> Result<Option<serde_json::Value>> {
2530 node_info!("eth_getBlockAccessListByBlockNumber");
2531 let block_request = self.block_request(Some(BlockId::Number(block_number))).await?;
2532 let BlockRequest::Number(number) = block_request else { return Ok(None) };
2533
2534 if let Some(fork) = self.get_fork()
2535 && fork.predates_fork_inclusive(number)
2536 {
2537 return Ok(fork.block_access_list_by_number(block_number).await?);
2538 }
2539
2540 Ok(None)
2541 }
2542
2543 pub async fn block_access_list_raw(&self, block_id: BlockId) -> Result<Option<Bytes>> {
2547 node_info!("eth_getBlockAccessListRaw");
2548 let block_request = self.block_request(Some(block_id)).await?;
2549 let BlockRequest::Number(number) = block_request else { return Ok(None) };
2550
2551 if let Some(fork) = self.get_fork()
2552 && fork.predates_fork_inclusive(number)
2553 {
2554 return Ok(fork.block_access_list_raw(block_id).await?);
2555 }
2556
2557 Ok(None)
2558 }
2559
2560 pub async fn transaction_count(
2567 &self,
2568 address: Address,
2569 block_number: Option<BlockId>,
2570 ) -> Result<U256> {
2571 node_info!("eth_getTransactionCount");
2572 self.get_transaction_count(address, block_number).await.map(U256::from)
2573 }
2574
2575 pub async fn block_transaction_count_by_number(
2579 &self,
2580 block_number: BlockNumber,
2581 ) -> Result<Option<U256>> {
2582 node_info!("eth_getBlockTransactionCountByNumber");
2583 let block_request = self.block_request(Some(block_number.into())).await?;
2584 if let BlockRequest::Pending(txs) = block_request {
2585 let block = self.backend.pending_block(txs).await;
2586 return Ok(Some(U256::from(block.block.body.transactions.len())));
2587 }
2588 let block = self.backend.block_by_number(block_number).await?;
2589 let txs = block.map(|b| match b.transactions() {
2590 BlockTransactions::Full(txs) => U256::from(txs.len()),
2591 BlockTransactions::Hashes(txs) => U256::from(txs.len()),
2592 BlockTransactions::Uncle => U256::from(0),
2593 });
2594 Ok(txs)
2595 }
2596
2597 pub async fn get_code(&self, address: Address, block_number: Option<BlockId>) -> Result<Bytes> {
2601 node_info!("eth_getCode");
2602 let block_request = self.block_request(block_number).await?;
2603 if let BlockRequest::Number(number) = block_request
2605 && let Some(fork) = self.get_fork()
2606 && fork.predates_fork(number)
2607 {
2608 return Ok(fork.get_code(address, number).await?);
2609 }
2610 self.backend.get_code(address, Some(block_request)).await
2611 }
2612
2613 pub async fn get_proof(
2618 &self,
2619 address: Address,
2620 keys: Vec<B256>,
2621 block_number: Option<BlockId>,
2622 ) -> Result<EIP1186AccountProofResponse> {
2623 node_info!("eth_getProof");
2624 let block_request = self.block_request(block_number).await?;
2625
2626 if let BlockRequest::Number(number) = block_request
2629 && let Some(fork) = self.get_fork()
2630 && fork.predates_fork_inclusive(number)
2631 {
2632 return Ok(fork.get_proof(address, keys, Some(number.into())).await?);
2633 }
2634
2635 let proof = self.backend.prove_account_at(address, keys, Some(block_request)).await?;
2636 Ok(proof)
2637 }
2638
2639 pub async fn sign_transaction(
2643 &self,
2644 request: WithOtherFields<TransactionRequest>,
2645 ) -> Result<String> {
2646 node_info!("eth_signTransaction");
2647 let request = self.parse_transaction_request(request)?;
2648
2649 let from = request.from().map(Ok).unwrap_or_else(|| {
2650 self.accounts()?.first().copied().ok_or(BlockchainError::NoSignerAvailable)
2651 })?;
2652
2653 let (nonce, _) = self.request_nonce_for_transaction(&request, from).await?;
2654
2655 let request = self.build_tx_request(request, nonce).await?;
2656
2657 let signed_transaction = self.sign_request(&from, request)?.encoded_2718();
2658 Ok(alloy_primitives::hex::encode_prefixed(signed_transaction))
2659 }
2660
2661 pub async fn send_transaction(
2665 &self,
2666 request: WithOtherFields<TransactionRequest>,
2667 ) -> Result<TxHash> {
2668 node_info!("eth_sendTransaction");
2669 let request = self.parse_transaction_request(request)?;
2670
2671 let from = request.from().map(Ok).unwrap_or_else(|| {
2672 self.accounts()?.first().copied().ok_or(BlockchainError::NoSignerAvailable)
2673 })?;
2674 let (nonce, on_chain_nonce) = self.request_nonce_for_transaction(&request, from).await?;
2675
2676 let typed_tx = self.build_tx_request(request, nonce).await?;
2677
2678 let pending_transaction = if self.is_impersonated(from) {
2680 let transaction = typed_tx.into_impersonated();
2681 self.ensure_typed_transaction_supported(&transaction)?;
2682 trace!(target : "node", ?from, "eth_sendTransaction: impersonating");
2683 PendingTransaction::with_impersonated(transaction, from)
2684 } else {
2685 let transaction = self.sign_request(&from, typed_tx)?;
2686 self.ensure_typed_transaction_supported(&transaction)?;
2687 PendingTransaction::new(transaction)?
2688 };
2689 self.backend.validate_pool_transaction(&pending_transaction).await?;
2691
2692 let (requires, provides) = nonce_markers(&pending_transaction, nonce, on_chain_nonce, from);
2693
2694 self.add_pending_transaction(pending_transaction, requires, provides)
2695 }
2696
2697 pub async fn resend_transaction(
2701 &self,
2702 request: WithOtherFields<TransactionRequest>,
2703 gas_price: Option<U256>,
2704 gas_limit: Option<U64>,
2705 ) -> Result<TxHash> {
2706 node_info!("eth_resend");
2707 let mut request = self.parse_transaction_request(request)?;
2708
2709 let from = request.from().map(Ok).unwrap_or_else(|| {
2710 self.accounts()?.first().copied().ok_or(BlockchainError::NoSignerAvailable)
2711 })?;
2712 let nonce = request.nonce().ok_or_else(|| {
2713 BlockchainError::InvalidTransactionRequest(
2714 "missing transaction nonce in transaction spec".to_string(),
2715 )
2716 })?;
2717
2718 if !self.pool.contains_sender_nonce(from, nonce) {
2719 return Err(BlockchainError::TransactionNotFound);
2720 }
2721
2722 if let Some(gas_price) = gas_price.filter(|gas_price| !gas_price.is_zero()) {
2723 request.set_gas_price(gas_price.saturating_to());
2724 }
2725
2726 if let Some(gas_limit) = gas_limit.filter(|gas_limit| *gas_limit != U64::ZERO) {
2727 request.set_gas_limit(gas_limit.to());
2728 }
2729
2730 let typed_tx = self.build_tx_request(request, nonce).await?;
2731
2732 let pending_transaction = if self.is_impersonated(from) {
2733 let transaction = typed_tx.into_impersonated();
2734 self.ensure_typed_transaction_supported(&transaction)?;
2735 trace!(target : "node", ?from, "eth_resend: impersonating");
2736 PendingTransaction::with_impersonated(transaction, from)
2737 } else {
2738 let transaction = self.sign_request(&from, typed_tx)?;
2739 self.ensure_typed_transaction_supported(&transaction)?;
2740 PendingTransaction::new(transaction)?
2741 };
2742
2743 self.backend.validate_pool_transaction(&pending_transaction).await?;
2744
2745 let on_chain_nonce = self.backend.current_nonce(from).await?;
2746 let (requires, provides) = nonce_markers(&pending_transaction, nonce, on_chain_nonce, from);
2747
2748 self.add_pending_transaction(pending_transaction, requires, provides)
2749 }
2750
2751 async fn await_transaction_inclusion(&self, hash: TxHash) -> Result<FoundryTxReceipt> {
2753 let mut stream = self.new_block_notifications();
2754 if let Some(receipt) = self.backend.transaction_receipt(hash).await? {
2756 return Ok(receipt);
2757 }
2758 while let Some(notification) = stream.next().await {
2759 if let Some(new_block) = notification.as_new_block()
2760 && let Some(block) = self.backend.get_block_by_hash(new_block.hash)
2761 && block.body.transactions.iter().any(|tx| tx.hash() == hash)
2762 && let Some(receipt) = self.backend.transaction_receipt(hash).await?
2763 {
2764 return Ok(receipt);
2765 }
2766 }
2767
2768 Err(BlockchainError::Message("Failed to await transaction inclusion".to_string()))
2769 }
2770
2771 fn transaction_confirmation_timeout(timeout_ms: Option<u64>) -> Duration {
2772 const TIMEOUT_DURATION: Duration = Duration::from_secs(30);
2773 timeout_ms
2774 .filter(|timeout_ms| *timeout_ms > 0)
2775 .map(Duration::from_millis)
2776 .map(|timeout| timeout.min(TIMEOUT_DURATION))
2777 .unwrap_or(TIMEOUT_DURATION)
2778 }
2779
2780 async fn check_transaction_inclusion(
2782 &self,
2783 hash: TxHash,
2784 timeout_ms: Option<u64>,
2785 ) -> Result<FoundryTxReceipt> {
2786 let timeout_duration = Self::transaction_confirmation_timeout(timeout_ms);
2787 tokio::time::timeout(timeout_duration, self.await_transaction_inclusion(hash))
2788 .await
2789 .unwrap_or_else(|_elapsed| {
2790 Err(BlockchainError::TransactionConfirmationTimeout {
2791 hash,
2792 duration: timeout_duration,
2793 })
2794 })
2795 }
2796
2797 pub async fn send_transaction_sync(
2801 &self,
2802 request: WithOtherFields<TransactionRequest>,
2803 ) -> Result<FoundryTxReceipt> {
2804 node_info!("eth_sendTransactionSync");
2805 let hash = self.send_transaction(request).await?;
2806
2807 let receipt = self.check_transaction_inclusion(hash, None).await?;
2808
2809 Ok(receipt)
2810 }
2811
2812 pub async fn send_raw_transaction(&self, tx: Bytes) -> Result<TxHash> {
2816 node_info!("eth_sendRawTransaction");
2817 let mut data = tx.as_ref();
2818 if data.is_empty() {
2819 return Err(BlockchainError::EmptyRawTransactionData);
2820 }
2821
2822 let transaction = FoundryTxEnvelope::decode_2718(&mut data)
2823 .map_err(|_| BlockchainError::FailedToDecodeSignedTransaction)?;
2824
2825 self.ensure_typed_transaction_supported(&transaction)?;
2826
2827 if self.backend.is_tempo() && TempoHardfork::from(self.backend.hardfork()).is_t5() {
2828 let classification = classify_payment_lane(tx.as_ref());
2829 trace!(target: "node", tx = ?transaction.hash(), ?classification, "classified transaction lane");
2830 }
2831
2832 let pending_transaction = PendingTransaction::new(transaction)?;
2833
2834 self.backend.validate_pool_transaction(&pending_transaction).await?;
2836
2837 let from = *pending_transaction.sender();
2838 let priority = self.transaction_priority(&pending_transaction.transaction);
2839
2840 let (requires, provides) = if let Some((requires, provides)) =
2842 tempo_parallel_nonce_markers(&pending_transaction)
2843 {
2844 (requires, provides)
2845 } else {
2846 let on_chain_nonce = self.backend.current_nonce(from).await?;
2847 let nonce = pending_transaction.transaction.nonce();
2848 (required_marker(nonce, on_chain_nonce, from), vec![to_marker(nonce, from)])
2849 };
2850
2851 let pool_transaction =
2852 PoolTransaction { requires, provides, pending_transaction, priority, is_replay: false };
2853
2854 let tx = self.pool.add_transaction(pool_transaction)?;
2855 trace!(target: "node", "Added transaction: [{:?}] sender={:?}", tx.hash(), from);
2856 Ok(*tx.hash())
2857 }
2858
2859 pub async fn send_raw_transaction_conditional(
2863 &self,
2864 tx: Bytes,
2865 _condition: TransactionConditional,
2866 ) -> Result<TxHash> {
2867 node_info!("eth_sendRawTransactionConditional");
2868 self.send_raw_transaction(tx).await
2869 }
2870
2871 pub fn anvil_classify_transaction(&self, tx: Bytes) -> Result<PaymentLaneClassification> {
2873 node_info!("anvil_classifyTransaction");
2874 let mut data = tx.as_ref();
2875 if data.is_empty() {
2876 return Err(BlockchainError::EmptyRawTransactionData);
2877 }
2878
2879 FoundryTxEnvelope::decode_2718(&mut data)
2880 .map_err(|_| BlockchainError::FailedToDecodeSignedTransaction)?;
2881
2882 Ok(self.classify_transaction_lane(tx.as_ref()))
2883 }
2884
2885 fn classify_transaction_lane(&self, raw: &[u8]) -> PaymentLaneClassification {
2886 if !self.backend.is_tempo() {
2887 return PaymentLaneClassification::general(PaymentLaneReason::NotTempo);
2888 }
2889
2890 if !TempoHardfork::from(self.backend.hardfork()).is_t5() {
2891 return PaymentLaneClassification::general(PaymentLaneReason::T5NotActive);
2892 }
2893
2894 classify_payment_lane(raw)
2895 }
2896
2897 pub async fn send_raw_transaction_sync(
2901 &self,
2902 tx: Bytes,
2903 timeout_ms: Option<u64>,
2904 ) -> Result<FoundryTxReceipt> {
2905 node_info!("eth_sendRawTransactionSync");
2906
2907 let hash = self.send_raw_transaction(tx).await?;
2908 let receipt = self.check_transaction_inclusion(hash, timeout_ms).await?;
2909
2910 Ok(receipt)
2911 }
2912
2913 pub async fn call(
2917 &self,
2918 request: WithOtherFields<TransactionRequest>,
2919 block_number: Option<BlockId>,
2920 overrides: EvmOverrides,
2921 ) -> Result<Bytes> {
2922 node_info!("eth_call");
2923 let block_request = self.block_request(block_number).await?;
2924 if let BlockRequest::Number(number) = block_request
2926 && let Some(fork) = self.get_fork()
2927 && fork.predates_fork(number)
2928 {
2929 if overrides.has_state() || overrides.has_block() {
2930 return Err(BlockchainError::EvmOverrideError(
2931 "not available on past forked blocks".to_string(),
2932 ));
2933 }
2934 return Ok(fork.call_raw(&request, Some(number.into())).await?);
2935 }
2936
2937 let fees = FeeDetails::new(
2938 request.gas_price,
2939 request.max_fee_per_gas,
2940 request.max_priority_fee_per_gas,
2941 request.max_fee_per_blob_gas,
2942 )?
2943 .or_zero_fees();
2944 self.on_blocking_task(|this| async move {
2947 let (exit, out, gas, _) =
2948 this.backend.call(request, fees, Some(block_request), overrides).await?;
2949 trace!(target : "node", "Call status {:?}, gas {}", exit, gas);
2950
2951 ensure_return_ok(exit, &out)
2952 })
2953 .await
2954 }
2955
2956 pub async fn call_many(
2957 &self,
2958 bundles: Vec<Bundle<WithOtherFields<TransactionRequest>>>,
2959 state_context: Option<StateContext>,
2960 state_override: Option<StateOverride>,
2961 ) -> Result<Vec<Vec<EthCallResponse>>> {
2962 node_info!("eth_callMany");
2963 let StateContext { transaction_index, block_number } = state_context.unwrap_or_default();
2964 if transaction_index.is_some_and(|index| index.index().is_some()) {
2965 return Err(BlockchainError::RpcError(RpcError::invalid_params(
2966 "transactionIndex is not supported for eth_callMany yet".to_string(),
2967 )));
2968 }
2969
2970 let block_request = self.block_request(block_number).await?;
2971 if let BlockRequest::Number(number) = block_request
2972 && let Some(fork) = self.get_fork()
2973 && fork.predates_fork(number)
2974 {
2975 return Ok(fork
2976 .call_many(
2977 bundles,
2978 Some(StateContext { transaction_index, block_number: Some(number.into()) }),
2979 state_override,
2980 )
2981 .await?);
2982 }
2983
2984 self.on_blocking_task(|this| async move {
2985 this.backend.call_many(bundles, Some(block_request), state_override).await
2986 })
2987 .await
2988 }
2989
2990 pub async fn call_bundle(&self, bundle: EthCallBundle) -> Result<EthCallBundleResponse> {
2994 node_info!("eth_callBundle");
2995 if bundle.txs.is_empty() {
2996 return Err(BlockchainError::RpcError(RpcError::invalid_params(
2997 "bundle missing txs".to_string(),
2998 )));
2999 }
3000 if bundle.block_number == 0 {
3001 return Err(BlockchainError::RpcError(RpcError::invalid_params(
3002 "bundle missing blockNumber".to_string(),
3003 )));
3004 }
3005
3006 let block_request = self.block_request(Some(bundle.state_block_number.into())).await?;
3007 if let BlockRequest::Number(number) = block_request
3008 && let Some(fork) = self.get_fork()
3009 && fork.predates_fork(number)
3010 {
3011 return Ok(fork.call_bundle(bundle).await?);
3012 }
3013
3014 let transactions = bundle
3015 .txs
3016 .iter()
3017 .map(|raw| {
3018 let mut data = raw.as_ref();
3019 if data.is_empty() {
3020 return Err(BlockchainError::EmptyRawTransactionData);
3021 }
3022 let transaction = FoundryTxEnvelope::decode_2718(&mut data)
3023 .map_err(|_| BlockchainError::FailedToDecodeSignedTransaction)?;
3024 self.ensure_typed_transaction_supported(&transaction)?;
3025 PendingTransaction::new(transaction).map_err(Into::into)
3026 })
3027 .collect::<Result<Vec<_>>>()?;
3028
3029 self.on_blocking_task(|this| async move {
3030 this.backend.call_bundle(bundle, transactions, Some(block_request)).await
3031 })
3032 .await
3033 }
3034
3035 pub async fn simulate_v1(
3036 &self,
3037 request: SimulatePayload,
3038 block_number: Option<BlockId>,
3039 ) -> Result<Vec<SimulatedBlock<AnyRpcBlock>>> {
3040 self.simulate_v1_raw(preserve_simulation_request_fields(request), block_number).await
3041 }
3042
3043 pub(crate) async fn simulate_v1_raw(
3044 &self,
3045 mut request: SimulatePayload<WithOtherFields<TransactionRequest>>,
3046 block_number: Option<BlockId>,
3047 ) -> Result<Vec<SimulatedBlock<AnyRpcBlock>>> {
3048 const DEFAULT_BLOCK_INTERVAL_SECS: u64 = 12;
3049
3050 node_info!("eth_simulateV1");
3051 if request.block_state_calls.is_empty() {
3052 return Err(BlockchainError::RpcError(RpcError::invalid_params("empty input")));
3053 }
3054 if request.block_state_calls.len() > MAX_SIMULATE_BLOCKS as usize {
3055 return Err(BlockchainError::RpcError(RpcError {
3056 code: ErrorCode::ServerError(-38026),
3057 message: "too many blocks".into(),
3058 data: None,
3059 }));
3060 }
3061 let block_id = block_number;
3062 let block_request =
3063 self.block_request(block_number).await.map_err(|error| match error {
3064 BlockchainError::BlockOutOfRange(_, _) | BlockchainError::BlockNotFound => {
3065 BlockchainError::RpcError(RpcError {
3066 code: ErrorCode::ServerError(-32000),
3067 message: "header not found".into(),
3068 data: None,
3069 })
3070 }
3071 error => error,
3072 })?;
3073 let block_interval = self.backend.time().block_timestamp_interval().unwrap_or_else(|| {
3074 self.miner
3075 .block_interval()
3076 .map(|duration| {
3077 duration
3078 .as_secs()
3079 .saturating_add(u64::from(duration.subsec_nanos() != 0))
3080 .max(1)
3081 })
3082 .unwrap_or(DEFAULT_BLOCK_INTERVAL_SECS)
3083 });
3084
3085 if let BlockRequest::Number(number) = block_request
3087 && let Some(fork) = self.get_fork()
3088 && fork.predates_fork(number)
3089 {
3090 let block_id = match block_id {
3091 Some(BlockId::Hash(hash)) => BlockId::Hash(hash),
3092 _ => number.into(),
3093 };
3094 let base_block = fork.fetch_block(block_id).await?.ok_or_else(|| {
3095 BlockchainError::RpcError(RpcError {
3096 code: ErrorCode::ServerError(-32000),
3097 message: "header not found".into(),
3098 data: None,
3099 })
3100 })?;
3101 request.block_state_calls = sanitize_simulation_blocks(
3102 request.block_state_calls,
3103 base_block.header.number(),
3104 base_block.header.timestamp(),
3105 block_interval,
3106 )?;
3107 return Ok(fork.simulate_v1(&request, Some(base_block.header.hash.into())).await?);
3108 }
3109
3110 self.on_blocking_task(|this| async move {
3113 let simulated_blocks =
3114 this.backend.simulate_raw(request, Some(block_request), block_interval).await?;
3115 trace!(target : "node", "Simulate status {:?}", simulated_blocks);
3116
3117 Ok(simulated_blocks)
3118 })
3119 .await
3120 }
3121
3122 pub async fn create_access_list(
3136 &self,
3137 request: WithOtherFields<TransactionRequest>,
3138 block_number: Option<BlockId>,
3139 state_override: Option<StateOverride>,
3140 ) -> Result<AccessListResult> {
3141 node_info!("eth_createAccessList");
3142 let block_request = self.block_request(block_number).await?;
3143 if let BlockRequest::Number(number) = block_request
3145 && let Some(fork) = self.get_fork()
3146 && fork.predates_fork(number)
3147 {
3148 if state_override.is_some() {
3149 return Err(BlockchainError::EvmOverrideError(
3150 "not available on past forked blocks".to_string(),
3151 ));
3152 }
3153 return Ok(fork.create_access_list_raw(&request, Some(number.into())).await?);
3154 }
3155 let typed_request = self.parse_transaction_request(request.clone())?;
3156
3157 self.backend
3158 .with_database_at(Some(block_request), |state, block_env| {
3159 let mut cache_db = CacheDB::new(state);
3160 if let Some(state_override) = state_override {
3161 apply_state_overrides(state_override.into_iter().collect(), &mut cache_db)?;
3162 }
3163
3164 let (_, _, _, access_list) = self.backend.build_access_list_with_state(
3165 &cache_db,
3166 request.clone(),
3167 FeeDetails::zero(),
3168 block_env.clone(),
3169 )?;
3170
3171 let (exit, _, gas_used, _) = self.backend.call_with_state_typed_access_list(
3176 &cache_db,
3177 typed_request,
3178 FeeDetails::zero(),
3179 block_env,
3180 access_list.clone(),
3181 )?;
3182
3183 Ok(AccessListResult {
3184 access_list,
3185 gas_used: U256::from(gas_used),
3186 error: execution_error(exit),
3187 })
3188 })
3189 .await?
3190 }
3191
3192 pub async fn estimate_gas(
3197 &self,
3198 request: WithOtherFields<TransactionRequest>,
3199 block_number: Option<BlockId>,
3200 overrides: EvmOverrides,
3201 ) -> Result<U256> {
3202 node_info!("eth_estimateGas");
3203 self.do_estimate_gas(
3204 request,
3205 block_number.or_else(|| Some(BlockNumber::Pending.into())),
3206 overrides,
3207 )
3208 .await
3209 .map(U256::from)
3210 }
3211
3212 pub async fn fill_transaction(
3219 &self,
3220 request: WithOtherFields<TransactionRequest>,
3221 ) -> Result<FillTransaction<AnyRpcTransaction>> {
3222 node_info!("eth_fillTransaction");
3223 let mut request = self.parse_transaction_request(request)?;
3224
3225 let from = match request.from() {
3226 Some(from) => from,
3227 None => self.accounts()?.first().copied().ok_or(BlockchainError::NoSignerAvailable)?,
3228 };
3229
3230 let nonce = self.request_nonce_for_transaction(&request, from).await?.0;
3231
3232 if request.gas_limit().is_none() {
3234 let estimated_gas = self
3235 .do_estimate_gas_typed(request.clone(), Some(BlockNumber::Pending.into()))
3236 .await?;
3237 request.set_gas_limit(estimated_gas as u64);
3238 }
3239
3240 let typed_tx = self.build_tx_request(request, nonce).await?;
3241 let tx = typed_tx.into_impersonated();
3242
3243 let raw = tx.encoded_2718().into();
3244
3245 let mut tx =
3246 transaction_build(None, MaybeImpersonatedTransaction::new(tx), None, None, None);
3247
3248 tx.0.inner.inner = Recovered::new_unchecked(tx.0.inner.inner.into_inner(), from);
3251
3252 Ok(FillTransaction { raw, tx })
3253 }
3254
3255 pub fn anvil_get_blob_by_tx_hash(&self, hash: B256) -> Result<Option<Vec<Blob>>> {
3257 node_info!("anvil_getBlobsByTransactionHash");
3258 Ok(self.backend.get_blob_by_tx_hash(hash)?)
3259 }
3260
3261 pub async fn transaction_by_hash(&self, hash: B256) -> Result<Option<AnyRpcTransaction>> {
3268 node_info!("eth_getTransactionByHash");
3269 let mut tx =
3270 self.pool.get_transaction(hash).map(|pending| self.build_pool_transaction(pending));
3271 if tx.is_none() {
3272 tx = self.backend.transaction_by_hash(hash).await?
3273 }
3274
3275 Ok(tx)
3276 }
3277
3278 fn build_pool_transaction(
3279 &self,
3280 pending: PendingTransaction<FoundryTxEnvelope>,
3281 ) -> AnyRpcTransaction {
3282 let from = *pending.sender();
3283 let tx = transaction_build(
3284 Some(*pending.hash()),
3285 pending.transaction,
3286 None,
3287 None,
3288 Some(self.backend.base_fee()),
3289 );
3290
3291 let WithOtherFields { inner: mut tx, other } = tx.0;
3292 tx.inner = Recovered::new_unchecked(tx.inner.into_inner(), from);
3295
3296 AnyRpcTransaction(WithOtherFields { inner: tx, other })
3297 }
3298
3299 pub async fn pending_transactions(&self) -> Result<Vec<AnyRpcTransaction>> {
3303 node_info!("eth_pendingTransactions");
3304 Ok(self
3305 .pool
3306 .ready_transactions()
3307 .map(|pending| self.build_pool_transaction(pending.pending_transaction.clone()))
3308 .collect())
3309 }
3310
3311 pub async fn transaction_by_sender_and_nonce(
3318 &self,
3319 sender: Address,
3320 nonce: U256,
3321 ) -> Result<Option<AnyRpcTransaction>> {
3322 node_info!("eth_getTransactionBySenderAndNonce");
3323
3324 for pending_tx in self.pool.ready_transactions().chain(self.pool.pending_transactions()) {
3326 if U256::from(pending_tx.pending_transaction.nonce()) == nonce
3327 && *pending_tx.pending_transaction.sender() == sender
3328 {
3329 let tx = transaction_build(
3330 Some(*pending_tx.pending_transaction.hash()),
3331 pending_tx.pending_transaction.transaction.clone(),
3332 None,
3333 None,
3334 Some(self.backend.base_fee()),
3335 );
3336
3337 let WithOtherFields { inner: mut tx, other } = tx.0;
3338 let from = *pending_tx.pending_transaction.sender();
3341 tx.inner = Recovered::new_unchecked(tx.inner.into_inner(), from);
3342
3343 return Ok(Some(AnyRpcTransaction(WithOtherFields { inner: tx, other })));
3344 }
3345 }
3346
3347 let highest_nonce = self.transaction_count(sender, None).await?.saturating_to::<u64>();
3348 let target_nonce = nonce.saturating_to::<u64>();
3349
3350 if target_nonce >= highest_nonce {
3352 return Ok(None);
3353 }
3354
3355 let latest_block = self.backend.best_number();
3357 if latest_block == 0 {
3358 return Ok(None);
3359 }
3360
3361 let mut low = 1u64;
3363 let mut high = latest_block;
3364
3365 while low <= high {
3366 let mid = low + (high - low) / 2;
3367 let mid_nonce =
3368 self.transaction_count(sender, Some(mid.into())).await?.saturating_to::<u64>();
3369
3370 if mid_nonce > target_nonce {
3371 high = mid - 1;
3372 } else {
3373 low = mid + 1;
3374 }
3375 }
3376
3377 let target_block = low;
3379 if target_block <= latest_block
3380 && let Some(txs) =
3381 self.backend.mined_transactions_by_block_number(target_block.into()).await
3382 {
3383 for tx in txs {
3384 if tx.from() == sender && tx.nonce() == target_nonce {
3385 return Ok(Some(tx));
3386 }
3387 }
3388 }
3389
3390 Ok(None)
3391 }
3392
3393 pub async fn transaction_receipt(&self, hash: B256) -> Result<Option<FoundryTxReceipt>> {
3397 node_info!("eth_getTransactionReceipt");
3398 self.backend.transaction_receipt(hash).await
3399 }
3400
3401 pub async fn block_receipts(&self, number: BlockId) -> Result<Option<Vec<FoundryTxReceipt>>> {
3405 node_info!("eth_getBlockReceipts");
3406 self.backend.block_receipts(number).await
3407 }
3408
3409 pub async fn logs(&self, filter: Filter) -> Result<Vec<Log>> {
3413 node_info!("eth_getLogs");
3414 self.backend.logs(filter).await
3415 }
3416
3417 pub async fn new_filter(&self, filter: Filter) -> Result<String> {
3421 node_info!("eth_newFilter");
3422 let historic = if filter.block_option.get_from_block().is_some() {
3425 self.backend.logs(filter.clone()).await?
3426 } else {
3427 vec![]
3428 };
3429 let filter = EthFilter::Logs(Box::new(LogsFilter {
3430 blocks: self.new_block_notifications(),
3431 storage: self.storage_info(),
3432 filter: FilteredParams::new(Some(filter)),
3433 historic: Some(historic),
3434 }));
3435 Ok(self.filters.add_filter(filter).await)
3436 }
3437
3438 pub async fn new_block_filter(&self) -> Result<String> {
3442 node_info!("eth_newBlockFilter");
3443 let filter = EthFilter::Blocks(self.new_block_notifications());
3444 Ok(self.filters.add_filter(filter).await)
3445 }
3446
3447 pub async fn new_pending_transaction_filter(&self, full: bool) -> Result<String> {
3451 node_info!("eth_newPendingTransactionFilter");
3452 let filter = if full {
3453 EthFilter::FullPendingTransactions(self.full_pending_transactions_filter())
3454 } else {
3455 EthFilter::PendingTransactions(self.new_ready_transactions())
3456 };
3457 Ok(self.filters.add_filter(filter).await)
3458 }
3459
3460 pub async fn get_filter_changes(&self, id: &str) -> ResponseResult {
3464 node_info!("eth_getFilterChanges");
3465 self.filters.get_filter_changes(id).await
3466 }
3467
3468 pub async fn get_filter_logs(&self, id: &str) -> Result<Vec<Log>> {
3472 node_info!("eth_getFilterLogs");
3473 if let Some(filter) = self.filters.get_log_filter(id).await {
3474 self.backend.logs(filter).await
3475 } else {
3476 Err(BlockchainError::FilterNotFound)
3477 }
3478 }
3479
3480 pub async fn uninstall_filter(&self, id: &str) -> Result<bool> {
3482 node_info!("eth_uninstallFilter");
3483 Ok(self.filters.uninstall_filter(id).await.is_some())
3484 }
3485
3486 pub async fn raw_transaction(&self, hash: B256) -> Result<Option<Bytes>> {
3490 node_info!("debug_getRawTransaction");
3491 self.inner_raw_transaction(hash).await
3492 }
3493
3494 pub async fn raw_receipts(&self, block: BlockId) -> Result<Vec<Bytes>> {
3498 node_info!("debug_getRawReceipts");
3499
3500 if let BlockRequest::Number(number) = self.block_request(Some(block)).await?
3502 && let Some(fork) = self.get_fork()
3503 && fork.predates_fork_inclusive(number)
3504 {
3505 let receipts = fork.block_receipts(number).await?.unwrap_or_default();
3506 return Ok(receipts
3507 .into_iter()
3508 .map(|receipt| {
3509 receipt.0.inner.inner.map_logs(|log| log.inner).encoded_2718().into()
3510 })
3511 .collect());
3512 }
3513
3514 let block = self.backend.get_block(block).ok_or(BlockchainError::BlockNotFound)?;
3515 let receipts = self
3516 .backend
3517 .mined_receipts(block.header.hash_slow())
3518 .ok_or(BlockchainError::BlockNotFound)?;
3519 Ok(receipts.into_iter().map(|receipt| receipt.encoded_2718().into()).collect())
3520 }
3521
3522 pub async fn raw_transactions(&self, block: BlockId) -> Result<Vec<Bytes>> {
3526 node_info!("debug_getRawTransactions");
3527
3528 if let Some(block) = self.backend.get_block(block) {
3529 return Ok(block
3530 .body
3531 .transactions
3532 .into_iter()
3533 .map(|tx| tx.into_inner().into_canonical().encoded_2718().into())
3534 .collect());
3535 }
3536
3537 let Some(fork) = self.get_fork() else {
3540 return Ok(Vec::new());
3541 };
3542 let block = match block {
3543 BlockId::Number(BlockNumber::Pending) => None,
3544 BlockId::Number(number) => {
3545 let number = self.backend.convert_block_number(Some(number));
3546 if !fork.predates_fork_inclusive(number) {
3547 return Ok(Vec::new());
3548 }
3549 fork.block_by_number_full(number).await?
3550 }
3551 BlockId::Hash(hash) => fork
3552 .block_by_hash_full(hash.block_hash)
3553 .await?
3554 .filter(|block| fork.predates_fork_inclusive(block.header().number())),
3555 };
3556 let Some(block) = block else {
3557 return Ok(Vec::new());
3558 };
3559 let BlockTransactions::Full(txs) = block.transactions() else {
3560 return Err(BlockchainError::Internal(
3561 "fork provider returned a non-full block for a full block request".to_string(),
3562 ));
3563 };
3564 Ok(txs.iter().map(|tx| tx.as_ref().encoded_2718().into()).collect())
3565 }
3566
3567 pub async fn raw_header(&self, block: BlockId) -> Result<Bytes> {
3571 node_info!("debug_getRawHeader");
3572 let block = self.backend.get_block(block).ok_or(BlockchainError::BlockNotFound)?;
3573 Ok(alloy_rlp::encode(&block.header).into())
3574 }
3575
3576 pub async fn raw_block(&self, block: BlockId) -> Result<Bytes> {
3580 node_info!("debug_getRawBlock");
3581 let block = self.backend.get_block(block).ok_or(BlockchainError::BlockNotFound)?;
3582 Ok(alloy_rlp::encode(canonical_block(block)).into())
3583 }
3584
3585 pub async fn raw_transaction_by_block_hash_and_index(
3589 &self,
3590 block_hash: B256,
3591 index: Index,
3592 ) -> Result<Option<Bytes>> {
3593 node_info!("eth_getRawTransactionByBlockHashAndIndex");
3594 match self.backend.transaction_by_block_hash_and_index(block_hash, index).await? {
3595 Some(tx) => self.inner_raw_transaction(tx.tx_hash()).await,
3596 None => Ok(None),
3597 }
3598 }
3599
3600 pub async fn raw_transaction_by_block_number_and_index(
3604 &self,
3605 block_number: BlockNumber,
3606 index: Index,
3607 ) -> Result<Option<Bytes>> {
3608 node_info!("eth_getRawTransactionByBlockNumberAndIndex");
3609 match self.backend.transaction_by_block_number_and_index(block_number, index).await? {
3610 Some(tx) => self.inner_raw_transaction(tx.tx_hash()).await,
3611 None => Ok(None),
3612 }
3613 }
3614
3615 pub async fn debug_trace_transaction(
3619 &self,
3620 tx_hash: B256,
3621 opts: GethDebugTracingOptions,
3622 ) -> Result<GethTrace> {
3623 node_info!("debug_traceTransaction");
3624 self.backend.debug_trace_transaction(tx_hash, opts).await
3625 }
3626
3627 pub async fn debug_trace_block(
3631 &self,
3632 rlp_block: Bytes,
3633 opts: GethDebugTracingOptions,
3634 ) -> Result<Vec<TraceResult>> {
3635 node_info!("debug_traceBlock");
3636 self.backend.debug_trace_block(rlp_block, opts).await
3637 }
3638
3639 pub async fn debug_trace_block_by_hash(
3643 &self,
3644 block_hash: B256,
3645 opts: GethDebugTracingOptions,
3646 ) -> Result<Vec<TraceResult>> {
3647 node_info!("debug_traceBlockByHash");
3648 self.backend.debug_trace_block_by_hash(block_hash, opts).await
3649 }
3650
3651 pub async fn debug_trace_block_by_number(
3655 &self,
3656 block_number: BlockNumber,
3657 opts: GethDebugTracingOptions,
3658 ) -> Result<Vec<TraceResult>> {
3659 node_info!("debug_traceBlockByNumber");
3660 self.backend.debug_trace_block_by_number(block_number, opts).await
3661 }
3662
3663 pub async fn debug_trace_call(
3667 &self,
3668 request: WithOtherFields<TransactionRequest>,
3669 block_number: Option<BlockId>,
3670 opts: GethDebugTracingCallOptions,
3671 ) -> Result<GethTrace> {
3672 node_info!("debug_traceCall");
3673 let block_request = self.block_request(block_number).await?;
3674 let fees = FeeDetails::new(
3675 request.gas_price,
3676 request.max_fee_per_gas,
3677 request.max_priority_fee_per_gas,
3678 request.max_fee_per_blob_gas,
3679 )?
3680 .or_zero_fees();
3681
3682 let result: std::result::Result<GethTrace, BlockchainError> =
3683 self.backend.call_with_tracing(request, fees, Some(block_request), opts).await;
3684 result
3685 }
3686
3687 pub async fn trace_call_many(
3691 &self,
3692 calls: Vec<(WithOtherFields<TransactionRequest>, HashSet<TraceType>)>,
3693 block_number: Option<BlockId>,
3694 ) -> Result<Vec<TraceResults>> {
3695 node_info!("trace_callMany");
3696 let block_number = block_number.unwrap_or(BlockId::Number(BlockNumber::Pending));
3697 let block_request = self.block_request(Some(block_number)).await?;
3698
3699 self.backend.trace_call_many(calls, Some(block_request)).await
3700 }
3701}
3702
3703impl EthApi<FoundryNetwork> {
3706 pub async fn anvil_mine(&self, num_blocks: Option<U256>, interval: Option<U256>) -> Result<()> {
3710 node_info!("anvil_mine");
3711 let interval = interval.map(|i| i.saturating_to::<u64>());
3712 let blocks = num_blocks.unwrap_or(U256::from(1));
3713 if blocks.is_zero() {
3714 return Ok(());
3715 }
3716
3717 self.on_blocking_task(|this| async move {
3718 for _ in 0..blocks.saturating_to::<u64>() {
3720 let pending_increase =
3722 interval.map(|interval| this.backend.time().apply_time_increase(interval));
3723 if let Err(error) = this.mine_one().await {
3724 if let Some(pending) = pending_increase {
3725 this.backend.time().revert_time_increase(pending);
3726 }
3727 return Err(error);
3728 }
3729 }
3730 Ok(())
3731 })
3732 .await?;
3733
3734 Ok(())
3735 }
3736
3737 async fn find_erc20_storage_slot(
3754 &self,
3755 token_address: Address,
3756 calldata: Bytes,
3757 expected_value: U256,
3758 ) -> Result<B256> {
3759 let tx = TransactionRequest::default().with_to(token_address).with_input(calldata.clone());
3760
3761 let access_list_result =
3763 self.create_access_list(WithOtherFields::new(tx.clone()), None, None).await?;
3764 let access_list = access_list_result.access_list;
3765
3766 for item in access_list.0 {
3769 if item.address != token_address {
3770 continue;
3771 };
3772 for slot in &item.storage_keys {
3773 let account_override = AccountOverride::default().with_state_diff(std::iter::once(
3774 (*slot, B256::from(expected_value.to_be_bytes())),
3775 ));
3776
3777 let state_override = StateOverridesBuilder::default()
3778 .append(token_address, account_override)
3779 .build();
3780
3781 let evm_override = EvmOverrides::state(Some(state_override));
3782
3783 let Ok(result) =
3784 self.call(WithOtherFields::new(tx.clone()), None, evm_override).await
3785 else {
3786 continue;
3788 };
3789
3790 let Ok(result_value) = U256::abi_decode(&result) else {
3791 continue;
3793 };
3794
3795 if result_value == expected_value {
3796 return Ok(*slot);
3797 }
3798 }
3799 }
3800
3801 Err(BlockchainError::Message("Unable to find storage slot".to_string()))
3802 }
3803
3804 pub async fn anvil_deal_erc20(
3808 &self,
3809 address: Address,
3810 token_address: Address,
3811 balance: U256,
3812 ) -> Result<()> {
3813 node_info!("anvil_dealERC20");
3814
3815 if self.backend.is_tempo()
3816 && self.backend.try_set_tip20_balance(address, token_address, balance).await?
3817 {
3818 return Ok(());
3819 }
3820
3821 sol! {
3822 #[sol(rpc)]
3823 contract IERC20 {
3824 function balanceOf(address target) external view returns (uint256);
3825 }
3826 }
3827
3828 let calldata = IERC20::balanceOfCall { target: address }.abi_encode().into();
3829
3830 let slot =
3832 self.find_erc20_storage_slot(token_address, calldata, balance).await.map_err(|_| {
3833 BlockchainError::Message("Unable to set ERC20 balance, no slot found".to_string())
3834 })?;
3835
3836 self.anvil_set_storage_at(
3838 token_address,
3839 U256::from_be_bytes(slot.0),
3840 B256::from(balance.to_be_bytes()),
3841 )
3842 .await?;
3843
3844 Ok(())
3845 }
3846
3847 pub async fn anvil_deal_tip20(
3851 &self,
3852 address: Address,
3853 token_address: Address,
3854 balance: U256,
3855 ) -> Result<()> {
3856 node_info!("anvil_dealTIP20");
3857 self.ensure_tempo_mode()?;
3858 self.backend.set_tip20_balance(address, token_address, balance).await?;
3859 Ok(())
3860 }
3861
3862 pub async fn anvil_set_erc20_allowance(
3866 &self,
3867 owner: Address,
3868 spender: Address,
3869 token_address: Address,
3870 amount: U256,
3871 ) -> Result<()> {
3872 node_info!("anvil_setERC20Allowance");
3873
3874 sol! {
3875 #[sol(rpc)]
3876 contract IERC20 {
3877 function allowance(address owner, address spender) external view returns (uint256);
3878 }
3879 }
3880
3881 let calldata = IERC20::allowanceCall { owner, spender }.abi_encode().into();
3882
3883 let slot =
3885 self.find_erc20_storage_slot(token_address, calldata, amount).await.map_err(|_| {
3886 BlockchainError::Message("Unable to set ERC20 allowance, no slot found".to_string())
3887 })?;
3888
3889 self.anvil_set_storage_at(
3891 token_address,
3892 U256::from_be_bytes(slot.0),
3893 B256::from(amount.to_be_bytes()),
3894 )
3895 .await?;
3896
3897 Ok(())
3898 }
3899
3900 pub async fn anvil_reorg(&self, options: ReorgOptions) -> Result<()> {
3914 node_info!("anvil_reorg");
3915 let depth = options.depth;
3916 let tx_block_pairs = options.tx_block_pairs;
3917
3918 let current_height = self.backend.best_number();
3920 let common_height = current_height.checked_sub(depth).ok_or(BlockchainError::RpcError(
3921 RpcError::invalid_params(format!(
3922 "Reorg depth must not exceed current chain height: current height {current_height}, depth {depth}"
3923 )),
3924 ))?;
3925
3926 let common_block =
3928 self.backend.get_block(common_height).ok_or(BlockchainError::BlockNotFound)?;
3929
3930 let block_pool_txs = if tx_block_pairs.is_empty() {
3933 HashMap::default()
3934 } else {
3935 let mut pairs = tx_block_pairs;
3936
3937 if let Some((_, num)) = pairs.iter().find(|(_, num)| *num >= depth) {
3939 return Err(BlockchainError::RpcError(RpcError::invalid_params(format!(
3940 "Block number for reorg tx will exceed the reorged chain height. Block number {num} must not exceed (depth-1) {}",
3941 depth - 1
3942 ))));
3943 }
3944
3945 pairs.sort_by_key(|a| a.1);
3947
3948 let mut nonces: HashMap<Address, u64> = HashMap::default();
3951
3952 let mut txs: HashMap<u64, Vec<Arc<PoolTransaction<FoundryTxEnvelope>>>> =
3953 HashMap::default();
3954 for pair in pairs {
3955 let (tx_data, block_index) = pair;
3956
3957 let pending = match tx_data {
3958 TransactionData::Raw(bytes) => {
3959 let mut data = bytes.as_ref();
3960 let decoded = FoundryTxEnvelope::decode_2718(&mut data)
3961 .map_err(|_| BlockchainError::FailedToDecodeSignedTransaction)?;
3962 PendingTransaction::new(decoded)?
3963 }
3964
3965 TransactionData::JSON(request) => {
3966 let from = request.from.map(Ok).unwrap_or_else(|| {
3967 self.accounts()?
3968 .first()
3969 .copied()
3970 .ok_or(BlockchainError::NoSignerAvailable)
3971 })?;
3972
3973 let curr_nonce = nonces.entry(from).or_insert(
3975 self.get_transaction_count(
3976 from,
3977 Some(common_block.header.number().into()),
3978 )
3979 .await?,
3980 );
3981
3982 let typed_tx = self.build_tx_request(request.into(), *curr_nonce).await?;
3984
3985 *curr_nonce += 1;
3987
3988 if self.is_impersonated(from) {
3990 let transaction = typed_tx.into_impersonated();
3991 self.ensure_typed_transaction_supported(&transaction)?;
3992 PendingTransaction::with_impersonated(transaction, from)
3993 } else {
3994 let transaction = self.sign_request(&from, typed_tx)?;
3995 self.ensure_typed_transaction_supported(&transaction)?;
3996 PendingTransaction::new(transaction)?
3997 }
3998 }
3999 };
4000
4001 let pooled = PoolTransaction::new(pending).with_replay();
4002 txs.entry(block_index).or_default().push(Arc::new(pooled));
4003 }
4004
4005 txs
4006 };
4007
4008 self.backend.reorg(depth, block_pool_txs, common_block).await?;
4009 Ok(())
4010 }
4011
4012 pub async fn evm_mine(&self, opts: Option<MineOptions>) -> Result<String> {
4019 node_info!("evm_mine");
4020
4021 self.do_evm_mine(opts).await?;
4022
4023 Ok("0x0".to_string())
4024 }
4025
4026 pub async fn evm_mine_detailed(&self, opts: Option<MineOptions>) -> Result<Vec<AnyRpcBlock>> {
4036 node_info!("evm_mine_detailed");
4037
4038 let mined_blocks = self.do_evm_mine(opts).await?;
4039
4040 let mut blocks = Vec::with_capacity(mined_blocks as usize);
4041
4042 let latest = self.backend.best_number();
4043 for offset in (0..mined_blocks).rev() {
4044 let block_num = latest - offset;
4045 if let Some(mut block) =
4046 self.backend.block_by_number_full(BlockNumber::Number(block_num)).await?
4047 {
4048 let block_txs = match block.transactions_mut() {
4049 BlockTransactions::Full(txs) => txs,
4050 BlockTransactions::Hashes(_) | BlockTransactions::Uncle => unreachable!(),
4051 };
4052 for tx in block_txs.iter_mut() {
4053 if let Some(receipt) = self.backend.mined_transaction_receipt(tx.tx_hash())
4054 && let Some(output) = receipt.out
4055 {
4056 if !receipt.inner.as_ref().status()
4058 && let Some(reason) = RevertDecoder::new().maybe_decode(&output, None)
4059 {
4060 tx.other.insert(
4061 "revertReason".to_string(),
4062 serde_json::to_value(reason).expect("Infallible"),
4063 );
4064 }
4065 tx.other.insert(
4066 "output".to_string(),
4067 serde_json::to_value(output).expect("Infallible"),
4068 );
4069 }
4070 }
4071 block.transactions = BlockTransactions::Full(block_txs.clone());
4072 blocks.push(block);
4073 }
4074 }
4075
4076 Ok(blocks)
4077 }
4078
4079 pub async fn eth_send_unsigned_transaction(
4083 &self,
4084 request: WithOtherFields<TransactionRequest>,
4085 ) -> Result<TxHash> {
4086 node_info!("eth_sendUnsignedTransaction");
4087 let request = self.parse_transaction_request(request)?;
4088 let from = request.from().ok_or(BlockchainError::NoSignerAvailable)?;
4090
4091 let (nonce, on_chain_nonce) = self.request_nonce_for_transaction(&request, from).await?;
4092
4093 let typed_tx = self.build_tx_request(request, nonce).await?;
4094
4095 let transaction = typed_tx.into_impersonated();
4096
4097 self.ensure_typed_transaction_supported(&transaction)?;
4098
4099 let pending_transaction = PendingTransaction::with_impersonated(transaction, from);
4100
4101 self.backend.validate_pool_transaction(&pending_transaction).await?;
4103
4104 let (requires, provides) = nonce_markers(&pending_transaction, nonce, on_chain_nonce, from);
4105
4106 self.add_pending_transaction(pending_transaction, requires, provides)
4107 }
4108
4109 pub async fn txpool_inspect(&self) -> Result<TxpoolInspect> {
4116 node_info!("txpool_inspect");
4117 let mut inspect = TxpoolInspect::default();
4118
4119 fn convert(tx: Arc<PoolTransaction<FoundryTxEnvelope>>) -> TxpoolInspectSummary {
4120 let tx = &tx.pending_transaction.transaction;
4121 let to = tx.to();
4122 let gas_price = tx.max_fee_per_gas();
4123 let value = tx.value();
4124 let gas = tx.gas_limit();
4125 TxpoolInspectSummary { to, value, gas, gas_price }
4126 }
4127
4128 for pending in self.pool.ready_transactions() {
4135 let entry = inspect.pending.entry(*pending.pending_transaction.sender()).or_default();
4136 let key = txpool_transaction_key(&pending.pending_transaction);
4137 entry.insert(key, convert(pending));
4138 }
4139 for queued in self.pool.pending_transactions() {
4140 let entry = inspect.queued.entry(*queued.pending_transaction.sender()).or_default();
4141 let key = txpool_transaction_key(&queued.pending_transaction);
4142 entry.insert(key, convert(queued));
4143 }
4144 Ok(inspect)
4145 }
4146
4147 pub async fn txpool_content(&self) -> Result<TxpoolContent<AnyRpcTransaction>> {
4154 node_info!("txpool_content");
4155 self.build_txpool_content(None)
4156 }
4157
4158 fn build_txpool_content(
4163 &self,
4164 filter: Option<Address>,
4165 ) -> Result<TxpoolContent<AnyRpcTransaction>> {
4166 let mut content = TxpoolContent::<AnyRpcTransaction>::default();
4167 fn convert(tx: Arc<PoolTransaction<FoundryTxEnvelope>>) -> Result<AnyRpcTransaction> {
4168 let from = *tx.pending_transaction.sender();
4169 let tx = transaction_build(
4170 Some(tx.hash()),
4171 tx.pending_transaction.transaction.clone(),
4172 None,
4173 None,
4174 None,
4175 );
4176
4177 let WithOtherFields { inner: mut tx, other } = tx.0;
4178
4179 tx.inner = Recovered::new_unchecked(tx.inner.into_inner(), from);
4182
4183 let tx = AnyRpcTransaction(WithOtherFields { inner: tx, other });
4184
4185 Ok(tx)
4186 }
4187
4188 for pending in self.pool.ready_transactions() {
4189 let sender = *pending.pending_transaction.sender();
4190 if filter.is_some_and(|from| from != sender) {
4191 continue;
4192 }
4193 let entry = content.pending.entry(sender).or_default();
4194 let key = txpool_transaction_key(&pending.pending_transaction);
4195 entry.insert(key, convert(pending)?);
4196 }
4197 for queued in self.pool.pending_transactions() {
4198 let sender = *queued.pending_transaction.sender();
4199 if filter.is_some_and(|from| from != sender) {
4200 continue;
4201 }
4202 let entry = content.queued.entry(sender).or_default();
4203 let key = txpool_transaction_key(&queued.pending_transaction);
4204 entry.insert(key, convert(queued)?);
4205 }
4206
4207 Ok(content)
4208 }
4209
4210 pub async fn txpool_content_from(
4218 &self,
4219 from: Address,
4220 ) -> Result<TxpoolContentFrom<AnyRpcTransaction>> {
4221 node_info!("txpool_contentFrom");
4222 let mut content = self.build_txpool_content(Some(from))?;
4223 Ok(content.remove_from(&from))
4224 }
4225}
4226
4227impl EthApi<FoundryNetwork> {
4228 async fn do_evm_mine(&self, opts: Option<MineOptions>) -> Result<u64> {
4230 let mut blocks_to_mine = 1u64;
4231
4232 if let Some(opts) = opts {
4233 let timestamp = match opts {
4234 MineOptions::Timestamp(timestamp) => timestamp,
4235 MineOptions::Options { timestamp, blocks } => {
4236 if let Some(blocks) = blocks {
4237 blocks_to_mine = blocks;
4238 }
4239 timestamp
4240 }
4241 };
4242 if let Some(timestamp) = timestamp {
4243 self.evm_set_next_block_timestamp(timestamp)?;
4245 }
4246 }
4247
4248 self.on_blocking_task(|this| async move {
4251 for _ in 0..blocks_to_mine {
4253 this.mine_one().await?;
4254 }
4255 Ok(())
4256 })
4257 .await?;
4258
4259 Ok(blocks_to_mine)
4260 }
4261
4262 async fn do_estimate_gas(
4263 &self,
4264 request: WithOtherFields<TransactionRequest>,
4265 block_number: Option<BlockId>,
4266 overrides: EvmOverrides,
4267 ) -> Result<u128> {
4268 let block_request = self.block_request(block_number).await?;
4269 if let BlockRequest::Number(number) = block_request
4271 && let Some(fork) = self.get_fork()
4272 && fork.predates_fork(number)
4273 {
4274 if overrides.has_state() || overrides.has_block() {
4275 return Err(BlockchainError::EvmOverrideError(
4276 "not available on past forked blocks".to_string(),
4277 ));
4278 }
4279 return Ok(fork.estimate_gas_raw(&request, Some(number.into())).await?);
4280 }
4281
4282 self.on_blocking_task(|this| async move {
4285 let request = this.parse_transaction_request(request)?;
4286 this.backend
4287 .with_database_at(Some(block_request), |state, mut block| {
4288 let mut cache_db = CacheDB::new(state);
4289 if let Some(state_overrides) = overrides.state {
4290 apply_state_overrides(
4291 state_overrides.into_iter().collect(),
4292 &mut cache_db,
4293 )?;
4294 }
4295 if let Some(block_overrides) = overrides.block {
4296 cache_db.apply_block_overrides(*block_overrides, &mut block);
4297 }
4298 this.do_estimate_gas_with_state(request, &cache_db, block)
4299 })
4300 .await?
4301 })
4302 .await
4303 }
4304
4305 async fn do_estimate_gas_typed(
4306 &self,
4307 request: FoundryTransactionRequest,
4308 block_number: Option<BlockId>,
4309 ) -> Result<u128> {
4310 let block_request = self.block_request(block_number).await?;
4311 self.on_blocking_task(|this| async move {
4312 this.backend
4313 .with_database_at(Some(block_request), |state, block| {
4314 this.do_estimate_gas_with_state(request, &state, block)
4315 })
4316 .await?
4317 })
4318 .await
4319 }
4320
4321 fn transaction_priority(&self, tx: &FoundryTxEnvelope) -> TransactionPriority {
4323 self.transaction_order.read().priority(tx)
4324 }
4325
4326 pub fn full_pending_transactions(&self) -> UnboundedReceiver<AnyRpcTransaction> {
4328 let (tx, rx) = unbounded_channel();
4329 let mut hashes = self.new_ready_transactions();
4330
4331 let this = self.clone();
4332
4333 tokio::spawn(async move {
4334 while let Some(hash) = hashes.next().await {
4335 if let Ok(Some(txn)) = this.transaction_by_hash(hash).await
4336 && tx.send(txn).is_err()
4337 {
4338 break;
4339 }
4340 }
4341 });
4342
4343 rx
4344 }
4345
4346 pub fn full_pending_transactions_filter(&self) -> mpsc::Receiver<AnyRpcTransaction> {
4351 let (tx, rx) = mpsc::channel(2048);
4353 let mut hashes = self.new_ready_transactions();
4354 let this = self.clone();
4355
4356 tokio::spawn(async move {
4357 while let Some(hash) = hashes.next().await {
4358 if let Ok(Some(txn)) = this.transaction_by_hash(hash).await
4359 && tx.send(txn).await.is_err()
4360 {
4361 break;
4362 }
4363 }
4364 });
4365
4366 rx
4367 }
4368
4369 pub fn transaction_receipts_subscription(
4371 &self,
4372 filter: TransactionReceiptsParams,
4373 ) -> UnboundedReceiver<Vec<FoundryTxReceipt>> {
4374 let (tx, rx) = unbounded_channel();
4375 let mut blocks = self.new_block_notifications();
4376 let this = self.clone();
4377
4378 tokio::spawn(async move {
4379 let hash_filter = filter
4381 .transaction_hashes
4382 .filter(|hashes| !hashes.is_empty())
4383 .map(|hashes| hashes.into_iter().collect::<std::collections::HashSet<_>>());
4384
4385 loop {
4386 let notification = tokio::select! {
4387 biased;
4388 _ = tx.closed() => break,
4390 maybe_block = blocks.next() => match maybe_block {
4391 Some(block) => block,
4392 None => break,
4393 },
4394 };
4395
4396 let Some(block) = notification.as_new_block() else {
4397 continue;
4398 };
4399
4400 let receipts = match this.block_receipts(BlockId::Hash(block.hash.into())).await {
4401 Ok(Some(mut receipts)) => {
4402 if let Some(hashes) = &hash_filter {
4403 receipts.retain(|receipt| hashes.contains(&receipt.transaction_hash()));
4404 }
4405 receipts
4406 }
4407 Ok(None) => continue,
4408 Err(err) => {
4409 trace!(target: "node", %err, "failed to build block receipts for subscription");
4410 continue;
4411 }
4412 };
4413
4414 if receipts.is_empty() {
4415 continue;
4416 }
4417
4418 if tx.send(receipts).is_err() {
4419 break;
4420 }
4421 }
4422 });
4423
4424 rx
4425 }
4426
4427 pub async fn mine_one(&self) -> Result<()> {
4429 let transactions = self.pool.ready_transactions().collect::<Vec<_>>();
4430 let outcome = self.backend.mine_block(transactions).await?;
4431
4432 trace!(target: "node", blocknumber = ?outcome.block_number, "mined block");
4433 self.pool.on_mined_block(outcome);
4434 Ok(())
4435 }
4436
4437 async fn pending_block(&self) -> AnyRpcBlock {
4439 let transactions = self.pool.ready_transactions().collect::<Vec<_>>();
4440 let info = self.backend.pending_block(transactions).await;
4441 self.backend.convert_block(info.block)
4442 }
4443
4444 async fn pending_block_full(&self) -> Option<AnyRpcBlock> {
4446 let transactions = self.pool.ready_transactions().collect::<Vec<_>>();
4447 let BlockInfo { block, transactions, receipts: _ } =
4448 self.backend.pending_block(transactions).await;
4449
4450 let mut partial_block = self.backend.convert_block(block.clone());
4451
4452 let mut block_transactions = Vec::with_capacity(block.body.transactions.len());
4453 let base_fee = self.backend.base_fee();
4454
4455 for info in transactions {
4456 let tx = block.body.transactions.get(info.transaction_index as usize)?.clone();
4457
4458 let tx = transaction_build(
4459 Some(info.transaction_hash),
4460 tx,
4461 Some(&block),
4462 Some(info),
4463 Some(base_fee),
4464 );
4465 block_transactions.push(tx);
4466 }
4467
4468 partial_block.transactions = BlockTransactions::from(block_transactions);
4469
4470 Some(partial_block)
4471 }
4472
4473 async fn build_tx_request(
4476 &self,
4477 mut request: FoundryTransactionRequest,
4478 nonce: u64,
4479 ) -> Result<FoundryTypedTx> {
4480 let from = request.from().or(self.accounts()?.first().copied());
4481 if let Some(from) = from {
4482 request.set_from(from);
4483 }
4484
4485 request.chain_id().is_none().then(|| request.set_chain_id(self.chain_id()));
4487 request.nonce().is_none().then(|| request.set_nonce(nonce));
4488 let is_tempo_batch =
4489 matches!(&request, FoundryTransactionRequest::Tempo(tx) if !tx.calls.is_empty());
4490 if request.kind().is_none() && !is_tempo_batch {
4491 request.set_kind(TxKind::default());
4492 }
4493 if request.gas_limit().is_none() {
4494 let fallback_gas_limit = {
4495 let evm_env = self.backend.evm_env().read();
4496 let block_gas_limit = evm_env.block_env.gas_limit;
4497 if evm_env.cfg_env.tx_gas_limit_cap.is_none() {
4498 block_gas_limit.min(evm_env.cfg_env().tx_gas_limit_cap())
4499 } else {
4500 block_gas_limit
4501 }
4502 };
4503 let estimated_gas = self
4504 .do_estimate_gas_typed(request.clone(), None)
4505 .await
4506 .map(|v| v as u64)
4507 .unwrap_or_else(|_| {
4508 if is_simple_transfer_request(request.as_ref()) {
4509 MIN_TRANSACTION_GAS as u64
4510 } else {
4511 fallback_gas_limit
4512 }
4513 });
4514 request.set_gas_limit(estimated_gas);
4515 }
4516
4517 if let Err((tx_type, _)) = request.missing_keys() {
4519 if matches!(tx_type, FoundryTxType::Legacy | FoundryTxType::Eip2930) {
4520 request.gas_price().is_none().then(|| request.set_gas_price(self.gas_price()));
4521 }
4522 if tx_type == FoundryTxType::Eip2930 {
4523 request
4524 .access_list()
4525 .is_none()
4526 .then(|| request.set_access_list(Default::default()));
4527 }
4528 if matches!(
4529 tx_type,
4530 FoundryTxType::Eip1559
4531 | FoundryTxType::Eip4844
4532 | FoundryTxType::Eip7702
4533 | FoundryTxType::Tempo
4534 ) {
4535 request
4536 .max_fee_per_gas()
4537 .is_none()
4538 .then(|| request.set_max_fee_per_gas(self.gas_price()));
4539 request
4540 .max_priority_fee_per_gas()
4541 .is_none()
4542 .then(|| request.set_max_priority_fee_per_gas(MIN_SUGGESTED_PRIORITY_FEE));
4543 }
4544 if tx_type == FoundryTxType::Eip4844 {
4545 request.as_ref().max_fee_per_blob_gas().is_none().then(|| {
4546 request.as_mut().set_max_fee_per_blob_gas(
4547 self.backend.fees().get_next_block_blob_base_fee_per_gas(),
4548 )
4549 });
4550 }
4551 }
4552
4553 match request
4554 .build_unsigned()
4555 .map_err(|e| BlockchainError::InvalidTransactionRequest(e.to_string()))?
4556 {
4557 FoundryTypedTx::Eip4844(TxEip4844Variant::TxEip4844(_))
4558 if !self.backend.skip_blob_validation(from) =>
4559 {
4560 Err(BlockchainError::FailedToDecodeTransaction)
4562 }
4563 res => Ok(res),
4564 }
4565 }
4566
4567 async fn get_transaction_count(
4569 &self,
4570 address: Address,
4571 block_number: Option<BlockId>,
4572 ) -> Result<u64> {
4573 let block_request = self.block_request(block_number).await?;
4574
4575 if let BlockRequest::Number(number) = block_request
4576 && let Some(fork) = self.get_fork()
4577 && fork.predates_fork(number)
4578 {
4579 return Ok(fork.get_nonce(address, number).await?);
4580 }
4581
4582 self.backend.get_nonce(address, block_request).await
4583 }
4584
4585 async fn request_nonce(
4593 &self,
4594 request: &TransactionRequest,
4595 from: Address,
4596 ) -> Result<(u64, u64)> {
4597 let highest_nonce =
4598 self.get_transaction_count(from, Some(BlockId::Number(BlockNumber::Pending))).await?;
4599 let nonce = request.nonce.unwrap_or(highest_nonce);
4600
4601 Ok((nonce, highest_nonce))
4602 }
4603
4604 fn add_pending_transaction(
4606 &self,
4607 pending_transaction: PendingTransaction<FoundryTxEnvelope>,
4608 requires: Vec<TxMarker>,
4609 provides: Vec<TxMarker>,
4610 ) -> Result<TxHash> {
4611 debug_assert!(requires != provides);
4612 let from = *pending_transaction.sender();
4613 let priority = self.transaction_priority(&pending_transaction.transaction);
4614 let pool_transaction =
4615 PoolTransaction { requires, provides, pending_transaction, priority, is_replay: false };
4616 let tx = self.pool.add_transaction(pool_transaction)?;
4617 trace!(target: "node", "Added transaction: [{:?}] sender={:?}", tx.hash(), from);
4618 Ok(*tx.hash())
4619 }
4620
4621 fn ensure_typed_transaction_supported(&self, tx: &FoundryTxEnvelope) -> Result<()> {
4623 match &tx {
4624 FoundryTxEnvelope::Eip2930(_) => self.backend.ensure_eip2930_active(),
4625 FoundryTxEnvelope::Eip1559(_) => self.backend.ensure_eip1559_active(),
4626 FoundryTxEnvelope::Eip4844(_) => self.backend.ensure_eip4844_active(),
4627 FoundryTxEnvelope::Eip7702(_) => self.backend.ensure_eip7702_active(),
4628 #[cfg(feature = "optimism")]
4629 FoundryTxEnvelope::Deposit(_) => self.backend.ensure_op_deposits_active(),
4630 #[cfg(feature = "optimism")]
4631 FoundryTxEnvelope::PostExec(_) => Err(BlockchainError::InvalidTransactionRequest(
4632 "not implemented for post-exec tx".to_string(),
4633 )),
4634 FoundryTxEnvelope::Legacy(_) => Ok(()),
4635 FoundryTxEnvelope::Tempo(_) => self.backend.ensure_tempo_active(),
4636 }
4637 }
4638
4639 pub async fn anvil_set_fee_token(&self, user: Address, token: Address) -> Result<()> {
4645 node_info!("anvil_setFeeToken");
4646 self.ensure_tempo_mode()?;
4647 self.backend.set_fee_token(user, token).await?;
4648 Ok(())
4649 }
4650
4651 pub async fn anvil_set_validator_fee_token(
4657 &self,
4658 validator: Address,
4659 token: Address,
4660 ) -> Result<()> {
4661 node_info!("anvil_setValidatorFeeToken");
4662 self.ensure_tempo_mode()?;
4663 self.backend.set_validator_fee_token(validator, token).await?;
4664 Ok(())
4665 }
4666
4667 pub async fn anvil_set_fee_amm_liquidity(
4673 &self,
4674 user_token: Address,
4675 validator_token: Address,
4676 amount: U256,
4677 ) -> Result<()> {
4678 node_info!("anvil_setFeeAmmLiquidity");
4679 self.ensure_tempo_mode()?;
4680 self.backend.set_fee_amm_liquidity(user_token, validator_token, amount).await?;
4681 Ok(())
4682 }
4683
4684 fn ensure_tempo_mode(&self) -> Result<()> {
4686 if self.backend.is_tempo() { Ok(()) } else { Err(BlockchainError::RpcUnimplemented) }
4687 }
4688
4689 fn parse_transaction_request(
4690 &self,
4691 request: WithOtherFields<TransactionRequest>,
4692 ) -> Result<FoundryTransactionRequest> {
4693 self.backend.parse_transaction_request(request)
4694 }
4695
4696 async fn request_nonce_for_transaction(
4697 &self,
4698 request: &FoundryTransactionRequest,
4699 from: Address,
4700 ) -> Result<(u64, u64)> {
4701 if let FoundryTransactionRequest::Tempo(request) = request
4702 && let Some(nonce_key) = request.nonce_key.filter(|key| !key.is_zero())
4703 {
4704 if let Some(nonce) = request.nonce() {
4705 return Ok((nonce, 0));
4706 }
4707 let nonce = self.backend.tempo_nonce(from, nonce_key, None).await?;
4708 return Ok((nonce, 0));
4709 }
4710 self.request_nonce(request.as_ref(), from).await
4711 }
4712}
4713
4714fn is_simple_transfer_request(request: &TransactionRequest) -> bool {
4715 request.to.as_ref().and_then(TxKind::to).is_some()
4716 && (request.input.input().is_none()
4717 || request.input.input().is_some_and(|data| data.is_empty()))
4718 && request.authorization_list.is_none()
4719 && request.access_list.is_none()
4720 && request.blob_versioned_hashes.is_none()
4721}
4722
4723fn required_marker(provided_nonce: u64, on_chain_nonce: u64, from: Address) -> Vec<TxMarker> {
4724 if provided_nonce == on_chain_nonce {
4725 return Vec::new();
4726 }
4727 let prev_nonce = provided_nonce.saturating_sub(1);
4728 if on_chain_nonce <= prev_nonce { vec![to_marker(prev_nonce, from)] } else { Vec::new() }
4729}
4730
4731fn tempo_parallel_nonce_markers(
4732 pending_transaction: &PendingTransaction<FoundryTxEnvelope>,
4733) -> Option<(Vec<TxMarker>, Vec<TxMarker>)> {
4734 pending_transaction
4737 .transaction
4738 .as_ref()
4739 .has_nonzero_tempo_nonce_key()
4740 .then(|| (vec![], vec![pending_transaction.hash().to_vec()]))
4741}
4742
4743fn nonce_markers(
4746 pending_transaction: &PendingTransaction<FoundryTxEnvelope>,
4747 nonce: u64,
4748 on_chain_nonce: u64,
4749 from: Address,
4750) -> (Vec<TxMarker>, Vec<TxMarker>) {
4751 tempo_parallel_nonce_markers(pending_transaction).unwrap_or_else(|| {
4752 (required_marker(nonce, on_chain_nonce, from), vec![to_marker(nonce, from)])
4753 })
4754}
4755
4756fn txpool_transaction_key(pending_transaction: &PendingTransaction<FoundryTxEnvelope>) -> String {
4757 match pending_transaction.transaction.as_ref() {
4758 FoundryTxEnvelope::Tempo(tx) if !tx.tx().nonce_key.is_zero() => {
4759 let tx = tx.tx();
4760 format!("{}:{}", tx.nonce_key, tx.nonce)
4761 }
4762 _ => pending_transaction.nonce().to_string(),
4763 }
4764}
4765
4766fn convert_transact_out(out: &Option<Output>) -> Bytes {
4767 match out {
4768 None => Default::default(),
4769 Some(Output::Call(out)) => out.to_vec().into(),
4770 Some(Output::Create(out, _)) => out.to_vec().into(),
4771 }
4772}
4773
4774fn ensure_return_ok(exit: InstructionResult, out: &Option<Output>) -> Result<Bytes> {
4776 let out = convert_transact_out(out);
4777 match exit {
4778 return_ok!() => Ok(out),
4779 return_revert!() => Err(InvalidTransactionError::Revert(Some(out)).into()),
4780 reason => Err(BlockchainError::EvmError(reason)),
4781 }
4782}
4783
4784fn execution_error(exit: InstructionResult) -> Option<String> {
4787 match SuccessOrHalt::<HaltReason>::from(exit) {
4788 SuccessOrHalt::Success(_) => None,
4789 SuccessOrHalt::Revert => Some("execution reverted".to_string()),
4790 SuccessOrHalt::Halt(reason) => Some(reason.to_string()),
4791 SuccessOrHalt::FatalExternalError => Some("fatal external error".to_string()),
4792 SuccessOrHalt::Internal(_) => Some("internal EVM error".to_string()),
4793 }
4794}
4795
4796fn determine_base_gas_by_kind(request: &FoundryTransactionRequest) -> u128 {
4798 let inner = request.as_ref();
4799 let kind = match request {
4800 FoundryTransactionRequest::Tempo(request) => {
4801 request.calls.first().map(|call| call.to).or_else(|| inner.kind())
4802 }
4803 _ => inner.kind(),
4804 };
4805 match kind {
4806 Some(TxKind::Call(_)) => {
4807 MIN_TRANSACTION_GAS
4808 + inner.authorization_list.as_ref().map_or(0, |auths_list| {
4809 auths_list.len() as u128 * PER_EMPTY_ACCOUNT_COST as u128
4810 })
4811 }
4812 Some(TxKind::Create) => MIN_CREATE_GAS,
4813 None => MIN_CREATE_GAS,
4815 }
4816}
4817
4818enum GasEstimationCallResult {
4820 Success(u128),
4821 OutOfGas,
4822 Revert(Option<Bytes>),
4823 EvmError(InstructionResult),
4824}
4825
4826impl TryFrom<Result<(InstructionResult, Option<Output>, u128, State)>> for GasEstimationCallResult {
4830 type Error = BlockchainError;
4831
4832 fn try_from(res: Result<(InstructionResult, Option<Output>, u128, State)>) -> Result<Self> {
4833 match res {
4834 Err(BlockchainError::InvalidTransaction(InvalidTransactionError::GasTooHigh(_))) => {
4836 Ok(Self::OutOfGas)
4837 }
4838 Err(BlockchainError::Message(ref msg))
4840 if msg.contains("insufficient gas for intrinsic cost") =>
4841 {
4842 Ok(Self::OutOfGas)
4843 }
4844 Err(err) => Err(err),
4845 Ok((exit, output, gas, _)) => match exit {
4846 return_ok!() => Ok(Self::Success(gas)),
4847
4848 InstructionResult::Revert => {
4850 Ok(Self::Revert(Some(output.map(|o| o.into_data()).unwrap_or_default())))
4851 }
4852 InstructionResult::CallTooDeep
4853 | InstructionResult::OutOfFunds
4854 | InstructionResult::CreateInitCodeStartingEF00
4855 | InstructionResult::InvalidEOFInitCode
4856 | InstructionResult::InvalidExtDelegateCallTarget => Ok(Self::EvmError(exit)),
4857
4858 InstructionResult::OutOfGas
4860 | InstructionResult::MemoryOOG
4861 | InstructionResult::MemoryLimitOOG
4862 | InstructionResult::PrecompileOOG
4863 | InstructionResult::InvalidOperandOOG
4864 | InstructionResult::ReentrancySentryOOG => Ok(Self::OutOfGas),
4865
4866 InstructionResult::OpcodeNotFound
4868 | InstructionResult::CallNotAllowedInsideStatic
4869 | InstructionResult::StateChangeDuringStaticCall
4870 | InstructionResult::InvalidFEOpcode
4871 | InstructionResult::InvalidJump
4872 | InstructionResult::NotActivated
4873 | InstructionResult::StackUnderflow
4874 | InstructionResult::StackOverflow
4875 | InstructionResult::OutOfOffset
4876 | InstructionResult::CreateCollision
4877 | InstructionResult::OverflowPayment
4878 | InstructionResult::PrecompileError
4879 | InstructionResult::NonceOverflow
4880 | InstructionResult::CreateContractSizeLimit
4881 | InstructionResult::CreateContractStartingWithEF
4882 | InstructionResult::CreateInitCodeSizeLimit
4883 | InstructionResult::InvalidImmediateEncoding
4884 | InstructionResult::FatalExternalError => Ok(Self::EvmError(exit)),
4885 },
4886 }
4887 }
4888}
4889
4890fn merge_pre_fork_fee_history(
4892 response: &mut FeeHistory,
4893 rewards: &mut Vec<Vec<u128>>,
4894 pre: FeeHistory,
4895 fork_block: u64,
4896) {
4897 response.oldest_block = pre.oldest_block;
4899 let count = fork_block.checked_sub(pre.oldest_block).map_or(0, |count| count.saturating_add(1))
4900 as usize;
4901
4902 response.base_fee_per_gas.extend(pre.base_fee_per_gas.into_iter().take(count));
4904 response.gas_used_ratio.extend(pre.gas_used_ratio.into_iter().take(count));
4905 if let Some(reward) = pre.reward {
4906 rewards.extend(reward.into_iter().take(count));
4907 }
4908
4909 response.base_fee_per_blob_gas.extend(pre.base_fee_per_blob_gas.into_iter().take(count));
4911 response.base_fee_per_blob_gas.resize(count, 0);
4912 response.blob_gas_used_ratio.extend(pre.blob_gas_used_ratio.into_iter().take(count));
4913 response.blob_gas_used_ratio.resize(count, 0.0);
4914}
4915
4916#[cfg(test)]
4917mod tests {
4918 use super::*;
4919 use crate::{NodeConfig, spawn};
4920
4921 #[tokio::test(flavor = "multi_thread")]
4923 async fn fee_history_is_complete_when_cache_entries_are_missing() {
4924 let (api, _handle) = spawn(NodeConfig::test()).await;
4925 let count = 10u64;
4926 api.anvil_mine(Some(U256::from(count)), None).await.unwrap();
4927
4928 tokio::time::timeout(Duration::from_secs(5), async {
4932 loop {
4933 if (1..=count).all(|number| api.fee_history_cache.lock().contains_key(&number)) {
4934 break;
4935 }
4936 tokio::task::yield_now().await;
4937 }
4938 })
4939 .await
4940 .unwrap();
4941 api.fee_history_cache.lock().clear();
4942
4943 let fee_history =
4944 api.fee_history(U256::from(count), BlockNumber::Latest, vec![50.0]).await.unwrap();
4945
4946 assert_eq!(fee_history.oldest_block, 1);
4947 assert_eq!(fee_history.gas_used_ratio.len(), count as usize);
4948 assert_eq!(fee_history.blob_gas_used_ratio.len(), count as usize);
4949 assert_eq!(fee_history.base_fee_per_gas.len(), count as usize + 1);
4950 assert_eq!(fee_history.base_fee_per_blob_gas.len(), count as usize + 1);
4951 let rewards = fee_history.reward.unwrap();
4952 assert_eq!(rewards.len(), count as usize);
4953 assert!(rewards.iter().all(|reward| reward.len() == 1));
4954 }
4955
4956 #[test]
4957 fn shortened_pre_fork_fee_history_uses_upstream_start() {
4958 let requested_lowest = 4;
4959 let fork_block = 10;
4960 let pre = FeeHistory {
4961 oldest_block: 5,
4962 base_fee_per_gas: vec![1; 7],
4963 gas_used_ratio: vec![0.0; 6],
4964 reward: Some(vec![vec![]; 6]),
4965 base_fee_per_blob_gas: vec![],
4966 blob_gas_used_ratio: vec![],
4967 };
4968
4969 let mut response = FeeHistory { oldest_block: requested_lowest, ..Default::default() };
4970 let mut rewards = Vec::new();
4971
4972 merge_pre_fork_fee_history(&mut response, &mut rewards, pre, fork_block);
4973
4974 assert_eq!(response.oldest_block, 5);
4975 assert_eq!(response.gas_used_ratio.len(), 6);
4976 assert_eq!(response.base_fee_per_gas.len(), 6);
4977 assert_eq!(response.blob_gas_used_ratio.len(), 6);
4978 assert_eq!(response.base_fee_per_blob_gas.len(), 6);
4979 assert_eq!(rewards.len(), 6);
4980 }
4981}