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, NetworkTransactionBuilder,
43 ReceiptResponse, TransactionBuilder, TransactionBuilder4844, TransactionResponse,
44 eip2718::Decodable2718,
45};
46use alloy_primitives::{
47 Address, B64, B256, Bytes, TxHash, TxKind, U64, U256,
48 map::{HashMap, HashSet},
49};
50use alloy_rpc_types::{
51 AccessList, AccessListResult, BlockId, BlockNumberOrTag as BlockNumber, BlockTransactions,
52 EIP1186AccountProofResponse, FeeHistory, Filter, FilteredParams, Index, Log, Work,
53 anvil::{
54 ForkedNetwork, Forking, Metadata, MineOptions, NodeEnvironment, NodeForkConfig, NodeInfo,
55 },
56 request::TransactionRequest,
57 simulate::{SimulatePayload, SimulatedBlock},
58 state::{AccountOverride, EvmOverrides, StateOverridesBuilder},
59 trace::{
60 filter::TraceFilter,
61 geth::{GethDebugTracingCallOptions, GethDebugTracingOptions, GethTrace, TraceResult},
62 parity::{LocalizedTransactionTrace, TraceResultsWithTransactionHash, TraceType},
63 },
64 txpool::{TxpoolContent, TxpoolInspect, TxpoolInspectSummary, TxpoolStatus},
65};
66use alloy_rpc_types_eth::FillTransaction;
67use alloy_serde::WithOtherFields;
68use alloy_sol_types::{SolCall, SolValue, sol};
69use alloy_transport::TransportErrorKind;
70use anvil_core::{
71 eth::{
72 EthRequest,
73 block::BlockInfo,
74 transaction::{MaybeImpersonatedTransaction, PendingTransaction},
75 },
76 types::{ReorgOptions, TransactionData},
77};
78use anvil_rpc::{error::RpcError, response::ResponseResult};
79use foundry_common::{
80 provider::ProviderBuilder,
81 version::{COMMIT_SHA, SEMVER_VERSION},
82};
83use foundry_evm::decode::RevertDecoder;
84use foundry_primitives::{
85 FoundryNetwork, FoundryReceiptEnvelope, FoundryTransactionRequest, FoundryTxEnvelope,
86 FoundryTxReceipt, FoundryTxType, FoundryTypedTx,
87};
88use futures::{
89 StreamExt, TryFutureExt,
90 channel::{mpsc::Receiver, oneshot},
91};
92use parking_lot::RwLock;
93use revm::{
94 context::BlockEnv,
95 context_interface::{block::BlobExcessGasAndPrice, result::Output},
96 database::CacheDB,
97 interpreter::{InstructionResult, return_ok, return_revert},
98 primitives::eip7702::PER_EMPTY_ACCOUNT_COST,
99};
100use std::{sync::Arc, time::Duration};
101use tokio::{
102 sync::mpsc::{UnboundedReceiver, unbounded_channel},
103 try_join,
104};
105
106pub const CLIENT_VERSION: &str = concat!("anvil/v", env!("CARGO_PKG_VERSION"));
108
109pub struct EthApi<N: Network> {
113 pool: Arc<Pool<N::TxEnvelope>>,
115 pub backend: Arc<backend::mem::Backend<N>>,
118 is_mining: bool,
120 signers: Arc<Vec<Box<dyn Signer<N>>>>,
122 fee_history_cache: FeeHistoryCache,
124 fee_history_limit: u64,
126 miner: Miner<N::TxEnvelope>,
131 logger: LoggingManager,
133 filters: Filters<N>,
135 transaction_order: Arc<RwLock<TransactionOrder>>,
137 net_listening: bool,
139 instance_id: Arc<RwLock<B256>>,
141}
142
143impl<N: Network> Clone for EthApi<N> {
144 fn clone(&self) -> Self {
145 Self {
146 pool: self.pool.clone(),
147 backend: self.backend.clone(),
148 is_mining: self.is_mining,
149 signers: self.signers.clone(),
150 fee_history_cache: self.fee_history_cache.clone(),
151 fee_history_limit: self.fee_history_limit,
152 miner: self.miner.clone(),
153 logger: self.logger.clone(),
154 filters: self.filters.clone(),
155 transaction_order: self.transaction_order.clone(),
156 net_listening: self.net_listening,
157 instance_id: self.instance_id.clone(),
158 }
159 }
160}
161
162impl<N: Network> EthApi<N> {
165 #[expect(clippy::too_many_arguments)]
167 pub fn new(
168 pool: Arc<Pool<N::TxEnvelope>>,
169 backend: Arc<backend::mem::Backend<N>>,
170 signers: Arc<Vec<Box<dyn Signer<N>>>>,
171 fee_history_cache: FeeHistoryCache,
172 fee_history_limit: u64,
173 miner: Miner<N::TxEnvelope>,
174 logger: LoggingManager,
175 filters: Filters<N>,
176 transactions_order: TransactionOrder,
177 ) -> Self {
178 Self {
179 pool,
180 backend,
181 is_mining: true,
182 signers,
183 fee_history_cache,
184 fee_history_limit,
185 miner,
186 logger,
187 filters,
188 net_listening: true,
189 transaction_order: Arc::new(RwLock::new(transactions_order)),
190 instance_id: Arc::new(RwLock::new(B256::random())),
191 }
192 }
193
194 pub fn gas_price(&self) -> u128 {
196 if self.backend.is_eip1559() {
197 if self.backend.is_min_priority_fee_enforced() {
198 (self.backend.base_fee() as u128).saturating_add(self.lowest_suggestion_tip())
199 } else {
200 self.backend.base_fee() as u128
201 }
202 } else {
203 self.backend.fees().raw_gas_price()
204 }
205 }
206
207 fn lowest_suggestion_tip(&self) -> u128 {
211 let block_number = self.backend.best_number();
212 let latest_cached_block = self.fee_history_cache.lock().get(&block_number).cloned();
213
214 match latest_cached_block {
215 Some(block) => block.rewards.iter().copied().min(),
216 None => self.fee_history_cache.lock().values().flat_map(|b| b.rewards.clone()).min(),
217 }
218 .map(|fee| fee.max(MIN_SUGGESTED_PRIORITY_FEE))
219 .unwrap_or(MIN_SUGGESTED_PRIORITY_FEE)
220 }
221
222 pub fn anvil_get_auto_mine(&self) -> Result<bool> {
226 node_info!("anvil_getAutomine");
227 Ok(self.miner.is_auto_mine())
228 }
229
230 pub fn anvil_get_interval_mining(&self) -> Result<Option<u64>> {
234 node_info!("anvil_getIntervalMining");
235 Ok(self.miner.get_interval())
236 }
237
238 pub async fn anvil_set_auto_mine(&self, enable_automine: bool) -> Result<()> {
243 node_info!("evm_setAutomine");
244 if self.miner.is_auto_mine() {
245 if enable_automine {
246 return Ok(());
247 }
248 self.miner.set_mining_mode(MiningMode::None);
249 } else if enable_automine {
250 let listener = self.pool.add_ready_listener();
251 let mode = MiningMode::instant(1_000, listener);
252 self.miner.set_mining_mode(mode);
253 }
254 Ok(())
255 }
256
257 pub fn anvil_set_interval_mining(&self, secs: u64) -> Result<()> {
261 node_info!("evm_setIntervalMining");
262 let mining_mode = if secs == 0 {
263 MiningMode::None
264 } else {
265 let block_time = Duration::from_secs(secs);
266
267 self.backend.update_interval_mine_block_time(block_time);
269
270 MiningMode::FixedBlockTime(FixedBlockTimeMiner::new(block_time))
271 };
272 self.miner.set_mining_mode(mining_mode);
273 Ok(())
274 }
275
276 pub async fn anvil_drop_transaction(&self, tx_hash: B256) -> Result<Option<B256>> {
280 node_info!("anvil_dropTransaction");
281 Ok(self.pool.drop_transaction(tx_hash).map(|tx| tx.hash()))
282 }
283
284 pub async fn anvil_drop_all_transactions(&self) -> Result<()> {
288 node_info!("anvil_dropAllTransactions");
289 self.pool.clear();
290 Ok(())
291 }
292
293 pub async fn anvil_set_chain_id(&self, chain_id: u64) -> Result<()> {
294 node_info!("anvil_setChainId");
295 self.backend.set_chain_id(chain_id);
296 Ok(())
297 }
298
299 pub async fn anvil_set_balance(&self, address: Address, balance: U256) -> Result<()> {
303 node_info!("anvil_setBalance");
304 self.backend.set_balance(address, balance).await?;
305 Ok(())
306 }
307
308 pub async fn anvil_set_code(&self, address: Address, code: Bytes) -> Result<()> {
312 node_info!("anvil_setCode");
313 self.backend.set_code(address, code).await?;
314 Ok(())
315 }
316
317 pub async fn anvil_set_nonce(&self, address: Address, nonce: U256) -> Result<()> {
321 node_info!("anvil_setNonce");
322 self.backend.set_nonce(address, nonce).await?;
323 Ok(())
324 }
325
326 pub async fn anvil_set_storage_at(
330 &self,
331 address: Address,
332 slot: U256,
333 val: B256,
334 ) -> Result<bool> {
335 node_info!("anvil_setStorageAt");
336 self.backend.set_storage_at(address, slot, val).await?;
337 Ok(true)
338 }
339
340 pub async fn anvil_set_logging(&self, enable: bool) -> Result<()> {
344 node_info!("anvil_setLoggingEnabled");
345 self.logger.set_enabled(enable);
346 Ok(())
347 }
348
349 pub async fn anvil_set_min_gas_price(&self, gas: U256) -> Result<()> {
353 node_info!("anvil_setMinGasPrice");
354 if self.backend.is_eip1559() {
355 return Err(RpcError::invalid_params(
356 "anvil_setMinGasPrice is not supported when EIP-1559 is active",
357 )
358 .into());
359 }
360 self.backend.set_gas_price(gas.saturating_to());
361 Ok(())
362 }
363
364 pub async fn anvil_set_next_block_base_fee_per_gas(&self, basefee: U256) -> Result<()> {
368 node_info!("anvil_setNextBlockBaseFeePerGas");
369 if !self.backend.is_eip1559() {
370 return Err(RpcError::invalid_params(
371 "anvil_setNextBlockBaseFeePerGas is only supported when EIP-1559 is active",
372 )
373 .into());
374 }
375 self.backend.set_base_fee(basefee.saturating_to());
376 Ok(())
377 }
378
379 pub async fn anvil_set_coinbase(&self, address: Address) -> Result<()> {
383 node_info!("anvil_setCoinbase");
384 self.backend.set_coinbase(address);
385 Ok(())
386 }
387
388 pub async fn anvil_node_info(&self) -> Result<NodeInfo> {
392 node_info!("anvil_nodeInfo");
393
394 let evm_env = self.backend.evm_env().read();
395 let fork_config = self.backend.get_fork();
396 let tx_order = self.transaction_order.read();
397 let hard_fork = self.backend.hardfork().name();
398
399 Ok(NodeInfo {
400 current_block_number: self.backend.best_number(),
401 current_block_timestamp: evm_env.block_env.timestamp.saturating_to(),
402 current_block_hash: self.backend.best_hash(),
403 hard_fork,
404 transaction_order: match *tx_order {
405 TransactionOrder::Fifo => "fifo".to_string(),
406 TransactionOrder::Fees => "fees".to_string(),
407 },
408 environment: NodeEnvironment {
409 base_fee: self.backend.base_fee() as u128,
410 chain_id: self.backend.chain_id().to::<u64>(),
411 gas_limit: self.backend.gas_limit(),
412 gas_price: self.gas_price(),
413 },
414 fork_config: fork_config
415 .map(|fork| {
416 let config = fork.config.read();
417
418 NodeForkConfig {
419 fork_url: config.eth_rpc_url().map(|s| s.to_string()),
420 fork_block_number: Some(config.block_number),
421 fork_retry_backoff: Some(config.backoff.as_millis()),
422 }
423 })
424 .unwrap_or_default(),
425 network: self.backend.is_tempo().then(|| "tempo".to_string()),
426 })
427 }
428
429 pub async fn anvil_metadata(&self) -> Result<Metadata> {
433 node_info!("anvil_metadata");
434 let fork_config = self.backend.get_fork();
435
436 Ok(Metadata {
437 client_version: CLIENT_VERSION.to_string(),
438 client_semver: Some(SEMVER_VERSION.to_string()),
439 client_commit_sha: Some(COMMIT_SHA.to_string()),
440 chain_id: self.backend.chain_id().to::<u64>(),
441 latest_block_hash: self.backend.best_hash(),
442 latest_block_number: self.backend.best_number(),
443 instance_id: *self.instance_id.read(),
444 forked_network: fork_config.map(|cfg| ForkedNetwork {
445 chain_id: cfg.chain_id(),
446 fork_block_number: cfg.block_number(),
447 fork_block_hash: cfg.block_hash(),
448 }),
449 snapshots: self.backend.list_state_snapshots(),
450 })
451 }
452
453 pub async fn anvil_remove_pool_transactions(&self, address: Address) -> Result<()> {
454 node_info!("anvil_removePoolTransactions");
455 self.pool.remove_transactions_by_address(address);
456 Ok(())
457 }
458
459 pub async fn evm_snapshot(&self) -> Result<U256> {
463 node_info!("evm_snapshot");
464 Ok(self.backend.create_state_snapshot().await)
465 }
466
467 pub async fn evm_increase_time(&self, seconds: U256) -> Result<i64> {
471 node_info!("evm_increaseTime");
472 Ok(self.backend.time().increase_time(seconds.try_into().unwrap_or(u64::MAX)) as i64)
473 }
474
475 pub fn evm_set_next_block_timestamp(&self, seconds: u64) -> Result<()> {
479 node_info!("evm_setNextBlockTimestamp");
480 self.backend.time().set_next_block_timestamp(seconds)
481 }
482
483 pub fn evm_set_time(&self, timestamp: u64) -> Result<u64> {
492 node_info!("evm_setTime");
493 let now = self.backend.time().current_call_timestamp();
494 self.backend.time().reset(timestamp);
495
496 let offset = timestamp.saturating_sub(now);
498 Ok(offset)
499 }
500
501 pub fn evm_set_block_gas_limit(&self, gas_limit: U256) -> Result<bool> {
505 node_info!("evm_setBlockGasLimit");
506 self.backend.set_gas_limit(gas_limit.saturating_to());
507 Ok(true)
508 }
509
510 pub fn evm_set_block_timestamp_interval(&self, seconds: u64) -> Result<()> {
514 node_info!("anvil_setBlockTimestampInterval");
515 self.backend.time().set_block_timestamp_interval(seconds);
516 Ok(())
517 }
518
519 pub fn evm_remove_block_timestamp_interval(&self) -> Result<bool> {
523 node_info!("anvil_removeBlockTimestampInterval");
524 Ok(self.backend.time().remove_block_timestamp_interval())
525 }
526
527 pub async fn anvil_set_rpc_url(&self, url: String) -> Result<()> {
531 node_info!("anvil_setRpcUrl");
532 if let Some(fork) = self.backend.get_fork() {
533 let mut config = fork.config.write();
534 let new_provider = Arc::new(
536 ProviderBuilder::new(&url).max_retry(10).initial_backoff(1000).build().map_err(
537 |_| {
538 TransportErrorKind::custom_str(
539 format!("Failed to parse invalid url {url}").as_str(),
540 )
541 },
542 )?, );
545 config.provider = new_provider;
546 trace!(target: "backend", "Updated fork rpc from \"{}\" to \"{}\"", config.eth_rpc_url().unwrap_or("none"), url);
547 config.fork_urls = vec![url.clone()];
548 }
549 self.backend.node_config.write().await.fork_urls = vec![url];
551 Ok(())
552 }
553
554 pub async fn txpool_status(&self) -> Result<TxpoolStatus> {
560 node_info!("txpool_status");
561 Ok(self.pool.txpool_status())
562 }
563
564 async fn on_blocking_task<C, F, R>(&self, c: C) -> Result<R>
566 where
567 C: FnOnce(Self) -> F,
568 F: Future<Output = Result<R>> + Send + 'static,
569 R: Send + 'static,
570 {
571 let (tx, rx) = oneshot::channel();
572 let this = self.clone();
573 let f = c(this);
574 tokio::task::spawn_blocking(move || {
575 tokio::runtime::Handle::current().block_on(async move {
576 let res = f.await;
577 let _ = tx.send(res);
578 })
579 });
580 rx.await.map_err(|_| BlockchainError::Internal("blocking task panicked".to_string()))?
581 }
582
583 pub fn set_transaction_order(&self, order: TransactionOrder) {
585 *self.transaction_order.write() = order;
586 }
587
588 pub fn chain_id(&self) -> u64 {
590 self.backend.chain_id().to::<u64>()
591 }
592
593 pub fn get_fork(&self) -> Option<ClientFork> {
595 self.backend.get_fork()
596 }
597
598 pub fn instance_id(&self) -> B256 {
600 *self.instance_id.read()
601 }
602
603 pub fn reset_instance_id(&self) {
605 *self.instance_id.write() = B256::random();
606 }
607
608 #[expect(clippy::borrowed_box)]
610 pub fn get_signer(&self, address: Address) -> Option<&Box<dyn Signer<N>>> {
611 self.signers.iter().find(|signer| signer.is_signer_for(address))
612 }
613
614 pub fn new_ready_transactions(&self) -> Receiver<TxHash> {
616 self.pool.add_ready_listener()
617 }
618
619 pub fn is_fork(&self) -> bool {
621 self.backend.is_fork()
622 }
623
624 pub async fn state_root(&self) -> Option<B256> {
626 self.backend.get_db().read().await.maybe_state_root()
627 }
628
629 pub fn is_impersonated(&self, addr: Address) -> bool {
631 self.backend.cheats().is_impersonated(addr)
632 }
633
634 pub fn storage_info(&self) -> StorageInfo<N> {
636 StorageInfo::new(Arc::clone(&self.backend))
637 }
638
639 #[allow(clippy::large_stack_frames)]
641 pub fn anvil_get_blob_by_versioned_hash(
642 &self,
643 hash: B256,
644 ) -> Result<Option<alloy_consensus::Blob>> {
645 node_info!("anvil_getBlobByHash");
646 Ok(self.backend.get_blob_by_versioned_hash(hash)?)
647 }
648
649 pub fn anvil_get_blobs_by_block_id(
651 &self,
652 block_id: impl Into<BlockId>,
653 versioned_hashes: Vec<B256>,
654 ) -> Result<Option<Vec<Blob>>> {
655 node_info!("anvil_getBlobsByBlockId");
656 Ok(self.backend.get_blobs_by_block_id(block_id, versioned_hashes)?)
657 }
658
659 pub fn anvil_get_genesis_time(&self) -> Result<u64> {
663 node_info!("anvil_getGenesisTime");
664 Ok(self.backend.genesis_time())
665 }
666
667 pub async fn anvil_reset(&self, forking: Option<Forking>) -> Result<()> {
673 self.reset_instance_id();
674 node_info!("anvil_reset");
675 if let Some(forking) = forking {
676 self.backend.reset_fork(forking).await?;
678 } else {
679 self.backend.reset_to_in_mem().await?;
681 }
682 self.pool.clear();
684 Ok(())
685 }
686
687 pub async fn evm_revert(&self, id: U256) -> Result<bool> {
692 node_info!("evm_revert");
693 self.backend.revert_state_snapshot(id).await
694 }
695
696 pub async fn anvil_impersonate_account(&self, address: Address) -> Result<()> {
700 node_info!("anvil_impersonateAccount");
701 self.backend.impersonate(address);
702 Ok(())
703 }
704
705 pub async fn anvil_stop_impersonating_account(&self, address: Address) -> Result<()> {
709 node_info!("anvil_stopImpersonatingAccount");
710 self.backend.stop_impersonating(address);
711 Ok(())
712 }
713
714 pub async fn anvil_auto_impersonate_account(&self, enabled: bool) -> Result<()> {
718 node_info!("anvil_autoImpersonateAccount");
719 self.backend.auto_impersonate_account(enabled);
720 Ok(())
721 }
722
723 pub async fn anvil_impersonate_signature(
725 &self,
726 signature: Bytes,
727 address: Address,
728 ) -> Result<()> {
729 node_info!("anvil_impersonateSignature");
730 self.backend.impersonate_signature(signature, address).await
731 }
732
733 pub fn new_block_notifications(&self) -> NewBlockNotifications {
735 self.backend.new_block_notifications()
736 }
737
738 pub fn client_version(&self) -> Result<String> {
742 node_info!("web3_clientVersion");
743 Ok(CLIENT_VERSION.to_string())
744 }
745
746 pub fn sha3(&self, bytes: Bytes) -> Result<String> {
750 node_info!("web3_sha3");
751 let hash = alloy_primitives::keccak256(bytes.as_ref());
752 Ok(alloy_primitives::hex::encode_prefixed(&hash[..]))
753 }
754
755 pub fn protocol_version(&self) -> Result<u64> {
759 node_info!("eth_protocolVersion");
760 Ok(1)
761 }
762
763 pub fn hashrate(&self) -> Result<U256> {
767 node_info!("eth_hashrate");
768 Ok(U256::ZERO)
769 }
770
771 pub fn author(&self) -> Result<Address> {
775 node_info!("eth_coinbase");
776 Ok(self.backend.coinbase())
777 }
778
779 pub fn is_mining(&self) -> Result<bool> {
783 node_info!("eth_mining");
784 Ok(self.is_mining)
785 }
786
787 pub fn eth_chain_id(&self) -> Result<Option<U64>> {
793 node_info!("eth_chainId");
794 Ok(Some(self.backend.chain_id().to::<U64>()))
795 }
796
797 pub fn network_id(&self) -> Result<Option<String>> {
801 node_info!("eth_networkId");
802 let chain_id = self.backend.chain_id().to::<u64>();
803 Ok(Some(format!("{chain_id}")))
804 }
805
806 pub fn net_listening(&self) -> Result<bool> {
810 node_info!("net_listening");
811 Ok(self.net_listening)
812 }
813
814 fn eth_gas_price(&self) -> Result<U256> {
816 node_info!("eth_gasPrice");
817 Ok(U256::from(self.gas_price()))
818 }
819
820 pub fn excess_blob_gas_and_price(&self) -> Result<Option<BlobExcessGasAndPrice>> {
822 Ok(self.backend.excess_blob_gas_and_price())
823 }
824
825 pub fn gas_max_priority_fee_per_gas(&self) -> Result<U256> {
830 self.max_priority_fee_per_gas()
831 }
832
833 pub fn blob_base_fee(&self) -> Result<U256> {
837 Ok(U256::from(self.backend.fees().base_fee_per_blob_gas()))
838 }
839
840 pub fn gas_limit(&self) -> U256 {
842 U256::from(self.backend.gas_limit())
843 }
844
845 pub fn accounts(&self) -> Result<Vec<Address>> {
849 node_info!("eth_accounts");
850 let mut unique = HashSet::new();
851 let mut accounts: Vec<Address> = Vec::new();
852 for signer in self.signers.iter() {
853 accounts.extend(signer.accounts().into_iter().filter(|acc| unique.insert(*acc)));
854 }
855 accounts.extend(
856 self.backend
857 .cheats()
858 .impersonated_accounts()
859 .into_iter()
860 .filter(|acc| unique.insert(*acc)),
861 );
862 Ok(accounts.into_iter().collect())
863 }
864
865 pub fn block_number(&self) -> Result<U256> {
869 node_info!("eth_blockNumber");
870 Ok(U256::from(self.backend.best_number()))
871 }
872
873 pub async fn block_by_hash(&self, hash: B256) -> Result<Option<AnyRpcBlock>> {
877 node_info!("eth_getBlockByHash");
878 self.backend.block_by_hash(hash).await
879 }
880
881 pub async fn block_by_hash_full(&self, hash: B256) -> Result<Option<AnyRpcBlock>> {
885 node_info!("eth_getBlockByHash");
886 self.backend.block_by_hash_full(hash).await
887 }
888
889 pub async fn block_transaction_count_by_hash(&self, hash: B256) -> Result<Option<U256>> {
893 node_info!("eth_getBlockTransactionCountByHash");
894 let block = self.backend.block_by_hash(hash).await?;
895 let txs = block.map(|b| match b.transactions() {
896 BlockTransactions::Full(txs) => U256::from(txs.len()),
897 BlockTransactions::Hashes(txs) => U256::from(txs.len()),
898 BlockTransactions::Uncle => U256::from(0),
899 });
900 Ok(txs)
901 }
902
903 pub async fn block_uncles_count_by_hash(&self, hash: B256) -> Result<U256> {
907 node_info!("eth_getUncleCountByBlockHash");
908 let block =
909 self.backend.block_by_hash(hash).await?.ok_or(BlockchainError::BlockNotFound)?;
910 Ok(U256::from(block.uncles.len()))
911 }
912
913 pub async fn block_uncles_count_by_number(&self, block_number: BlockNumber) -> Result<U256> {
917 node_info!("eth_getUncleCountByBlockNumber");
918 let block = self
919 .backend
920 .block_by_number(block_number)
921 .await?
922 .ok_or(BlockchainError::BlockNotFound)?;
923 Ok(U256::from(block.uncles.len()))
924 }
925
926 pub async fn sign_typed_data(
930 &self,
931 _address: Address,
932 _data: serde_json::Value,
933 ) -> Result<String> {
934 node_info!("eth_signTypedData");
935 Err(BlockchainError::RpcUnimplemented)
936 }
937
938 pub async fn sign_typed_data_v3(
942 &self,
943 _address: Address,
944 _data: serde_json::Value,
945 ) -> Result<String> {
946 node_info!("eth_signTypedData_v3");
947 Err(BlockchainError::RpcUnimplemented)
948 }
949
950 pub async fn sign_typed_data_v4(&self, address: Address, data: &TypedData) -> Result<String> {
954 node_info!("eth_signTypedData_v4");
955 let signer = self.get_signer(address).ok_or(BlockchainError::NoSignerAvailable)?;
956 let signature = signer.sign_typed_data(address, data).await?;
957 let signature = alloy_primitives::hex::encode(signature.as_bytes());
958 Ok(format!("0x{signature}"))
959 }
960
961 pub async fn sign(&self, address: Address, content: impl AsRef<[u8]>) -> Result<String> {
965 node_info!("eth_sign");
966 let signer = self.get_signer(address).ok_or(BlockchainError::NoSignerAvailable)?;
967 let signature =
968 alloy_primitives::hex::encode(signer.sign(address, content.as_ref()).await?.as_bytes());
969 Ok(format!("0x{signature}"))
970 }
971
972 pub async fn transaction_by_block_hash_and_index(
976 &self,
977 hash: B256,
978 index: Index,
979 ) -> Result<Option<AnyRpcTransaction>> {
980 node_info!("eth_getTransactionByBlockHashAndIndex");
981 self.backend.transaction_by_block_hash_and_index(hash, index).await
982 }
983
984 pub async fn transaction_by_block_number_and_index(
988 &self,
989 block: BlockNumber,
990 idx: Index,
991 ) -> Result<Option<AnyRpcTransaction>> {
992 node_info!("eth_getTransactionByBlockNumberAndIndex");
993 self.backend.transaction_by_block_number_and_index(block, idx).await
994 }
995
996 pub async fn uncle_by_block_hash_and_index(
1000 &self,
1001 block_hash: B256,
1002 idx: Index,
1003 ) -> Result<Option<AnyRpcBlock>> {
1004 node_info!("eth_getUncleByBlockHashAndIndex");
1005 let number =
1006 self.backend.ensure_block_number(Some(BlockId::Hash(block_hash.into()))).await?;
1007 if let Some(fork) = self.get_fork()
1008 && fork.predates_fork_inclusive(number)
1009 {
1010 return Ok(fork.uncle_by_block_hash_and_index(block_hash, idx.into()).await?);
1011 }
1012 Ok(None)
1014 }
1015
1016 pub async fn uncle_by_block_number_and_index(
1020 &self,
1021 block_number: BlockNumber,
1022 idx: Index,
1023 ) -> Result<Option<AnyRpcBlock>> {
1024 node_info!("eth_getUncleByBlockNumberAndIndex");
1025 let number = self.backend.ensure_block_number(Some(BlockId::Number(block_number))).await?;
1026 if let Some(fork) = self.get_fork()
1027 && fork.predates_fork_inclusive(number)
1028 {
1029 return Ok(fork.uncle_by_block_number_and_index(number, idx.into()).await?);
1030 }
1031 Ok(None)
1033 }
1034
1035 pub fn work(&self) -> Result<Work> {
1039 node_info!("eth_getWork");
1040 Err(BlockchainError::RpcUnimplemented)
1041 }
1042
1043 pub fn syncing(&self) -> Result<bool> {
1047 node_info!("eth_syncing");
1048 Ok(false)
1049 }
1050
1051 pub fn config(&self) -> Result<EthConfig> {
1062 node_info!("eth_config");
1063 Ok(EthConfig {
1064 current: EthForkConfig {
1065 activation_time: 0,
1066 blob_schedule: self.backend.blob_params(),
1067 chain_id: self.backend.chain_id().to::<u64>(),
1068 fork_id: Bytes::from_static(&[0; 4]),
1069 precompiles: self.backend.precompiles(),
1070 system_contracts: self.backend.system_contracts(),
1071 },
1072 next: None,
1073 last: None,
1074 })
1075 }
1076
1077 pub fn submit_work(&self, _: B64, _: B256, _: B256) -> Result<bool> {
1081 node_info!("eth_submitWork");
1082 Err(BlockchainError::RpcUnimplemented)
1083 }
1084
1085 pub fn submit_hashrate(&self, _: U256, _: B256) -> Result<bool> {
1089 node_info!("eth_submitHashrate");
1090 Err(BlockchainError::RpcUnimplemented)
1091 }
1092
1093 pub async fn fee_history(
1097 &self,
1098 block_count: U256,
1099 newest_block: BlockNumber,
1100 reward_percentiles: Vec<f64>,
1101 ) -> Result<FeeHistory> {
1102 node_info!("eth_feeHistory");
1103 let number = self.backend.convert_block_number(Some(newest_block));
1106
1107 if let Some(fork) = self.get_fork() {
1109 if fork.predates_fork_inclusive(number) {
1112 return fork
1113 .fee_history(block_count.to(), BlockNumber::Number(number), &reward_percentiles)
1114 .await
1115 .map_err(BlockchainError::AlloyForkProvider);
1116 }
1117 }
1118
1119 const MAX_BLOCK_COUNT: u64 = 1024u64;
1120 let block_count = block_count.saturating_to::<u64>().min(MAX_BLOCK_COUNT);
1121
1122 let highest = number;
1124 let lowest = highest.saturating_sub(block_count.saturating_sub(1));
1125
1126 if lowest < self.backend.best_number().saturating_sub(self.fee_history_limit) {
1128 return Err(FeeHistoryError::InvalidBlockRange.into());
1129 }
1130
1131 let mut response = FeeHistory {
1132 oldest_block: lowest,
1133 base_fee_per_gas: Vec::new(),
1134 gas_used_ratio: Vec::new(),
1135 reward: Some(Default::default()),
1136 base_fee_per_blob_gas: Default::default(),
1137 blob_gas_used_ratio: Default::default(),
1138 };
1139 let mut rewards = Vec::new();
1140
1141 {
1142 let fee_history = self.fee_history_cache.lock();
1143
1144 for n in lowest..=highest {
1146 if let Some(block) = fee_history.get(&n) {
1148 response.base_fee_per_gas.push(block.base_fee);
1149 response.base_fee_per_blob_gas.push(block.base_fee_per_blob_gas.unwrap_or(0));
1150 response.blob_gas_used_ratio.push(block.blob_gas_used_ratio);
1151 response.gas_used_ratio.push(block.gas_used_ratio);
1152
1153 if !reward_percentiles.is_empty() {
1155 let mut block_rewards = Vec::new();
1156 let resolution_per_percentile: f64 = 2.0;
1157 for p in &reward_percentiles {
1158 let p = p.clamp(0.0, 100.0);
1159 let index = ((p.round() / 2f64) * 2f64) * resolution_per_percentile;
1160 let reward = block.rewards.get(index as usize).map_or(0, |r| *r);
1161 block_rewards.push(reward);
1162 }
1163 rewards.push(block_rewards);
1164 }
1165 }
1166 }
1167 }
1168
1169 response.reward = Some(rewards);
1170
1171 response.base_fee_per_gas.push(self.backend.fees().base_fee() as u128);
1176
1177 response.base_fee_per_blob_gas.push(self.backend.fees().base_fee_per_blob_gas());
1181
1182 Ok(response)
1183 }
1184
1185 pub fn max_priority_fee_per_gas(&self) -> Result<U256> {
1192 node_info!("eth_maxPriorityFeePerGas");
1193 Ok(U256::from(self.lowest_suggestion_tip()))
1194 }
1195
1196 pub async fn debug_code_by_hash(
1200 &self,
1201 hash: B256,
1202 block_id: Option<BlockId>,
1203 ) -> Result<Option<Bytes>> {
1204 node_info!("debug_codeByHash");
1205 self.backend.debug_code_by_hash(hash, block_id).await
1206 }
1207
1208 pub async fn debug_db_get(&self, key: String) -> Result<Option<Bytes>> {
1213 node_info!("debug_dbGet");
1214 self.backend.debug_db_get(key).await
1215 }
1216
1217 pub async fn trace_transaction(&self, tx_hash: B256) -> Result<Vec<LocalizedTransactionTrace>> {
1221 node_info!("trace_transaction");
1222 self.backend.trace_transaction(tx_hash).await
1223 }
1224
1225 pub async fn trace_block(&self, block: BlockNumber) -> Result<Vec<LocalizedTransactionTrace>> {
1229 node_info!("trace_block");
1230 self.backend.trace_block(block).await
1231 }
1232
1233 pub async fn trace_filter(
1237 &self,
1238 filter: TraceFilter,
1239 ) -> Result<Vec<LocalizedTransactionTrace>> {
1240 node_info!("trace_filter");
1241 self.backend.trace_filter(filter).await
1242 }
1243
1244 pub async fn trace_replay_block_transactions(
1248 &self,
1249 block: BlockNumber,
1250 trace_types: HashSet<TraceType>,
1251 ) -> Result<Vec<TraceResultsWithTransactionHash>> {
1252 node_info!("trace_replayBlockTransactions");
1253 self.backend.trace_replay_block_transactions(block, trace_types).await
1254 }
1255}
1256
1257impl<N: Network<ReceiptEnvelope = FoundryReceiptEnvelope>> EthApi<N> {
1258 pub async fn serialized_state(
1260 &self,
1261 preserve_historical_states: bool,
1262 ) -> Result<SerializableState> {
1263 self.backend.serialized_state(preserve_historical_states).await
1264 }
1265}
1266
1267impl EthApi<FoundryNetwork> {
1270 pub async fn anvil_dump_state(
1275 &self,
1276 preserve_historical_states: Option<bool>,
1277 ) -> Result<Bytes> {
1278 node_info!("anvil_dumpState");
1279 self.backend.dump_state(preserve_historical_states.unwrap_or(false)).await
1280 }
1281
1282 pub async fn anvil_load_state(&self, buf: Bytes) -> Result<bool> {
1287 node_info!("anvil_loadState");
1288 self.backend.load_state_bytes(buf).await
1289 }
1290
1291 async fn block_request(
1292 &self,
1293 block_number: Option<BlockId>,
1294 ) -> Result<BlockRequest<FoundryTxEnvelope>> {
1295 let block_request = match block_number {
1296 Some(BlockId::Number(BlockNumber::Pending)) => {
1297 let pending_txs = self.pool.ready_transactions().collect();
1298 BlockRequest::Pending(pending_txs)
1299 }
1300 _ => {
1301 let number = self.backend.ensure_block_number(block_number).await?;
1302 BlockRequest::Number(number)
1303 }
1304 };
1305 Ok(block_request)
1306 }
1307
1308 pub async fn anvil_add_balance(&self, address: Address, balance: U256) -> Result<()> {
1312 node_info!("anvil_addBalance");
1313 let current_balance = self.backend.get_balance(address, None).await?;
1314 self.backend.set_balance(address, current_balance.saturating_add(balance)).await?;
1315 Ok(())
1316 }
1317
1318 pub async fn anvil_rollback(&self, depth: Option<u64>) -> Result<()> {
1329 node_info!("anvil_rollback");
1330 let depth = depth.unwrap_or(1);
1331
1332 let current_height = self.backend.best_number();
1334 let common_height = current_height.checked_sub(depth).ok_or(BlockchainError::RpcError(
1335 RpcError::invalid_params(format!(
1336 "Rollback depth must not exceed current chain height: current height {current_height}, depth {depth}"
1337 )),
1338 ))?;
1339
1340 let common_block =
1342 self.backend.get_block(common_height).ok_or(BlockchainError::BlockNotFound)?;
1343
1344 self.backend.rollback(common_block).await?;
1345 Ok(())
1346 }
1347
1348 fn do_estimate_gas_with_state(
1352 &self,
1353 mut request: WithOtherFields<TransactionRequest>,
1354 state: &dyn DatabaseRef,
1355 block_env: BlockEnv,
1356 ) -> Result<u128> {
1357 if !self.backend.is_tempo() {
1362 let to = request.to.as_ref().and_then(TxKind::to);
1363
1364 let maybe_transfer = (request.input.input().is_none()
1366 || request.input.input().is_some_and(|data| data.is_empty()))
1367 && request.authorization_list.is_none()
1368 && request.access_list.is_none()
1369 && request.blob_versioned_hashes.is_none();
1370
1371 if maybe_transfer
1372 && let Some(to) = to
1373 && let Ok(target_code) = self.backend.get_code_with_state(&state, *to)
1374 && target_code.as_ref().is_empty()
1375 {
1376 return Ok(MIN_TRANSACTION_GAS);
1377 }
1378 }
1379
1380 let fees = FeeDetails::new(
1381 request.gas_price,
1382 request.max_fee_per_gas,
1383 request.max_priority_fee_per_gas,
1384 request.max_fee_per_blob_gas,
1385 )?
1386 .or_zero_fees();
1387
1388 let mut highest_gas_limit = request.gas.map_or(block_env.gas_limit.into(), |g| g as u128);
1391
1392 let is_tempo_tx = request.other.get("feeToken").is_some_and(|v| !v.is_null());
1394
1395 let gas_price = fees.gas_price.unwrap_or_default();
1396 if gas_price > 0
1399 && !is_tempo_tx
1400 && let Some(from) = request.from
1401 {
1402 let mut available_funds = self.backend.get_balance_with_state(state, from)?;
1403 if let Some(value) = request.value {
1404 if value > available_funds {
1405 return Err(InvalidTransactionError::InsufficientFunds.into());
1406 }
1407 available_funds -= value;
1409 }
1410 let allowance = available_funds.checked_div(U256::from(gas_price)).unwrap_or_default();
1412 highest_gas_limit = std::cmp::min(highest_gas_limit, allowance.saturating_to());
1413 }
1414
1415 let mut call_to_estimate = request.clone();
1416 call_to_estimate.gas = Some(highest_gas_limit as u64);
1417
1418 let ethres =
1420 self.backend.call_with_state(&state, call_to_estimate, fees.clone(), block_env.clone());
1421
1422 let gas_used = match ethres.try_into()? {
1423 GasEstimationCallResult::Success(gas) => Ok(gas),
1424 GasEstimationCallResult::OutOfGas => {
1425 Err(InvalidTransactionError::BasicOutOfGas(highest_gas_limit).into())
1426 }
1427 GasEstimationCallResult::Revert(output) => {
1428 Err(InvalidTransactionError::Revert(output).into())
1429 }
1430 GasEstimationCallResult::EvmError(err) => {
1431 warn!(target: "node", "estimation failed due to {:?}", err);
1432 Err(BlockchainError::EvmError(err))
1433 }
1434 }?;
1435
1436 let mut lowest_gas_limit = determine_base_gas_by_kind(&request);
1443
1444 let mut mid_gas_limit =
1446 std::cmp::min(gas_used * 3, (highest_gas_limit + lowest_gas_limit) / 2);
1447
1448 while (highest_gas_limit - lowest_gas_limit) > 1 {
1450 request.gas = Some(mid_gas_limit as u64);
1451 let ethres = self.backend.call_with_state(
1452 &state,
1453 request.clone(),
1454 fees.clone(),
1455 block_env.clone(),
1456 );
1457
1458 match ethres.try_into()? {
1459 GasEstimationCallResult::Success(_) => {
1460 highest_gas_limit = mid_gas_limit;
1464 }
1465 GasEstimationCallResult::OutOfGas
1466 | GasEstimationCallResult::Revert(_)
1467 | GasEstimationCallResult::EvmError(_) => {
1468 lowest_gas_limit = mid_gas_limit;
1475 }
1476 };
1477 mid_gas_limit = (highest_gas_limit + lowest_gas_limit) / 2;
1479 }
1480
1481 trace!(target : "node", "Estimated Gas for call {:?}", highest_gas_limit);
1482
1483 Ok(highest_gas_limit)
1484 }
1485
1486 #[allow(clippy::large_stack_frames)]
1488 pub async fn execute(&self, request: EthRequest) -> ResponseResult {
1489 trace!(target: "rpc::api", "executing eth request");
1490 let response = match request.clone() {
1491 EthRequest::EthProtocolVersion(()) => self.protocol_version().to_rpc_result(),
1492 EthRequest::Web3ClientVersion(()) => self.client_version().to_rpc_result(),
1493 EthRequest::Web3Sha3(content) => self.sha3(content).to_rpc_result(),
1494 EthRequest::EthGetAccount(addr, block) => {
1495 self.get_account(addr, block).await.to_rpc_result()
1496 }
1497 EthRequest::EthGetAccountInfo(addr, block) => {
1498 self.get_account_info(addr, block).await.to_rpc_result()
1499 }
1500 EthRequest::EthGetBalance(addr, block) => {
1501 self.balance(addr, block).await.to_rpc_result()
1502 }
1503 EthRequest::EthGetTransactionByHash(hash) => {
1504 self.transaction_by_hash(hash).await.to_rpc_result()
1505 }
1506 EthRequest::EthSendTransaction(request) => {
1507 self.send_transaction(*request).await.to_rpc_result()
1508 }
1509 EthRequest::EthSendTransactionSync(request) => {
1510 self.send_transaction_sync(*request).await.to_rpc_result()
1511 }
1512 EthRequest::EthChainId(_) => self.eth_chain_id().to_rpc_result(),
1513 EthRequest::EthNetworkId(_) => self.network_id().to_rpc_result(),
1514 EthRequest::NetListening(_) => self.net_listening().to_rpc_result(),
1515 EthRequest::EthHashrate(()) => self.hashrate().to_rpc_result(),
1516 EthRequest::EthGasPrice(_) => self.eth_gas_price().to_rpc_result(),
1517 EthRequest::EthMaxPriorityFeePerGas(_) => {
1518 self.gas_max_priority_fee_per_gas().to_rpc_result()
1519 }
1520 EthRequest::EthBlobBaseFee(_) => self.blob_base_fee().to_rpc_result(),
1521 EthRequest::EthAccounts(_) => self.accounts().to_rpc_result(),
1522 EthRequest::EthBlockNumber(_) => self.block_number().to_rpc_result(),
1523 EthRequest::EthCoinbase(()) => self.author().to_rpc_result(),
1524 EthRequest::EthGetStorageAt(addr, slot, block) => {
1525 self.storage_at(addr, slot, block).await.to_rpc_result()
1526 }
1527 EthRequest::EthGetStorageValues(requests, block) => {
1528 self.storage_values(requests, block).await.to_rpc_result()
1529 }
1530 EthRequest::EthGetBlockByHash(hash, full) => {
1531 if full {
1532 self.block_by_hash_full(hash).await.to_rpc_result()
1533 } else {
1534 self.block_by_hash(hash).await.to_rpc_result()
1535 }
1536 }
1537 EthRequest::EthGetBlockByNumber(num, full) => {
1538 if full {
1539 self.block_by_number_full(num).await.to_rpc_result()
1540 } else {
1541 self.block_by_number(num).await.to_rpc_result()
1542 }
1543 }
1544 EthRequest::EthGetTransactionCount(addr, block) => {
1545 self.transaction_count(addr, block).await.to_rpc_result()
1546 }
1547 EthRequest::EthGetTransactionCountByHash(hash) => {
1548 self.block_transaction_count_by_hash(hash).await.to_rpc_result()
1549 }
1550 EthRequest::EthGetTransactionCountByNumber(num) => {
1551 self.block_transaction_count_by_number(num).await.to_rpc_result()
1552 }
1553 EthRequest::EthGetUnclesCountByHash(hash) => {
1554 self.block_uncles_count_by_hash(hash).await.to_rpc_result()
1555 }
1556 EthRequest::EthGetUnclesCountByNumber(num) => {
1557 self.block_uncles_count_by_number(num).await.to_rpc_result()
1558 }
1559 EthRequest::EthGetCodeAt(addr, block) => {
1560 self.get_code(addr, block).await.to_rpc_result()
1561 }
1562 EthRequest::EthGetProof(addr, keys, block) => {
1563 self.get_proof(addr, keys, block).await.to_rpc_result()
1564 }
1565 EthRequest::EthSign(addr, content) => self.sign(addr, content).await.to_rpc_result(),
1566 EthRequest::PersonalSign(content, addr) => {
1567 self.sign(addr, content).await.to_rpc_result()
1568 }
1569 EthRequest::EthSignTransaction(request) => {
1570 self.sign_transaction(*request).await.to_rpc_result()
1571 }
1572 EthRequest::EthSignTypedData(addr, data) => {
1573 self.sign_typed_data(addr, data).await.to_rpc_result()
1574 }
1575 EthRequest::EthSignTypedDataV3(addr, data) => {
1576 self.sign_typed_data_v3(addr, data).await.to_rpc_result()
1577 }
1578 EthRequest::EthSignTypedDataV4(addr, data) => {
1579 self.sign_typed_data_v4(addr, &data).await.to_rpc_result()
1580 }
1581 EthRequest::EthSendRawTransaction(tx) => {
1582 self.send_raw_transaction(tx).await.to_rpc_result()
1583 }
1584 EthRequest::EthSendRawTransactionSync(tx) => {
1585 self.send_raw_transaction_sync(tx).await.to_rpc_result()
1586 }
1587 EthRequest::EthCall(call, block, state_override, block_overrides) => self
1588 .call(call, block, EvmOverrides::new(state_override, block_overrides))
1589 .await
1590 .to_rpc_result(),
1591 EthRequest::EthSimulateV1(simulation, block) => {
1592 self.simulate_v1(simulation, block).await.to_rpc_result()
1593 }
1594 EthRequest::EthCreateAccessList(call, block) => {
1595 self.create_access_list(call, block).await.to_rpc_result()
1596 }
1597 EthRequest::EthEstimateGas(call, block, state_override, block_overrides) => self
1598 .estimate_gas(call, block, EvmOverrides::new(state_override, block_overrides))
1599 .await
1600 .to_rpc_result(),
1601 EthRequest::EthFillTransaction(request) => {
1602 self.fill_transaction(request).await.to_rpc_result()
1603 }
1604 EthRequest::EthGetRawTransactionByHash(hash) => {
1605 self.raw_transaction(hash).await.to_rpc_result()
1606 }
1607 EthRequest::GetBlobByHash(hash) => {
1608 self.anvil_get_blob_by_versioned_hash(hash).to_rpc_result()
1609 }
1610 EthRequest::GetBlobByTransactionHash(hash) => {
1611 self.anvil_get_blob_by_tx_hash(hash).to_rpc_result()
1612 }
1613 EthRequest::GetGenesisTime(()) => self.anvil_get_genesis_time().to_rpc_result(),
1614 EthRequest::EthGetRawTransactionByBlockHashAndIndex(hash, index) => {
1615 self.raw_transaction_by_block_hash_and_index(hash, index).await.to_rpc_result()
1616 }
1617 EthRequest::EthGetRawTransactionByBlockNumberAndIndex(num, index) => {
1618 self.raw_transaction_by_block_number_and_index(num, index).await.to_rpc_result()
1619 }
1620 EthRequest::EthGetTransactionByBlockHashAndIndex(hash, index) => {
1621 self.transaction_by_block_hash_and_index(hash, index).await.to_rpc_result()
1622 }
1623 EthRequest::EthGetTransactionByBlockNumberAndIndex(num, index) => {
1624 self.transaction_by_block_number_and_index(num, index).await.to_rpc_result()
1625 }
1626 EthRequest::EthGetTransactionReceipt(tx) => {
1627 self.transaction_receipt(tx).await.to_rpc_result()
1628 }
1629 EthRequest::EthGetBlockReceipts(number) => {
1630 self.block_receipts(number).await.to_rpc_result()
1631 }
1632 EthRequest::EthGetUncleByBlockHashAndIndex(hash, index) => {
1633 self.uncle_by_block_hash_and_index(hash, index).await.to_rpc_result()
1634 }
1635 EthRequest::EthGetUncleByBlockNumberAndIndex(num, index) => {
1636 self.uncle_by_block_number_and_index(num, index).await.to_rpc_result()
1637 }
1638 EthRequest::EthGetLogs(filter) => self.logs(filter).await.to_rpc_result(),
1639 EthRequest::EthGetWork(_) => self.work().to_rpc_result(),
1640 EthRequest::EthSyncing(_) => self.syncing().to_rpc_result(),
1641 EthRequest::EthConfig(_) => self.config().to_rpc_result(),
1642 EthRequest::EthSubmitWork(nonce, pow, digest) => {
1643 self.submit_work(nonce, pow, digest).to_rpc_result()
1644 }
1645 EthRequest::EthSubmitHashRate(rate, id) => {
1646 self.submit_hashrate(rate, id).to_rpc_result()
1647 }
1648 EthRequest::EthFeeHistory(count, newest, reward_percentiles) => {
1649 self.fee_history(count, newest, reward_percentiles).await.to_rpc_result()
1650 }
1651 EthRequest::DebugGetRawTransaction(hash) => {
1653 self.raw_transaction(hash).await.to_rpc_result()
1654 }
1655 EthRequest::DebugTraceTransaction(tx, opts) => {
1657 self.debug_trace_transaction(tx, opts).await.to_rpc_result()
1658 }
1659 EthRequest::DebugTraceCall(tx, block, opts) => {
1661 self.debug_trace_call(tx, block, opts).await.to_rpc_result()
1662 }
1663 EthRequest::DebugCodeByHash(hash, block) => {
1664 self.debug_code_by_hash(hash, block).await.to_rpc_result()
1665 }
1666 EthRequest::DebugDbGet(key) => self.debug_db_get(key).await.to_rpc_result(),
1667 EthRequest::DebugTraceBlockByHash(block_hash, opts) => {
1668 self.debug_trace_block_by_hash(block_hash, opts).await.to_rpc_result()
1669 }
1670 EthRequest::DebugTraceBlockByNumber(block_number, opts) => {
1671 self.debug_trace_block_by_number(block_number, opts).await.to_rpc_result()
1672 }
1673 EthRequest::TraceTransaction(tx) => self.trace_transaction(tx).await.to_rpc_result(),
1674 EthRequest::TraceBlock(block) => self.trace_block(block).await.to_rpc_result(),
1675 EthRequest::TraceFilter(filter) => self.trace_filter(filter).await.to_rpc_result(),
1676 EthRequest::TraceReplayBlockTransactions(block, trace_types) => {
1677 self.trace_replay_block_transactions(block, trace_types).await.to_rpc_result()
1678 }
1679 EthRequest::ImpersonateAccount(addr) => {
1680 self.anvil_impersonate_account(addr).await.to_rpc_result()
1681 }
1682 EthRequest::StopImpersonatingAccount(addr) => {
1683 self.anvil_stop_impersonating_account(addr).await.to_rpc_result()
1684 }
1685 EthRequest::AutoImpersonateAccount(enable) => {
1686 self.anvil_auto_impersonate_account(enable).await.to_rpc_result()
1687 }
1688 EthRequest::ImpersonateSignature(signature, address) => {
1689 self.anvil_impersonate_signature(signature, address).await.to_rpc_result()
1690 }
1691 EthRequest::GetAutoMine(()) => self.anvil_get_auto_mine().to_rpc_result(),
1692 EthRequest::Mine(blocks, interval) => {
1693 self.anvil_mine(blocks, interval).await.to_rpc_result()
1694 }
1695 EthRequest::SetAutomine(enabled) => {
1696 self.anvil_set_auto_mine(enabled).await.to_rpc_result()
1697 }
1698 EthRequest::SetIntervalMining(interval) => {
1699 self.anvil_set_interval_mining(interval).to_rpc_result()
1700 }
1701 EthRequest::GetIntervalMining(()) => self.anvil_get_interval_mining().to_rpc_result(),
1702 EthRequest::DropTransaction(tx) => {
1703 self.anvil_drop_transaction(tx).await.to_rpc_result()
1704 }
1705 EthRequest::DropAllTransactions() => {
1706 self.anvil_drop_all_transactions().await.to_rpc_result()
1707 }
1708 EthRequest::Reset(fork) => {
1709 self.anvil_reset(fork.and_then(|p| p.params)).await.to_rpc_result()
1710 }
1711 EthRequest::SetBalance(addr, val) => {
1712 self.anvil_set_balance(addr, val).await.to_rpc_result()
1713 }
1714 EthRequest::AddBalance(addr, val) => {
1715 self.anvil_add_balance(addr, val).await.to_rpc_result()
1716 }
1717 EthRequest::DealERC20(addr, token_addr, val) => {
1718 self.anvil_deal_erc20(addr, token_addr, val).await.to_rpc_result()
1719 }
1720 EthRequest::SetERC20Allowance(owner, spender, token_addr, val) => self
1721 .anvil_set_erc20_allowance(owner, spender, token_addr, val)
1722 .await
1723 .to_rpc_result(),
1724 EthRequest::SetCode(addr, code) => {
1725 self.anvil_set_code(addr, code).await.to_rpc_result()
1726 }
1727 EthRequest::SetNonce(addr, nonce) => {
1728 self.anvil_set_nonce(addr, nonce).await.to_rpc_result()
1729 }
1730 EthRequest::SetStorageAt(addr, slot, val) => {
1731 self.anvil_set_storage_at(addr, slot, val).await.to_rpc_result()
1732 }
1733 EthRequest::SetCoinbase(addr) => self.anvil_set_coinbase(addr).await.to_rpc_result(),
1734 EthRequest::SetChainId(id) => self.anvil_set_chain_id(id).await.to_rpc_result(),
1735 EthRequest::SetLogging(log) => self.anvil_set_logging(log).await.to_rpc_result(),
1736 EthRequest::SetMinGasPrice(gas) => {
1737 self.anvil_set_min_gas_price(gas).await.to_rpc_result()
1738 }
1739 EthRequest::SetNextBlockBaseFeePerGas(gas) => {
1740 self.anvil_set_next_block_base_fee_per_gas(gas).await.to_rpc_result()
1741 }
1742 EthRequest::DumpState(preserve_historical_states) => self
1743 .anvil_dump_state(preserve_historical_states.and_then(|s| s.params))
1744 .await
1745 .to_rpc_result(),
1746 EthRequest::LoadState(buf) => self.anvil_load_state(buf).await.to_rpc_result(),
1747 EthRequest::NodeInfo(_) => self.anvil_node_info().await.to_rpc_result(),
1748 EthRequest::AnvilMetadata(_) => self.anvil_metadata().await.to_rpc_result(),
1749 EthRequest::EvmSnapshot(_) => self.evm_snapshot().await.to_rpc_result(),
1750 EthRequest::EvmRevert(id) => self.evm_revert(id).await.to_rpc_result(),
1751 EthRequest::EvmIncreaseTime(time) => self.evm_increase_time(time).await.to_rpc_result(),
1752 EthRequest::EvmSetNextBlockTimeStamp(time) => {
1753 if time >= U256::from(u64::MAX) {
1754 return ResponseResult::Error(RpcError::invalid_params(
1755 "The timestamp is too big",
1756 ));
1757 }
1758 let time = time.to::<u64>();
1759 self.evm_set_next_block_timestamp(time).to_rpc_result()
1760 }
1761 EthRequest::EvmSetTime(timestamp) => {
1762 if timestamp >= U256::from(u64::MAX) {
1763 return ResponseResult::Error(RpcError::invalid_params(
1764 "The timestamp is too big",
1765 ));
1766 }
1767 let raw = timestamp.to::<u64>();
1771 let time = if raw > 1_000_000_000_000 {
1772 Duration::from_millis(raw).as_secs()
1773 } else {
1774 raw
1775 };
1776 self.evm_set_time(time).to_rpc_result()
1777 }
1778 EthRequest::EvmSetBlockGasLimit(gas_limit) => {
1779 self.evm_set_block_gas_limit(gas_limit).to_rpc_result()
1780 }
1781 EthRequest::EvmSetBlockTimeStampInterval(time) => {
1782 self.evm_set_block_timestamp_interval(time).to_rpc_result()
1783 }
1784 EthRequest::EvmRemoveBlockTimeStampInterval(()) => {
1785 self.evm_remove_block_timestamp_interval().to_rpc_result()
1786 }
1787 EthRequest::EvmMine(mine) => {
1788 self.evm_mine(mine.and_then(|p| p.params)).await.to_rpc_result()
1789 }
1790 EthRequest::EvmMineDetailed(mine) => {
1791 self.evm_mine_detailed(mine.and_then(|p| p.params)).await.to_rpc_result()
1792 }
1793 EthRequest::SetRpcUrl(url) => self.anvil_set_rpc_url(url).await.to_rpc_result(),
1794 EthRequest::EthSendUnsignedTransaction(tx) => {
1795 self.eth_send_unsigned_transaction(*tx).await.to_rpc_result()
1796 }
1797 EthRequest::EthNewFilter(filter) => self.new_filter(filter).await.to_rpc_result(),
1798 EthRequest::EthGetFilterChanges(id) => self.get_filter_changes(&id).await,
1799 EthRequest::EthNewBlockFilter(_) => self.new_block_filter().await.to_rpc_result(),
1800 EthRequest::EthNewPendingTransactionFilter(_) => {
1801 self.new_pending_transaction_filter().await.to_rpc_result()
1802 }
1803 EthRequest::EthGetFilterLogs(id) => self.get_filter_logs(&id).await.to_rpc_result(),
1804 EthRequest::EthUninstallFilter(id) => self.uninstall_filter(&id).await.to_rpc_result(),
1805 EthRequest::TxPoolStatus(_) => self.txpool_status().await.to_rpc_result(),
1806 EthRequest::TxPoolInspect(_) => self.txpool_inspect().await.to_rpc_result(),
1807 EthRequest::TxPoolContent(_) => self.txpool_content().await.to_rpc_result(),
1808 EthRequest::ErigonGetHeaderByNumber(num) => {
1809 self.erigon_get_header_by_number(num).await.to_rpc_result()
1810 }
1811 EthRequest::OtsGetApiLevel(_) => self.ots_get_api_level().await.to_rpc_result(),
1812 EthRequest::OtsGetInternalOperations(hash) => {
1813 self.ots_get_internal_operations(hash).await.to_rpc_result()
1814 }
1815 EthRequest::OtsHasCode(addr, num) => self.ots_has_code(addr, num).await.to_rpc_result(),
1816 EthRequest::OtsTraceTransaction(hash) => {
1817 self.ots_trace_transaction(hash).await.to_rpc_result()
1818 }
1819 EthRequest::OtsGetTransactionError(hash) => {
1820 self.ots_get_transaction_error(hash).await.to_rpc_result()
1821 }
1822 EthRequest::OtsGetBlockDetails(num) => {
1823 self.ots_get_block_details(num).await.to_rpc_result()
1824 }
1825 EthRequest::OtsGetBlockDetailsByHash(hash) => {
1826 self.ots_get_block_details_by_hash(hash).await.to_rpc_result()
1827 }
1828 EthRequest::OtsGetBlockTransactions(num, page, page_size) => {
1829 self.ots_get_block_transactions(num, page, page_size).await.to_rpc_result()
1830 }
1831 EthRequest::OtsSearchTransactionsBefore(address, num, page_size) => {
1832 self.ots_search_transactions_before(address, num, page_size).await.to_rpc_result()
1833 }
1834 EthRequest::OtsSearchTransactionsAfter(address, num, page_size) => {
1835 self.ots_search_transactions_after(address, num, page_size).await.to_rpc_result()
1836 }
1837 EthRequest::OtsGetTransactionBySenderAndNonce(address, nonce) => {
1838 self.ots_get_transaction_by_sender_and_nonce(address, nonce).await.to_rpc_result()
1839 }
1840 EthRequest::EthGetTransactionBySenderAndNonce(sender, nonce) => {
1841 self.transaction_by_sender_and_nonce(sender, nonce).await.to_rpc_result()
1842 }
1843 EthRequest::OtsGetContractCreator(address) => {
1844 self.ots_get_contract_creator(address).await.to_rpc_result()
1845 }
1846 EthRequest::RemovePoolTransactions(address) => {
1847 self.anvil_remove_pool_transactions(address).await.to_rpc_result()
1848 }
1849 EthRequest::Reorg(reorg_options) => {
1850 self.anvil_reorg(reorg_options).await.to_rpc_result()
1851 }
1852 EthRequest::Rollback(depth) => self.anvil_rollback(depth).await.to_rpc_result(),
1853 EthRequest::SetFeeToken(user, token) => {
1854 self.anvil_set_fee_token(user, token).await.to_rpc_result()
1855 }
1856 EthRequest::SetValidatorFeeToken(validator, token) => {
1857 self.anvil_set_validator_fee_token(validator, token).await.to_rpc_result()
1858 }
1859 EthRequest::SetFeeAmmLiquidity(user_token, validator_token, amount) => self
1860 .anvil_set_fee_amm_liquidity(user_token, validator_token, amount)
1861 .await
1862 .to_rpc_result(),
1863 };
1864
1865 if let ResponseResult::Error(err) = &response {
1866 node_info!("\nRPC request failed:");
1867 node_info!(" Request: {:?}", request);
1868 node_info!(" Error: {}\n", err);
1869 }
1870
1871 response
1872 }
1873
1874 fn sign_request(&self, from: &Address, typed_tx: FoundryTypedTx) -> Result<FoundryTxEnvelope> {
1875 match typed_tx {
1876 #[cfg(feature = "optimism")]
1877 FoundryTypedTx::Deposit(_) => return Ok(build_impersonated(typed_tx)),
1878 _ => {
1879 for signer in self.signers.iter() {
1880 if signer.accounts().contains(from) {
1881 return signer.sign_transaction_from(from, typed_tx);
1882 }
1883 }
1884 }
1885 }
1886 Err(BlockchainError::NoSignerAvailable)
1887 }
1888
1889 async fn inner_raw_transaction(&self, hash: B256) -> Result<Option<Bytes>> {
1890 match self.pool.get_transaction(hash) {
1891 Some(tx) => Ok(Some(tx.transaction.encoded_2718().into())),
1892 None => match self.backend.transaction_by_hash(hash).await? {
1893 Some(tx) => Ok(Some(tx.as_ref().encoded_2718().into())),
1894 None => Ok(None),
1895 },
1896 }
1897 }
1898
1899 pub async fn balance(&self, address: Address, block_number: Option<BlockId>) -> Result<U256> {
1903 node_info!("eth_getBalance");
1904 let block_request = self.block_request(block_number).await?;
1905
1906 if let BlockRequest::Number(number) = block_request
1908 && let Some(fork) = self.get_fork()
1909 && fork.predates_fork(number)
1910 {
1911 return Ok(fork.get_balance(address, number).await?);
1912 }
1913
1914 self.backend.get_balance(address, Some(block_request)).await
1915 }
1916
1917 pub async fn get_account(
1921 &self,
1922 address: Address,
1923 block_number: Option<BlockId>,
1924 ) -> Result<TrieAccount> {
1925 node_info!("eth_getAccount");
1926 let block_request = self.block_request(block_number).await?;
1927
1928 if let BlockRequest::Number(number) = block_request
1930 && let Some(fork) = self.get_fork()
1931 && fork.predates_fork(number)
1932 {
1933 return Ok(fork.get_account(address, number).await?);
1934 }
1935
1936 self.backend.get_account_at_block(address, Some(block_request)).await
1937 }
1938
1939 pub async fn get_account_info(
1943 &self,
1944 address: Address,
1945 block_number: Option<BlockId>,
1946 ) -> Result<alloy_rpc_types::eth::AccountInfo> {
1947 node_info!("eth_getAccountInfo");
1948
1949 if let Some(fork) = self.get_fork() {
1950 let block_request = self.block_request(block_number).await?;
1951 if let BlockRequest::Number(number) = block_request {
1953 trace!(target: "node", "get_account_info: fork block {}, requested block {number}", fork.block_number());
1954 return if fork.predates_fork(number) {
1955 let balance = fork.get_balance(address, number).map_err(BlockchainError::from);
1958 let code = fork.get_code(address, number).map_err(BlockchainError::from);
1959 let nonce = self.get_transaction_count(address, Some(number.into()));
1960 let (balance, code, nonce) = try_join!(balance, code, nonce)?;
1961
1962 Ok(alloy_rpc_types::eth::AccountInfo { balance, nonce, code })
1963 } else {
1964 let account_info = self.backend.get_account(address).await?;
1967 let code = self.backend.get_code(address, Some(block_request)).await?;
1968 Ok(alloy_rpc_types::eth::AccountInfo {
1969 balance: account_info.balance,
1970 nonce: account_info.nonce,
1971 code,
1972 })
1973 };
1974 }
1975 }
1976
1977 let account = self.get_account(address, block_number);
1978 let code = self.get_code(address, block_number);
1979 let (account, code) = try_join!(account, code)?;
1980 Ok(alloy_rpc_types::eth::AccountInfo {
1981 balance: account.balance,
1982 nonce: account.nonce,
1983 code,
1984 })
1985 }
1986 pub async fn storage_at(
1990 &self,
1991 address: Address,
1992 index: U256,
1993 block_number: Option<BlockId>,
1994 ) -> Result<B256> {
1995 node_info!("eth_getStorageAt");
1996 let block_request = self.block_request(block_number).await?;
1997
1998 if let BlockRequest::Number(number) = block_request
2000 && let Some(fork) = self.get_fork()
2001 && fork.predates_fork(number)
2002 {
2003 return Ok(B256::from(
2004 fork.storage_at(address, index, Some(BlockNumber::Number(number))).await?,
2005 ));
2006 }
2007
2008 self.backend.storage_at(address, index, Some(block_request)).await
2009 }
2010
2011 pub async fn storage_values(
2015 &self,
2016 requests: HashMap<Address, Vec<B256>>,
2017 block_number: Option<BlockId>,
2018 ) -> Result<HashMap<Address, Vec<B256>>> {
2019 node_info!("eth_getStorageValues");
2020
2021 let total_slots: usize = requests.values().map(|s| s.len()).sum();
2022 if total_slots > 1024 {
2023 return Err(BlockchainError::RpcError(RpcError::invalid_params(format!(
2024 "total slot count {total_slots} exceeds limit 1024"
2025 ))));
2026 }
2027
2028 let block_request = self.block_request(block_number).await?;
2029
2030 if let BlockRequest::Number(number) = block_request
2032 && let Some(fork) = self.get_fork()
2033 && fork.predates_fork(number)
2034 {
2035 let mut result: HashMap<Address, Vec<B256>> = HashMap::default();
2036 for (address, slots) in requests {
2037 let mut values = Vec::with_capacity(slots.len());
2038 for slot in &slots {
2039 let val = fork
2040 .storage_at(address, (*slot).into(), Some(BlockNumber::Number(number)))
2041 .await?;
2042 values.push(B256::from(val));
2043 }
2044 result.insert(address, values);
2045 }
2046 return Ok(result);
2047 }
2048
2049 self.backend.storage_values(requests, Some(block_request)).await
2050 }
2051
2052 pub async fn block_by_number(&self, number: BlockNumber) -> Result<Option<AnyRpcBlock>> {
2056 node_info!("eth_getBlockByNumber");
2057 if number == BlockNumber::Pending {
2058 return Ok(Some(self.pending_block().await));
2059 }
2060
2061 self.backend.block_by_number(number).await
2062 }
2063
2064 pub async fn block_by_number_full(&self, number: BlockNumber) -> Result<Option<AnyRpcBlock>> {
2068 node_info!("eth_getBlockByNumber");
2069 if number == BlockNumber::Pending {
2070 return Ok(self.pending_block_full().await);
2071 }
2072 self.backend.block_by_number_full(number).await
2073 }
2074
2075 pub async fn transaction_count(
2082 &self,
2083 address: Address,
2084 block_number: Option<BlockId>,
2085 ) -> Result<U256> {
2086 node_info!("eth_getTransactionCount");
2087 self.get_transaction_count(address, block_number).await.map(U256::from)
2088 }
2089
2090 pub async fn block_transaction_count_by_number(
2094 &self,
2095 block_number: BlockNumber,
2096 ) -> Result<Option<U256>> {
2097 node_info!("eth_getBlockTransactionCountByNumber");
2098 let block_request = self.block_request(Some(block_number.into())).await?;
2099 if let BlockRequest::Pending(txs) = block_request {
2100 let block = self.backend.pending_block(txs).await;
2101 return Ok(Some(U256::from(block.block.body.transactions.len())));
2102 }
2103 let block = self.backend.block_by_number(block_number).await?;
2104 let txs = block.map(|b| match b.transactions() {
2105 BlockTransactions::Full(txs) => U256::from(txs.len()),
2106 BlockTransactions::Hashes(txs) => U256::from(txs.len()),
2107 BlockTransactions::Uncle => U256::from(0),
2108 });
2109 Ok(txs)
2110 }
2111
2112 pub async fn get_code(&self, address: Address, block_number: Option<BlockId>) -> Result<Bytes> {
2116 node_info!("eth_getCode");
2117 let block_request = self.block_request(block_number).await?;
2118 if let BlockRequest::Number(number) = block_request
2120 && let Some(fork) = self.get_fork()
2121 && fork.predates_fork(number)
2122 {
2123 return Ok(fork.get_code(address, number).await?);
2124 }
2125 self.backend.get_code(address, Some(block_request)).await
2126 }
2127
2128 pub async fn get_proof(
2133 &self,
2134 address: Address,
2135 keys: Vec<B256>,
2136 block_number: Option<BlockId>,
2137 ) -> Result<EIP1186AccountProofResponse> {
2138 node_info!("eth_getProof");
2139 let block_request = self.block_request(block_number).await?;
2140
2141 if let BlockRequest::Number(number) = block_request
2144 && let Some(fork) = self.get_fork()
2145 && fork.predates_fork_inclusive(number)
2146 {
2147 return Ok(fork.get_proof(address, keys, Some(number.into())).await?);
2148 }
2149
2150 let proof = self.backend.prove_account_at(address, keys, Some(block_request)).await?;
2151 Ok(proof)
2152 }
2153
2154 pub async fn sign_transaction(
2158 &self,
2159 request: WithOtherFields<TransactionRequest>,
2160 ) -> Result<String> {
2161 node_info!("eth_signTransaction");
2162
2163 let from = request.from.map(Ok).unwrap_or_else(|| {
2164 self.accounts()?.first().copied().ok_or(BlockchainError::NoSignerAvailable)
2165 })?;
2166
2167 let (nonce, _) = self.request_nonce(&request, from).await?;
2168
2169 let request = self.build_tx_request(request, nonce).await?;
2170
2171 let signed_transaction = self.sign_request(&from, request)?.encoded_2718();
2172 Ok(alloy_primitives::hex::encode_prefixed(signed_transaction))
2173 }
2174
2175 pub async fn send_transaction(
2179 &self,
2180 request: WithOtherFields<TransactionRequest>,
2181 ) -> Result<TxHash> {
2182 node_info!("eth_sendTransaction");
2183
2184 let from = request.from.map(Ok).unwrap_or_else(|| {
2185 self.accounts()?.first().copied().ok_or(BlockchainError::NoSignerAvailable)
2186 })?;
2187 let (nonce, on_chain_nonce) = self.request_nonce(&request, from).await?;
2188
2189 let typed_tx = self.build_tx_request(request, nonce).await?;
2190
2191 let pending_transaction = if self.is_impersonated(from) {
2193 let transaction = sign::build_impersonated(typed_tx);
2194 self.ensure_typed_transaction_supported(&transaction)?;
2195 trace!(target : "node", ?from, "eth_sendTransaction: impersonating");
2196 PendingTransaction::with_impersonated(transaction, from)
2197 } else {
2198 let transaction = self.sign_request(&from, typed_tx)?;
2199 self.ensure_typed_transaction_supported(&transaction)?;
2200 PendingTransaction::new(transaction)?
2201 };
2202 self.backend.validate_pool_transaction(&pending_transaction).await?;
2204
2205 let (requires, provides) = if let Some((requires, provides)) =
2206 tempo_parallel_nonce_markers(&pending_transaction)
2207 {
2208 (requires, provides)
2209 } else {
2210 (required_marker(nonce, on_chain_nonce, from), vec![to_marker(nonce, from)])
2211 };
2212
2213 self.add_pending_transaction(pending_transaction, requires, provides)
2214 }
2215
2216 async fn await_transaction_inclusion(&self, hash: TxHash) -> Result<FoundryTxReceipt> {
2218 let mut stream = self.new_block_notifications();
2219 if let Some(receipt) = self.backend.transaction_receipt(hash).await? {
2221 return Ok(receipt);
2222 }
2223 while let Some(notification) = stream.next().await {
2224 if let Some(block) = self.backend.get_block_by_hash(notification.hash)
2225 && block.body.transactions.iter().any(|tx| tx.hash() == hash)
2226 && let Some(receipt) = self.backend.transaction_receipt(hash).await?
2227 {
2228 return Ok(receipt);
2229 }
2230 }
2231
2232 Err(BlockchainError::Message("Failed to await transaction inclusion".to_string()))
2233 }
2234
2235 async fn check_transaction_inclusion(&self, hash: TxHash) -> Result<FoundryTxReceipt> {
2237 const TIMEOUT_DURATION: Duration = Duration::from_secs(30);
2238 tokio::time::timeout(TIMEOUT_DURATION, self.await_transaction_inclusion(hash))
2239 .await
2240 .unwrap_or_else(|_elapsed| {
2241 Err(BlockchainError::TransactionConfirmationTimeout {
2242 hash,
2243 duration: TIMEOUT_DURATION,
2244 })
2245 })
2246 }
2247
2248 pub async fn send_transaction_sync(
2252 &self,
2253 request: WithOtherFields<TransactionRequest>,
2254 ) -> Result<FoundryTxReceipt> {
2255 node_info!("eth_sendTransactionSync");
2256 let hash = self.send_transaction(request).await?;
2257
2258 let receipt = self.check_transaction_inclusion(hash).await?;
2259
2260 Ok(receipt)
2261 }
2262
2263 pub async fn send_raw_transaction(&self, tx: Bytes) -> Result<TxHash> {
2267 node_info!("eth_sendRawTransaction");
2268 let mut data = tx.as_ref();
2269 if data.is_empty() {
2270 return Err(BlockchainError::EmptyRawTransactionData);
2271 }
2272
2273 let transaction = FoundryTxEnvelope::decode_2718(&mut data)
2274 .map_err(|_| BlockchainError::FailedToDecodeSignedTransaction)?;
2275
2276 self.ensure_typed_transaction_supported(&transaction)?;
2277
2278 let pending_transaction = PendingTransaction::new(transaction)?;
2279
2280 self.backend.validate_pool_transaction(&pending_transaction).await?;
2282
2283 let from = *pending_transaction.sender();
2284 let priority = self.transaction_priority(&pending_transaction.transaction);
2285
2286 let (requires, provides) = if let Some((requires, provides)) =
2288 tempo_parallel_nonce_markers(&pending_transaction)
2289 {
2290 (requires, provides)
2291 } else {
2292 let on_chain_nonce = self.backend.current_nonce(from).await?;
2293 let nonce = pending_transaction.transaction.nonce();
2294 (required_marker(nonce, on_chain_nonce, from), vec![to_marker(nonce, from)])
2295 };
2296
2297 let pool_transaction =
2298 PoolTransaction { requires, provides, pending_transaction, priority };
2299
2300 let tx = self.pool.add_transaction(pool_transaction)?;
2301 trace!(target: "node", "Added transaction: [{:?}] sender={:?}", tx.hash(), from);
2302 Ok(*tx.hash())
2303 }
2304
2305 pub async fn send_raw_transaction_sync(&self, tx: Bytes) -> Result<FoundryTxReceipt> {
2309 node_info!("eth_sendRawTransactionSync");
2310
2311 let hash = self.send_raw_transaction(tx).await?;
2312 let receipt = self.check_transaction_inclusion(hash).await?;
2313
2314 Ok(receipt)
2315 }
2316
2317 pub async fn call(
2321 &self,
2322 request: WithOtherFields<TransactionRequest>,
2323 block_number: Option<BlockId>,
2324 overrides: EvmOverrides,
2325 ) -> Result<Bytes> {
2326 node_info!("eth_call");
2327 let block_request = self.block_request(block_number).await?;
2328 if let BlockRequest::Number(number) = block_request
2330 && let Some(fork) = self.get_fork()
2331 && fork.predates_fork(number)
2332 {
2333 if overrides.has_state() || overrides.has_block() {
2334 return Err(BlockchainError::EvmOverrideError(
2335 "not available on past forked blocks".to_string(),
2336 ));
2337 }
2338 return Ok(fork.call(&request, Some(number.into())).await?);
2339 }
2340
2341 let fees = FeeDetails::new(
2342 request.gas_price,
2343 request.max_fee_per_gas,
2344 request.max_priority_fee_per_gas,
2345 request.max_fee_per_blob_gas,
2346 )?
2347 .or_zero_fees();
2348 self.on_blocking_task(|this| async move {
2351 let (exit, out, gas, _) =
2352 this.backend.call(request, fees, Some(block_request), overrides).await?;
2353 trace!(target : "node", "Call status {:?}, gas {}", exit, gas);
2354
2355 ensure_return_ok(exit, &out)
2356 })
2357 .await
2358 }
2359
2360 pub async fn simulate_v1(
2361 &self,
2362 request: SimulatePayload,
2363 block_number: Option<BlockId>,
2364 ) -> Result<Vec<SimulatedBlock<AnyRpcBlock>>> {
2365 node_info!("eth_simulateV1");
2366 let block_request = self.block_request(block_number).await?;
2367 if let BlockRequest::Number(number) = block_request
2369 && let Some(fork) = self.get_fork()
2370 && fork.predates_fork(number)
2371 {
2372 return Ok(fork.simulate_v1(&request, Some(number.into())).await?);
2373 }
2374
2375 self.on_blocking_task(|this| async move {
2378 let simulated_blocks = this.backend.simulate(request, Some(block_request)).await?;
2379 trace!(target : "node", "Simulate status {:?}", simulated_blocks);
2380
2381 Ok(simulated_blocks)
2382 })
2383 .await
2384 }
2385
2386 pub async fn create_access_list(
2400 &self,
2401 mut request: WithOtherFields<TransactionRequest>,
2402 block_number: Option<BlockId>,
2403 ) -> Result<AccessListResult> {
2404 node_info!("eth_createAccessList");
2405 let block_request = self.block_request(block_number).await?;
2406 if let BlockRequest::Number(number) = block_request
2408 && let Some(fork) = self.get_fork()
2409 && fork.predates_fork(number)
2410 {
2411 return Ok(fork.create_access_list(&request, Some(number.into())).await?);
2412 }
2413
2414 self.backend
2415 .with_database_at(Some(block_request), |state, block_env| {
2416 let (exit, out, _, access_list) = self.backend.build_access_list_with_state(
2417 &state,
2418 request.clone(),
2419 FeeDetails::zero(),
2420 block_env.clone(),
2421 )?;
2422 ensure_return_ok(exit, &out)?;
2423
2424 request.access_list = Some(access_list.clone());
2426
2427 let (exit, out, gas_used, _) =
2428 self.backend.call_with_state(&state, request, FeeDetails::zero(), block_env)?;
2429 ensure_return_ok(exit, &out)?;
2430
2431 Ok(AccessListResult {
2432 access_list: AccessList(access_list.0),
2433 gas_used: U256::from(gas_used),
2434 error: None,
2435 })
2436 })
2437 .await?
2438 }
2439
2440 pub async fn estimate_gas(
2445 &self,
2446 request: WithOtherFields<TransactionRequest>,
2447 block_number: Option<BlockId>,
2448 overrides: EvmOverrides,
2449 ) -> Result<U256> {
2450 node_info!("eth_estimateGas");
2451 self.do_estimate_gas(
2452 request,
2453 block_number.or_else(|| Some(BlockNumber::Pending.into())),
2454 overrides,
2455 )
2456 .await
2457 .map(U256::from)
2458 }
2459
2460 pub async fn fill_transaction(
2467 &self,
2468 mut request: WithOtherFields<TransactionRequest>,
2469 ) -> Result<FillTransaction<AnyRpcTransaction>> {
2470 node_info!("eth_fillTransaction");
2471
2472 let from = match request.as_ref().from() {
2473 Some(from) => from,
2474 None => self.accounts()?.first().copied().ok_or(BlockchainError::NoSignerAvailable)?,
2475 };
2476
2477 let nonce = if let Some(nonce) = request.as_ref().nonce() {
2478 nonce
2479 } else {
2480 self.request_nonce(&request, from).await?.0
2481 };
2482
2483 if request.as_ref().gas_limit().is_none() {
2487 let estimated_gas =
2488 self.estimate_gas(request.clone(), None, EvmOverrides::default()).await?;
2489 request.as_mut().set_gas_limit(estimated_gas.to());
2490 }
2491
2492 let typed_tx = self.build_tx_request(request, nonce).await?;
2493 let tx = build_impersonated(typed_tx);
2494
2495 let raw = tx.encoded_2718().into();
2496
2497 let mut tx =
2498 transaction_build(None, MaybeImpersonatedTransaction::new(tx), None, None, None);
2499
2500 tx.0.inner.inner = Recovered::new_unchecked(tx.0.inner.inner.into_inner(), from);
2503
2504 Ok(FillTransaction { raw, tx })
2505 }
2506
2507 pub fn anvil_get_blob_by_tx_hash(&self, hash: B256) -> Result<Option<Vec<Blob>>> {
2509 node_info!("anvil_getBlobsByTransactionHash");
2510 Ok(self.backend.get_blob_by_tx_hash(hash)?)
2511 }
2512
2513 pub async fn transaction_by_hash(&self, hash: B256) -> Result<Option<AnyRpcTransaction>> {
2520 node_info!("eth_getTransactionByHash");
2521 let mut tx = self.pool.get_transaction(hash).map(|pending| {
2522 let from = *pending.sender();
2523 let tx = transaction_build(
2524 Some(*pending.hash()),
2525 pending.transaction,
2526 None,
2527 None,
2528 Some(self.backend.base_fee()),
2529 );
2530
2531 let WithOtherFields { inner: mut tx, other } = tx.0;
2532 tx.inner = Recovered::new_unchecked(tx.inner.into_inner(), from);
2535
2536 AnyRpcTransaction(WithOtherFields { inner: tx, other })
2537 });
2538 if tx.is_none() {
2539 tx = self.backend.transaction_by_hash(hash).await?
2540 }
2541
2542 Ok(tx)
2543 }
2544
2545 pub async fn transaction_by_sender_and_nonce(
2552 &self,
2553 sender: Address,
2554 nonce: U256,
2555 ) -> Result<Option<AnyRpcTransaction>> {
2556 node_info!("eth_getTransactionBySenderAndNonce");
2557
2558 for pending_tx in self.pool.ready_transactions().chain(self.pool.pending_transactions()) {
2560 if U256::from(pending_tx.pending_transaction.nonce()) == nonce
2561 && *pending_tx.pending_transaction.sender() == sender
2562 {
2563 let tx = transaction_build(
2564 Some(*pending_tx.pending_transaction.hash()),
2565 pending_tx.pending_transaction.transaction.clone(),
2566 None,
2567 None,
2568 Some(self.backend.base_fee()),
2569 );
2570
2571 let WithOtherFields { inner: mut tx, other } = tx.0;
2572 let from = *pending_tx.pending_transaction.sender();
2575 tx.inner = Recovered::new_unchecked(tx.inner.into_inner(), from);
2576
2577 return Ok(Some(AnyRpcTransaction(WithOtherFields { inner: tx, other })));
2578 }
2579 }
2580
2581 let highest_nonce = self.transaction_count(sender, None).await?.saturating_to::<u64>();
2582 let target_nonce = nonce.saturating_to::<u64>();
2583
2584 if target_nonce >= highest_nonce {
2586 return Ok(None);
2587 }
2588
2589 let latest_block = self.backend.best_number();
2591 if latest_block == 0 {
2592 return Ok(None);
2593 }
2594
2595 let mut low = 1u64;
2597 let mut high = latest_block;
2598
2599 while low <= high {
2600 let mid = low + (high - low) / 2;
2601 let mid_nonce =
2602 self.transaction_count(sender, Some(mid.into())).await?.saturating_to::<u64>();
2603
2604 if mid_nonce > target_nonce {
2605 high = mid - 1;
2606 } else {
2607 low = mid + 1;
2608 }
2609 }
2610
2611 let target_block = low;
2613 if target_block <= latest_block
2614 && let Some(txs) =
2615 self.backend.mined_transactions_by_block_number(target_block.into()).await
2616 {
2617 for tx in txs {
2618 if tx.from() == sender && tx.nonce() == target_nonce {
2619 return Ok(Some(tx));
2620 }
2621 }
2622 }
2623
2624 Ok(None)
2625 }
2626
2627 pub async fn transaction_receipt(&self, hash: B256) -> Result<Option<FoundryTxReceipt>> {
2631 node_info!("eth_getTransactionReceipt");
2632 self.backend.transaction_receipt(hash).await
2633 }
2634
2635 pub async fn block_receipts(&self, number: BlockId) -> Result<Option<Vec<FoundryTxReceipt>>> {
2639 node_info!("eth_getBlockReceipts");
2640 self.backend.block_receipts(number).await
2641 }
2642
2643 pub async fn logs(&self, filter: Filter) -> Result<Vec<Log>> {
2647 node_info!("eth_getLogs");
2648 self.backend.logs(filter).await
2649 }
2650
2651 pub async fn new_filter(&self, filter: Filter) -> Result<String> {
2655 node_info!("eth_newFilter");
2656 let historic = if filter.block_option.get_from_block().is_some() {
2659 self.backend.logs(filter.clone()).await?
2660 } else {
2661 vec![]
2662 };
2663 let filter = EthFilter::Logs(Box::new(LogsFilter {
2664 blocks: self.new_block_notifications(),
2665 storage: self.storage_info(),
2666 filter: FilteredParams::new(Some(filter)),
2667 historic: Some(historic),
2668 }));
2669 Ok(self.filters.add_filter(filter).await)
2670 }
2671
2672 pub async fn new_block_filter(&self) -> Result<String> {
2676 node_info!("eth_newBlockFilter");
2677 let filter = EthFilter::Blocks(self.new_block_notifications());
2678 Ok(self.filters.add_filter(filter).await)
2679 }
2680
2681 pub async fn new_pending_transaction_filter(&self) -> Result<String> {
2685 node_info!("eth_newPendingTransactionFilter");
2686 let filter = EthFilter::PendingTransactions(self.new_ready_transactions());
2687 Ok(self.filters.add_filter(filter).await)
2688 }
2689
2690 pub async fn get_filter_changes(&self, id: &str) -> ResponseResult {
2694 node_info!("eth_getFilterChanges");
2695 self.filters.get_filter_changes(id).await
2696 }
2697
2698 pub async fn get_filter_logs(&self, id: &str) -> Result<Vec<Log>> {
2702 node_info!("eth_getFilterLogs");
2703 if let Some(filter) = self.filters.get_log_filter(id).await {
2704 self.backend.logs(filter).await
2705 } else {
2706 Err(BlockchainError::FilterNotFound)
2707 }
2708 }
2709
2710 pub async fn uninstall_filter(&self, id: &str) -> Result<bool> {
2712 node_info!("eth_uninstallFilter");
2713 Ok(self.filters.uninstall_filter(id).await.is_some())
2714 }
2715
2716 pub async fn raw_transaction(&self, hash: B256) -> Result<Option<Bytes>> {
2720 node_info!("debug_getRawTransaction");
2721 self.inner_raw_transaction(hash).await
2722 }
2723
2724 pub async fn raw_transaction_by_block_hash_and_index(
2728 &self,
2729 block_hash: B256,
2730 index: Index,
2731 ) -> Result<Option<Bytes>> {
2732 node_info!("eth_getRawTransactionByBlockHashAndIndex");
2733 match self.backend.transaction_by_block_hash_and_index(block_hash, index).await? {
2734 Some(tx) => self.inner_raw_transaction(tx.tx_hash()).await,
2735 None => Ok(None),
2736 }
2737 }
2738
2739 pub async fn raw_transaction_by_block_number_and_index(
2743 &self,
2744 block_number: BlockNumber,
2745 index: Index,
2746 ) -> Result<Option<Bytes>> {
2747 node_info!("eth_getRawTransactionByBlockNumberAndIndex");
2748 match self.backend.transaction_by_block_number_and_index(block_number, index).await? {
2749 Some(tx) => self.inner_raw_transaction(tx.tx_hash()).await,
2750 None => Ok(None),
2751 }
2752 }
2753
2754 pub async fn debug_trace_transaction(
2758 &self,
2759 tx_hash: B256,
2760 opts: GethDebugTracingOptions,
2761 ) -> Result<GethTrace> {
2762 node_info!("debug_traceTransaction");
2763 self.backend.debug_trace_transaction(tx_hash, opts).await
2764 }
2765
2766 pub async fn debug_trace_block_by_hash(
2770 &self,
2771 block_hash: B256,
2772 opts: GethDebugTracingOptions,
2773 ) -> Result<Vec<TraceResult>> {
2774 node_info!("debug_traceBlockByHash");
2775 self.backend.debug_trace_block_by_hash(block_hash, opts).await
2776 }
2777
2778 pub async fn debug_trace_block_by_number(
2782 &self,
2783 block_number: BlockNumber,
2784 opts: GethDebugTracingOptions,
2785 ) -> Result<Vec<TraceResult>> {
2786 node_info!("debug_traceBlockByNumber");
2787 self.backend.debug_trace_block_by_number(block_number, opts).await
2788 }
2789
2790 pub async fn debug_trace_call(
2794 &self,
2795 request: WithOtherFields<TransactionRequest>,
2796 block_number: Option<BlockId>,
2797 opts: GethDebugTracingCallOptions,
2798 ) -> Result<GethTrace> {
2799 node_info!("debug_traceCall");
2800 let block_request = self.block_request(block_number).await?;
2801 let fees = FeeDetails::new(
2802 request.gas_price,
2803 request.max_fee_per_gas,
2804 request.max_priority_fee_per_gas,
2805 request.max_fee_per_blob_gas,
2806 )?
2807 .or_zero_fees();
2808
2809 let result: std::result::Result<GethTrace, BlockchainError> =
2810 self.backend.call_with_tracing(request, fees, Some(block_request), opts).await;
2811 result
2812 }
2813}
2814
2815impl EthApi<FoundryNetwork> {
2818 pub async fn anvil_mine(&self, num_blocks: Option<U256>, interval: Option<U256>) -> Result<()> {
2822 node_info!("anvil_mine");
2823 let interval = interval.map(|i| i.saturating_to::<u64>());
2824 let blocks = num_blocks.unwrap_or(U256::from(1));
2825 if blocks.is_zero() {
2826 return Ok(());
2827 }
2828
2829 self.on_blocking_task(|this| async move {
2830 for _ in 0..blocks.saturating_to::<u64>() {
2832 if let Some(interval) = interval {
2834 this.backend.time().increase_time(interval);
2835 }
2836 this.mine_one().await;
2837 }
2838 Ok(())
2839 })
2840 .await?;
2841
2842 Ok(())
2843 }
2844
2845 async fn find_erc20_storage_slot(
2862 &self,
2863 token_address: Address,
2864 calldata: Bytes,
2865 expected_value: U256,
2866 ) -> Result<B256> {
2867 let tx = TransactionRequest::default().with_to(token_address).with_input(calldata.clone());
2868
2869 let access_list_result =
2871 self.create_access_list(WithOtherFields::new(tx.clone()), None).await?;
2872 let access_list = access_list_result.access_list;
2873
2874 for item in access_list.0 {
2877 if item.address != token_address {
2878 continue;
2879 };
2880 for slot in &item.storage_keys {
2881 let account_override = AccountOverride::default().with_state_diff(std::iter::once(
2882 (*slot, B256::from(expected_value.to_be_bytes())),
2883 ));
2884
2885 let state_override = StateOverridesBuilder::default()
2886 .append(token_address, account_override)
2887 .build();
2888
2889 let evm_override = EvmOverrides::state(Some(state_override));
2890
2891 let Ok(result) =
2892 self.call(WithOtherFields::new(tx.clone()), None, evm_override).await
2893 else {
2894 continue;
2896 };
2897
2898 let Ok(result_value) = U256::abi_decode(&result) else {
2899 continue;
2901 };
2902
2903 if result_value == expected_value {
2904 return Ok(*slot);
2905 }
2906 }
2907 }
2908
2909 Err(BlockchainError::Message("Unable to find storage slot".to_string()))
2910 }
2911
2912 pub async fn anvil_deal_erc20(
2916 &self,
2917 address: Address,
2918 token_address: Address,
2919 balance: U256,
2920 ) -> Result<()> {
2921 node_info!("anvil_dealERC20");
2922
2923 sol! {
2924 #[sol(rpc)]
2925 contract IERC20 {
2926 function balanceOf(address target) external view returns (uint256);
2927 }
2928 }
2929
2930 let calldata = IERC20::balanceOfCall { target: address }.abi_encode().into();
2931
2932 let slot =
2934 self.find_erc20_storage_slot(token_address, calldata, balance).await.map_err(|_| {
2935 BlockchainError::Message("Unable to set ERC20 balance, no slot found".to_string())
2936 })?;
2937
2938 self.anvil_set_storage_at(
2940 token_address,
2941 U256::from_be_bytes(slot.0),
2942 B256::from(balance.to_be_bytes()),
2943 )
2944 .await?;
2945
2946 Ok(())
2947 }
2948
2949 pub async fn anvil_set_erc20_allowance(
2953 &self,
2954 owner: Address,
2955 spender: Address,
2956 token_address: Address,
2957 amount: U256,
2958 ) -> Result<()> {
2959 node_info!("anvil_setERC20Allowance");
2960
2961 sol! {
2962 #[sol(rpc)]
2963 contract IERC20 {
2964 function allowance(address owner, address spender) external view returns (uint256);
2965 }
2966 }
2967
2968 let calldata = IERC20::allowanceCall { owner, spender }.abi_encode().into();
2969
2970 let slot =
2972 self.find_erc20_storage_slot(token_address, calldata, amount).await.map_err(|_| {
2973 BlockchainError::Message("Unable to set ERC20 allowance, no slot found".to_string())
2974 })?;
2975
2976 self.anvil_set_storage_at(
2978 token_address,
2979 U256::from_be_bytes(slot.0),
2980 B256::from(amount.to_be_bytes()),
2981 )
2982 .await?;
2983
2984 Ok(())
2985 }
2986
2987 pub async fn anvil_reorg(&self, options: ReorgOptions) -> Result<()> {
3001 node_info!("anvil_reorg");
3002 let depth = options.depth;
3003 let tx_block_pairs = options.tx_block_pairs;
3004
3005 let current_height = self.backend.best_number();
3007 let common_height = current_height.checked_sub(depth).ok_or(BlockchainError::RpcError(
3008 RpcError::invalid_params(format!(
3009 "Reorg depth must not exceed current chain height: current height {current_height}, depth {depth}"
3010 )),
3011 ))?;
3012
3013 let common_block =
3015 self.backend.get_block(common_height).ok_or(BlockchainError::BlockNotFound)?;
3016
3017 let block_pool_txs = if tx_block_pairs.is_empty() {
3020 HashMap::default()
3021 } else {
3022 let mut pairs = tx_block_pairs;
3023
3024 if let Some((_, num)) = pairs.iter().find(|(_, num)| *num >= depth) {
3026 return Err(BlockchainError::RpcError(RpcError::invalid_params(format!(
3027 "Block number for reorg tx will exceed the reorged chain height. Block number {num} must not exceed (depth-1) {}",
3028 depth - 1
3029 ))));
3030 }
3031
3032 pairs.sort_by_key(|a| a.1);
3034
3035 let mut nonces: HashMap<Address, u64> = HashMap::default();
3038
3039 let mut txs: HashMap<u64, Vec<Arc<PoolTransaction<FoundryTxEnvelope>>>> =
3040 HashMap::default();
3041 for pair in pairs {
3042 let (tx_data, block_index) = pair;
3043
3044 let pending = match tx_data {
3045 TransactionData::Raw(bytes) => {
3046 let mut data = bytes.as_ref();
3047 let decoded = FoundryTxEnvelope::decode_2718(&mut data)
3048 .map_err(|_| BlockchainError::FailedToDecodeSignedTransaction)?;
3049 PendingTransaction::new(decoded)?
3050 }
3051
3052 TransactionData::JSON(request) => {
3053 let from = request.from.map(Ok).unwrap_or_else(|| {
3054 self.accounts()?
3055 .first()
3056 .copied()
3057 .ok_or(BlockchainError::NoSignerAvailable)
3058 })?;
3059
3060 let curr_nonce = nonces.entry(from).or_insert(
3062 self.get_transaction_count(
3063 from,
3064 Some(common_block.header.number().into()),
3065 )
3066 .await?,
3067 );
3068
3069 let typed_tx = self.build_tx_request(request.into(), *curr_nonce).await?;
3071
3072 *curr_nonce += 1;
3074
3075 if self.is_impersonated(from) {
3077 let transaction = sign::build_impersonated(typed_tx);
3078 self.ensure_typed_transaction_supported(&transaction)?;
3079 PendingTransaction::with_impersonated(transaction, from)
3080 } else {
3081 let transaction = self.sign_request(&from, typed_tx)?;
3082 self.ensure_typed_transaction_supported(&transaction)?;
3083 PendingTransaction::new(transaction)?
3084 }
3085 }
3086 };
3087
3088 let pooled = PoolTransaction::new(pending);
3089 txs.entry(block_index).or_default().push(Arc::new(pooled));
3090 }
3091
3092 txs
3093 };
3094
3095 self.backend.reorg(depth, block_pool_txs, common_block).await?;
3096 Ok(())
3097 }
3098
3099 pub async fn evm_mine(&self, opts: Option<MineOptions>) -> Result<String> {
3106 node_info!("evm_mine");
3107
3108 self.do_evm_mine(opts).await?;
3109
3110 Ok("0x0".to_string())
3111 }
3112
3113 pub async fn evm_mine_detailed(&self, opts: Option<MineOptions>) -> Result<Vec<AnyRpcBlock>> {
3123 node_info!("evm_mine_detailed");
3124
3125 let mined_blocks = self.do_evm_mine(opts).await?;
3126
3127 let mut blocks = Vec::with_capacity(mined_blocks as usize);
3128
3129 let latest = self.backend.best_number();
3130 for offset in (0..mined_blocks).rev() {
3131 let block_num = latest - offset;
3132 if let Some(mut block) =
3133 self.backend.block_by_number_full(BlockNumber::Number(block_num)).await?
3134 {
3135 let block_txs = match block.transactions_mut() {
3136 BlockTransactions::Full(txs) => txs,
3137 BlockTransactions::Hashes(_) | BlockTransactions::Uncle => unreachable!(),
3138 };
3139 for tx in block_txs.iter_mut() {
3140 if let Some(receipt) = self.backend.mined_transaction_receipt(tx.tx_hash())
3141 && let Some(output) = receipt.out
3142 {
3143 if !receipt.inner.as_ref().status()
3145 && let Some(reason) = RevertDecoder::new().maybe_decode(&output, None)
3146 {
3147 tx.other.insert(
3148 "revertReason".to_string(),
3149 serde_json::to_value(reason).expect("Infallible"),
3150 );
3151 }
3152 tx.other.insert(
3153 "output".to_string(),
3154 serde_json::to_value(output).expect("Infallible"),
3155 );
3156 }
3157 }
3158 block.transactions = BlockTransactions::Full(block_txs.clone());
3159 blocks.push(block);
3160 }
3161 }
3162
3163 Ok(blocks)
3164 }
3165
3166 pub async fn eth_send_unsigned_transaction(
3170 &self,
3171 request: WithOtherFields<TransactionRequest>,
3172 ) -> Result<TxHash> {
3173 node_info!("eth_sendUnsignedTransaction");
3174 let from = request.from.ok_or(BlockchainError::NoSignerAvailable)?;
3176
3177 let (nonce, on_chain_nonce) = self.request_nonce(&request, from).await?;
3178
3179 let typed_tx = self.build_tx_request(request, nonce).await?;
3180
3181 let transaction = sign::build_impersonated(typed_tx);
3182
3183 self.ensure_typed_transaction_supported(&transaction)?;
3184
3185 let pending_transaction = PendingTransaction::with_impersonated(transaction, from);
3186
3187 self.backend.validate_pool_transaction(&pending_transaction).await?;
3189
3190 let (requires, provides) = if let Some((requires, provides)) =
3191 tempo_parallel_nonce_markers(&pending_transaction)
3192 {
3193 (requires, provides)
3194 } else {
3195 (required_marker(nonce, on_chain_nonce, from), vec![to_marker(nonce, from)])
3196 };
3197
3198 self.add_pending_transaction(pending_transaction, requires, provides)
3199 }
3200
3201 pub async fn txpool_inspect(&self) -> Result<TxpoolInspect> {
3208 node_info!("txpool_inspect");
3209 let mut inspect = TxpoolInspect::default();
3210
3211 fn convert(tx: Arc<PoolTransaction<FoundryTxEnvelope>>) -> TxpoolInspectSummary {
3212 let tx = &tx.pending_transaction.transaction;
3213 let to = tx.to();
3214 let gas_price = tx.max_fee_per_gas();
3215 let value = tx.value();
3216 let gas = tx.gas_limit();
3217 TxpoolInspectSummary { to, value, gas, gas_price }
3218 }
3219
3220 for pending in self.pool.ready_transactions() {
3227 let entry = inspect.pending.entry(*pending.pending_transaction.sender()).or_default();
3228 let key = pending.pending_transaction.nonce().to_string();
3229 entry.insert(key, convert(pending));
3230 }
3231 for queued in self.pool.pending_transactions() {
3232 let entry = inspect.queued.entry(*queued.pending_transaction.sender()).or_default();
3233 let key = queued.pending_transaction.nonce().to_string();
3234 entry.insert(key, convert(queued));
3235 }
3236 Ok(inspect)
3237 }
3238
3239 pub async fn txpool_content(&self) -> Result<TxpoolContent<AnyRpcTransaction>> {
3246 node_info!("txpool_content");
3247 let mut content = TxpoolContent::<AnyRpcTransaction>::default();
3248 fn convert(tx: Arc<PoolTransaction<FoundryTxEnvelope>>) -> Result<AnyRpcTransaction> {
3249 let from = *tx.pending_transaction.sender();
3250 let tx = transaction_build(
3251 Some(tx.hash()),
3252 tx.pending_transaction.transaction.clone(),
3253 None,
3254 None,
3255 None,
3256 );
3257
3258 let WithOtherFields { inner: mut tx, other } = tx.0;
3259
3260 tx.inner = Recovered::new_unchecked(tx.inner.into_inner(), from);
3263
3264 let tx = AnyRpcTransaction(WithOtherFields { inner: tx, other });
3265
3266 Ok(tx)
3267 }
3268
3269 for pending in self.pool.ready_transactions() {
3270 let entry = content.pending.entry(*pending.pending_transaction.sender()).or_default();
3271 let key = pending.pending_transaction.nonce().to_string();
3272 entry.insert(key, convert(pending)?);
3273 }
3274 for queued in self.pool.pending_transactions() {
3275 let entry = content.queued.entry(*queued.pending_transaction.sender()).or_default();
3276 let key = queued.pending_transaction.nonce().to_string();
3277 entry.insert(key, convert(queued)?);
3278 }
3279
3280 Ok(content)
3281 }
3282}
3283
3284impl EthApi<FoundryNetwork> {
3285 async fn do_evm_mine(&self, opts: Option<MineOptions>) -> Result<u64> {
3287 let mut blocks_to_mine = 1u64;
3288
3289 if let Some(opts) = opts {
3290 let timestamp = match opts {
3291 MineOptions::Timestamp(timestamp) => timestamp,
3292 MineOptions::Options { timestamp, blocks } => {
3293 if let Some(blocks) = blocks {
3294 blocks_to_mine = blocks;
3295 }
3296 timestamp
3297 }
3298 };
3299 if let Some(timestamp) = timestamp {
3300 self.evm_set_next_block_timestamp(timestamp)?;
3302 }
3303 }
3304
3305 self.on_blocking_task(|this| async move {
3308 for _ in 0..blocks_to_mine {
3310 this.mine_one().await;
3311 }
3312 Ok(())
3313 })
3314 .await?;
3315
3316 Ok(blocks_to_mine)
3317 }
3318
3319 async fn do_estimate_gas(
3320 &self,
3321 request: WithOtherFields<TransactionRequest>,
3322 block_number: Option<BlockId>,
3323 overrides: EvmOverrides,
3324 ) -> Result<u128> {
3325 let block_request = self.block_request(block_number).await?;
3326 if let BlockRequest::Number(number) = block_request
3328 && let Some(fork) = self.get_fork()
3329 && fork.predates_fork(number)
3330 {
3331 if overrides.has_state() || overrides.has_block() {
3332 return Err(BlockchainError::EvmOverrideError(
3333 "not available on past forked blocks".to_string(),
3334 ));
3335 }
3336 return Ok(fork.estimate_gas(&request, Some(number.into())).await?);
3337 }
3338
3339 self.on_blocking_task(|this| async move {
3342 this.backend
3343 .with_database_at(Some(block_request), |state, mut block| {
3344 let mut cache_db = CacheDB::new(state);
3345 if let Some(state_overrides) = overrides.state {
3346 apply_state_overrides(
3347 state_overrides.into_iter().collect(),
3348 &mut cache_db,
3349 )?;
3350 }
3351 if let Some(block_overrides) = overrides.block {
3352 cache_db.apply_block_overrides(*block_overrides, &mut block);
3353 }
3354 this.do_estimate_gas_with_state(request, &cache_db, block)
3355 })
3356 .await?
3357 })
3358 .await
3359 }
3360
3361 fn transaction_priority(&self, tx: &FoundryTxEnvelope) -> TransactionPriority {
3363 self.transaction_order.read().priority(tx)
3364 }
3365
3366 pub fn full_pending_transactions(&self) -> UnboundedReceiver<AnyRpcTransaction> {
3368 let (tx, rx) = unbounded_channel();
3369 let mut hashes = self.new_ready_transactions();
3370
3371 let this = self.clone();
3372
3373 tokio::spawn(async move {
3374 while let Some(hash) = hashes.next().await {
3375 if let Ok(Some(txn)) = this.transaction_by_hash(hash).await
3376 && tx.send(txn).is_err()
3377 {
3378 break;
3379 }
3380 }
3381 });
3382
3383 rx
3384 }
3385
3386 pub async fn mine_one(&self) {
3388 let transactions = self.pool.ready_transactions().collect::<Vec<_>>();
3389 let outcome = self.backend.mine_block(transactions).await;
3390
3391 trace!(target: "node", blocknumber = ?outcome.block_number, "mined block");
3392 self.pool.on_mined_block(outcome);
3393 }
3394
3395 async fn pending_block(&self) -> AnyRpcBlock {
3397 let transactions = self.pool.ready_transactions().collect::<Vec<_>>();
3398 let info = self.backend.pending_block(transactions).await;
3399 self.backend.convert_block(info.block)
3400 }
3401
3402 async fn pending_block_full(&self) -> Option<AnyRpcBlock> {
3404 let transactions = self.pool.ready_transactions().collect::<Vec<_>>();
3405 let BlockInfo { block, transactions, receipts: _ } =
3406 self.backend.pending_block(transactions).await;
3407
3408 let mut partial_block = self.backend.convert_block(block.clone());
3409
3410 let mut block_transactions = Vec::with_capacity(block.body.transactions.len());
3411 let base_fee = self.backend.base_fee();
3412
3413 for info in transactions {
3414 let tx = block.body.transactions.get(info.transaction_index as usize)?.clone();
3415
3416 let tx = transaction_build(
3417 Some(info.transaction_hash),
3418 tx,
3419 Some(&block),
3420 Some(info),
3421 Some(base_fee),
3422 );
3423 block_transactions.push(tx);
3424 }
3425
3426 partial_block.transactions = BlockTransactions::from(block_transactions);
3427
3428 Some(partial_block)
3429 }
3430
3431 async fn build_tx_request(
3434 &self,
3435 request: WithOtherFields<TransactionRequest>,
3436 nonce: u64,
3437 ) -> Result<FoundryTypedTx> {
3438 let mut request = Into::<FoundryTransactionRequest>::into(request);
3439 let from = request.from().or(self.accounts()?.first().copied());
3440
3441 request.chain_id().is_none().then(|| request.set_chain_id(self.chain_id()));
3443 request.nonce().is_none().then(|| request.set_nonce(nonce));
3444 request.kind().is_none().then(|| request.set_kind(TxKind::default()));
3445 if request.gas_limit().is_none() {
3446 request.set_gas_limit(
3447 self.do_estimate_gas(
3448 request.as_ref().clone().into(),
3449 None,
3450 EvmOverrides::default(),
3451 )
3452 .await
3453 .map(|v| v as u64)
3454 .unwrap_or(self.backend.gas_limit()),
3455 );
3456 }
3457
3458 if let Err((tx_type, _)) = request.missing_keys() {
3460 if matches!(tx_type, FoundryTxType::Legacy | FoundryTxType::Eip2930) {
3461 request.gas_price().is_none().then(|| request.set_gas_price(self.gas_price()));
3462 }
3463 if tx_type == FoundryTxType::Eip2930 {
3464 request
3465 .access_list()
3466 .is_none()
3467 .then(|| request.set_access_list(Default::default()));
3468 }
3469 if matches!(
3470 tx_type,
3471 FoundryTxType::Eip1559
3472 | FoundryTxType::Eip4844
3473 | FoundryTxType::Eip7702
3474 | FoundryTxType::Tempo
3475 ) {
3476 request
3477 .max_fee_per_gas()
3478 .is_none()
3479 .then(|| request.set_max_fee_per_gas(self.gas_price()));
3480 request
3481 .max_priority_fee_per_gas()
3482 .is_none()
3483 .then(|| request.set_max_priority_fee_per_gas(MIN_SUGGESTED_PRIORITY_FEE));
3484 }
3485 if tx_type == FoundryTxType::Eip4844 {
3486 request.as_ref().max_fee_per_blob_gas().is_none().then(|| {
3487 request.as_mut().set_max_fee_per_blob_gas(
3488 self.backend.fees().get_next_block_blob_base_fee_per_gas(),
3489 )
3490 });
3491 }
3492 }
3493
3494 match request
3495 .build_unsigned()
3496 .map_err(|e| BlockchainError::InvalidTransactionRequest(e.to_string()))?
3497 {
3498 FoundryTypedTx::Eip4844(TxEip4844Variant::TxEip4844(_))
3499 if !self.backend.skip_blob_validation(from) =>
3500 {
3501 Err(BlockchainError::FailedToDecodeTransaction)
3503 }
3504 res => Ok(res),
3505 }
3506 }
3507
3508 async fn get_transaction_count(
3510 &self,
3511 address: Address,
3512 block_number: Option<BlockId>,
3513 ) -> Result<u64> {
3514 let block_request = self.block_request(block_number).await?;
3515
3516 if let BlockRequest::Number(number) = block_request
3517 && let Some(fork) = self.get_fork()
3518 && fork.predates_fork(number)
3519 {
3520 return Ok(fork.get_nonce(address, number).await?);
3521 }
3522
3523 self.backend.get_nonce(address, block_request).await
3524 }
3525
3526 async fn request_nonce(
3534 &self,
3535 request: &TransactionRequest,
3536 from: Address,
3537 ) -> Result<(u64, u64)> {
3538 let highest_nonce =
3539 self.get_transaction_count(from, Some(BlockId::Number(BlockNumber::Pending))).await?;
3540 let nonce = request.nonce.unwrap_or(highest_nonce);
3541
3542 Ok((nonce, highest_nonce))
3543 }
3544
3545 fn add_pending_transaction(
3547 &self,
3548 pending_transaction: PendingTransaction<FoundryTxEnvelope>,
3549 requires: Vec<TxMarker>,
3550 provides: Vec<TxMarker>,
3551 ) -> Result<TxHash> {
3552 debug_assert!(requires != provides);
3553 let from = *pending_transaction.sender();
3554 let priority = self.transaction_priority(&pending_transaction.transaction);
3555 let pool_transaction =
3556 PoolTransaction { requires, provides, pending_transaction, priority };
3557 let tx = self.pool.add_transaction(pool_transaction)?;
3558 trace!(target: "node", "Added transaction: [{:?}] sender={:?}", tx.hash(), from);
3559 Ok(*tx.hash())
3560 }
3561
3562 fn ensure_typed_transaction_supported(&self, tx: &FoundryTxEnvelope) -> Result<()> {
3564 match &tx {
3565 FoundryTxEnvelope::Eip2930(_) => self.backend.ensure_eip2930_active(),
3566 FoundryTxEnvelope::Eip1559(_) => self.backend.ensure_eip1559_active(),
3567 FoundryTxEnvelope::Eip4844(_) => self.backend.ensure_eip4844_active(),
3568 FoundryTxEnvelope::Eip7702(_) => self.backend.ensure_eip7702_active(),
3569 #[cfg(feature = "optimism")]
3570 FoundryTxEnvelope::Deposit(_) => self.backend.ensure_op_deposits_active(),
3571 #[cfg(feature = "optimism")]
3572 FoundryTxEnvelope::PostExec(_) => Err(BlockchainError::InvalidTransactionRequest(
3573 "not implemented for post-exec tx".to_string(),
3574 )),
3575 FoundryTxEnvelope::Legacy(_) => Ok(()),
3576 FoundryTxEnvelope::Tempo(_) => self.backend.ensure_tempo_active(),
3577 }
3578 }
3579
3580 pub async fn anvil_set_fee_token(&self, user: Address, token: Address) -> Result<()> {
3586 node_info!("anvil_setFeeToken");
3587 if !self.backend.is_tempo() {
3588 return Err(BlockchainError::RpcUnimplemented);
3589 }
3590 self.backend.set_fee_token(user, token).await?;
3591 Ok(())
3592 }
3593
3594 pub async fn anvil_set_validator_fee_token(
3600 &self,
3601 validator: Address,
3602 token: Address,
3603 ) -> Result<()> {
3604 node_info!("anvil_setValidatorFeeToken");
3605 if !self.backend.is_tempo() {
3606 return Err(BlockchainError::RpcUnimplemented);
3607 }
3608 self.backend.set_validator_fee_token(validator, token).await?;
3609 Ok(())
3610 }
3611
3612 pub async fn anvil_set_fee_amm_liquidity(
3618 &self,
3619 user_token: Address,
3620 validator_token: Address,
3621 amount: U256,
3622 ) -> Result<()> {
3623 node_info!("anvil_setFeeAmmLiquidity");
3624 if !self.backend.is_tempo() {
3625 return Err(BlockchainError::RpcUnimplemented);
3626 }
3627 self.backend.set_fee_amm_liquidity(user_token, validator_token, amount).await?;
3628 Ok(())
3629 }
3630}
3631
3632fn required_marker(provided_nonce: u64, on_chain_nonce: u64, from: Address) -> Vec<TxMarker> {
3633 if provided_nonce == on_chain_nonce {
3634 return Vec::new();
3635 }
3636 let prev_nonce = provided_nonce.saturating_sub(1);
3637 if on_chain_nonce <= prev_nonce { vec![to_marker(prev_nonce, from)] } else { Vec::new() }
3638}
3639
3640fn tempo_parallel_nonce_markers(
3641 pending_transaction: &PendingTransaction<FoundryTxEnvelope>,
3642) -> Option<(Vec<TxMarker>, Vec<TxMarker>)> {
3643 pending_transaction
3646 .transaction
3647 .as_ref()
3648 .has_nonzero_tempo_nonce_key()
3649 .then(|| (vec![], vec![pending_transaction.hash().to_vec()]))
3650}
3651
3652fn convert_transact_out(out: &Option<Output>) -> Bytes {
3653 match out {
3654 None => Default::default(),
3655 Some(Output::Call(out)) => out.to_vec().into(),
3656 Some(Output::Create(out, _)) => out.to_vec().into(),
3657 }
3658}
3659
3660fn ensure_return_ok(exit: InstructionResult, out: &Option<Output>) -> Result<Bytes> {
3662 let out = convert_transact_out(out);
3663 match exit {
3664 return_ok!() => Ok(out),
3665 return_revert!() => Err(InvalidTransactionError::Revert(Some(out)).into()),
3666 reason => Err(BlockchainError::EvmError(reason)),
3667 }
3668}
3669
3670fn determine_base_gas_by_kind(request: &WithOtherFields<TransactionRequest>) -> u128 {
3672 match request.kind() {
3673 Some(TxKind::Call(_)) => {
3674 MIN_TRANSACTION_GAS
3675 + request.inner().authorization_list.as_ref().map_or(0, |auths_list| {
3676 auths_list.len() as u128 * PER_EMPTY_ACCOUNT_COST as u128
3677 })
3678 }
3679 Some(TxKind::Create) => MIN_CREATE_GAS,
3680 None => MIN_CREATE_GAS,
3682 }
3683}
3684
3685enum GasEstimationCallResult {
3687 Success(u128),
3688 OutOfGas,
3689 Revert(Option<Bytes>),
3690 EvmError(InstructionResult),
3691}
3692
3693impl TryFrom<Result<(InstructionResult, Option<Output>, u128, State)>> for GasEstimationCallResult {
3697 type Error = BlockchainError;
3698
3699 fn try_from(res: Result<(InstructionResult, Option<Output>, u128, State)>) -> Result<Self> {
3700 match res {
3701 Err(BlockchainError::InvalidTransaction(InvalidTransactionError::GasTooHigh(_))) => {
3703 Ok(Self::OutOfGas)
3704 }
3705 Err(BlockchainError::Message(ref msg))
3707 if msg.contains("insufficient gas for intrinsic cost") =>
3708 {
3709 Ok(Self::OutOfGas)
3710 }
3711 Err(err) => Err(err),
3712 Ok((exit, output, gas, _)) => match exit {
3713 return_ok!() => Ok(Self::Success(gas)),
3714
3715 InstructionResult::Revert => Ok(Self::Revert(output.map(|o| o.into_data()))),
3717 InstructionResult::CallTooDeep
3718 | InstructionResult::OutOfFunds
3719 | InstructionResult::CreateInitCodeStartingEF00
3720 | InstructionResult::InvalidEOFInitCode
3721 | InstructionResult::InvalidExtDelegateCallTarget => Ok(Self::EvmError(exit)),
3722
3723 InstructionResult::OutOfGas
3725 | InstructionResult::MemoryOOG
3726 | InstructionResult::MemoryLimitOOG
3727 | InstructionResult::PrecompileOOG
3728 | InstructionResult::InvalidOperandOOG
3729 | InstructionResult::ReentrancySentryOOG => Ok(Self::OutOfGas),
3730
3731 InstructionResult::OpcodeNotFound
3733 | InstructionResult::CallNotAllowedInsideStatic
3734 | InstructionResult::StateChangeDuringStaticCall
3735 | InstructionResult::InvalidFEOpcode
3736 | InstructionResult::InvalidJump
3737 | InstructionResult::NotActivated
3738 | InstructionResult::StackUnderflow
3739 | InstructionResult::StackOverflow
3740 | InstructionResult::OutOfOffset
3741 | InstructionResult::CreateCollision
3742 | InstructionResult::OverflowPayment
3743 | InstructionResult::PrecompileError
3744 | InstructionResult::NonceOverflow
3745 | InstructionResult::CreateContractSizeLimit
3746 | InstructionResult::CreateContractStartingWithEF
3747 | InstructionResult::CreateInitCodeSizeLimit
3748 | InstructionResult::InvalidImmediateEncoding
3749 | InstructionResult::FatalExternalError => Ok(Self::EvmError(exit)),
3750 },
3751 }
3752 }
3753}