zksync_web3_rs/zks_provider/
mod.rs

1use async_trait::async_trait;
2use ethers::{
3    abi::{HumanReadableParser, Token, Tokenize},
4    prelude::{
5        k256::{
6            ecdsa::{RecoveryId, Signature as RecoverableSignature},
7            schnorr::signature::hazmat::PrehashSigner,
8        },
9        SignerMiddleware,
10    },
11    providers::{JsonRpcClient, Middleware, Provider, ProviderError},
12    signers::{Signer, Wallet},
13    types::{
14        transaction::{eip2718::TypedTransaction, eip712::Eip712Error},
15        Address, BlockNumber, Eip1559TransactionRequest, Signature, TransactionReceipt, TxHash,
16        H256, U256, U64,
17    },
18};
19use ethers_contract::providers::PendingTransaction;
20use serde::Serialize;
21use serde_json::json;
22use std::{collections::HashMap, fmt::Debug, time::Duration};
23use tokio::time::Instant;
24
25pub mod types;
26use types::Fee;
27
28use crate::{
29    eip712::{Eip712Meta, Eip712Transaction, Eip712TransactionRequest},
30    zks_utils::{self, DEFAULT_GAS, EIP712_TX_TYPE, MAX_FEE_PER_GAS, MAX_PRIORITY_FEE_PER_GAS},
31    zks_wallet::{CallRequest, Overrides},
32};
33
34use self::types::{
35    BlockDetails, BlockRange, BridgeContracts, DebugTrace, L1BatchDetails, Proof, TokenInfo,
36    TracerConfig, Transaction, TransactionDetails,
37};
38
39/// This trait wraps every JSON-RPC call specified in zkSync Era's documentation
40/// https://era.zksync.io/docs/api/api.html#zksync-era-json-rpc-methods
41#[async_trait]
42pub trait ZKSProvider {
43    type Provider: JsonRpcClient;
44    type ZKProvider: JsonRpcClient;
45
46    async fn zk_estimate_gas<T>(&self, transaction: T) -> Result<U256, ProviderError>
47    where
48        T: Debug + Serialize + Send + Sync;
49
50    /// Returns the fee for the transaction.
51    async fn estimate_fee<T>(&self, transaction: T) -> Result<Fee, ProviderError>
52    where
53        T: Debug + Serialize + Send + Sync;
54
55    /// Returns an estimate of the gas required for a L1 to L2 transaction.
56    async fn estimate_gas_l1_to_l2<T>(&self, transaction: T) -> Result<U256, ProviderError>
57    where
58        T: Debug + Serialize + Send + Sync;
59
60    /// Returns all balances for confirmed tokens given by an account address.
61    async fn get_all_account_balances(
62        &self,
63        address: Address,
64    ) -> Result<HashMap<Address, U256>, ProviderError>;
65
66    /// Returns additional zkSync-specific information about the L2 block.
67    /// * `committed`: The batch is closed and the state transition it creates exists on layer 1.
68    /// * `proven`: The batch proof has been created, submitted, and accepted on layer 1.
69    /// * `executed`: The batch state transition has been executed on L1; meaning the root state has been updated.
70    async fn get_block_details<T>(&self, block: T) -> Result<Option<BlockDetails>, ProviderError>
71    where
72        T: Into<U64> + Send + Sync + Serialize + Debug;
73
74    /// Returns L1/L2 addresses of default bridges.
75    async fn get_bridge_contracts(&self) -> Result<BridgeContracts, ProviderError>;
76
77    /// Returns bytecode of a transaction given by its hash.
78    async fn get_bytecode_by_hash(&self, hash: H256) -> Result<Option<Vec<u8>>, ProviderError>;
79
80    /// Returns [address, symbol, name, and decimal] information of all tokens within a range of ids given by parameters `from` and `limit`.
81    ///
82    /// **Confirmed** in the method name means the method returns any token bridged to zkSync via the official bridge.
83    ///
84    /// > This method is mainly used by the zkSync team as it relates to a database query where the primary keys relate to the given ids.
85    async fn get_confirmed_tokens(
86        &self,
87        from: u32,
88        limit: u8,
89    ) -> Result<Vec<TokenInfo>, ProviderError>;
90
91    /// Returns the range of blocks contained within a batch given by batch number.
92    ///
93    /// The range is given by beginning/end block numbers in hexadecimal.
94    async fn get_l1_batch_block_range<T>(&self, batch: T) -> Result<BlockRange, ProviderError>
95    where
96        T: Into<U64> + Send + Sync + Serialize + Debug;
97
98    /// Returns data pertaining to a given batch.
99    async fn get_l1_batch_details<T>(&self, batch: T) -> Result<L1BatchDetails, ProviderError>
100    where
101        T: Into<U64> + Send + Sync + Serialize + Debug;
102
103    /// Given a transaction hash, and an index of the L2 to L1 log produced within the
104    /// transaction, it returns the proof for the corresponding L2 to L1 log.
105    ///
106    /// The index of the log that can be obtained from the transaction receipt (it
107    /// includes a list of every log produced by the transaction).
108    async fn get_l2_to_l1_log_proof(
109        &self,
110        tx_hash: H256,
111        l2_to_l1_log_index: Option<u64>,
112    ) -> Result<Option<Proof>, ProviderError>;
113
114    /// Given a block, a sender, a message, and an optional message log index in the
115    /// block containing the L1->L2 message, it returns the proof for the message sent
116    /// via the L1Messenger system contract.
117    async fn get_l2_to_l1_msg_proof<T>(
118        &self,
119        block: T,
120        sender: Address,
121        msg: H256,
122        l2_log_position: Option<u64>,
123    ) -> Result<Option<Proof>, ProviderError>
124    where
125        T: Into<U64> + Send + Sync + Serialize + Debug;
126
127    /// Returns the address of the zkSync Era contract.
128    async fn get_main_contract(&self) -> Result<Address, ProviderError>;
129
130    /// Returns data of transactions in a block.
131    async fn get_raw_block_transactions<T>(
132        &self,
133        block: T,
134    ) -> Result<Vec<Transaction>, ProviderError>
135    where
136        T: Into<U64> + Send + Sync + Serialize + Debug;
137
138    /// Returns the address of the [testnet paymaster](https://era.zksync.io/docs/dev/developer-guides/aa.html#testnet-paymaster): the paymaster that is available
139    /// on testnets and enables paying fees in ERC-20 compatible tokens.
140    async fn get_testnet_paymaster(&self) -> Result<Address, ProviderError>;
141
142    /// Returns the price of a given token in USD.
143    async fn get_token_price(&self, address: Address) -> Result<String, ProviderError>;
144
145    /// Returns data from a specific transaction given by the transaction hash.
146    async fn get_transaction_details(
147        &self,
148        hash: H256,
149    ) -> Result<Option<TransactionDetails>, ProviderError>;
150
151    /// Returns the latest L1 batch number.
152    async fn get_l1_batch_number(&self) -> Result<U256, ProviderError>;
153
154    /// Returns the chain id of the underlying L1.
155    async fn get_l1_chain_id(&self) -> Result<U256, ProviderError>;
156
157    /// Returns debug trace of all executed calls contained in a block given by its L2 hash.
158    async fn debug_trace_block_by_hash(
159        &self,
160        hash: H256,
161        options: Option<TracerConfig>,
162    ) -> Result<DebugTrace, ProviderError>;
163
164    /// Returns debug trace of all executed calls contained in a block given by its L2 block number.
165    async fn debug_trace_block_by_number<T>(
166        &self,
167        block: T,
168        options: Option<TracerConfig>,
169    ) -> Result<DebugTrace, ProviderError>
170    where
171        T: Into<U64> + Send + Sync + Serialize + Debug;
172
173    /// Returns debug trace containing information on a specific calls given by the call request.
174    async fn debug_trace_call<R, T>(
175        &self,
176        request: R,
177        block: Option<T>,
178        options: Option<TracerConfig>,
179    ) -> Result<DebugTrace, ProviderError>
180    where
181        R: Debug + Serialize + Send + Sync,
182        T: Into<U64> + Send + Sync + Serialize + Debug;
183
184    /// Uses the EVM's callTracer to return a debug trace of a specific transaction given by its transaction hash.
185    async fn debug_trace_transaction(
186        &self,
187        hash: H256,
188        options: Option<TracerConfig>,
189    ) -> Result<DebugTrace, ProviderError>;
190
191    async fn send_eip712<D>(
192        &self,
193        wallet: &Wallet<D>,
194        contract_address: Address,
195        function_signature: &str,
196        function_parameters: Option<Vec<String>>,
197        overrides: Option<Overrides>,
198    ) -> Result<PendingTransaction<Self::ZKProvider>, ProviderError>
199    where
200        D: PrehashSigner<(RecoverableSignature, RecoveryId)> + Send + Sync;
201
202    async fn send<D>(
203        &self,
204        wallet: &Wallet<D>,
205        contract_address: Address,
206        function_signature: &str,
207        function_parameters: Option<Vec<String>>,
208        overrides: Option<Overrides>,
209    ) -> Result<PendingTransaction<Self::Provider>, ProviderError>
210    where
211        D: PrehashSigner<(RecoverableSignature, RecoveryId)> + Send + Sync;
212
213    async fn wait_for_finalize(
214        &self,
215        transaction_receipt: TxHash,
216        polling_time_in_seconds: Option<Duration>,
217        timeout_in_seconds: Option<Duration>,
218    ) -> Result<TransactionReceipt, ProviderError>;
219
220    async fn call(&self, request: &CallRequest) -> Result<Vec<Token>, ProviderError>;
221
222    async fn send_transaction_eip712<T, D>(
223        &self,
224        wallet: &Wallet<D>,
225        transaction: T,
226    ) -> Result<PendingTransaction<Self::ZKProvider>, ProviderError>
227    where
228        T: TryInto<Eip712TransactionRequest> + Send + Sync + Debug,
229        D: PrehashSigner<(RecoverableSignature, RecoveryId)> + Send + Sync;
230}
231
232#[async_trait]
233impl<M: Middleware + ZKSProvider, S: Signer> ZKSProvider for SignerMiddleware<M, S> {
234    type Provider = <M as Middleware>::Provider;
235    type ZKProvider = <M as ZKSProvider>::ZKProvider;
236
237    async fn zk_estimate_gas<T>(&self, transaction: T) -> Result<U256, ProviderError>
238    where
239        T: Debug + Serialize + Send + Sync,
240    {
241        <M as ZKSProvider>::zk_estimate_gas(self.inner(), transaction).await
242    }
243
244    async fn estimate_fee<T>(&self, transaction: T) -> Result<Fee, ProviderError>
245    where
246        T: Debug + Serialize + Send + Sync,
247    {
248        self.inner().estimate_fee(transaction).await
249    }
250
251    async fn estimate_gas_l1_to_l2<T>(&self, transaction: T) -> Result<U256, ProviderError>
252    where
253        T: Debug + Serialize + Send + Sync,
254    {
255        self.inner().estimate_gas_l1_to_l2(transaction).await
256    }
257
258    async fn get_all_account_balances(
259        &self,
260        address: Address,
261    ) -> Result<HashMap<Address, U256>, ProviderError> {
262        self.inner().get_all_account_balances(address).await
263    }
264
265    async fn get_block_details<T>(&self, block: T) -> Result<Option<BlockDetails>, ProviderError>
266    where
267        T: Into<U64> + Send + Sync + Serialize + Debug,
268    {
269        self.inner().get_block_details(block).await
270    }
271
272    async fn get_bridge_contracts(&self) -> Result<BridgeContracts, ProviderError> {
273        self.inner().get_bridge_contracts().await
274    }
275
276    async fn get_bytecode_by_hash(&self, hash: H256) -> Result<Option<Vec<u8>>, ProviderError> {
277        self.inner().get_bytecode_by_hash(hash).await
278    }
279
280    async fn get_confirmed_tokens(
281        &self,
282        from: u32,
283        limit: u8,
284    ) -> Result<Vec<TokenInfo>, ProviderError> {
285        self.inner().get_confirmed_tokens(from, limit).await
286    }
287
288    async fn get_l1_batch_block_range<T>(&self, batch_id: T) -> Result<BlockRange, ProviderError>
289    where
290        T: Into<U64> + Send + Sync + Serialize + Debug,
291    {
292        self.inner().get_l1_batch_block_range(batch_id).await
293    }
294
295    async fn get_l1_batch_details<T>(&self, batch_id: T) -> Result<L1BatchDetails, ProviderError>
296    where
297        T: Into<U64> + Send + Sync + Serialize + Debug,
298    {
299        self.inner().get_l1_batch_details(batch_id).await
300    }
301
302    async fn get_l2_to_l1_log_proof(
303        &self,
304        tx_hash: H256,
305        l2_to_l1_log_index: Option<u64>,
306    ) -> Result<Option<Proof>, ProviderError> {
307        self.inner()
308            .get_l2_to_l1_log_proof(tx_hash, l2_to_l1_log_index)
309            .await
310    }
311
312    async fn get_l2_to_l1_msg_proof<T>(
313        &self,
314        block: T,
315        sender: Address,
316        msg: H256,
317        l2_log_position: Option<u64>,
318    ) -> Result<Option<Proof>, ProviderError>
319    where
320        T: Into<U64> + Send + Sync + Serialize + Debug,
321    {
322        self.inner()
323            .get_l2_to_l1_msg_proof(block, sender, msg, l2_log_position)
324            .await
325    }
326
327    async fn get_main_contract(&self) -> Result<Address, ProviderError> {
328        self.inner().get_main_contract().await
329    }
330
331    async fn get_raw_block_transactions<T>(
332        &self,
333        block: T,
334    ) -> Result<Vec<Transaction>, ProviderError>
335    where
336        T: Into<U64> + Send + Sync + Serialize + Debug,
337    {
338        self.inner().get_raw_block_transactions(block).await
339    }
340
341    async fn get_testnet_paymaster(&self) -> Result<Address, ProviderError> {
342        self.inner().get_testnet_paymaster().await
343    }
344
345    async fn get_token_price(&self, address: Address) -> Result<String, ProviderError> {
346        self.inner().get_token_price(address).await
347    }
348
349    async fn get_transaction_details(
350        &self,
351        hash: H256,
352    ) -> Result<Option<TransactionDetails>, ProviderError> {
353        self.inner().get_transaction_details(hash).await
354    }
355
356    async fn get_l1_batch_number(&self) -> Result<U256, ProviderError> {
357        self.inner().get_l1_batch_number().await
358    }
359
360    async fn get_l1_chain_id(&self) -> Result<U256, ProviderError> {
361        self.inner().get_l1_chain_id().await
362    }
363
364    async fn debug_trace_block_by_hash(
365        &self,
366        hash: H256,
367        options: Option<TracerConfig>,
368    ) -> Result<DebugTrace, ProviderError> {
369        ZKSProvider::debug_trace_block_by_hash(self.inner(), hash, options).await
370    }
371
372    async fn debug_trace_block_by_number<T>(
373        &self,
374        block: T,
375        options: Option<TracerConfig>,
376    ) -> Result<DebugTrace, ProviderError>
377    where
378        T: Into<U64> + Send + Sync + Serialize + Debug,
379    {
380        ZKSProvider::debug_trace_block_by_number(self.inner(), block, options).await
381    }
382
383    async fn debug_trace_call<R, T>(
384        &self,
385        request: R,
386        block: Option<T>,
387        options: Option<TracerConfig>,
388    ) -> Result<DebugTrace, ProviderError>
389    where
390        R: Debug + Serialize + Send + Sync,
391        T: Into<U64> + Send + Sync + Serialize + Debug,
392    {
393        ZKSProvider::debug_trace_call(self.inner(), request, block, options).await
394    }
395
396    async fn debug_trace_transaction(
397        &self,
398        hash: H256,
399        options: Option<TracerConfig>,
400    ) -> Result<DebugTrace, ProviderError> {
401        ZKSProvider::debug_trace_transaction(self.inner(), hash, options).await
402    }
403
404    async fn send_eip712<D>(
405        &self,
406        wallet: &Wallet<D>,
407        contract_address: Address,
408        function_signature: &str,
409        function_parameters: Option<Vec<String>>,
410        overrides: Option<Overrides>,
411    ) -> Result<PendingTransaction<Self::ZKProvider>, ProviderError>
412    where
413        D: PrehashSigner<(RecoverableSignature, RecoveryId)> + Send + Sync,
414    {
415        self.inner()
416            .send_eip712(
417                wallet,
418                contract_address,
419                function_signature,
420                function_parameters,
421                overrides,
422            )
423            .await
424    }
425
426    async fn send<D>(
427        &self,
428        wallet: &Wallet<D>,
429        contract_address: Address,
430        function_signature: &str,
431        function_parameters: Option<Vec<String>>,
432        _overrides: Option<Overrides>,
433    ) -> Result<PendingTransaction<Self::Provider>, ProviderError>
434    where
435        D: PrehashSigner<(RecoverableSignature, RecoveryId)> + Send + Sync,
436    {
437        let tx = build_send_tx(
438            self,
439            wallet,
440            contract_address,
441            function_signature,
442            function_parameters,
443            _overrides,
444        )
445        .await?;
446        self.send_transaction(tx, None)
447            .await
448            .map_err(|e| ProviderError::CustomError(format!("Error sending transaction: {e:?}")))
449    }
450
451    async fn send_transaction_eip712<T, D>(
452        &self,
453        wallet: &Wallet<D>,
454        transaction: T,
455    ) -> Result<PendingTransaction<Self::ZKProvider>, ProviderError>
456    where
457        T: TryInto<Eip712TransactionRequest> + Sync + Send + Debug,
458        D: PrehashSigner<(RecoverableSignature, RecoveryId)> + Send + Sync,
459    {
460        self.inner()
461            .send_transaction_eip712(wallet, transaction)
462            .await
463    }
464
465    async fn wait_for_finalize(
466        &self,
467        transaction_receipt: TxHash,
468        polling_time_in_seconds: Option<Duration>,
469        timeout_in_seconds: Option<Duration>,
470    ) -> Result<TransactionReceipt, ProviderError> {
471        self.inner()
472            .wait_for_finalize(
473                transaction_receipt,
474                polling_time_in_seconds,
475                timeout_in_seconds,
476            )
477            .await
478    }
479
480    async fn call(&self, request: &CallRequest) -> Result<Vec<Token>, ProviderError> {
481        ZKSProvider::call(self.inner(), request).await
482    }
483}
484
485#[async_trait]
486impl<P: JsonRpcClient> ZKSProvider for Provider<P> {
487    type Provider = P;
488    type ZKProvider = P;
489
490    async fn zk_estimate_gas<T>(&self, transaction: T) -> Result<U256, ProviderError>
491    where
492        T: Debug + Serialize + Send + Sync,
493    {
494        self.request("eth_estimateGas", [transaction]).await
495    }
496
497    async fn estimate_fee<T>(&self, transaction: T) -> Result<Fee, ProviderError>
498    where
499        T: Debug + Serialize + Send + Sync,
500    {
501        self.request("zks_estimateFee", [transaction]).await
502    }
503
504    async fn estimate_gas_l1_to_l2<T>(&self, transaction: T) -> Result<U256, ProviderError>
505    where
506        T: Debug + Serialize + Send + Sync,
507    {
508        self.request("zks_estimateGasL1ToL2", [transaction]).await
509    }
510
511    async fn get_all_account_balances(
512        &self,
513        address: Address,
514    ) -> Result<HashMap<Address, U256>, ProviderError> {
515        self.request("zks_getAllAccountBalances", [address]).await
516    }
517
518    async fn get_block_details<T>(&self, block: T) -> Result<Option<BlockDetails>, ProviderError>
519    where
520        T: Into<U64> + Send + Sync + Serialize + Debug,
521    {
522        self.request("zks_getBlockDetails", [block]).await
523    }
524
525    async fn get_bridge_contracts(&self) -> Result<BridgeContracts, ProviderError> {
526        self.request("zks_getBridgeContracts", ()).await
527    }
528
529    async fn get_bytecode_by_hash(&self, hash: H256) -> Result<Option<Vec<u8>>, ProviderError> {
530        self.request("zks_getBytecodeByHash", [hash]).await
531    }
532
533    async fn get_confirmed_tokens(
534        &self,
535        from: u32,
536        limit: u8,
537    ) -> Result<Vec<TokenInfo>, ProviderError> {
538        self.request("zks_getConfirmedTokens", [from, limit.into()])
539            .await
540    }
541
542    async fn get_l1_batch_block_range<T>(&self, batch: T) -> Result<BlockRange, ProviderError>
543    where
544        T: Into<U64> + Send + Sync + Serialize + Debug,
545    {
546        self.request("zks_getL1BatchBlockRange", [batch]).await
547    }
548
549    async fn get_l1_batch_details<T>(&self, batch: T) -> Result<L1BatchDetails, ProviderError>
550    where
551        T: Into<U64> + Send + Sync + Serialize + Debug,
552    {
553        self.request("zks_getL1BatchDetails", [batch]).await
554    }
555
556    async fn get_l2_to_l1_log_proof(
557        &self,
558        tx_hash: H256,
559        l2_to_l1_log_index: Option<u64>,
560    ) -> Result<Option<Proof>, ProviderError> {
561        self.request(
562            "zks_getL2ToL1LogProof",
563            json!([tx_hash, l2_to_l1_log_index]),
564        )
565        .await
566    }
567
568    async fn get_l2_to_l1_msg_proof<T>(
569        &self,
570        block: T,
571        sender: Address,
572        msg: H256,
573        l2_log_position: Option<u64>,
574    ) -> Result<Option<Proof>, ProviderError>
575    where
576        T: Into<U64> + Send + Sync + Serialize + Debug,
577    {
578        self.request(
579            "zks_getL2ToL1MsgProof",
580            json!([block, sender, msg, l2_log_position]),
581        )
582        .await
583    }
584
585    async fn get_main_contract(&self) -> Result<Address, ProviderError> {
586        self.request("zks_getMainContract", ()).await
587    }
588
589    async fn get_raw_block_transactions<T>(
590        &self,
591        block: T,
592    ) -> Result<Vec<Transaction>, ProviderError>
593    where
594        T: Into<U64> + Send + Sync + Serialize + Debug,
595    {
596        self.request("zks_getRawBlockTransactions", [block]).await
597    }
598
599    async fn get_testnet_paymaster(&self) -> Result<Address, ProviderError> {
600        self.request("zks_getTestnetPaymaster", ()).await
601    }
602
603    async fn get_token_price(&self, address: Address) -> Result<String, ProviderError> {
604        self.request("zks_getTokenPrice", [address]).await
605    }
606
607    async fn get_transaction_details(
608        &self,
609        hash: H256,
610    ) -> Result<Option<TransactionDetails>, ProviderError> {
611        self.request("zks_getTransactionDetails", [hash]).await
612    }
613
614    async fn get_l1_batch_number(&self) -> Result<U256, ProviderError> {
615        self.request("zks_L1BatchNumber", ()).await
616    }
617
618    async fn get_l1_chain_id(&self) -> Result<U256, ProviderError> {
619        self.request("zks_L1ChainId", ()).await
620    }
621
622    async fn debug_trace_block_by_hash(
623        &self,
624        hash: H256,
625        options: Option<TracerConfig>,
626    ) -> Result<DebugTrace, ProviderError> {
627        let processable_response = self
628            .request::<serde_json::Value, serde_json::Value>(
629                "debug_traceBlockByHash",
630                json!([hash, options]),
631            )
632            .await?
633            .get(0)
634            .ok_or(ProviderError::CustomError(
635                "error on debug_trace_block_by_hash".to_owned(),
636            ))?
637            .get("result")
638            .ok_or(ProviderError::CustomError(
639                "error on debug_trace_block_by_hash".to_owned(),
640            ))?
641            .clone();
642        serde_json::from_value(processable_response).map_err(ProviderError::SerdeJson)
643    }
644
645    async fn debug_trace_block_by_number<T>(
646        &self,
647        block: T,
648        options: Option<TracerConfig>,
649    ) -> Result<DebugTrace, ProviderError>
650    where
651        T: Into<U64> + Send + Sync + Serialize + Debug,
652    {
653        let processable_response = self
654            .request::<serde_json::Value, serde_json::Value>(
655                "debug_traceBlockByNumber",
656                json!([block, options]),
657            )
658            .await?
659            .get(0)
660            .ok_or(ProviderError::CustomError(
661                "error on debug_trace_block_by_hash".to_owned(),
662            ))?
663            .get("result")
664            .ok_or(ProviderError::CustomError(
665                "error on debug_trace_block_by_hash".to_owned(),
666            ))?
667            .clone();
668        serde_json::from_value(processable_response).map_err(ProviderError::SerdeJson)
669    }
670
671    async fn debug_trace_call<R, T>(
672        &self,
673        request: R,
674        block: Option<T>,
675        options: Option<TracerConfig>,
676    ) -> Result<DebugTrace, ProviderError>
677    where
678        R: Debug + Serialize + Send + Sync,
679        T: Into<U64> + Send + Sync + Serialize + Debug,
680    {
681        self.request("debug_traceCall", json!([request, block, options]))
682            .await
683    }
684
685    async fn debug_trace_transaction(
686        &self,
687        hash: H256,
688        options: Option<TracerConfig>,
689    ) -> Result<DebugTrace, ProviderError> {
690        self.request("debug_traceTransaction", json!([hash, options]))
691            .await
692    }
693
694    async fn send_transaction_eip712<T, D>(
695        &self,
696        wallet: &Wallet<D>,
697        transaction: T,
698    ) -> Result<PendingTransaction<Self::ZKProvider>, ProviderError>
699    where
700        T: TryInto<Eip712TransactionRequest> + Sync + Send + Debug,
701        D: PrehashSigner<(RecoverableSignature, RecoveryId)> + Send + Sync,
702    {
703        let mut request: Eip712TransactionRequest = transaction.try_into().map_err(|_e| {
704            ProviderError::CustomError("error on send_transaction_eip712".to_owned())
705        })?;
706
707        let gas_price = self.get_gas_price().await?;
708        request = request
709            .from(wallet.address())
710            .chain_id(wallet.chain_id())
711            .nonce(self.get_transaction_count(wallet.address(), None).await?)
712            .gas_price(gas_price)
713            .max_fee_per_gas(gas_price);
714
715        let custom_data = request.clone().custom_data;
716        let fee = self.estimate_fee(request.clone()).await?;
717        request = request
718            .max_priority_fee_per_gas(fee.max_priority_fee_per_gas)
719            .max_fee_per_gas(fee.max_fee_per_gas)
720            .gas_limit(fee.gas_limit);
721        let signable_data: Eip712Transaction = request
722            .clone()
723            .try_into()
724            .map_err(|e: Eip712Error| ProviderError::CustomError(e.to_string()))?;
725        let signature: Signature = wallet
726            .sign_typed_data(&signable_data)
727            .await
728            .map_err(|e| ProviderError::CustomError(format!("error signing transaction: {e}")))?;
729        request = request.custom_data(custom_data.custom_signature(signature.to_vec()));
730        let encoded_rlp = &*request
731            .rlp_signed(signature)
732            .map_err(|e| ProviderError::CustomError(format!("Error in the rlp encoding {e}")))?;
733
734        self.send_raw_transaction([&[EIP712_TX_TYPE], encoded_rlp].concat().into())
735            .await
736    }
737
738    async fn send_eip712<D>(
739        &self,
740        wallet: &Wallet<D>,
741        contract_address: Address,
742        function_signature: &str,
743        function_parameters: Option<Vec<String>>,
744        overrides: Option<Overrides>,
745    ) -> Result<PendingTransaction<Self::ZKProvider>, ProviderError>
746    where
747        D: PrehashSigner<(RecoverableSignature, RecoveryId)> + Send + Sync,
748    {
749        // Note: We couldn't implement ProviderError::LexerError because ethers-rs's LexerError is not exposed.
750        // TODO check for ECADD precompile address to get the function signature.
751        let function = HumanReadableParser::parse_function(function_signature)
752            .map_err(|e| ProviderError::CustomError(e.to_string()))?;
753
754        let mut send_request = if let Some(overrides) = overrides {
755            Eip712TransactionRequest::from_overrides(overrides)
756        } else {
757            Eip712TransactionRequest::new()
758        };
759
760        let function_args = if let Some(function_args) = function_parameters {
761            function
762                .decode_input(
763                    &zks_utils::encode_args(&function, &function_args)
764                        .map_err(|e| ProviderError::CustomError(e.to_string()))?,
765                )
766                .map_err(|e| ProviderError::CustomError(e.to_string()))?
767        } else {
768            vec![]
769        };
770
771        send_request = send_request
772            .r#type(EIP712_TX_TYPE)
773            .from(wallet.address())
774            .to(contract_address)
775            .chain_id(wallet.chain_id())
776            .nonce(self.get_transaction_count(wallet.address(), None).await?)
777            .gas_price(self.get_gas_price().await?)
778            .max_fee_per_gas(self.get_gas_price().await?)
779            .data(if !function_args.is_empty() {
780                function
781                    .encode_input(&function_args)
782                    .map_err(|e| ProviderError::CustomError(e.to_string()))?
783            } else {
784                function.short_signature().into()
785            });
786
787        let fee = self.estimate_fee(send_request.clone()).await?;
788        send_request = send_request
789            .max_priority_fee_per_gas(fee.max_priority_fee_per_gas)
790            .max_fee_per_gas(fee.max_fee_per_gas)
791            .gas_limit(fee.gas_limit);
792
793        let signable_data: Eip712Transaction = send_request
794            .clone()
795            .try_into()
796            .map_err(|e: Eip712Error| ProviderError::CustomError(e.to_string()))?;
797        let signature: Signature = wallet
798            .sign_typed_data(&signable_data)
799            .await
800            .map_err(|e| ProviderError::CustomError(format!("error signing transaction: {e}")))?;
801        send_request =
802            send_request.custom_data(Eip712Meta::new().custom_signature(signature.to_vec()));
803
804        let encoded_rlp = &*send_request
805            .rlp_signed(signature)
806            .map_err(|e| ProviderError::CustomError(format!("error encoding transaction: {e}")))?;
807        self.send_raw_transaction([&[EIP712_TX_TYPE], encoded_rlp].concat().into())
808            .await
809    }
810
811    async fn send<D>(
812        &self,
813        wallet: &Wallet<D>,
814        contract_address: Address,
815        function_signature: &str,
816        function_parameters: Option<Vec<String>>,
817        _overrides: Option<Overrides>,
818    ) -> Result<PendingTransaction<Self::Provider>, ProviderError>
819    where
820        D: PrehashSigner<(RecoverableSignature, RecoveryId)> + Send + Sync,
821    {
822        let tx = build_send_tx(
823            self,
824            wallet,
825            contract_address,
826            function_signature,
827            function_parameters,
828            _overrides,
829        )
830        .await?;
831        self.send_transaction(tx, None).await
832    }
833
834    async fn wait_for_finalize(
835        &self,
836        tx_hash: TxHash,
837        polling_time_in_seconds: Option<Duration>,
838        timeout_in_seconds: Option<Duration>,
839    ) -> Result<TransactionReceipt, ProviderError> {
840        let polling_time_in_seconds = polling_time_in_seconds.unwrap_or(Duration::from_secs(2));
841        let mut timer = tokio::time::interval(polling_time_in_seconds);
842        let start = Instant::now();
843
844        let transaction_receipt =
845            self.get_transaction_receipt(tx_hash)
846                .await?
847                .ok_or(ProviderError::CustomError(
848                    "No transaction receipt".to_owned(),
849                ))?;
850
851        loop {
852            timer.tick().await;
853
854            if let Some(timeout) = timeout_in_seconds {
855                if start.elapsed() >= timeout {
856                    return Err(ProviderError::CustomError(
857                        "Error waiting for transaction to be included into the finalized block"
858                            .to_owned(),
859                    ));
860                }
861            }
862
863            // Wait for transaction to be included into the finalized block.
864            let latest_block =
865                self.get_block(BlockNumber::Finalized)
866                    .await?
867                    .ok_or(ProviderError::CustomError(
868                        "Error getting finalized block".to_owned(),
869                    ))?;
870
871            if transaction_receipt.block_number <= latest_block.number {
872                return Ok(transaction_receipt);
873            }
874        }
875    }
876
877    async fn call(&self, request: &CallRequest) -> Result<Vec<Token>, ProviderError> {
878        let function = request
879            .get_parsed_function()
880            .map_err(|e| ProviderError::CustomError(format!("Failed to parse function: {e}")))?;
881        let request: Eip1559TransactionRequest = request
882            .clone()
883            .try_into()
884            .map_err(|e| ProviderError::CustomError(format!("Failed to convert request: {e}")))?;
885        let transaction: TypedTransaction = request.into();
886
887        let encoded_output = Middleware::call(self, &transaction, None).await?;
888        let decoded_output = function.decode_output(&encoded_output).map_err(|e| {
889            ProviderError::CustomError(format!("failed to decode output: {e}\n{encoded_output}"))
890        })?;
891
892        Ok(if decoded_output.is_empty() {
893            encoded_output.into_tokens()
894        } else {
895            decoded_output
896        })
897    }
898}
899
900async fn build_send_tx<D>(
901    provider: &impl Middleware,
902    wallet: &Wallet<D>,
903    contract_address: Address,
904    function_signature: &str,
905    function_parameters: Option<Vec<String>>,
906    _overrides: Option<Overrides>,
907) -> Result<TypedTransaction, ProviderError>
908where
909    D: PrehashSigner<(RecoverableSignature, RecoveryId)> + Send + Sync,
910{
911    let function = HumanReadableParser::parse_function(function_signature)
912        .map_err(|e| ProviderError::CustomError(e.to_string()))?;
913
914    let function_args = if let Some(function_args) = function_parameters {
915        function
916            .decode_input(
917                &zks_utils::encode_args(&function, &function_args)
918                    .map_err(|e| ProviderError::CustomError(e.to_string()))?,
919            )
920            .map_err(|e| ProviderError::CustomError(e.to_string()))?
921    } else {
922        vec![]
923    };
924
925    // Sending transaction calling the main contract.
926    let send_request = Eip1559TransactionRequest::new()
927        .from(wallet.address())
928        .to(contract_address)
929        .chain_id(wallet.chain_id())
930        .nonce(
931            provider
932                .get_transaction_count(wallet.address(), None)
933                .await
934                .map_err(|e| ProviderError::CustomError(e.to_string()))?,
935        )
936        .data(if !function_args.is_empty() {
937            function
938                .encode_input(&function_args)
939                .map_err(|e| ProviderError::CustomError(e.to_string()))?
940        } else {
941            function.short_signature().into()
942        })
943        .value(0_u8)
944        //FIXME we should use default calculation for gas related fields.
945        .gas(DEFAULT_GAS)
946        .max_fee_per_gas(MAX_FEE_PER_GAS)
947        .max_priority_fee_per_gas(MAX_PRIORITY_FEE_PER_GAS);
948
949    Ok(send_request.into())
950}