1use super::{
2 backend::mem::{BlockRequest, DatabaseRef, State},
3 sign::build_impersonated,
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::NewBlockNotifications,
13 validate::TransactionValidator,
14 },
15 error::{
16 BlockchainError, FeeHistoryError, InvalidTransactionError, Result, ToRpcResponseResult,
17 },
18 fees::{FeeDetails, FeeHistoryCache, MIN_SUGGESTED_PRIORITY_FEE},
19 macros::node_info,
20 miner::FixedBlockTimeMiner,
21 pool::{
22 Pool,
23 transactions::{
24 PoolTransaction, TransactionOrder, TransactionPriority, TxMarker, to_marker,
25 },
26 },
27 sign::{self, Signer},
28 },
29 filter::{EthFilter, Filters, LogsFilter},
30 mem::transaction_build,
31};
32use alloy_consensus::{
33 Blob, BlockHeader, Transaction, TrieAccount, TxEip4844Variant, transaction::Recovered,
34};
35use alloy_dyn_abi::TypedData;
36use alloy_eips::{
37 eip2718::Encodable2718,
38 eip7910::{EthConfig, EthForkConfig},
39};
40use alloy_evm::overrides::{OverrideBlockHashes, apply_state_overrides};
41use alloy_network::{
42 AnyRpcBlock, AnyRpcTransaction, BlockResponse, Network, ReceiptResponse, TransactionBuilder,
43 TransactionBuilder4844, TransactionResponse, eip2718::Decodable2718,
44};
45use alloy_primitives::{
46 Address, B64, B256, Bytes, TxHash, TxKind, U64, U256,
47 map::{HashMap, HashSet},
48};
49use alloy_rpc_types::{
50 AccessList, AccessListResult, BlockId, BlockNumberOrTag as BlockNumber, BlockTransactions,
51 EIP1186AccountProofResponse, FeeHistory, Filter, FilteredParams, Index, Log, Work,
52 anvil::{
53 ForkedNetwork, Forking, Metadata, MineOptions, NodeEnvironment, NodeForkConfig, NodeInfo,
54 },
55 request::TransactionRequest,
56 simulate::{SimulatePayload, SimulatedBlock},
57 state::{AccountOverride, EvmOverrides, StateOverridesBuilder},
58 trace::{
59 filter::TraceFilter,
60 geth::{GethDebugTracingCallOptions, GethDebugTracingOptions, GethTrace},
61 parity::{LocalizedTransactionTrace, TraceResultsWithTransactionHash, TraceType},
62 },
63 txpool::{TxpoolContent, TxpoolInspect, TxpoolInspectSummary, TxpoolStatus},
64};
65use alloy_rpc_types_eth::FillTransaction;
66use alloy_serde::WithOtherFields;
67use alloy_sol_types::{SolCall, SolValue, sol};
68use alloy_transport::TransportErrorKind;
69use anvil_core::{
70 eth::{
71 EthRequest,
72 block::BlockInfo,
73 transaction::{MaybeImpersonatedTransaction, PendingTransaction},
74 },
75 types::{ReorgOptions, TransactionData},
76};
77use anvil_rpc::{error::RpcError, response::ResponseResult};
78use foundry_common::provider::ProviderBuilder;
79use foundry_evm::decode::RevertDecoder;
80use foundry_primitives::{
81 FoundryNetwork, FoundryReceiptEnvelope, FoundryTransactionRequest, FoundryTxEnvelope,
82 FoundryTxReceipt, FoundryTxType, FoundryTypedTx,
83};
84use futures::{
85 StreamExt, TryFutureExt,
86 channel::{mpsc::Receiver, oneshot},
87};
88use parking_lot::RwLock;
89use revm::{
90 context::BlockEnv,
91 context_interface::{block::BlobExcessGasAndPrice, result::Output},
92 database::CacheDB,
93 interpreter::{InstructionResult, return_ok, return_revert},
94 primitives::eip7702::PER_EMPTY_ACCOUNT_COST,
95};
96use std::{sync::Arc, time::Duration};
97use tokio::{
98 sync::mpsc::{UnboundedReceiver, unbounded_channel},
99 try_join,
100};
101
102pub const CLIENT_VERSION: &str = concat!("anvil/v", env!("CARGO_PKG_VERSION"));
104
105pub struct EthApi<N: Network> {
109 pool: Arc<Pool<N::TxEnvelope>>,
111 pub backend: Arc<backend::mem::Backend<N>>,
114 is_mining: bool,
116 signers: Arc<Vec<Box<dyn Signer<N>>>>,
118 fee_history_cache: FeeHistoryCache,
120 fee_history_limit: u64,
122 miner: Miner<N::TxEnvelope>,
127 logger: LoggingManager,
129 filters: Filters<N>,
131 transaction_order: Arc<RwLock<TransactionOrder>>,
133 net_listening: bool,
135 instance_id: Arc<RwLock<B256>>,
137}
138
139impl<N: Network> Clone for EthApi<N> {
140 fn clone(&self) -> Self {
141 Self {
142 pool: self.pool.clone(),
143 backend: self.backend.clone(),
144 is_mining: self.is_mining,
145 signers: self.signers.clone(),
146 fee_history_cache: self.fee_history_cache.clone(),
147 fee_history_limit: self.fee_history_limit,
148 miner: self.miner.clone(),
149 logger: self.logger.clone(),
150 filters: self.filters.clone(),
151 transaction_order: self.transaction_order.clone(),
152 net_listening: self.net_listening,
153 instance_id: self.instance_id.clone(),
154 }
155 }
156}
157
158impl<N: Network> EthApi<N> {
161 #[expect(clippy::too_many_arguments)]
163 pub fn new(
164 pool: Arc<Pool<N::TxEnvelope>>,
165 backend: Arc<backend::mem::Backend<N>>,
166 signers: Arc<Vec<Box<dyn Signer<N>>>>,
167 fee_history_cache: FeeHistoryCache,
168 fee_history_limit: u64,
169 miner: Miner<N::TxEnvelope>,
170 logger: LoggingManager,
171 filters: Filters<N>,
172 transactions_order: TransactionOrder,
173 ) -> Self {
174 Self {
175 pool,
176 backend,
177 is_mining: true,
178 signers,
179 fee_history_cache,
180 fee_history_limit,
181 miner,
182 logger,
183 filters,
184 net_listening: true,
185 transaction_order: Arc::new(RwLock::new(transactions_order)),
186 instance_id: Arc::new(RwLock::new(B256::random())),
187 }
188 }
189
190 pub fn gas_price(&self) -> u128 {
192 if self.backend.is_eip1559() {
193 if self.backend.is_min_priority_fee_enforced() {
194 (self.backend.base_fee() as u128).saturating_add(self.lowest_suggestion_tip())
195 } else {
196 self.backend.base_fee() as u128
197 }
198 } else {
199 self.backend.fees().raw_gas_price()
200 }
201 }
202
203 fn lowest_suggestion_tip(&self) -> u128 {
207 let block_number = self.backend.best_number();
208 let latest_cached_block = self.fee_history_cache.lock().get(&block_number).cloned();
209
210 match latest_cached_block {
211 Some(block) => block.rewards.iter().copied().min(),
212 None => self.fee_history_cache.lock().values().flat_map(|b| b.rewards.clone()).min(),
213 }
214 .map(|fee| fee.max(MIN_SUGGESTED_PRIORITY_FEE))
215 .unwrap_or(MIN_SUGGESTED_PRIORITY_FEE)
216 }
217
218 pub fn anvil_get_auto_mine(&self) -> Result<bool> {
222 node_info!("anvil_getAutomine");
223 Ok(self.miner.is_auto_mine())
224 }
225
226 pub fn anvil_get_interval_mining(&self) -> Result<Option<u64>> {
230 node_info!("anvil_getIntervalMining");
231 Ok(self.miner.get_interval())
232 }
233
234 pub async fn anvil_set_auto_mine(&self, enable_automine: bool) -> Result<()> {
239 node_info!("evm_setAutomine");
240 if self.miner.is_auto_mine() {
241 if enable_automine {
242 return Ok(());
243 }
244 self.miner.set_mining_mode(MiningMode::None);
245 } else if enable_automine {
246 let listener = self.pool.add_ready_listener();
247 let mode = MiningMode::instant(1_000, listener);
248 self.miner.set_mining_mode(mode);
249 }
250 Ok(())
251 }
252
253 pub fn anvil_set_interval_mining(&self, secs: u64) -> Result<()> {
257 node_info!("evm_setIntervalMining");
258 let mining_mode = if secs == 0 {
259 MiningMode::None
260 } else {
261 let block_time = Duration::from_secs(secs);
262
263 self.backend.update_interval_mine_block_time(block_time);
265
266 MiningMode::FixedBlockTime(FixedBlockTimeMiner::new(block_time))
267 };
268 self.miner.set_mining_mode(mining_mode);
269 Ok(())
270 }
271
272 pub async fn anvil_drop_transaction(&self, tx_hash: B256) -> Result<Option<B256>> {
276 node_info!("anvil_dropTransaction");
277 Ok(self.pool.drop_transaction(tx_hash).map(|tx| tx.hash()))
278 }
279
280 pub async fn anvil_drop_all_transactions(&self) -> Result<()> {
284 node_info!("anvil_dropAllTransactions");
285 self.pool.clear();
286 Ok(())
287 }
288
289 pub async fn anvil_set_chain_id(&self, chain_id: u64) -> Result<()> {
290 node_info!("anvil_setChainId");
291 self.backend.set_chain_id(chain_id);
292 Ok(())
293 }
294
295 pub async fn anvil_set_balance(&self, address: Address, balance: U256) -> Result<()> {
299 node_info!("anvil_setBalance");
300 self.backend.set_balance(address, balance).await?;
301 Ok(())
302 }
303
304 pub async fn anvil_set_code(&self, address: Address, code: Bytes) -> Result<()> {
308 node_info!("anvil_setCode");
309 self.backend.set_code(address, code).await?;
310 Ok(())
311 }
312
313 pub async fn anvil_set_nonce(&self, address: Address, nonce: U256) -> Result<()> {
317 node_info!("anvil_setNonce");
318 self.backend.set_nonce(address, nonce).await?;
319 Ok(())
320 }
321
322 pub async fn anvil_set_storage_at(
326 &self,
327 address: Address,
328 slot: U256,
329 val: B256,
330 ) -> Result<bool> {
331 node_info!("anvil_setStorageAt");
332 self.backend.set_storage_at(address, slot, val).await?;
333 Ok(true)
334 }
335
336 pub async fn anvil_set_logging(&self, enable: bool) -> Result<()> {
340 node_info!("anvil_setLoggingEnabled");
341 self.logger.set_enabled(enable);
342 Ok(())
343 }
344
345 pub async fn anvil_set_min_gas_price(&self, gas: U256) -> Result<()> {
349 node_info!("anvil_setMinGasPrice");
350 if self.backend.is_eip1559() {
351 return Err(RpcError::invalid_params(
352 "anvil_setMinGasPrice is not supported when EIP-1559 is active",
353 )
354 .into());
355 }
356 self.backend.set_gas_price(gas.to());
357 Ok(())
358 }
359
360 pub async fn anvil_set_next_block_base_fee_per_gas(&self, basefee: U256) -> Result<()> {
364 node_info!("anvil_setNextBlockBaseFeePerGas");
365 if !self.backend.is_eip1559() {
366 return Err(RpcError::invalid_params(
367 "anvil_setNextBlockBaseFeePerGas is only supported when EIP-1559 is active",
368 )
369 .into());
370 }
371 self.backend.set_base_fee(basefee.to());
372 Ok(())
373 }
374
375 pub async fn anvil_set_coinbase(&self, address: Address) -> Result<()> {
379 node_info!("anvil_setCoinbase");
380 self.backend.set_coinbase(address);
381 Ok(())
382 }
383
384 pub async fn anvil_node_info(&self) -> Result<NodeInfo> {
388 node_info!("anvil_nodeInfo");
389
390 let evm_env = self.backend.evm_env().read();
391 let fork_config = self.backend.get_fork();
392 let tx_order = self.transaction_order.read();
393 let hard_fork = self.backend.hardfork().name();
394
395 Ok(NodeInfo {
396 current_block_number: self.backend.best_number(),
397 current_block_timestamp: evm_env.block_env.timestamp.saturating_to(),
398 current_block_hash: self.backend.best_hash(),
399 hard_fork,
400 transaction_order: match *tx_order {
401 TransactionOrder::Fifo => "fifo".to_string(),
402 TransactionOrder::Fees => "fees".to_string(),
403 },
404 environment: NodeEnvironment {
405 base_fee: self.backend.base_fee() as u128,
406 chain_id: self.backend.chain_id().to::<u64>(),
407 gas_limit: self.backend.gas_limit(),
408 gas_price: self.gas_price(),
409 },
410 fork_config: fork_config
411 .map(|fork| {
412 let config = fork.config.read();
413
414 NodeForkConfig {
415 fork_url: Some(config.eth_rpc_url.clone()),
416 fork_block_number: Some(config.block_number),
417 fork_retry_backoff: Some(config.backoff.as_millis()),
418 }
419 })
420 .unwrap_or_default(),
421 network: self.backend.is_tempo().then(|| "tempo".to_string()),
422 })
423 }
424
425 pub async fn anvil_metadata(&self) -> Result<Metadata> {
429 node_info!("anvil_metadata");
430 let fork_config = self.backend.get_fork();
431
432 Ok(Metadata {
433 client_version: CLIENT_VERSION.to_string(),
434 chain_id: self.backend.chain_id().to::<u64>(),
435 latest_block_hash: self.backend.best_hash(),
436 latest_block_number: self.backend.best_number(),
437 instance_id: *self.instance_id.read(),
438 forked_network: fork_config.map(|cfg| ForkedNetwork {
439 chain_id: cfg.chain_id(),
440 fork_block_number: cfg.block_number(),
441 fork_block_hash: cfg.block_hash(),
442 }),
443 snapshots: self.backend.list_state_snapshots(),
444 })
445 }
446
447 pub async fn anvil_remove_pool_transactions(&self, address: Address) -> Result<()> {
448 node_info!("anvil_removePoolTransactions");
449 self.pool.remove_transactions_by_address(address);
450 Ok(())
451 }
452
453 pub async fn evm_snapshot(&self) -> Result<U256> {
457 node_info!("evm_snapshot");
458 Ok(self.backend.create_state_snapshot().await)
459 }
460
461 pub async fn evm_increase_time(&self, seconds: U256) -> Result<i64> {
465 node_info!("evm_increaseTime");
466 Ok(self.backend.time().increase_time(seconds.try_into().unwrap_or(u64::MAX)) as i64)
467 }
468
469 pub fn evm_set_next_block_timestamp(&self, seconds: u64) -> Result<()> {
473 node_info!("evm_setNextBlockTimestamp");
474 self.backend.time().set_next_block_timestamp(seconds)
475 }
476
477 pub fn evm_set_time(&self, timestamp: u64) -> Result<u64> {
482 node_info!("evm_setTime");
483 let now = self.backend.time().current_call_timestamp();
484 self.backend.time().reset(timestamp);
485
486 let offset = timestamp.saturating_sub(now);
488 Ok(Duration::from_millis(offset).as_secs())
489 }
490
491 pub fn evm_set_block_gas_limit(&self, gas_limit: U256) -> Result<bool> {
495 node_info!("evm_setBlockGasLimit");
496 self.backend.set_gas_limit(gas_limit.to());
497 Ok(true)
498 }
499
500 pub fn evm_set_block_timestamp_interval(&self, seconds: u64) -> Result<()> {
504 node_info!("anvil_setBlockTimestampInterval");
505 self.backend.time().set_block_timestamp_interval(seconds);
506 Ok(())
507 }
508
509 pub fn evm_remove_block_timestamp_interval(&self) -> Result<bool> {
513 node_info!("anvil_removeBlockTimestampInterval");
514 Ok(self.backend.time().remove_block_timestamp_interval())
515 }
516
517 pub fn anvil_set_rpc_url(&self, url: String) -> Result<()> {
521 node_info!("anvil_setRpcUrl");
522 if let Some(fork) = self.backend.get_fork() {
523 let mut config = fork.config.write();
524 let new_provider = Arc::new(
526 ProviderBuilder::new(&url).max_retry(10).initial_backoff(1000).build().map_err(
527 |_| {
528 TransportErrorKind::custom_str(
529 format!("Failed to parse invalid url {url}").as_str(),
530 )
531 },
532 )?, );
535 config.provider = new_provider;
536 trace!(target: "backend", "Updated fork rpc from \"{}\" to \"{}\"", config.eth_rpc_url, url);
537 config.eth_rpc_url = url;
538 }
539 Ok(())
540 }
541
542 pub async fn txpool_status(&self) -> Result<TxpoolStatus> {
548 node_info!("txpool_status");
549 Ok(self.pool.txpool_status())
550 }
551
552 async fn on_blocking_task<C, F, R>(&self, c: C) -> Result<R>
554 where
555 C: FnOnce(Self) -> F,
556 F: Future<Output = Result<R>> + Send + 'static,
557 R: Send + 'static,
558 {
559 let (tx, rx) = oneshot::channel();
560 let this = self.clone();
561 let f = c(this);
562 tokio::task::spawn_blocking(move || {
563 tokio::runtime::Handle::current().block_on(async move {
564 let res = f.await;
565 let _ = tx.send(res);
566 })
567 });
568 rx.await.map_err(|_| BlockchainError::Internal("blocking task panicked".to_string()))?
569 }
570
571 pub fn set_transaction_order(&self, order: TransactionOrder) {
573 *self.transaction_order.write() = order;
574 }
575
576 pub fn chain_id(&self) -> u64 {
578 self.backend.chain_id().to::<u64>()
579 }
580
581 pub fn get_fork(&self) -> Option<ClientFork> {
583 self.backend.get_fork()
584 }
585
586 pub fn instance_id(&self) -> B256 {
588 *self.instance_id.read()
589 }
590
591 pub fn reset_instance_id(&self) {
593 *self.instance_id.write() = B256::random();
594 }
595
596 #[expect(clippy::borrowed_box)]
598 pub fn get_signer(&self, address: Address) -> Option<&Box<dyn Signer<N>>> {
599 self.signers.iter().find(|signer| signer.is_signer_for(address))
600 }
601
602 pub fn new_ready_transactions(&self) -> Receiver<TxHash> {
604 self.pool.add_ready_listener()
605 }
606
607 pub fn is_fork(&self) -> bool {
609 self.backend.is_fork()
610 }
611
612 pub async fn state_root(&self) -> Option<B256> {
614 self.backend.get_db().read().await.maybe_state_root()
615 }
616
617 pub fn is_impersonated(&self, addr: Address) -> bool {
619 self.backend.cheats().is_impersonated(addr)
620 }
621
622 pub fn storage_info(&self) -> StorageInfo<N> {
624 StorageInfo::new(Arc::clone(&self.backend))
625 }
626
627 pub fn anvil_get_blob_by_versioned_hash(
629 &self,
630 hash: B256,
631 ) -> Result<Option<alloy_consensus::Blob>> {
632 node_info!("anvil_getBlobByHash");
633 Ok(self.backend.get_blob_by_versioned_hash(hash)?)
634 }
635
636 pub fn anvil_get_blobs_by_block_id(
638 &self,
639 block_id: impl Into<BlockId>,
640 versioned_hashes: Vec<B256>,
641 ) -> Result<Option<Vec<Blob>>> {
642 node_info!("anvil_getBlobsByBlockId");
643 Ok(self.backend.get_blobs_by_block_id(block_id, versioned_hashes)?)
644 }
645
646 pub fn anvil_get_genesis_time(&self) -> Result<u64> {
650 node_info!("anvil_getGenesisTime");
651 Ok(self.backend.genesis_time())
652 }
653
654 pub async fn anvil_reset(&self, forking: Option<Forking>) -> Result<()> {
660 self.reset_instance_id();
661 node_info!("anvil_reset");
662 if let Some(forking) = forking {
663 self.backend.reset_fork(forking).await?;
665 } else {
666 self.backend.reset_to_in_mem().await?;
668 }
669 self.pool.clear();
671 Ok(())
672 }
673
674 pub async fn evm_revert(&self, id: U256) -> Result<bool> {
679 node_info!("evm_revert");
680 self.backend.revert_state_snapshot(id).await
681 }
682
683 pub async fn anvil_impersonate_account(&self, address: Address) -> Result<()> {
687 node_info!("anvil_impersonateAccount");
688 self.backend.impersonate(address);
689 Ok(())
690 }
691
692 pub async fn anvil_stop_impersonating_account(&self, address: Address) -> Result<()> {
696 node_info!("anvil_stopImpersonatingAccount");
697 self.backend.stop_impersonating(address);
698 Ok(())
699 }
700
701 pub async fn anvil_auto_impersonate_account(&self, enabled: bool) -> Result<()> {
705 node_info!("anvil_autoImpersonateAccount");
706 self.backend.auto_impersonate_account(enabled);
707 Ok(())
708 }
709
710 pub async fn anvil_impersonate_signature(
712 &self,
713 signature: Bytes,
714 address: Address,
715 ) -> Result<()> {
716 node_info!("anvil_impersonateSignature");
717 self.backend.impersonate_signature(signature, address).await
718 }
719
720 pub fn new_block_notifications(&self) -> NewBlockNotifications {
722 self.backend.new_block_notifications()
723 }
724
725 pub fn client_version(&self) -> Result<String> {
729 node_info!("web3_clientVersion");
730 Ok(CLIENT_VERSION.to_string())
731 }
732
733 pub fn sha3(&self, bytes: Bytes) -> Result<String> {
737 node_info!("web3_sha3");
738 let hash = alloy_primitives::keccak256(bytes.as_ref());
739 Ok(alloy_primitives::hex::encode_prefixed(&hash[..]))
740 }
741
742 pub fn protocol_version(&self) -> Result<u64> {
746 node_info!("eth_protocolVersion");
747 Ok(1)
748 }
749
750 pub fn hashrate(&self) -> Result<U256> {
754 node_info!("eth_hashrate");
755 Ok(U256::ZERO)
756 }
757
758 pub fn author(&self) -> Result<Address> {
762 node_info!("eth_coinbase");
763 Ok(self.backend.coinbase())
764 }
765
766 pub fn is_mining(&self) -> Result<bool> {
770 node_info!("eth_mining");
771 Ok(self.is_mining)
772 }
773
774 pub fn eth_chain_id(&self) -> Result<Option<U64>> {
780 node_info!("eth_chainId");
781 Ok(Some(self.backend.chain_id().to::<U64>()))
782 }
783
784 pub fn network_id(&self) -> Result<Option<String>> {
788 node_info!("eth_networkId");
789 let chain_id = self.backend.chain_id().to::<u64>();
790 Ok(Some(format!("{chain_id}")))
791 }
792
793 pub fn net_listening(&self) -> Result<bool> {
797 node_info!("net_listening");
798 Ok(self.net_listening)
799 }
800
801 fn eth_gas_price(&self) -> Result<U256> {
803 node_info!("eth_gasPrice");
804 Ok(U256::from(self.gas_price()))
805 }
806
807 pub fn excess_blob_gas_and_price(&self) -> Result<Option<BlobExcessGasAndPrice>> {
809 Ok(self.backend.excess_blob_gas_and_price())
810 }
811
812 pub fn gas_max_priority_fee_per_gas(&self) -> Result<U256> {
817 self.max_priority_fee_per_gas()
818 }
819
820 pub fn blob_base_fee(&self) -> Result<U256> {
824 Ok(U256::from(self.backend.fees().base_fee_per_blob_gas()))
825 }
826
827 pub fn gas_limit(&self) -> U256 {
829 U256::from(self.backend.gas_limit())
830 }
831
832 pub fn accounts(&self) -> Result<Vec<Address>> {
836 node_info!("eth_accounts");
837 let mut unique = HashSet::new();
838 let mut accounts: Vec<Address> = Vec::new();
839 for signer in self.signers.iter() {
840 accounts.extend(signer.accounts().into_iter().filter(|acc| unique.insert(*acc)));
841 }
842 accounts.extend(
843 self.backend
844 .cheats()
845 .impersonated_accounts()
846 .into_iter()
847 .filter(|acc| unique.insert(*acc)),
848 );
849 Ok(accounts.into_iter().collect())
850 }
851
852 pub fn block_number(&self) -> Result<U256> {
856 node_info!("eth_blockNumber");
857 Ok(U256::from(self.backend.best_number()))
858 }
859
860 pub async fn block_by_hash(&self, hash: B256) -> Result<Option<AnyRpcBlock>> {
864 node_info!("eth_getBlockByHash");
865 self.backend.block_by_hash(hash).await
866 }
867
868 pub async fn block_by_hash_full(&self, hash: B256) -> Result<Option<AnyRpcBlock>> {
872 node_info!("eth_getBlockByHash");
873 self.backend.block_by_hash_full(hash).await
874 }
875
876 pub async fn block_transaction_count_by_hash(&self, hash: B256) -> Result<Option<U256>> {
880 node_info!("eth_getBlockTransactionCountByHash");
881 let block = self.backend.block_by_hash(hash).await?;
882 let txs = block.map(|b| match b.transactions() {
883 BlockTransactions::Full(txs) => U256::from(txs.len()),
884 BlockTransactions::Hashes(txs) => U256::from(txs.len()),
885 BlockTransactions::Uncle => U256::from(0),
886 });
887 Ok(txs)
888 }
889
890 pub async fn block_uncles_count_by_hash(&self, hash: B256) -> Result<U256> {
894 node_info!("eth_getUncleCountByBlockHash");
895 let block =
896 self.backend.block_by_hash(hash).await?.ok_or(BlockchainError::BlockNotFound)?;
897 Ok(U256::from(block.uncles.len()))
898 }
899
900 pub async fn block_uncles_count_by_number(&self, block_number: BlockNumber) -> Result<U256> {
904 node_info!("eth_getUncleCountByBlockNumber");
905 let block = self
906 .backend
907 .block_by_number(block_number)
908 .await?
909 .ok_or(BlockchainError::BlockNotFound)?;
910 Ok(U256::from(block.uncles.len()))
911 }
912
913 pub async fn sign_typed_data(
917 &self,
918 _address: Address,
919 _data: serde_json::Value,
920 ) -> Result<String> {
921 node_info!("eth_signTypedData");
922 Err(BlockchainError::RpcUnimplemented)
923 }
924
925 pub async fn sign_typed_data_v3(
929 &self,
930 _address: Address,
931 _data: serde_json::Value,
932 ) -> Result<String> {
933 node_info!("eth_signTypedData_v3");
934 Err(BlockchainError::RpcUnimplemented)
935 }
936
937 pub async fn sign_typed_data_v4(&self, address: Address, data: &TypedData) -> Result<String> {
941 node_info!("eth_signTypedData_v4");
942 let signer = self.get_signer(address).ok_or(BlockchainError::NoSignerAvailable)?;
943 let signature = signer.sign_typed_data(address, data).await?;
944 let signature = alloy_primitives::hex::encode(signature.as_bytes());
945 Ok(format!("0x{signature}"))
946 }
947
948 pub async fn sign(&self, address: Address, content: impl AsRef<[u8]>) -> Result<String> {
952 node_info!("eth_sign");
953 let signer = self.get_signer(address).ok_or(BlockchainError::NoSignerAvailable)?;
954 let signature =
955 alloy_primitives::hex::encode(signer.sign(address, content.as_ref()).await?.as_bytes());
956 Ok(format!("0x{signature}"))
957 }
958
959 pub async fn transaction_by_block_hash_and_index(
963 &self,
964 hash: B256,
965 index: Index,
966 ) -> Result<Option<AnyRpcTransaction>> {
967 node_info!("eth_getTransactionByBlockHashAndIndex");
968 self.backend.transaction_by_block_hash_and_index(hash, index).await
969 }
970
971 pub async fn transaction_by_block_number_and_index(
975 &self,
976 block: BlockNumber,
977 idx: Index,
978 ) -> Result<Option<AnyRpcTransaction>> {
979 node_info!("eth_getTransactionByBlockNumberAndIndex");
980 self.backend.transaction_by_block_number_and_index(block, idx).await
981 }
982
983 pub async fn uncle_by_block_hash_and_index(
987 &self,
988 block_hash: B256,
989 idx: Index,
990 ) -> Result<Option<AnyRpcBlock>> {
991 node_info!("eth_getUncleByBlockHashAndIndex");
992 let number =
993 self.backend.ensure_block_number(Some(BlockId::Hash(block_hash.into()))).await?;
994 if let Some(fork) = self.get_fork()
995 && fork.predates_fork_inclusive(number)
996 {
997 return Ok(fork.uncle_by_block_hash_and_index(block_hash, idx.into()).await?);
998 }
999 Ok(None)
1001 }
1002
1003 pub async fn uncle_by_block_number_and_index(
1007 &self,
1008 block_number: BlockNumber,
1009 idx: Index,
1010 ) -> Result<Option<AnyRpcBlock>> {
1011 node_info!("eth_getUncleByBlockNumberAndIndex");
1012 let number = self.backend.ensure_block_number(Some(BlockId::Number(block_number))).await?;
1013 if let Some(fork) = self.get_fork()
1014 && fork.predates_fork_inclusive(number)
1015 {
1016 return Ok(fork.uncle_by_block_number_and_index(number, idx.into()).await?);
1017 }
1018 Ok(None)
1020 }
1021
1022 pub fn work(&self) -> Result<Work> {
1026 node_info!("eth_getWork");
1027 Err(BlockchainError::RpcUnimplemented)
1028 }
1029
1030 pub fn syncing(&self) -> Result<bool> {
1034 node_info!("eth_syncing");
1035 Ok(false)
1036 }
1037
1038 pub fn config(&self) -> Result<EthConfig> {
1049 node_info!("eth_config");
1050 Ok(EthConfig {
1051 current: EthForkConfig {
1052 activation_time: 0,
1053 blob_schedule: self.backend.blob_params(),
1054 chain_id: self.backend.chain_id().to::<u64>(),
1055 fork_id: Bytes::from_static(&[0; 4]),
1056 precompiles: self.backend.precompiles(),
1057 system_contracts: self.backend.system_contracts(),
1058 },
1059 next: None,
1060 last: None,
1061 })
1062 }
1063
1064 pub fn submit_work(&self, _: B64, _: B256, _: B256) -> Result<bool> {
1068 node_info!("eth_submitWork");
1069 Err(BlockchainError::RpcUnimplemented)
1070 }
1071
1072 pub fn submit_hashrate(&self, _: U256, _: B256) -> Result<bool> {
1076 node_info!("eth_submitHashrate");
1077 Err(BlockchainError::RpcUnimplemented)
1078 }
1079
1080 pub async fn fee_history(
1084 &self,
1085 block_count: U256,
1086 newest_block: BlockNumber,
1087 reward_percentiles: Vec<f64>,
1088 ) -> Result<FeeHistory> {
1089 node_info!("eth_feeHistory");
1090 let current = self.backend.best_number();
1093 let slots_in_an_epoch = 32u64;
1094
1095 let number = match newest_block {
1096 BlockNumber::Latest | BlockNumber::Pending => current,
1097 BlockNumber::Earliest => 0,
1098 BlockNumber::Number(n) => n,
1099 BlockNumber::Safe => current.saturating_sub(slots_in_an_epoch),
1100 BlockNumber::Finalized => current.saturating_sub(slots_in_an_epoch * 2),
1101 };
1102
1103 if let Some(fork) = self.get_fork() {
1105 if fork.predates_fork_inclusive(number) {
1108 return fork
1109 .fee_history(block_count.to(), BlockNumber::Number(number), &reward_percentiles)
1110 .await
1111 .map_err(BlockchainError::AlloyForkProvider);
1112 }
1113 }
1114
1115 const MAX_BLOCK_COUNT: u64 = 1024u64;
1116 let block_count = block_count.to::<u64>().min(MAX_BLOCK_COUNT);
1117
1118 let highest = number;
1120 let lowest = highest.saturating_sub(block_count.saturating_sub(1));
1121
1122 if lowest < self.backend.best_number().saturating_sub(self.fee_history_limit) {
1124 return Err(FeeHistoryError::InvalidBlockRange.into());
1125 }
1126
1127 let mut response = FeeHistory {
1128 oldest_block: lowest,
1129 base_fee_per_gas: Vec::new(),
1130 gas_used_ratio: Vec::new(),
1131 reward: Some(Default::default()),
1132 base_fee_per_blob_gas: Default::default(),
1133 blob_gas_used_ratio: Default::default(),
1134 };
1135 let mut rewards = Vec::new();
1136
1137 {
1138 let fee_history = self.fee_history_cache.lock();
1139
1140 for n in lowest..=highest {
1142 if let Some(block) = fee_history.get(&n) {
1144 response.base_fee_per_gas.push(block.base_fee);
1145 response.base_fee_per_blob_gas.push(block.base_fee_per_blob_gas.unwrap_or(0));
1146 response.blob_gas_used_ratio.push(block.blob_gas_used_ratio);
1147 response.gas_used_ratio.push(block.gas_used_ratio);
1148
1149 if !reward_percentiles.is_empty() {
1151 let mut block_rewards = Vec::new();
1152 let resolution_per_percentile: f64 = 2.0;
1153 for p in &reward_percentiles {
1154 let p = p.clamp(0.0, 100.0);
1155 let index = ((p.round() / 2f64) * 2f64) * resolution_per_percentile;
1156 let reward = block.rewards.get(index as usize).map_or(0, |r| *r);
1157 block_rewards.push(reward);
1158 }
1159 rewards.push(block_rewards);
1160 }
1161 }
1162 }
1163 }
1164
1165 response.reward = Some(rewards);
1166
1167 response.base_fee_per_gas.push(self.backend.fees().base_fee() as u128);
1172
1173 response.base_fee_per_blob_gas.push(self.backend.fees().base_fee_per_blob_gas());
1177
1178 Ok(response)
1179 }
1180
1181 pub fn max_priority_fee_per_gas(&self) -> Result<U256> {
1188 node_info!("eth_maxPriorityFeePerGas");
1189 Ok(U256::from(self.lowest_suggestion_tip()))
1190 }
1191
1192 pub async fn debug_code_by_hash(
1196 &self,
1197 hash: B256,
1198 block_id: Option<BlockId>,
1199 ) -> Result<Option<Bytes>> {
1200 node_info!("debug_codeByHash");
1201 self.backend.debug_code_by_hash(hash, block_id).await
1202 }
1203
1204 pub async fn debug_db_get(&self, key: String) -> Result<Option<Bytes>> {
1209 node_info!("debug_dbGet");
1210 self.backend.debug_db_get(key).await
1211 }
1212
1213 pub async fn trace_transaction(&self, tx_hash: B256) -> Result<Vec<LocalizedTransactionTrace>> {
1217 node_info!("trace_transaction");
1218 self.backend.trace_transaction(tx_hash).await
1219 }
1220
1221 pub async fn trace_block(&self, block: BlockNumber) -> Result<Vec<LocalizedTransactionTrace>> {
1225 node_info!("trace_block");
1226 self.backend.trace_block(block).await
1227 }
1228
1229 pub async fn trace_filter(
1233 &self,
1234 filter: TraceFilter,
1235 ) -> Result<Vec<LocalizedTransactionTrace>> {
1236 node_info!("trace_filter");
1237 self.backend.trace_filter(filter).await
1238 }
1239
1240 pub async fn trace_replay_block_transactions(
1244 &self,
1245 block: BlockNumber,
1246 trace_types: HashSet<TraceType>,
1247 ) -> Result<Vec<TraceResultsWithTransactionHash>> {
1248 node_info!("trace_replayBlockTransactions");
1249 self.backend.trace_replay_block_transactions(block, trace_types).await
1250 }
1251}
1252
1253impl<N: Network<ReceiptEnvelope = FoundryReceiptEnvelope>> EthApi<N> {
1254 pub async fn serialized_state(
1256 &self,
1257 preserve_historical_states: bool,
1258 ) -> Result<SerializableState> {
1259 self.backend.serialized_state(preserve_historical_states).await
1260 }
1261}
1262
1263impl EthApi<FoundryNetwork> {
1266 pub async fn anvil_dump_state(
1271 &self,
1272 preserve_historical_states: Option<bool>,
1273 ) -> Result<Bytes> {
1274 node_info!("anvil_dumpState");
1275 self.backend.dump_state(preserve_historical_states.unwrap_or(false)).await
1276 }
1277
1278 pub async fn anvil_load_state(&self, buf: Bytes) -> Result<bool> {
1283 node_info!("anvil_loadState");
1284 self.backend.load_state_bytes(buf).await
1285 }
1286
1287 async fn block_request(
1288 &self,
1289 block_number: Option<BlockId>,
1290 ) -> Result<BlockRequest<FoundryTxEnvelope>> {
1291 let block_request = match block_number {
1292 Some(BlockId::Number(BlockNumber::Pending)) => {
1293 let pending_txs = self.pool.ready_transactions().collect();
1294 BlockRequest::Pending(pending_txs)
1295 }
1296 _ => {
1297 let number = self.backend.ensure_block_number(block_number).await?;
1298 BlockRequest::Number(number)
1299 }
1300 };
1301 Ok(block_request)
1302 }
1303
1304 pub async fn anvil_add_balance(&self, address: Address, balance: U256) -> Result<()> {
1308 node_info!("anvil_addBalance");
1309 let current_balance = self.backend.get_balance(address, None).await?;
1310 self.backend.set_balance(address, current_balance.saturating_add(balance)).await?;
1311 Ok(())
1312 }
1313
1314 pub async fn anvil_rollback(&self, depth: Option<u64>) -> Result<()> {
1325 node_info!("anvil_rollback");
1326 let depth = depth.unwrap_or(1);
1327
1328 let current_height = self.backend.best_number();
1330 let common_height = current_height.checked_sub(depth).ok_or(BlockchainError::RpcError(
1331 RpcError::invalid_params(format!(
1332 "Rollback depth must not exceed current chain height: current height {current_height}, depth {depth}"
1333 )),
1334 ))?;
1335
1336 let common_block =
1338 self.backend.get_block(common_height).ok_or(BlockchainError::BlockNotFound)?;
1339
1340 self.backend.rollback(common_block).await?;
1341 Ok(())
1342 }
1343
1344 fn do_estimate_gas_with_state(
1348 &self,
1349 mut request: WithOtherFields<TransactionRequest>,
1350 state: &dyn DatabaseRef,
1351 block_env: BlockEnv,
1352 ) -> Result<u128> {
1353 if !self.backend.is_tempo() {
1358 let to = request.to.as_ref().and_then(TxKind::to);
1359
1360 let maybe_transfer = (request.input.input().is_none()
1362 || request.input.input().is_some_and(|data| data.is_empty()))
1363 && request.authorization_list.is_none()
1364 && request.access_list.is_none()
1365 && request.blob_versioned_hashes.is_none();
1366
1367 if maybe_transfer
1368 && let Some(to) = to
1369 && let Ok(target_code) = self.backend.get_code_with_state(&state, *to)
1370 && target_code.as_ref().is_empty()
1371 {
1372 return Ok(MIN_TRANSACTION_GAS);
1373 }
1374 }
1375
1376 let fees = FeeDetails::new(
1377 request.gas_price,
1378 request.max_fee_per_gas,
1379 request.max_priority_fee_per_gas,
1380 request.max_fee_per_blob_gas,
1381 )?
1382 .or_zero_fees();
1383
1384 let mut highest_gas_limit = request.gas.map_or(block_env.gas_limit.into(), |g| g as u128);
1387
1388 let is_tempo_tx = request.other.get("feeToken").is_some_and(|v| !v.is_null());
1390
1391 let gas_price = fees.gas_price.unwrap_or_default();
1392 if gas_price > 0
1395 && !is_tempo_tx
1396 && let Some(from) = request.from
1397 {
1398 let mut available_funds = self.backend.get_balance_with_state(state, from)?;
1399 if let Some(value) = request.value {
1400 if value > available_funds {
1401 return Err(InvalidTransactionError::InsufficientFunds.into());
1402 }
1403 available_funds -= value;
1405 }
1406 let allowance = available_funds.checked_div(U256::from(gas_price)).unwrap_or_default();
1408 highest_gas_limit = std::cmp::min(highest_gas_limit, allowance.saturating_to());
1409 }
1410
1411 let mut call_to_estimate = request.clone();
1412 call_to_estimate.gas = Some(highest_gas_limit as u64);
1413
1414 let ethres =
1416 self.backend.call_with_state(&state, call_to_estimate, fees.clone(), block_env.clone());
1417
1418 let gas_used = match ethres.try_into()? {
1419 GasEstimationCallResult::Success(gas) => Ok(gas),
1420 GasEstimationCallResult::OutOfGas => {
1421 Err(InvalidTransactionError::BasicOutOfGas(highest_gas_limit).into())
1422 }
1423 GasEstimationCallResult::Revert(output) => {
1424 Err(InvalidTransactionError::Revert(output).into())
1425 }
1426 GasEstimationCallResult::EvmError(err) => {
1427 warn!(target: "node", "estimation failed due to {:?}", err);
1428 Err(BlockchainError::EvmError(err))
1429 }
1430 }?;
1431
1432 let mut lowest_gas_limit = determine_base_gas_by_kind(&request);
1439
1440 let mut mid_gas_limit =
1442 std::cmp::min(gas_used * 3, (highest_gas_limit + lowest_gas_limit) / 2);
1443
1444 while (highest_gas_limit - lowest_gas_limit) > 1 {
1446 request.gas = Some(mid_gas_limit as u64);
1447 let ethres = self.backend.call_with_state(
1448 &state,
1449 request.clone(),
1450 fees.clone(),
1451 block_env.clone(),
1452 );
1453
1454 match ethres.try_into()? {
1455 GasEstimationCallResult::Success(_) => {
1456 highest_gas_limit = mid_gas_limit;
1460 }
1461 GasEstimationCallResult::OutOfGas
1462 | GasEstimationCallResult::Revert(_)
1463 | GasEstimationCallResult::EvmError(_) => {
1464 lowest_gas_limit = mid_gas_limit;
1471 }
1472 };
1473 mid_gas_limit = (highest_gas_limit + lowest_gas_limit) / 2;
1475 }
1476
1477 trace!(target : "node", "Estimated Gas for call {:?}", highest_gas_limit);
1478
1479 Ok(highest_gas_limit)
1480 }
1481
1482 pub async fn execute(&self, request: EthRequest) -> ResponseResult {
1484 trace!(target: "rpc::api", "executing eth request");
1485 let response = match request.clone() {
1486 EthRequest::EthProtocolVersion(()) => self.protocol_version().to_rpc_result(),
1487 EthRequest::Web3ClientVersion(()) => self.client_version().to_rpc_result(),
1488 EthRequest::Web3Sha3(content) => self.sha3(content).to_rpc_result(),
1489 EthRequest::EthGetAccount(addr, block) => {
1490 self.get_account(addr, block).await.to_rpc_result()
1491 }
1492 EthRequest::EthGetAccountInfo(addr, block) => {
1493 self.get_account_info(addr, block).await.to_rpc_result()
1494 }
1495 EthRequest::EthGetBalance(addr, block) => {
1496 self.balance(addr, block).await.to_rpc_result()
1497 }
1498 EthRequest::EthGetTransactionByHash(hash) => {
1499 self.transaction_by_hash(hash).await.to_rpc_result()
1500 }
1501 EthRequest::EthSendTransaction(request) => {
1502 self.send_transaction(*request).await.to_rpc_result()
1503 }
1504 EthRequest::EthSendTransactionSync(request) => {
1505 self.send_transaction_sync(*request).await.to_rpc_result()
1506 }
1507 EthRequest::EthChainId(_) => self.eth_chain_id().to_rpc_result(),
1508 EthRequest::EthNetworkId(_) => self.network_id().to_rpc_result(),
1509 EthRequest::NetListening(_) => self.net_listening().to_rpc_result(),
1510 EthRequest::EthHashrate(()) => self.hashrate().to_rpc_result(),
1511 EthRequest::EthGasPrice(_) => self.eth_gas_price().to_rpc_result(),
1512 EthRequest::EthMaxPriorityFeePerGas(_) => {
1513 self.gas_max_priority_fee_per_gas().to_rpc_result()
1514 }
1515 EthRequest::EthBlobBaseFee(_) => self.blob_base_fee().to_rpc_result(),
1516 EthRequest::EthAccounts(_) => self.accounts().to_rpc_result(),
1517 EthRequest::EthBlockNumber(_) => self.block_number().to_rpc_result(),
1518 EthRequest::EthCoinbase(()) => self.author().to_rpc_result(),
1519 EthRequest::EthGetStorageAt(addr, slot, block) => {
1520 self.storage_at(addr, slot, block).await.to_rpc_result()
1521 }
1522 EthRequest::EthGetStorageValues(requests, block) => {
1523 self.storage_values(requests, block).await.to_rpc_result()
1524 }
1525 EthRequest::EthGetBlockByHash(hash, full) => {
1526 if full {
1527 self.block_by_hash_full(hash).await.to_rpc_result()
1528 } else {
1529 self.block_by_hash(hash).await.to_rpc_result()
1530 }
1531 }
1532 EthRequest::EthGetBlockByNumber(num, full) => {
1533 if full {
1534 self.block_by_number_full(num).await.to_rpc_result()
1535 } else {
1536 self.block_by_number(num).await.to_rpc_result()
1537 }
1538 }
1539 EthRequest::EthGetTransactionCount(addr, block) => {
1540 self.transaction_count(addr, block).await.to_rpc_result()
1541 }
1542 EthRequest::EthGetTransactionCountByHash(hash) => {
1543 self.block_transaction_count_by_hash(hash).await.to_rpc_result()
1544 }
1545 EthRequest::EthGetTransactionCountByNumber(num) => {
1546 self.block_transaction_count_by_number(num).await.to_rpc_result()
1547 }
1548 EthRequest::EthGetUnclesCountByHash(hash) => {
1549 self.block_uncles_count_by_hash(hash).await.to_rpc_result()
1550 }
1551 EthRequest::EthGetUnclesCountByNumber(num) => {
1552 self.block_uncles_count_by_number(num).await.to_rpc_result()
1553 }
1554 EthRequest::EthGetCodeAt(addr, block) => {
1555 self.get_code(addr, block).await.to_rpc_result()
1556 }
1557 EthRequest::EthGetProof(addr, keys, block) => {
1558 self.get_proof(addr, keys, block).await.to_rpc_result()
1559 }
1560 EthRequest::EthSign(addr, content) => self.sign(addr, content).await.to_rpc_result(),
1561 EthRequest::PersonalSign(content, addr) => {
1562 self.sign(addr, content).await.to_rpc_result()
1563 }
1564 EthRequest::EthSignTransaction(request) => {
1565 self.sign_transaction(*request).await.to_rpc_result()
1566 }
1567 EthRequest::EthSignTypedData(addr, data) => {
1568 self.sign_typed_data(addr, data).await.to_rpc_result()
1569 }
1570 EthRequest::EthSignTypedDataV3(addr, data) => {
1571 self.sign_typed_data_v3(addr, data).await.to_rpc_result()
1572 }
1573 EthRequest::EthSignTypedDataV4(addr, data) => {
1574 self.sign_typed_data_v4(addr, &data).await.to_rpc_result()
1575 }
1576 EthRequest::EthSendRawTransaction(tx) => {
1577 self.send_raw_transaction(tx).await.to_rpc_result()
1578 }
1579 EthRequest::EthSendRawTransactionSync(tx) => {
1580 self.send_raw_transaction_sync(tx).await.to_rpc_result()
1581 }
1582 EthRequest::EthCall(call, block, state_override, block_overrides) => self
1583 .call(call, block, EvmOverrides::new(state_override, block_overrides))
1584 .await
1585 .to_rpc_result(),
1586 EthRequest::EthSimulateV1(simulation, block) => {
1587 self.simulate_v1(simulation, block).await.to_rpc_result()
1588 }
1589 EthRequest::EthCreateAccessList(call, block) => {
1590 self.create_access_list(call, block).await.to_rpc_result()
1591 }
1592 EthRequest::EthEstimateGas(call, block, state_override, block_overrides) => self
1593 .estimate_gas(call, block, EvmOverrides::new(state_override, block_overrides))
1594 .await
1595 .to_rpc_result(),
1596 EthRequest::EthFillTransaction(request) => {
1597 self.fill_transaction(request).await.to_rpc_result()
1598 }
1599 EthRequest::EthGetRawTransactionByHash(hash) => {
1600 self.raw_transaction(hash).await.to_rpc_result()
1601 }
1602 EthRequest::GetBlobByHash(hash) => {
1603 self.anvil_get_blob_by_versioned_hash(hash).to_rpc_result()
1604 }
1605 EthRequest::GetBlobByTransactionHash(hash) => {
1606 self.anvil_get_blob_by_tx_hash(hash).to_rpc_result()
1607 }
1608 EthRequest::GetGenesisTime(()) => self.anvil_get_genesis_time().to_rpc_result(),
1609 EthRequest::EthGetRawTransactionByBlockHashAndIndex(hash, index) => {
1610 self.raw_transaction_by_block_hash_and_index(hash, index).await.to_rpc_result()
1611 }
1612 EthRequest::EthGetRawTransactionByBlockNumberAndIndex(num, index) => {
1613 self.raw_transaction_by_block_number_and_index(num, index).await.to_rpc_result()
1614 }
1615 EthRequest::EthGetTransactionByBlockHashAndIndex(hash, index) => {
1616 self.transaction_by_block_hash_and_index(hash, index).await.to_rpc_result()
1617 }
1618 EthRequest::EthGetTransactionByBlockNumberAndIndex(num, index) => {
1619 self.transaction_by_block_number_and_index(num, index).await.to_rpc_result()
1620 }
1621 EthRequest::EthGetTransactionReceipt(tx) => {
1622 self.transaction_receipt(tx).await.to_rpc_result()
1623 }
1624 EthRequest::EthGetBlockReceipts(number) => {
1625 self.block_receipts(number).await.to_rpc_result()
1626 }
1627 EthRequest::EthGetUncleByBlockHashAndIndex(hash, index) => {
1628 self.uncle_by_block_hash_and_index(hash, index).await.to_rpc_result()
1629 }
1630 EthRequest::EthGetUncleByBlockNumberAndIndex(num, index) => {
1631 self.uncle_by_block_number_and_index(num, index).await.to_rpc_result()
1632 }
1633 EthRequest::EthGetLogs(filter) => self.logs(filter).await.to_rpc_result(),
1634 EthRequest::EthGetWork(_) => self.work().to_rpc_result(),
1635 EthRequest::EthSyncing(_) => self.syncing().to_rpc_result(),
1636 EthRequest::EthConfig(_) => self.config().to_rpc_result(),
1637 EthRequest::EthSubmitWork(nonce, pow, digest) => {
1638 self.submit_work(nonce, pow, digest).to_rpc_result()
1639 }
1640 EthRequest::EthSubmitHashRate(rate, id) => {
1641 self.submit_hashrate(rate, id).to_rpc_result()
1642 }
1643 EthRequest::EthFeeHistory(count, newest, reward_percentiles) => {
1644 self.fee_history(count, newest, reward_percentiles).await.to_rpc_result()
1645 }
1646 EthRequest::DebugGetRawTransaction(hash) => {
1648 self.raw_transaction(hash).await.to_rpc_result()
1649 }
1650 EthRequest::DebugTraceTransaction(tx, opts) => {
1652 self.debug_trace_transaction(tx, opts).await.to_rpc_result()
1653 }
1654 EthRequest::DebugTraceCall(tx, block, opts) => {
1656 self.debug_trace_call(tx, block, opts).await.to_rpc_result()
1657 }
1658 EthRequest::DebugCodeByHash(hash, block) => {
1659 self.debug_code_by_hash(hash, block).await.to_rpc_result()
1660 }
1661 EthRequest::DebugDbGet(key) => self.debug_db_get(key).await.to_rpc_result(),
1662 EthRequest::TraceTransaction(tx) => self.trace_transaction(tx).await.to_rpc_result(),
1663 EthRequest::TraceBlock(block) => self.trace_block(block).await.to_rpc_result(),
1664 EthRequest::TraceFilter(filter) => self.trace_filter(filter).await.to_rpc_result(),
1665 EthRequest::TraceReplayBlockTransactions(block, trace_types) => {
1666 self.trace_replay_block_transactions(block, trace_types).await.to_rpc_result()
1667 }
1668 EthRequest::ImpersonateAccount(addr) => {
1669 self.anvil_impersonate_account(addr).await.to_rpc_result()
1670 }
1671 EthRequest::StopImpersonatingAccount(addr) => {
1672 self.anvil_stop_impersonating_account(addr).await.to_rpc_result()
1673 }
1674 EthRequest::AutoImpersonateAccount(enable) => {
1675 self.anvil_auto_impersonate_account(enable).await.to_rpc_result()
1676 }
1677 EthRequest::ImpersonateSignature(signature, address) => {
1678 self.anvil_impersonate_signature(signature, address).await.to_rpc_result()
1679 }
1680 EthRequest::GetAutoMine(()) => self.anvil_get_auto_mine().to_rpc_result(),
1681 EthRequest::Mine(blocks, interval) => {
1682 self.anvil_mine(blocks, interval).await.to_rpc_result()
1683 }
1684 EthRequest::SetAutomine(enabled) => {
1685 self.anvil_set_auto_mine(enabled).await.to_rpc_result()
1686 }
1687 EthRequest::SetIntervalMining(interval) => {
1688 self.anvil_set_interval_mining(interval).to_rpc_result()
1689 }
1690 EthRequest::GetIntervalMining(()) => self.anvil_get_interval_mining().to_rpc_result(),
1691 EthRequest::DropTransaction(tx) => {
1692 self.anvil_drop_transaction(tx).await.to_rpc_result()
1693 }
1694 EthRequest::DropAllTransactions() => {
1695 self.anvil_drop_all_transactions().await.to_rpc_result()
1696 }
1697 EthRequest::Reset(fork) => {
1698 self.anvil_reset(fork.and_then(|p| p.params)).await.to_rpc_result()
1699 }
1700 EthRequest::SetBalance(addr, val) => {
1701 self.anvil_set_balance(addr, val).await.to_rpc_result()
1702 }
1703 EthRequest::AddBalance(addr, val) => {
1704 self.anvil_add_balance(addr, val).await.to_rpc_result()
1705 }
1706 EthRequest::DealERC20(addr, token_addr, val) => {
1707 self.anvil_deal_erc20(addr, token_addr, val).await.to_rpc_result()
1708 }
1709 EthRequest::SetERC20Allowance(owner, spender, token_addr, val) => self
1710 .anvil_set_erc20_allowance(owner, spender, token_addr, val)
1711 .await
1712 .to_rpc_result(),
1713 EthRequest::SetCode(addr, code) => {
1714 self.anvil_set_code(addr, code).await.to_rpc_result()
1715 }
1716 EthRequest::SetNonce(addr, nonce) => {
1717 self.anvil_set_nonce(addr, nonce).await.to_rpc_result()
1718 }
1719 EthRequest::SetStorageAt(addr, slot, val) => {
1720 self.anvil_set_storage_at(addr, slot, val).await.to_rpc_result()
1721 }
1722 EthRequest::SetCoinbase(addr) => self.anvil_set_coinbase(addr).await.to_rpc_result(),
1723 EthRequest::SetChainId(id) => self.anvil_set_chain_id(id).await.to_rpc_result(),
1724 EthRequest::SetLogging(log) => self.anvil_set_logging(log).await.to_rpc_result(),
1725 EthRequest::SetMinGasPrice(gas) => {
1726 self.anvil_set_min_gas_price(gas).await.to_rpc_result()
1727 }
1728 EthRequest::SetNextBlockBaseFeePerGas(gas) => {
1729 self.anvil_set_next_block_base_fee_per_gas(gas).await.to_rpc_result()
1730 }
1731 EthRequest::DumpState(preserve_historical_states) => self
1732 .anvil_dump_state(preserve_historical_states.and_then(|s| s.params))
1733 .await
1734 .to_rpc_result(),
1735 EthRequest::LoadState(buf) => self.anvil_load_state(buf).await.to_rpc_result(),
1736 EthRequest::NodeInfo(_) => self.anvil_node_info().await.to_rpc_result(),
1737 EthRequest::AnvilMetadata(_) => self.anvil_metadata().await.to_rpc_result(),
1738 EthRequest::EvmSnapshot(_) => self.evm_snapshot().await.to_rpc_result(),
1739 EthRequest::EvmRevert(id) => self.evm_revert(id).await.to_rpc_result(),
1740 EthRequest::EvmIncreaseTime(time) => self.evm_increase_time(time).await.to_rpc_result(),
1741 EthRequest::EvmSetNextBlockTimeStamp(time) => {
1742 if time >= U256::from(u64::MAX) {
1743 return ResponseResult::Error(RpcError::invalid_params(
1744 "The timestamp is too big",
1745 ));
1746 }
1747 let time = time.to::<u64>();
1748 self.evm_set_next_block_timestamp(time).to_rpc_result()
1749 }
1750 EthRequest::EvmSetTime(timestamp) => {
1751 if timestamp >= U256::from(u64::MAX) {
1752 return ResponseResult::Error(RpcError::invalid_params(
1753 "The timestamp is too big",
1754 ));
1755 }
1756 let time = timestamp.to::<u64>();
1757 self.evm_set_time(time).to_rpc_result()
1758 }
1759 EthRequest::EvmSetBlockGasLimit(gas_limit) => {
1760 self.evm_set_block_gas_limit(gas_limit).to_rpc_result()
1761 }
1762 EthRequest::EvmSetBlockTimeStampInterval(time) => {
1763 self.evm_set_block_timestamp_interval(time).to_rpc_result()
1764 }
1765 EthRequest::EvmRemoveBlockTimeStampInterval(()) => {
1766 self.evm_remove_block_timestamp_interval().to_rpc_result()
1767 }
1768 EthRequest::EvmMine(mine) => {
1769 self.evm_mine(mine.and_then(|p| p.params)).await.to_rpc_result()
1770 }
1771 EthRequest::EvmMineDetailed(mine) => {
1772 self.evm_mine_detailed(mine.and_then(|p| p.params)).await.to_rpc_result()
1773 }
1774 EthRequest::SetRpcUrl(url) => self.anvil_set_rpc_url(url).to_rpc_result(),
1775 EthRequest::EthSendUnsignedTransaction(tx) => {
1776 self.eth_send_unsigned_transaction(*tx).await.to_rpc_result()
1777 }
1778 EthRequest::EthNewFilter(filter) => self.new_filter(filter).await.to_rpc_result(),
1779 EthRequest::EthGetFilterChanges(id) => self.get_filter_changes(&id).await,
1780 EthRequest::EthNewBlockFilter(_) => self.new_block_filter().await.to_rpc_result(),
1781 EthRequest::EthNewPendingTransactionFilter(_) => {
1782 self.new_pending_transaction_filter().await.to_rpc_result()
1783 }
1784 EthRequest::EthGetFilterLogs(id) => self.get_filter_logs(&id).await.to_rpc_result(),
1785 EthRequest::EthUninstallFilter(id) => self.uninstall_filter(&id).await.to_rpc_result(),
1786 EthRequest::TxPoolStatus(_) => self.txpool_status().await.to_rpc_result(),
1787 EthRequest::TxPoolInspect(_) => self.txpool_inspect().await.to_rpc_result(),
1788 EthRequest::TxPoolContent(_) => self.txpool_content().await.to_rpc_result(),
1789 EthRequest::ErigonGetHeaderByNumber(num) => {
1790 self.erigon_get_header_by_number(num).await.to_rpc_result()
1791 }
1792 EthRequest::OtsGetApiLevel(_) => self.ots_get_api_level().await.to_rpc_result(),
1793 EthRequest::OtsGetInternalOperations(hash) => {
1794 self.ots_get_internal_operations(hash).await.to_rpc_result()
1795 }
1796 EthRequest::OtsHasCode(addr, num) => self.ots_has_code(addr, num).await.to_rpc_result(),
1797 EthRequest::OtsTraceTransaction(hash) => {
1798 self.ots_trace_transaction(hash).await.to_rpc_result()
1799 }
1800 EthRequest::OtsGetTransactionError(hash) => {
1801 self.ots_get_transaction_error(hash).await.to_rpc_result()
1802 }
1803 EthRequest::OtsGetBlockDetails(num) => {
1804 self.ots_get_block_details(num).await.to_rpc_result()
1805 }
1806 EthRequest::OtsGetBlockDetailsByHash(hash) => {
1807 self.ots_get_block_details_by_hash(hash).await.to_rpc_result()
1808 }
1809 EthRequest::OtsGetBlockTransactions(num, page, page_size) => {
1810 self.ots_get_block_transactions(num, page, page_size).await.to_rpc_result()
1811 }
1812 EthRequest::OtsSearchTransactionsBefore(address, num, page_size) => {
1813 self.ots_search_transactions_before(address, num, page_size).await.to_rpc_result()
1814 }
1815 EthRequest::OtsSearchTransactionsAfter(address, num, page_size) => {
1816 self.ots_search_transactions_after(address, num, page_size).await.to_rpc_result()
1817 }
1818 EthRequest::OtsGetTransactionBySenderAndNonce(address, nonce) => {
1819 self.ots_get_transaction_by_sender_and_nonce(address, nonce).await.to_rpc_result()
1820 }
1821 EthRequest::EthGetTransactionBySenderAndNonce(sender, nonce) => {
1822 self.transaction_by_sender_and_nonce(sender, nonce).await.to_rpc_result()
1823 }
1824 EthRequest::OtsGetContractCreator(address) => {
1825 self.ots_get_contract_creator(address).await.to_rpc_result()
1826 }
1827 EthRequest::RemovePoolTransactions(address) => {
1828 self.anvil_remove_pool_transactions(address).await.to_rpc_result()
1829 }
1830 EthRequest::Reorg(reorg_options) => {
1831 self.anvil_reorg(reorg_options).await.to_rpc_result()
1832 }
1833 EthRequest::Rollback(depth) => self.anvil_rollback(depth).await.to_rpc_result(),
1834 };
1835
1836 if let ResponseResult::Error(err) = &response {
1837 node_info!("\nRPC request failed:");
1838 node_info!(" Request: {:?}", request);
1839 node_info!(" Error: {}\n", err);
1840 }
1841
1842 response
1843 }
1844
1845 fn sign_request(&self, from: &Address, typed_tx: FoundryTypedTx) -> Result<FoundryTxEnvelope> {
1846 match typed_tx {
1847 FoundryTypedTx::Deposit(_) => return Ok(build_impersonated(typed_tx)),
1848 _ => {
1849 for signer in self.signers.iter() {
1850 if signer.accounts().contains(from) {
1851 return signer.sign_transaction_from(from, typed_tx);
1852 }
1853 }
1854 }
1855 }
1856 Err(BlockchainError::NoSignerAvailable)
1857 }
1858
1859 async fn inner_raw_transaction(&self, hash: B256) -> Result<Option<Bytes>> {
1860 match self.pool.get_transaction(hash) {
1861 Some(tx) => Ok(Some(tx.transaction.encoded_2718().into())),
1862 None => match self.backend.transaction_by_hash(hash).await? {
1863 Some(tx) => Ok(Some(tx.as_ref().encoded_2718().into())),
1864 None => Ok(None),
1865 },
1866 }
1867 }
1868
1869 pub async fn balance(&self, address: Address, block_number: Option<BlockId>) -> Result<U256> {
1873 node_info!("eth_getBalance");
1874 let block_request = self.block_request(block_number).await?;
1875
1876 if let BlockRequest::Number(number) = block_request
1878 && let Some(fork) = self.get_fork()
1879 && fork.predates_fork(number)
1880 {
1881 return Ok(fork.get_balance(address, number).await?);
1882 }
1883
1884 self.backend.get_balance(address, Some(block_request)).await
1885 }
1886
1887 pub async fn get_account(
1891 &self,
1892 address: Address,
1893 block_number: Option<BlockId>,
1894 ) -> Result<TrieAccount> {
1895 node_info!("eth_getAccount");
1896 let block_request = self.block_request(block_number).await?;
1897
1898 if let BlockRequest::Number(number) = block_request
1900 && let Some(fork) = self.get_fork()
1901 && fork.predates_fork(number)
1902 {
1903 return Ok(fork.get_account(address, number).await?);
1904 }
1905
1906 self.backend.get_account_at_block(address, Some(block_request)).await
1907 }
1908
1909 pub async fn get_account_info(
1913 &self,
1914 address: Address,
1915 block_number: Option<BlockId>,
1916 ) -> Result<alloy_rpc_types::eth::AccountInfo> {
1917 node_info!("eth_getAccountInfo");
1918
1919 if let Some(fork) = self.get_fork() {
1920 let block_request = self.block_request(block_number).await?;
1921 if let BlockRequest::Number(number) = block_request {
1923 trace!(target: "node", "get_account_info: fork block {}, requested block {number}", fork.block_number());
1924 return if fork.predates_fork(number) {
1925 let balance = fork.get_balance(address, number).map_err(BlockchainError::from);
1928 let code = fork.get_code(address, number).map_err(BlockchainError::from);
1929 let nonce = self.get_transaction_count(address, Some(number.into()));
1930 let (balance, code, nonce) = try_join!(balance, code, nonce)?;
1931
1932 Ok(alloy_rpc_types::eth::AccountInfo { balance, nonce, code })
1933 } else {
1934 let account_info = self.backend.get_account(address).await?;
1937 let code = self.backend.get_code(address, Some(block_request)).await?;
1938 Ok(alloy_rpc_types::eth::AccountInfo {
1939 balance: account_info.balance,
1940 nonce: account_info.nonce,
1941 code,
1942 })
1943 };
1944 }
1945 }
1946
1947 let account = self.get_account(address, block_number);
1948 let code = self.get_code(address, block_number);
1949 let (account, code) = try_join!(account, code)?;
1950 Ok(alloy_rpc_types::eth::AccountInfo {
1951 balance: account.balance,
1952 nonce: account.nonce,
1953 code,
1954 })
1955 }
1956 pub async fn storage_at(
1960 &self,
1961 address: Address,
1962 index: U256,
1963 block_number: Option<BlockId>,
1964 ) -> Result<B256> {
1965 node_info!("eth_getStorageAt");
1966 let block_request = self.block_request(block_number).await?;
1967
1968 if let BlockRequest::Number(number) = block_request
1970 && let Some(fork) = self.get_fork()
1971 && fork.predates_fork(number)
1972 {
1973 return Ok(B256::from(
1974 fork.storage_at(address, index, Some(BlockNumber::Number(number))).await?,
1975 ));
1976 }
1977
1978 self.backend.storage_at(address, index, Some(block_request)).await
1979 }
1980
1981 pub async fn storage_values(
1985 &self,
1986 requests: HashMap<Address, Vec<B256>>,
1987 block_number: Option<BlockId>,
1988 ) -> Result<HashMap<Address, Vec<B256>>> {
1989 node_info!("eth_getStorageValues");
1990
1991 let total_slots: usize = requests.values().map(|s| s.len()).sum();
1992 if total_slots > 1024 {
1993 return Err(BlockchainError::RpcError(RpcError::invalid_params(format!(
1994 "total slot count {total_slots} exceeds limit 1024"
1995 ))));
1996 }
1997
1998 let block_request = self.block_request(block_number).await?;
1999
2000 if let BlockRequest::Number(number) = block_request
2002 && let Some(fork) = self.get_fork()
2003 && fork.predates_fork(number)
2004 {
2005 let mut result: HashMap<Address, Vec<B256>> = HashMap::default();
2006 for (address, slots) in requests {
2007 let mut values = Vec::with_capacity(slots.len());
2008 for slot in &slots {
2009 let val = fork
2010 .storage_at(address, (*slot).into(), Some(BlockNumber::Number(number)))
2011 .await?;
2012 values.push(B256::from(val));
2013 }
2014 result.insert(address, values);
2015 }
2016 return Ok(result);
2017 }
2018
2019 self.backend.storage_values(requests, Some(block_request)).await
2020 }
2021
2022 pub async fn block_by_number(&self, number: BlockNumber) -> Result<Option<AnyRpcBlock>> {
2026 node_info!("eth_getBlockByNumber");
2027 if number == BlockNumber::Pending {
2028 return Ok(Some(self.pending_block().await));
2029 }
2030
2031 self.backend.block_by_number(number).await
2032 }
2033
2034 pub async fn block_by_number_full(&self, number: BlockNumber) -> Result<Option<AnyRpcBlock>> {
2038 node_info!("eth_getBlockByNumber");
2039 if number == BlockNumber::Pending {
2040 return Ok(self.pending_block_full().await);
2041 }
2042 self.backend.block_by_number_full(number).await
2043 }
2044
2045 pub async fn transaction_count(
2052 &self,
2053 address: Address,
2054 block_number: Option<BlockId>,
2055 ) -> Result<U256> {
2056 node_info!("eth_getTransactionCount");
2057 self.get_transaction_count(address, block_number).await.map(U256::from)
2058 }
2059
2060 pub async fn block_transaction_count_by_number(
2064 &self,
2065 block_number: BlockNumber,
2066 ) -> Result<Option<U256>> {
2067 node_info!("eth_getBlockTransactionCountByNumber");
2068 let block_request = self.block_request(Some(block_number.into())).await?;
2069 if let BlockRequest::Pending(txs) = block_request {
2070 let block = self.backend.pending_block(txs).await;
2071 return Ok(Some(U256::from(block.block.body.transactions.len())));
2072 }
2073 let block = self.backend.block_by_number(block_number).await?;
2074 let txs = block.map(|b| match b.transactions() {
2075 BlockTransactions::Full(txs) => U256::from(txs.len()),
2076 BlockTransactions::Hashes(txs) => U256::from(txs.len()),
2077 BlockTransactions::Uncle => U256::from(0),
2078 });
2079 Ok(txs)
2080 }
2081
2082 pub async fn get_code(&self, address: Address, block_number: Option<BlockId>) -> Result<Bytes> {
2086 node_info!("eth_getCode");
2087 let block_request = self.block_request(block_number).await?;
2088 if let BlockRequest::Number(number) = block_request
2090 && let Some(fork) = self.get_fork()
2091 && fork.predates_fork(number)
2092 {
2093 return Ok(fork.get_code(address, number).await?);
2094 }
2095 self.backend.get_code(address, Some(block_request)).await
2096 }
2097
2098 pub async fn get_proof(
2103 &self,
2104 address: Address,
2105 keys: Vec<B256>,
2106 block_number: Option<BlockId>,
2107 ) -> Result<EIP1186AccountProofResponse> {
2108 node_info!("eth_getProof");
2109 let block_request = self.block_request(block_number).await?;
2110
2111 if let BlockRequest::Number(number) = block_request
2114 && let Some(fork) = self.get_fork()
2115 && fork.predates_fork_inclusive(number)
2116 {
2117 return Ok(fork.get_proof(address, keys, Some(number.into())).await?);
2118 }
2119
2120 let proof = self.backend.prove_account_at(address, keys, Some(block_request)).await?;
2121 Ok(proof)
2122 }
2123
2124 pub async fn sign_transaction(
2128 &self,
2129 request: WithOtherFields<TransactionRequest>,
2130 ) -> Result<String> {
2131 node_info!("eth_signTransaction");
2132
2133 let from = request.from.map(Ok).unwrap_or_else(|| {
2134 self.accounts()?.first().copied().ok_or(BlockchainError::NoSignerAvailable)
2135 })?;
2136
2137 let (nonce, _) = self.request_nonce(&request, from).await?;
2138
2139 let request = self.build_tx_request(request, nonce).await?;
2140
2141 let signed_transaction = self.sign_request(&from, request)?.encoded_2718();
2142 Ok(alloy_primitives::hex::encode_prefixed(signed_transaction))
2143 }
2144
2145 pub async fn send_transaction(
2149 &self,
2150 request: WithOtherFields<TransactionRequest>,
2151 ) -> Result<TxHash> {
2152 node_info!("eth_sendTransaction");
2153
2154 let from = request.from.map(Ok).unwrap_or_else(|| {
2155 self.accounts()?.first().copied().ok_or(BlockchainError::NoSignerAvailable)
2156 })?;
2157 let (nonce, on_chain_nonce) = self.request_nonce(&request, from).await?;
2158
2159 let typed_tx = self.build_tx_request(request, nonce).await?;
2160
2161 let pending_transaction = if self.is_impersonated(from) {
2163 let transaction = sign::build_impersonated(typed_tx);
2164 self.ensure_typed_transaction_supported(&transaction)?;
2165 trace!(target : "node", ?from, "eth_sendTransaction: impersonating");
2166 PendingTransaction::with_impersonated(transaction, from)
2167 } else {
2168 let transaction = self.sign_request(&from, typed_tx)?;
2169 self.ensure_typed_transaction_supported(&transaction)?;
2170 PendingTransaction::new(transaction)?
2171 };
2172 self.backend.validate_pool_transaction(&pending_transaction).await?;
2174
2175 let requires = required_marker(nonce, on_chain_nonce, from);
2176 let provides = vec![to_marker(nonce, from)];
2177 debug_assert!(requires != provides);
2178
2179 self.add_pending_transaction(pending_transaction, requires, provides)
2180 }
2181
2182 async fn await_transaction_inclusion(&self, hash: TxHash) -> Result<FoundryTxReceipt> {
2184 let mut stream = self.new_block_notifications();
2185 if let Some(receipt) = self.backend.transaction_receipt(hash).await? {
2187 return Ok(receipt);
2188 }
2189 while let Some(notification) = stream.next().await {
2190 if let Some(block) = self.backend.get_block_by_hash(notification.hash)
2191 && block.body.transactions.iter().any(|tx| tx.hash() == hash)
2192 && let Some(receipt) = self.backend.transaction_receipt(hash).await?
2193 {
2194 return Ok(receipt);
2195 }
2196 }
2197
2198 Err(BlockchainError::Message("Failed to await transaction inclusion".to_string()))
2199 }
2200
2201 async fn check_transaction_inclusion(&self, hash: TxHash) -> Result<FoundryTxReceipt> {
2203 const TIMEOUT_DURATION: Duration = Duration::from_secs(30);
2204 tokio::time::timeout(TIMEOUT_DURATION, self.await_transaction_inclusion(hash))
2205 .await
2206 .unwrap_or_else(|_elapsed| {
2207 Err(BlockchainError::TransactionConfirmationTimeout {
2208 hash,
2209 duration: TIMEOUT_DURATION,
2210 })
2211 })
2212 }
2213
2214 pub async fn send_transaction_sync(
2218 &self,
2219 request: WithOtherFields<TransactionRequest>,
2220 ) -> Result<FoundryTxReceipt> {
2221 node_info!("eth_sendTransactionSync");
2222 let hash = self.send_transaction(request).await?;
2223
2224 let receipt = self.check_transaction_inclusion(hash).await?;
2225
2226 Ok(receipt)
2227 }
2228
2229 pub async fn send_raw_transaction(&self, tx: Bytes) -> Result<TxHash> {
2233 node_info!("eth_sendRawTransaction");
2234 let mut data = tx.as_ref();
2235 if data.is_empty() {
2236 return Err(BlockchainError::EmptyRawTransactionData);
2237 }
2238
2239 let transaction = FoundryTxEnvelope::decode_2718(&mut data)
2240 .map_err(|_| BlockchainError::FailedToDecodeSignedTransaction)?;
2241
2242 self.ensure_typed_transaction_supported(&transaction)?;
2243
2244 let pending_transaction = PendingTransaction::new(transaction)?;
2245
2246 self.backend.validate_pool_transaction(&pending_transaction).await?;
2248
2249 let from = *pending_transaction.sender();
2250 let priority = self.transaction_priority(&pending_transaction.transaction);
2251
2252 let (requires, provides) = if let FoundryTxEnvelope::Tempo(aa_tx) =
2254 pending_transaction.transaction.as_ref()
2255 && !aa_tx.tx().nonce_key.is_zero()
2256 {
2257 (vec![], vec![pending_transaction.hash().to_vec()])
2258 } else {
2259 let on_chain_nonce = self.backend.current_nonce(from).await?;
2260 let nonce = pending_transaction.transaction.nonce();
2261 (required_marker(nonce, on_chain_nonce, from), vec![to_marker(nonce, from)])
2262 };
2263
2264 let pool_transaction =
2265 PoolTransaction { requires, provides, pending_transaction, priority };
2266
2267 let tx = self.pool.add_transaction(pool_transaction)?;
2268 trace!(target: "node", "Added transaction: [{:?}] sender={:?}", tx.hash(), from);
2269 Ok(*tx.hash())
2270 }
2271
2272 pub async fn send_raw_transaction_sync(&self, tx: Bytes) -> Result<FoundryTxReceipt> {
2276 node_info!("eth_sendRawTransactionSync");
2277
2278 let hash = self.send_raw_transaction(tx).await?;
2279 let receipt = self.check_transaction_inclusion(hash).await?;
2280
2281 Ok(receipt)
2282 }
2283
2284 pub async fn call(
2288 &self,
2289 request: WithOtherFields<TransactionRequest>,
2290 block_number: Option<BlockId>,
2291 overrides: EvmOverrides,
2292 ) -> Result<Bytes> {
2293 node_info!("eth_call");
2294 let block_request = self.block_request(block_number).await?;
2295 if let BlockRequest::Number(number) = block_request
2297 && let Some(fork) = self.get_fork()
2298 && fork.predates_fork(number)
2299 {
2300 if overrides.has_state() || overrides.has_block() {
2301 return Err(BlockchainError::EvmOverrideError(
2302 "not available on past forked blocks".to_string(),
2303 ));
2304 }
2305 return Ok(fork.call(&request, Some(number.into())).await?);
2306 }
2307
2308 let fees = FeeDetails::new(
2309 request.gas_price,
2310 request.max_fee_per_gas,
2311 request.max_priority_fee_per_gas,
2312 request.max_fee_per_blob_gas,
2313 )?
2314 .or_zero_fees();
2315 self.on_blocking_task(|this| async move {
2318 let (exit, out, gas, _) =
2319 this.backend.call(request, fees, Some(block_request), overrides).await?;
2320 trace!(target : "node", "Call status {:?}, gas {}", exit, gas);
2321
2322 ensure_return_ok(exit, &out)
2323 })
2324 .await
2325 }
2326
2327 pub async fn simulate_v1(
2328 &self,
2329 request: SimulatePayload,
2330 block_number: Option<BlockId>,
2331 ) -> Result<Vec<SimulatedBlock<AnyRpcBlock>>> {
2332 node_info!("eth_simulateV1");
2333 let block_request = self.block_request(block_number).await?;
2334 if let BlockRequest::Number(number) = block_request
2336 && let Some(fork) = self.get_fork()
2337 && fork.predates_fork(number)
2338 {
2339 return Ok(fork.simulate_v1(&request, Some(number.into())).await?);
2340 }
2341
2342 self.on_blocking_task(|this| async move {
2345 let simulated_blocks = this.backend.simulate(request, Some(block_request)).await?;
2346 trace!(target : "node", "Simulate status {:?}", simulated_blocks);
2347
2348 Ok(simulated_blocks)
2349 })
2350 .await
2351 }
2352
2353 pub async fn create_access_list(
2367 &self,
2368 mut request: WithOtherFields<TransactionRequest>,
2369 block_number: Option<BlockId>,
2370 ) -> Result<AccessListResult> {
2371 node_info!("eth_createAccessList");
2372 let block_request = self.block_request(block_number).await?;
2373 if let BlockRequest::Number(number) = block_request
2375 && let Some(fork) = self.get_fork()
2376 && fork.predates_fork(number)
2377 {
2378 return Ok(fork.create_access_list(&request, Some(number.into())).await?);
2379 }
2380
2381 self.backend
2382 .with_database_at(Some(block_request), |state, block_env| {
2383 let (exit, out, _, access_list) = self.backend.build_access_list_with_state(
2384 &state,
2385 request.clone(),
2386 FeeDetails::zero(),
2387 block_env.clone(),
2388 )?;
2389 ensure_return_ok(exit, &out)?;
2390
2391 request.access_list = Some(access_list.clone());
2393
2394 let (exit, out, gas_used, _) =
2395 self.backend.call_with_state(&state, request, FeeDetails::zero(), block_env)?;
2396 ensure_return_ok(exit, &out)?;
2397
2398 Ok(AccessListResult {
2399 access_list: AccessList(access_list.0),
2400 gas_used: U256::from(gas_used),
2401 error: None,
2402 })
2403 })
2404 .await?
2405 }
2406
2407 pub async fn estimate_gas(
2412 &self,
2413 request: WithOtherFields<TransactionRequest>,
2414 block_number: Option<BlockId>,
2415 overrides: EvmOverrides,
2416 ) -> Result<U256> {
2417 node_info!("eth_estimateGas");
2418 self.do_estimate_gas(
2419 request,
2420 block_number.or_else(|| Some(BlockNumber::Pending.into())),
2421 overrides,
2422 )
2423 .await
2424 .map(U256::from)
2425 }
2426
2427 pub async fn fill_transaction(
2434 &self,
2435 mut request: WithOtherFields<TransactionRequest>,
2436 ) -> Result<FillTransaction<AnyRpcTransaction>> {
2437 node_info!("eth_fillTransaction");
2438
2439 let from = match request.as_ref().from() {
2440 Some(from) => from,
2441 None => self.accounts()?.first().copied().ok_or(BlockchainError::NoSignerAvailable)?,
2442 };
2443
2444 let nonce = if let Some(nonce) = request.as_ref().nonce() {
2445 nonce
2446 } else {
2447 self.request_nonce(&request, from).await?.0
2448 };
2449
2450 if request.as_ref().gas_limit().is_none() {
2454 let estimated_gas =
2455 self.estimate_gas(request.clone(), None, EvmOverrides::default()).await?;
2456 request.as_mut().set_gas_limit(estimated_gas.to());
2457 }
2458
2459 let typed_tx = self.build_tx_request(request, nonce).await?;
2460 let tx = build_impersonated(typed_tx);
2461
2462 let raw = tx.encoded_2718().into();
2463
2464 let mut tx =
2465 transaction_build(None, MaybeImpersonatedTransaction::new(tx), None, None, None);
2466
2467 tx.0.inner.inner = Recovered::new_unchecked(tx.0.inner.inner.into_inner(), from);
2470
2471 Ok(FillTransaction { raw, tx })
2472 }
2473
2474 pub fn anvil_get_blob_by_tx_hash(&self, hash: B256) -> Result<Option<Vec<Blob>>> {
2476 node_info!("anvil_getBlobsByTransactionHash");
2477 Ok(self.backend.get_blob_by_tx_hash(hash)?)
2478 }
2479
2480 pub async fn transaction_by_hash(&self, hash: B256) -> Result<Option<AnyRpcTransaction>> {
2487 node_info!("eth_getTransactionByHash");
2488 let mut tx = self.pool.get_transaction(hash).map(|pending| {
2489 let from = *pending.sender();
2490 let tx = transaction_build(
2491 Some(*pending.hash()),
2492 pending.transaction,
2493 None,
2494 None,
2495 Some(self.backend.base_fee()),
2496 );
2497
2498 let WithOtherFields { inner: mut tx, other } = tx.0;
2499 tx.inner = Recovered::new_unchecked(tx.inner.into_inner(), from);
2502
2503 AnyRpcTransaction(WithOtherFields { inner: tx, other })
2504 });
2505 if tx.is_none() {
2506 tx = self.backend.transaction_by_hash(hash).await?
2507 }
2508
2509 Ok(tx)
2510 }
2511
2512 pub async fn transaction_by_sender_and_nonce(
2519 &self,
2520 sender: Address,
2521 nonce: U256,
2522 ) -> Result<Option<AnyRpcTransaction>> {
2523 node_info!("eth_getTransactionBySenderAndNonce");
2524
2525 for pending_tx in self.pool.ready_transactions().chain(self.pool.pending_transactions()) {
2527 if U256::from(pending_tx.pending_transaction.nonce()) == nonce
2528 && *pending_tx.pending_transaction.sender() == sender
2529 {
2530 let tx = transaction_build(
2531 Some(*pending_tx.pending_transaction.hash()),
2532 pending_tx.pending_transaction.transaction.clone(),
2533 None,
2534 None,
2535 Some(self.backend.base_fee()),
2536 );
2537
2538 let WithOtherFields { inner: mut tx, other } = tx.0;
2539 let from = *pending_tx.pending_transaction.sender();
2542 tx.inner = Recovered::new_unchecked(tx.inner.into_inner(), from);
2543
2544 return Ok(Some(AnyRpcTransaction(WithOtherFields { inner: tx, other })));
2545 }
2546 }
2547
2548 let highest_nonce = self.transaction_count(sender, None).await?.saturating_to::<u64>();
2549 let target_nonce = nonce.saturating_to::<u64>();
2550
2551 if target_nonce >= highest_nonce {
2553 return Ok(None);
2554 }
2555
2556 let latest_block = self.backend.best_number();
2558 if latest_block == 0 {
2559 return Ok(None);
2560 }
2561
2562 let mut low = 1u64;
2564 let mut high = latest_block;
2565
2566 while low <= high {
2567 let mid = low + (high - low) / 2;
2568 let mid_nonce =
2569 self.transaction_count(sender, Some(mid.into())).await?.saturating_to::<u64>();
2570
2571 if mid_nonce > target_nonce {
2572 high = mid - 1;
2573 } else {
2574 low = mid + 1;
2575 }
2576 }
2577
2578 let target_block = low;
2580 if target_block <= latest_block
2581 && let Some(txs) =
2582 self.backend.mined_transactions_by_block_number(target_block.into()).await
2583 {
2584 for tx in txs {
2585 if tx.from() == sender && tx.nonce() == target_nonce {
2586 return Ok(Some(tx));
2587 }
2588 }
2589 }
2590
2591 Ok(None)
2592 }
2593
2594 pub async fn transaction_receipt(&self, hash: B256) -> Result<Option<FoundryTxReceipt>> {
2598 node_info!("eth_getTransactionReceipt");
2599 self.backend.transaction_receipt(hash).await
2600 }
2601
2602 pub async fn block_receipts(&self, number: BlockId) -> Result<Option<Vec<FoundryTxReceipt>>> {
2606 node_info!("eth_getBlockReceipts");
2607 self.backend.block_receipts(number).await
2608 }
2609
2610 pub async fn logs(&self, filter: Filter) -> Result<Vec<Log>> {
2614 node_info!("eth_getLogs");
2615 self.backend.logs(filter).await
2616 }
2617
2618 pub async fn new_filter(&self, filter: Filter) -> Result<String> {
2622 node_info!("eth_newFilter");
2623 let historic = if filter.block_option.get_from_block().is_some() {
2626 self.backend.logs(filter.clone()).await?
2627 } else {
2628 vec![]
2629 };
2630 let filter = EthFilter::Logs(Box::new(LogsFilter {
2631 blocks: self.new_block_notifications(),
2632 storage: self.storage_info(),
2633 filter: FilteredParams::new(Some(filter)),
2634 historic: Some(historic),
2635 }));
2636 Ok(self.filters.add_filter(filter).await)
2637 }
2638
2639 pub async fn new_block_filter(&self) -> Result<String> {
2643 node_info!("eth_newBlockFilter");
2644 let filter = EthFilter::Blocks(self.new_block_notifications());
2645 Ok(self.filters.add_filter(filter).await)
2646 }
2647
2648 pub async fn new_pending_transaction_filter(&self) -> Result<String> {
2652 node_info!("eth_newPendingTransactionFilter");
2653 let filter = EthFilter::PendingTransactions(self.new_ready_transactions());
2654 Ok(self.filters.add_filter(filter).await)
2655 }
2656
2657 pub async fn get_filter_changes(&self, id: &str) -> ResponseResult {
2661 node_info!("eth_getFilterChanges");
2662 self.filters.get_filter_changes(id).await
2663 }
2664
2665 pub async fn get_filter_logs(&self, id: &str) -> Result<Vec<Log>> {
2669 node_info!("eth_getFilterLogs");
2670 if let Some(filter) = self.filters.get_log_filter(id).await {
2671 self.backend.logs(filter).await
2672 } else {
2673 Err(BlockchainError::FilterNotFound)
2674 }
2675 }
2676
2677 pub async fn uninstall_filter(&self, id: &str) -> Result<bool> {
2679 node_info!("eth_uninstallFilter");
2680 Ok(self.filters.uninstall_filter(id).await.is_some())
2681 }
2682
2683 pub async fn raw_transaction(&self, hash: B256) -> Result<Option<Bytes>> {
2687 node_info!("debug_getRawTransaction");
2688 self.inner_raw_transaction(hash).await
2689 }
2690
2691 pub async fn raw_transaction_by_block_hash_and_index(
2695 &self,
2696 block_hash: B256,
2697 index: Index,
2698 ) -> Result<Option<Bytes>> {
2699 node_info!("eth_getRawTransactionByBlockHashAndIndex");
2700 match self.backend.transaction_by_block_hash_and_index(block_hash, index).await? {
2701 Some(tx) => self.inner_raw_transaction(tx.tx_hash()).await,
2702 None => Ok(None),
2703 }
2704 }
2705
2706 pub async fn raw_transaction_by_block_number_and_index(
2710 &self,
2711 block_number: BlockNumber,
2712 index: Index,
2713 ) -> Result<Option<Bytes>> {
2714 node_info!("eth_getRawTransactionByBlockNumberAndIndex");
2715 match self.backend.transaction_by_block_number_and_index(block_number, index).await? {
2716 Some(tx) => self.inner_raw_transaction(tx.tx_hash()).await,
2717 None => Ok(None),
2718 }
2719 }
2720
2721 pub async fn debug_trace_transaction(
2725 &self,
2726 tx_hash: B256,
2727 opts: GethDebugTracingOptions,
2728 ) -> Result<GethTrace> {
2729 node_info!("debug_traceTransaction");
2730 self.backend.debug_trace_transaction(tx_hash, opts).await
2731 }
2732
2733 pub async fn debug_trace_call(
2737 &self,
2738 request: WithOtherFields<TransactionRequest>,
2739 block_number: Option<BlockId>,
2740 opts: GethDebugTracingCallOptions,
2741 ) -> Result<GethTrace> {
2742 node_info!("debug_traceCall");
2743 let block_request = self.block_request(block_number).await?;
2744 let fees = FeeDetails::new(
2745 request.gas_price,
2746 request.max_fee_per_gas,
2747 request.max_priority_fee_per_gas,
2748 request.max_fee_per_blob_gas,
2749 )?
2750 .or_zero_fees();
2751
2752 let result: std::result::Result<GethTrace, BlockchainError> =
2753 self.backend.call_with_tracing(request, fees, Some(block_request), opts).await;
2754 result
2755 }
2756}
2757
2758impl EthApi<FoundryNetwork> {
2761 pub async fn anvil_mine(&self, num_blocks: Option<U256>, interval: Option<U256>) -> Result<()> {
2765 node_info!("anvil_mine");
2766 let interval = interval.map(|i| i.to::<u64>());
2767 let blocks = num_blocks.unwrap_or(U256::from(1));
2768 if blocks.is_zero() {
2769 return Ok(());
2770 }
2771
2772 self.on_blocking_task(|this| async move {
2773 for _ in 0..blocks.to::<u64>() {
2775 if let Some(interval) = interval {
2777 this.backend.time().increase_time(interval);
2778 }
2779 this.mine_one().await;
2780 }
2781 Ok(())
2782 })
2783 .await?;
2784
2785 Ok(())
2786 }
2787
2788 async fn find_erc20_storage_slot(
2805 &self,
2806 token_address: Address,
2807 calldata: Bytes,
2808 expected_value: U256,
2809 ) -> Result<B256> {
2810 let tx = TransactionRequest::default().with_to(token_address).with_input(calldata.clone());
2811
2812 let access_list_result =
2814 self.create_access_list(WithOtherFields::new(tx.clone()), None).await?;
2815 let access_list = access_list_result.access_list;
2816
2817 for item in access_list.0 {
2820 if item.address != token_address {
2821 continue;
2822 };
2823 for slot in &item.storage_keys {
2824 let account_override = AccountOverride::default().with_state_diff(std::iter::once(
2825 (*slot, B256::from(expected_value.to_be_bytes())),
2826 ));
2827
2828 let state_override = StateOverridesBuilder::default()
2829 .append(token_address, account_override)
2830 .build();
2831
2832 let evm_override = EvmOverrides::state(Some(state_override));
2833
2834 let Ok(result) =
2835 self.call(WithOtherFields::new(tx.clone()), None, evm_override).await
2836 else {
2837 continue;
2839 };
2840
2841 let Ok(result_value) = U256::abi_decode(&result) else {
2842 continue;
2844 };
2845
2846 if result_value == expected_value {
2847 return Ok(*slot);
2848 }
2849 }
2850 }
2851
2852 Err(BlockchainError::Message("Unable to find storage slot".to_string()))
2853 }
2854
2855 pub async fn anvil_deal_erc20(
2859 &self,
2860 address: Address,
2861 token_address: Address,
2862 balance: U256,
2863 ) -> Result<()> {
2864 node_info!("anvil_dealERC20");
2865
2866 sol! {
2867 #[sol(rpc)]
2868 contract IERC20 {
2869 function balanceOf(address target) external view returns (uint256);
2870 }
2871 }
2872
2873 let calldata = IERC20::balanceOfCall { target: address }.abi_encode().into();
2874
2875 let slot =
2877 self.find_erc20_storage_slot(token_address, calldata, balance).await.map_err(|_| {
2878 BlockchainError::Message("Unable to set ERC20 balance, no slot found".to_string())
2879 })?;
2880
2881 self.anvil_set_storage_at(
2883 token_address,
2884 U256::from_be_bytes(slot.0),
2885 B256::from(balance.to_be_bytes()),
2886 )
2887 .await?;
2888
2889 Ok(())
2890 }
2891
2892 pub async fn anvil_set_erc20_allowance(
2896 &self,
2897 owner: Address,
2898 spender: Address,
2899 token_address: Address,
2900 amount: U256,
2901 ) -> Result<()> {
2902 node_info!("anvil_setERC20Allowance");
2903
2904 sol! {
2905 #[sol(rpc)]
2906 contract IERC20 {
2907 function allowance(address owner, address spender) external view returns (uint256);
2908 }
2909 }
2910
2911 let calldata = IERC20::allowanceCall { owner, spender }.abi_encode().into();
2912
2913 let slot =
2915 self.find_erc20_storage_slot(token_address, calldata, amount).await.map_err(|_| {
2916 BlockchainError::Message("Unable to set ERC20 allowance, no slot found".to_string())
2917 })?;
2918
2919 self.anvil_set_storage_at(
2921 token_address,
2922 U256::from_be_bytes(slot.0),
2923 B256::from(amount.to_be_bytes()),
2924 )
2925 .await?;
2926
2927 Ok(())
2928 }
2929
2930 pub async fn anvil_reorg(&self, options: ReorgOptions) -> Result<()> {
2944 node_info!("anvil_reorg");
2945 let depth = options.depth;
2946 let tx_block_pairs = options.tx_block_pairs;
2947
2948 let current_height = self.backend.best_number();
2950 let common_height = current_height.checked_sub(depth).ok_or(BlockchainError::RpcError(
2951 RpcError::invalid_params(format!(
2952 "Reorg depth must not exceed current chain height: current height {current_height}, depth {depth}"
2953 )),
2954 ))?;
2955
2956 let common_block =
2958 self.backend.get_block(common_height).ok_or(BlockchainError::BlockNotFound)?;
2959
2960 let block_pool_txs = if tx_block_pairs.is_empty() {
2963 HashMap::default()
2964 } else {
2965 let mut pairs = tx_block_pairs;
2966
2967 if let Some((_, num)) = pairs.iter().find(|(_, num)| *num >= depth) {
2969 return Err(BlockchainError::RpcError(RpcError::invalid_params(format!(
2970 "Block number for reorg tx will exceed the reorged chain height. Block number {num} must not exceed (depth-1) {}",
2971 depth - 1
2972 ))));
2973 }
2974
2975 pairs.sort_by_key(|a| a.1);
2977
2978 let mut nonces: HashMap<Address, u64> = HashMap::default();
2981
2982 let mut txs: HashMap<u64, Vec<Arc<PoolTransaction<FoundryTxEnvelope>>>> =
2983 HashMap::default();
2984 for pair in pairs {
2985 let (tx_data, block_index) = pair;
2986
2987 let pending = match tx_data {
2988 TransactionData::Raw(bytes) => {
2989 let mut data = bytes.as_ref();
2990 let decoded = FoundryTxEnvelope::decode_2718(&mut data)
2991 .map_err(|_| BlockchainError::FailedToDecodeSignedTransaction)?;
2992 PendingTransaction::new(decoded)?
2993 }
2994
2995 TransactionData::JSON(request) => {
2996 let from = request.from.map(Ok).unwrap_or_else(|| {
2997 self.accounts()?
2998 .first()
2999 .copied()
3000 .ok_or(BlockchainError::NoSignerAvailable)
3001 })?;
3002
3003 let curr_nonce = nonces.entry(from).or_insert(
3005 self.get_transaction_count(
3006 from,
3007 Some(common_block.header.number().into()),
3008 )
3009 .await?,
3010 );
3011
3012 let typed_tx = self.build_tx_request(request.into(), *curr_nonce).await?;
3014
3015 *curr_nonce += 1;
3017
3018 if self.is_impersonated(from) {
3020 let transaction = sign::build_impersonated(typed_tx);
3021 self.ensure_typed_transaction_supported(&transaction)?;
3022 PendingTransaction::with_impersonated(transaction, from)
3023 } else {
3024 let transaction = self.sign_request(&from, typed_tx)?;
3025 self.ensure_typed_transaction_supported(&transaction)?;
3026 PendingTransaction::new(transaction)?
3027 }
3028 }
3029 };
3030
3031 let pooled = PoolTransaction::new(pending);
3032 txs.entry(block_index).or_default().push(Arc::new(pooled));
3033 }
3034
3035 txs
3036 };
3037
3038 self.backend.reorg(depth, block_pool_txs, common_block).await?;
3039 Ok(())
3040 }
3041
3042 pub async fn evm_mine(&self, opts: Option<MineOptions>) -> Result<String> {
3049 node_info!("evm_mine");
3050
3051 self.do_evm_mine(opts).await?;
3052
3053 Ok("0x0".to_string())
3054 }
3055
3056 pub async fn evm_mine_detailed(&self, opts: Option<MineOptions>) -> Result<Vec<AnyRpcBlock>> {
3066 node_info!("evm_mine_detailed");
3067
3068 let mined_blocks = self.do_evm_mine(opts).await?;
3069
3070 let mut blocks = Vec::with_capacity(mined_blocks as usize);
3071
3072 let latest = self.backend.best_number();
3073 for offset in (0..mined_blocks).rev() {
3074 let block_num = latest - offset;
3075 if let Some(mut block) =
3076 self.backend.block_by_number_full(BlockNumber::Number(block_num)).await?
3077 {
3078 let block_txs = match block.transactions_mut() {
3079 BlockTransactions::Full(txs) => txs,
3080 BlockTransactions::Hashes(_) | BlockTransactions::Uncle => unreachable!(),
3081 };
3082 for tx in block_txs.iter_mut() {
3083 if let Some(receipt) = self.backend.mined_transaction_receipt(tx.tx_hash())
3084 && let Some(output) = receipt.out
3085 {
3086 if !receipt.inner.as_ref().status()
3088 && let Some(reason) = RevertDecoder::new().maybe_decode(&output, None)
3089 {
3090 tx.other.insert(
3091 "revertReason".to_string(),
3092 serde_json::to_value(reason).expect("Infallible"),
3093 );
3094 }
3095 tx.other.insert(
3096 "output".to_string(),
3097 serde_json::to_value(output).expect("Infallible"),
3098 );
3099 }
3100 }
3101 block.transactions = BlockTransactions::Full(block_txs.clone());
3102 blocks.push(block);
3103 }
3104 }
3105
3106 Ok(blocks)
3107 }
3108
3109 pub async fn eth_send_unsigned_transaction(
3113 &self,
3114 request: WithOtherFields<TransactionRequest>,
3115 ) -> Result<TxHash> {
3116 node_info!("eth_sendUnsignedTransaction");
3117 let from = request.from.ok_or(BlockchainError::NoSignerAvailable)?;
3119
3120 let (nonce, on_chain_nonce) = self.request_nonce(&request, from).await?;
3121
3122 let typed_tx = self.build_tx_request(request, nonce).await?;
3123
3124 let transaction = sign::build_impersonated(typed_tx);
3125
3126 self.ensure_typed_transaction_supported(&transaction)?;
3127
3128 let pending_transaction = PendingTransaction::with_impersonated(transaction, from);
3129
3130 self.backend.validate_pool_transaction(&pending_transaction).await?;
3132
3133 let requires = required_marker(nonce, on_chain_nonce, from);
3134 let provides = vec![to_marker(nonce, from)];
3135
3136 self.add_pending_transaction(pending_transaction, requires, provides)
3137 }
3138
3139 pub async fn txpool_inspect(&self) -> Result<TxpoolInspect> {
3146 node_info!("txpool_inspect");
3147 let mut inspect = TxpoolInspect::default();
3148
3149 fn convert(tx: Arc<PoolTransaction<FoundryTxEnvelope>>) -> TxpoolInspectSummary {
3150 let tx = &tx.pending_transaction.transaction;
3151 let to = tx.to();
3152 let gas_price = tx.max_fee_per_gas();
3153 let value = tx.value();
3154 let gas = tx.gas_limit();
3155 TxpoolInspectSummary { to, value, gas, gas_price }
3156 }
3157
3158 for pending in self.pool.ready_transactions() {
3165 let entry = inspect.pending.entry(*pending.pending_transaction.sender()).or_default();
3166 let key = pending.pending_transaction.nonce().to_string();
3167 entry.insert(key, convert(pending));
3168 }
3169 for queued in self.pool.pending_transactions() {
3170 let entry = inspect.pending.entry(*queued.pending_transaction.sender()).or_default();
3171 let key = queued.pending_transaction.nonce().to_string();
3172 entry.insert(key, convert(queued));
3173 }
3174 Ok(inspect)
3175 }
3176
3177 pub async fn txpool_content(&self) -> Result<TxpoolContent<AnyRpcTransaction>> {
3184 node_info!("txpool_content");
3185 let mut content = TxpoolContent::<AnyRpcTransaction>::default();
3186 fn convert(tx: Arc<PoolTransaction<FoundryTxEnvelope>>) -> Result<AnyRpcTransaction> {
3187 let from = *tx.pending_transaction.sender();
3188 let tx = transaction_build(
3189 Some(tx.hash()),
3190 tx.pending_transaction.transaction.clone(),
3191 None,
3192 None,
3193 None,
3194 );
3195
3196 let WithOtherFields { inner: mut tx, other } = tx.0;
3197
3198 tx.inner = Recovered::new_unchecked(tx.inner.into_inner(), from);
3201
3202 let tx = AnyRpcTransaction(WithOtherFields { inner: tx, other });
3203
3204 Ok(tx)
3205 }
3206
3207 for pending in self.pool.ready_transactions() {
3208 let entry = content.pending.entry(*pending.pending_transaction.sender()).or_default();
3209 let key = pending.pending_transaction.nonce().to_string();
3210 entry.insert(key, convert(pending)?);
3211 }
3212 for queued in self.pool.pending_transactions() {
3213 let entry = content.pending.entry(*queued.pending_transaction.sender()).or_default();
3214 let key = queued.pending_transaction.nonce().to_string();
3215 entry.insert(key, convert(queued)?);
3216 }
3217
3218 Ok(content)
3219 }
3220}
3221
3222impl EthApi<FoundryNetwork> {
3223 async fn do_evm_mine(&self, opts: Option<MineOptions>) -> Result<u64> {
3225 let mut blocks_to_mine = 1u64;
3226
3227 if let Some(opts) = opts {
3228 let timestamp = match opts {
3229 MineOptions::Timestamp(timestamp) => timestamp,
3230 MineOptions::Options { timestamp, blocks } => {
3231 if let Some(blocks) = blocks {
3232 blocks_to_mine = blocks;
3233 }
3234 timestamp
3235 }
3236 };
3237 if let Some(timestamp) = timestamp {
3238 self.evm_set_next_block_timestamp(timestamp)?;
3240 }
3241 }
3242
3243 self.on_blocking_task(|this| async move {
3246 for _ in 0..blocks_to_mine {
3248 this.mine_one().await;
3249 }
3250 Ok(())
3251 })
3252 .await?;
3253
3254 Ok(blocks_to_mine)
3255 }
3256
3257 async fn do_estimate_gas(
3258 &self,
3259 request: WithOtherFields<TransactionRequest>,
3260 block_number: Option<BlockId>,
3261 overrides: EvmOverrides,
3262 ) -> Result<u128> {
3263 let block_request = self.block_request(block_number).await?;
3264 if let BlockRequest::Number(number) = block_request
3266 && let Some(fork) = self.get_fork()
3267 && fork.predates_fork(number)
3268 {
3269 if overrides.has_state() || overrides.has_block() {
3270 return Err(BlockchainError::EvmOverrideError(
3271 "not available on past forked blocks".to_string(),
3272 ));
3273 }
3274 return Ok(fork.estimate_gas(&request, Some(number.into())).await?);
3275 }
3276
3277 self.on_blocking_task(|this| async move {
3280 this.backend
3281 .with_database_at(Some(block_request), |state, mut block| {
3282 let mut cache_db = CacheDB::new(state);
3283 if let Some(state_overrides) = overrides.state {
3284 apply_state_overrides(
3285 state_overrides.into_iter().collect(),
3286 &mut cache_db,
3287 )?;
3288 }
3289 if let Some(block_overrides) = overrides.block {
3290 cache_db.apply_block_overrides(*block_overrides, &mut block);
3291 }
3292 this.do_estimate_gas_with_state(request, &cache_db, block)
3293 })
3294 .await?
3295 })
3296 .await
3297 }
3298
3299 fn transaction_priority(&self, tx: &FoundryTxEnvelope) -> TransactionPriority {
3301 self.transaction_order.read().priority(tx)
3302 }
3303
3304 pub fn full_pending_transactions(&self) -> UnboundedReceiver<AnyRpcTransaction> {
3306 let (tx, rx) = unbounded_channel();
3307 let mut hashes = self.new_ready_transactions();
3308
3309 let this = self.clone();
3310
3311 tokio::spawn(async move {
3312 while let Some(hash) = hashes.next().await {
3313 if let Ok(Some(txn)) = this.transaction_by_hash(hash).await
3314 && tx.send(txn).is_err()
3315 {
3316 break;
3317 }
3318 }
3319 });
3320
3321 rx
3322 }
3323
3324 pub async fn mine_one(&self) {
3326 let transactions = self.pool.ready_transactions().collect::<Vec<_>>();
3327 let outcome = self.backend.mine_block(transactions).await;
3328
3329 trace!(target: "node", blocknumber = ?outcome.block_number, "mined block");
3330 self.pool.on_mined_block(outcome);
3331 }
3332
3333 async fn pending_block(&self) -> AnyRpcBlock {
3335 let transactions = self.pool.ready_transactions().collect::<Vec<_>>();
3336 let info = self.backend.pending_block(transactions).await;
3337 self.backend.convert_block(info.block)
3338 }
3339
3340 async fn pending_block_full(&self) -> Option<AnyRpcBlock> {
3342 let transactions = self.pool.ready_transactions().collect::<Vec<_>>();
3343 let BlockInfo { block, transactions, receipts: _ } =
3344 self.backend.pending_block(transactions).await;
3345
3346 let mut partial_block = self.backend.convert_block(block.clone());
3347
3348 let mut block_transactions = Vec::with_capacity(block.body.transactions.len());
3349 let base_fee = self.backend.base_fee();
3350
3351 for info in transactions {
3352 let tx = block.body.transactions.get(info.transaction_index as usize)?.clone();
3353
3354 let tx = transaction_build(
3355 Some(info.transaction_hash),
3356 tx,
3357 Some(&block),
3358 Some(info),
3359 Some(base_fee),
3360 );
3361 block_transactions.push(tx);
3362 }
3363
3364 partial_block.transactions = BlockTransactions::from(block_transactions);
3365
3366 Some(partial_block)
3367 }
3368
3369 async fn build_tx_request(
3372 &self,
3373 request: WithOtherFields<TransactionRequest>,
3374 nonce: u64,
3375 ) -> Result<FoundryTypedTx> {
3376 let mut request = Into::<FoundryTransactionRequest>::into(request);
3377 let from = request.from().or(self.accounts()?.first().copied());
3378
3379 request.chain_id().is_none().then(|| request.set_chain_id(self.chain_id()));
3381 request.nonce().is_none().then(|| request.set_nonce(nonce));
3382 request.kind().is_none().then(|| request.set_kind(TxKind::default()));
3383 if request.gas_limit().is_none() {
3384 request.set_gas_limit(
3385 self.do_estimate_gas(
3386 request.as_ref().clone().into(),
3387 None,
3388 EvmOverrides::default(),
3389 )
3390 .await
3391 .map(|v| v as u64)
3392 .unwrap_or(self.backend.gas_limit()),
3393 );
3394 }
3395
3396 if let Err((tx_type, _)) = request.missing_keys() {
3398 if matches!(tx_type, FoundryTxType::Legacy | FoundryTxType::Eip2930) {
3399 request.gas_price().is_none().then(|| request.set_gas_price(self.gas_price()));
3400 }
3401 if tx_type == FoundryTxType::Eip2930 {
3402 request
3403 .access_list()
3404 .is_none()
3405 .then(|| request.set_access_list(Default::default()));
3406 }
3407 if matches!(
3408 tx_type,
3409 FoundryTxType::Eip1559
3410 | FoundryTxType::Eip4844
3411 | FoundryTxType::Eip7702
3412 | FoundryTxType::Tempo
3413 ) {
3414 request
3415 .max_fee_per_gas()
3416 .is_none()
3417 .then(|| request.set_max_fee_per_gas(self.gas_price()));
3418 request
3419 .max_priority_fee_per_gas()
3420 .is_none()
3421 .then(|| request.set_max_priority_fee_per_gas(MIN_SUGGESTED_PRIORITY_FEE));
3422 }
3423 if tx_type == FoundryTxType::Eip4844 {
3424 request.as_ref().max_fee_per_blob_gas().is_none().then(|| {
3425 request.as_mut().set_max_fee_per_blob_gas(
3426 self.backend.fees().get_next_block_blob_base_fee_per_gas(),
3427 )
3428 });
3429 }
3430 }
3431
3432 match request
3433 .build_unsigned()
3434 .map_err(|e| BlockchainError::InvalidTransactionRequest(e.to_string()))?
3435 {
3436 FoundryTypedTx::Eip4844(TxEip4844Variant::TxEip4844(_))
3437 if !self.backend.skip_blob_validation(from) =>
3438 {
3439 Err(BlockchainError::FailedToDecodeTransaction)
3441 }
3442 res => Ok(res),
3443 }
3444 }
3445
3446 async fn get_transaction_count(
3448 &self,
3449 address: Address,
3450 block_number: Option<BlockId>,
3451 ) -> Result<u64> {
3452 let block_request = self.block_request(block_number).await?;
3453
3454 if let BlockRequest::Number(number) = block_request
3455 && let Some(fork) = self.get_fork()
3456 && fork.predates_fork(number)
3457 {
3458 return Ok(fork.get_nonce(address, number).await?);
3459 }
3460
3461 self.backend.get_nonce(address, block_request).await
3462 }
3463
3464 async fn request_nonce(
3472 &self,
3473 request: &TransactionRequest,
3474 from: Address,
3475 ) -> Result<(u64, u64)> {
3476 let highest_nonce =
3477 self.get_transaction_count(from, Some(BlockId::Number(BlockNumber::Pending))).await?;
3478 let nonce = request.nonce.unwrap_or(highest_nonce);
3479
3480 Ok((nonce, highest_nonce))
3481 }
3482
3483 fn add_pending_transaction(
3485 &self,
3486 pending_transaction: PendingTransaction<FoundryTxEnvelope>,
3487 requires: Vec<TxMarker>,
3488 provides: Vec<TxMarker>,
3489 ) -> Result<TxHash> {
3490 let from = *pending_transaction.sender();
3491 let priority = self.transaction_priority(&pending_transaction.transaction);
3492 let pool_transaction =
3493 PoolTransaction { requires, provides, pending_transaction, priority };
3494 let tx = self.pool.add_transaction(pool_transaction)?;
3495 trace!(target: "node", "Added transaction: [{:?}] sender={:?}", tx.hash(), from);
3496 Ok(*tx.hash())
3497 }
3498
3499 fn ensure_typed_transaction_supported(&self, tx: &FoundryTxEnvelope) -> Result<()> {
3501 match &tx {
3502 FoundryTxEnvelope::Eip2930(_) => self.backend.ensure_eip2930_active(),
3503 FoundryTxEnvelope::Eip1559(_) => self.backend.ensure_eip1559_active(),
3504 FoundryTxEnvelope::Eip4844(_) => self.backend.ensure_eip4844_active(),
3505 FoundryTxEnvelope::Eip7702(_) => self.backend.ensure_eip7702_active(),
3506 FoundryTxEnvelope::Deposit(_) => self.backend.ensure_op_deposits_active(),
3507 FoundryTxEnvelope::Legacy(_) => Ok(()),
3508 FoundryTxEnvelope::Tempo(_) => self.backend.ensure_tempo_active(),
3509 }
3510 }
3511}
3512
3513fn required_marker(provided_nonce: u64, on_chain_nonce: u64, from: Address) -> Vec<TxMarker> {
3514 if provided_nonce == on_chain_nonce {
3515 return Vec::new();
3516 }
3517 let prev_nonce = provided_nonce.saturating_sub(1);
3518 if on_chain_nonce <= prev_nonce { vec![to_marker(prev_nonce, from)] } else { Vec::new() }
3519}
3520
3521fn convert_transact_out(out: &Option<Output>) -> Bytes {
3522 match out {
3523 None => Default::default(),
3524 Some(Output::Call(out)) => out.to_vec().into(),
3525 Some(Output::Create(out, _)) => out.to_vec().into(),
3526 }
3527}
3528
3529fn ensure_return_ok(exit: InstructionResult, out: &Option<Output>) -> Result<Bytes> {
3531 let out = convert_transact_out(out);
3532 match exit {
3533 return_ok!() => Ok(out),
3534 return_revert!() => Err(InvalidTransactionError::Revert(Some(out)).into()),
3535 reason => Err(BlockchainError::EvmError(reason)),
3536 }
3537}
3538
3539fn determine_base_gas_by_kind(request: &WithOtherFields<TransactionRequest>) -> u128 {
3541 match request.kind() {
3542 Some(TxKind::Call(_)) => {
3543 MIN_TRANSACTION_GAS
3544 + request.inner().authorization_list.as_ref().map_or(0, |auths_list| {
3545 auths_list.len() as u128 * PER_EMPTY_ACCOUNT_COST as u128
3546 })
3547 }
3548 Some(TxKind::Create) => MIN_CREATE_GAS,
3549 None => MIN_CREATE_GAS,
3551 }
3552}
3553
3554enum GasEstimationCallResult {
3556 Success(u128),
3557 OutOfGas,
3558 Revert(Option<Bytes>),
3559 EvmError(InstructionResult),
3560}
3561
3562impl TryFrom<Result<(InstructionResult, Option<Output>, u128, State)>> for GasEstimationCallResult {
3566 type Error = BlockchainError;
3567
3568 fn try_from(res: Result<(InstructionResult, Option<Output>, u128, State)>) -> Result<Self> {
3569 match res {
3570 Err(BlockchainError::InvalidTransaction(InvalidTransactionError::GasTooHigh(_))) => {
3572 Ok(Self::OutOfGas)
3573 }
3574 Err(BlockchainError::Message(ref msg))
3576 if msg.contains("insufficient gas for intrinsic cost") =>
3577 {
3578 Ok(Self::OutOfGas)
3579 }
3580 Err(err) => Err(err),
3581 Ok((exit, output, gas, _)) => match exit {
3582 return_ok!() => Ok(Self::Success(gas)),
3583
3584 InstructionResult::Revert => Ok(Self::Revert(output.map(|o| o.into_data()))),
3586 InstructionResult::CallTooDeep
3587 | InstructionResult::OutOfFunds
3588 | InstructionResult::CreateInitCodeStartingEF00
3589 | InstructionResult::InvalidEOFInitCode
3590 | InstructionResult::InvalidExtDelegateCallTarget => Ok(Self::EvmError(exit)),
3591
3592 InstructionResult::OutOfGas
3594 | InstructionResult::MemoryOOG
3595 | InstructionResult::MemoryLimitOOG
3596 | InstructionResult::PrecompileOOG
3597 | InstructionResult::InvalidOperandOOG
3598 | InstructionResult::ReentrancySentryOOG => Ok(Self::OutOfGas),
3599
3600 InstructionResult::OpcodeNotFound
3602 | InstructionResult::CallNotAllowedInsideStatic
3603 | InstructionResult::StateChangeDuringStaticCall
3604 | InstructionResult::InvalidFEOpcode
3605 | InstructionResult::InvalidJump
3606 | InstructionResult::NotActivated
3607 | InstructionResult::StackUnderflow
3608 | InstructionResult::StackOverflow
3609 | InstructionResult::OutOfOffset
3610 | InstructionResult::CreateCollision
3611 | InstructionResult::OverflowPayment
3612 | InstructionResult::PrecompileError
3613 | InstructionResult::NonceOverflow
3614 | InstructionResult::CreateContractSizeLimit
3615 | InstructionResult::CreateContractStartingWithEF
3616 | InstructionResult::CreateInitCodeSizeLimit
3617 | InstructionResult::InvalidImmediateEncoding
3618 | InstructionResult::FatalExternalError => Ok(Self::EvmError(exit)),
3619 },
3620 }
3621 }
3622}