1- use crate :: {
2- call:: { ContractCall , ContractError } ,
3- Lazy ,
4- } ;
1+ use crate :: call:: { ContractCall , ContractError } ;
52use ethers_core:: {
63 abi:: { AbiDecode , Detokenize , Function , Token } ,
74 types:: { Address , BlockNumber , Bytes , Chain , NameOrAddress , H160 , U256 } ,
85} ;
6+
97use ethers_providers:: { Middleware , PendingTransaction } ;
10- use std:: { convert:: TryFrom , sync:: Arc } ;
8+ use std:: { convert:: TryFrom , fmt , sync:: Arc } ;
119
1210pub mod multicall_contract;
1311use multicall_contract:: multicall_3:: {
@@ -26,68 +24,78 @@ pub const MULTICALL_ADDRESS: Address = H160([
2624] ) ;
2725
2826/// The chain IDs that [`MULTICALL_ADDRESS`] has been deployed to.
27+ ///
2928/// Taken from: <https://github.com/mds1/multicall#multicall3-contract-addresses>
30- pub static MULTICALL_SUPPORTED_CHAIN_IDS : Lazy < [ U256 ; 48 ] > = Lazy :: new ( || {
29+ pub const MULTICALL_SUPPORTED_CHAIN_IDS : & [ u64 ] = {
3130 use Chain :: * ;
32- [
33- U256 :: from ( Mainnet ) , // Mainnet
34- U256 :: from ( Kovan ) , // Kovan
35- U256 :: from ( Rinkeby ) , // Rinkeby
36- U256 :: from ( Goerli ) , // Goerli
37- U256 :: from ( Ropsten ) , // Ropsten
38- U256 :: from ( Sepolia ) , // Sepolia
39- U256 :: from ( Optimism ) , // Optimism
40- U256 :: from ( OptimismGoerli ) , // OptimismGoerli
41- U256 :: from ( OptimismKovan ) , // OptimismKovan
42- U256 :: from ( Arbitrum ) , // Arbitrum
43- U256 :: from ( ArbitrumGoerli ) , // ArbitrumGoerli,
44- U256 :: from ( ArbitrumTestnet ) , // Arbitrum Rinkeby
45- U256 :: from ( Polygon ) , // Polygon
46- U256 :: from ( PolygonMumbai ) , // PolygonMumbai
47- U256 :: from ( XDai ) , // XDai
48- U256 :: from ( Chiado ) , // ChiadoTestnet
49- U256 :: from ( Avalanche ) , // Avalanche
50- U256 :: from ( AvalancheFuji ) , // AvalancheFuji
51- U256 :: from ( FantomTestnet ) , // FantomTestnet
52- U256 :: from ( Fantom ) , // Fantom
53- U256 :: from ( BinanceSmartChain ) , // BinanceSmartChain
54- U256 :: from ( BinanceSmartChainTestnet ) , // BinanceSmartChainTestnet
55- U256 :: from ( Moonbeam ) , // Moonbeam
56- U256 :: from ( Moonriver ) , // Moonriver
57- U256 :: from ( Moonbase ) , // Moonbase
58- U256 :: from ( 1666600000 ) , // Harmony0
59- U256 :: from ( 1666600001 ) , // Harmony1
60- U256 :: from ( 1666600002 ) , // Harmony2
61- U256 :: from ( 1666600003 ) , // Harmony3
62- U256 :: from ( Cronos ) , // Cronos
63- U256 :: from ( 122 ) , // Fuse
64- U256 :: from ( 19 ) , // Songbird
65- U256 :: from ( 16 ) , // CostonTestnet
66- U256 :: from ( 288 ) , // Boba
67- U256 :: from ( Aurora ) , // Aurora
68- U256 :: from ( 592 ) , // Astar
69- U256 :: from ( 66 ) , // OKC
70- U256 :: from ( 128 ) , // Heco
71- U256 :: from ( 1088 ) , // Metis
72- U256 :: from ( Rsk ) , // Rsk
73- U256 :: from ( 31 ) , // RskTestnet
74- U256 :: from ( Evmos ) , // Evmos
75- U256 :: from ( EvmosTestnet ) , // EvmosTestnet
76- U256 :: from ( 71402 ) , // Godwoken
77- U256 :: from ( 71401 ) , // GodwokenTestnet
78- U256 :: from ( 8217 ) , // Klaytn
79- U256 :: from ( 2001 ) , // Milkomeda
80- U256 :: from ( 321 ) , // KCC
31+ & [
32+ Mainnet as u64 , // Mainnet
33+ Kovan as u64 , // Kovan
34+ Rinkeby as u64 , // Rinkeby
35+ Goerli as u64 , // Görli
36+ Ropsten as u64 , // Ropsten
37+ Sepolia as u64 , // Sepolia
38+ Optimism as u64 , // Optimism
39+ OptimismKovan as u64 , // Optimism Kovan
40+ OptimismGoerli as u64 , // Optimism Görli
41+ Arbitrum as u64 , // Arbitrum
42+ ArbitrumNova as u64 , // Arbitrum Nova
43+ ArbitrumGoerli as u64 , // Arbitrum Görli
44+ ArbitrumTestnet as u64 , // Arbitrum Rinkeby
45+ Polygon as u64 , // Polygon
46+ PolygonMumbai as u64 , // Polygon Mumbai
47+ XDai as u64 , // Gnosis Chain
48+ Avalanche as u64 , // Avalanche
49+ AvalancheFuji as u64 , // Avalanche Fuji
50+ FantomTestnet as u64 , // Fantom Testnet
51+ Fantom as u64 , // Fantom Opera
52+ BinanceSmartChain as u64 , // BNB Smart Chain
53+ BinanceSmartChainTestnet as u64 , // BNB Smart Chain Testnet
54+ Moonbeam as u64 , // Moonbeam
55+ Moonriver as u64 , // Moonriver
56+ Moonbase as u64 , // Moonbase
57+ 1666600000 , // Harmony0
58+ 1666600001 , // Harmony1
59+ 1666600002 , // Harmony2
60+ 1666600003 , // Harmony3
61+ Cronos as u64 , // Cronos
62+ 122 , // Fuse
63+ 14 , // Flare Mainnet
64+ 19 , // Songbird Canary Network
65+ 16 , // Coston Testnet
66+ 114 , // Coston2 Testnet
67+ 288 , // Boba
68+ Aurora as u64 , // Aurora
69+ 592 , // Astar
70+ 66 , // OKC
71+ 128 , // Heco Chain
72+ 1088 , // Metis
73+ Rsk as u64 , // Rsk
74+ 31 , // Rsk Testnet
75+ Evmos as u64 , // Evmos
76+ EvmosTestnet as u64 , // Evmos Testnet
77+ Oasis as u64 , // Oasis
78+ 42261 , // Oasis Emerald ParaTime Testnet
79+ 42262 , // Oasis Emerald ParaTime
80+ Celo as u64 , // Celo
81+ CeloAlfajores as u64 , // Celo Alfajores Testnet
82+ 71402 , // Godwoken
83+ 71401 , // Godwoken Testnet
84+ 8217 , // Klaytn
85+ 2001 , // Milkomeda
86+ 321 , // KCC
87+ 106 , // Velas
88+ 40 , // Telos
8189 ]
82- } ) ;
90+ } ;
8391
8492#[ derive( Debug , thiserror:: Error ) ]
8593pub enum MulticallError < M : Middleware > {
8694 #[ error( transparent) ]
8795 ContractError ( #[ from] ContractError < M > ) ,
8896
8997 #[ error( "Chain ID {0} is currently not supported by Multicall. Provide an address instead." ) ]
90- InvalidChainId ( U256 ) ,
98+ InvalidChainId ( u64 ) ,
9199
92100 #[ error( "Illegal revert: Multicall2 call reverted when it wasn't allowed to." ) ]
93101 IllegalRevert ,
@@ -257,7 +265,6 @@ impl TryFrom<u8> for MulticallVersion {
257265/// [`add_call`]: #method.add_call
258266/// [`call`]: #method.call
259267/// [`send`]: #method.send
260- #[ derive( Clone ) ]
261268#[ must_use = "Multicall does nothing unless you use `call` or `send`" ]
262269pub struct Multicall < M > {
263270 /// The Multicall contract interface.
@@ -268,15 +275,27 @@ pub struct Multicall<M> {
268275 calls : Vec < Call > ,
269276}
270277
271- // Manually implement Debug due to Middleware trait bounds.
272- impl < M : Middleware > std:: fmt:: Debug for Multicall < M > {
273- fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
278+ // Manually implement Clone and Debug to avoid trait bounds.
279+ impl < M > Clone for Multicall < M > {
280+ fn clone ( & self ) -> Self {
281+ Self {
282+ contract : self . contract . clone ( ) ,
283+ version : self . version ,
284+ legacy : self . legacy ,
285+ block : self . block . clone ( ) ,
286+ calls : self . calls . clone ( ) ,
287+ }
288+ }
289+ }
290+
291+ impl < M > fmt:: Debug for Multicall < M > {
292+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
274293 f. debug_struct ( "Multicall" )
294+ . field ( "address" , & self . contract . address ( ) )
275295 . field ( "version" , & self . version )
276296 . field ( "legacy" , & self . legacy )
277297 . field ( "block" , & self . block )
278298 . field ( "calls" , & self . calls )
279- . field ( "contract" , & self . contract )
280299 . finish ( )
281300 }
282301}
@@ -305,7 +324,7 @@ impl<M: Middleware> Multicall<M> {
305324 Some ( addr) => addr,
306325 None => {
307326 let chain_id =
308- client. get_chainid ( ) . await . map_err ( ContractError :: MiddlewareError ) ?;
327+ client. get_chainid ( ) . await . map_err ( ContractError :: MiddlewareError ) ?. as_u64 ( ) ;
309328 if !MULTICALL_SUPPORTED_CHAIN_IDS . contains ( & chain_id) {
310329 return Err ( MulticallError :: InvalidChainId ( chain_id) )
311330 }
@@ -341,22 +360,24 @@ impl<M: Middleware> Multicall<M> {
341360 pub fn new_with_chain_id (
342361 client : impl Into < Arc < M > > ,
343362 address : Option < Address > ,
344- chain_id : Option < impl Into < U256 > > ,
363+ chain_id : Option < impl Into < u64 > > ,
345364 ) -> Result < Self , M > {
346365 // If no address is provided, check if chain_id is supported and use the default multicall
347366 // address.
348- let address: Address = match address {
349- Some ( addr) => addr,
350- None => {
351- // Can't fetch chain_id from provider since we're not in an async function so we
352- // panic instead.
353- let chain_id =
354- chain_id. expect ( "Must provide at least one of: address or chain ID." ) . into ( ) ;
367+ let address: Address = match ( address, chain_id) {
368+ ( Some ( addr) , _) => addr,
369+ ( _, Some ( chain_id) ) => {
370+ let chain_id = chain_id. into ( ) ;
355371 if !MULTICALL_SUPPORTED_CHAIN_IDS . contains ( & chain_id) {
356372 return Err ( MulticallError :: InvalidChainId ( chain_id) )
357373 }
358374 MULTICALL_ADDRESS
359375 }
376+ _ => {
377+ // Can't fetch chain_id from provider since we're not in an async function so we
378+ // panic instead.
379+ panic ! ( "Must provide at least one of: address or chain ID." )
380+ }
360381 } ;
361382
362383 // Instantiate the multicall contract
0 commit comments