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