Skip to content
This repository was archived by the owner on Oct 19, 2024. It is now read-only.

Commit 5edcd37

Browse files
DaniPopesgakonst
andauthored
feat(contract): use u64 and add more chains to multicall (#2042)
* feat: add new chains and use u64 * chore: manually implement Clone and Debug to avoid trait bounds. Co-authored-by: Georgios Konstantopoulos <[email protected]>
1 parent 9e559ae commit 5edcd37

File tree

1 file changed

+92
-71
lines changed
  • ethers-contract/src/multicall

1 file changed

+92
-71
lines changed

ethers-contract/src/multicall/mod.rs

Lines changed: 92 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
1-
use crate::{
2-
call::{ContractCall, ContractError},
3-
Lazy,
4-
};
1+
use crate::call::{ContractCall, ContractError};
52
use ethers_core::{
63
abi::{AbiDecode, Detokenize, Function, Token},
74
types::{Address, BlockNumber, Bytes, Chain, NameOrAddress, H160, U256},
85
};
6+
97
use ethers_providers::{Middleware, PendingTransaction};
10-
use std::{convert::TryFrom, sync::Arc};
8+
use std::{convert::TryFrom, fmt, sync::Arc};
119

1210
pub mod multicall_contract;
1311
use 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)]
8593
pub 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`"]
262269
pub 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

Comments
 (0)