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