alloy_chains/
named.rs

1use alloy_primitives::{address, Address};
2use core::{cmp::Ordering, fmt, time::Duration};
3use num_enum::TryFromPrimitiveError;
4
5#[allow(unused_imports)]
6use alloc::string::String;
7// When adding a new chain:
8//   1. add new variant to the NamedChain enum;
9//   2. add extra information in the last `impl` block (explorer URLs, block time) when applicable;
10//   3. (optional) add aliases:
11//     - Strum (in kebab-case): `#[strum(to_string = "<main>", serialize = "<aliasX>", ...)]`
12//      `to_string = "<main>"` must be present and will be used in `Display`, `Serialize`
13//      and `FromStr`, while `serialize = "<aliasX>"` will be appended to `FromStr`.
14//      More info: <https://docs.rs/strum/latest/strum/additional_attributes/index.html#attributes-on-variants>
15//     - Serde (in snake_case): `#[cfg_attr(feature = "serde", serde(alias = "<aliasX>", ...))]`
16//      Aliases are appended to the `Deserialize` implementation.
17//      More info: <https://serde.rs/variant-attrs.html>
18//     - Add a test at the bottom of the file
19//   4. run `cargo test --all-features` to update the JSON bindings and schema.
20//   5. run `cargo fmt --all` to properly format the code.
21
22// We don't derive Serialize because it is manually implemented using AsRef<str> and it would break
23// a lot of things since Serialize is `kebab-case` vs Deserialize `snake_case`. This means that the
24// NamedChain type is not "round-trippable", because the Serialize and Deserialize implementations
25// do not use the same case style.
26
27/// An Ethereum EIP-155 chain.
28#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
29#[derive(strum::IntoStaticStr)] // Into<&'static str>, AsRef<str>, fmt::Display and serde::Serialize
30#[derive(strum::VariantNames)] // NamedChain::VARIANTS
31#[derive(strum::VariantArray)] // NamedChain::VARIANTS
32#[derive(strum::EnumString)] // FromStr, TryFrom<&str>
33#[derive(strum::EnumIter)] // NamedChain::iter
34#[derive(strum::EnumCount)] // NamedChain::COUNT
35#[derive(num_enum::TryFromPrimitive)] // TryFrom<u64>
36#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
37#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
38#[strum(serialize_all = "kebab-case")]
39#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
40#[repr(u64)]
41#[allow(missing_docs)]
42#[non_exhaustive]
43pub enum NamedChain {
44    #[strum(to_string = "mainnet", serialize = "ethlive")]
45    #[cfg_attr(feature = "serde", serde(alias = "ethlive"))]
46    Mainnet = 1,
47    Morden = 2,
48    Ropsten = 3,
49    Rinkeby = 4,
50    Goerli = 5,
51    Kovan = 42,
52    Holesky = 17000,
53    Hoodi = 560048,
54    Sepolia = 11155111,
55
56    #[cfg_attr(feature = "serde", serde(alias = "odyssey"))]
57    Odyssey = 911867,
58
59    Optimism = 10,
60    #[cfg_attr(feature = "serde", serde(alias = "optimism-kovan"))]
61    OptimismKovan = 69,
62    #[cfg_attr(feature = "serde", serde(alias = "optimism-goerli"))]
63    OptimismGoerli = 420,
64    #[cfg_attr(feature = "serde", serde(alias = "optimism-sepolia"))]
65    OptimismSepolia = 11155420,
66
67    #[strum(to_string = "bob")]
68    #[cfg_attr(feature = "serde", serde(alias = "bob"))]
69    Bob = 60808,
70    #[strum(to_string = "bob-sepolia")]
71    #[cfg_attr(feature = "serde", serde(alias = "bob-sepolia"))]
72    BobSepolia = 808813,
73
74    #[cfg_attr(feature = "serde", serde(alias = "arbitrum_one", alias = "arbitrum-one"))]
75    Arbitrum = 42161,
76    ArbitrumTestnet = 421611,
77    #[cfg_attr(feature = "serde", serde(alias = "arbitrum-goerli"))]
78    ArbitrumGoerli = 421613,
79    #[cfg_attr(feature = "serde", serde(alias = "arbitrum-sepolia"))]
80    ArbitrumSepolia = 421614,
81    #[cfg_attr(feature = "serde", serde(alias = "arbitrum-nova"))]
82    ArbitrumNova = 42170,
83
84    Cronos = 25,
85    CronosTestnet = 338,
86
87    Rsk = 30,
88
89    #[strum(to_string = "telos")]
90    #[cfg_attr(feature = "serde", serde(alias = "telos", alias = "telos_evm"))]
91    TelosEvm = 40,
92    #[strum(to_string = "telos-testnet")]
93    #[cfg_attr(
94        feature = "serde",
95        serde(alias = "telos_testnet", alias = "telos-evm-testnet", alias = "telos_evm_testnet")
96    )]
97    TelosEvmTestnet = 41,
98
99    #[strum(to_string = "crab")]
100    #[cfg_attr(feature = "serde", serde(alias = "crab"))]
101    Crab = 44,
102    #[strum(to_string = "darwinia")]
103    #[cfg_attr(feature = "serde", serde(alias = "darwinia"))]
104    Darwinia = 46,
105    #[strum(to_string = "koi")]
106    #[cfg_attr(feature = "serde", serde(alias = "koi"))]
107    Koi = 701,
108
109    /// Note the correct name for BSC should be `BNB Smart Chain` due to the rebranding: <https://www.bnbchain.org/en/blog/bsc-is-now-bnb-chain-the-infrastructure-for-the-metafi-universe>
110    /// We keep `Binance Smart Chain` for backward compatibility, and the enum could be renamed in
111    /// the future release.
112    #[strum(to_string = "bsc", serialize = "binance-smart-chain", serialize = "bnb-smart-chain")]
113    #[cfg_attr(
114        feature = "serde",
115        serde(alias = "bsc", alias = "bnb-smart-chain", alias = "binance-smart-chain")
116    )]
117    BinanceSmartChain = 56,
118    #[strum(
119        to_string = "bsc-testnet",
120        serialize = "binance-smart-chain-testnet",
121        serialize = "bnb-smart-chain-testnet"
122    )]
123    #[cfg_attr(
124        feature = "serde",
125        serde(
126            alias = "bsc_testnet",
127            alias = "bsc-testnet",
128            alias = "bnb-smart-chain-testnet",
129            alias = "binance-smart-chain-testnet"
130        )
131    )]
132    BinanceSmartChainTestnet = 97,
133
134    Poa = 99,
135    Sokol = 77,
136
137    Scroll = 534352,
138    #[cfg_attr(
139        feature = "serde",
140        serde(alias = "scroll_sepolia_testnet", alias = "scroll-sepolia")
141    )]
142    ScrollSepolia = 534351,
143
144    Metis = 1088,
145
146    #[cfg_attr(feature = "serde", serde(alias = "conflux-espace-testnet"))]
147    CfxTestnet = 71,
148    #[cfg_attr(feature = "serde", serde(alias = "conflux-espace"))]
149    Cfx = 1030,
150
151    #[strum(to_string = "xdai", serialize = "gnosis", serialize = "gnosis-chain")]
152    #[cfg_attr(feature = "serde", serde(alias = "xdai", alias = "gnosis", alias = "gnosis-chain"))]
153    Gnosis = 100,
154
155    Polygon = 137,
156    #[strum(to_string = "mumbai", serialize = "polygon-mumbai")]
157    #[cfg_attr(feature = "serde", serde(alias = "mumbai", alias = "polygon-mumbai"))]
158    PolygonMumbai = 80001,
159    #[strum(to_string = "amoy", serialize = "polygon-amoy")]
160    #[cfg_attr(feature = "serde", serde(alias = "amoy", alias = "polygon-amoy"))]
161    PolygonAmoy = 80002,
162    #[strum(serialize = "polygon-zkevm", serialize = "zkevm")]
163    #[cfg_attr(
164        feature = "serde",
165        serde(alias = "zkevm", alias = "polygon_zkevm", alias = "polygon-zkevm")
166    )]
167    PolygonZkEvm = 1101,
168    #[strum(serialize = "polygon-zkevm-testnet", serialize = "zkevm-testnet")]
169    #[cfg_attr(
170        feature = "serde",
171        serde(
172            alias = "zkevm-testnet",
173            alias = "polygon_zkevm_testnet",
174            alias = "polygon-zkevm-testnet"
175        )
176    )]
177    PolygonZkEvmTestnet = 1442,
178
179    Fantom = 250,
180    FantomTestnet = 4002,
181
182    Moonbeam = 1284,
183    MoonbeamDev = 1281,
184
185    Moonriver = 1285,
186
187    Moonbase = 1287,
188
189    Dev = 1337,
190    #[strum(to_string = "anvil-hardhat", serialize = "anvil", serialize = "hardhat")]
191    #[cfg_attr(
192        feature = "serde",
193        serde(alias = "anvil", alias = "hardhat", alias = "anvil-hardhat")
194    )]
195    AnvilHardhat = 31337,
196
197    #[strum(to_string = "gravity-alpha-mainnet")]
198    #[cfg_attr(feature = "serde", serde(alias = "gravity-alpha-mainnet"))]
199    GravityAlphaMainnet = 1625,
200    #[strum(to_string = "gravity-alpha-testnet-sepolia")]
201    #[cfg_attr(feature = "serde", serde(alias = "gravity-alpha-testnet-sepolia"))]
202    GravityAlphaTestnetSepolia = 13505,
203
204    Evmos = 9001,
205    EvmosTestnet = 9000,
206
207    Chiado = 10200,
208
209    Oasis = 26863,
210
211    Emerald = 42262,
212    EmeraldTestnet = 42261,
213
214    FilecoinMainnet = 314,
215    FilecoinCalibrationTestnet = 314159,
216
217    Avalanche = 43114,
218    #[strum(to_string = "fuji", serialize = "avalanche-fuji")]
219    #[cfg_attr(feature = "serde", serde(alias = "fuji"))]
220    AvalancheFuji = 43113,
221
222    Celo = 42220,
223    CeloAlfajores = 44787,
224    CeloBaklava = 62320,
225
226    Aurora = 1313161554,
227    AuroraTestnet = 1313161555,
228
229    Canto = 7700,
230    CantoTestnet = 740,
231
232    Boba = 288,
233
234    Base = 8453,
235    #[cfg_attr(feature = "serde", serde(alias = "base-goerli"))]
236    BaseGoerli = 84531,
237    #[cfg_attr(feature = "serde", serde(alias = "base-sepolia"))]
238    BaseSepolia = 84532,
239    #[cfg_attr(feature = "serde", serde(alias = "syndr"))]
240    Syndr = 404,
241    #[cfg_attr(feature = "serde", serde(alias = "syndr-sepolia"))]
242    SyndrSepolia = 444444,
243
244    Shimmer = 148,
245
246    Ink = 57073,
247    #[cfg_attr(feature = "serde", serde(alias = "ink_sepolia_testnet", alias = "ink-sepolia"))]
248    InkSepolia = 763373,
249
250    #[strum(to_string = "fraxtal")]
251    #[cfg_attr(feature = "serde", serde(alias = "fraxtal"))]
252    Fraxtal = 252,
253    #[strum(to_string = "fraxtal-testnet")]
254    #[cfg_attr(feature = "serde", serde(alias = "fraxtal-testnet"))]
255    FraxtalTestnet = 2522,
256
257    Blast = 81457,
258    #[cfg_attr(feature = "serde", serde(alias = "blast-sepolia"))]
259    BlastSepolia = 168587773,
260
261    Linea = 59144,
262    #[cfg_attr(feature = "serde", serde(alias = "linea-goerli"))]
263    LineaGoerli = 59140,
264    #[cfg_attr(feature = "serde", serde(alias = "linea-sepolia"))]
265    LineaSepolia = 59141,
266
267    #[strum(to_string = "zksync")]
268    #[cfg_attr(feature = "serde", serde(alias = "zksync"))]
269    ZkSync = 324,
270    #[strum(to_string = "zksync-testnet")]
271    #[cfg_attr(feature = "serde", serde(alias = "zksync_testnet", alias = "zksync-testnet"))]
272    ZkSyncTestnet = 300,
273
274    #[strum(to_string = "mantle")]
275    #[cfg_attr(feature = "serde", serde(alias = "mantle"))]
276    Mantle = 5000,
277    #[strum(to_string = "mantle-testnet")]
278    #[cfg_attr(feature = "serde", serde(alias = "mantle-testnet"))]
279    MantleTestnet = 5001,
280    #[strum(to_string = "mantle-sepolia")]
281    #[cfg_attr(feature = "serde", serde(alias = "mantle-sepolia"))]
282    MantleSepolia = 5003,
283
284    #[strum(to_string = "xai")]
285    #[cfg_attr(feature = "serde", serde(alias = "xai"))]
286    Xai = 660279,
287    #[strum(to_string = "xai-sepolia")]
288    #[cfg_attr(feature = "serde", serde(alias = "xai-sepolia"))]
289    XaiSepolia = 37714555429,
290
291    #[strum(to_string = "happychain-testnet")]
292    #[cfg_attr(feature = "serde", serde(alias = "happychain-testnet"))]
293    HappychainTestnet = 216,
294
295    Viction = 88,
296
297    Zora = 7777777,
298    #[cfg_attr(feature = "serde", serde(alias = "zora-sepolia"))]
299    ZoraSepolia = 999999999,
300
301    Pgn = 424,
302    #[cfg_attr(feature = "serde", serde(alias = "pgn-sepolia"))]
303    PgnSepolia = 58008,
304
305    Mode = 34443,
306    #[cfg_attr(feature = "serde", serde(alias = "mode-sepolia"))]
307    ModeSepolia = 919,
308
309    Elastos = 20,
310
311    #[cfg_attr(
312        feature = "serde",
313        serde(alias = "kakarot-sepolia", alias = "kakarot-starknet-sepolia")
314    )]
315    KakarotSepolia = 920637907288165,
316
317    #[cfg_attr(feature = "serde", serde(alias = "etherlink"))]
318    Etherlink = 42793,
319
320    #[cfg_attr(feature = "serde", serde(alias = "etherlink-testnet"))]
321    EtherlinkTestnet = 128123,
322
323    Degen = 666666666,
324
325    #[strum(to_string = "opbnb-mainnet")]
326    #[cfg_attr(
327        feature = "serde",
328        serde(rename = "opbnb_mainnet", alias = "opbnb-mainnet", alias = "op-bnb-mainnet")
329    )]
330    OpBNBMainnet = 204,
331    #[strum(to_string = "opbnb-testnet")]
332    #[cfg_attr(
333        feature = "serde",
334        serde(rename = "opbnb_testnet", alias = "opbnb-testnet", alias = "op-bnb-testnet")
335    )]
336    OpBNBTestnet = 5611,
337
338    Ronin = 2020,
339
340    #[cfg_attr(feature = "serde", serde(alias = "ronin-testnet"))]
341    RoninTestnet = 2021,
342
343    Taiko = 167000,
344    #[cfg_attr(feature = "serde", serde(alias = "taiko-hekla"))]
345    TaikoHekla = 167009,
346
347    #[strum(to_string = "autonomys-nova-testnet")]
348    #[cfg_attr(
349        feature = "serde",
350        serde(rename = "autonomys_nova_testnet", alias = "autonomys-nova-testnet")
351    )]
352    AutonomysNovaTestnet = 490000,
353
354    Flare = 14,
355    #[cfg_attr(feature = "serde", serde(alias = "flare-coston2"))]
356    FlareCoston2 = 114,
357
358    #[strum(to_string = "acala")]
359    #[cfg_attr(feature = "serde", serde(alias = "acala"))]
360    Acala = 787,
361    #[strum(to_string = "acala-mandala-testnet")]
362    #[cfg_attr(feature = "serde", serde(alias = "acala-mandala-testnet"))]
363    AcalaMandalaTestnet = 595,
364    #[strum(to_string = "acala-testnet")]
365    #[cfg_attr(feature = "serde", serde(alias = "acala-testnet"))]
366    AcalaTestnet = 597,
367
368    #[strum(to_string = "karura")]
369    #[cfg_attr(feature = "serde", serde(alias = "karura"))]
370    Karura = 686,
371    #[strum(to_string = "karura-testnet")]
372    #[cfg_attr(feature = "serde", serde(alias = "karura-testnet"))]
373    KaruraTestnet = 596,
374    #[strum(to_string = "pulsechain")]
375    #[cfg_attr(feature = "serde", serde(alias = "pulsechain"))]
376    Pulsechain = 369,
377    #[strum(to_string = "pulsechain-testnet")]
378    #[cfg_attr(feature = "serde", serde(alias = "pulsechain-testnet"))]
379    PulsechainTestnet = 943,
380
381    #[strum(to_string = "immutable")]
382    #[cfg_attr(feature = "serde", serde(alias = "immutable"))]
383    Immutable = 13371,
384    #[strum(to_string = "immutable-testnet")]
385    #[cfg_attr(feature = "serde", serde(alias = "immutable-testnet"))]
386    ImmutableTestnet = 13473,
387
388    #[strum(to_string = "soneium")]
389    #[cfg_attr(feature = "serde", serde(alias = "soneium"))]
390    Soneium = 1868,
391
392    #[strum(to_string = "soneium-minato-testnet")]
393    #[cfg_attr(feature = "serde", serde(alias = "soneium-minato-testnet"))]
394    SoneiumMinatoTestnet = 1946,
395
396    #[cfg_attr(feature = "serde", serde(alias = "worldchain"))]
397    World = 480,
398    #[strum(to_string = "world-sepolia")]
399    #[cfg_attr(feature = "serde", serde(alias = "worldchain-sepolia", alias = "world-sepolia"))]
400    WorldSepolia = 4801,
401    Iotex = 4689,
402    Core = 1116,
403    Merlin = 4200,
404    Bitlayer = 200901,
405    Vana = 1480,
406    Zeta = 7000,
407    Kaia = 8217,
408    Story = 1514,
409    Sei = 1329,
410
411    Unichain = 130,
412    #[strum(to_string = "unichain-sepolia")]
413    #[cfg_attr(feature = "serde", serde(alias = "unichain-sepolia"))]
414    UnichainSepolia = 1301,
415
416    #[strum(to_string = "apechain")]
417    #[cfg_attr(feature = "serde", serde(alias = "apechain"))]
418    ApeChain = 33139,
419    #[strum(to_string = "curtis", serialize = "apechain-testnet")]
420    #[cfg_attr(feature = "serde", serde(alias = "apechain-testnet", alias = "curtis"))]
421    Curtis = 33111,
422
423    #[strum(to_string = "sonic-blaze")]
424    #[cfg_attr(feature = "serde", serde(alias = "sonic-blaze"))]
425    SonicBlaze = 57054,
426    #[strum(to_string = "sonic-testnet")]
427    #[cfg_attr(feature = "serde", serde(alias = "sonic-testnet"))]
428    SonicTestnet = 64165,
429    #[strum(to_string = "sonic")]
430    #[cfg_attr(feature = "serde", serde(alias = "sonic"))]
431    Sonic = 146,
432
433    #[strum(to_string = "treasure")]
434    #[cfg_attr(feature = "serde", serde(alias = "treasure"))]
435    Treasure = 61166,
436
437    #[strum(to_string = "treasure-topaz", serialize = "treasure-topaz-testnet")]
438    #[cfg_attr(
439        feature = "serde",
440        serde(alias = "treasure-topaz-testnet", alias = "treasure-topaz")
441    )]
442    TreasureTopaz = 978658,
443
444    #[strum(to_string = "berachain-bepolia", serialize = "berachain-bepolia-testnet")]
445    #[cfg_attr(
446        feature = "serde",
447        serde(alias = "berachain-bepolia-testnet", alias = "berachain-bepolia")
448    )]
449    BerachainBepolia = 80069,
450
451    #[strum(to_string = "berachain-bartio", serialize = "berachain-bartio-testnet")]
452    #[cfg_attr(
453        feature = "serde",
454        serde(alias = "berachain-bartio-testnet", alias = "berachain-bartio")
455    )]
456    BerachainBartio = 80084,
457
458    #[strum(to_string = "berachain-artio", serialize = "berachain-artio-testnet")]
459    #[cfg_attr(
460        feature = "serde",
461        serde(alias = "berachain-artio-testnet", alias = "berachain-artio")
462    )]
463    BerachainArtio = 80085,
464
465    Berachain = 80094,
466
467    #[strum(to_string = "superposition-testnet")]
468    #[cfg_attr(feature = "serde", serde(alias = "superposition-testnet"))]
469    SuperpositionTestnet = 98985,
470
471    #[strum(to_string = "superposition")]
472    #[cfg_attr(feature = "serde", serde(alias = "superposition"))]
473    Superposition = 55244,
474
475    #[strum(serialize = "monad-testnet")]
476    #[cfg_attr(feature = "serde", serde(alias = "monad-testnet"))]
477    MonadTestnet = 10143,
478
479    #[strum(to_string = "hyperliquid")]
480    #[cfg_attr(feature = "serde", serde(alias = "hyperliquid"))]
481    Hyperliquid = 999,
482
483    #[strum(to_string = "abstract")]
484    #[cfg_attr(feature = "serde", serde(alias = "abstract"))]
485    Abstract = 2741,
486}
487
488// This must be implemented manually so we avoid a conflict with `TryFromPrimitive` where it treats
489// the `#[default]` attribute as its own `#[num_enum(default)]`
490impl Default for NamedChain {
491    #[inline]
492    fn default() -> Self {
493        Self::Mainnet
494    }
495}
496
497macro_rules! impl_into_numeric {
498    ($($t:ty)+) => {$(
499        impl From<NamedChain> for $t {
500            #[inline]
501            fn from(chain: NamedChain) -> Self {
502                chain as $t
503            }
504        }
505    )+};
506}
507
508impl_into_numeric!(u64 i64 u128 i128);
509#[cfg(target_pointer_width = "64")]
510impl_into_numeric!(usize isize);
511
512macro_rules! impl_try_from_numeric {
513    ($($native:ty)+) => {
514        $(
515            impl TryFrom<$native> for NamedChain {
516                type Error = TryFromPrimitiveError<NamedChain>;
517
518                #[inline]
519                fn try_from(value: $native) -> Result<Self, Self::Error> {
520                    (value as u64).try_into()
521                }
522            }
523        )+
524    };
525}
526
527impl_try_from_numeric!(u8 i8 u16 i16 u32 i32 usize isize);
528
529impl fmt::Display for NamedChain {
530    #[inline]
531    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
532        self.as_str().fmt(f)
533    }
534}
535
536impl AsRef<str> for NamedChain {
537    #[inline]
538    fn as_ref(&self) -> &str {
539        self.as_str()
540    }
541}
542
543impl PartialEq<u64> for NamedChain {
544    #[inline]
545    fn eq(&self, other: &u64) -> bool {
546        (*self as u64) == *other
547    }
548}
549
550impl PartialOrd<u64> for NamedChain {
551    #[inline]
552    fn partial_cmp(&self, other: &u64) -> Option<Ordering> {
553        (*self as u64).partial_cmp(other)
554    }
555}
556
557#[cfg(feature = "serde")]
558impl serde::Serialize for NamedChain {
559    #[inline]
560    fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
561        s.serialize_str(self.as_ref())
562    }
563}
564
565#[cfg(feature = "rlp")]
566impl alloy_rlp::Encodable for NamedChain {
567    #[inline]
568    fn encode(&self, out: &mut dyn alloy_rlp::BufMut) {
569        (*self as u64).encode(out)
570    }
571
572    #[inline]
573    fn length(&self) -> usize {
574        (*self as u64).length()
575    }
576}
577
578#[cfg(feature = "rlp")]
579impl alloy_rlp::Decodable for NamedChain {
580    #[inline]
581    fn decode(buf: &mut &[u8]) -> alloy_rlp::Result<Self> {
582        let n = u64::decode(buf)?;
583        Self::try_from(n).map_err(|_| alloy_rlp::Error::Overflow)
584    }
585}
586
587// NB: all utility functions *should* be explicitly exhaustive (not use `_` matcher) so we don't
588//     forget to update them when adding a new `NamedChain` variant.
589#[allow(clippy::match_like_matches_macro)]
590#[deny(unreachable_patterns, unused_variables)]
591impl NamedChain {
592    /// Returns the string representation of the chain.
593    #[inline]
594    pub fn as_str(&self) -> &'static str {
595        self.into()
596    }
597
598    /// Returns `true` if this chain is Ethereum or an Ethereum testnet.
599    pub const fn is_ethereum(&self) -> bool {
600        use NamedChain::*;
601
602        matches!(self, Mainnet | Morden | Ropsten | Rinkeby | Goerli | Kovan | Holesky | Sepolia)
603    }
604
605    /// Returns true if the chain contains Optimism configuration.
606    pub const fn is_optimism(self) -> bool {
607        use NamedChain::*;
608
609        matches!(
610            self,
611            Optimism
612                | OptimismGoerli
613                | OptimismKovan
614                | OptimismSepolia
615                | Base
616                | BaseGoerli
617                | BaseSepolia
618                | Fraxtal
619                | FraxtalTestnet
620                | Ink
621                | InkSepolia
622                | Mode
623                | ModeSepolia
624                | Pgn
625                | PgnSepolia
626                | Zora
627                | ZoraSepolia
628                | BlastSepolia
629                | OpBNBMainnet
630                | OpBNBTestnet
631                | Soneium
632                | SoneiumMinatoTestnet
633                | Odyssey
634                | World
635                | WorldSepolia
636                | Unichain
637                | UnichainSepolia
638                | HappychainTestnet
639        )
640    }
641
642    /// Returns true if the chain contains Arbitrum configuration.
643    pub const fn is_arbitrum(self) -> bool {
644        use NamedChain::*;
645
646        matches!(self, Arbitrum | ArbitrumTestnet | ArbitrumGoerli | ArbitrumSepolia | ArbitrumNova)
647    }
648
649    /// Returns the chain's average blocktime, if applicable.
650    ///
651    /// It can be beneficial to know the average blocktime to adjust the polling of an HTTP provider
652    /// for example.
653    ///
654    /// **Note:** this is not an accurate average, but is rather a sensible default derived from
655    /// blocktime charts such as [Etherscan's](https://etherscan.com/chart/blocktime)
656    /// or [Polygonscan's](https://polygonscan.com/chart/blocktime).
657    ///
658    /// # Examples
659    ///
660    /// ```
661    /// use alloy_chains::NamedChain;
662    /// use std::time::Duration;
663    ///
664    /// assert_eq!(NamedChain::Mainnet.average_blocktime_hint(), Some(Duration::from_millis(12_000)),);
665    /// assert_eq!(NamedChain::Optimism.average_blocktime_hint(), Some(Duration::from_millis(2_000)),);
666    /// ```
667    pub const fn average_blocktime_hint(self) -> Option<Duration> {
668        use NamedChain::*;
669
670        Some(Duration::from_millis(match self {
671            Mainnet | Taiko | TaikoHekla => 12_000,
672
673            Arbitrum
674            | ArbitrumTestnet
675            | ArbitrumGoerli
676            | ArbitrumSepolia
677            | GravityAlphaMainnet
678            | GravityAlphaTestnetSepolia
679            | Xai
680            | XaiSepolia
681            | Syndr
682            | SyndrSepolia
683            | ArbitrumNova
684            | ApeChain
685            | Curtis
686            | SuperpositionTestnet
687            | Superposition => 260,
688
689            Optimism | OptimismGoerli | OptimismSepolia | Base | BaseGoerli | BaseSepolia
690            | Blast | BlastSepolia | Fraxtal | FraxtalTestnet | Zora | ZoraSepolia | Mantle
691            | MantleSepolia | Mode | ModeSepolia | Pgn | PgnSepolia | HappychainTestnet
692            | Soneium | SoneiumMinatoTestnet | Bob | BobSepolia => 2_000,
693
694            Ink | InkSepolia | Odyssey => 1_000,
695
696            Viction => 2_000,
697
698            Polygon | PolygonMumbai | PolygonAmoy => 2_100,
699
700            Acala | AcalaMandalaTestnet | AcalaTestnet | Karura | KaruraTestnet | Moonbeam
701            | Moonriver => 12_500,
702
703            BinanceSmartChain | BinanceSmartChainTestnet => 3_000,
704
705            Avalanche | AvalancheFuji => 2_000,
706
707            Fantom | FantomTestnet => 1_200,
708
709            Cronos | CronosTestnet | Canto | CantoTestnet => 5_700,
710
711            Evmos | EvmosTestnet => 1_900,
712
713            Aurora | AuroraTestnet => 1_100,
714
715            Oasis => 5_500,
716
717            Emerald | Darwinia | Crab | Koi => 6_000,
718
719            Dev | AnvilHardhat => 200,
720
721            Celo | CeloAlfajores | CeloBaklava => 5_000,
722
723            FilecoinCalibrationTestnet | FilecoinMainnet => 30_000,
724
725            Scroll | ScrollSepolia => 3_000,
726
727            Shimmer => 5_000,
728
729            Gnosis | Chiado => 5_000,
730
731            Elastos => 5_000,
732
733            Etherlink => 5_000,
734
735            EtherlinkTestnet => 5_000,
736
737            Degen => 600,
738
739            Cfx | CfxTestnet => 500,
740
741            OpBNBMainnet | OpBNBTestnet | AutonomysNovaTestnet => 1_000,
742
743            Ronin | RoninTestnet => 3_000,
744
745            Flare => 1_800,
746
747            FlareCoston2 => 2_500,
748
749            Pulsechain => 10000,
750            PulsechainTestnet => 10101,
751
752            Immutable | ImmutableTestnet => 2_000,
753
754            World | WorldSepolia => 2_000,
755
756            Iotex => 5_000,
757            Core => 3_000,
758            Merlin => 3_000,
759            Bitlayer => 3_000,
760            Vana => 6_000,
761            Zeta => 6_000,
762            Kaia => 1_000,
763            Story => 2_500,
764            Sei => 500,
765
766            Sonic => 1_000,
767
768            TelosEvm | TelosEvmTestnet => 500,
769
770            UnichainSepolia | Unichain => 1_000,
771
772            BerachainBepolia | BerachainBartio | BerachainArtio | Berachain => 2_000,
773
774            MonadTestnet => 500,
775
776            Hyperliquid => 2_000,
777
778            Abstract => 1_000,
779
780            Morden | Ropsten | Rinkeby | Goerli | Kovan | Sepolia | Holesky | Hoodi
781            | MantleTestnet | Moonbase | MoonbeamDev | OptimismKovan | Poa | Sokol | Rsk
782            | EmeraldTestnet | Boba | ZkSync | ZkSyncTestnet | PolygonZkEvm
783            | PolygonZkEvmTestnet | Metis | Linea | LineaGoerli | LineaSepolia | KakarotSepolia
784            | SonicBlaze | SonicTestnet | Treasure | TreasureTopaz => return None,
785        }))
786    }
787
788    /// Returns whether the chain implements EIP-1559 (with the type 2 EIP-2718 transaction type).
789    ///
790    /// # Examples
791    ///
792    /// ```
793    /// use alloy_chains::NamedChain;
794    ///
795    /// assert!(!NamedChain::Mainnet.is_legacy());
796    /// assert!(NamedChain::Celo.is_legacy());
797    /// ```
798    pub const fn is_legacy(self) -> bool {
799        use NamedChain::*;
800
801        match self {
802            // Known legacy chains / non EIP-1559 compliant.
803            Acala
804            | AcalaMandalaTestnet
805            | AcalaTestnet
806            | ArbitrumTestnet
807            | BinanceSmartChain
808            | BinanceSmartChainTestnet
809            | Boba
810            | Celo
811            | CeloAlfajores
812            | CeloBaklava
813            | Elastos
814            | Emerald
815            | EmeraldTestnet
816            | Fantom
817            | FantomTestnet
818            | Karura
819            | KaruraTestnet
820            | MantleTestnet
821            | Metis
822            | Oasis
823            | OptimismKovan
824            | PolygonZkEvm
825            | PolygonZkEvmTestnet
826            | Ronin
827            | RoninTestnet
828            | Rsk
829            | Shimmer
830            | TelosEvm
831            | TelosEvmTestnet
832            | Treasure
833            | TreasureTopaz
834            | Viction
835            | ZkSync
836            | ZkSyncTestnet => true,
837
838            // Known EIP-1559 chains.
839            Mainnet
840            | Goerli
841            | Sepolia
842            | Holesky
843            | Hoodi
844            | Odyssey
845            | Base
846            | BaseGoerli
847            | BaseSepolia
848            | Blast
849            | BlastSepolia
850            | Fraxtal
851            | FraxtalTestnet
852            | Optimism
853            | OptimismGoerli
854            | OptimismSepolia
855            | Bob
856            | BobSepolia
857            | Polygon
858            | PolygonMumbai
859            | PolygonAmoy
860            | Avalanche
861            | AvalancheFuji
862            | Arbitrum
863            | ArbitrumGoerli
864            | ArbitrumSepolia
865            | ArbitrumNova
866            | GravityAlphaMainnet
867            | GravityAlphaTestnetSepolia
868            | Xai
869            | XaiSepolia
870            | HappychainTestnet
871            | Syndr
872            | SyndrSepolia
873            | FilecoinMainnet
874            | Linea
875            | LineaGoerli
876            | LineaSepolia
877            | FilecoinCalibrationTestnet
878            | Gnosis
879            | Chiado
880            | Zora
881            | ZoraSepolia
882            | Ink
883            | InkSepolia
884            | Mantle
885            | MantleSepolia
886            | Mode
887            | ModeSepolia
888            | Pgn
889            | PgnSepolia
890            | KakarotSepolia
891            | Etherlink
892            | EtherlinkTestnet
893            | Degen
894            | OpBNBMainnet
895            | OpBNBTestnet
896            | Taiko
897            | TaikoHekla
898            | AutonomysNovaTestnet
899            | Flare
900            | FlareCoston2
901            | Scroll
902            | ScrollSepolia
903            | Darwinia
904            | Cfx
905            | CfxTestnet
906            | Crab
907            | Pulsechain
908            | PulsechainTestnet
909            | Koi
910            | Immutable
911            | ImmutableTestnet
912            | Soneium
913            | SoneiumMinatoTestnet
914            | Sonic
915            | World
916            | WorldSepolia
917            | Unichain
918            | UnichainSepolia
919            | ApeChain
920            | BerachainBepolia
921            | BerachainBartio
922            | BerachainArtio
923            | Berachain
924            | Curtis
925            | SuperpositionTestnet
926            | Superposition
927            | MonadTestnet
928            | Hyperliquid
929            | Abstract => false,
930
931            // Unknown / not applicable, default to false for backwards compatibility.
932            Dev | AnvilHardhat | Morden | Ropsten | Rinkeby | Cronos | CronosTestnet | Kovan
933            | Sokol | Poa | Moonbeam | MoonbeamDev | Moonriver | Moonbase | Evmos
934            | EvmosTestnet | Aurora | AuroraTestnet | Canto | CantoTestnet | Iotex | Core
935            | Merlin | Bitlayer | SonicBlaze | SonicTestnet | Vana | Zeta | Kaia | Story | Sei => {
936                false
937            }
938        }
939    }
940
941    /// Returns whether the chain supports the [Shanghai hardfork][ref].
942    ///
943    /// [ref]: https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/shanghai.md
944    pub const fn supports_shanghai(self) -> bool {
945        use NamedChain::*;
946
947        matches!(
948            self,
949            Mainnet
950                | Goerli
951                | Sepolia
952                | Holesky
953                | Hoodi
954                | AnvilHardhat
955                | Optimism
956                | OptimismGoerli
957                | OptimismSepolia
958                | Bob
959                | BobSepolia
960                | Odyssey
961                | Base
962                | BaseGoerli
963                | BaseSepolia
964                | Blast
965                | BlastSepolia
966                | Fraxtal
967                | FraxtalTestnet
968                | Ink
969                | InkSepolia
970                | Gnosis
971                | Chiado
972                | ZoraSepolia
973                | Mantle
974                | MantleSepolia
975                | Mode
976                | ModeSepolia
977                | PolygonMumbai
978                | Polygon
979                | Arbitrum
980                | ArbitrumNova
981                | ArbitrumSepolia
982                | GravityAlphaMainnet
983                | GravityAlphaTestnetSepolia
984                | Xai
985                | XaiSepolia
986                | Syndr
987                | SyndrSepolia
988                | Etherlink
989                | EtherlinkTestnet
990                | Scroll
991                | ScrollSepolia
992                | HappychainTestnet
993                | Shimmer
994                | BinanceSmartChain
995                | BinanceSmartChainTestnet
996                | OpBNBMainnet
997                | OpBNBTestnet
998                | KakarotSepolia
999                | Taiko
1000                | TaikoHekla
1001                | Avalanche
1002                | AvalancheFuji
1003                | AutonomysNovaTestnet
1004                | Acala
1005                | AcalaMandalaTestnet
1006                | AcalaTestnet
1007                | Karura
1008                | KaruraTestnet
1009                | Darwinia
1010                | Crab
1011                | Cfx
1012                | CfxTestnet
1013                | Pulsechain
1014                | PulsechainTestnet
1015                | Koi
1016                | Immutable
1017                | ImmutableTestnet
1018                | Soneium
1019                | SoneiumMinatoTestnet
1020                | World
1021                | WorldSepolia
1022                | Iotex
1023                | Unichain
1024                | UnichainSepolia
1025                | ApeChain
1026                | Curtis
1027                | SuperpositionTestnet
1028                | Superposition
1029                | MonadTestnet
1030        )
1031    }
1032
1033    #[doc(hidden)]
1034    #[deprecated(since = "0.1.3", note = "use `supports_shanghai` instead")]
1035    pub const fn supports_push0(self) -> bool {
1036        self.supports_shanghai()
1037    }
1038
1039    /// Returns whether the chain is a testnet.
1040    pub const fn is_testnet(self) -> bool {
1041        use NamedChain::*;
1042
1043        match self {
1044            // Ethereum testnets.
1045            Goerli | Holesky | Kovan | Sepolia | Morden | Ropsten | Rinkeby | Hoodi => true,
1046
1047            // Other testnets.
1048            ArbitrumGoerli
1049            | ArbitrumSepolia
1050            | ArbitrumTestnet
1051            | SyndrSepolia
1052            | AuroraTestnet
1053            | AvalancheFuji
1054            | Odyssey
1055            | BaseGoerli
1056            | BaseSepolia
1057            | BlastSepolia
1058            | BinanceSmartChainTestnet
1059            | CantoTestnet
1060            | CronosTestnet
1061            | CeloAlfajores
1062            | CeloBaklava
1063            | EmeraldTestnet
1064            | EvmosTestnet
1065            | FantomTestnet
1066            | FilecoinCalibrationTestnet
1067            | FraxtalTestnet
1068            | HappychainTestnet
1069            | LineaGoerli
1070            | LineaSepolia
1071            | InkSepolia
1072            | MantleTestnet
1073            | MantleSepolia
1074            | MoonbeamDev
1075            | OptimismGoerli
1076            | OptimismKovan
1077            | OptimismSepolia
1078            | BobSepolia
1079            | PolygonMumbai
1080            | PolygonAmoy
1081            | PolygonZkEvmTestnet
1082            | ScrollSepolia
1083            | Shimmer
1084            | ZkSyncTestnet
1085            | ZoraSepolia
1086            | ModeSepolia
1087            | PgnSepolia
1088            | KakarotSepolia
1089            | EtherlinkTestnet
1090            | OpBNBTestnet
1091            | RoninTestnet
1092            | TaikoHekla
1093            | AutonomysNovaTestnet
1094            | FlareCoston2
1095            | AcalaMandalaTestnet
1096            | AcalaTestnet
1097            | KaruraTestnet
1098            | CfxTestnet
1099            | PulsechainTestnet
1100            | GravityAlphaTestnetSepolia
1101            | XaiSepolia
1102            | Koi
1103            | ImmutableTestnet
1104            | SoneiumMinatoTestnet
1105            | WorldSepolia
1106            | UnichainSepolia
1107            | Curtis
1108            | TreasureTopaz
1109            | SonicBlaze
1110            | SonicTestnet
1111            | BerachainBepolia
1112            | BerachainBartio
1113            | BerachainArtio
1114            | SuperpositionTestnet
1115            | MonadTestnet
1116            | TelosEvmTestnet => true,
1117
1118            // Dev chains.
1119            Dev | AnvilHardhat => true,
1120
1121            // Mainnets.
1122            Mainnet | Optimism | Arbitrum | ArbitrumNova | Blast | Syndr | Cronos | Rsk
1123            | BinanceSmartChain | Poa | Sokol | Scroll | Metis | Gnosis | Polygon
1124            | PolygonZkEvm | Fantom | Moonbeam | Moonriver | Moonbase | Evmos | Chiado | Oasis
1125            | Emerald | FilecoinMainnet | Avalanche | Celo | Aurora | Canto | Boba | Base
1126            | Fraxtal | Ink | Linea | ZkSync | Mantle | GravityAlphaMainnet | Xai | Zora | Pgn
1127            | Mode | Viction | Elastos | Degen | OpBNBMainnet | Ronin | Taiko | Flare | Acala
1128            | Karura | Darwinia | Cfx | Crab | Pulsechain | Etherlink | Immutable | World
1129            | Iotex | Core | Merlin | Bitlayer | ApeChain | Vana | Zeta | Kaia | Treasure | Bob
1130            | Soneium | Sonic | Superposition | Berachain | Unichain | TelosEvm | Story | Sei
1131            | Hyperliquid | Abstract => false,
1132        }
1133    }
1134
1135    /// Returns the symbol of the chain's native currency.
1136    pub const fn native_currency_symbol(self) -> Option<&'static str> {
1137        use NamedChain::*;
1138
1139        Some(match self {
1140            Mainnet | Goerli | Holesky | Kovan | Sepolia | Morden | Ropsten | Rinkeby | Scroll
1141            | ScrollSepolia | Taiko | TaikoHekla | Unichain | UnichainSepolia
1142            | SuperpositionTestnet | Superposition | Abstract => "ETH",
1143
1144            Mantle | MantleSepolia => "MNT",
1145
1146            GravityAlphaMainnet | GravityAlphaTestnetSepolia => "G",
1147
1148            Xai | XaiSepolia => "XAI",
1149
1150            HappychainTestnet => "HAPPY",
1151
1152            BinanceSmartChain | BinanceSmartChainTestnet | OpBNBMainnet | OpBNBTestnet => "BNB",
1153
1154            Etherlink | EtherlinkTestnet => "XTZ",
1155
1156            Degen => "DEGEN",
1157
1158            Ronin | RoninTestnet => "RON",
1159
1160            Shimmer => "SMR",
1161
1162            Flare => "FLR",
1163
1164            FlareCoston2 => "C2FLR",
1165
1166            Darwinia => "RING",
1167
1168            Crab => "CRAB",
1169
1170            Koi => "KRING",
1171
1172            Cfx | CfxTestnet => "CFX",
1173            Pulsechain | PulsechainTestnet => "PLS",
1174
1175            Immutable => "IMX",
1176            ImmutableTestnet => "tIMX",
1177
1178            World | WorldSepolia => "WRLD",
1179
1180            Iotex => "IOTX",
1181            Core => "CORE",
1182            Merlin => "BTC",
1183            Bitlayer => "BTC",
1184            Vana => "VANA",
1185            Zeta => "ZETA",
1186            Kaia => "KAIA",
1187            Story => "IP",
1188            Sei => "SEI",
1189            ApeChain | Curtis => "APE",
1190
1191            Treasure | TreasureTopaz => "MAGIC",
1192
1193            BerachainBepolia | BerachainBartio | BerachainArtio | Berachain => "BERA",
1194
1195            Sonic | SonicBlaze => "S",
1196
1197            TelosEvm | TelosEvmTestnet => "TLOS",
1198
1199            Hyperliquid => "HYPE",
1200
1201            Polygon | PolygonMumbai | PolygonZkEvm | PolygonZkEvmTestnet | PolygonAmoy => "POL",
1202
1203            _ => return None,
1204        })
1205    }
1206
1207    /// Returns the chain's blockchain explorer and its API (Etherscan and Etherscan-like) URLs.
1208    ///
1209    /// Returns `(API_URL, BASE_URL)`.
1210    ///
1211    /// All URLs have no trailing `/`
1212    ///
1213    /// # Examples
1214    ///
1215    /// ```
1216    /// use alloy_chains::NamedChain;
1217    ///
1218    /// assert_eq!(
1219    ///     NamedChain::Mainnet.etherscan_urls(),
1220    ///     Some(("https://api.etherscan.io/api", "https://etherscan.io"))
1221    /// );
1222    /// assert_eq!(
1223    ///     NamedChain::Avalanche.etherscan_urls(),
1224    ///     Some(("https://api.snowtrace.io/api", "https://snowtrace.io"))
1225    /// );
1226    /// assert_eq!(NamedChain::AnvilHardhat.etherscan_urls(), None);
1227    /// ```
1228    pub const fn etherscan_urls(self) -> Option<(&'static str, &'static str)> {
1229        use NamedChain::*;
1230
1231        Some(match self {
1232            Mainnet => ("https://api.etherscan.io/api", "https://etherscan.io"),
1233            Ropsten => ("https://api-ropsten.etherscan.io/api", "https://ropsten.etherscan.io"),
1234            Kovan => ("https://api-kovan.etherscan.io/api", "https://kovan.etherscan.io"),
1235            Rinkeby => ("https://api-rinkeby.etherscan.io/api", "https://rinkeby.etherscan.io"),
1236            Goerli => ("https://api-goerli.etherscan.io/api", "https://goerli.etherscan.io"),
1237            Sepolia => ("https://api-sepolia.etherscan.io/api", "https://sepolia.etherscan.io"),
1238            Holesky => ("https://api-holesky.etherscan.io/api", "https://holesky.etherscan.io"),
1239            Hoodi => ("https://api-hoodi.etherscan.io/api", "https://hoodi.etherscan.io"),
1240
1241            Polygon => ("https://api.polygonscan.com/api", "https://polygonscan.com"),
1242            PolygonMumbai => {
1243                ("https://api-testnet.polygonscan.com/api", "https://mumbai.polygonscan.com")
1244            }
1245            PolygonAmoy => ("https://api-amoy.polygonscan.com/api", "https://amoy.polygonscan.com"),
1246
1247            PolygonZkEvm => {
1248                ("https://api-zkevm.polygonscan.com/api", "https://zkevm.polygonscan.com")
1249            }
1250            PolygonZkEvmTestnet => (
1251                "https://api-testnet-zkevm.polygonscan.com/api",
1252                "https://testnet-zkevm.polygonscan.com",
1253            ),
1254
1255            Avalanche => ("https://api.snowtrace.io/api", "https://snowtrace.io"),
1256            AvalancheFuji => {
1257                ("https://api-testnet.snowtrace.io/api", "https://testnet.snowtrace.io")
1258            }
1259
1260            Optimism => {
1261                ("https://api-optimistic.etherscan.io/api", "https://optimistic.etherscan.io")
1262            }
1263            OptimismGoerli => (
1264                "https://api-goerli-optimistic.etherscan.io/api",
1265                "https://goerli-optimism.etherscan.io",
1266            ),
1267            OptimismKovan => (
1268                "https://api-kovan-optimistic.etherscan.io/api",
1269                "https://kovan-optimistic.etherscan.io",
1270            ),
1271            OptimismSepolia => (
1272                "https://api-sepolia-optimistic.etherscan.io/api",
1273                "https://sepolia-optimism.etherscan.io",
1274            ),
1275
1276            Bob => ("https://explorer.gobob.xyz/api", "https://explorer.gobob.xyz"),
1277            BobSepolia => (
1278                "https://bob-sepolia.explorer.gobob.xyz/api",
1279                "https://bob-sepolia.explorer.gobob.xyz",
1280            ),
1281
1282            Fantom => ("https://api.ftmscan.com/api", "https://ftmscan.com"),
1283            FantomTestnet => ("https://api-testnet.ftmscan.com/api", "https://testnet.ftmscan.com"),
1284
1285            BinanceSmartChain => ("https://api.bscscan.com/api", "https://bscscan.com"),
1286            BinanceSmartChainTestnet => {
1287                ("https://api-testnet.bscscan.com/api", "https://testnet.bscscan.com")
1288            }
1289
1290            OpBNBMainnet => ("https://opbnb.bscscan.com/api", "https://opbnb.bscscan.com"),
1291            OpBNBTestnet => {
1292                ("https://opbnb-testnet.bscscan.com/api", "https://opbnb-testnet.bscscan.com")
1293            }
1294
1295            Arbitrum => ("https://api.arbiscan.io/api", "https://arbiscan.io"),
1296            ArbitrumTestnet => {
1297                ("https://api-testnet.arbiscan.io/api", "https://testnet.arbiscan.io")
1298            }
1299            ArbitrumGoerli => ("https://api-goerli.arbiscan.io/api", "https://goerli.arbiscan.io"),
1300            ArbitrumSepolia => {
1301                ("https://api-sepolia.arbiscan.io/api", "https://sepolia.arbiscan.io")
1302            }
1303            ArbitrumNova => ("https://api-nova.arbiscan.io/api", "https://nova.arbiscan.io"),
1304
1305            GravityAlphaMainnet => {
1306                ("https://explorer.gravity.xyz/api", "https://explorer.gravity.xyz")
1307            }
1308            GravityAlphaTestnetSepolia => {
1309                ("https://explorer-sepolia.gravity.xyz/api", "https://explorer-sepolia.gravity.xyz")
1310            }
1311            HappychainTestnet => {
1312                ("https://explorer.testnet.happy.tech/api", "https://explorer.testnet.happy.tech")
1313            }
1314
1315            XaiSepolia => ("https://sepolia.xaiscan.io/api", "https://sepolia.xaiscan.io"),
1316            Xai => ("https://xaiscan.io/api", "https://xaiscan.io"),
1317
1318            Syndr => ("https://explorer.syndr.com/api", "https://explorer.syndr.com"),
1319            SyndrSepolia => {
1320                ("https://sepolia-explorer.syndr.com/api", "https://sepolia-explorer.syndr.com")
1321            }
1322
1323            Cronos => ("https://api.cronoscan.com/api", "https://cronoscan.com"),
1324            CronosTestnet => {
1325                ("https://api-testnet.cronoscan.com/api", "https://testnet.cronoscan.com")
1326            }
1327
1328            Moonbeam => ("https://api-moonbeam.moonscan.io/api", "https://moonbeam.moonscan.io"),
1329            Moonbase => ("https://api-moonbase.moonscan.io/api", "https://moonbase.moonscan.io"),
1330            Moonriver => ("https://api-moonriver.moonscan.io/api", "https://moonriver.moonscan.io"),
1331
1332            Gnosis => ("https://api.gnosisscan.io/api", "https://gnosisscan.io"),
1333
1334            Scroll => ("https://api.scrollscan.com/api", "https://scrollscan.com"),
1335            ScrollSepolia => {
1336                ("https://api-sepolia.scrollscan.com/api", "https://sepolia.scrollscan.com")
1337            }
1338
1339            Ink => ("https://explorer.inkonchain.com/api/v2", "https://explorer.inkonchain.com"),
1340            InkSepolia => (
1341                "https://explorer-sepolia.inkonchain.com/api/v2",
1342                "https://explorer-sepolia.inkonchain.com",
1343            ),
1344
1345            Shimmer => {
1346                ("https://explorer.evm.shimmer.network/api", "https://explorer.evm.shimmer.network")
1347            }
1348
1349            Metis => (
1350                "https://api.routescan.io/v2/network/mainnet/evm/1088/etherscan",
1351                "https://explorer.metis.io",
1352            ),
1353
1354            Chiado => {
1355                ("https://blockscout.chiadochain.net/api", "https://blockscout.chiadochain.net")
1356            }
1357
1358            FilecoinCalibrationTestnet => (
1359                "https://api.calibration.node.glif.io/rpc/v1",
1360                "https://calibration.filfox.info/en",
1361            ),
1362
1363            Sokol => ("https://blockscout.com/poa/sokol/api", "https://blockscout.com/poa/sokol"),
1364
1365            Poa => ("https://blockscout.com/poa/core/api", "https://blockscout.com/poa/core"),
1366
1367            Rsk => ("https://blockscout.com/rsk/mainnet/api", "https://blockscout.com/rsk/mainnet"),
1368
1369            Oasis => ("https://scan.oasischain.io/api", "https://scan.oasischain.io"),
1370
1371            Emerald => {
1372                ("https://explorer.emerald.oasis.dev/api", "https://explorer.emerald.oasis.dev")
1373            }
1374            EmeraldTestnet => (
1375                "https://testnet.explorer.emerald.oasis.dev/api",
1376                "https://testnet.explorer.emerald.oasis.dev",
1377            ),
1378
1379            Aurora => ("https://api.aurorascan.dev/api", "https://aurorascan.dev"),
1380            AuroraTestnet => {
1381                ("https://testnet.aurorascan.dev/api", "https://testnet.aurorascan.dev")
1382            }
1383
1384            Evmos => ("https://evm.evmos.org/api", "https://evm.evmos.org"),
1385            EvmosTestnet => ("https://evm.evmos.dev/api", "https://evm.evmos.dev"),
1386
1387            Celo => ("https://api.celoscan.io/api", "https://celoscan.io"),
1388            CeloAlfajores => {
1389                ("https://api-alfajores.celoscan.io/api", "https://alfajores.celoscan.io")
1390            }
1391            CeloBaklava => {
1392                ("https://explorer.celo.org/baklava/api", "https://explorer.celo.org/baklava")
1393            }
1394
1395            Canto => ("https://evm.explorer.canto.io/api", "https://evm.explorer.canto.io"),
1396            CantoTestnet => (
1397                "https://testnet-explorer.canto.neobase.one/api",
1398                "https://testnet-explorer.canto.neobase.one",
1399            ),
1400
1401            Boba => ("https://api.bobascan.com/api", "https://bobascan.com"),
1402
1403            Base => ("https://api.basescan.org/api", "https://basescan.org"),
1404            BaseGoerli => ("https://api-goerli.basescan.org/api", "https://goerli.basescan.org"),
1405            BaseSepolia => ("https://api-sepolia.basescan.org/api", "https://sepolia.basescan.org"),
1406
1407            Fraxtal => ("https://api.fraxscan.com/api", "https://fraxscan.com"),
1408            FraxtalTestnet => {
1409                ("https://api-holesky.fraxscan.com/api", "https://holesky.fraxscan.com")
1410            }
1411
1412            Blast => ("https://api.blastscan.io/api", "https://blastscan.io"),
1413            BlastSepolia => {
1414                ("https://api-sepolia.blastscan.io/api", "https://sepolia.blastscan.io")
1415            }
1416
1417            ZkSync => ("https://api-era.zksync.network/api", "https://era.zksync.network"),
1418            ZkSyncTestnet => {
1419                ("https://api-sepolia-era.zksync.network/api", "https://sepolia-era.zksync.network")
1420            }
1421
1422            Linea => ("https://api.lineascan.build/api", "https://lineascan.build"),
1423            LineaGoerli => {
1424                ("https://explorer.goerli.linea.build/api", "https://explorer.goerli.linea.build")
1425            }
1426            LineaSepolia => {
1427                ("https://api-sepolia.lineascan.build/api", "https://sepolia.lineascan.build")
1428            }
1429
1430            Mantle => ("https://explorer.mantle.xyz/api", "https://explorer.mantle.xyz"),
1431            MantleTestnet => {
1432                ("https://explorer.testnet.mantle.xyz/api", "https://explorer.testnet.mantle.xyz")
1433            }
1434            MantleSepolia => {
1435                ("https://explorer.sepolia.mantle.xyz/api", "https://explorer.sepolia.mantle.xyz")
1436            }
1437
1438            Viction => ("https://www.vicscan.xyz/api", "https://www.vicscan.xyz"),
1439
1440            Zora => ("https://explorer.zora.energy/api", "https://explorer.zora.energy"),
1441            ZoraSepolia => {
1442                ("https://sepolia.explorer.zora.energy/api", "https://sepolia.explorer.zora.energy")
1443            }
1444
1445            Pgn => {
1446                ("https://explorer.publicgoods.network/api", "https://explorer.publicgoods.network")
1447            }
1448
1449            PgnSepolia => (
1450                "https://explorer.sepolia.publicgoods.network/api",
1451                "https://explorer.sepolia.publicgoods.network",
1452            ),
1453
1454            Mode => ("https://explorer.mode.network/api", "https://explorer.mode.network"),
1455            ModeSepolia => (
1456                "https://sepolia.explorer.mode.network/api",
1457                "https://sepolia.explorer.mode.network",
1458            ),
1459
1460            Elastos => ("https://esc.elastos.io/api", "https://esc.elastos.io"),
1461            KakarotSepolia => {
1462                ("https://sepolia.kakarotscan.org/api", "https://sepolia.kakarotscan.org")
1463            }
1464            Etherlink => ("https://explorer.etherlink.com/api", "https://explorer.etherlink.com"),
1465            EtherlinkTestnet => (
1466                "https://testnet-explorer.etherlink.com/api",
1467                "https://testnet-explorer.etherlink.com",
1468            ),
1469            Degen => ("https://explorer.degen.tips/api", "https://explorer.degen.tips"),
1470            Ronin => ("https://skynet-api.roninchain.com/ronin", "https://app.roninchain.com"),
1471            RoninTestnet => (
1472                "https://api-gateway.skymavis.com/rpc/testnet",
1473                "https://saigon-app.roninchain.com",
1474            ),
1475            Taiko => ("https://api.taikoscan.io/api", "https://taikoscan.io"),
1476            TaikoHekla => ("https://api-testnet.taikoscan.io/api", "https://hekla.taikoscan.io"),
1477            Flare => {
1478                ("https://flare-explorer.flare.network/api", "https://flare-explorer.flare.network")
1479            }
1480            FlareCoston2 => (
1481                "https://coston2-explorer.flare.network/api",
1482                "https://coston2-explorer.flare.network",
1483            ),
1484            Acala => ("https://blockscout.acala.network/api", "https://blockscout.acala.network"),
1485            AcalaMandalaTestnet => (
1486                "https://blockscout.mandala.aca-staging.network/api",
1487                "https://blockscout.mandala.aca-staging.network",
1488            ),
1489            AcalaTestnet => (
1490                "https://blockscout.acala-testnet.aca-staging.network/api",
1491                "https://blockscout.acala-testnet.aca-staging.network",
1492            ),
1493            Karura => {
1494                ("https://blockscout.karura.network/api", "https://blockscout.karura.network")
1495            }
1496            KaruraTestnet => (
1497                "https://blockscout.karura-testnet.aca-staging.network/api",
1498                "https://blockscout.karura-testnet.aca-staging.network",
1499            ),
1500
1501            Darwinia => {
1502                ("https://explorer.darwinia.network/api", "https://explorer.darwinia.network")
1503            }
1504            Crab => {
1505                ("https://crab-scan.darwinia.network/api", "https://crab-scan.darwinia.network")
1506            }
1507            Koi => ("https://koi-scan.darwinia.network/api", "https://koi-scan.darwinia.network"),
1508            Cfx => ("https://evmapi.confluxscan.net/api", "https://evm.confluxscan.io"),
1509            CfxTestnet => {
1510                ("https://evmapi-testnet.confluxscan.net/api", "https://evmtestnet.confluxscan.io")
1511            }
1512            Pulsechain => ("https://api.scan.pulsechain.com", "https://scan.pulsechain.com"),
1513            PulsechainTestnet => (
1514                "https://api.scan.v4.testnet.pulsechain.com",
1515                "https://scan.v4.testnet.pulsechain.com",
1516            ),
1517
1518            Immutable => ("https://explorer.immutable.com/api", "https://explorer.immutable.com"),
1519            ImmutableTestnet => (
1520                "https://explorer.testnet.immutable.com/api",
1521                "https://explorer.testnet.immutable.com",
1522            ),
1523            Soneium => ("https://soneium.blockscout.com/api", "https://soneium.blockscout.com"),
1524            SoneiumMinatoTestnet => (
1525                "https://soneium-minato.blockscout.com/api",
1526                "https://soneium-minato.blockscout.com",
1527            ),
1528            Odyssey => {
1529                ("https://odyssey-explorer.ithaca.xyz/api", "https://odyssey-explorer.ithaca.xyz")
1530            }
1531            World => ("https://api.worldscan.org/api", "https://worldscan.org"),
1532            WorldSepolia => {
1533                ("https://api-sepolia.worldscan.org/api", "https://sepolia.worldscan.org")
1534            }
1535            Unichain => ("https://api.uniscan.xyz/api", "https://uniscan.xyz"),
1536            UnichainSepolia => {
1537                ("https://api-sepolia.uniscan.xyz/api", "https://sepolia.uniscan.xyz")
1538            }
1539            Core => ("https://openapi.coredao.org/api", "https://scan.coredao.org"),
1540            Merlin => ("https://scan.merlinchain.io/api", "https://scan.merlinchain.io"),
1541            Bitlayer => ("https://api.btrscan.com/scan/api", "https://www.btrscan.com"),
1542            Vana => ("https://api.vanascan.io/api", "https://vanascan.io"),
1543            Zeta => ("https://zetachain.blockscout.com/api", "https://zetachain.blockscout.com"),
1544            Kaia => ("https://mainnet-oapi.kaiascan.io/api", "https://kaiascan.io"),
1545            Story => ("https://www.storyscan.xyz/api/v2", "https://www.storyscan.xyz"),
1546
1547            ApeChain => ("https://api.apescan.io/api", "https://apescan.io"),
1548            Curtis => ("https://curtis.explorer.caldera.xyz/api/v2", "https://curtis.apescan.io"),
1549            SonicBlaze => {
1550                ("https://api-testnet.sonicscan.org/api", "https://testnet.sonicscan.org")
1551            }
1552            SonicTestnet => (
1553                "https://api.routescan.io/v2/network/testnet/evm/64165/etherscan/api",
1554                "https://scan.soniclabs.com",
1555            ),
1556            Sonic => ("https://api.sonicscan.org/api", "https://sonicscan.org"),
1557            Treasure => ("https://block-explorer.treasurescan.io/api", "https://treasurescan.io"),
1558            TreasureTopaz => (
1559                "https://block-explorer.topaz.treasurescan.io/api",
1560                "https://topaz.treasurescan.io",
1561            ),
1562            BerachainBepolia => {
1563                ("https://bepolia.beratrail.io/api", "https://bepolia.beratrail.io")
1564            }
1565            BerachainBartio => ("https://bartio.beratrail.io/api", "https://bartio.beratrail.io"),
1566            BerachainArtio => ("https://artio.beratrail.io/api", "https://artio.beratrail.io"),
1567            Berachain => ("https://api.berascan.com/api", "https://berascan.com"),
1568            SuperpositionTestnet => (
1569                "https://testnet-explorer.superposition.so/api",
1570                "https://testnet-explorer.superposition.so",
1571            ),
1572            Superposition => {
1573                ("https://explorer.superposition.so/api", "https://explorer.superposition.so")
1574            }
1575            MonadTestnet => ("https://sourcify.dev/server", "https://testnet.monadexplorer.com"),
1576            TelosEvm => ("https://api.teloscan.io/api", "https://teloscan.io"),
1577            TelosEvmTestnet => {
1578                ("https://api.testnet.teloscan.io/api", "https://testnet.teloscan.io")
1579            }
1580            Hyperliquid => (
1581                "https://hyperliquid.cloud.blockscout.com/api/v2",
1582                "https://hyperliquid.cloud.blockscout.com",
1583            ),
1584            Abstract => ("https://api.abscan.org/api", "https://abscan.org"),
1585            // TODO: add hoodi etherscan when live
1586            AnvilHardhat | Dev | Morden | MoonbeamDev | FilecoinMainnet | AutonomysNovaTestnet
1587            | Iotex | Sei => {
1588                return None;
1589            }
1590        })
1591    }
1592
1593    /// Returns the chain's blockchain explorer's API key environment variable's default name.
1594    ///
1595    /// # Examples
1596    ///
1597    /// ```
1598    /// use alloy_chains::NamedChain;
1599    ///
1600    /// assert_eq!(NamedChain::Mainnet.etherscan_api_key_name(), Some("ETHERSCAN_API_KEY"));
1601    /// assert_eq!(NamedChain::AnvilHardhat.etherscan_api_key_name(), None);
1602    /// ```
1603    pub const fn etherscan_api_key_name(self) -> Option<&'static str> {
1604        use NamedChain::*;
1605
1606        let api_key_name = match self {
1607            Mainnet
1608            | Morden
1609            | Ropsten
1610            | Kovan
1611            | Rinkeby
1612            | Goerli
1613            | Holesky
1614            | Hoodi
1615            | Optimism
1616            | OptimismGoerli
1617            | OptimismKovan
1618            | OptimismSepolia
1619            | BinanceSmartChain
1620            | BinanceSmartChainTestnet
1621            | OpBNBMainnet
1622            | OpBNBTestnet
1623            | Arbitrum
1624            | ArbitrumTestnet
1625            | ArbitrumGoerli
1626            | ArbitrumSepolia
1627            | ArbitrumNova
1628            | Syndr
1629            | SyndrSepolia
1630            | Cronos
1631            | CronosTestnet
1632            | Aurora
1633            | AuroraTestnet
1634            | Celo
1635            | CeloAlfajores
1636            | Base
1637            | Linea
1638            | LineaSepolia
1639            | Mantle
1640            | MantleTestnet
1641            | MantleSepolia
1642            | Xai
1643            | XaiSepolia
1644            | BaseGoerli
1645            | BaseSepolia
1646            | Fraxtal
1647            | FraxtalTestnet
1648            | Blast
1649            | BlastSepolia
1650            | Gnosis
1651            | Scroll
1652            | ScrollSepolia
1653            | Taiko
1654            | TaikoHekla
1655            | Unichain
1656            | UnichainSepolia
1657            | MonadTestnet
1658            | ApeChain
1659            | Abstract => "ETHERSCAN_API_KEY",
1660
1661            Avalanche | AvalancheFuji => "SNOWTRACE_API_KEY",
1662
1663            Polygon | PolygonMumbai | PolygonAmoy | PolygonZkEvm | PolygonZkEvmTestnet => {
1664                "POLYGONSCAN_API_KEY"
1665            }
1666
1667            Fantom | FantomTestnet => "FTMSCAN_API_KEY",
1668
1669            Moonbeam | Moonbase | MoonbeamDev | Moonriver => "MOONSCAN_API_KEY",
1670
1671            Acala | AcalaMandalaTestnet | AcalaTestnet | Canto | CantoTestnet | CeloBaklava
1672            | Etherlink | EtherlinkTestnet | Flare | FlareCoston2 | KakarotSepolia | Karura
1673            | KaruraTestnet | Mode | ModeSepolia | Pgn | PgnSepolia | Shimmer | Zora
1674            | ZoraSepolia | Darwinia | Crab | Koi | Immutable | ImmutableTestnet | Soneium
1675            | SoneiumMinatoTestnet | World | WorldSepolia | Curtis | Ink | InkSepolia
1676            | SuperpositionTestnet | Superposition | Vana | Story | Hyperliquid => {
1677                "BLOCKSCOUT_API_KEY"
1678            }
1679
1680            Boba => "BOBASCAN_API_KEY",
1681
1682            Core => "CORESCAN_API_KEY",
1683            Merlin => "MERLINSCAN_API_KEY",
1684            Bitlayer => "BITLAYERSCAN_API_KEY",
1685            Zeta => "ZETASCAN_API_KEY",
1686            Kaia => "KAIASCAN_API_KEY",
1687            Sonic => "SONICSCAN_API_KEY",
1688            Berachain => "BERASCAN_API_KEY",
1689            // Explicitly exhaustive. See NB above.
1690            Metis
1691            | Chiado
1692            | Odyssey
1693            | Sepolia
1694            | Rsk
1695            | Sokol
1696            | Poa
1697            | Oasis
1698            | Emerald
1699            | EmeraldTestnet
1700            | Evmos
1701            | EvmosTestnet
1702            | AnvilHardhat
1703            | Dev
1704            | GravityAlphaMainnet
1705            | GravityAlphaTestnetSepolia
1706            | Bob
1707            | BobSepolia
1708            | ZkSync
1709            | ZkSyncTestnet
1710            | FilecoinMainnet
1711            | LineaGoerli
1712            | FilecoinCalibrationTestnet
1713            | Viction
1714            | Elastos
1715            | Degen
1716            | Ronin
1717            | RoninTestnet
1718            | Cfx
1719            | CfxTestnet
1720            | Pulsechain
1721            | PulsechainTestnet
1722            | AutonomysNovaTestnet
1723            | Iotex
1724            | HappychainTestnet
1725            | SonicBlaze
1726            | SonicTestnet
1727            | Treasure
1728            | TreasureTopaz
1729            | BerachainBepolia
1730            | BerachainBartio
1731            | BerachainArtio
1732            | TelosEvm
1733            | TelosEvmTestnet
1734            | Sei => return None,
1735        };
1736
1737        Some(api_key_name)
1738    }
1739
1740    /// Returns the chain's blockchain explorer's API key, from the environment variable with the
1741    /// name specified in [`etherscan_api_key_name`](NamedChain::etherscan_api_key_name).
1742    ///
1743    /// # Examples
1744    ///
1745    /// ```
1746    /// use alloy_chains::NamedChain;
1747    ///
1748    /// let chain = NamedChain::Mainnet;
1749    /// std::env::set_var(chain.etherscan_api_key_name().unwrap(), "KEY");
1750    /// assert_eq!(chain.etherscan_api_key().as_deref(), Some("KEY"));
1751    /// ```
1752    #[cfg(feature = "std")]
1753    pub fn etherscan_api_key(self) -> Option<String> {
1754        self.etherscan_api_key_name().and_then(|name| std::env::var(name).ok())
1755    }
1756
1757    /// Returns the address of the public DNS node list for the given chain.
1758    ///
1759    /// See also <https://github.com/ethereum/discv4-dns-lists>.
1760    pub fn public_dns_network_protocol(self) -> Option<String> {
1761        use NamedChain::*;
1762
1763        const DNS_PREFIX: &str = "enrtree://AKA3AM6LPBYEUDMVNU3BSVQJ5AD45Y7YPOHJLEF6W26QOE4VTUDPE@";
1764        if let Mainnet | Goerli | Sepolia | Ropsten | Rinkeby | Holesky | Hoodi = self {
1765            // `{DNS_PREFIX}all.{self.lower()}.ethdisco.net`
1766            let mut s = String::with_capacity(DNS_PREFIX.len() + 32);
1767            s.push_str(DNS_PREFIX);
1768            s.push_str("all.");
1769            let chain_str = self.as_ref();
1770            s.push_str(chain_str);
1771            let l = s.len();
1772            s[l - chain_str.len()..].make_ascii_lowercase();
1773            s.push_str(".ethdisco.net");
1774
1775            Some(s)
1776        } else {
1777            None
1778        }
1779    }
1780
1781    /// Returns the address of the most popular wrapped native token address for this chain, if it
1782    /// exists.
1783    ///
1784    /// Example:
1785    ///
1786    /// ```
1787    /// use alloy_chains::NamedChain;
1788    /// use alloy_primitives::address;
1789    ///
1790    /// let chain = NamedChain::Mainnet;
1791    /// assert_eq!(
1792    ///     chain.wrapped_native_token(),
1793    ///     Some(address!("C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"))
1794    /// );
1795    /// ```
1796    pub const fn wrapped_native_token(self) -> Option<Address> {
1797        use NamedChain::*;
1798
1799        let addr = match self {
1800            Mainnet => address!("C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"),
1801            Optimism => address!("4200000000000000000000000000000000000006"),
1802            BinanceSmartChain => address!("bb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c"),
1803            OpBNBMainnet => address!("4200000000000000000000000000000000000006"),
1804            Arbitrum => address!("82af49447d8a07e3bd95bd0d56f35241523fbab1"),
1805            Base => address!("4200000000000000000000000000000000000006"),
1806            Linea => address!("e5d7c2a44ffddf6b295a15c148167daaaf5cf34f"),
1807            Mantle => address!("deaddeaddeaddeaddeaddeaddeaddeaddead1111"),
1808            Blast => address!("4300000000000000000000000000000000000004"),
1809            Gnosis => address!("e91d153e0b41518a2ce8dd3d7944fa863463a97d"),
1810            Scroll => address!("5300000000000000000000000000000000000004"),
1811            Taiko => address!("a51894664a773981c6c112c43ce576f315d5b1b6"),
1812            Avalanche => address!("b31f66aa3c1e785363f0875a1b74e27b85fd66c7"),
1813            Polygon => address!("0d500b1d8e8ef31e21c99d1db9a6444d3adf1270"),
1814            Fantom => address!("21be370d5312f44cb42ce377bc9b8a0cef1a4c83"),
1815            Iotex => address!("a00744882684c3e4747faefd68d283ea44099d03"),
1816            Core => address!("40375C92d9FAf44d2f9db9Bd9ba41a3317a2404f"),
1817            Merlin => address!("F6D226f9Dc15d9bB51182815b320D3fBE324e1bA"),
1818            Bitlayer => address!("ff204e2681a6fa0e2c3fade68a1b28fb90e4fc5f"),
1819            ApeChain => address!("48b62137EdfA95a428D35C09E44256a739F6B557"),
1820            Vana => address!("00EDdD9621Fb08436d0331c149D1690909a5906d"),
1821            Zeta => address!("5F0b1a82749cb4E2278EC87F8BF6B618dC71a8bf"),
1822            Kaia => address!("19aac5f612f524b754ca7e7c41cbfa2e981a4432"),
1823            Story => address!("1514000000000000000000000000000000000000"),
1824            Treasure => address!("263d8f36bb8d0d9526255e205868c26690b04b88"),
1825            Superposition => address!("1fB719f10b56d7a85DCD32f27f897375fB21cfdd"),
1826            Sonic => address!("039e2fB66102314Ce7b64Ce5Ce3E5183bc94aD38"),
1827            Berachain => address!("6969696969696969696969696969696969696969"),
1828            Hyperliquid => address!("5555555555555555555555555555555555555555"),
1829            Abstract => address!("3439153EB7AF838Ad19d56E1571FBD09333C2809"),
1830            Sei => address!("E30feDd158A2e3b13e9badaeABaFc5516e95e8C7"),
1831            _ => return None,
1832        };
1833
1834        Some(addr)
1835    }
1836}
1837
1838#[cfg(test)]
1839mod tests {
1840    use super::*;
1841    use strum::{EnumCount, IntoEnumIterator};
1842
1843    #[allow(unused_imports)]
1844    use alloc::string::ToString;
1845
1846    #[test]
1847    #[cfg(feature = "serde")]
1848    fn default() {
1849        assert_eq!(serde_json::to_string(&NamedChain::default()).unwrap(), "\"mainnet\"");
1850    }
1851
1852    #[test]
1853    fn enum_iter() {
1854        assert_eq!(NamedChain::COUNT, NamedChain::iter().size_hint().0);
1855    }
1856
1857    #[test]
1858    fn roundtrip_string() {
1859        for chain in NamedChain::iter() {
1860            let chain_string = chain.to_string();
1861            assert_eq!(chain_string, format!("{chain}"));
1862            assert_eq!(chain_string.as_str(), chain.as_ref());
1863            #[cfg(feature = "serde")]
1864            assert_eq!(serde_json::to_string(&chain).unwrap(), format!("\"{chain_string}\""));
1865
1866            assert_eq!(chain_string.parse::<NamedChain>().unwrap(), chain);
1867        }
1868    }
1869
1870    #[test]
1871    #[cfg(feature = "serde")]
1872    fn roundtrip_serde() {
1873        for chain in NamedChain::iter() {
1874            let chain_string = serde_json::to_string(&chain).unwrap();
1875            let chain_string = chain_string.replace('-', "_");
1876            assert_eq!(serde_json::from_str::<'_, NamedChain>(&chain_string).unwrap(), chain);
1877        }
1878    }
1879
1880    #[test]
1881    fn aliases() {
1882        use NamedChain::*;
1883
1884        // kebab-case
1885        const ALIASES: &[(NamedChain, &[&str])] = &[
1886            (Mainnet, &["ethlive"]),
1887            (BinanceSmartChain, &["bsc", "bnb-smart-chain", "binance-smart-chain"]),
1888            (
1889                BinanceSmartChainTestnet,
1890                &["bsc-testnet", "bnb-smart-chain-testnet", "binance-smart-chain-testnet"],
1891            ),
1892            (Gnosis, &["gnosis", "gnosis-chain"]),
1893            (PolygonMumbai, &["mumbai"]),
1894            (PolygonZkEvm, &["zkevm", "polygon-zkevm"]),
1895            (PolygonZkEvmTestnet, &["zkevm-testnet", "polygon-zkevm-testnet"]),
1896            (AnvilHardhat, &["anvil", "hardhat"]),
1897            (AvalancheFuji, &["fuji"]),
1898            (ZkSync, &["zksync"]),
1899            (Mantle, &["mantle"]),
1900            (MantleTestnet, &["mantle-testnet"]),
1901            (MantleSepolia, &["mantle-sepolia"]),
1902            (GravityAlphaMainnet, &["gravity-alpha-mainnet"]),
1903            (GravityAlphaTestnetSepolia, &["gravity-alpha-testnet-sepolia"]),
1904            (Bob, &["bob"]),
1905            (BobSepolia, &["bob-sepolia"]),
1906            (HappychainTestnet, &["happychain-testnet"]),
1907            (Xai, &["xai"]),
1908            (XaiSepolia, &["xai-sepolia"]),
1909            (Base, &["base"]),
1910            (BaseGoerli, &["base-goerli"]),
1911            (BaseSepolia, &["base-sepolia"]),
1912            (Fraxtal, &["fraxtal"]),
1913            (FraxtalTestnet, &["fraxtal-testnet"]),
1914            (Ink, &["ink"]),
1915            (InkSepolia, &["ink-sepolia"]),
1916            (BlastSepolia, &["blast-sepolia"]),
1917            (Syndr, &["syndr"]),
1918            (SyndrSepolia, &["syndr-sepolia"]),
1919            (LineaGoerli, &["linea-goerli"]),
1920            (LineaSepolia, &["linea-sepolia"]),
1921            (AutonomysNovaTestnet, &["autonomys-nova-testnet"]),
1922            (Immutable, &["immutable"]),
1923            (ImmutableTestnet, &["immutable-testnet"]),
1924            (Soneium, &["soneium"]),
1925            (SoneiumMinatoTestnet, &["soneium-minato-testnet"]),
1926            (ApeChain, &["apechain"]),
1927            (Curtis, &["apechain-testnet", "curtis"]),
1928            (Treasure, &["treasure"]),
1929            (TreasureTopaz, &["treasure-topaz-testnet", "treasure-topaz"]),
1930            (BerachainBepolia, &["berachain-bepolia-testnet", "berachain-bepolia"]),
1931            (BerachainArtio, &["berachain-artio-testnet", "berachain-artio"]),
1932            (BerachainBartio, &["berachain-bartio-testnet", "berachain-bartio"]),
1933            (SuperpositionTestnet, &["superposition-testnet"]),
1934            (Superposition, &["superposition"]),
1935            (Hyperliquid, &["hyperliquid"]),
1936            (Abstract, &["abstract"]),
1937        ];
1938
1939        for &(chain, aliases) in ALIASES {
1940            for &alias in aliases {
1941                let named = alias.parse::<NamedChain>().expect(alias);
1942                assert_eq!(named, chain);
1943
1944                #[cfg(feature = "serde")]
1945                {
1946                    assert_eq!(
1947                        serde_json::from_str::<NamedChain>(&format!("\"{alias}\"")).unwrap(),
1948                        chain
1949                    );
1950
1951                    assert_eq!(
1952                        serde_json::from_str::<NamedChain>(&format!("\"{named}\"")).unwrap(),
1953                        chain
1954                    );
1955                }
1956            }
1957        }
1958    }
1959
1960    #[test]
1961    #[cfg(feature = "serde")]
1962    fn serde_to_string_match() {
1963        for chain in NamedChain::iter() {
1964            let chain_serde = serde_json::to_string(&chain).unwrap();
1965            let chain_string = format!("\"{chain}\"");
1966            assert_eq!(chain_serde, chain_string);
1967        }
1968    }
1969
1970    #[test]
1971    fn test_dns_network() {
1972        let s = "enrtree://AKA3AM6LPBYEUDMVNU3BSVQJ5AD45Y7YPOHJLEF6W26QOE4VTUDPE@all.mainnet.ethdisco.net";
1973        assert_eq!(NamedChain::Mainnet.public_dns_network_protocol().unwrap(), s);
1974    }
1975
1976    #[test]
1977    fn ensure_no_trailing_etherscan_url_separator() {
1978        for chain in NamedChain::iter() {
1979            if let Some((api, base)) = chain.etherscan_urls() {
1980                assert!(!api.ends_with('/'), "{:?} api url has trailing /", chain);
1981                assert!(!base.ends_with('/'), "{:?} base url has trailing /", chain);
1982            }
1983        }
1984    }
1985}