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::ChainNotifications,
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, AnyRpcHeader, AnyRpcTransaction, BlockResponse, Network,
43 NetworkTransactionBuilder, ReceiptResponse, TransactionBuilder, TransactionBuilder4844,
44 TransactionResponse, 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 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 erc4337::TransactionConditional,
57 pubsub::TransactionReceiptsParams,
58 request::TransactionRequest,
59 simulate::{MAX_SIMULATE_BLOCKS, SimulatePayload, SimulatedBlock},
60 state::{AccountOverride, EvmOverrides, StateOverride, StateOverridesBuilder},
61 trace::{
62 filter::TraceFilter,
63 geth::{GethDebugTracingCallOptions, GethDebugTracingOptions, GethTrace, TraceResult},
64 opcode::{BlockOpcodeGas, TransactionOpcodeGas},
65 parity::{
66 LocalizedTransactionTrace, TraceResults, TraceResultsWithTransactionHash, TraceType,
67 },
68 },
69 txpool::{TxpoolContent, TxpoolContentFrom, TxpoolInspect, TxpoolInspectSummary, TxpoolStatus},
70};
71use alloy_rpc_types_eth::{AccountInfo, Bundle, EthCallResponse, FillTransaction, StateContext};
72use alloy_rpc_types_mev::{EthCallBundle, EthCallBundleResponse};
73use alloy_serde::WithOtherFields;
74use alloy_sol_types::{SolCall, SolValue, sol};
75use alloy_transport::TransportErrorKind;
76use anvil_core::{
77 eth::{
78 EthRequest,
79 block::{BlockInfo, canonical_block, canonical_block_transaction},
80 transaction::{MaybeImpersonatedTransaction, PendingTransaction},
81 },
82 types::{ReorgOptions, TransactionData},
83};
84use anvil_rpc::{
85 error::{ErrorCode, RpcError},
86 response::ResponseResult,
87};
88use foundry_common::{
89 provider::ProviderBuilder,
90 tempo::{PaymentLaneClassification, PaymentLaneReason, classify_payment_lane},
91 version::{COMMIT_SHA, SEMVER_VERSION},
92};
93use foundry_evm::decode::RevertDecoder;
94use foundry_primitives::{
95 FoundryNetwork, FoundryReceiptEnvelope, FoundryTransactionRequest, FoundryTxEnvelope,
96 FoundryTxReceipt, FoundryTxType, FoundryTypedTx,
97};
98use futures::{
99 StreamExt, TryFutureExt,
100 channel::{mpsc::Receiver, oneshot},
101};
102use parking_lot::RwLock;
103use revm::{
104 context::{BlockEnv, Cfg},
105 context_interface::{
106 block::BlobExcessGasAndPrice,
107 result::{HaltReason, Output},
108 },
109 database::CacheDB,
110 interpreter::{InstructionResult, SuccessOrHalt, return_ok, return_revert},
111 primitives::eip7702::PER_EMPTY_ACCOUNT_COST,
112};
113use std::{sync::Arc, time::Duration};
114use tempo_hardfork::TempoHardfork;
115use tokio::{
116 sync::mpsc::{self, UnboundedReceiver, unbounded_channel},
117 try_join,
118};
119
120pub const CLIENT_VERSION: &str = concat!("anvil/v", env!("CARGO_PKG_VERSION"));
122
123pub struct EthApi<N: Network> {
127 pool: Arc<Pool<N::TxEnvelope>>,
129 pub backend: Arc<backend::mem::Backend<N>>,
132 is_mining: bool,
134 signers: Arc<Vec<Box<dyn Signer<N>>>>,
136 fee_history_cache: FeeHistoryCache,
138 fee_history_limit: u64,
140 miner: Miner<N::TxEnvelope>,
145 logger: LoggingManager,
147 filters: Filters<N>,
149 transaction_order: Arc<RwLock<TransactionOrder>>,
151 net_listening: bool,
153 instance_id: Arc<RwLock<B256>>,
155}
156
157impl<N: Network> Clone for EthApi<N> {
158 fn clone(&self) -> Self {
159 Self {
160 pool: self.pool.clone(),
161 backend: self.backend.clone(),
162 is_mining: self.is_mining,
163 signers: self.signers.clone(),
164 fee_history_cache: self.fee_history_cache.clone(),
165 fee_history_limit: self.fee_history_limit,
166 miner: self.miner.clone(),
167 logger: self.logger.clone(),
168 filters: self.filters.clone(),
169 transaction_order: self.transaction_order.clone(),
170 net_listening: self.net_listening,
171 instance_id: self.instance_id.clone(),
172 }
173 }
174}
175
176impl<N: Network> EthApi<N> {
179 #[expect(clippy::too_many_arguments)]
181 pub fn new(
182 pool: Arc<Pool<N::TxEnvelope>>,
183 backend: Arc<backend::mem::Backend<N>>,
184 signers: Arc<Vec<Box<dyn Signer<N>>>>,
185 fee_history_cache: FeeHistoryCache,
186 fee_history_limit: u64,
187 miner: Miner<N::TxEnvelope>,
188 logger: LoggingManager,
189 filters: Filters<N>,
190 transactions_order: TransactionOrder,
191 ) -> Self {
192 Self {
193 pool,
194 backend,
195 is_mining: true,
196 signers,
197 fee_history_cache,
198 fee_history_limit,
199 miner,
200 logger,
201 filters,
202 net_listening: true,
203 transaction_order: Arc::new(RwLock::new(transactions_order)),
204 instance_id: Arc::new(RwLock::new(B256::random())),
205 }
206 }
207
208 pub fn gas_price(&self) -> u128 {
210 if self.backend.is_eip1559() {
211 if self.backend.is_min_priority_fee_enforced() {
212 (self.backend.base_fee() as u128).saturating_add(self.lowest_suggestion_tip())
213 } else {
214 self.backend.base_fee() as u128
215 }
216 } else {
217 self.backend.fees().raw_gas_price()
218 }
219 }
220
221 fn lowest_suggestion_tip(&self) -> u128 {
225 let block_number = self.backend.best_number();
226 let latest_cached_block = self.fee_history_cache.lock().get(&block_number).cloned();
227
228 match latest_cached_block {
229 Some(block) => block.rewards.iter().copied().min(),
230 None => self.fee_history_cache.lock().values().flat_map(|b| b.rewards.clone()).min(),
231 }
232 .map(|fee| fee.max(MIN_SUGGESTED_PRIORITY_FEE))
233 .unwrap_or(MIN_SUGGESTED_PRIORITY_FEE)
234 }
235
236 pub fn anvil_get_auto_mine(&self) -> Result<bool> {
240 node_info!("anvil_getAutomine");
241 Ok(self.miner.is_auto_mine())
242 }
243
244 pub fn anvil_get_interval_mining(&self) -> Result<Option<u64>> {
248 node_info!("anvil_getIntervalMining");
249 Ok(self.miner.get_interval())
250 }
251
252 pub async fn anvil_set_auto_mine(&self, enable_automine: bool) -> Result<()> {
257 node_info!("evm_setAutomine");
258 if self.miner.is_auto_mine() {
259 if enable_automine {
260 return Ok(());
261 }
262 self.miner.set_mining_mode(MiningMode::None);
263 } else if enable_automine {
264 let listener = self.pool.add_ready_listener();
265 let mode = MiningMode::instant(1_000, listener);
266 self.miner.set_mining_mode(mode);
267 }
268 Ok(())
269 }
270
271 pub fn anvil_set_interval_mining(&self, secs: u64) -> Result<()> {
275 node_info!("evm_setIntervalMining");
276 let mining_mode = if secs == 0 {
277 MiningMode::None
278 } else {
279 let block_time = Duration::from_secs(secs);
280
281 self.backend.update_interval_mine_block_time(block_time);
283
284 MiningMode::FixedBlockTime(FixedBlockTimeMiner::new(block_time))
285 };
286 self.miner.set_mining_mode(mining_mode);
287 Ok(())
288 }
289
290 pub async fn anvil_drop_transaction(&self, tx_hash: B256) -> Result<Option<B256>> {
294 node_info!("anvil_dropTransaction");
295 Ok(self.pool.drop_transaction(tx_hash).map(|tx| tx.hash()))
296 }
297
298 pub async fn anvil_drop_all_transactions(&self) -> Result<()> {
302 node_info!("anvil_dropAllTransactions");
303 self.pool.clear();
304 Ok(())
305 }
306
307 pub async fn debug_clear_txpool(&self) -> Result<()> {
311 node_info!("debug_clearTxpool");
312 self.pool.clear();
313 Ok(())
314 }
315
316 pub async fn anvil_set_chain_id(&self, chain_id: u64) -> Result<()> {
317 node_info!("anvil_setChainId");
318 self.backend.set_chain_id(chain_id);
319 Ok(())
320 }
321
322 pub async fn anvil_set_balance(&self, address: Address, balance: U256) -> Result<()> {
326 node_info!("anvil_setBalance");
327 self.backend.set_balance(address, balance).await?;
328 Ok(())
329 }
330
331 pub async fn anvil_set_code(&self, address: Address, code: Bytes) -> Result<()> {
335 node_info!("anvil_setCode");
336 self.backend.set_code(address, code).await?;
337 Ok(())
338 }
339
340 pub async fn anvil_set_nonce(&self, address: Address, nonce: U256) -> Result<()> {
344 node_info!("anvil_setNonce");
345 self.backend.set_nonce(address, nonce).await?;
346 Ok(())
347 }
348
349 pub async fn anvil_set_storage_at(
353 &self,
354 address: Address,
355 slot: U256,
356 val: B256,
357 ) -> Result<bool> {
358 node_info!("anvil_setStorageAt");
359 self.backend.set_storage_at(address, slot, val).await?;
360 Ok(true)
361 }
362
363 pub async fn anvil_set_logging(&self, enable: bool) -> Result<()> {
367 node_info!("anvil_setLoggingEnabled");
368 self.logger.set_enabled(enable);
369 Ok(())
370 }
371
372 pub async fn anvil_set_min_gas_price(&self, gas: U256) -> Result<()> {
376 node_info!("anvil_setMinGasPrice");
377 if self.backend.is_eip1559() {
378 return Err(RpcError::invalid_params(
379 "anvil_setMinGasPrice is not supported when EIP-1559 is active",
380 )
381 .into());
382 }
383 self.backend.set_gas_price(gas.saturating_to());
384 Ok(())
385 }
386
387 pub async fn anvil_set_next_block_base_fee_per_gas(&self, basefee: U256) -> Result<()> {
391 node_info!("anvil_setNextBlockBaseFeePerGas");
392 if !self.backend.is_eip1559() {
393 return Err(RpcError::invalid_params(
394 "anvil_setNextBlockBaseFeePerGas is only supported when EIP-1559 is active",
395 )
396 .into());
397 }
398 self.backend.set_base_fee(basefee.saturating_to());
399 Ok(())
400 }
401
402 pub async fn anvil_set_coinbase(&self, address: Address) -> Result<()> {
406 node_info!("anvil_setCoinbase");
407 self.backend.set_coinbase(address);
408 Ok(())
409 }
410
411 pub async fn anvil_set_next_block_prevrandao(&self, prevrandao: B256) -> Result<()> {
418 node_info!("anvil_setNextBlockPrevRandao");
419 self.backend.set_next_block_prevrandao(prevrandao);
420 Ok(())
421 }
422
423 pub async fn anvil_node_info(&self) -> Result<NodeInfo> {
427 node_info!("anvil_nodeInfo");
428
429 let evm_env = self.backend.evm_env().read();
430 let fork_config = self.backend.get_fork();
431 let tx_order = self.transaction_order.read();
432 let hard_fork = self.backend.hardfork().name();
433
434 Ok(NodeInfo {
435 current_block_number: self.backend.best_number(),
436 current_block_timestamp: evm_env.block_env.timestamp.saturating_to(),
437 current_block_hash: self.backend.best_hash(),
438 hard_fork,
439 transaction_order: match *tx_order {
440 TransactionOrder::Fifo => "fifo".to_string(),
441 TransactionOrder::Fees => "fees".to_string(),
442 },
443 environment: NodeEnvironment {
444 base_fee: self.backend.base_fee() as u128,
445 chain_id: self.backend.chain_id().to::<u64>(),
446 gas_limit: self.backend.gas_limit(),
447 gas_price: self.gas_price(),
448 },
449 fork_config: fork_config
450 .map(|fork| {
451 let config = fork.config.read();
452
453 NodeForkConfig {
454 fork_url: config.eth_rpc_url().map(|s| s.to_string()),
455 fork_block_number: Some(config.block_number),
456 fork_retry_backoff: Some(config.backoff.as_millis()),
457 }
458 })
459 .unwrap_or_default(),
460 network: self.backend.is_tempo().then(|| "tempo".to_string()),
461 })
462 }
463
464 pub async fn anvil_metadata(&self) -> Result<Metadata> {
468 node_info!("anvil_metadata");
469 let fork_config = self.backend.get_fork();
470
471 Ok(Metadata {
472 client_version: CLIENT_VERSION.to_string(),
473 client_semver: Some(SEMVER_VERSION.to_string()),
474 client_commit_sha: Some(COMMIT_SHA.to_string()),
475 chain_id: self.backend.chain_id().to::<u64>(),
476 latest_block_hash: self.backend.best_hash(),
477 latest_block_number: self.backend.best_number(),
478 instance_id: *self.instance_id.read(),
479 forked_network: fork_config.map(|cfg| ForkedNetwork {
480 chain_id: cfg.chain_id(),
481 fork_block_number: cfg.block_number(),
482 fork_block_hash: cfg.block_hash(),
483 }),
484 snapshots: self.backend.list_state_snapshots(),
485 })
486 }
487
488 pub async fn anvil_remove_pool_transactions(&self, address: Address) -> Result<()> {
489 node_info!("anvil_removePoolTransactions");
490 self.pool.remove_transactions_by_address(address);
491 Ok(())
492 }
493
494 pub async fn evm_snapshot(&self) -> Result<U256> {
498 node_info!("evm_snapshot");
499 Ok(self.backend.create_state_snapshot().await)
500 }
501
502 pub async fn evm_increase_time(&self, seconds: U256) -> Result<i64> {
506 node_info!("evm_increaseTime");
507 Ok(self.backend.time().increase_time(seconds.try_into().unwrap_or(u64::MAX)) as i64)
508 }
509
510 pub fn evm_set_next_block_timestamp(&self, seconds: u64) -> Result<()> {
514 node_info!("evm_setNextBlockTimestamp");
515 self.backend.time().set_next_block_timestamp(seconds)
516 }
517
518 pub fn evm_set_time(&self, timestamp: u64) -> Result<u64> {
527 node_info!("evm_setTime");
528 let now = self.backend.time().current_call_timestamp();
529 self.backend.time().reset(timestamp);
530
531 let offset = timestamp.saturating_sub(now);
533 Ok(offset)
534 }
535
536 pub fn evm_set_block_gas_limit(&self, gas_limit: U256) -> Result<bool> {
540 node_info!("evm_setBlockGasLimit");
541 self.backend.set_gas_limit(gas_limit.saturating_to());
542 Ok(true)
543 }
544
545 pub fn evm_set_block_timestamp_interval(&self, seconds: u64) -> Result<()> {
549 node_info!("anvil_setBlockTimestampInterval");
550 self.backend.time().set_block_timestamp_interval(seconds);
551 Ok(())
552 }
553
554 pub fn evm_remove_block_timestamp_interval(&self) -> Result<bool> {
558 node_info!("anvil_removeBlockTimestampInterval");
559 Ok(self.backend.time().remove_block_timestamp_interval())
560 }
561
562 pub async fn anvil_set_rpc_url(&self, url: String) -> Result<()> {
566 node_info!("anvil_setRpcUrl");
567 if let Some(fork) = self.backend.get_fork() {
568 let mut config = fork.config.write();
569 let new_provider = Arc::new(
571 ProviderBuilder::new(&url).max_retry(10).initial_backoff(1000).build().map_err(
572 |_| {
573 TransportErrorKind::custom_str(
574 format!("Failed to parse invalid url {url}").as_str(),
575 )
576 },
577 )?, );
580 config.provider = new_provider;
581 trace!(target: "backend", "Updated fork rpc from \"{}\" to \"{}\"", config.eth_rpc_url().unwrap_or("none"), url);
582 config.fork_urls = vec![url.clone()];
583 }
584 self.backend.node_config.write().await.fork_urls = vec![url];
586 Ok(())
587 }
588
589 pub async fn txpool_status(&self) -> Result<TxpoolStatus> {
595 node_info!("txpool_status");
596 Ok(self.pool.txpool_status())
597 }
598
599 async fn on_blocking_task<C, F, R>(&self, c: C) -> Result<R>
601 where
602 C: FnOnce(Self) -> F,
603 F: Future<Output = Result<R>> + Send + 'static,
604 R: Send + 'static,
605 {
606 let (tx, rx) = oneshot::channel();
607 let this = self.clone();
608 let f = c(this);
609 tokio::task::spawn_blocking(move || {
610 tokio::runtime::Handle::current().block_on(async move {
611 let res = f.await;
612 let _ = tx.send(res);
613 })
614 });
615 rx.await.map_err(|_| BlockchainError::Internal("blocking task panicked".to_string()))?
616 }
617
618 pub fn set_transaction_order(&self, order: TransactionOrder) {
620 *self.transaction_order.write() = order;
621 }
622
623 pub fn chain_id(&self) -> u64 {
625 self.backend.chain_id().to::<u64>()
626 }
627
628 pub fn get_fork(&self) -> Option<ClientFork> {
630 self.backend.get_fork()
631 }
632
633 pub fn instance_id(&self) -> B256 {
635 *self.instance_id.read()
636 }
637
638 pub fn reset_instance_id(&self) {
640 *self.instance_id.write() = B256::random();
641 }
642
643 #[expect(clippy::borrowed_box)]
645 pub fn get_signer(&self, address: Address) -> Option<&Box<dyn Signer<N>>> {
646 self.signers.iter().find(|signer| signer.is_signer_for(address))
647 }
648
649 pub fn new_ready_transactions(&self) -> Receiver<TxHash> {
651 self.pool.add_ready_listener()
652 }
653
654 pub fn is_fork(&self) -> bool {
656 self.backend.is_fork()
657 }
658
659 pub async fn state_root(&self) -> Option<B256> {
661 self.backend.get_db().read().await.maybe_state_root()
662 }
663
664 pub fn is_impersonated(&self, addr: Address) -> bool {
666 self.backend.cheats().is_impersonated(addr)
667 }
668
669 pub fn storage_info(&self) -> StorageInfo<N> {
671 StorageInfo::new(Arc::clone(&self.backend))
672 }
673
674 #[allow(clippy::large_stack_frames)]
676 pub fn anvil_get_blob_by_versioned_hash(
677 &self,
678 hash: B256,
679 ) -> Result<Option<alloy_consensus::Blob>> {
680 node_info!("anvil_getBlobByHash");
681 Ok(self.backend.get_blob_by_versioned_hash(hash)?)
682 }
683
684 pub fn anvil_get_blobs_by_block_id(
686 &self,
687 block_id: impl Into<BlockId>,
688 versioned_hashes: Vec<B256>,
689 ) -> Result<Option<Vec<Blob>>> {
690 node_info!("anvil_getBlobsByBlockId");
691 Ok(self.backend.get_blobs_by_block_id(block_id, versioned_hashes)?)
692 }
693
694 pub fn anvil_get_genesis_time(&self) -> Result<u64> {
698 node_info!("anvil_getGenesisTime");
699 Ok(self.backend.genesis_time())
700 }
701
702 pub async fn anvil_reset(&self, forking: Option<Forking>) -> Result<()> {
708 self.reset_instance_id();
709 node_info!("anvil_reset");
710 if let Some(forking) = forking {
711 self.backend.reset_fork(forking).await?;
713 } else {
714 self.backend.reset_to_in_mem().await?;
716 }
717 self.pool.clear();
719 Ok(())
720 }
721
722 pub async fn evm_revert(&self, id: U256) -> Result<bool> {
727 node_info!("evm_revert");
728 self.backend.revert_state_snapshot(id).await
729 }
730
731 pub async fn anvil_impersonate_account(&self, address: Address) -> Result<()> {
735 node_info!("anvil_impersonateAccount");
736 self.backend.impersonate(address);
737 Ok(())
738 }
739
740 pub async fn anvil_stop_impersonating_account(&self, address: Address) -> Result<()> {
744 node_info!("anvil_stopImpersonatingAccount");
745 self.backend.stop_impersonating(address);
746 Ok(())
747 }
748
749 pub async fn anvil_auto_impersonate_account(&self, enabled: bool) -> Result<()> {
753 node_info!("anvil_autoImpersonateAccount");
754 self.backend.auto_impersonate_account(enabled);
755 Ok(())
756 }
757
758 pub async fn anvil_impersonate_signature(
760 &self,
761 signature: Bytes,
762 address: Address,
763 ) -> Result<()> {
764 node_info!("anvil_impersonateSignature");
765 self.backend.impersonate_signature(signature, address).await
766 }
767
768 pub fn new_block_notifications(&self) -> ChainNotifications {
771 self.backend.new_block_notifications()
772 }
773
774 pub fn client_version(&self) -> Result<String> {
778 node_info!("web3_clientVersion");
779 Ok(CLIENT_VERSION.to_string())
780 }
781
782 pub fn sha3(&self, bytes: Bytes) -> Result<String> {
786 node_info!("web3_sha3");
787 let hash = alloy_primitives::keccak256(bytes.as_ref());
788 Ok(alloy_primitives::hex::encode_prefixed(&hash[..]))
789 }
790
791 pub fn protocol_version(&self) -> Result<u64> {
795 node_info!("eth_protocolVersion");
796 Ok(1)
797 }
798
799 pub fn hashrate(&self) -> Result<U256> {
803 node_info!("eth_hashrate");
804 Ok(U256::ZERO)
805 }
806
807 pub fn author(&self) -> Result<Address> {
811 node_info!("eth_coinbase");
812 Ok(self.backend.coinbase())
813 }
814
815 pub fn is_mining(&self) -> Result<bool> {
819 node_info!("eth_mining");
820 Ok(self.is_mining)
821 }
822
823 pub fn eth_chain_id(&self) -> Result<Option<U64>> {
829 node_info!("eth_chainId");
830 Ok(Some(self.backend.chain_id().to::<U64>()))
831 }
832
833 pub fn network_id(&self) -> Result<Option<String>> {
837 node_info!("eth_networkId");
838 let chain_id = self.backend.chain_id().to::<u64>();
839 Ok(Some(format!("{chain_id}")))
840 }
841
842 pub fn net_listening(&self) -> Result<bool> {
846 node_info!("net_listening");
847 Ok(self.net_listening)
848 }
849
850 fn eth_gas_price(&self) -> Result<U256> {
852 node_info!("eth_gasPrice");
853 Ok(U256::from(self.gas_price()))
854 }
855
856 pub fn base_fee(&self) -> Result<Option<U256>> {
860 node_info!("eth_baseFee");
861 Ok(self.backend.is_eip1559().then(|| U256::from(self.backend.base_fee())))
862 }
863
864 pub fn excess_blob_gas_and_price(&self) -> Result<Option<BlobExcessGasAndPrice>> {
866 Ok(self.backend.excess_blob_gas_and_price())
867 }
868
869 pub fn gas_max_priority_fee_per_gas(&self) -> Result<U256> {
874 self.max_priority_fee_per_gas()
875 }
876
877 pub fn blob_base_fee(&self) -> Result<U256> {
881 Ok(U256::from(self.backend.fees().base_fee_per_blob_gas()))
882 }
883
884 pub fn gas_limit(&self) -> U256 {
886 U256::from(self.backend.gas_limit())
887 }
888
889 pub fn accounts(&self) -> Result<Vec<Address>> {
893 node_info!("eth_accounts");
894 let mut unique = HashSet::new();
895 let mut accounts: Vec<Address> = Vec::new();
896 for signer in self.signers.iter() {
897 accounts.extend(signer.accounts().into_iter().filter(|acc| unique.insert(*acc)));
898 }
899 accounts.extend(
900 self.backend
901 .cheats()
902 .impersonated_accounts()
903 .into_iter()
904 .filter(|acc| unique.insert(*acc)),
905 );
906 Ok(accounts.into_iter().collect())
907 }
908
909 pub fn block_number(&self) -> Result<U256> {
913 node_info!("eth_blockNumber");
914 Ok(U256::from(self.backend.best_number()))
915 }
916
917 pub async fn block_by_hash(&self, hash: B256) -> Result<Option<AnyRpcBlock>> {
921 node_info!("eth_getBlockByHash");
922 self.backend.block_by_hash(hash).await
923 }
924
925 pub async fn header_by_hash(
929 &self,
930 hash: B256,
931 ) -> Result<Option<WithOtherFields<AnyRpcHeader>>> {
932 node_info!("eth_getHeaderByHash");
933 Ok(self.backend.block_by_hash(hash).await?.map(|block| {
934 let WithOtherFields { inner: block, other } = block.0;
935 WithOtherFields { inner: block.header, other }
936 }))
937 }
938
939 pub async fn block_by_hash_full(&self, hash: B256) -> Result<Option<AnyRpcBlock>> {
943 node_info!("eth_getBlockByHash");
944 self.backend.block_by_hash_full(hash).await
945 }
946
947 pub async fn block_transaction_count_by_hash(&self, hash: B256) -> Result<Option<U256>> {
951 node_info!("eth_getBlockTransactionCountByHash");
952 let block = self.backend.block_by_hash(hash).await?;
953 let txs = block.map(|b| match b.transactions() {
954 BlockTransactions::Full(txs) => U256::from(txs.len()),
955 BlockTransactions::Hashes(txs) => U256::from(txs.len()),
956 BlockTransactions::Uncle => U256::from(0),
957 });
958 Ok(txs)
959 }
960
961 pub async fn block_uncles_count_by_hash(&self, hash: B256) -> Result<U256> {
965 node_info!("eth_getUncleCountByBlockHash");
966 let block =
967 self.backend.block_by_hash(hash).await?.ok_or(BlockchainError::BlockNotFound)?;
968 Ok(U256::from(block.uncles.len()))
969 }
970
971 pub async fn block_uncles_count_by_number(&self, block_number: BlockNumber) -> Result<U256> {
975 node_info!("eth_getUncleCountByBlockNumber");
976 let block = self
977 .backend
978 .block_by_number(block_number)
979 .await?
980 .ok_or(BlockchainError::BlockNotFound)?;
981 Ok(U256::from(block.uncles.len()))
982 }
983
984 pub async fn sign_typed_data(
988 &self,
989 _address: Address,
990 _data: serde_json::Value,
991 ) -> Result<String> {
992 node_info!("eth_signTypedData");
993 Err(BlockchainError::RpcUnimplemented)
994 }
995
996 pub async fn sign_typed_data_v3(
1000 &self,
1001 _address: Address,
1002 _data: serde_json::Value,
1003 ) -> Result<String> {
1004 node_info!("eth_signTypedData_v3");
1005 Err(BlockchainError::RpcUnimplemented)
1006 }
1007
1008 pub async fn sign_typed_data_v4(&self, address: Address, data: &TypedData) -> Result<String> {
1012 node_info!("eth_signTypedData_v4");
1013 let signer = self.get_signer(address).ok_or(BlockchainError::NoSignerAvailable)?;
1014 let signature = signer.sign_typed_data(address, data).await?;
1015 let signature = alloy_primitives::hex::encode(signature.as_bytes());
1016 Ok(format!("0x{signature}"))
1017 }
1018
1019 pub async fn sign(&self, address: Address, content: impl AsRef<[u8]>) -> Result<String> {
1023 node_info!("eth_sign");
1024 let signer = self.get_signer(address).ok_or(BlockchainError::NoSignerAvailable)?;
1025 let signature =
1026 alloy_primitives::hex::encode(signer.sign(address, content.as_ref()).await?.as_bytes());
1027 Ok(format!("0x{signature}"))
1028 }
1029
1030 pub async fn transaction_by_block_hash_and_index(
1034 &self,
1035 hash: B256,
1036 index: Index,
1037 ) -> Result<Option<AnyRpcTransaction>> {
1038 node_info!("eth_getTransactionByBlockHashAndIndex");
1039 self.backend.transaction_by_block_hash_and_index(hash, index).await
1040 }
1041
1042 pub async fn transaction_by_block_number_and_index(
1046 &self,
1047 block: BlockNumber,
1048 idx: Index,
1049 ) -> Result<Option<AnyRpcTransaction>> {
1050 node_info!("eth_getTransactionByBlockNumberAndIndex");
1051 self.backend.transaction_by_block_number_and_index(block, idx).await
1052 }
1053
1054 pub async fn uncle_by_block_hash_and_index(
1058 &self,
1059 block_hash: B256,
1060 idx: Index,
1061 ) -> Result<Option<AnyRpcBlock>> {
1062 node_info!("eth_getUncleByBlockHashAndIndex");
1063 let number =
1064 self.backend.ensure_block_number(Some(BlockId::Hash(block_hash.into()))).await?;
1065 if let Some(fork) = self.get_fork()
1066 && fork.predates_fork_inclusive(number)
1067 {
1068 return Ok(fork.uncle_by_block_hash_and_index(block_hash, idx.into()).await?);
1069 }
1070 Ok(None)
1072 }
1073
1074 pub async fn uncle_by_block_number_and_index(
1078 &self,
1079 block_number: BlockNumber,
1080 idx: Index,
1081 ) -> Result<Option<AnyRpcBlock>> {
1082 node_info!("eth_getUncleByBlockNumberAndIndex");
1083 let number = self.backend.ensure_block_number(Some(BlockId::Number(block_number))).await?;
1084 if let Some(fork) = self.get_fork()
1085 && fork.predates_fork_inclusive(number)
1086 {
1087 return Ok(fork.uncle_by_block_number_and_index(number, idx.into()).await?);
1088 }
1089 Ok(None)
1091 }
1092
1093 pub fn work(&self) -> Result<Work> {
1097 node_info!("eth_getWork");
1098 Err(BlockchainError::RpcUnimplemented)
1099 }
1100
1101 pub fn syncing(&self) -> Result<bool> {
1105 node_info!("eth_syncing");
1106 Ok(false)
1107 }
1108
1109 pub fn config(&self) -> Result<EthConfig> {
1120 node_info!("eth_config");
1121 Ok(EthConfig {
1122 current: EthForkConfig {
1123 activation_time: 0,
1124 blob_schedule: self.backend.blob_params(),
1125 chain_id: self.backend.chain_id().to::<u64>(),
1126 fork_id: Bytes::from_static(&[0; 4]),
1127 precompiles: self.backend.precompiles(),
1128 system_contracts: self.backend.system_contracts(),
1129 },
1130 next: None,
1131 last: None,
1132 })
1133 }
1134
1135 pub fn submit_work(&self, _: B64, _: B256, _: B256) -> Result<bool> {
1139 node_info!("eth_submitWork");
1140 Err(BlockchainError::RpcUnimplemented)
1141 }
1142
1143 pub fn submit_hashrate(&self, _: U256, _: B256) -> Result<bool> {
1147 node_info!("eth_submitHashrate");
1148 Err(BlockchainError::RpcUnimplemented)
1149 }
1150
1151 pub async fn fee_history(
1155 &self,
1156 block_count: U256,
1157 newest_block: BlockNumber,
1158 reward_percentiles: Vec<f64>,
1159 ) -> Result<FeeHistory> {
1160 node_info!("eth_feeHistory");
1161 let number = self.backend.convert_block_number(Some(newest_block));
1164
1165 if let Some(fork) = self.get_fork() {
1167 if fork.predates_fork_inclusive(number) {
1170 return fork
1171 .fee_history(block_count.to(), BlockNumber::Number(number), &reward_percentiles)
1172 .await
1173 .map_err(BlockchainError::AlloyForkProvider);
1174 }
1175 }
1176
1177 const MAX_BLOCK_COUNT: u64 = 1024u64;
1178 let block_count = block_count.saturating_to::<u64>().min(MAX_BLOCK_COUNT);
1179
1180 let highest = number;
1182 let lowest = highest.saturating_sub(block_count.saturating_sub(1));
1183
1184 if lowest < self.backend.best_number().saturating_sub(self.fee_history_limit) {
1186 return Err(FeeHistoryError::InvalidBlockRange.into());
1187 }
1188
1189 let mut response = FeeHistory {
1190 oldest_block: lowest,
1191 base_fee_per_gas: Vec::new(),
1192 gas_used_ratio: Vec::new(),
1193 reward: Some(Default::default()),
1194 base_fee_per_blob_gas: Default::default(),
1195 blob_gas_used_ratio: Default::default(),
1196 };
1197 let mut rewards = Vec::new();
1198
1199 {
1200 let fee_history = self.fee_history_cache.lock();
1201
1202 for n in lowest..=highest {
1204 if let Some(block) = fee_history.get(&n) {
1206 response.base_fee_per_gas.push(block.base_fee);
1207 response.base_fee_per_blob_gas.push(block.base_fee_per_blob_gas.unwrap_or(0));
1208 response.blob_gas_used_ratio.push(block.blob_gas_used_ratio);
1209 response.gas_used_ratio.push(block.gas_used_ratio);
1210
1211 if !reward_percentiles.is_empty() {
1213 let mut block_rewards = Vec::new();
1214 let resolution_per_percentile: f64 = 2.0;
1215 for p in &reward_percentiles {
1216 let p = p.clamp(0.0, 100.0);
1217 let index = ((p.round() / 2f64) * 2f64) * resolution_per_percentile;
1218 let reward = block.rewards.get(index as usize).map_or(0, |r| *r);
1219 block_rewards.push(reward);
1220 }
1221 rewards.push(block_rewards);
1222 }
1223 }
1224 }
1225 }
1226
1227 response.reward = Some(rewards);
1228
1229 response.base_fee_per_gas.push(self.backend.fees().base_fee() as u128);
1234
1235 response.base_fee_per_blob_gas.push(self.backend.fees().base_fee_per_blob_gas());
1239
1240 Ok(response)
1241 }
1242
1243 pub fn max_priority_fee_per_gas(&self) -> Result<U256> {
1250 node_info!("eth_maxPriorityFeePerGas");
1251 Ok(U256::from(self.lowest_suggestion_tip()))
1252 }
1253
1254 pub async fn debug_code_by_hash(
1258 &self,
1259 hash: B256,
1260 block_id: Option<BlockId>,
1261 ) -> Result<Option<Bytes>> {
1262 node_info!("debug_codeByHash");
1263 self.backend.debug_code_by_hash(hash, block_id).await
1264 }
1265
1266 pub async fn debug_db_get(&self, key: String) -> Result<Option<Bytes>> {
1271 node_info!("debug_dbGet");
1272 self.backend.debug_db_get(key).await
1273 }
1274
1275 pub fn debug_get_modified_accounts_by_number(
1277 &self,
1278 _start_number: u64,
1279 _end_number: u64,
1280 ) -> Result<()> {
1281 node_info!("debug_getModifiedAccountsByNumber");
1282 Ok(())
1283 }
1284
1285 pub fn debug_free_os_memory(&self) -> Result<()> {
1287 node_info!("debug_freeOSMemory");
1288 Ok(())
1289 }
1290
1291 pub async fn trace_call(
1295 &self,
1296 request: WithOtherFields<TransactionRequest>,
1297 mut trace_types: HashSet<TraceType>,
1298 block_id: Option<BlockId>,
1299 ) -> Result<TraceResults>
1300 where
1301 N: Network<TxEnvelope = FoundryTxEnvelope, ReceiptEnvelope = FoundryReceiptEnvelope>,
1302 {
1303 node_info!("trace_call");
1304 if trace_types.is_empty() {
1305 trace_types.insert(TraceType::Trace);
1306 }
1307
1308 let block_id = block_id.unwrap_or_default();
1309 let block_request = match &block_id {
1310 BlockId::Number(BlockNumber::Pending) => {
1311 let pending_txs = self.pool.ready_transactions().collect();
1312 BlockRequest::Pending(pending_txs)
1313 }
1314 _ => {
1315 let number = self.backend.ensure_block_number(Some(block_id)).await?;
1316 BlockRequest::Number(number)
1317 }
1318 };
1319 let fees = FeeDetails::new(
1320 request.gas_price,
1321 request.max_fee_per_gas,
1322 request.max_priority_fee_per_gas,
1323 request.max_fee_per_blob_gas,
1324 )?
1325 .or_zero_fees();
1326
1327 self.backend.trace_call(request, fees, trace_types, block_request, block_id).await
1328 }
1329
1330 pub async fn trace_transaction(&self, tx_hash: B256) -> Result<Vec<LocalizedTransactionTrace>> {
1334 node_info!("trace_transaction");
1335 self.backend.trace_transaction(tx_hash).await
1336 }
1337
1338 pub async fn trace_block(&self, block: BlockNumber) -> Result<Vec<LocalizedTransactionTrace>> {
1342 node_info!("trace_block");
1343 self.backend.trace_block(block).await
1344 }
1345
1346 pub async fn trace_filter(
1350 &self,
1351 filter: TraceFilter,
1352 ) -> Result<Vec<LocalizedTransactionTrace>> {
1353 node_info!("trace_filter");
1354 self.backend.trace_filter(filter).await
1355 }
1356
1357 pub async fn trace_get(
1361 &self,
1362 hash: B256,
1363 indices: Vec<Index>,
1364 ) -> Result<Option<LocalizedTransactionTrace>> {
1365 node_info!("trace_get");
1366 self.backend.trace_get(hash, indices).await
1367 }
1368
1369 pub async fn trace_replay_block_transactions(
1373 &self,
1374 block: BlockNumber,
1375 trace_types: HashSet<TraceType>,
1376 ) -> Result<Vec<TraceResultsWithTransactionHash>> {
1377 node_info!("trace_replayBlockTransactions");
1378 self.backend.trace_replay_block_transactions(block, trace_types).await
1379 }
1380
1381 pub async fn trace_replay_transaction(
1385 &self,
1386 transaction: B256,
1387 trace_types: HashSet<TraceType>,
1388 ) -> Result<TraceResults> {
1389 node_info!("trace_replayTransaction");
1390 self.backend.trace_replay_transaction(transaction, trace_types).await
1391 }
1392}
1393
1394impl<N: Network<ReceiptEnvelope = FoundryReceiptEnvelope>> EthApi<N> {
1395 pub async fn serialized_state(
1397 &self,
1398 preserve_historical_states: bool,
1399 ) -> Result<SerializableState> {
1400 self.backend.serialized_state(preserve_historical_states).await
1401 }
1402}
1403
1404impl EthApi<FoundryNetwork> {
1407 pub async fn anvil_dump_state(
1412 &self,
1413 preserve_historical_states: Option<bool>,
1414 ) -> Result<Bytes> {
1415 node_info!("anvil_dumpState");
1416 self.backend.dump_state(preserve_historical_states.unwrap_or(false)).await
1417 }
1418
1419 pub async fn anvil_load_state(&self, buf: Bytes) -> Result<bool> {
1424 node_info!("anvil_loadState");
1425 self.backend.load_state_bytes(buf).await
1426 }
1427
1428 async fn block_request(
1429 &self,
1430 block_number: Option<BlockId>,
1431 ) -> Result<BlockRequest<FoundryTxEnvelope>> {
1432 let block_request = match block_number {
1433 Some(BlockId::Number(BlockNumber::Pending)) => {
1434 let pending_txs = self.pool.ready_transactions().collect();
1435 BlockRequest::Pending(pending_txs)
1436 }
1437 _ => {
1438 let number = self.backend.ensure_block_number(block_number).await?;
1439 BlockRequest::Number(number)
1440 }
1441 };
1442 Ok(block_request)
1443 }
1444
1445 pub async fn debug_account_info_at(
1449 &self,
1450 block_id: BlockId,
1451 tx_index: Index,
1452 address: Address,
1453 ) -> Result<Option<AccountInfo>> {
1454 node_info!("debug_accountInfoAt");
1455 self.backend.debug_account_info_at(block_id, tx_index, address).await
1456 }
1457
1458 pub async fn trace_transaction_opcode_gas(
1462 &self,
1463 tx_hash: B256,
1464 ) -> Result<Option<TransactionOpcodeGas>> {
1465 node_info!("trace_transactionOpcodeGas");
1466 self.backend.trace_transaction_opcode_gas(tx_hash).await
1467 }
1468
1469 pub async fn trace_block_opcode_gas(
1473 &self,
1474 block_id: BlockId,
1475 ) -> Result<Option<BlockOpcodeGas>> {
1476 node_info!("trace_blockOpcodeGas");
1477 self.backend.trace_block_opcode_gas(block_id).await
1478 }
1479
1480 pub async fn trace_raw_transaction(
1484 &self,
1485 tx: Bytes,
1486 trace_types: HashSet<TraceType>,
1487 block_number: Option<BlockId>,
1488 ) -> Result<TraceResults> {
1489 node_info!("trace_rawTransaction");
1490
1491 let mut data = tx.as_ref();
1492 if data.is_empty() {
1493 return Err(BlockchainError::EmptyRawTransactionData);
1494 }
1495
1496 let transaction = FoundryTxEnvelope::decode_2718(&mut data)
1497 .map_err(|_| BlockchainError::FailedToDecodeSignedTransaction)?;
1498 self.ensure_typed_transaction_supported(&transaction)?;
1499
1500 let pending_transaction = PendingTransaction::new(transaction)?;
1501 let block_request = self.block_request(block_number).await?;
1502
1503 self.backend
1504 .trace_raw_transaction(pending_transaction, trace_types, Some(block_request))
1505 .await
1506 }
1507
1508 pub async fn anvil_add_balance(&self, address: Address, balance: U256) -> Result<()> {
1512 node_info!("anvil_addBalance");
1513 let current_balance = self.backend.get_balance(address, None).await?;
1514 self.backend.set_balance(address, current_balance.saturating_add(balance)).await?;
1515 Ok(())
1516 }
1517
1518 pub async fn anvil_rollback(&self, depth: Option<u64>) -> Result<()> {
1529 node_info!("anvil_rollback");
1530 let depth = depth.unwrap_or(1);
1531
1532 let current_height = self.backend.best_number();
1534 let common_height = current_height.checked_sub(depth).ok_or(BlockchainError::RpcError(
1535 RpcError::invalid_params(format!(
1536 "Rollback depth must not exceed current chain height: current height {current_height}, depth {depth}"
1537 )),
1538 ))?;
1539
1540 let common_block =
1542 self.backend.get_block(common_height).ok_or(BlockchainError::BlockNotFound)?;
1543
1544 self.backend.rollback(common_block).await?;
1545 Ok(())
1546 }
1547
1548 fn do_estimate_gas_with_state(
1552 &self,
1553 mut request: WithOtherFields<TransactionRequest>,
1554 state: &dyn DatabaseRef,
1555 block_env: BlockEnv,
1556 ) -> Result<u128> {
1557 let fees = FeeDetails::new(
1558 request.gas_price,
1559 request.max_fee_per_gas,
1560 request.max_priority_fee_per_gas,
1561 request.max_fee_per_blob_gas,
1562 )?
1563 .or_zero_fees();
1564
1565 let mut highest_gas_limit = request.gas.map_or(block_env.gas_limit.into(), |g| g as u128);
1568
1569 let is_tempo_aa_tx =
1572 self.backend.is_tempo() && request.other.get("feeToken").is_some_and(|v| !v.is_null());
1573
1574 let gas_price = fees.gas_price.unwrap_or_default();
1575 if !is_tempo_aa_tx && let Some(from) = request.from {
1580 let mut available_funds = self.backend.get_balance_with_state(state, from)?;
1581 if let Some(value) = request.value {
1582 if value > available_funds {
1583 return Err(InvalidTransactionError::InsufficientFunds.into());
1584 }
1585 available_funds -= value;
1587 }
1588 if gas_price > 0 {
1589 let allowance =
1591 available_funds.checked_div(U256::from(gas_price)).unwrap_or_default();
1592 highest_gas_limit = std::cmp::min(highest_gas_limit, allowance.saturating_to());
1593 }
1594 }
1595
1596 if !self.backend.is_tempo() {
1601 let to = request.to.as_ref().and_then(TxKind::to);
1602
1603 let maybe_transfer = (request.input.input().is_none()
1605 || request.input.input().is_some_and(|data| data.is_empty()))
1606 && request.authorization_list.is_none()
1607 && request.access_list.is_none()
1608 && request.blob_versioned_hashes.is_none();
1609
1610 if maybe_transfer
1611 && highest_gas_limit >= MIN_TRANSACTION_GAS
1612 && let Some(to) = to
1613 && let Ok(target_code) = self.backend.get_code_with_state(&state, *to)
1614 && target_code.as_ref().is_empty()
1615 {
1616 return Ok(MIN_TRANSACTION_GAS);
1617 }
1618 }
1619
1620 let mut call_to_estimate = request.clone();
1621 call_to_estimate.gas = Some(highest_gas_limit as u64);
1622
1623 let ethres =
1625 self.backend.call_with_state(&state, call_to_estimate, fees.clone(), block_env.clone());
1626
1627 let gas_used = match ethres.try_into()? {
1628 GasEstimationCallResult::Success(gas) => Ok(gas),
1629 GasEstimationCallResult::OutOfGas => {
1630 Err(InvalidTransactionError::BasicOutOfGas(highest_gas_limit).into())
1631 }
1632 GasEstimationCallResult::Revert(output) => {
1633 Err(InvalidTransactionError::Revert(output).into())
1634 }
1635 GasEstimationCallResult::EvmError(err) => {
1636 warn!(target: "node", "estimation failed due to {:?}", err);
1637 Err(BlockchainError::EvmError(err))
1638 }
1639 }?;
1640
1641 let mut lowest_gas_limit = determine_base_gas_by_kind(&request);
1648
1649 let mut mid_gas_limit =
1651 std::cmp::min(gas_used * 3, (highest_gas_limit + lowest_gas_limit) / 2);
1652
1653 while (highest_gas_limit - lowest_gas_limit) > 1 {
1655 request.gas = Some(mid_gas_limit as u64);
1656 let ethres = self.backend.call_with_state(
1657 &state,
1658 request.clone(),
1659 fees.clone(),
1660 block_env.clone(),
1661 );
1662
1663 match ethres.try_into()? {
1664 GasEstimationCallResult::Success(_) => {
1665 highest_gas_limit = mid_gas_limit;
1669 }
1670 GasEstimationCallResult::OutOfGas
1671 | GasEstimationCallResult::Revert(_)
1672 | GasEstimationCallResult::EvmError(_) => {
1673 lowest_gas_limit = mid_gas_limit;
1680 }
1681 };
1682 mid_gas_limit = (highest_gas_limit + lowest_gas_limit) / 2;
1684 }
1685
1686 trace!(target : "node", "Estimated Gas for call {:?}", highest_gas_limit);
1687
1688 Ok(highest_gas_limit)
1689 }
1690
1691 #[allow(clippy::large_stack_frames)]
1693 pub async fn execute(&self, request: EthRequest) -> ResponseResult {
1694 trace!(target: "rpc::api", "executing eth request");
1695 let response = match request.clone() {
1696 EthRequest::EthProtocolVersion(()) => self.protocol_version().to_rpc_result(),
1697 EthRequest::Web3ClientVersion(()) => self.client_version().to_rpc_result(),
1698 EthRequest::Web3Sha3(content) => self.sha3(content).to_rpc_result(),
1699 EthRequest::EthGetAccount(addr, block) => {
1700 self.get_account(addr, block).await.to_rpc_result()
1701 }
1702 EthRequest::EthGetAccountInfo(addr, block) => {
1703 self.get_account_info(addr, block).await.to_rpc_result()
1704 }
1705 EthRequest::EthGetBalance(addr, block) => {
1706 self.balance(addr, block).await.to_rpc_result()
1707 }
1708 EthRequest::EthGetTransactionByHash(hash) => {
1709 self.transaction_by_hash(hash).await.to_rpc_result()
1710 }
1711 EthRequest::EthPendingTransactions(_) => {
1712 self.pending_transactions().await.to_rpc_result()
1713 }
1714 EthRequest::EthSendTransaction(request) => {
1715 self.send_transaction(*request).await.to_rpc_result()
1716 }
1717 EthRequest::EthResend(request, gas_price, gas_limit) => {
1718 self.resend_transaction(*request, gas_price, gas_limit).await.to_rpc_result()
1719 }
1720 EthRequest::EthSendTransactionSync(request) => {
1721 self.send_transaction_sync(*request).await.to_rpc_result()
1722 }
1723 EthRequest::EthChainId(_) => self.eth_chain_id().to_rpc_result(),
1724 EthRequest::EthNetworkId(_) => self.network_id().to_rpc_result(),
1725 EthRequest::NetListening(_) => self.net_listening().to_rpc_result(),
1726 EthRequest::EthHashrate(()) => self.hashrate().to_rpc_result(),
1727 EthRequest::EthGasPrice(_) => self.eth_gas_price().to_rpc_result(),
1728 EthRequest::EthBaseFee(_) => self.base_fee().to_rpc_result(),
1729 EthRequest::EthMaxPriorityFeePerGas(_) => {
1730 self.gas_max_priority_fee_per_gas().to_rpc_result()
1731 }
1732 EthRequest::EthBlobBaseFee(_) => self.blob_base_fee().to_rpc_result(),
1733 EthRequest::EthAccounts(_) => self.accounts().to_rpc_result(),
1734 EthRequest::EthBlockNumber(_) => self.block_number().to_rpc_result(),
1735 EthRequest::EthCoinbase(()) => self.author().to_rpc_result(),
1736 EthRequest::EthGetStorageAt(addr, slot, block) => {
1737 self.storage_at(addr, slot, block).await.to_rpc_result()
1738 }
1739 EthRequest::EthGetStorageValues(requests, block) => {
1740 self.storage_values(requests, block).await.to_rpc_result()
1741 }
1742 EthRequest::EthGetBlockByHash(hash, full) => {
1743 if full {
1744 self.block_by_hash_full(hash).await.to_rpc_result()
1745 } else {
1746 self.block_by_hash(hash).await.to_rpc_result()
1747 }
1748 }
1749 EthRequest::EthGetHeaderByHash(hash) => self.header_by_hash(hash).await.to_rpc_result(),
1750 EthRequest::EthGetBlockByNumber(num, full) => {
1751 if full {
1752 self.block_by_number_full(num).await.to_rpc_result()
1753 } else {
1754 self.block_by_number(num).await.to_rpc_result()
1755 }
1756 }
1757 EthRequest::EthGetHeaderByNumber(num) => {
1758 self.header_by_number(num).await.to_rpc_result()
1759 }
1760 EthRequest::EthGetBlockAccessList(block_id) => {
1761 self.block_access_list(block_id).await.to_rpc_result()
1762 }
1763 EthRequest::EthGetBlockAccessListByBlockHash(block_hash) => {
1764 self.block_access_list_by_hash(block_hash).await.to_rpc_result()
1765 }
1766 EthRequest::EthGetBlockAccessListByBlockNumber(block_number) => {
1767 self.block_access_list_by_number(block_number).await.to_rpc_result()
1768 }
1769 EthRequest::EthGetBlockAccessListRaw(block_id) => {
1770 self.block_access_list_raw(block_id).await.to_rpc_result()
1771 }
1772 EthRequest::EthGetTransactionCount(addr, block) => {
1773 self.transaction_count(addr, block).await.to_rpc_result()
1774 }
1775 EthRequest::EthGetTransactionCountByHash(hash) => {
1776 self.block_transaction_count_by_hash(hash).await.to_rpc_result()
1777 }
1778 EthRequest::EthGetTransactionCountByNumber(num) => {
1779 self.block_transaction_count_by_number(num).await.to_rpc_result()
1780 }
1781 EthRequest::EthGetUnclesCountByHash(hash) => {
1782 self.block_uncles_count_by_hash(hash).await.to_rpc_result()
1783 }
1784 EthRequest::EthGetUnclesCountByNumber(num) => {
1785 self.block_uncles_count_by_number(num).await.to_rpc_result()
1786 }
1787 EthRequest::EthGetCodeAt(addr, block) => {
1788 self.get_code(addr, block).await.to_rpc_result()
1789 }
1790 EthRequest::EthGetProof(addr, keys, block) => {
1791 self.get_proof(addr, keys, block).await.to_rpc_result()
1792 }
1793 EthRequest::EthSign(addr, content) => self.sign(addr, content).await.to_rpc_result(),
1794 EthRequest::PersonalSign(content, addr) => {
1795 self.sign(addr, content).await.to_rpc_result()
1796 }
1797 EthRequest::EthSignTransaction(request) => {
1798 self.sign_transaction(*request).await.to_rpc_result()
1799 }
1800 EthRequest::EthSignTypedData(addr, data) => {
1801 self.sign_typed_data(addr, data).await.to_rpc_result()
1802 }
1803 EthRequest::EthSignTypedDataV3(addr, data) => {
1804 self.sign_typed_data_v3(addr, data).await.to_rpc_result()
1805 }
1806 EthRequest::EthSignTypedDataV4(addr, data) => {
1807 self.sign_typed_data_v4(addr, &data).await.to_rpc_result()
1808 }
1809 EthRequest::EthSendRawTransaction(tx) => {
1810 self.send_raw_transaction(tx).await.to_rpc_result()
1811 }
1812 EthRequest::EthSendRawTransactionSync(tx, timeout_ms) => {
1813 self.send_raw_transaction_sync(tx, timeout_ms).await.to_rpc_result()
1814 }
1815 EthRequest::EthSendRawTransactionConditional(tx, condition) => {
1816 self.send_raw_transaction_conditional(tx, condition).await.to_rpc_result()
1817 }
1818 EthRequest::AnvilClassifyTransaction(tx) => {
1819 self.anvil_classify_transaction(tx).to_rpc_result()
1820 }
1821 EthRequest::EthCall(call, block, state_override, block_overrides) => self
1822 .call(call, block, EvmOverrides::new(state_override, block_overrides))
1823 .await
1824 .to_rpc_result(),
1825 EthRequest::EthCallMany(bundles, state_context, state_override) => {
1826 self.call_many(bundles, state_context, state_override).await.to_rpc_result()
1827 }
1828 EthRequest::EthCallBundle(bundle) => self.call_bundle(bundle).await.to_rpc_result(),
1829 EthRequest::EthSimulateV1(simulation, block) => {
1830 self.simulate_v1(simulation, block).await.to_rpc_result()
1831 }
1832 EthRequest::EthCreateAccessList(call, block, state_override) => {
1833 self.create_access_list(call, block, state_override).await.to_rpc_result()
1834 }
1835 EthRequest::EthEstimateGas(call, block, state_override, block_overrides) => self
1836 .estimate_gas(call, block, EvmOverrides::new(state_override, block_overrides))
1837 .await
1838 .to_rpc_result(),
1839 EthRequest::EthFillTransaction(request) => {
1840 self.fill_transaction(request).await.to_rpc_result()
1841 }
1842 EthRequest::EthGetRawTransactionByHash(hash) => {
1843 self.raw_transaction(hash).await.to_rpc_result()
1844 }
1845 EthRequest::GetBlobByHash(hash) => {
1846 self.anvil_get_blob_by_versioned_hash(hash).to_rpc_result()
1847 }
1848 EthRequest::GetBlobByTransactionHash(hash) => {
1849 self.anvil_get_blob_by_tx_hash(hash).to_rpc_result()
1850 }
1851 EthRequest::GetGenesisTime(()) => self.anvil_get_genesis_time().to_rpc_result(),
1852 EthRequest::EthGetRawTransactionByBlockHashAndIndex(hash, index) => {
1853 self.raw_transaction_by_block_hash_and_index(hash, index).await.to_rpc_result()
1854 }
1855 EthRequest::EthGetRawTransactionByBlockNumberAndIndex(num, index) => {
1856 self.raw_transaction_by_block_number_and_index(num, index).await.to_rpc_result()
1857 }
1858 EthRequest::EthGetTransactionByBlockHashAndIndex(hash, index) => {
1859 self.transaction_by_block_hash_and_index(hash, index).await.to_rpc_result()
1860 }
1861 EthRequest::EthGetTransactionByBlockNumberAndIndex(num, index) => {
1862 self.transaction_by_block_number_and_index(num, index).await.to_rpc_result()
1863 }
1864 EthRequest::EthGetTransactionReceipt(tx) => {
1865 self.transaction_receipt(tx).await.to_rpc_result()
1866 }
1867 EthRequest::EthGetBlockReceipts(number) => {
1868 self.block_receipts(number).await.to_rpc_result()
1869 }
1870 EthRequest::EthGetUncleByBlockHashAndIndex(hash, index) => {
1871 self.uncle_by_block_hash_and_index(hash, index).await.to_rpc_result()
1872 }
1873 EthRequest::EthGetUncleByBlockNumberAndIndex(num, index) => {
1874 self.uncle_by_block_number_and_index(num, index).await.to_rpc_result()
1875 }
1876 EthRequest::EthGetLogs(filter) => self.logs(filter).await.to_rpc_result(),
1877 EthRequest::EthGetWork(_) => self.work().to_rpc_result(),
1878 EthRequest::EthSyncing(_) => self.syncing().to_rpc_result(),
1879 EthRequest::EthConfig(_) => self.config().to_rpc_result(),
1880 EthRequest::EthSubmitWork(nonce, pow, digest) => {
1881 self.submit_work(nonce, pow, digest).to_rpc_result()
1882 }
1883 EthRequest::EthSubmitHashRate(rate, id) => {
1884 self.submit_hashrate(rate, id).to_rpc_result()
1885 }
1886 EthRequest::EthFeeHistory(count, newest, reward_percentiles) => {
1887 self.fee_history(count, newest, reward_percentiles).await.to_rpc_result()
1888 }
1889 EthRequest::DebugGetRawTransaction(hash) => {
1891 self.raw_transaction(hash).await.to_rpc_result()
1892 }
1893 EthRequest::DebugGetRawReceipts(block) => {
1894 self.raw_receipts(block).await.to_rpc_result()
1895 }
1896 EthRequest::DebugGetRawTransactions(block) => {
1897 self.raw_transactions(block).await.to_rpc_result()
1898 }
1899 EthRequest::DebugGetRawHeader(block) => self.raw_header(block).await.to_rpc_result(),
1900 EthRequest::DebugGetRawBlock(block) => self.raw_block(block).await.to_rpc_result(),
1901 EthRequest::DebugClearTxpool(_) => self.debug_clear_txpool().await.to_rpc_result(),
1903 EthRequest::DebugTraceTransaction(tx, opts) => {
1905 self.debug_trace_transaction(tx, opts).await.to_rpc_result()
1906 }
1907 EthRequest::DebugTraceCall(tx, block, opts) => {
1909 self.debug_trace_call(tx, block, opts).await.to_rpc_result()
1910 }
1911 EthRequest::DebugCodeByHash(hash, block) => {
1912 self.debug_code_by_hash(hash, block).await.to_rpc_result()
1913 }
1914 EthRequest::DebugDbGet(key) => self.debug_db_get(key).await.to_rpc_result(),
1915 EthRequest::DebugGetModifiedAccountsByNumber(start_number, end_number) => {
1916 self.debug_get_modified_accounts_by_number(start_number, end_number).to_rpc_result()
1917 }
1918 EthRequest::DebugFreeOsMemory(()) => self.debug_free_os_memory().to_rpc_result(),
1919 EthRequest::DebugAccountInfoAt(block_id, tx_index, address) => {
1920 self.debug_account_info_at(block_id, tx_index, address).await.to_rpc_result()
1921 }
1922 EthRequest::DebugTraceBlock(rlp_block, opts) => {
1923 self.debug_trace_block(rlp_block, opts).await.to_rpc_result()
1924 }
1925 EthRequest::DebugTraceBlockByHash(block_hash, opts) => {
1926 self.debug_trace_block_by_hash(block_hash, opts).await.to_rpc_result()
1927 }
1928 EthRequest::DebugTraceBlockByNumber(block_number, opts) => {
1929 self.debug_trace_block_by_number(block_number, opts).await.to_rpc_result()
1930 }
1931 EthRequest::TraceCall(tx, trace_types, block) => {
1932 self.trace_call(tx, trace_types, block).await.to_rpc_result()
1933 }
1934 EthRequest::TraceTransaction(tx) => self.trace_transaction(tx).await.to_rpc_result(),
1935 EthRequest::TraceBlock(block) => self.trace_block(block).await.to_rpc_result(),
1936 EthRequest::TraceFilter(filter) => self.trace_filter(filter).await.to_rpc_result(),
1937 EthRequest::TraceGet(hash, indices) => {
1938 self.trace_get(hash, indices).await.to_rpc_result()
1939 }
1940 EthRequest::TraceReplayBlockTransactions(block, trace_types) => {
1941 self.trace_replay_block_transactions(block, trace_types).await.to_rpc_result()
1942 }
1943 EthRequest::TraceReplayTransaction(transaction, trace_types) => {
1944 self.trace_replay_transaction(transaction, trace_types).await.to_rpc_result()
1945 }
1946 EthRequest::TraceTransactionOpcodeGas(tx_hash) => {
1947 self.trace_transaction_opcode_gas(tx_hash).await.to_rpc_result()
1948 }
1949 EthRequest::TraceBlockOpcodeGas(block_id) => {
1950 self.trace_block_opcode_gas(block_id).await.to_rpc_result()
1951 }
1952 EthRequest::TraceRawTransaction(tx, trace_types, block_number) => {
1953 self.trace_raw_transaction(tx, trace_types, block_number).await.to_rpc_result()
1954 }
1955 EthRequest::TraceCallMany(calls, block_number) => {
1956 self.trace_call_many(calls, block_number).await.to_rpc_result()
1957 }
1958 EthRequest::ImpersonateAccount(addr) => {
1959 self.anvil_impersonate_account(addr).await.to_rpc_result()
1960 }
1961 EthRequest::StopImpersonatingAccount(addr) => {
1962 self.anvil_stop_impersonating_account(addr).await.to_rpc_result()
1963 }
1964 EthRequest::AutoImpersonateAccount(enable) => {
1965 self.anvil_auto_impersonate_account(enable).await.to_rpc_result()
1966 }
1967 EthRequest::ImpersonateSignature(signature, address) => {
1968 self.anvil_impersonate_signature(signature, address).await.to_rpc_result()
1969 }
1970 EthRequest::GetAutoMine(()) => self.anvil_get_auto_mine().to_rpc_result(),
1971 EthRequest::Mine(blocks, interval) => {
1972 self.anvil_mine(blocks, interval).await.to_rpc_result()
1973 }
1974 EthRequest::SetAutomine(enabled) => {
1975 self.anvil_set_auto_mine(enabled).await.to_rpc_result()
1976 }
1977 EthRequest::SetIntervalMining(interval) => {
1978 self.anvil_set_interval_mining(interval).to_rpc_result()
1979 }
1980 EthRequest::GetIntervalMining(()) => self.anvil_get_interval_mining().to_rpc_result(),
1981 EthRequest::DropTransaction(tx) => {
1982 self.anvil_drop_transaction(tx).await.to_rpc_result()
1983 }
1984 EthRequest::DropAllTransactions() => {
1985 self.anvil_drop_all_transactions().await.to_rpc_result()
1986 }
1987 EthRequest::Reset(fork) => {
1988 self.anvil_reset(fork.and_then(|p| p.params)).await.to_rpc_result()
1989 }
1990 EthRequest::SetBalance(addr, val) => {
1991 self.anvil_set_balance(addr, val).await.to_rpc_result()
1992 }
1993 EthRequest::AddBalance(addr, val) => {
1994 self.anvil_add_balance(addr, val).await.to_rpc_result()
1995 }
1996 EthRequest::DealERC20(addr, token_addr, val) => {
1997 self.anvil_deal_erc20(addr, token_addr, val).await.to_rpc_result()
1998 }
1999 EthRequest::DealTIP20(addr, token_addr, val) => {
2000 self.anvil_deal_tip20(addr, token_addr, val).await.to_rpc_result()
2001 }
2002 EthRequest::SetERC20Allowance(owner, spender, token_addr, val) => self
2003 .anvil_set_erc20_allowance(owner, spender, token_addr, val)
2004 .await
2005 .to_rpc_result(),
2006 EthRequest::SetCode(addr, code) => {
2007 self.anvil_set_code(addr, code).await.to_rpc_result()
2008 }
2009 EthRequest::SetNonce(addr, nonce) => {
2010 self.anvil_set_nonce(addr, nonce).await.to_rpc_result()
2011 }
2012 EthRequest::SetStorageAt(addr, slot, val) => {
2013 self.anvil_set_storage_at(addr, slot, val).await.to_rpc_result()
2014 }
2015 EthRequest::SetCoinbase(addr) => self.anvil_set_coinbase(addr).await.to_rpc_result(),
2016 EthRequest::SetNextBlockPrevRandao(prevrandao) => {
2017 self.anvil_set_next_block_prevrandao(prevrandao).await.to_rpc_result()
2018 }
2019 EthRequest::SetChainId(id) => self.anvil_set_chain_id(id).await.to_rpc_result(),
2020 EthRequest::SetLogging(log) => self.anvil_set_logging(log).await.to_rpc_result(),
2021 EthRequest::SetMinGasPrice(gas) => {
2022 self.anvil_set_min_gas_price(gas).await.to_rpc_result()
2023 }
2024 EthRequest::SetNextBlockBaseFeePerGas(gas) => {
2025 self.anvil_set_next_block_base_fee_per_gas(gas).await.to_rpc_result()
2026 }
2027 EthRequest::DumpState(preserve_historical_states) => self
2028 .anvil_dump_state(preserve_historical_states.and_then(|s| s.params))
2029 .await
2030 .to_rpc_result(),
2031 EthRequest::LoadState(buf) => self.anvil_load_state(buf).await.to_rpc_result(),
2032 EthRequest::NodeInfo(_) => self.anvil_node_info().await.to_rpc_result(),
2033 EthRequest::AnvilMetadata(_) => self.anvil_metadata().await.to_rpc_result(),
2034 EthRequest::EvmSnapshot(_) => self.evm_snapshot().await.to_rpc_result(),
2035 EthRequest::EvmRevert(id) => self.evm_revert(id).await.to_rpc_result(),
2036 EthRequest::EvmIncreaseTime(time) => self.evm_increase_time(time).await.to_rpc_result(),
2037 EthRequest::EvmSetNextBlockTimeStamp(time) => {
2038 if time >= U256::from(u64::MAX) {
2039 return ResponseResult::Error(RpcError::invalid_params(
2040 "The timestamp is too big",
2041 ));
2042 }
2043 let time = time.to::<u64>();
2044 self.evm_set_next_block_timestamp(time).to_rpc_result()
2045 }
2046 EthRequest::EvmSetTime(timestamp) => {
2047 if timestamp >= U256::from(u64::MAX) {
2048 return ResponseResult::Error(RpcError::invalid_params(
2049 "The timestamp is too big",
2050 ));
2051 }
2052 let raw = timestamp.to::<u64>();
2056 let time = if raw > 1_000_000_000_000 {
2057 Duration::from_millis(raw).as_secs()
2058 } else {
2059 raw
2060 };
2061 self.evm_set_time(time).to_rpc_result()
2062 }
2063 EthRequest::EvmSetBlockGasLimit(gas_limit) => {
2064 self.evm_set_block_gas_limit(gas_limit).to_rpc_result()
2065 }
2066 EthRequest::EvmSetBlockTimeStampInterval(time) => {
2067 self.evm_set_block_timestamp_interval(time).to_rpc_result()
2068 }
2069 EthRequest::EvmRemoveBlockTimeStampInterval(()) => {
2070 self.evm_remove_block_timestamp_interval().to_rpc_result()
2071 }
2072 EthRequest::EvmMine(mine) => {
2073 self.evm_mine(mine.and_then(|p| p.params)).await.to_rpc_result()
2074 }
2075 EthRequest::EvmMineDetailed(mine) => {
2076 self.evm_mine_detailed(mine.and_then(|p| p.params)).await.to_rpc_result()
2077 }
2078 EthRequest::SetRpcUrl(url) => self.anvil_set_rpc_url(url).await.to_rpc_result(),
2079 EthRequest::EthSendUnsignedTransaction(tx) => {
2080 self.eth_send_unsigned_transaction(*tx).await.to_rpc_result()
2081 }
2082 EthRequest::EthNewFilter(filter) => self.new_filter(filter).await.to_rpc_result(),
2083 EthRequest::EthGetFilterChanges(id) => self.get_filter_changes(&id).await,
2084 EthRequest::EthNewBlockFilter(_) => self.new_block_filter().await.to_rpc_result(),
2085 EthRequest::EthNewPendingTransactionFilter(full) => {
2086 self.new_pending_transaction_filter(full.unwrap_or(false)).await.to_rpc_result()
2087 }
2088 EthRequest::EthGetFilterLogs(id) => self.get_filter_logs(&id).await.to_rpc_result(),
2089 EthRequest::EthUninstallFilter(id) => self.uninstall_filter(&id).await.to_rpc_result(),
2090 EthRequest::TxPoolStatus(_) => self.txpool_status().await.to_rpc_result(),
2091 EthRequest::TxPoolInspect(_) => self.txpool_inspect().await.to_rpc_result(),
2092 EthRequest::TxPoolContent(_) => self.txpool_content().await.to_rpc_result(),
2093 EthRequest::TxPoolContentFrom(from) => {
2094 self.txpool_content_from(from).await.to_rpc_result()
2095 }
2096 EthRequest::ErigonGetHeaderByNumber(num) => {
2097 self.erigon_get_header_by_number(num).await.to_rpc_result()
2098 }
2099 EthRequest::OtsGetApiLevel(_) => self.ots_get_api_level().await.to_rpc_result(),
2100 EthRequest::OtsGetInternalOperations(hash) => {
2101 self.ots_get_internal_operations(hash).await.to_rpc_result()
2102 }
2103 EthRequest::OtsHasCode(addr, num) => self.ots_has_code(addr, num).await.to_rpc_result(),
2104 EthRequest::OtsTraceTransaction(hash) => {
2105 self.ots_trace_transaction(hash).await.to_rpc_result()
2106 }
2107 EthRequest::OtsGetTransactionError(hash) => {
2108 self.ots_get_transaction_error(hash).await.to_rpc_result()
2109 }
2110 EthRequest::OtsGetBlockDetails(num) => {
2111 self.ots_get_block_details(num).await.to_rpc_result()
2112 }
2113 EthRequest::OtsGetBlockDetailsByHash(hash) => {
2114 self.ots_get_block_details_by_hash(hash).await.to_rpc_result()
2115 }
2116 EthRequest::OtsGetBlockTransactions(num, page, page_size) => {
2117 self.ots_get_block_transactions(num, page, page_size).await.to_rpc_result()
2118 }
2119 EthRequest::OtsSearchTransactionsBefore(address, num, page_size) => {
2120 self.ots_search_transactions_before(address, num, page_size).await.to_rpc_result()
2121 }
2122 EthRequest::OtsSearchTransactionsAfter(address, num, page_size) => {
2123 self.ots_search_transactions_after(address, num, page_size).await.to_rpc_result()
2124 }
2125 EthRequest::OtsGetTransactionBySenderAndNonce(address, nonce) => {
2126 self.ots_get_transaction_by_sender_and_nonce(address, nonce).await.to_rpc_result()
2127 }
2128 EthRequest::EthGetTransactionBySenderAndNonce(sender, nonce) => {
2129 self.transaction_by_sender_and_nonce(sender, nonce).await.to_rpc_result()
2130 }
2131 EthRequest::OtsGetContractCreator(address) => {
2132 self.ots_get_contract_creator(address).await.to_rpc_result()
2133 }
2134 EthRequest::RemovePoolTransactions(address) => {
2135 self.anvil_remove_pool_transactions(address).await.to_rpc_result()
2136 }
2137 EthRequest::Reorg(reorg_options) => {
2138 self.anvil_reorg(reorg_options).await.to_rpc_result()
2139 }
2140 EthRequest::Rollback(depth) => self.anvil_rollback(depth).await.to_rpc_result(),
2141 EthRequest::SetFeeToken(user, token) => {
2142 self.anvil_set_fee_token(user, token).await.to_rpc_result()
2143 }
2144 EthRequest::SetValidatorFeeToken(validator, token) => {
2145 self.anvil_set_validator_fee_token(validator, token).await.to_rpc_result()
2146 }
2147 EthRequest::SetFeeAmmLiquidity(user_token, validator_token, amount) => self
2148 .anvil_set_fee_amm_liquidity(user_token, validator_token, amount)
2149 .await
2150 .to_rpc_result(),
2151 };
2152
2153 if let ResponseResult::Error(err) = &response {
2154 node_info!("\nRPC request failed:");
2155 node_info!(" Request: {:?}", request);
2156 node_info!(" Error: {}\n", err);
2157 }
2158
2159 response
2160 }
2161
2162 fn sign_request(&self, from: &Address, typed_tx: FoundryTypedTx) -> Result<FoundryTxEnvelope> {
2163 match typed_tx {
2164 #[cfg(feature = "optimism")]
2165 FoundryTypedTx::Deposit(_) => return Ok(build_impersonated(typed_tx)),
2166 _ => {
2167 for signer in self.signers.iter() {
2168 if signer.accounts().contains(from) {
2169 return signer.sign_transaction_from(from, typed_tx);
2170 }
2171 }
2172 }
2173 }
2174 Err(BlockchainError::NoSignerAvailable)
2175 }
2176
2177 async fn inner_raw_transaction(&self, hash: B256) -> Result<Option<Bytes>> {
2178 match self.pool.get_transaction(hash) {
2179 Some(tx) => Ok(Some(tx.transaction.encoded_2718().into())),
2180 None => match self.backend.transaction_by_hash(hash).await? {
2181 Some(tx) => Ok(Some(tx.as_ref().encoded_2718().into())),
2182 None => Ok(None),
2183 },
2184 }
2185 }
2186
2187 pub async fn balance(&self, address: Address, block_number: Option<BlockId>) -> Result<U256> {
2191 node_info!("eth_getBalance");
2192 let block_request = self.block_request(block_number).await?;
2193
2194 if let BlockRequest::Number(number) = block_request
2196 && let Some(fork) = self.get_fork()
2197 && fork.predates_fork(number)
2198 {
2199 return Ok(fork.get_balance(address, number).await?);
2200 }
2201
2202 self.backend.get_balance(address, Some(block_request)).await
2203 }
2204
2205 pub async fn get_account(
2209 &self,
2210 address: Address,
2211 block_number: Option<BlockId>,
2212 ) -> Result<TrieAccount> {
2213 node_info!("eth_getAccount");
2214 let block_request = self.block_request(block_number).await?;
2215
2216 if let BlockRequest::Number(number) = block_request
2218 && let Some(fork) = self.get_fork()
2219 && fork.predates_fork(number)
2220 {
2221 return Ok(fork.get_account(address, number).await?);
2222 }
2223
2224 self.backend.get_account_at_block(address, Some(block_request)).await
2225 }
2226
2227 pub async fn get_account_info(
2231 &self,
2232 address: Address,
2233 block_number: Option<BlockId>,
2234 ) -> Result<alloy_rpc_types::eth::AccountInfo> {
2235 node_info!("eth_getAccountInfo");
2236
2237 if let Some(fork) = self.get_fork() {
2238 let block_request = self.block_request(block_number).await?;
2239 if let BlockRequest::Number(number) = block_request {
2241 trace!(target: "node", "get_account_info: fork block {}, requested block {number}", fork.block_number());
2242 return if fork.predates_fork(number) {
2243 let balance = fork.get_balance(address, number).map_err(BlockchainError::from);
2246 let code = fork.get_code(address, number).map_err(BlockchainError::from);
2247 let nonce = self.get_transaction_count(address, Some(number.into()));
2248 let (balance, code, nonce) = try_join!(balance, code, nonce)?;
2249
2250 Ok(alloy_rpc_types::eth::AccountInfo { balance, nonce, code })
2251 } else {
2252 let account_info = self.backend.get_account(address).await?;
2255 let code = self.backend.get_code(address, Some(block_request)).await?;
2256 Ok(alloy_rpc_types::eth::AccountInfo {
2257 balance: account_info.balance,
2258 nonce: account_info.nonce,
2259 code,
2260 })
2261 };
2262 }
2263 }
2264
2265 let account = self.get_account(address, block_number);
2266 let code = self.get_code(address, block_number);
2267 let (account, code) = try_join!(account, code)?;
2268 Ok(alloy_rpc_types::eth::AccountInfo {
2269 balance: account.balance,
2270 nonce: account.nonce,
2271 code,
2272 })
2273 }
2274 pub async fn storage_at(
2278 &self,
2279 address: Address,
2280 index: U256,
2281 block_number: Option<BlockId>,
2282 ) -> Result<B256> {
2283 node_info!("eth_getStorageAt");
2284 let block_request = self.block_request(block_number).await?;
2285
2286 if let BlockRequest::Number(number) = block_request
2288 && let Some(fork) = self.get_fork()
2289 && fork.predates_fork(number)
2290 {
2291 return Ok(B256::from(
2292 fork.storage_at(address, index, Some(BlockNumber::Number(number))).await?,
2293 ));
2294 }
2295
2296 self.backend.storage_at(address, index, Some(block_request)).await
2297 }
2298
2299 pub async fn storage_values(
2303 &self,
2304 requests: HashMap<Address, Vec<B256>>,
2305 block_number: Option<BlockId>,
2306 ) -> Result<HashMap<Address, Vec<B256>>> {
2307 node_info!("eth_getStorageValues");
2308
2309 let total_slots: usize = requests.values().map(|s| s.len()).sum();
2310 if total_slots > 1024 {
2311 return Err(BlockchainError::RpcError(RpcError::invalid_params(format!(
2312 "total slot count {total_slots} exceeds limit 1024"
2313 ))));
2314 }
2315
2316 let block_request = self.block_request(block_number).await?;
2317
2318 if let BlockRequest::Number(number) = block_request
2320 && let Some(fork) = self.get_fork()
2321 && fork.predates_fork(number)
2322 {
2323 let mut result: HashMap<Address, Vec<B256>> = HashMap::default();
2324 for (address, slots) in requests {
2325 let mut values = Vec::with_capacity(slots.len());
2326 for slot in &slots {
2327 let val = fork
2328 .storage_at(address, (*slot).into(), Some(BlockNumber::Number(number)))
2329 .await?;
2330 values.push(B256::from(val));
2331 }
2332 result.insert(address, values);
2333 }
2334 return Ok(result);
2335 }
2336
2337 self.backend.storage_values(requests, Some(block_request)).await
2338 }
2339
2340 pub async fn block_by_number(&self, number: BlockNumber) -> Result<Option<AnyRpcBlock>> {
2344 node_info!("eth_getBlockByNumber");
2345 if number == BlockNumber::Pending {
2346 return Ok(Some(self.pending_block().await));
2347 }
2348
2349 self.backend.block_by_number(number).await
2350 }
2351
2352 pub async fn header_by_number(
2356 &self,
2357 number: BlockNumber,
2358 ) -> Result<Option<WithOtherFields<AnyRpcHeader>>> {
2359 node_info!("eth_getHeaderByNumber");
2360 if number == BlockNumber::Pending {
2361 let WithOtherFields { inner: block, other } = self.pending_block().await.0;
2362 return Ok(Some(WithOtherFields { inner: block.header, other }));
2363 }
2364
2365 Ok(self.backend.block_by_number(number).await?.map(|block| {
2366 let WithOtherFields { inner: block, other } = block.0;
2367 WithOtherFields { inner: block.header, other }
2368 }))
2369 }
2370
2371 pub async fn block_by_number_full(&self, number: BlockNumber) -> Result<Option<AnyRpcBlock>> {
2375 node_info!("eth_getBlockByNumber");
2376 if number == BlockNumber::Pending {
2377 return Ok(self.pending_block_full().await);
2378 }
2379 self.backend.block_by_number_full(number).await
2380 }
2381
2382 pub async fn block_access_list(&self, block_id: BlockId) -> Result<Option<serde_json::Value>> {
2386 node_info!("eth_getBlockAccessList");
2387 let block_request = self.block_request(Some(block_id)).await?;
2388 let BlockRequest::Number(number) = block_request else { return Ok(None) };
2389
2390 if let Some(fork) = self.get_fork()
2391 && fork.predates_fork_inclusive(number)
2392 {
2393 return Ok(fork.block_access_list(block_id).await?);
2394 }
2395
2396 Ok(None)
2397 }
2398
2399 pub async fn block_access_list_by_hash(
2403 &self,
2404 block_hash: B256,
2405 ) -> Result<Option<serde_json::Value>> {
2406 node_info!("eth_getBlockAccessListByBlockHash");
2407 if let Some(fork) = self.get_fork() {
2408 return Ok(fork.block_access_list_by_hash(block_hash).await?);
2409 }
2410 Ok(None)
2411 }
2412
2413 pub async fn block_access_list_by_number(
2417 &self,
2418 block_number: BlockNumber,
2419 ) -> Result<Option<serde_json::Value>> {
2420 node_info!("eth_getBlockAccessListByBlockNumber");
2421 let block_request = self.block_request(Some(BlockId::Number(block_number))).await?;
2422 let BlockRequest::Number(number) = block_request else { return Ok(None) };
2423
2424 if let Some(fork) = self.get_fork()
2425 && fork.predates_fork_inclusive(number)
2426 {
2427 return Ok(fork.block_access_list_by_number(block_number).await?);
2428 }
2429
2430 Ok(None)
2431 }
2432
2433 pub async fn block_access_list_raw(&self, block_id: BlockId) -> Result<Option<Bytes>> {
2437 node_info!("eth_getBlockAccessListRaw");
2438 let block_request = self.block_request(Some(block_id)).await?;
2439 let BlockRequest::Number(number) = block_request else { return Ok(None) };
2440
2441 if let Some(fork) = self.get_fork()
2442 && fork.predates_fork_inclusive(number)
2443 {
2444 return Ok(fork.block_access_list_raw(block_id).await?);
2445 }
2446
2447 Ok(None)
2448 }
2449
2450 pub async fn transaction_count(
2457 &self,
2458 address: Address,
2459 block_number: Option<BlockId>,
2460 ) -> Result<U256> {
2461 node_info!("eth_getTransactionCount");
2462 self.get_transaction_count(address, block_number).await.map(U256::from)
2463 }
2464
2465 pub async fn block_transaction_count_by_number(
2469 &self,
2470 block_number: BlockNumber,
2471 ) -> Result<Option<U256>> {
2472 node_info!("eth_getBlockTransactionCountByNumber");
2473 let block_request = self.block_request(Some(block_number.into())).await?;
2474 if let BlockRequest::Pending(txs) = block_request {
2475 let block = self.backend.pending_block(txs).await;
2476 return Ok(Some(U256::from(block.block.body.transactions.len())));
2477 }
2478 let block = self.backend.block_by_number(block_number).await?;
2479 let txs = block.map(|b| match b.transactions() {
2480 BlockTransactions::Full(txs) => U256::from(txs.len()),
2481 BlockTransactions::Hashes(txs) => U256::from(txs.len()),
2482 BlockTransactions::Uncle => U256::from(0),
2483 });
2484 Ok(txs)
2485 }
2486
2487 pub async fn get_code(&self, address: Address, block_number: Option<BlockId>) -> Result<Bytes> {
2491 node_info!("eth_getCode");
2492 let block_request = self.block_request(block_number).await?;
2493 if let BlockRequest::Number(number) = block_request
2495 && let Some(fork) = self.get_fork()
2496 && fork.predates_fork(number)
2497 {
2498 return Ok(fork.get_code(address, number).await?);
2499 }
2500 self.backend.get_code(address, Some(block_request)).await
2501 }
2502
2503 pub async fn get_proof(
2508 &self,
2509 address: Address,
2510 keys: Vec<B256>,
2511 block_number: Option<BlockId>,
2512 ) -> Result<EIP1186AccountProofResponse> {
2513 node_info!("eth_getProof");
2514 let block_request = self.block_request(block_number).await?;
2515
2516 if let BlockRequest::Number(number) = block_request
2519 && let Some(fork) = self.get_fork()
2520 && fork.predates_fork_inclusive(number)
2521 {
2522 return Ok(fork.get_proof(address, keys, Some(number.into())).await?);
2523 }
2524
2525 let proof = self.backend.prove_account_at(address, keys, Some(block_request)).await?;
2526 Ok(proof)
2527 }
2528
2529 pub async fn sign_transaction(
2533 &self,
2534 request: WithOtherFields<TransactionRequest>,
2535 ) -> Result<String> {
2536 node_info!("eth_signTransaction");
2537
2538 let from = request.from.map(Ok).unwrap_or_else(|| {
2539 self.accounts()?.first().copied().ok_or(BlockchainError::NoSignerAvailable)
2540 })?;
2541
2542 let (nonce, _) = self.request_nonce(&request, from).await?;
2543
2544 let request = self.build_tx_request(request, nonce).await?;
2545
2546 let signed_transaction = self.sign_request(&from, request)?.encoded_2718();
2547 Ok(alloy_primitives::hex::encode_prefixed(signed_transaction))
2548 }
2549
2550 pub async fn send_transaction(
2554 &self,
2555 request: WithOtherFields<TransactionRequest>,
2556 ) -> Result<TxHash> {
2557 node_info!("eth_sendTransaction");
2558
2559 let from = request.from.map(Ok).unwrap_or_else(|| {
2560 self.accounts()?.first().copied().ok_or(BlockchainError::NoSignerAvailable)
2561 })?;
2562 let (nonce, on_chain_nonce) = self.request_nonce(&request, from).await?;
2563
2564 let typed_tx = self.build_tx_request(request, nonce).await?;
2565
2566 let pending_transaction = if self.is_impersonated(from) {
2568 let transaction = sign::build_impersonated(typed_tx);
2569 self.ensure_typed_transaction_supported(&transaction)?;
2570 trace!(target : "node", ?from, "eth_sendTransaction: impersonating");
2571 PendingTransaction::with_impersonated(transaction, from)
2572 } else {
2573 let transaction = self.sign_request(&from, typed_tx)?;
2574 self.ensure_typed_transaction_supported(&transaction)?;
2575 PendingTransaction::new(transaction)?
2576 };
2577 self.backend.validate_pool_transaction(&pending_transaction).await?;
2579
2580 let (requires, provides) = nonce_markers(&pending_transaction, nonce, on_chain_nonce, from);
2581
2582 self.add_pending_transaction(pending_transaction, requires, provides)
2583 }
2584
2585 pub async fn resend_transaction(
2589 &self,
2590 mut request: WithOtherFields<TransactionRequest>,
2591 gas_price: Option<U256>,
2592 gas_limit: Option<U64>,
2593 ) -> Result<TxHash> {
2594 node_info!("eth_resend");
2595
2596 let from = request.from.map(Ok).unwrap_or_else(|| {
2597 self.accounts()?.first().copied().ok_or(BlockchainError::NoSignerAvailable)
2598 })?;
2599 let nonce = request.nonce.ok_or_else(|| {
2600 BlockchainError::InvalidTransactionRequest(
2601 "missing transaction nonce in transaction spec".to_string(),
2602 )
2603 })?;
2604
2605 if !self.pool.contains_sender_nonce(from, nonce) {
2606 return Err(BlockchainError::TransactionNotFound);
2607 }
2608
2609 if let Some(gas_price) = gas_price.filter(|gas_price| !gas_price.is_zero()) {
2610 request.set_gas_price(gas_price.saturating_to());
2611 }
2612
2613 if let Some(gas_limit) = gas_limit.filter(|gas_limit| *gas_limit != U64::ZERO) {
2614 request.set_gas_limit(gas_limit.to());
2615 }
2616
2617 let typed_tx = self.build_tx_request(request, nonce).await?;
2618
2619 let pending_transaction = if self.is_impersonated(from) {
2620 let transaction = sign::build_impersonated(typed_tx);
2621 self.ensure_typed_transaction_supported(&transaction)?;
2622 trace!(target : "node", ?from, "eth_resend: impersonating");
2623 PendingTransaction::with_impersonated(transaction, from)
2624 } else {
2625 let transaction = self.sign_request(&from, typed_tx)?;
2626 self.ensure_typed_transaction_supported(&transaction)?;
2627 PendingTransaction::new(transaction)?
2628 };
2629
2630 self.backend.validate_pool_transaction(&pending_transaction).await?;
2631
2632 let on_chain_nonce = self.backend.current_nonce(from).await?;
2633 let (requires, provides) = nonce_markers(&pending_transaction, nonce, on_chain_nonce, from);
2634
2635 self.add_pending_transaction(pending_transaction, requires, provides)
2636 }
2637
2638 async fn await_transaction_inclusion(&self, hash: TxHash) -> Result<FoundryTxReceipt> {
2640 let mut stream = self.new_block_notifications();
2641 if let Some(receipt) = self.backend.transaction_receipt(hash).await? {
2643 return Ok(receipt);
2644 }
2645 while let Some(notification) = stream.next().await {
2646 if let Some(new_block) = notification.as_new_block()
2647 && let Some(block) = self.backend.get_block_by_hash(new_block.hash)
2648 && block.body.transactions.iter().any(|tx| tx.hash() == hash)
2649 && let Some(receipt) = self.backend.transaction_receipt(hash).await?
2650 {
2651 return Ok(receipt);
2652 }
2653 }
2654
2655 Err(BlockchainError::Message("Failed to await transaction inclusion".to_string()))
2656 }
2657
2658 fn transaction_confirmation_timeout(timeout_ms: Option<u64>) -> Duration {
2659 const TIMEOUT_DURATION: Duration = Duration::from_secs(30);
2660 timeout_ms
2661 .filter(|timeout_ms| *timeout_ms > 0)
2662 .map(Duration::from_millis)
2663 .map(|timeout| timeout.min(TIMEOUT_DURATION))
2664 .unwrap_or(TIMEOUT_DURATION)
2665 }
2666
2667 async fn check_transaction_inclusion(
2669 &self,
2670 hash: TxHash,
2671 timeout_ms: Option<u64>,
2672 ) -> Result<FoundryTxReceipt> {
2673 let timeout_duration = Self::transaction_confirmation_timeout(timeout_ms);
2674 tokio::time::timeout(timeout_duration, self.await_transaction_inclusion(hash))
2675 .await
2676 .unwrap_or_else(|_elapsed| {
2677 Err(BlockchainError::TransactionConfirmationTimeout {
2678 hash,
2679 duration: timeout_duration,
2680 })
2681 })
2682 }
2683
2684 pub async fn send_transaction_sync(
2688 &self,
2689 request: WithOtherFields<TransactionRequest>,
2690 ) -> Result<FoundryTxReceipt> {
2691 node_info!("eth_sendTransactionSync");
2692 let hash = self.send_transaction(request).await?;
2693
2694 let receipt = self.check_transaction_inclusion(hash, None).await?;
2695
2696 Ok(receipt)
2697 }
2698
2699 pub async fn send_raw_transaction(&self, tx: Bytes) -> Result<TxHash> {
2703 node_info!("eth_sendRawTransaction");
2704 let mut data = tx.as_ref();
2705 if data.is_empty() {
2706 return Err(BlockchainError::EmptyRawTransactionData);
2707 }
2708
2709 let transaction = FoundryTxEnvelope::decode_2718(&mut data)
2710 .map_err(|_| BlockchainError::FailedToDecodeSignedTransaction)?;
2711
2712 self.ensure_typed_transaction_supported(&transaction)?;
2713
2714 if self.backend.is_tempo() && TempoHardfork::from(self.backend.hardfork()).is_t5() {
2715 let classification = classify_payment_lane(tx.as_ref());
2716 trace!(target: "node", tx = ?transaction.hash(), ?classification, "classified transaction lane");
2717 }
2718
2719 let pending_transaction = PendingTransaction::new(transaction)?;
2720
2721 self.backend.validate_pool_transaction(&pending_transaction).await?;
2723
2724 let from = *pending_transaction.sender();
2725 let priority = self.transaction_priority(&pending_transaction.transaction);
2726
2727 let (requires, provides) = if let Some((requires, provides)) =
2729 tempo_parallel_nonce_markers(&pending_transaction)
2730 {
2731 (requires, provides)
2732 } else {
2733 let on_chain_nonce = self.backend.current_nonce(from).await?;
2734 let nonce = pending_transaction.transaction.nonce();
2735 (required_marker(nonce, on_chain_nonce, from), vec![to_marker(nonce, from)])
2736 };
2737
2738 let pool_transaction =
2739 PoolTransaction { requires, provides, pending_transaction, priority };
2740
2741 let tx = self.pool.add_transaction(pool_transaction)?;
2742 trace!(target: "node", "Added transaction: [{:?}] sender={:?}", tx.hash(), from);
2743 Ok(*tx.hash())
2744 }
2745
2746 pub async fn send_raw_transaction_conditional(
2750 &self,
2751 tx: Bytes,
2752 _condition: TransactionConditional,
2753 ) -> Result<TxHash> {
2754 node_info!("eth_sendRawTransactionConditional");
2755 self.send_raw_transaction(tx).await
2756 }
2757
2758 pub fn anvil_classify_transaction(&self, tx: Bytes) -> Result<PaymentLaneClassification> {
2760 node_info!("anvil_classifyTransaction");
2761 let mut data = tx.as_ref();
2762 if data.is_empty() {
2763 return Err(BlockchainError::EmptyRawTransactionData);
2764 }
2765
2766 FoundryTxEnvelope::decode_2718(&mut data)
2767 .map_err(|_| BlockchainError::FailedToDecodeSignedTransaction)?;
2768
2769 Ok(self.classify_transaction_lane(tx.as_ref()))
2770 }
2771
2772 fn classify_transaction_lane(&self, raw: &[u8]) -> PaymentLaneClassification {
2773 if !self.backend.is_tempo() {
2774 return PaymentLaneClassification::general(PaymentLaneReason::NotTempo);
2775 }
2776
2777 if !TempoHardfork::from(self.backend.hardfork()).is_t5() {
2778 return PaymentLaneClassification::general(PaymentLaneReason::T5NotActive);
2779 }
2780
2781 classify_payment_lane(raw)
2782 }
2783
2784 pub async fn send_raw_transaction_sync(
2788 &self,
2789 tx: Bytes,
2790 timeout_ms: Option<u64>,
2791 ) -> Result<FoundryTxReceipt> {
2792 node_info!("eth_sendRawTransactionSync");
2793
2794 let hash = self.send_raw_transaction(tx).await?;
2795 let receipt = self.check_transaction_inclusion(hash, timeout_ms).await?;
2796
2797 Ok(receipt)
2798 }
2799
2800 pub async fn call(
2804 &self,
2805 request: WithOtherFields<TransactionRequest>,
2806 block_number: Option<BlockId>,
2807 overrides: EvmOverrides,
2808 ) -> Result<Bytes> {
2809 node_info!("eth_call");
2810 let block_request = self.block_request(block_number).await?;
2811 if let BlockRequest::Number(number) = block_request
2813 && let Some(fork) = self.get_fork()
2814 && fork.predates_fork(number)
2815 {
2816 if overrides.has_state() || overrides.has_block() {
2817 return Err(BlockchainError::EvmOverrideError(
2818 "not available on past forked blocks".to_string(),
2819 ));
2820 }
2821 return Ok(fork.call(&request, Some(number.into())).await?);
2822 }
2823
2824 let fees = FeeDetails::new(
2825 request.gas_price,
2826 request.max_fee_per_gas,
2827 request.max_priority_fee_per_gas,
2828 request.max_fee_per_blob_gas,
2829 )?
2830 .or_zero_fees();
2831 self.on_blocking_task(|this| async move {
2834 let (exit, out, gas, _) =
2835 this.backend.call(request, fees, Some(block_request), overrides).await?;
2836 trace!(target : "node", "Call status {:?}, gas {}", exit, gas);
2837
2838 ensure_return_ok(exit, &out)
2839 })
2840 .await
2841 }
2842
2843 pub async fn call_many(
2844 &self,
2845 bundles: Vec<Bundle<WithOtherFields<TransactionRequest>>>,
2846 state_context: Option<StateContext>,
2847 state_override: Option<StateOverride>,
2848 ) -> Result<Vec<Vec<EthCallResponse>>> {
2849 node_info!("eth_callMany");
2850 let StateContext { transaction_index, block_number } = state_context.unwrap_or_default();
2851 if transaction_index.is_some_and(|index| index.index().is_some()) {
2852 return Err(BlockchainError::RpcError(RpcError::invalid_params(
2853 "transactionIndex is not supported for eth_callMany yet".to_string(),
2854 )));
2855 }
2856
2857 let block_request = self.block_request(block_number).await?;
2858 if let BlockRequest::Number(number) = block_request
2859 && let Some(fork) = self.get_fork()
2860 && fork.predates_fork(number)
2861 {
2862 return Ok(fork
2863 .call_many(
2864 bundles,
2865 Some(StateContext { transaction_index, block_number: Some(number.into()) }),
2866 state_override,
2867 )
2868 .await?);
2869 }
2870
2871 self.on_blocking_task(|this| async move {
2872 this.backend.call_many(bundles, Some(block_request), state_override).await
2873 })
2874 .await
2875 }
2876
2877 pub async fn call_bundle(&self, bundle: EthCallBundle) -> Result<EthCallBundleResponse> {
2881 node_info!("eth_callBundle");
2882 if bundle.txs.is_empty() {
2883 return Err(BlockchainError::RpcError(RpcError::invalid_params(
2884 "bundle missing txs".to_string(),
2885 )));
2886 }
2887 if bundle.block_number == 0 {
2888 return Err(BlockchainError::RpcError(RpcError::invalid_params(
2889 "bundle missing blockNumber".to_string(),
2890 )));
2891 }
2892
2893 let block_request = self.block_request(Some(bundle.state_block_number.into())).await?;
2894 if let BlockRequest::Number(number) = block_request
2895 && let Some(fork) = self.get_fork()
2896 && fork.predates_fork(number)
2897 {
2898 return Ok(fork.call_bundle(bundle).await?);
2899 }
2900
2901 let transactions = bundle
2902 .txs
2903 .iter()
2904 .map(|raw| {
2905 let mut data = raw.as_ref();
2906 if data.is_empty() {
2907 return Err(BlockchainError::EmptyRawTransactionData);
2908 }
2909 let transaction = FoundryTxEnvelope::decode_2718(&mut data)
2910 .map_err(|_| BlockchainError::FailedToDecodeSignedTransaction)?;
2911 self.ensure_typed_transaction_supported(&transaction)?;
2912 PendingTransaction::new(transaction).map_err(Into::into)
2913 })
2914 .collect::<Result<Vec<_>>>()?;
2915
2916 self.on_blocking_task(|this| async move {
2917 this.backend.call_bundle(bundle, transactions, Some(block_request)).await
2918 })
2919 .await
2920 }
2921
2922 pub async fn simulate_v1(
2923 &self,
2924 request: SimulatePayload,
2925 block_number: Option<BlockId>,
2926 ) -> Result<Vec<SimulatedBlock<AnyRpcBlock>>> {
2927 node_info!("eth_simulateV1");
2928 if request.block_state_calls.is_empty() {
2929 return Err(BlockchainError::RpcError(RpcError::invalid_params("empty input")));
2930 }
2931 if request.block_state_calls.len() > MAX_SIMULATE_BLOCKS as usize {
2932 return Err(BlockchainError::RpcError(RpcError {
2933 code: ErrorCode::ServerError(-38026),
2934 message: "too many blocks".into(),
2935 data: None,
2936 }));
2937 }
2938 let block_request =
2939 self.block_request(block_number).await.map_err(|error| match error {
2940 BlockchainError::BlockOutOfRange(_, _) | BlockchainError::BlockNotFound => {
2941 BlockchainError::RpcError(RpcError {
2942 code: ErrorCode::ServerError(-32000),
2943 message: "header not found".into(),
2944 data: None,
2945 })
2946 }
2947 error => error,
2948 })?;
2949 if let BlockRequest::Number(number) = block_request
2951 && let Some(fork) = self.get_fork()
2952 && fork.predates_fork(number)
2953 {
2954 return Ok(fork.simulate_v1(&request, Some(number.into())).await?);
2955 }
2956
2957 self.on_blocking_task(|this| async move {
2960 let simulated_blocks = this.backend.simulate(request, Some(block_request)).await?;
2961 trace!(target : "node", "Simulate status {:?}", simulated_blocks);
2962
2963 Ok(simulated_blocks)
2964 })
2965 .await
2966 }
2967
2968 pub async fn create_access_list(
2982 &self,
2983 mut request: WithOtherFields<TransactionRequest>,
2984 block_number: Option<BlockId>,
2985 state_override: Option<StateOverride>,
2986 ) -> Result<AccessListResult> {
2987 node_info!("eth_createAccessList");
2988 let block_request = self.block_request(block_number).await?;
2989 if let BlockRequest::Number(number) = block_request
2991 && let Some(fork) = self.get_fork()
2992 && fork.predates_fork(number)
2993 {
2994 if state_override.is_some() {
2995 return Err(BlockchainError::EvmOverrideError(
2996 "not available on past forked blocks".to_string(),
2997 ));
2998 }
2999 return Ok(fork.create_access_list(&request, Some(number.into())).await?);
3000 }
3001
3002 self.backend
3003 .with_database_at(Some(block_request), |state, block_env| {
3004 let mut cache_db = CacheDB::new(state);
3005 if let Some(state_override) = state_override {
3006 apply_state_overrides(state_override.into_iter().collect(), &mut cache_db)?;
3007 }
3008
3009 let (_, _, _, access_list) = self.backend.build_access_list_with_state(
3010 &cache_db,
3011 request.clone(),
3012 FeeDetails::zero(),
3013 block_env.clone(),
3014 )?;
3015
3016 request.access_list = Some(access_list.clone());
3021 let (exit, _, gas_used, _) = self.backend.call_with_state(
3022 &cache_db,
3023 request,
3024 FeeDetails::zero(),
3025 block_env,
3026 )?;
3027
3028 Ok(AccessListResult {
3029 access_list,
3030 gas_used: U256::from(gas_used),
3031 error: execution_error(exit),
3032 })
3033 })
3034 .await?
3035 }
3036
3037 pub async fn estimate_gas(
3042 &self,
3043 request: WithOtherFields<TransactionRequest>,
3044 block_number: Option<BlockId>,
3045 overrides: EvmOverrides,
3046 ) -> Result<U256> {
3047 node_info!("eth_estimateGas");
3048 self.do_estimate_gas(
3049 request,
3050 block_number.or_else(|| Some(BlockNumber::Pending.into())),
3051 overrides,
3052 )
3053 .await
3054 .map(U256::from)
3055 }
3056
3057 pub async fn fill_transaction(
3064 &self,
3065 mut request: WithOtherFields<TransactionRequest>,
3066 ) -> Result<FillTransaction<AnyRpcTransaction>> {
3067 node_info!("eth_fillTransaction");
3068
3069 let from = match request.as_ref().from() {
3070 Some(from) => from,
3071 None => self.accounts()?.first().copied().ok_or(BlockchainError::NoSignerAvailable)?,
3072 };
3073
3074 let nonce = if let Some(nonce) = request.as_ref().nonce() {
3075 nonce
3076 } else {
3077 self.request_nonce(&request, from).await?.0
3078 };
3079
3080 if request.as_ref().gas_limit().is_none() {
3082 let estimated_gas =
3083 self.estimate_gas(request.clone(), None, EvmOverrides::default()).await?;
3084 request.as_mut().set_gas_limit(estimated_gas.to());
3085 }
3086
3087 let typed_tx = self.build_tx_request(request, nonce).await?;
3088 let tx = build_impersonated(typed_tx);
3089
3090 let raw = tx.encoded_2718().into();
3091
3092 let mut tx =
3093 transaction_build(None, MaybeImpersonatedTransaction::new(tx), None, None, None);
3094
3095 tx.0.inner.inner = Recovered::new_unchecked(tx.0.inner.inner.into_inner(), from);
3098
3099 Ok(FillTransaction { raw, tx })
3100 }
3101
3102 pub fn anvil_get_blob_by_tx_hash(&self, hash: B256) -> Result<Option<Vec<Blob>>> {
3104 node_info!("anvil_getBlobsByTransactionHash");
3105 Ok(self.backend.get_blob_by_tx_hash(hash)?)
3106 }
3107
3108 pub async fn transaction_by_hash(&self, hash: B256) -> Result<Option<AnyRpcTransaction>> {
3115 node_info!("eth_getTransactionByHash");
3116 let mut tx =
3117 self.pool.get_transaction(hash).map(|pending| self.build_pool_transaction(pending));
3118 if tx.is_none() {
3119 tx = self.backend.transaction_by_hash(hash).await?
3120 }
3121
3122 Ok(tx)
3123 }
3124
3125 fn build_pool_transaction(
3126 &self,
3127 pending: PendingTransaction<FoundryTxEnvelope>,
3128 ) -> AnyRpcTransaction {
3129 let from = *pending.sender();
3130 let tx = transaction_build(
3131 Some(*pending.hash()),
3132 pending.transaction,
3133 None,
3134 None,
3135 Some(self.backend.base_fee()),
3136 );
3137
3138 let WithOtherFields { inner: mut tx, other } = tx.0;
3139 tx.inner = Recovered::new_unchecked(tx.inner.into_inner(), from);
3142
3143 AnyRpcTransaction(WithOtherFields { inner: tx, other })
3144 }
3145
3146 pub async fn pending_transactions(&self) -> Result<Vec<AnyRpcTransaction>> {
3150 node_info!("eth_pendingTransactions");
3151 Ok(self
3152 .pool
3153 .ready_transactions()
3154 .map(|pending| self.build_pool_transaction(pending.pending_transaction.clone()))
3155 .collect())
3156 }
3157
3158 pub async fn transaction_by_sender_and_nonce(
3165 &self,
3166 sender: Address,
3167 nonce: U256,
3168 ) -> Result<Option<AnyRpcTransaction>> {
3169 node_info!("eth_getTransactionBySenderAndNonce");
3170
3171 for pending_tx in self.pool.ready_transactions().chain(self.pool.pending_transactions()) {
3173 if U256::from(pending_tx.pending_transaction.nonce()) == nonce
3174 && *pending_tx.pending_transaction.sender() == sender
3175 {
3176 let tx = transaction_build(
3177 Some(*pending_tx.pending_transaction.hash()),
3178 pending_tx.pending_transaction.transaction.clone(),
3179 None,
3180 None,
3181 Some(self.backend.base_fee()),
3182 );
3183
3184 let WithOtherFields { inner: mut tx, other } = tx.0;
3185 let from = *pending_tx.pending_transaction.sender();
3188 tx.inner = Recovered::new_unchecked(tx.inner.into_inner(), from);
3189
3190 return Ok(Some(AnyRpcTransaction(WithOtherFields { inner: tx, other })));
3191 }
3192 }
3193
3194 let highest_nonce = self.transaction_count(sender, None).await?.saturating_to::<u64>();
3195 let target_nonce = nonce.saturating_to::<u64>();
3196
3197 if target_nonce >= highest_nonce {
3199 return Ok(None);
3200 }
3201
3202 let latest_block = self.backend.best_number();
3204 if latest_block == 0 {
3205 return Ok(None);
3206 }
3207
3208 let mut low = 1u64;
3210 let mut high = latest_block;
3211
3212 while low <= high {
3213 let mid = low + (high - low) / 2;
3214 let mid_nonce =
3215 self.transaction_count(sender, Some(mid.into())).await?.saturating_to::<u64>();
3216
3217 if mid_nonce > target_nonce {
3218 high = mid - 1;
3219 } else {
3220 low = mid + 1;
3221 }
3222 }
3223
3224 let target_block = low;
3226 if target_block <= latest_block
3227 && let Some(txs) =
3228 self.backend.mined_transactions_by_block_number(target_block.into()).await
3229 {
3230 for tx in txs {
3231 if tx.from() == sender && tx.nonce() == target_nonce {
3232 return Ok(Some(tx));
3233 }
3234 }
3235 }
3236
3237 Ok(None)
3238 }
3239
3240 pub async fn transaction_receipt(&self, hash: B256) -> Result<Option<FoundryTxReceipt>> {
3244 node_info!("eth_getTransactionReceipt");
3245 self.backend.transaction_receipt(hash).await
3246 }
3247
3248 pub async fn block_receipts(&self, number: BlockId) -> Result<Option<Vec<FoundryTxReceipt>>> {
3252 node_info!("eth_getBlockReceipts");
3253 self.backend.block_receipts(number).await
3254 }
3255
3256 pub async fn logs(&self, filter: Filter) -> Result<Vec<Log>> {
3260 node_info!("eth_getLogs");
3261 self.backend.logs(filter).await
3262 }
3263
3264 pub async fn new_filter(&self, filter: Filter) -> Result<String> {
3268 node_info!("eth_newFilter");
3269 let historic = if filter.block_option.get_from_block().is_some() {
3272 self.backend.logs(filter.clone()).await?
3273 } else {
3274 vec![]
3275 };
3276 let filter = EthFilter::Logs(Box::new(LogsFilter {
3277 blocks: self.new_block_notifications(),
3278 storage: self.storage_info(),
3279 filter: FilteredParams::new(Some(filter)),
3280 historic: Some(historic),
3281 }));
3282 Ok(self.filters.add_filter(filter).await)
3283 }
3284
3285 pub async fn new_block_filter(&self) -> Result<String> {
3289 node_info!("eth_newBlockFilter");
3290 let filter = EthFilter::Blocks(self.new_block_notifications());
3291 Ok(self.filters.add_filter(filter).await)
3292 }
3293
3294 pub async fn new_pending_transaction_filter(&self, full: bool) -> Result<String> {
3298 node_info!("eth_newPendingTransactionFilter");
3299 let filter = if full {
3300 EthFilter::FullPendingTransactions(self.full_pending_transactions_filter())
3301 } else {
3302 EthFilter::PendingTransactions(self.new_ready_transactions())
3303 };
3304 Ok(self.filters.add_filter(filter).await)
3305 }
3306
3307 pub async fn get_filter_changes(&self, id: &str) -> ResponseResult {
3311 node_info!("eth_getFilterChanges");
3312 self.filters.get_filter_changes(id).await
3313 }
3314
3315 pub async fn get_filter_logs(&self, id: &str) -> Result<Vec<Log>> {
3319 node_info!("eth_getFilterLogs");
3320 if let Some(filter) = self.filters.get_log_filter(id).await {
3321 self.backend.logs(filter).await
3322 } else {
3323 Err(BlockchainError::FilterNotFound)
3324 }
3325 }
3326
3327 pub async fn uninstall_filter(&self, id: &str) -> Result<bool> {
3329 node_info!("eth_uninstallFilter");
3330 Ok(self.filters.uninstall_filter(id).await.is_some())
3331 }
3332
3333 pub async fn raw_transaction(&self, hash: B256) -> Result<Option<Bytes>> {
3337 node_info!("debug_getRawTransaction");
3338 self.inner_raw_transaction(hash).await
3339 }
3340
3341 pub async fn raw_receipts(&self, block: BlockId) -> Result<Vec<Bytes>> {
3345 node_info!("debug_getRawReceipts");
3346
3347 if let BlockRequest::Number(number) = self.block_request(Some(block)).await?
3349 && let Some(fork) = self.get_fork()
3350 && fork.predates_fork_inclusive(number)
3351 {
3352 let receipts = fork.block_receipts(number).await?.unwrap_or_default();
3353 return Ok(receipts
3354 .into_iter()
3355 .map(|receipt| {
3356 receipt.0.inner.inner.map_logs(|log| log.inner).encoded_2718().into()
3357 })
3358 .collect());
3359 }
3360
3361 let block = self.backend.get_block(block).ok_or(BlockchainError::BlockNotFound)?;
3362 let receipts = self
3363 .backend
3364 .mined_receipts(block.header.hash_slow())
3365 .ok_or(BlockchainError::BlockNotFound)?;
3366 Ok(receipts.into_iter().map(|receipt| receipt.encoded_2718().into()).collect())
3367 }
3368
3369 pub async fn raw_transactions(&self, block: BlockId) -> Result<Vec<Bytes>> {
3373 node_info!("debug_getRawTransactions");
3374
3375 if let Some(block) = self.backend.get_block(block) {
3376 return Ok(block
3377 .body
3378 .transactions
3379 .into_iter()
3380 .map(|tx| canonical_block_transaction(tx.into_inner()).encoded_2718().into())
3381 .collect());
3382 }
3383
3384 let Some(fork) = self.get_fork() else {
3387 return Ok(Vec::new());
3388 };
3389 let block = match block {
3390 BlockId::Number(BlockNumber::Pending) => None,
3391 BlockId::Number(number) => {
3392 let number = self.backend.convert_block_number(Some(number));
3393 if !fork.predates_fork_inclusive(number) {
3394 return Ok(Vec::new());
3395 }
3396 fork.block_by_number_full(number).await?
3397 }
3398 BlockId::Hash(hash) => fork
3399 .block_by_hash_full(hash.block_hash)
3400 .await?
3401 .filter(|block| fork.predates_fork_inclusive(block.header().number())),
3402 };
3403 let Some(block) = block else {
3404 return Ok(Vec::new());
3405 };
3406 let BlockTransactions::Full(txs) = block.transactions() else {
3407 return Err(BlockchainError::Internal(
3408 "fork provider returned a non-full block for a full block request".to_string(),
3409 ));
3410 };
3411 Ok(txs.iter().map(|tx| tx.as_ref().encoded_2718().into()).collect())
3412 }
3413
3414 pub async fn raw_header(&self, block: BlockId) -> Result<Bytes> {
3418 node_info!("debug_getRawHeader");
3419 let block = self.backend.get_block(block).ok_or(BlockchainError::BlockNotFound)?;
3420 Ok(alloy_rlp::encode(&block.header).into())
3421 }
3422
3423 pub async fn raw_block(&self, block: BlockId) -> Result<Bytes> {
3427 node_info!("debug_getRawBlock");
3428 let block = self.backend.get_block(block).ok_or(BlockchainError::BlockNotFound)?;
3429 Ok(alloy_rlp::encode(canonical_block(block)).into())
3430 }
3431
3432 pub async fn raw_transaction_by_block_hash_and_index(
3436 &self,
3437 block_hash: B256,
3438 index: Index,
3439 ) -> Result<Option<Bytes>> {
3440 node_info!("eth_getRawTransactionByBlockHashAndIndex");
3441 match self.backend.transaction_by_block_hash_and_index(block_hash, index).await? {
3442 Some(tx) => self.inner_raw_transaction(tx.tx_hash()).await,
3443 None => Ok(None),
3444 }
3445 }
3446
3447 pub async fn raw_transaction_by_block_number_and_index(
3451 &self,
3452 block_number: BlockNumber,
3453 index: Index,
3454 ) -> Result<Option<Bytes>> {
3455 node_info!("eth_getRawTransactionByBlockNumberAndIndex");
3456 match self.backend.transaction_by_block_number_and_index(block_number, index).await? {
3457 Some(tx) => self.inner_raw_transaction(tx.tx_hash()).await,
3458 None => Ok(None),
3459 }
3460 }
3461
3462 pub async fn debug_trace_transaction(
3466 &self,
3467 tx_hash: B256,
3468 opts: GethDebugTracingOptions,
3469 ) -> Result<GethTrace> {
3470 node_info!("debug_traceTransaction");
3471 self.backend.debug_trace_transaction(tx_hash, opts).await
3472 }
3473
3474 pub async fn debug_trace_block(
3478 &self,
3479 rlp_block: Bytes,
3480 opts: GethDebugTracingOptions,
3481 ) -> Result<Vec<TraceResult>> {
3482 node_info!("debug_traceBlock");
3483 self.backend.debug_trace_block(rlp_block, opts).await
3484 }
3485
3486 pub async fn debug_trace_block_by_hash(
3490 &self,
3491 block_hash: B256,
3492 opts: GethDebugTracingOptions,
3493 ) -> Result<Vec<TraceResult>> {
3494 node_info!("debug_traceBlockByHash");
3495 self.backend.debug_trace_block_by_hash(block_hash, opts).await
3496 }
3497
3498 pub async fn debug_trace_block_by_number(
3502 &self,
3503 block_number: BlockNumber,
3504 opts: GethDebugTracingOptions,
3505 ) -> Result<Vec<TraceResult>> {
3506 node_info!("debug_traceBlockByNumber");
3507 self.backend.debug_trace_block_by_number(block_number, opts).await
3508 }
3509
3510 pub async fn debug_trace_call(
3514 &self,
3515 request: WithOtherFields<TransactionRequest>,
3516 block_number: Option<BlockId>,
3517 opts: GethDebugTracingCallOptions,
3518 ) -> Result<GethTrace> {
3519 node_info!("debug_traceCall");
3520 let block_request = self.block_request(block_number).await?;
3521 let fees = FeeDetails::new(
3522 request.gas_price,
3523 request.max_fee_per_gas,
3524 request.max_priority_fee_per_gas,
3525 request.max_fee_per_blob_gas,
3526 )?
3527 .or_zero_fees();
3528
3529 let result: std::result::Result<GethTrace, BlockchainError> =
3530 self.backend.call_with_tracing(request, fees, Some(block_request), opts).await;
3531 result
3532 }
3533
3534 pub async fn trace_call_many(
3538 &self,
3539 calls: Vec<(WithOtherFields<TransactionRequest>, HashSet<TraceType>)>,
3540 block_number: Option<BlockId>,
3541 ) -> Result<Vec<TraceResults>> {
3542 node_info!("trace_callMany");
3543 let block_number = block_number.unwrap_or(BlockId::Number(BlockNumber::Pending));
3544 let block_request = self.block_request(Some(block_number)).await?;
3545
3546 self.backend.trace_call_many(calls, Some(block_request)).await
3547 }
3548}
3549
3550impl EthApi<FoundryNetwork> {
3553 pub async fn anvil_mine(&self, num_blocks: Option<U256>, interval: Option<U256>) -> Result<()> {
3557 node_info!("anvil_mine");
3558 let interval = interval.map(|i| i.saturating_to::<u64>());
3559 let blocks = num_blocks.unwrap_or(U256::from(1));
3560 if blocks.is_zero() {
3561 return Ok(());
3562 }
3563
3564 self.on_blocking_task(|this| async move {
3565 for _ in 0..blocks.saturating_to::<u64>() {
3567 if let Some(interval) = interval {
3569 this.backend.time().increase_time(interval);
3570 }
3571 this.mine_one().await;
3572 }
3573 Ok(())
3574 })
3575 .await?;
3576
3577 Ok(())
3578 }
3579
3580 async fn find_erc20_storage_slot(
3597 &self,
3598 token_address: Address,
3599 calldata: Bytes,
3600 expected_value: U256,
3601 ) -> Result<B256> {
3602 let tx = TransactionRequest::default().with_to(token_address).with_input(calldata.clone());
3603
3604 let access_list_result =
3606 self.create_access_list(WithOtherFields::new(tx.clone()), None, None).await?;
3607 let access_list = access_list_result.access_list;
3608
3609 for item in access_list.0 {
3612 if item.address != token_address {
3613 continue;
3614 };
3615 for slot in &item.storage_keys {
3616 let account_override = AccountOverride::default().with_state_diff(std::iter::once(
3617 (*slot, B256::from(expected_value.to_be_bytes())),
3618 ));
3619
3620 let state_override = StateOverridesBuilder::default()
3621 .append(token_address, account_override)
3622 .build();
3623
3624 let evm_override = EvmOverrides::state(Some(state_override));
3625
3626 let Ok(result) =
3627 self.call(WithOtherFields::new(tx.clone()), None, evm_override).await
3628 else {
3629 continue;
3631 };
3632
3633 let Ok(result_value) = U256::abi_decode(&result) else {
3634 continue;
3636 };
3637
3638 if result_value == expected_value {
3639 return Ok(*slot);
3640 }
3641 }
3642 }
3643
3644 Err(BlockchainError::Message("Unable to find storage slot".to_string()))
3645 }
3646
3647 pub async fn anvil_deal_erc20(
3651 &self,
3652 address: Address,
3653 token_address: Address,
3654 balance: U256,
3655 ) -> Result<()> {
3656 node_info!("anvil_dealERC20");
3657
3658 if self.backend.is_tempo()
3659 && self.backend.try_set_tip20_balance(address, token_address, balance).await?
3660 {
3661 return Ok(());
3662 }
3663
3664 sol! {
3665 #[sol(rpc)]
3666 contract IERC20 {
3667 function balanceOf(address target) external view returns (uint256);
3668 }
3669 }
3670
3671 let calldata = IERC20::balanceOfCall { target: address }.abi_encode().into();
3672
3673 let slot =
3675 self.find_erc20_storage_slot(token_address, calldata, balance).await.map_err(|_| {
3676 BlockchainError::Message("Unable to set ERC20 balance, no slot found".to_string())
3677 })?;
3678
3679 self.anvil_set_storage_at(
3681 token_address,
3682 U256::from_be_bytes(slot.0),
3683 B256::from(balance.to_be_bytes()),
3684 )
3685 .await?;
3686
3687 Ok(())
3688 }
3689
3690 pub async fn anvil_deal_tip20(
3694 &self,
3695 address: Address,
3696 token_address: Address,
3697 balance: U256,
3698 ) -> Result<()> {
3699 node_info!("anvil_dealTIP20");
3700 self.ensure_tempo_mode()?;
3701 self.backend.set_tip20_balance(address, token_address, balance).await?;
3702 Ok(())
3703 }
3704
3705 pub async fn anvil_set_erc20_allowance(
3709 &self,
3710 owner: Address,
3711 spender: Address,
3712 token_address: Address,
3713 amount: U256,
3714 ) -> Result<()> {
3715 node_info!("anvil_setERC20Allowance");
3716
3717 sol! {
3718 #[sol(rpc)]
3719 contract IERC20 {
3720 function allowance(address owner, address spender) external view returns (uint256);
3721 }
3722 }
3723
3724 let calldata = IERC20::allowanceCall { owner, spender }.abi_encode().into();
3725
3726 let slot =
3728 self.find_erc20_storage_slot(token_address, calldata, amount).await.map_err(|_| {
3729 BlockchainError::Message("Unable to set ERC20 allowance, no slot found".to_string())
3730 })?;
3731
3732 self.anvil_set_storage_at(
3734 token_address,
3735 U256::from_be_bytes(slot.0),
3736 B256::from(amount.to_be_bytes()),
3737 )
3738 .await?;
3739
3740 Ok(())
3741 }
3742
3743 pub async fn anvil_reorg(&self, options: ReorgOptions) -> Result<()> {
3757 node_info!("anvil_reorg");
3758 let depth = options.depth;
3759 let tx_block_pairs = options.tx_block_pairs;
3760
3761 let current_height = self.backend.best_number();
3763 let common_height = current_height.checked_sub(depth).ok_or(BlockchainError::RpcError(
3764 RpcError::invalid_params(format!(
3765 "Reorg depth must not exceed current chain height: current height {current_height}, depth {depth}"
3766 )),
3767 ))?;
3768
3769 let common_block =
3771 self.backend.get_block(common_height).ok_or(BlockchainError::BlockNotFound)?;
3772
3773 let block_pool_txs = if tx_block_pairs.is_empty() {
3776 HashMap::default()
3777 } else {
3778 let mut pairs = tx_block_pairs;
3779
3780 if let Some((_, num)) = pairs.iter().find(|(_, num)| *num >= depth) {
3782 return Err(BlockchainError::RpcError(RpcError::invalid_params(format!(
3783 "Block number for reorg tx will exceed the reorged chain height. Block number {num} must not exceed (depth-1) {}",
3784 depth - 1
3785 ))));
3786 }
3787
3788 pairs.sort_by_key(|a| a.1);
3790
3791 let mut nonces: HashMap<Address, u64> = HashMap::default();
3794
3795 let mut txs: HashMap<u64, Vec<Arc<PoolTransaction<FoundryTxEnvelope>>>> =
3796 HashMap::default();
3797 for pair in pairs {
3798 let (tx_data, block_index) = pair;
3799
3800 let pending = match tx_data {
3801 TransactionData::Raw(bytes) => {
3802 let mut data = bytes.as_ref();
3803 let decoded = FoundryTxEnvelope::decode_2718(&mut data)
3804 .map_err(|_| BlockchainError::FailedToDecodeSignedTransaction)?;
3805 PendingTransaction::new(decoded)?
3806 }
3807
3808 TransactionData::JSON(request) => {
3809 let from = request.from.map(Ok).unwrap_or_else(|| {
3810 self.accounts()?
3811 .first()
3812 .copied()
3813 .ok_or(BlockchainError::NoSignerAvailable)
3814 })?;
3815
3816 let curr_nonce = nonces.entry(from).or_insert(
3818 self.get_transaction_count(
3819 from,
3820 Some(common_block.header.number().into()),
3821 )
3822 .await?,
3823 );
3824
3825 let typed_tx = self.build_tx_request(request.into(), *curr_nonce).await?;
3827
3828 *curr_nonce += 1;
3830
3831 if self.is_impersonated(from) {
3833 let transaction = sign::build_impersonated(typed_tx);
3834 self.ensure_typed_transaction_supported(&transaction)?;
3835 PendingTransaction::with_impersonated(transaction, from)
3836 } else {
3837 let transaction = self.sign_request(&from, typed_tx)?;
3838 self.ensure_typed_transaction_supported(&transaction)?;
3839 PendingTransaction::new(transaction)?
3840 }
3841 }
3842 };
3843
3844 let pooled = PoolTransaction::new(pending);
3845 txs.entry(block_index).or_default().push(Arc::new(pooled));
3846 }
3847
3848 txs
3849 };
3850
3851 self.backend.reorg(depth, block_pool_txs, common_block).await?;
3852 Ok(())
3853 }
3854
3855 pub async fn evm_mine(&self, opts: Option<MineOptions>) -> Result<String> {
3862 node_info!("evm_mine");
3863
3864 self.do_evm_mine(opts).await?;
3865
3866 Ok("0x0".to_string())
3867 }
3868
3869 pub async fn evm_mine_detailed(&self, opts: Option<MineOptions>) -> Result<Vec<AnyRpcBlock>> {
3879 node_info!("evm_mine_detailed");
3880
3881 let mined_blocks = self.do_evm_mine(opts).await?;
3882
3883 let mut blocks = Vec::with_capacity(mined_blocks as usize);
3884
3885 let latest = self.backend.best_number();
3886 for offset in (0..mined_blocks).rev() {
3887 let block_num = latest - offset;
3888 if let Some(mut block) =
3889 self.backend.block_by_number_full(BlockNumber::Number(block_num)).await?
3890 {
3891 let block_txs = match block.transactions_mut() {
3892 BlockTransactions::Full(txs) => txs,
3893 BlockTransactions::Hashes(_) | BlockTransactions::Uncle => unreachable!(),
3894 };
3895 for tx in block_txs.iter_mut() {
3896 if let Some(receipt) = self.backend.mined_transaction_receipt(tx.tx_hash())
3897 && let Some(output) = receipt.out
3898 {
3899 if !receipt.inner.as_ref().status()
3901 && let Some(reason) = RevertDecoder::new().maybe_decode(&output, None)
3902 {
3903 tx.other.insert(
3904 "revertReason".to_string(),
3905 serde_json::to_value(reason).expect("Infallible"),
3906 );
3907 }
3908 tx.other.insert(
3909 "output".to_string(),
3910 serde_json::to_value(output).expect("Infallible"),
3911 );
3912 }
3913 }
3914 block.transactions = BlockTransactions::Full(block_txs.clone());
3915 blocks.push(block);
3916 }
3917 }
3918
3919 Ok(blocks)
3920 }
3921
3922 pub async fn eth_send_unsigned_transaction(
3926 &self,
3927 request: WithOtherFields<TransactionRequest>,
3928 ) -> Result<TxHash> {
3929 node_info!("eth_sendUnsignedTransaction");
3930 let from = request.from.ok_or(BlockchainError::NoSignerAvailable)?;
3932
3933 let (nonce, on_chain_nonce) = self.request_nonce(&request, from).await?;
3934
3935 let typed_tx = self.build_tx_request(request, nonce).await?;
3936
3937 let transaction = sign::build_impersonated(typed_tx);
3938
3939 self.ensure_typed_transaction_supported(&transaction)?;
3940
3941 let pending_transaction = PendingTransaction::with_impersonated(transaction, from);
3942
3943 self.backend.validate_pool_transaction(&pending_transaction).await?;
3945
3946 let (requires, provides) = nonce_markers(&pending_transaction, nonce, on_chain_nonce, from);
3947
3948 self.add_pending_transaction(pending_transaction, requires, provides)
3949 }
3950
3951 pub async fn txpool_inspect(&self) -> Result<TxpoolInspect> {
3958 node_info!("txpool_inspect");
3959 let mut inspect = TxpoolInspect::default();
3960
3961 fn convert(tx: Arc<PoolTransaction<FoundryTxEnvelope>>) -> TxpoolInspectSummary {
3962 let tx = &tx.pending_transaction.transaction;
3963 let to = tx.to();
3964 let gas_price = tx.max_fee_per_gas();
3965 let value = tx.value();
3966 let gas = tx.gas_limit();
3967 TxpoolInspectSummary { to, value, gas, gas_price }
3968 }
3969
3970 for pending in self.pool.ready_transactions() {
3977 let entry = inspect.pending.entry(*pending.pending_transaction.sender()).or_default();
3978 let key = txpool_transaction_key(&pending.pending_transaction);
3979 entry.insert(key, convert(pending));
3980 }
3981 for queued in self.pool.pending_transactions() {
3982 let entry = inspect.queued.entry(*queued.pending_transaction.sender()).or_default();
3983 let key = txpool_transaction_key(&queued.pending_transaction);
3984 entry.insert(key, convert(queued));
3985 }
3986 Ok(inspect)
3987 }
3988
3989 pub async fn txpool_content(&self) -> Result<TxpoolContent<AnyRpcTransaction>> {
3996 node_info!("txpool_content");
3997 self.build_txpool_content(None)
3998 }
3999
4000 fn build_txpool_content(
4005 &self,
4006 filter: Option<Address>,
4007 ) -> Result<TxpoolContent<AnyRpcTransaction>> {
4008 let mut content = TxpoolContent::<AnyRpcTransaction>::default();
4009 fn convert(tx: Arc<PoolTransaction<FoundryTxEnvelope>>) -> Result<AnyRpcTransaction> {
4010 let from = *tx.pending_transaction.sender();
4011 let tx = transaction_build(
4012 Some(tx.hash()),
4013 tx.pending_transaction.transaction.clone(),
4014 None,
4015 None,
4016 None,
4017 );
4018
4019 let WithOtherFields { inner: mut tx, other } = tx.0;
4020
4021 tx.inner = Recovered::new_unchecked(tx.inner.into_inner(), from);
4024
4025 let tx = AnyRpcTransaction(WithOtherFields { inner: tx, other });
4026
4027 Ok(tx)
4028 }
4029
4030 for pending in self.pool.ready_transactions() {
4031 let sender = *pending.pending_transaction.sender();
4032 if filter.is_some_and(|from| from != sender) {
4033 continue;
4034 }
4035 let entry = content.pending.entry(sender).or_default();
4036 let key = txpool_transaction_key(&pending.pending_transaction);
4037 entry.insert(key, convert(pending)?);
4038 }
4039 for queued in self.pool.pending_transactions() {
4040 let sender = *queued.pending_transaction.sender();
4041 if filter.is_some_and(|from| from != sender) {
4042 continue;
4043 }
4044 let entry = content.queued.entry(sender).or_default();
4045 let key = txpool_transaction_key(&queued.pending_transaction);
4046 entry.insert(key, convert(queued)?);
4047 }
4048
4049 Ok(content)
4050 }
4051
4052 pub async fn txpool_content_from(
4060 &self,
4061 from: Address,
4062 ) -> Result<TxpoolContentFrom<AnyRpcTransaction>> {
4063 node_info!("txpool_contentFrom");
4064 let mut content = self.build_txpool_content(Some(from))?;
4065 Ok(content.remove_from(&from))
4066 }
4067}
4068
4069impl EthApi<FoundryNetwork> {
4070 async fn do_evm_mine(&self, opts: Option<MineOptions>) -> Result<u64> {
4072 let mut blocks_to_mine = 1u64;
4073
4074 if let Some(opts) = opts {
4075 let timestamp = match opts {
4076 MineOptions::Timestamp(timestamp) => timestamp,
4077 MineOptions::Options { timestamp, blocks } => {
4078 if let Some(blocks) = blocks {
4079 blocks_to_mine = blocks;
4080 }
4081 timestamp
4082 }
4083 };
4084 if let Some(timestamp) = timestamp {
4085 self.evm_set_next_block_timestamp(timestamp)?;
4087 }
4088 }
4089
4090 self.on_blocking_task(|this| async move {
4093 for _ in 0..blocks_to_mine {
4095 this.mine_one().await;
4096 }
4097 Ok(())
4098 })
4099 .await?;
4100
4101 Ok(blocks_to_mine)
4102 }
4103
4104 async fn do_estimate_gas(
4105 &self,
4106 request: WithOtherFields<TransactionRequest>,
4107 block_number: Option<BlockId>,
4108 overrides: EvmOverrides,
4109 ) -> Result<u128> {
4110 let block_request = self.block_request(block_number).await?;
4111 if let BlockRequest::Number(number) = block_request
4113 && let Some(fork) = self.get_fork()
4114 && fork.predates_fork(number)
4115 {
4116 if overrides.has_state() || overrides.has_block() {
4117 return Err(BlockchainError::EvmOverrideError(
4118 "not available on past forked blocks".to_string(),
4119 ));
4120 }
4121 return Ok(fork.estimate_gas(&request, Some(number.into())).await?);
4122 }
4123
4124 self.on_blocking_task(|this| async move {
4127 this.backend
4128 .with_database_at(Some(block_request), |state, mut block| {
4129 let mut cache_db = CacheDB::new(state);
4130 if let Some(state_overrides) = overrides.state {
4131 apply_state_overrides(
4132 state_overrides.into_iter().collect(),
4133 &mut cache_db,
4134 )?;
4135 }
4136 if let Some(block_overrides) = overrides.block {
4137 cache_db.apply_block_overrides(*block_overrides, &mut block);
4138 }
4139 this.do_estimate_gas_with_state(request, &cache_db, block)
4140 })
4141 .await?
4142 })
4143 .await
4144 }
4145
4146 fn transaction_priority(&self, tx: &FoundryTxEnvelope) -> TransactionPriority {
4148 self.transaction_order.read().priority(tx)
4149 }
4150
4151 pub fn full_pending_transactions(&self) -> UnboundedReceiver<AnyRpcTransaction> {
4153 let (tx, rx) = unbounded_channel();
4154 let mut hashes = self.new_ready_transactions();
4155
4156 let this = self.clone();
4157
4158 tokio::spawn(async move {
4159 while let Some(hash) = hashes.next().await {
4160 if let Ok(Some(txn)) = this.transaction_by_hash(hash).await
4161 && tx.send(txn).is_err()
4162 {
4163 break;
4164 }
4165 }
4166 });
4167
4168 rx
4169 }
4170
4171 pub fn full_pending_transactions_filter(&self) -> mpsc::Receiver<AnyRpcTransaction> {
4176 let (tx, rx) = mpsc::channel(2048);
4178 let mut hashes = self.new_ready_transactions();
4179 let this = self.clone();
4180
4181 tokio::spawn(async move {
4182 while let Some(hash) = hashes.next().await {
4183 if let Ok(Some(txn)) = this.transaction_by_hash(hash).await
4184 && tx.send(txn).await.is_err()
4185 {
4186 break;
4187 }
4188 }
4189 });
4190
4191 rx
4192 }
4193
4194 pub fn transaction_receipts_subscription(
4196 &self,
4197 filter: TransactionReceiptsParams,
4198 ) -> UnboundedReceiver<Vec<FoundryTxReceipt>> {
4199 let (tx, rx) = unbounded_channel();
4200 let mut blocks = self.new_block_notifications();
4201 let this = self.clone();
4202
4203 tokio::spawn(async move {
4204 let hash_filter = filter
4206 .transaction_hashes
4207 .filter(|hashes| !hashes.is_empty())
4208 .map(|hashes| hashes.into_iter().collect::<std::collections::HashSet<_>>());
4209
4210 loop {
4211 let notification = tokio::select! {
4212 biased;
4213 _ = tx.closed() => break,
4215 maybe_block = blocks.next() => match maybe_block {
4216 Some(block) => block,
4217 None => break,
4218 },
4219 };
4220
4221 let Some(block) = notification.as_new_block() else {
4222 continue;
4223 };
4224
4225 let receipts = match this.block_receipts(BlockId::Hash(block.hash.into())).await {
4226 Ok(Some(mut receipts)) => {
4227 if let Some(hashes) = &hash_filter {
4228 receipts.retain(|receipt| hashes.contains(&receipt.transaction_hash()));
4229 }
4230 receipts
4231 }
4232 Ok(None) => continue,
4233 Err(err) => {
4234 trace!(target: "node", %err, "failed to build block receipts for subscription");
4235 continue;
4236 }
4237 };
4238
4239 if receipts.is_empty() {
4240 continue;
4241 }
4242
4243 if tx.send(receipts).is_err() {
4244 break;
4245 }
4246 }
4247 });
4248
4249 rx
4250 }
4251
4252 pub async fn mine_one(&self) {
4254 let transactions = self.pool.ready_transactions().collect::<Vec<_>>();
4255 let outcome = self.backend.mine_block(transactions).await;
4256
4257 trace!(target: "node", blocknumber = ?outcome.block_number, "mined block");
4258 self.pool.on_mined_block(outcome);
4259 }
4260
4261 async fn pending_block(&self) -> AnyRpcBlock {
4263 let transactions = self.pool.ready_transactions().collect::<Vec<_>>();
4264 let info = self.backend.pending_block(transactions).await;
4265 self.backend.convert_block(info.block)
4266 }
4267
4268 async fn pending_block_full(&self) -> Option<AnyRpcBlock> {
4270 let transactions = self.pool.ready_transactions().collect::<Vec<_>>();
4271 let BlockInfo { block, transactions, receipts: _ } =
4272 self.backend.pending_block(transactions).await;
4273
4274 let mut partial_block = self.backend.convert_block(block.clone());
4275
4276 let mut block_transactions = Vec::with_capacity(block.body.transactions.len());
4277 let base_fee = self.backend.base_fee();
4278
4279 for info in transactions {
4280 let tx = block.body.transactions.get(info.transaction_index as usize)?.clone();
4281
4282 let tx = transaction_build(
4283 Some(info.transaction_hash),
4284 tx,
4285 Some(&block),
4286 Some(info),
4287 Some(base_fee),
4288 );
4289 block_transactions.push(tx);
4290 }
4291
4292 partial_block.transactions = BlockTransactions::from(block_transactions);
4293
4294 Some(partial_block)
4295 }
4296
4297 async fn build_tx_request(
4300 &self,
4301 request: WithOtherFields<TransactionRequest>,
4302 nonce: u64,
4303 ) -> Result<FoundryTypedTx> {
4304 let mut request = Into::<FoundryTransactionRequest>::into(request);
4305 let from = request.from().or(self.accounts()?.first().copied());
4306 if let Some(from) = from {
4307 request.set_from(from);
4308 }
4309
4310 request.chain_id().is_none().then(|| request.set_chain_id(self.chain_id()));
4312 request.nonce().is_none().then(|| request.set_nonce(nonce));
4313 request.kind().is_none().then(|| request.set_kind(TxKind::default()));
4314 if request.gas_limit().is_none() {
4315 let fallback_gas_limit = {
4316 let evm_env = self.backend.evm_env().read();
4317 let block_gas_limit = evm_env.block_env.gas_limit;
4318 if evm_env.cfg_env.tx_gas_limit_cap.is_none() {
4319 block_gas_limit.min(evm_env.cfg_env().tx_gas_limit_cap())
4320 } else {
4321 block_gas_limit
4322 }
4323 };
4324 let estimated_gas = self
4325 .do_estimate_gas(request.as_ref().clone().into(), None, EvmOverrides::default())
4326 .await
4327 .map(|v| v as u64)
4328 .unwrap_or_else(|_| {
4329 if is_simple_transfer_request(request.as_ref()) {
4330 MIN_TRANSACTION_GAS as u64
4331 } else {
4332 fallback_gas_limit
4333 }
4334 });
4335 request.set_gas_limit(estimated_gas);
4336 }
4337
4338 if let Err((tx_type, _)) = request.missing_keys() {
4340 if matches!(tx_type, FoundryTxType::Legacy | FoundryTxType::Eip2930) {
4341 request.gas_price().is_none().then(|| request.set_gas_price(self.gas_price()));
4342 }
4343 if tx_type == FoundryTxType::Eip2930 {
4344 request
4345 .access_list()
4346 .is_none()
4347 .then(|| request.set_access_list(Default::default()));
4348 }
4349 if matches!(
4350 tx_type,
4351 FoundryTxType::Eip1559
4352 | FoundryTxType::Eip4844
4353 | FoundryTxType::Eip7702
4354 | FoundryTxType::Tempo
4355 ) {
4356 request
4357 .max_fee_per_gas()
4358 .is_none()
4359 .then(|| request.set_max_fee_per_gas(self.gas_price()));
4360 request
4361 .max_priority_fee_per_gas()
4362 .is_none()
4363 .then(|| request.set_max_priority_fee_per_gas(MIN_SUGGESTED_PRIORITY_FEE));
4364 }
4365 if tx_type == FoundryTxType::Eip4844 {
4366 request.as_ref().max_fee_per_blob_gas().is_none().then(|| {
4367 request.as_mut().set_max_fee_per_blob_gas(
4368 self.backend.fees().get_next_block_blob_base_fee_per_gas(),
4369 )
4370 });
4371 }
4372 }
4373
4374 match request
4375 .build_unsigned()
4376 .map_err(|e| BlockchainError::InvalidTransactionRequest(e.to_string()))?
4377 {
4378 FoundryTypedTx::Eip4844(TxEip4844Variant::TxEip4844(_))
4379 if !self.backend.skip_blob_validation(from) =>
4380 {
4381 Err(BlockchainError::FailedToDecodeTransaction)
4383 }
4384 res => Ok(res),
4385 }
4386 }
4387
4388 async fn get_transaction_count(
4390 &self,
4391 address: Address,
4392 block_number: Option<BlockId>,
4393 ) -> Result<u64> {
4394 let block_request = self.block_request(block_number).await?;
4395
4396 if let BlockRequest::Number(number) = block_request
4397 && let Some(fork) = self.get_fork()
4398 && fork.predates_fork(number)
4399 {
4400 return Ok(fork.get_nonce(address, number).await?);
4401 }
4402
4403 self.backend.get_nonce(address, block_request).await
4404 }
4405
4406 async fn request_nonce(
4414 &self,
4415 request: &TransactionRequest,
4416 from: Address,
4417 ) -> Result<(u64, u64)> {
4418 let highest_nonce =
4419 self.get_transaction_count(from, Some(BlockId::Number(BlockNumber::Pending))).await?;
4420 let nonce = request.nonce.unwrap_or(highest_nonce);
4421
4422 Ok((nonce, highest_nonce))
4423 }
4424
4425 fn add_pending_transaction(
4427 &self,
4428 pending_transaction: PendingTransaction<FoundryTxEnvelope>,
4429 requires: Vec<TxMarker>,
4430 provides: Vec<TxMarker>,
4431 ) -> Result<TxHash> {
4432 debug_assert!(requires != provides);
4433 let from = *pending_transaction.sender();
4434 let priority = self.transaction_priority(&pending_transaction.transaction);
4435 let pool_transaction =
4436 PoolTransaction { requires, provides, pending_transaction, priority };
4437 let tx = self.pool.add_transaction(pool_transaction)?;
4438 trace!(target: "node", "Added transaction: [{:?}] sender={:?}", tx.hash(), from);
4439 Ok(*tx.hash())
4440 }
4441
4442 fn ensure_typed_transaction_supported(&self, tx: &FoundryTxEnvelope) -> Result<()> {
4444 match &tx {
4445 FoundryTxEnvelope::Eip2930(_) => self.backend.ensure_eip2930_active(),
4446 FoundryTxEnvelope::Eip1559(_) => self.backend.ensure_eip1559_active(),
4447 FoundryTxEnvelope::Eip4844(_) => self.backend.ensure_eip4844_active(),
4448 FoundryTxEnvelope::Eip7702(_) => self.backend.ensure_eip7702_active(),
4449 #[cfg(feature = "optimism")]
4450 FoundryTxEnvelope::Deposit(_) => self.backend.ensure_op_deposits_active(),
4451 #[cfg(feature = "optimism")]
4452 FoundryTxEnvelope::PostExec(_) => Err(BlockchainError::InvalidTransactionRequest(
4453 "not implemented for post-exec tx".to_string(),
4454 )),
4455 FoundryTxEnvelope::Legacy(_) => Ok(()),
4456 FoundryTxEnvelope::Tempo(_) => self.backend.ensure_tempo_active(),
4457 }
4458 }
4459
4460 pub async fn anvil_set_fee_token(&self, user: Address, token: Address) -> Result<()> {
4466 node_info!("anvil_setFeeToken");
4467 self.ensure_tempo_mode()?;
4468 self.backend.set_fee_token(user, token).await?;
4469 Ok(())
4470 }
4471
4472 pub async fn anvil_set_validator_fee_token(
4478 &self,
4479 validator: Address,
4480 token: Address,
4481 ) -> Result<()> {
4482 node_info!("anvil_setValidatorFeeToken");
4483 self.ensure_tempo_mode()?;
4484 self.backend.set_validator_fee_token(validator, token).await?;
4485 Ok(())
4486 }
4487
4488 pub async fn anvil_set_fee_amm_liquidity(
4494 &self,
4495 user_token: Address,
4496 validator_token: Address,
4497 amount: U256,
4498 ) -> Result<()> {
4499 node_info!("anvil_setFeeAmmLiquidity");
4500 self.ensure_tempo_mode()?;
4501 self.backend.set_fee_amm_liquidity(user_token, validator_token, amount).await?;
4502 Ok(())
4503 }
4504
4505 fn ensure_tempo_mode(&self) -> Result<()> {
4507 if self.backend.is_tempo() { Ok(()) } else { Err(BlockchainError::RpcUnimplemented) }
4508 }
4509}
4510
4511fn is_simple_transfer_request(request: &TransactionRequest) -> bool {
4512 request.to.as_ref().and_then(TxKind::to).is_some()
4513 && (request.input.input().is_none()
4514 || request.input.input().is_some_and(|data| data.is_empty()))
4515 && request.authorization_list.is_none()
4516 && request.access_list.is_none()
4517 && request.blob_versioned_hashes.is_none()
4518}
4519
4520fn required_marker(provided_nonce: u64, on_chain_nonce: u64, from: Address) -> Vec<TxMarker> {
4521 if provided_nonce == on_chain_nonce {
4522 return Vec::new();
4523 }
4524 let prev_nonce = provided_nonce.saturating_sub(1);
4525 if on_chain_nonce <= prev_nonce { vec![to_marker(prev_nonce, from)] } else { Vec::new() }
4526}
4527
4528fn tempo_parallel_nonce_markers(
4529 pending_transaction: &PendingTransaction<FoundryTxEnvelope>,
4530) -> Option<(Vec<TxMarker>, Vec<TxMarker>)> {
4531 pending_transaction
4534 .transaction
4535 .as_ref()
4536 .has_nonzero_tempo_nonce_key()
4537 .then(|| (vec![], vec![pending_transaction.hash().to_vec()]))
4538}
4539
4540fn nonce_markers(
4543 pending_transaction: &PendingTransaction<FoundryTxEnvelope>,
4544 nonce: u64,
4545 on_chain_nonce: u64,
4546 from: Address,
4547) -> (Vec<TxMarker>, Vec<TxMarker>) {
4548 tempo_parallel_nonce_markers(pending_transaction).unwrap_or_else(|| {
4549 (required_marker(nonce, on_chain_nonce, from), vec![to_marker(nonce, from)])
4550 })
4551}
4552
4553fn txpool_transaction_key(pending_transaction: &PendingTransaction<FoundryTxEnvelope>) -> String {
4554 match pending_transaction.transaction.as_ref() {
4555 FoundryTxEnvelope::Tempo(tx) if !tx.tx().nonce_key.is_zero() => {
4556 let tx = tx.tx();
4557 format!("{}:{}", tx.nonce_key, tx.nonce)
4558 }
4559 _ => pending_transaction.nonce().to_string(),
4560 }
4561}
4562
4563fn convert_transact_out(out: &Option<Output>) -> Bytes {
4564 match out {
4565 None => Default::default(),
4566 Some(Output::Call(out)) => out.to_vec().into(),
4567 Some(Output::Create(out, _)) => out.to_vec().into(),
4568 }
4569}
4570
4571fn ensure_return_ok(exit: InstructionResult, out: &Option<Output>) -> Result<Bytes> {
4573 let out = convert_transact_out(out);
4574 match exit {
4575 return_ok!() => Ok(out),
4576 return_revert!() => Err(InvalidTransactionError::Revert(Some(out)).into()),
4577 reason => Err(BlockchainError::EvmError(reason)),
4578 }
4579}
4580
4581fn execution_error(exit: InstructionResult) -> Option<String> {
4584 match SuccessOrHalt::<HaltReason>::from(exit) {
4585 SuccessOrHalt::Success(_) => None,
4586 SuccessOrHalt::Revert => Some("execution reverted".to_string()),
4587 SuccessOrHalt::Halt(reason) => Some(reason.to_string()),
4588 SuccessOrHalt::FatalExternalError => Some("fatal external error".to_string()),
4589 SuccessOrHalt::Internal(_) => Some("internal EVM error".to_string()),
4590 }
4591}
4592
4593fn determine_base_gas_by_kind(request: &WithOtherFields<TransactionRequest>) -> u128 {
4595 match request.kind() {
4596 Some(TxKind::Call(_)) => {
4597 MIN_TRANSACTION_GAS
4598 + request.inner().authorization_list.as_ref().map_or(0, |auths_list| {
4599 auths_list.len() as u128 * PER_EMPTY_ACCOUNT_COST as u128
4600 })
4601 }
4602 Some(TxKind::Create) => MIN_CREATE_GAS,
4603 None => MIN_CREATE_GAS,
4605 }
4606}
4607
4608enum GasEstimationCallResult {
4610 Success(u128),
4611 OutOfGas,
4612 Revert(Option<Bytes>),
4613 EvmError(InstructionResult),
4614}
4615
4616impl TryFrom<Result<(InstructionResult, Option<Output>, u128, State)>> for GasEstimationCallResult {
4620 type Error = BlockchainError;
4621
4622 fn try_from(res: Result<(InstructionResult, Option<Output>, u128, State)>) -> Result<Self> {
4623 match res {
4624 Err(BlockchainError::InvalidTransaction(InvalidTransactionError::GasTooHigh(_))) => {
4626 Ok(Self::OutOfGas)
4627 }
4628 Err(BlockchainError::Message(ref msg))
4630 if msg.contains("insufficient gas for intrinsic cost") =>
4631 {
4632 Ok(Self::OutOfGas)
4633 }
4634 Err(err) => Err(err),
4635 Ok((exit, output, gas, _)) => match exit {
4636 return_ok!() => Ok(Self::Success(gas)),
4637
4638 InstructionResult::Revert => {
4640 Ok(Self::Revert(Some(output.map(|o| o.into_data()).unwrap_or_default())))
4641 }
4642 InstructionResult::CallTooDeep
4643 | InstructionResult::OutOfFunds
4644 | InstructionResult::CreateInitCodeStartingEF00
4645 | InstructionResult::InvalidEOFInitCode
4646 | InstructionResult::InvalidExtDelegateCallTarget => Ok(Self::EvmError(exit)),
4647
4648 InstructionResult::OutOfGas
4650 | InstructionResult::MemoryOOG
4651 | InstructionResult::MemoryLimitOOG
4652 | InstructionResult::PrecompileOOG
4653 | InstructionResult::InvalidOperandOOG
4654 | InstructionResult::ReentrancySentryOOG => Ok(Self::OutOfGas),
4655
4656 InstructionResult::OpcodeNotFound
4658 | InstructionResult::CallNotAllowedInsideStatic
4659 | InstructionResult::StateChangeDuringStaticCall
4660 | InstructionResult::InvalidFEOpcode
4661 | InstructionResult::InvalidJump
4662 | InstructionResult::NotActivated
4663 | InstructionResult::StackUnderflow
4664 | InstructionResult::StackOverflow
4665 | InstructionResult::OutOfOffset
4666 | InstructionResult::CreateCollision
4667 | InstructionResult::OverflowPayment
4668 | InstructionResult::PrecompileError
4669 | InstructionResult::NonceOverflow
4670 | InstructionResult::CreateContractSizeLimit
4671 | InstructionResult::CreateContractStartingWithEF
4672 | InstructionResult::CreateInitCodeSizeLimit
4673 | InstructionResult::InvalidImmediateEncoding
4674 | InstructionResult::FatalExternalError => Ok(Self::EvmError(exit)),
4675 },
4676 }
4677 }
4678}