Skip to main content

anvil_polkadot/api_server/
server.rs

1use crate::{
2    api_server::{
3        ApiRequest,
4        error::{Error, Result, ToRpcResponseResult},
5        filters::{
6            BlockFilter, BlockNotifications, EthFilter, Filters, LogsFilter,
7            PendingTransactionsFilter, eviction_task,
8        },
9        revive_conversions::{
10            AlloyU256, ReviveAddress, ReviveBlockId, ReviveBlockNumberOrTag, ReviveBytes,
11            ReviveFilter, ReviveTrace, ReviveTracerType, SubstrateU256,
12            convert_to_generic_transaction,
13        },
14        signer::DevSigner,
15        trace_helpers::{parity_block_trace_builder, parity_transaction_trace_builder},
16        txpool_helpers::{
17            TxpoolTransactionInfo, extract_sender, extract_tx_info, extract_tx_summary,
18            transaction_matches_eth_hash,
19        },
20    },
21    logging::LoggingManager,
22    macros::node_info,
23    substrate_node::{
24        host::recover_maybe_impersonated_address,
25        impersonation::ImpersonationManager,
26        in_mem_rpc::InMemoryRpcClient,
27        mining_engine::MiningEngine,
28        revert::{RevertInfo, RevertManager},
29        service::{
30            BackendError, BackendWithOverlay, Client, Service, TransactionPoolHandle,
31            storage::{
32                AccountType, BytecodeType, CodeInfo, ContractInfo, ReviveAccountInfo,
33                SystemAccountInfo,
34            },
35        },
36    },
37};
38use alloy_dyn_abi::TypedData;
39use alloy_eips::{BlockId, BlockNumberOrTag};
40use alloy_primitives::{Address, B256, U64, U256};
41use alloy_rpc_types::{
42    Filter, TransactionRequest,
43    anvil::{Forking, Metadata as AnvilMetadata, MineOptions, NodeEnvironment, NodeInfo},
44    trace::{
45        geth::{GethDebugTracingCallOptions, GethDebugTracingOptions, GethTrace, TraceResult},
46        parity::LocalizedTransactionTrace,
47    },
48    txpool::{TxpoolContent, TxpoolInspect, TxpoolStatus},
49};
50use alloy_serde::WithOtherFields;
51use alloy_trie::{EMPTY_ROOT_HASH, KECCAK_EMPTY, TrieAccount};
52use anvil_core::eth::{EthRequest, Params as AnvilCoreParams};
53use anvil_rpc::response::ResponseResult;
54use chrono::{DateTime, Datelike, Utc};
55use codec::{Decode, Encode};
56use futures::{StreamExt, channel::mpsc};
57use indexmap::IndexMap;
58use pallet_revive_eth_rpc::{
59    BlockInfoProvider, EthRpcError, ReceiptExtractor, ReceiptProvider, SubxtBlockInfoProvider,
60    client::{Client as EthRpcClient, ClientError, SubscriptionType},
61    subxt_client::{
62        self, SrcChainConfig, runtime_types::bounded_collections::bounded_vec::BoundedVec,
63    },
64};
65use polkadot_sdk::{
66    pallet_revive::{
67        ReviveApi,
68        evm::{
69            self, Block, BlockNumberOrTagOrHash, BlockTag, Bytes, CallTracerConfig,
70            FeeHistoryResult, FilterResults, Log, ReceiptInfo, TracerType, TransactionInfo,
71            TransactionSigned,
72        },
73    },
74    parachains_common::{AccountId, Hash, Nonce},
75    polkadot_sdk_frame::runtime::types_common::OpaqueBlock,
76    sc_client_api::HeaderBackend,
77    sc_service::{InPoolTransaction, SpawnTaskHandle, TransactionPool},
78    sp_api::{Metadata as _, ProvideRuntimeApi},
79    sp_blockchain::Info,
80    sp_core::{self, Hasher, keccak_256},
81    sp_runtime::{FixedU128, traits::BlakeTwo256},
82};
83use revm::primitives::hardfork::SpecId;
84use sqlx::sqlite::SqlitePoolOptions;
85use std::{collections::BTreeSet, sync::Arc, time::Duration};
86use substrate_runtime::{Balance, constants::NATIVE_TO_ETH_RATIO};
87use subxt::{
88    Metadata as SubxtMetadata, OnlineClient, backend::rpc::RpcClient,
89    client::RuntimeVersion as SubxtRuntimeVersion, config::substrate::H256,
90    ext::subxt_rpcs::LegacyRpcMethods, utils::H160,
91};
92use subxt_signer::eth::Keypair;
93use tokio::try_join;
94
95pub const CLIENT_VERSION: &str = concat!("anvil-polkadot/v", env!("CARGO_PKG_VERSION"));
96const TIMEOUT_DURATION: Duration = Duration::from_secs(30);
97
98pub struct ApiServer {
99    eth_rpc_client: EthRpcClient,
100    req_receiver: mpsc::Receiver<ApiRequest>,
101    backend: BackendWithOverlay,
102    logging_manager: LoggingManager,
103    client: Arc<Client>,
104    mining_engine: Arc<MiningEngine>,
105    wallet: DevSigner,
106    block_provider: SubxtBlockInfoProvider,
107    revert_manager: RevertManager,
108    impersonation_manager: ImpersonationManager,
109    tx_pool: Arc<TransactionPoolHandle>,
110    instance_id: B256,
111    /// Tracks all active filters
112    filters: Filters,
113}
114
115impl ApiServer {
116    #[allow(clippy::too_many_arguments)]
117    pub async fn new(
118        substrate_service: Service,
119        req_receiver: mpsc::Receiver<ApiRequest>,
120        logging_manager: LoggingManager,
121        revert_manager: RevertManager,
122        impersonation_manager: ImpersonationManager,
123        signers: Vec<Keypair>,
124        filters: Filters,
125        revive_rpc_block_limit: Option<usize>,
126    ) -> Result<Self> {
127        let rpc_client = RpcClient::new(InMemoryRpcClient(substrate_service.rpc_handlers.clone()));
128        let api = create_online_client(&substrate_service, rpc_client.clone()).await?;
129        let rpc = LegacyRpcMethods::<SrcChainConfig>::new(rpc_client.clone());
130        let block_provider = SubxtBlockInfoProvider::new(api.clone(), rpc.clone()).await?;
131        let eth_rpc_client = create_revive_rpc_client(
132            api.clone(),
133            rpc_client.clone(),
134            rpc,
135            block_provider.clone(),
136            substrate_service.spawn_handle.clone(),
137            revive_rpc_block_limit,
138        )
139        .await?;
140
141        let filters_clone = filters.clone();
142        substrate_service.spawn_handle.spawn("filter-eviction-task", "None", async move {
143            eviction_task(filters_clone).await;
144        });
145        Ok(Self {
146            block_provider,
147            req_receiver,
148            logging_manager,
149            backend: BackendWithOverlay::new(
150                substrate_service.backend.clone(),
151                substrate_service.storage_overrides.clone(),
152            ),
153            client: substrate_service.client.clone(),
154            mining_engine: substrate_service.mining_engine.clone(),
155            eth_rpc_client,
156            revert_manager,
157            impersonation_manager,
158            tx_pool: substrate_service.tx_pool.clone(),
159            wallet: DevSigner::new(signers)?,
160            instance_id: B256::random(),
161            filters,
162        })
163    }
164
165    pub async fn run(mut self) {
166        while let Some(msg) = self.req_receiver.next().await {
167            let resp = self.execute(msg.req).await;
168
169            if let Err(resp) = msg.resp_sender.send(resp) {
170                node_info!("Request was cancelled before sending the response: {:?}", resp);
171            }
172        }
173    }
174
175    pub async fn execute(&mut self, req: EthRequest) -> ResponseResult {
176        let res = match req.clone() {
177            EthRequest::SetLogging(enabled) => self.set_logging(enabled).to_rpc_result(),
178            //------- Gas -----------
179            EthRequest::SetNextBlockBaseFeePerGas(base_fee) => {
180                node_info!("evm_setNextBlockBaseFeePerGas");
181                let latest_block = self.latest_block();
182                // We inject in substrate storage an 1e18 denominated value after transforming it
183                // to a 1e12.
184                self.backend.inject_next_fee_multiplier(
185                    latest_block,
186                    FixedU128::from_rational(base_fee.to::<u128>(), NATIVE_TO_ETH_RATIO.into()),
187                );
188                Ok(()).to_rpc_result()
189            }
190
191            //------- Mining---------
192            EthRequest::Mine(blocks, interval) => self.mine(blocks, interval).await.to_rpc_result(),
193            EthRequest::SetIntervalMining(interval) => {
194                self.set_interval_mining(interval).to_rpc_result()
195            }
196            EthRequest::GetIntervalMining(_) => self.get_interval_mining().to_rpc_result(),
197            EthRequest::GetAutoMine(_) => self.get_auto_mine().to_rpc_result(),
198            EthRequest::SetAutomine(enabled) => self.set_auto_mine(enabled).to_rpc_result(),
199            EthRequest::EvmMine(mine) => self.evm_mine(mine).await.to_rpc_result(),
200            EthRequest::EvmMineDetailed(mine) => self.evm_mine_detailed(mine).await.to_rpc_result(),
201
202            // ---- Coinbase ----
203            EthRequest::SetCoinbase(address) => {
204                node_info!("anvil_setCoinbase");
205                let latest_block = self.latest_block();
206                let account_id = self
207                    .client
208                    .runtime_api()
209                    .account_id(latest_block, H160::from_slice(address.as_slice()))
210                    .map_err(Error::RuntimeApi);
211                account_id
212                    .map(|inner| self.backend.inject_aura_authority(latest_block, inner))
213                    .to_rpc_result()
214            }
215            EthRequest::EthCoinbase(()) => {
216                node_info!("eth_coinbase");
217                let latest_block = self.latest_block();
218                let authority =
219                    self.backend.read_aura_authority(latest_block).map_err(Error::Backend);
220                authority
221                    .and_then(|inner| {
222                        self.client
223                            .runtime_api()
224                            .address(latest_block, inner)
225                            .map_err(Error::RuntimeApi)
226                    })
227                    .map(|inner| Address::from(inner.to_fixed_bytes()))
228                    .to_rpc_result()
229            }
230
231            //------- TimeMachine---------
232            EthRequest::EvmSetBlockTimeStampInterval(time) => {
233                self.set_block_timestamp_interval(time).to_rpc_result()
234            }
235            EthRequest::EvmRemoveBlockTimeStampInterval(_) => {
236                self.remove_block_timestamp_interval().to_rpc_result()
237            }
238            EthRequest::EvmSetNextBlockTimeStamp(time) => {
239                self.set_next_block_timestamp(time).to_rpc_result()
240            }
241            EthRequest::EvmIncreaseTime(time) => self.increase_time(time).to_rpc_result(),
242            EthRequest::EvmSetTime(timestamp) => self.set_time(timestamp).to_rpc_result(),
243
244            // -- Impersonation --
245            EthRequest::ImpersonateAccount(addr) => {
246                self.impersonate_account(H160::from_slice(addr.0.as_ref())).to_rpc_result()
247            }
248            EthRequest::StopImpersonatingAccount(addr) => {
249                self.stop_impersonating_account(&H160::from_slice(addr.0.as_ref())).to_rpc_result()
250            }
251            EthRequest::AutoImpersonateAccount(enable) => {
252                self.auto_impersonate_account(enable).to_rpc_result()
253            }
254            EthRequest::EthSendUnsignedTransaction(request) => {
255                node_info!("eth_sendUnsignedTransaction");
256                self.send_transaction(*request.clone(), true).await.to_rpc_result()
257            }
258
259            //------- Eth RPCs---------
260            EthRequest::EthChainId(_) => self.eth_chain_id().to_rpc_result(),
261            EthRequest::EthNetworkId(_) => self.network_id().to_rpc_result(),
262            EthRequest::NetListening(_) => self.net_listening().to_rpc_result(),
263            EthRequest::EthSyncing(_) => self.syncing().to_rpc_result(),
264            EthRequest::EthGetTransactionReceipt(tx_hash) => {
265                self.transaction_receipt(tx_hash).await.to_rpc_result()
266            }
267            EthRequest::EthGetBalance(addr, block) => {
268                self.get_balance(addr, block).await.to_rpc_result()
269            }
270            EthRequest::EthGetStorageAt(addr, slot, block) => {
271                self.get_storage_at(addr, slot, block).await.to_rpc_result()
272            }
273            EthRequest::EthGetCodeAt(addr, block) => {
274                self.get_code(addr, block).await.to_rpc_result()
275            }
276            EthRequest::EthGetBlockByHash(hash, full) => {
277                self.get_block_by_hash(hash, full).await.to_rpc_result()
278            }
279            EthRequest::EthEstimateGas(call, block, _overrides, _block_overrides) => {
280                self.estimate_gas(call, block).await.to_rpc_result()
281            }
282            EthRequest::EthCall(call, block, _, _) => self.call(call, block).await.to_rpc_result(),
283            EthRequest::EthSendTransaction(request) => {
284                self.send_transaction(*request.clone(), false).await.to_rpc_result()
285            }
286            EthRequest::EthSendTransactionSync(request) => {
287                self.send_transaction_sync(*request).await.to_rpc_result()
288            }
289            EthRequest::EthGasPrice(()) => self.gas_price().await.to_rpc_result(),
290            EthRequest::EthGetBlockByNumber(num, hydrated) => {
291                node_info!("eth_getBlockByNumber");
292                self.get_block_by_number(num, hydrated).await.to_rpc_result()
293            }
294            EthRequest::EthGetTransactionCount(addr, block) => self
295                .get_transaction_count(ReviveAddress::from(addr).inner(), block)
296                .await
297                .map(|val| AlloyU256::from(val).inner())
298                .to_rpc_result(),
299            EthRequest::EthBlockNumber(()) => {
300                node_info!("eth_blockNumber");
301                Ok(U256::from(self.client.info().best_number)).to_rpc_result()
302            }
303            EthRequest::EthGetTransactionCountByHash(hash) => {
304                node_info!("eth_getBlockTransactionCountByHash");
305                self.get_block_transaction_count_by_hash(hash).await.to_rpc_result()
306            }
307            EthRequest::EthGetTransactionCountByNumber(num) => {
308                node_info!("eth_getBlockTransactionCountByNumber");
309                self.get_block_transaction_count_by_number(num).await.to_rpc_result()
310            }
311            EthRequest::EthGetTransactionByBlockHashAndIndex(hash, index) => {
312                node_info!("eth_getTransactionByBlockHashAndIndex");
313                self.get_transaction_by_block_hash_and_index(hash, index.into())
314                    .await
315                    .to_rpc_result()
316            }
317            EthRequest::EthGetTransactionByBlockNumberAndIndex(num, index) => {
318                node_info!("eth_getTransactionByBlockNumberAndIndex");
319                self.get_transaction_by_block_number_and_index(num, index.into())
320                    .await
321                    .to_rpc_result()
322            }
323            EthRequest::EthGetTransactionByHash(hash) => {
324                node_info!("eth_getTransactionByHash");
325                self.get_transaction_by_hash(hash).await.to_rpc_result()
326            }
327            EthRequest::Web3ClientVersion(()) => {
328                node_info!("web3_clientVersion");
329                Ok(CLIENT_VERSION.to_string()).to_rpc_result()
330            }
331            EthRequest::EthFeeHistory(count, newest, reward_percentiles) => {
332                node_info!("eth_feeHistory");
333                self.fee_history(count, newest, Some(reward_percentiles)).await.to_rpc_result()
334            }
335            EthRequest::EthMaxPriorityFeePerGas(_) => {
336                node_info!("eth_maxPriorityFeePerGas");
337                self.max_priority_fee_per_gas().await.to_rpc_result()
338            }
339            EthRequest::EthSendRawTransaction(tx) => {
340                node_info!("eth_sendRawTransaction");
341                self.send_raw_transaction(ReviveBytes::from(tx).inner()).await.to_rpc_result()
342            }
343            EthRequest::EthSendRawTransactionSync(tx) => {
344                self.send_raw_transaction_sync(ReviveBytes::from(tx).inner()).await.to_rpc_result()
345            }
346            EthRequest::EthGetLogs(filter) => {
347                node_info!("eth_getLogs");
348                self.get_logs(filter).await.to_rpc_result()
349            }
350            EthRequest::EthAccounts(_) => {
351                node_info!("eth_accounts");
352                self.accounts().to_rpc_result()
353            }
354            // ------- State injector ---------
355            EthRequest::SetBalance(address, value) => {
356                self.set_balance(address, value).to_rpc_result()
357            }
358            EthRequest::SetNonce(address, value) => self.set_nonce(address, value).to_rpc_result(),
359            EthRequest::SetCode(address, bytes) => self.set_code(address, bytes).to_rpc_result(),
360            EthRequest::SetStorageAt(address, key, value) => {
361                self.set_storage_at(address, key, value).to_rpc_result()
362            }
363            EthRequest::SetImmutableStorageAt(address, data) => {
364                self.set_immutable_storage_at(address, data).to_rpc_result()
365            }
366            EthRequest::SetChainId(chain_id) => self.set_chain_id(chain_id).to_rpc_result(),
367            // --- Revert ---
368            EthRequest::EvmSnapshot(()) => self.snapshot().await.to_rpc_result(),
369            EthRequest::Rollback(depth) => self.rollback(depth).await.to_rpc_result(),
370            EthRequest::EvmRevert(id) => self.revert(id).await.to_rpc_result(),
371            EthRequest::Reset(params) => {
372                self.reset(params.and_then(|p| p.params)).await.to_rpc_result()
373            }
374            // ------- Wallet ---------
375            EthRequest::EthSign(addr, content) => {
376                node_info!("eth_sign");
377                self.sign(addr, content).await.to_rpc_result()
378            }
379            EthRequest::EthSignTypedDataV4(addr, data) => {
380                self.sign_typed_data_v4(addr, data).await.to_rpc_result()
381            }
382            EthRequest::EthSignTypedData(addr, data) => {
383                self.sign_typed_data(addr, data).to_rpc_result()
384            }
385            EthRequest::EthSignTypedDataV3(addr, data) => {
386                self.sign_typed_data_v3(addr, data).to_rpc_result()
387            }
388            EthRequest::EthSignTransaction(request) => {
389                self.sign_transaction(*request).await.to_rpc_result()
390            }
391            EthRequest::PersonalSign(content, addr) => {
392                node_info!("personal_sign");
393                self.sign(addr, content).await.to_rpc_result()
394            }
395            EthRequest::EthGetAccount(addr, block) => {
396                self.get_account(addr, block).await.to_rpc_result()
397            }
398            EthRequest::EthGetAccountInfo(addr, block) => {
399                self.get_account_info(addr, block).await.to_rpc_result()
400            }
401            //------- Transaction Pool ---------
402            EthRequest::TxPoolStatus(_) => self.txpool_status().await.to_rpc_result(),
403            EthRequest::TxPoolInspect(_) => self.txpool_inspect().await.to_rpc_result(),
404            EthRequest::TxPoolContent(_) => self.txpool_content().await.to_rpc_result(),
405            EthRequest::DropAllTransactions() => {
406                self.anvil_drop_all_transactions().await.to_rpc_result()
407            }
408            EthRequest::DropTransaction(eth_hash) => {
409                self.anvil_drop_transaction(eth_hash).await.to_rpc_result()
410            }
411            EthRequest::RemovePoolTransactions(address) => {
412                self.anvil_remove_pool_transactions(address).await.to_rpc_result()
413            }
414            // --- Metadata ---
415            EthRequest::NodeInfo(_) => self.anvil_node_info().await.to_rpc_result(),
416            EthRequest::AnvilMetadata(_) => self.anvil_metadata().await.to_rpc_result(),
417            // --- Trace ---
418            EthRequest::DebugTraceTransaction(tx_hash, geth_tracer_options) => {
419                self.debug_trace_transaction(tx_hash, geth_tracer_options).await.to_rpc_result()
420            }
421            EthRequest::DebugTraceCall(request, block_number, geth_tracer_options) => self
422                .debug_trace_call(request, block_number, geth_tracer_options)
423                .await
424                .to_rpc_result(),
425            // Non-standard anvil RPC, comes from Geth
426            EthRequest::DebugTraceBlockByNumber(block_number, geth_tracer_options) => self
427                .debug_trace_block_by_number(block_number, geth_tracer_options)
428                .await
429                .to_rpc_result(),
430            EthRequest::TraceTransaction(tx_hash) => {
431                self.trace_transaction(tx_hash).await.to_rpc_result()
432            }
433            EthRequest::TraceBlock(block_number) => {
434                self.trace_block(block_number).await.to_rpc_result()
435            }
436            // --- Filters ---
437            EthRequest::EthNewFilter(filter) => {
438                self.new_filter(ReviveFilter::from(filter).into_inner()).await.to_rpc_result()
439            }
440            EthRequest::EthGetFilterLogs(id) => self.get_filter_logs(&id).await.to_rpc_result(),
441            EthRequest::EthGetFilterChanges(id) => self.get_filter_changes(&id).await,
442            EthRequest::EthNewBlockFilter(_) => self.new_block_filter().await.to_rpc_result(),
443            EthRequest::EthNewPendingTransactionFilter(_) => {
444                self.new_pending_transactions_filter().await.to_rpc_result()
445            }
446            EthRequest::EthUninstallFilter(id) => self.uninstall_filter(&id).await.to_rpc_result(),
447            _ => Err::<(), _>(Error::RpcUnimplemented).to_rpc_result(),
448        };
449
450        if let ResponseResult::Error(err) = &res {
451            node_info!("\nRPC request failed:");
452            node_info!("    Request: {:?}", req);
453            node_info!("    Error: {}\n", err);
454        }
455
456        res
457    }
458
459    fn set_logging(&self, enabled: bool) -> Result<()> {
460        node_info!("anvil_setLoggingEnabled");
461
462        self.logging_manager.set_enabled(enabled);
463        Ok(())
464    }
465
466    // Mining related RPCs.
467    async fn mine(&self, blocks: Option<U256>, interval: Option<U256>) -> Result<()> {
468        node_info!("anvil_mine");
469
470        if blocks.is_some_and(|b| u64::try_from(b).is_err()) {
471            return Err(Error::InvalidParams("The number of blocks is too large".to_string()));
472        }
473        if interval.is_some_and(|i| u64::try_from(i).is_err()) {
474            return Err(Error::InvalidParams(
475                "The interval between blocks is too large".to_string(),
476            ));
477        }
478
479        // Subscribe to new best blocks.
480        let receiver = self.eth_rpc_client.block_notifier().map(|sender| sender.subscribe());
481
482        let awaited_hash = self
483            .mining_engine
484            .mine(blocks.map(|b| b.to()), interval.map(|i| Duration::from_secs(i.to())))
485            .await
486            .map_err(Error::Mining)?;
487        self.wait_for_hash(receiver, awaited_hash).await?;
488        Ok(())
489    }
490
491    fn set_interval_mining(&self, interval: u64) -> Result<()> {
492        node_info!("evm_setIntervalMining");
493
494        self.mining_engine.set_interval_mining(Duration::from_secs(interval));
495        Ok(())
496    }
497
498    fn get_interval_mining(&self) -> Result<Option<u64>> {
499        node_info!("anvil_getIntervalMining");
500
501        Ok(self.mining_engine.get_interval_mining())
502    }
503
504    fn get_auto_mine(&self) -> Result<bool> {
505        node_info!("anvil_getAutomine");
506
507        Ok(self.mining_engine.is_automine())
508    }
509
510    fn set_auto_mine(&self, enabled: bool) -> Result<()> {
511        node_info!("evm_setAutomine");
512
513        self.mining_engine.set_auto_mine(enabled);
514        Ok(())
515    }
516
517    async fn evm_mine(&self, mine: Option<AnvilCoreParams<Option<MineOptions>>>) -> Result<String> {
518        node_info!("evm_mine");
519
520        // Subscribe to new best blocks.
521        let receiver = self.eth_rpc_client.block_notifier().map(|sender| sender.subscribe());
522        let awaited_hash = self.mining_engine.evm_mine(mine.and_then(|p| p.params)).await?;
523        self.wait_for_hash(receiver, awaited_hash).await?;
524        Ok("0x0".to_string())
525    }
526
527    async fn evm_mine_detailed(
528        &self,
529        mine: Option<AnvilCoreParams<Option<MineOptions>>>,
530    ) -> Result<Vec<Block>> {
531        node_info!("evm_mineDetailed");
532
533        // Subscribe to new best blocks.
534        let receiver = self.eth_rpc_client.block_notifier().map(|sender| sender.subscribe());
535
536        let (mined_blocks, awaited_hash) =
537            self.mining_engine.do_evm_mine(mine.and_then(|p| p.params)).await?;
538
539        self.wait_for_hash(receiver, awaited_hash).await?;
540
541        let mut blocks = Vec::with_capacity(mined_blocks as usize);
542        let last_block = self.client.info().best_number as u64;
543        let starting = last_block - mined_blocks + 1;
544        for block_number in starting..=last_block {
545            if let Some(block) =
546                self.get_block_by_number(BlockNumberOrTag::Number(block_number), true).await?
547            {
548                blocks.push(block);
549            }
550        }
551        Ok(blocks)
552    }
553
554    // TimeMachine RPCs
555    fn set_block_timestamp_interval(&self, time: u64) -> Result<()> {
556        node_info!("anvil_setBlockTimestampInterval");
557
558        self.mining_engine.set_block_timestamp_interval(Duration::from_secs(time));
559        Ok(())
560    }
561
562    fn remove_block_timestamp_interval(&self) -> Result<bool> {
563        node_info!("anvil_removeBlockTimestampInterval");
564
565        Ok(self.mining_engine.remove_block_timestamp_interval())
566    }
567
568    fn set_next_block_timestamp(&self, time: U256) -> Result<()> {
569        node_info!("evm_setNextBlockTimeStamp");
570
571        if time >= U256::from(u64::MAX) {
572            return Err(Error::InvalidParams("The timestamp is too big".to_string()));
573        }
574        let time = time.to::<u64>();
575        self.mining_engine
576            .set_next_block_timestamp(Duration::from_secs(time))
577            .map_err(Error::Mining)
578    }
579
580    fn increase_time(&self, time: U256) -> Result<i64> {
581        node_info!("evm_increaseTime");
582
583        Ok(self.mining_engine.increase_time(Duration::from_secs(time.try_into().unwrap_or(0))))
584    }
585
586    fn set_time(&self, timestamp: U256) -> Result<u64> {
587        node_info!("evm_setTime");
588
589        if timestamp >= U256::from(u64::MAX) {
590            return Err(Error::InvalidParams("The timestamp is too big".to_string()));
591        }
592        let time = timestamp.to::<u64>();
593        let time_ms = time.saturating_mul(1000);
594        // Get the time for the last block.
595        let latest_block = self.latest_block();
596        let last_block_timestamp = self.backend.read_timestamp(latest_block)?;
597        // Inject the new time if the timestamp precedes last block time
598        if time_ms < last_block_timestamp {
599            self.backend.inject_timestamp(latest_block, time_ms);
600        }
601        Ok(self.mining_engine.set_time(Duration::from_secs(time)))
602    }
603
604    // Impersonation RPC
605    fn impersonate_account(&mut self, addr: H160) -> Result<()> {
606        node_info!("anvil_impersonateAccount");
607        self.impersonation_manager.impersonate(addr);
608        Ok(())
609    }
610
611    fn auto_impersonate_account(&mut self, enable: bool) -> Result<()> {
612        node_info!("anvil_autoImpersonateAccount");
613        self.impersonation_manager.set_auto_impersonate_account(enable);
614        Ok(())
615    }
616
617    fn stop_impersonating_account(&mut self, addr: &H160) -> Result<()> {
618        node_info!("anvil_stopImpersonatingAccount");
619        self.impersonation_manager.stop_impersonating(addr);
620        Ok(())
621    }
622
623    fn chain_id(&self, at: Hash) -> u64 {
624        self.backend.read_chain_id(at).expect("Chain ID is populated on genesis")
625    }
626
627    // Eth RPCs
628    fn eth_chain_id(&self) -> Result<U64> {
629        node_info!("eth_chainId");
630        let latest_block = self.latest_block();
631
632        Ok(U256::from(self.chain_id(latest_block)).to::<U64>())
633    }
634
635    fn network_id(&self) -> Result<u64> {
636        node_info!("eth_networkId");
637        let latest_block = self.latest_block();
638
639        Ok(self.chain_id(latest_block))
640    }
641
642    fn net_listening(&self) -> Result<bool> {
643        node_info!("net_listening");
644        Ok(true)
645    }
646
647    fn syncing(&self) -> Result<bool> {
648        node_info!("eth_syncing");
649        Ok(false)
650    }
651
652    async fn transaction_receipt(&self, tx_hash: B256) -> Result<Option<ReceiptInfo>> {
653        node_info!("eth_getTransactionReceipt");
654        Ok(self.eth_rpc_client.receipt(&(tx_hash.0.into())).await)
655    }
656
657    async fn get_balance(&self, addr: Address, block: Option<BlockId>) -> Result<U256> {
658        node_info!("eth_getBalance");
659        let hash = self.get_block_hash_for_tag(block).await?;
660
661        let runtime_api = self.eth_rpc_client.runtime_api(hash);
662        let balance = runtime_api.balance(ReviveAddress::from(addr).inner()).await?;
663        Ok(AlloyU256::from(balance).inner())
664    }
665
666    async fn get_storage_at(
667        &self,
668        addr: Address,
669        slot: U256,
670        block: Option<BlockId>,
671    ) -> Result<B256> {
672        node_info!("eth_getStorageAt");
673        let hash = self.get_block_hash_for_tag(block).await?;
674        let runtime_api = self.eth_rpc_client.runtime_api(hash);
675        let bytes: B256 = match runtime_api
676            .get_storage(ReviveAddress::from(addr).inner(), slot.to_be_bytes())
677            .await
678        {
679            Ok(Some(bytes)) => bytes.as_slice().try_into().map_err(|_| {
680                Error::InternalError("Unable to convert value to 32-byte value".to_string())
681            })?,
682            Ok(None) | Err(ClientError::ContractNotFound) => Default::default(),
683            Err(err) => return Err(Error::ReviveRpc(EthRpcError::ClientError(err))),
684        };
685        Ok(bytes)
686    }
687
688    async fn get_code(&self, address: Address, block: Option<BlockId>) -> Result<Bytes> {
689        node_info!("eth_getCode");
690
691        let hash = self.get_block_hash_for_tag(block).await?;
692        let code = self
693            .eth_rpc_client
694            .runtime_api(hash)
695            .code(ReviveAddress::from(address).inner())
696            .await?;
697        Ok(code.into())
698    }
699
700    /// Returns the EVM block with the given ethereum hash.
701    async fn get_block_by_hash(
702        &self,
703        block_hash: B256,
704        hydrated_transactions: bool,
705    ) -> Result<Option<Block>> {
706        node_info!("eth_getBlockByHash");
707        let Some(block) = self
708            .eth_rpc_client
709            .block_by_ethereum_hash(&H256::from_slice(block_hash.as_slice()))
710            .await?
711        else {
712            return Ok(None);
713        };
714        let block = self.eth_rpc_client.evm_block(block, hydrated_transactions).await;
715        Ok(block)
716    }
717
718    async fn estimate_gas(
719        &self,
720        request: WithOtherFields<TransactionRequest>,
721        block: Option<BlockId>,
722    ) -> Result<sp_core::U256> {
723        node_info!("eth_estimateGas");
724
725        let hash = self.get_block_hash_for_tag(block).await?;
726        let runtime_api = self.eth_rpc_client.runtime_api(hash);
727        let dry_run = runtime_api
728            .dry_run(
729                convert_to_generic_transaction(request.into_inner()),
730                ReviveBlockId::from(block).inner(),
731            )
732            .await?;
733        Ok(dry_run.eth_gas)
734    }
735
736    async fn call(
737        &self,
738        request: WithOtherFields<TransactionRequest>,
739        block: Option<BlockId>,
740    ) -> Result<Bytes> {
741        node_info!("eth_call");
742
743        let hash = self.get_block_hash_for_tag(block).await?;
744
745        let runtime_api = self.eth_rpc_client.runtime_api(hash);
746        let dry_run = runtime_api
747            .dry_run(
748                convert_to_generic_transaction(request.into_inner()),
749                ReviveBlockId::from(block).inner(),
750            )
751            .await?;
752
753        Ok(dry_run.data.into())
754    }
755
756    async fn gas_price(&self) -> Result<sp_core::U256> {
757        node_info!("eth_gasPrice");
758
759        let hash = self.latest_block();
760
761        let runtime_api = self.eth_rpc_client.runtime_api(hash);
762        runtime_api.gas_price().await.map_err(Error::from)
763    }
764
765    async fn get_transaction_count(
766        &self,
767        address: H160,
768        block: Option<BlockId>,
769    ) -> Result<sp_core::U256> {
770        node_info!("eth_getTransactionCount");
771        let hash = self.get_block_hash_for_tag(block).await?;
772        let runtime_api = self.eth_rpc_client.runtime_api(hash);
773        let nonce = runtime_api.nonce(address).await?;
774        Ok(nonce)
775    }
776
777    async fn send_raw_transaction(&self, transaction: Bytes) -> Result<H256> {
778        let hash = H256(keccak_256(&transaction.0));
779        let call = subxt_client::tx().revive().eth_transact(transaction.0);
780        self.eth_rpc_client.submit(call).await?;
781        Ok(hash)
782    }
783
784    pub async fn send_raw_transaction_sync(&self, tx: Bytes) -> Result<ReceiptInfo> {
785        node_info!("eth_sendRawTransactionSync");
786        // Subscribe to new best blocks.
787        let receiver = self
788            .eth_rpc_client
789            .block_notifier()
790            .ok_or_else(|| {
791                Error::InternalError("Invalid receiver. Unable to wait for receipt".to_string())
792            })?
793            .subscribe();
794        let hash = B256::from_slice(self.send_raw_transaction(tx).await?.as_ref());
795        self.wait_for_receipt(hash, receiver).await
796    }
797
798    async fn send_transaction(
799        &self,
800        transaction_req: WithOtherFields<TransactionRequest>,
801        unsigned_tx: bool,
802    ) -> Result<H256> {
803        node_info!("eth_sendTransaction");
804        let mut transaction = convert_to_generic_transaction(transaction_req.clone().into_inner());
805        let Some(from) = transaction.from else {
806            return Err(Error::ReviveRpc(EthRpcError::InvalidTransaction));
807        };
808
809        let best_hash = self.latest_block();
810        let best_eth_hash =
811            self.eth_rpc_client.resolve_ethereum_hash(&best_hash).await.ok_or_else(|| {
812                Error::InternalError("Ethereum block hash of latest block not found".to_string())
813            })?;
814        let latest_block_id = Some(BlockId::hash(B256::from_slice(best_eth_hash.as_ref())));
815        let account = if self.impersonation_manager.is_impersonated(from) || unsigned_tx {
816            None
817        } else {
818            Some(
819                *self
820                    .accounts()?
821                    .iter()
822                    .find(|account| **account == from)
823                    .ok_or(Error::ReviveRpc(EthRpcError::AccountNotFound(from)))?,
824            )
825        };
826
827        if transaction.gas.is_none() {
828            transaction.gas =
829                Some(self.estimate_gas(transaction_req.clone(), latest_block_id).await?);
830        }
831
832        if transaction.gas_price.is_none() {
833            transaction.gas_price = Some(self.gas_price().await?);
834        }
835
836        if transaction.nonce.is_none() {
837            transaction.nonce = Some(self.get_transaction_count(from, latest_block_id).await?);
838        }
839
840        if transaction.chain_id.is_none() {
841            transaction.chain_id =
842                Some(sp_core::U256::from_big_endian(&self.chain_id(best_hash).to_be_bytes()));
843        }
844
845        let tx = transaction
846            .try_into_unsigned()
847            .map_err(|_| Error::ReviveRpc(EthRpcError::InvalidTransaction))?;
848
849        let payload = match account {
850            Some(addr) => self
851                .wallet
852                .sign_transaction(Address::from(ReviveAddress::new(addr)), tx)?
853                .signed_payload(),
854            None => {
855                // Create impersonated signature format:
856                // [0; 12] + [address; 20] + [IMPERSONATION_MARKER; 32] + [recovery_id; 1]
857                // The recovery_id (byte 64) must be 0 or 1 for valid ECDSA signatures
858                use crate::substrate_node::host::IMPERSONATION_MARKER;
859                let mut fake_signature = [IMPERSONATION_MARKER; 65];
860                fake_signature[..12].fill(0);
861                fake_signature[12..32].copy_from_slice(from.as_bytes());
862                fake_signature[64] = 0; // Valid recovery ID
863                tx.with_signature(fake_signature).signed_payload()
864            }
865        };
866
867        self.send_raw_transaction(Bytes(payload)).await
868    }
869
870    async fn send_transaction_sync(
871        &self,
872        request: WithOtherFields<TransactionRequest>,
873    ) -> Result<ReceiptInfo> {
874        node_info!("eth_sendTransactionSync");
875        // Subscribe to new best blocks.
876        let receiver = self
877            .eth_rpc_client
878            .block_notifier()
879            .ok_or_else(|| {
880                Error::InternalError("Invalid receiver. Unable to wait for receipt".to_string())
881            })?
882            .subscribe();
883        let hash = B256::from_slice(self.send_transaction(request, false).await?.as_ref());
884        self.wait_for_receipt(hash, receiver).await
885    }
886
887    async fn get_block_by_number(
888        &self,
889        block_number: BlockNumberOrTag,
890        hydrated_transactions: bool,
891    ) -> Result<Option<Block>> {
892        let Some(block) = self
893            .eth_rpc_client
894            .block_by_number_or_tag(&ReviveBlockNumberOrTag::from(block_number).inner())
895            .await?
896        else {
897            return Ok(None);
898        };
899        let block = self.eth_rpc_client.evm_block(block, hydrated_transactions).await;
900        Ok(block)
901    }
902
903    pub(crate) async fn snapshot(&mut self) -> Result<U256> {
904        node_info!("evm_snapshot");
905        Ok(self.revert_manager.snapshot())
906    }
907
908    pub(crate) async fn revert(&mut self, id: U256) -> Result<bool> {
909        node_info!("evm_revert");
910        let res = self
911            .revert_manager
912            .revert(id)
913            .map_err(|err| Error::Backend(BackendError::Client(err)))?;
914        let Some(res) = res else { return Ok(false) };
915
916        self.on_revert_update(res).await?;
917
918        Ok(true)
919    }
920
921    /// Reset to genesis if no forking information is set.
922    ///
923    /// TODO: currently the forking information is not consider at the
924    /// RPC level, but it will need to be considered once forking feature
925    /// is functional.
926    pub(crate) async fn reset(&mut self, forking: Option<Forking>) -> Result<()> {
927        self.instance_id = B256::random();
928        node_info!("anvil_reset");
929        // TODO: should be removed once forking feature is implemented and support is added in
930        // revert manager to handle it
931        if forking.is_some() {
932            return Err(Error::RpcUnimplemented);
933        }
934
935        let res = self
936            .revert_manager
937            .reset_to_genesis()
938            .map_err(|err| Error::Backend(BackendError::Client(err)))?;
939
940        self.on_revert_update(res).await
941    }
942
943    pub(crate) async fn rollback(&mut self, depth: Option<u64>) -> Result<()> {
944        node_info!("anvil_rollback");
945        let res = self
946            .revert_manager
947            .rollback(depth)
948            .map_err(|err| Error::Backend(BackendError::Client(err)))?;
949
950        self.on_revert_update(res).await?;
951
952        Ok(())
953    }
954
955    async fn anvil_node_info(&self) -> Result<NodeInfo> {
956        node_info!("anvil_nodeInfo");
957
958        let best_hash = self.latest_block();
959        let Some(latest_evm_block) = self.get_block_by_substrate_hash(best_hash).await? else {
960            return Err(Error::InternalError("Latest block not found".to_string()));
961        };
962        let current_block_number: u64 =
963            latest_evm_block.number.try_into().map_err(|_| EthRpcError::ConversionError)?;
964        let current_block_timestamp: u64 =
965            latest_evm_block.timestamp.try_into().map_err(|_| EthRpcError::ConversionError)?;
966        // This is both gas price and base fee, since pallet-revive does not support tips
967        // https://github.com/paritytech/polkadot-sdk/blob/227c73b5c8810c0f34e87447f00e96743234fa52/substrate/frame/revive/rpc/src/lib.rs#L269
968        let base_fee: u128 = latest_evm_block
969            .base_fee_per_gas
970            .try_into()
971            .map_err(|_| EthRpcError::ConversionError)?;
972        let gas_limit: u64 = latest_evm_block.gas_limit.try_into().unwrap_or(u64::MAX);
973        // pallet-revive should currently support all opcodes in PRAGUE.
974        let hard_fork: &str = SpecId::PRAGUE.into();
975
976        Ok(NodeInfo {
977            current_block_number,
978            current_block_timestamp,
979            current_block_hash: B256::from_slice(latest_evm_block.hash.as_ref()),
980            hard_fork: hard_fork.to_string(),
981            // pallet-revive does not support tips
982            transaction_order: "fifo".to_string(),
983            environment: NodeEnvironment {
984                base_fee,
985                chain_id: self.chain_id(best_hash),
986                gas_limit,
987                gas_price: base_fee,
988            },
989            // Forking is not supported yet in anvil-polkadot
990            fork_config: Default::default(),
991        })
992    }
993
994    async fn anvil_metadata(&self) -> Result<AnvilMetadata> {
995        node_info!("anvil_metadata");
996
997        let best_hash = self.latest_block();
998        let Some(latest_evm_block) = self.get_block_by_substrate_hash(best_hash).await? else {
999            return Err(Error::InternalError("Latest block not found".to_string()));
1000        };
1001        let latest_block_number: u64 =
1002            latest_evm_block.number.try_into().map_err(|_| EthRpcError::ConversionError)?;
1003
1004        Ok(AnvilMetadata {
1005            client_version: CLIENT_VERSION.to_string(),
1006            chain_id: self.chain_id(best_hash),
1007            latest_block_hash: B256::from_slice(latest_evm_block.hash.as_ref()),
1008            latest_block_number,
1009            instance_id: self.instance_id,
1010            // Forking is not supported yet in anvil-polkadot
1011            forked_network: None,
1012            snapshots: self.revert_manager.list_snapshots(),
1013        })
1014    }
1015
1016    async fn get_block_transaction_count_by_hash(&self, block_hash: B256) -> Result<Option<U256>> {
1017        let block_hash = H256::from_slice(block_hash.as_slice());
1018        Ok(self.eth_rpc_client.receipts_count_per_block(&block_hash).await.map(U256::from))
1019    }
1020
1021    async fn get_block_transaction_count_by_number(
1022        &self,
1023        block_number: BlockNumberOrTag,
1024    ) -> Result<Option<U256>> {
1025        let Some(hash) =
1026            self.maybe_get_block_hash_for_tag(Some(BlockId::Number(block_number))).await?
1027        else {
1028            return Ok(None);
1029        };
1030
1031        Ok(self.eth_rpc_client.receipts_count_per_block(&hash).await.map(U256::from))
1032    }
1033
1034    async fn get_transaction_by_block_hash_and_index(
1035        &self,
1036        block_hash: B256,
1037        transaction_index: U256,
1038    ) -> Result<Option<TransactionInfo>> {
1039        let Some(receipt) = self
1040            .eth_rpc_client
1041            .receipt_by_hash_and_index(
1042                &H256::from_slice(block_hash.as_ref()),
1043                transaction_index.try_into().map_err(|_| EthRpcError::ConversionError)?,
1044            )
1045            .await
1046        else {
1047            return Ok(None);
1048        };
1049
1050        let Some(signed_tx) =
1051            self.eth_rpc_client.signed_tx_by_hash(&receipt.transaction_hash).await
1052        else {
1053            return Ok(None);
1054        };
1055
1056        Ok(Some(TransactionInfo::new(&receipt, signed_tx)))
1057    }
1058
1059    async fn get_transaction_by_block_number_and_index(
1060        &self,
1061        block: BlockNumberOrTag,
1062        transaction_index: U256,
1063    ) -> Result<Option<TransactionInfo>> {
1064        let Some(block) = self
1065            .eth_rpc_client
1066            .block_by_number_or_tag(&ReviveBlockNumberOrTag::from(block).inner())
1067            .await?
1068        else {
1069            return Ok(None);
1070        };
1071        self.get_transaction_by_block_hash_and_index(
1072            B256::from_slice(block.hash().as_ref()),
1073            transaction_index,
1074        )
1075        .await
1076    }
1077
1078    async fn get_transaction_by_hash(
1079        &self,
1080        transaction_hash: B256,
1081    ) -> Result<Option<TransactionInfo>> {
1082        let tx_hash = H256::from_slice(transaction_hash.as_ref());
1083        let receipt = self.eth_rpc_client.receipt(&tx_hash).await;
1084        let signed_tx = self.eth_rpc_client.signed_tx_by_hash(&tx_hash).await;
1085        if let (Some(receipt), Some(signed_tx)) = (receipt, signed_tx) {
1086            return Ok(Some(TransactionInfo::new(&receipt, signed_tx)));
1087        }
1088
1089        Ok(None)
1090    }
1091
1092    async fn fee_history(
1093        &self,
1094        block_count: U256,
1095        newest_block: BlockNumberOrTag,
1096        reward_percentiles: Option<Vec<f64>>,
1097    ) -> Result<FeeHistoryResult> {
1098        let block_count: u32 = block_count.try_into().map_err(|_| EthRpcError::ConversionError)?;
1099        let result = self
1100            .eth_rpc_client
1101            .fee_history(
1102                block_count,
1103                ReviveBlockNumberOrTag::from(newest_block).inner(),
1104                reward_percentiles,
1105            )
1106            .await?;
1107        Ok(result)
1108    }
1109
1110    async fn max_priority_fee_per_gas(&self) -> Result<sp_core::U256> {
1111        // We do not support tips. Hence the recommended priority fee is
1112        // always zero. The effective gas price will always be the base price.
1113        Ok(Default::default())
1114    }
1115
1116    pub fn accounts(&self) -> Result<Vec<H160>> {
1117        node_info!("eth_accounts");
1118        // Use an ordered set, so that the order is maintained between calls.
1119        let mut accounts = BTreeSet::new();
1120
1121        accounts.extend(self.wallet.accounts());
1122        accounts.extend(self.impersonation_manager.impersonated_accounts.clone());
1123        Ok(accounts.into_iter().collect())
1124    }
1125
1126    async fn get_logs(&self, filter: Filter) -> Result<FilterResults> {
1127        let logs = self.eth_rpc_client.logs(Some(ReviveFilter::from(filter).into_inner())).await?;
1128        Ok(FilterResults::Logs(logs))
1129    }
1130
1131    // State injector RPCs
1132    fn set_chain_id(&self, chain_id: u64) -> Result<()> {
1133        node_info!("anvil_setChainId");
1134
1135        let latest_block = self.latest_block();
1136        self.backend.inject_chain_id(latest_block, chain_id);
1137
1138        Ok(())
1139    }
1140
1141    fn set_balance(&self, address: Address, value: U256) -> Result<()> {
1142        node_info!("anvil_setBalance");
1143
1144        let latest_block = self.latest_block();
1145
1146        let (new_balance, dust) = self.construct_balance_with_dust(latest_block, value)?;
1147
1148        let account_id = self.get_account_id(latest_block, address)?;
1149        self.set_frame_system_balance(latest_block, account_id, new_balance)?;
1150
1151        let mut revive_account_info = self
1152            .backend
1153            .read_revive_account_info(latest_block, address)?
1154            .unwrap_or(ReviveAccountInfo { account_type: AccountType::EOA, dust: 0 });
1155
1156        if revive_account_info.dust != dust {
1157            revive_account_info.dust = dust;
1158
1159            self.backend.inject_revive_account_info(latest_block, address, revive_account_info);
1160        }
1161
1162        Ok(())
1163    }
1164
1165    fn set_nonce(&self, address: Address, value: U256) -> Result<()> {
1166        node_info!("anvil_setNonce");
1167
1168        let latest_block = self.latest_block();
1169
1170        let account_id = self.get_account_id(latest_block, address)?;
1171
1172        let mut account_info = self
1173            .backend
1174            .read_system_account_info(latest_block, account_id.clone())?
1175            .unwrap_or_else(|| SystemAccountInfo { providers: 1, ..Default::default() });
1176
1177        account_info.nonce = value.try_into().map_err(|_| Error::NonceOverflow)?;
1178
1179        self.backend.inject_system_account_info(latest_block, account_id, account_info);
1180
1181        Ok(())
1182    }
1183
1184    fn set_storage_at(&self, address: Address, key: U256, value: B256) -> Result<()> {
1185        node_info!("anvil_setStorageAt");
1186
1187        let latest_block = self.latest_block();
1188
1189        let account_id = self.get_account_id(latest_block, address)?;
1190
1191        let maybe_system_account_info =
1192            self.backend.read_system_account_info(latest_block, account_id.clone())?;
1193        let nonce = maybe_system_account_info.as_ref().map(|info| info.nonce).unwrap_or_default();
1194
1195        if maybe_system_account_info.is_none() {
1196            self.set_frame_system_balance(
1197                latest_block,
1198                account_id,
1199                substrate_runtime::currency::DOLLARS,
1200            )?;
1201        }
1202
1203        let trie_id = match self.backend.read_revive_account_info(latest_block, address)? {
1204            // If the account doesn't exist, create one.
1205            None => {
1206                let contract_info = new_contract_info(&address, (*KECCAK_EMPTY).into(), nonce);
1207                let trie_id = contract_info.trie_id.0.clone();
1208
1209                self.backend.inject_revive_account_info(
1210                    latest_block,
1211                    address,
1212                    ReviveAccountInfo {
1213                        account_type: AccountType::Contract(contract_info),
1214                        dust: 0,
1215                    },
1216                );
1217
1218                trie_id
1219            }
1220            // If the account is not already a contract account, make it one.
1221            Some(ReviveAccountInfo { account_type: AccountType::EOA, dust }) => {
1222                let contract_info = new_contract_info(&address, (*KECCAK_EMPTY).into(), nonce);
1223                let trie_id = contract_info.trie_id.0.clone();
1224
1225                self.backend.inject_revive_account_info(
1226                    latest_block,
1227                    address,
1228                    ReviveAccountInfo { account_type: AccountType::Contract(contract_info), dust },
1229                );
1230
1231                trie_id
1232            }
1233            Some(ReviveAccountInfo {
1234                account_type: AccountType::Contract(contract_info), ..
1235            }) => contract_info.trie_id.0,
1236        };
1237
1238        self.backend.inject_child_storage(
1239            latest_block,
1240            trie_id,
1241            key.to_be_bytes_vec(),
1242            value.to_vec(),
1243        );
1244
1245        Ok(())
1246    }
1247
1248    fn set_code(&self, address: Address, bytes: alloy_primitives::Bytes) -> Result<()> {
1249        node_info!("anvil_setCode");
1250
1251        let latest_block = self.latest_block();
1252
1253        let account_id = self.get_account_id(latest_block, address)?;
1254
1255        let code_hash = H256(keccak_256(&bytes));
1256
1257        let maybe_system_account_info =
1258            self.backend.read_system_account_info(latest_block, account_id.clone())?;
1259        let nonce = maybe_system_account_info.as_ref().map(|info| info.nonce).unwrap_or_default();
1260
1261        if maybe_system_account_info.is_none() {
1262            self.set_frame_system_balance(
1263                latest_block,
1264                account_id.clone(),
1265                substrate_runtime::currency::DOLLARS,
1266            )?;
1267        }
1268
1269        let mut old_code_info = None;
1270        let revive_account_info = match self
1271            .backend
1272            .read_revive_account_info(latest_block, address)?
1273        {
1274            None => {
1275                let contract_info = new_contract_info(&address, code_hash, nonce);
1276
1277                ReviveAccountInfo { account_type: AccountType::Contract(contract_info), dust: 0 }
1278            }
1279            Some(ReviveAccountInfo { account_type: AccountType::EOA, dust }) => {
1280                let contract_info = new_contract_info(&address, code_hash, nonce);
1281
1282                ReviveAccountInfo { account_type: AccountType::Contract(contract_info), dust }
1283            }
1284            Some(ReviveAccountInfo {
1285                account_type: AccountType::Contract(mut contract_info),
1286                dust,
1287            }) => {
1288                if let Some(code_info) =
1289                    self.backend.read_code_info(latest_block, contract_info.code_hash)?
1290                {
1291                    if code_info.refcount == 1 && contract_info.code_hash != code_hash {
1292                        // Remove the pristine code and code info for the old hash.
1293                        self.backend.inject_pristine_code(
1294                            latest_block,
1295                            contract_info.code_hash,
1296                            None,
1297                        );
1298                        self.backend.inject_code_info(latest_block, contract_info.code_hash, None);
1299                    }
1300
1301                    old_code_info = Some(code_info);
1302                }
1303
1304                contract_info.code_hash = code_hash;
1305
1306                ReviveAccountInfo { account_type: AccountType::Contract(contract_info), dust }
1307            }
1308        };
1309
1310        self.backend.inject_revive_account_info(latest_block, address, revive_account_info);
1311
1312        let code_info = old_code_info
1313            .map(|mut code_info| {
1314                code_info.code_len = bytes.len() as u32;
1315                code_info.code_type = BytecodeType::Evm;
1316                code_info
1317            })
1318            .unwrap_or_else(|| CodeInfo {
1319                owner: <[u8; 32]>::from(account_id).into(),
1320                deposit: Default::default(),
1321                refcount: 1,
1322                code_len: bytes.len() as u32,
1323                behaviour_version: 0,
1324                code_type: BytecodeType::Evm,
1325            });
1326
1327        self.backend.inject_pristine_code(latest_block, code_hash, Some(bytes));
1328        self.backend.inject_code_info(latest_block, code_hash, Some(code_info));
1329
1330        Ok(())
1331    }
1332
1333    fn set_immutable_storage_at(
1334        &self,
1335        address: Address,
1336        immutables: Vec<alloy_primitives::Bytes>,
1337    ) -> Result<()> {
1338        node_info!("anvil_setImmutableStorageAt");
1339
1340        let latest_block = self.latest_block();
1341
1342        // Convert ABI-encoded immutable values (big-endian) to PVM format (little-endian).
1343        //
1344        // ## Data Format
1345        //
1346        // Each element in `immutables` is a single ABI-encoded immutable value:
1347        // - Value in big-endian format (standard for Solidity ABI encoding)
1348        // - Padded to 32 bytes
1349        //
1350        // Example: For a contract with immutables `uint256 value` and `address addr`:
1351        //   immutables[0] = <32-byte big-endian uint256>
1352        //   immutables[1] = <12 zeros + 20-byte address>
1353        //
1354        // ## Conversion
1355        //
1356        // This method converts each immutable value (32-byte chunk) from big-endian to
1357        // little-endian, since PVM (Polkadot Virtual Machine) expects immutable data in
1358        // little-endian format. The conversion is done by reversing each 32-byte word.
1359        // Then all converted values are concatenated in order.
1360        let pvm_data: Vec<u8> = immutables
1361            .into_iter()
1362            .flat_map(|immutable| {
1363                let mut word = [0u8; 32];
1364                let len = immutable.len().min(32);
1365                word[..len].copy_from_slice(&immutable[..len]);
1366                word.reverse();
1367                word
1368            })
1369            .collect();
1370
1371        self.backend.inject_immutable_data(latest_block, address, pvm_data);
1372
1373        Ok(())
1374    }
1375
1376    // ----- Wallet RPCs
1377    async fn sign(&self, address: Address, content: impl AsRef<[u8]>) -> Result<String> {
1378        Ok(alloy_primitives::hex::encode_prefixed(self.wallet.sign(address, content.as_ref())?))
1379    }
1380
1381    fn sign_typed_data(&self, _address: Address, _data: serde_json::Value) -> Result<String> {
1382        node_info!("eth_signTypedData");
1383        Err(Error::RpcUnimplemented)
1384    }
1385
1386    fn sign_typed_data_v3(&self, _address: Address, _data: serde_json::Value) -> Result<String> {
1387        node_info!("eth_signTypedData_v3");
1388        Err(Error::RpcUnimplemented)
1389    }
1390
1391    async fn sign_transaction(
1392        &self,
1393        tx: WithOtherFields<TransactionRequest>,
1394    ) -> Result<TransactionSigned> {
1395        node_info!("eth_signTransaction");
1396        let from = tx.inner().from.ok_or(Error::ReviveRpc(EthRpcError::InvalidTransaction))?;
1397        let generic_transaction = convert_to_generic_transaction(tx.into_inner());
1398        let unsigned_transaction = generic_transaction
1399            .try_into_unsigned()
1400            .map_err(|_| Error::ReviveRpc(EthRpcError::InvalidTransaction))?;
1401        self.wallet.sign_transaction(from, unsigned_transaction)
1402    }
1403
1404    async fn sign_typed_data_v4(&self, address: Address, data: TypedData) -> Result<String> {
1405        node_info!("eth_signTypedData_v4");
1406        Ok(alloy_primitives::hex::encode_prefixed(self.wallet.sign_typed_data(address, &data)?))
1407    }
1408
1409    async fn get_account(
1410        &self,
1411        address: Address,
1412        block_number: Option<BlockId>,
1413    ) -> Result<TrieAccount> {
1414        node_info!("eth_getAccount");
1415        let addr = ReviveAddress::from(address).inner();
1416        let nonce = self.get_transaction_count(addr, block_number).await?;
1417        let balance = self.get_balance(address, block_number).await?;
1418        let code = self.get_code(address, block_number).await?;
1419        let code_hash =
1420            if code.is_empty() { KECCAK_EMPTY } else { B256::from(keccak_256(&code.0)) };
1421        // TODO: Compute real hash
1422        let storage_root = EMPTY_ROOT_HASH;
1423
1424        Ok(TrieAccount { nonce: nonce.as_u64(), balance, storage_root, code_hash })
1425    }
1426
1427    async fn get_account_info(
1428        &self,
1429        address: Address,
1430        block_number: Option<BlockId>,
1431    ) -> Result<alloy_rpc_types::eth::AccountInfo> {
1432        node_info!("eth_getAccountInfo");
1433        let account = self.get_account(address, block_number);
1434        let code = self.get_code(address, block_number);
1435        let (account, code) = try_join!(account, code)?;
1436        Ok(alloy_rpc_types::eth::AccountInfo {
1437            balance: account.balance,
1438            nonce: account.nonce,
1439            code: alloy_primitives::Bytes::from(code.0),
1440        })
1441    }
1442
1443    // ----- Filter RPCs
1444
1445    /// Creates a filter to notify about new blocks
1446    async fn new_block_filter(&self) -> Result<String> {
1447        node_info!("eth_newBlockFilter");
1448        let filter = EthFilter::Blocks(BlockFilter::new(BlockNotifications::new(
1449            self.new_block_notifications()?,
1450        )));
1451        Ok(self.filters.add_filter(filter).await)
1452    }
1453
1454    /// Remove filter
1455    async fn uninstall_filter(&self, id: &str) -> Result<bool> {
1456        node_info!("eth_uninstallFilter");
1457        Ok(self.filters.uninstall_filter(id).await.is_some())
1458    }
1459
1460    /// Polls a filter and returns all events that happened since the last poll.
1461    async fn get_filter_changes(&self, id: &str) -> ResponseResult {
1462        node_info!("eth_getFilterChanges");
1463        self.filters.get_filter_changes(id).await
1464    }
1465
1466    async fn new_pending_transactions_filter(&self) -> Result<String> {
1467        node_info!("eth_newPendingTransactionFilter");
1468        let filter = EthFilter::PendingTransactions(PendingTransactionsFilter::new(
1469            BlockNotifications::new(self.new_block_notifications()?),
1470            self.tx_pool.clone(),
1471            self.eth_rpc_client.clone(),
1472        ));
1473        Ok(self.filters.add_filter(filter).await)
1474    }
1475
1476    async fn new_filter(&self, filter: evm::Filter) -> Result<String> {
1477        node_info!("eth_newFilter");
1478        let eth_filter = EthFilter::Logs(
1479            LogsFilter::new(
1480                BlockNotifications::new(self.new_block_notifications()?),
1481                self.eth_rpc_client.clone(),
1482                filter,
1483            )
1484            .await?,
1485        );
1486        Ok(self.filters.add_filter(eth_filter).await)
1487    }
1488
1489    async fn get_filter_logs(&self, id: &str) -> Result<Vec<Log>> {
1490        node_info!("eth_getFilterLogs");
1491        if let Some(filter) = self.filters.get_log_filter(id).await {
1492            Ok(self.eth_rpc_client.logs(Some(filter)).await?)
1493        } else {
1494            Ok(Vec::new())
1495        }
1496    }
1497
1498    // ----- Helpers
1499    async fn update_block_provider_on_revert(&self, info: &Info<OpaqueBlock>) -> Result<()> {
1500        let best_block = self.block_provider.block_by_number(info.best_number).await?.ok_or(
1501            Error::InternalError(format!(
1502                "Could not find best block with number {}",
1503                info.best_number
1504            )),
1505        )?;
1506        self.block_provider.update_latest(best_block, SubscriptionType::BestBlocks).await;
1507
1508        let finalized_block =
1509            self.block_provider.block_by_number(info.finalized_number).await?.ok_or(
1510                Error::InternalError(format!(
1511                    "Could not find finalized block with number {}",
1512                    info.finalized_number
1513                )),
1514            )?;
1515        self.block_provider.update_latest(finalized_block, SubscriptionType::FinalizedBlocks).await;
1516
1517        Ok(())
1518    }
1519
1520    async fn update_time_on_revert(&self, best_hash: Hash) -> Result<()> {
1521        let timestamp = self.backend.read_timestamp(best_hash)?;
1522        self.mining_engine.set_time(Duration::from_millis(timestamp));
1523        Ok(())
1524    }
1525
1526    async fn on_revert_update(&self, revert_info: RevertInfo) -> Result<()> {
1527        if revert_info.reverted > 0 {
1528            self.update_block_provider_on_revert(&revert_info.info).await?;
1529        }
1530
1531        self.update_time_on_revert(revert_info.info.best_hash).await?;
1532
1533        Ok(())
1534    }
1535
1536    // This function translates a block ethereum hash to a substrate hash if needed.
1537    async fn maybe_get_block_hash_for_tag(
1538        &self,
1539        block_id: Option<BlockId>,
1540    ) -> Result<Option<H256>> {
1541        match ReviveBlockId::from(block_id).inner() {
1542            BlockNumberOrTagOrHash::BlockHash(hash) => {
1543                // Translate the ethereum hash to a substrate hash.
1544                Ok(Some(self.eth_rpc_client.resolve_substrate_hash(&hash).await.ok_or(
1545                    Error::ReviveRpc(EthRpcError::ClientError(ClientError::EthereumBlockNotFound)),
1546                )?))
1547            }
1548            BlockNumberOrTagOrHash::BlockNumber(block_number) => {
1549                let n = block_number.try_into().map_err(|_| {
1550                    Error::InvalidParams("Block number conversion failed".to_string())
1551                })?;
1552                Ok(self.eth_rpc_client.get_block_hash(n).await?)
1553            }
1554            BlockNumberOrTagOrHash::BlockTag(BlockTag::Finalized | BlockTag::Safe) => {
1555                let block = self.eth_rpc_client.latest_finalized_block().await;
1556                Ok(Some(block.hash()))
1557            }
1558            BlockNumberOrTagOrHash::BlockTag(_) => {
1559                let block = self.eth_rpc_client.latest_block().await;
1560                Ok(Some(block.hash()))
1561            }
1562        }
1563    }
1564
1565    /// Returns the substrate block hash for a given block id.
1566    async fn get_block_hash_for_tag(&self, block_id: Option<BlockId>) -> Result<H256> {
1567        self.maybe_get_block_hash_for_tag(block_id)
1568            .await?
1569            .ok_or(Error::InvalidParams("Block number not found".to_string()))
1570    }
1571
1572    fn get_account_id(&self, block: Hash, address: Address) -> Result<AccountId> {
1573        Ok(self.client.runtime_api().account_id(block, ReviveAddress::from(address).inner())?)
1574    }
1575
1576    fn construct_balance_with_dust(&self, block: Hash, value: U256) -> Result<(Balance, u32)> {
1577        self.client
1578            .runtime_api()
1579            .new_balance_with_dust(block, SubstrateU256::from(value).inner())?
1580            .map_err(|_| Error::BalanceConversion)
1581    }
1582
1583    fn latest_block(&self) -> H256 {
1584        self.backend.blockchain().info().best_hash
1585    }
1586
1587    /// Returns the EVM block for a given substrate block hash.
1588    async fn get_block_by_substrate_hash(&self, block_hash: H256) -> Result<Option<Block>> {
1589        let Some(substrate_block) = self.eth_rpc_client.block_by_hash(&block_hash).await? else {
1590            return Ok(None);
1591        };
1592        let Some(evm_block) = self.eth_rpc_client.evm_block(substrate_block, false).await else {
1593            return Err(Error::InternalError(
1594                "EVM block not found for substrate block".to_string(),
1595            ));
1596        };
1597        Ok(Some(evm_block))
1598    }
1599
1600    fn set_frame_system_balance(
1601        &self,
1602        latest_block: H256,
1603        account_id: AccountId,
1604        balance: Balance,
1605    ) -> Result<()> {
1606        let mut total_issuance = self.backend.read_total_issuance(latest_block)?;
1607
1608        let mut system_account_info = self
1609            .backend
1610            .read_system_account_info(latest_block, account_id.clone())?
1611            .unwrap_or_else(|| SystemAccountInfo { providers: 1, ..Default::default() });
1612
1613        if let Some(diff) = balance.checked_sub(system_account_info.data.free) {
1614            total_issuance = total_issuance.saturating_add(diff);
1615        } else {
1616            total_issuance = total_issuance.saturating_sub(system_account_info.data.free - balance);
1617        }
1618
1619        system_account_info.data.free = balance;
1620
1621        self.backend.inject_system_account_info(latest_block, account_id, system_account_info);
1622        self.backend.inject_total_issuance(latest_block, total_issuance);
1623
1624        Ok(())
1625    }
1626
1627    /// Returns transaction pool status
1628    async fn txpool_status(&self) -> Result<TxpoolStatus> {
1629        node_info!("txpool_status");
1630        let pool_status = self.tx_pool.status();
1631        Ok(TxpoolStatus { pending: pool_status.ready as u64, queued: pool_status.future as u64 })
1632    }
1633
1634    /// Returns a summary of all transactions in the pool
1635    async fn txpool_inspect(&self) -> Result<TxpoolInspect> {
1636        node_info!("txpool_inspect");
1637        let mut inspect = TxpoolInspect::default();
1638
1639        for tx in self.tx_pool.ready() {
1640            if let Some((sender, nonce, summary)) = extract_tx_summary(tx.data()) {
1641                let entry = inspect.pending.entry(sender).or_default();
1642                entry.insert(nonce.to_string(), summary);
1643            }
1644        }
1645
1646        for tx in self.tx_pool.futures() {
1647            if let Some((sender, nonce, summary)) = extract_tx_summary(tx.data()) {
1648                let entry = inspect.queued.entry(sender).or_default();
1649                entry.insert(nonce.to_string(), summary);
1650            }
1651        }
1652
1653        Ok(inspect)
1654    }
1655
1656    /// Returns full transaction details for all transactions in the pool
1657    async fn txpool_content(&self) -> Result<TxpoolContent<TxpoolTransactionInfo>> {
1658        node_info!("txpool_content");
1659        let mut content = TxpoolContent::default();
1660
1661        for tx in self.tx_pool.ready() {
1662            if let Some((sender, nonce, tx_info)) = extract_tx_info(tx.data()) {
1663                let entry = content.pending.entry(sender).or_default();
1664                entry.insert(nonce.to_string(), tx_info);
1665            }
1666        }
1667
1668        for tx in self.tx_pool.futures() {
1669            if let Some((sender, nonce, tx_info)) = extract_tx_info(tx.data()) {
1670                let entry = content.queued.entry(sender).or_default();
1671                entry.insert(nonce.to_string(), tx_info);
1672            }
1673        }
1674
1675        Ok(content)
1676    }
1677
1678    /// Drop all transactions from pool
1679    async fn anvil_drop_all_transactions(&self) -> Result<()> {
1680        node_info!("anvil_dropAllTransactions");
1681        let ready_txs = self.tx_pool.ready();
1682        let future_txs = self.tx_pool.futures();
1683
1684        let mut invalid_txs = IndexMap::new();
1685
1686        for tx in ready_txs {
1687            invalid_txs.insert(*tx.hash(), None);
1688        }
1689
1690        for tx in future_txs {
1691            invalid_txs.insert(*tx.hash(), None);
1692        }
1693
1694        self.tx_pool.report_invalid(None, invalid_txs).await;
1695
1696        Ok(())
1697    }
1698
1699    /// Drop a specific transaction from the pool by its ETH hash
1700    async fn anvil_drop_transaction(&self, eth_hash: B256) -> Result<Option<B256>> {
1701        node_info!("anvil_dropTransaction");
1702        for tx in self.tx_pool.ready() {
1703            if transaction_matches_eth_hash(tx.data(), eth_hash) {
1704                let mut invalid_txs = IndexMap::new();
1705                invalid_txs.insert(*tx.hash(), None);
1706                self.tx_pool.report_invalid(None, invalid_txs).await;
1707                return Ok(Some(eth_hash));
1708            }
1709        }
1710
1711        for tx in self.tx_pool.futures() {
1712            if transaction_matches_eth_hash(tx.data(), eth_hash) {
1713                let mut invalid_txs = IndexMap::new();
1714                invalid_txs.insert(*tx.hash(), None);
1715                self.tx_pool.report_invalid(None, invalid_txs).await;
1716                return Ok(Some(eth_hash));
1717            }
1718        }
1719
1720        // Transaction not found
1721        Ok(None)
1722    }
1723
1724    /// Remove all transactions from a specific sender address
1725    async fn anvil_remove_pool_transactions(&self, address: Address) -> Result<()> {
1726        node_info!("anvil_removePoolTransactions");
1727        let mut invalid_txs = IndexMap::new();
1728
1729        for tx in self.tx_pool.ready() {
1730            if let Some(sender) = extract_sender(tx.data())
1731                && sender == address
1732            {
1733                invalid_txs.insert(*tx.hash(), None);
1734            }
1735        }
1736
1737        for tx in self.tx_pool.futures() {
1738            if let Some(sender) = extract_sender(tx.data())
1739                && sender == address
1740            {
1741                invalid_txs.insert(*tx.hash(), None);
1742            }
1743        }
1744
1745        if !invalid_txs.is_empty() {
1746            self.tx_pool.report_invalid(None, invalid_txs).await;
1747        }
1748
1749        Ok(())
1750    }
1751
1752    async fn debug_trace_transaction(
1753        &self,
1754        tx_hash: B256,
1755        geth_tracer_options: GethDebugTracingOptions,
1756    ) -> Result<GethTrace> {
1757        node_info!("debug_traceTransaction");
1758        let trace = self
1759            .eth_rpc_client
1760            .trace_transaction(
1761                H256::from_slice(tx_hash.as_ref()),
1762                ReviveTracerType::from(geth_tracer_options).inner(),
1763            )
1764            .await?;
1765        Ok(ReviveTrace::new(trace).into())
1766    }
1767
1768    async fn debug_trace_call(
1769        &self,
1770        request: WithOtherFields<TransactionRequest>,
1771        block_number: Option<BlockId>,
1772        geth_tracer_options: GethDebugTracingCallOptions,
1773    ) -> Result<GethTrace> {
1774        node_info!("debug_traceCall");
1775        let hash = self.get_block_hash_for_tag(block_number).await?;
1776        let runtime_api = self.eth_rpc_client.runtime_api(hash);
1777        let transaction = convert_to_generic_transaction(request.into_inner());
1778        let trace = runtime_api
1779            .trace_call(transaction, ReviveTracerType::from(geth_tracer_options).inner())
1780            .await?;
1781        Ok(ReviveTrace::new(trace).into())
1782    }
1783
1784    async fn debug_trace_block_by_number(
1785        &self,
1786        block_number: BlockNumberOrTag,
1787        geth_tracer_options: GethDebugTracingOptions,
1788    ) -> Result<Vec<TraceResult>> {
1789        node_info!("debug_traceBlockByNumber");
1790
1791        Ok(self
1792            .eth_rpc_client
1793            .trace_block_by_number(
1794                ReviveBlockNumberOrTag::from(block_number).inner(),
1795                ReviveTracerType::from(geth_tracer_options).inner(),
1796            )
1797            .await?
1798            .into_iter()
1799            .map(|tx_trace| TraceResult::Success {
1800                result: ReviveTrace::new(tx_trace.trace).into(),
1801                tx_hash: Some(B256::from_slice(tx_trace.tx_hash.as_ref())),
1802            })
1803            .collect::<Vec<_>>())
1804    }
1805
1806    async fn trace_transaction(&self, tx_hash: B256) -> Result<Vec<LocalizedTransactionTrace>> {
1807        node_info!("trace_transaction");
1808        let trace = self
1809            .eth_rpc_client
1810            .trace_transaction(
1811                H256::from_slice(tx_hash.as_ref()),
1812                TracerType::CallTracer(Some(CallTracerConfig::default())),
1813            )
1814            .await?;
1815        let tx_info = self.get_transaction_by_hash(tx_hash).await?;
1816        parity_transaction_trace_builder(trace, tx_info)
1817    }
1818
1819    async fn trace_block(
1820        &self,
1821        block_number: BlockNumberOrTag,
1822    ) -> Result<Vec<LocalizedTransactionTrace>> {
1823        node_info!("trace_block");
1824        // hydrated_transactions is true because we need tx info to build the trace
1825        let Some(block) = self.get_block_by_number(block_number, true).await? else {
1826            return Ok(vec![]);
1827        };
1828        let traces = self
1829            .eth_rpc_client
1830            .trace_block_by_number(
1831                ReviveBlockNumberOrTag::from(block_number).inner(),
1832                TracerType::CallTracer(Some(CallTracerConfig::default())),
1833            )
1834            .await?;
1835
1836        parity_block_trace_builder(traces, block)
1837    }
1838
1839    // ----- Helpers -----
1840
1841    async fn wait_for_receipt(
1842        &self,
1843        hash: B256,
1844        mut receiver: tokio::sync::broadcast::Receiver<H256>,
1845    ) -> Result<ReceiptInfo> {
1846        tokio::time::timeout(TIMEOUT_DURATION, async {
1847            while let Ok(_block_hash) = receiver.recv().await {
1848                if let Some(receipt) = self.transaction_receipt(hash).await? {
1849                    return Ok(receipt);
1850                }
1851            }
1852            Err(Error::TransactionConfirmationTimeout { hash, duration: TIMEOUT_DURATION })
1853        })
1854        .await
1855        .unwrap_or_else(|_| {
1856            Err(Error::TransactionConfirmationTimeout { hash, duration: TIMEOUT_DURATION })
1857        })
1858    }
1859
1860    async fn wait_for_hash(
1861        &self,
1862        receiver: Option<tokio::sync::broadcast::Receiver<H256>>,
1863        awaited_hash: H256,
1864    ) -> Result<()> {
1865        if let Some(mut receiver) = receiver {
1866            tokio::time::timeout(Duration::from_secs(3), async {
1867                loop {
1868                    if let Ok(block_hash) = receiver.recv().await {
1869                        if let Err(e) = self.log_mined_block(block_hash).await {
1870                            node_info!("Failed to log mined block {block_hash:?}: {e:?}");
1871                        }
1872                        if block_hash == awaited_hash {
1873                            break;
1874                        }
1875                    }
1876                }
1877            })
1878            .await
1879            .map_err(|e| {
1880                Error::InternalError(format!(
1881                    "Was not notified about the new best block in time {e:?}."
1882                ))
1883            })?;
1884        }
1885        Ok(())
1886    }
1887
1888    fn new_block_notifications(&self) -> Result<tokio::sync::broadcast::Receiver<H256>> {
1889        self.eth_rpc_client
1890            .block_notifier()
1891            .map(|sender| sender.subscribe())
1892            .ok_or(Error::InternalError("Could not subscribe to new blocks. 😢".to_string()))
1893    }
1894
1895    async fn log_mined_block(&self, block_hash: H256) -> Result<()> {
1896        let block_timestamp = self.backend.read_timestamp(block_hash)?;
1897        let block_number = self.backend.read_block_number(block_hash)?;
1898        let timestamp = utc_from_millis(block_timestamp)?;
1899        node_info!("    Block Number: {}", block_number);
1900        node_info!("    Block Hash: {:?}", block_hash);
1901        if timestamp.year() > 9999 {
1902            // rf2822 panics with more than 4 digits
1903            node_info!("    Block Time: {:?}\n", timestamp.to_rfc3339());
1904        } else {
1905            node_info!("    Block Time: {:?}\n", timestamp.to_rfc2822());
1906        }
1907        Ok(())
1908    }
1909}
1910
1911/// Returns the `Utc` datetime for the given seconds since unix epoch
1912fn utc_from_millis(millis: u64) -> Result<DateTime<Utc>> {
1913    DateTime::from_timestamp_millis(
1914        millis.try_into().map_err(|err| {
1915            Error::InvalidParams(format!("Could not convert the timestamp: {err:?}"))
1916        })?,
1917    )
1918    .ok_or(Error::InvalidParams("Could not get the utc datetime 😭".to_string()))
1919}
1920
1921fn new_contract_info(address: &Address, code_hash: H256, nonce: Nonce) -> ContractInfo {
1922    let address = H160::from_slice(address.as_slice());
1923
1924    let trie_id =
1925        ("bcontract_trie_v1", address, nonce).using_encoded(BlakeTwo256::hash).as_ref().to_vec();
1926
1927    ContractInfo {
1928        trie_id: BoundedVec(trie_id),
1929        code_hash,
1930        storage_bytes: 0,
1931        storage_items: 0,
1932        storage_byte_deposit: 0,
1933        storage_item_deposit: 0,
1934        storage_base_deposit: 0,
1935        immutable_data_len: 0,
1936    }
1937}
1938
1939async fn create_online_client(
1940    substrate_service: &Service,
1941    rpc_client: RpcClient,
1942) -> Result<OnlineClient<SrcChainConfig>> {
1943    let genesis_block_number = substrate_service.genesis_block_number.try_into().map_err(|_| {
1944        Error::InternalError(format!(
1945            "Genesis block number {} is too large for u32 (max: {})",
1946            substrate_service.genesis_block_number,
1947            u32::MAX
1948        ))
1949    })?;
1950
1951    let Some(genesis_hash) = substrate_service.client.hash(genesis_block_number).ok().flatten()
1952    else {
1953        return Err(Error::InternalError(format!(
1954            "Genesis hash not found for genesis block number {}",
1955            substrate_service.genesis_block_number
1956        )));
1957    };
1958
1959    let Ok(runtime_version) = substrate_service.client.runtime_version_at(genesis_hash) else {
1960        return Err(Error::InternalError(
1961            "Runtime version not found for given genesis hash".to_string(),
1962        ));
1963    };
1964
1965    let subxt_runtime_version = SubxtRuntimeVersion {
1966        spec_version: runtime_version.spec_version,
1967        transaction_version: runtime_version.transaction_version,
1968    };
1969
1970    let Ok(supported_metadata_versions) =
1971        substrate_service.client.runtime_api().metadata_versions(genesis_hash)
1972    else {
1973        return Err(Error::InternalError("Unable to fetch metadata versions".to_string()));
1974    };
1975
1976    let Some(latest_metadata_version) = supported_metadata_versions.into_iter().max() else {
1977        return Err(Error::InternalError("No stable metadata versions supported".to_string()));
1978    };
1979
1980    let opaque_metadata = substrate_service
1981        .client
1982        .runtime_api()
1983        .metadata_at_version(genesis_hash, latest_metadata_version)
1984        .map_err(|_| {
1985            Error::InternalError("Failed to get runtime API for genesis hash".to_string())
1986        })?
1987        .ok_or_else(|| {
1988            Error::InternalError(format!(
1989                "Metadata not found for version {latest_metadata_version} at genesis hash"
1990            ))
1991        })?;
1992    let subxt_metadata = SubxtMetadata::decode(&mut (*opaque_metadata).as_slice())
1993        .map_err(|_| Error::InternalError("Unable to decode metadata".to_string()))?;
1994
1995    OnlineClient::<SrcChainConfig>::from_rpc_client_with(
1996        genesis_hash,
1997        subxt_runtime_version,
1998        subxt_metadata,
1999        rpc_client,
2000    )
2001    .map_err(|err| {
2002        Error::InternalError(format!("Failed to initialize the subxt online client: {err}"))
2003    })
2004}
2005
2006async fn create_revive_rpc_client(
2007    api: OnlineClient<SrcChainConfig>,
2008    rpc_client: RpcClient,
2009    rpc: LegacyRpcMethods<SrcChainConfig>,
2010    block_provider: SubxtBlockInfoProvider,
2011    task_spawn_handle: SpawnTaskHandle,
2012    keep_latest_n_blocks: Option<usize>,
2013) -> Result<EthRpcClient> {
2014    let pool = SqlitePoolOptions::new()
2015        .max_connections(1)
2016        // see sqlite in-memory issue: https://github.com/launchbadge/sqlx/issues/2510
2017        .idle_timeout(None)
2018        .max_lifetime(None)
2019        .connect("sqlite::memory:")
2020        .await
2021        .map_err(|err| Error::ReviveRpc(EthRpcError::ClientError(ClientError::SqlxError(err))))?;
2022
2023    let receipt_extractor = ReceiptExtractor::new_with_custom_address_recovery(
2024        api.clone(),
2025        None,
2026        Arc::new(recover_maybe_impersonated_address),
2027    )
2028    .await
2029    .map_err(|err| Error::ReviveRpc(EthRpcError::ClientError(err)))?;
2030
2031    let receipt_provider =
2032        ReceiptProvider::new(pool, block_provider.clone(), receipt_extractor, keep_latest_n_blocks)
2033            .await
2034            .map_err(|err| {
2035                Error::ReviveRpc(EthRpcError::ClientError(ClientError::SqlxError(err)))
2036            })?;
2037
2038    let mut eth_rpc_client =
2039        EthRpcClient::new(api, rpc_client, rpc, block_provider, receipt_provider)
2040            .await
2041            .map_err(Error::from)?;
2042    // Genesis block is not imported via block import notifications, so we need to subscribe and
2043    // cache it manually.
2044    let _ = eth_rpc_client.subscribe_and_cache_blocks(1).await;
2045
2046    // Capacity is chosen using random.org
2047    eth_rpc_client.set_block_notifier(Some(tokio::sync::broadcast::channel::<H256>(50).0));
2048    let eth_rpc_client_clone = eth_rpc_client.clone();
2049    task_spawn_handle.spawn("block-subscription", "None", async move {
2050        let eth_rpc_client = eth_rpc_client_clone;
2051        let best_future =
2052            eth_rpc_client.subscribe_and_cache_new_blocks(SubscriptionType::BestBlocks);
2053        let finalized_future =
2054            eth_rpc_client.subscribe_and_cache_new_blocks(SubscriptionType::FinalizedBlocks);
2055        let res = tokio::try_join!(best_future, finalized_future).map(|_| ());
2056        if let Err(err) = res {
2057            panic!("Block subscription task failed: {err:?}")
2058        }
2059    });
2060
2061    Ok(eth_rpc_client)
2062}