superchain_primitives/
superchain.rs1use alloc::{string::String, vec::Vec};
4use alloy_primitives::Address;
5
6use crate::ChainConfig;
7use crate::HardForkConfiguration;
8
9#[derive(Debug, Clone, Default, Hash, Eq, PartialEq)]
11#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
12#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
13pub struct Superchain {
14 pub name: String,
16 pub config: SuperchainConfig,
18 pub chains: Vec<ChainConfig>,
20}
21
22#[derive(Debug, Clone, Default, Hash, Eq, PartialEq)]
24#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
25#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
26#[cfg_attr(feature = "serde", serde(rename_all = "PascalCase"))]
27pub struct SuperchainConfig {
28 pub name: String,
30 pub l1: SuperchainL1Info,
32 pub protocol_versions_addr: Option<Address>,
34 pub superchain_config_addr: Option<Address>,
36 #[cfg_attr(feature = "serde", serde(flatten))]
38 pub hardfork_defaults: HardForkConfiguration,
39}
40
41#[derive(Debug, Clone, Default, Hash, Eq, PartialEq)]
43#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
44#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
45#[cfg_attr(feature = "serde", serde(rename_all = "PascalCase"))]
46pub struct SuperchainL1Info {
47 #[cfg_attr(feature = "serde", serde(rename = "ChainID"))]
49 pub chain_id: u64,
50 #[cfg_attr(feature = "serde", serde(rename = "PublicRPC"))]
52 pub public_rpc: String,
53 pub explorer: String,
55}
56
57#[derive(Debug, Clone, Default, Hash, Eq, PartialEq)]
59#[cfg_attr(
60 feature = "serde",
61 derive(serde_repr::Serialize_repr, serde_repr::Deserialize_repr)
62)]
63#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
64#[repr(u8)]
65pub enum SuperchainLevel {
66 Frontier = 0,
69 #[default]
72 Standard = 1,
73}
74
75#[cfg(test)]
76mod tests {
77 use super::*;
78 use alloy_primitives::address;
79
80 fn ref_config() -> SuperchainConfig {
81 SuperchainConfig {
82 name: "Mainnet".to_string(),
83 l1: SuperchainL1Info {
84 chain_id: 1,
85 public_rpc: "https://ethereum-rpc.publicnode.com".to_string(),
86 explorer: "https://etherscan.io".to_string(),
87 },
88 protocol_versions_addr: Some(address!("8062AbC286f5e7D9428a0Ccb9AbD71e50d93b935")),
89 superchain_config_addr: Some(address!("95703e0982140D16f8ebA6d158FccEde42f04a4C")),
90 hardfork_defaults: HardForkConfiguration::default(),
91 }
92 }
93
94 #[test]
95 fn test_superchain_l1_info_serde() {
96 let l1_str = r#"{
97 "ChainID": 1,
98 "PublicRPC": "https://ethereum-rpc.publicnode.com",
99 "Explorer": "https://etherscan.io"
100 }"#;
101 let l1: SuperchainL1Info = serde_json::from_str(l1_str).unwrap();
102 assert_eq!(
103 l1,
104 SuperchainL1Info {
105 chain_id: 1,
106 public_rpc: "https://ethereum-rpc.publicnode.com".to_string(),
107 explorer: "https://etherscan.io".to_string(),
108 }
109 );
110 }
111
112 #[test]
113 fn test_superchain_config_serde() {
114 let cfg_str = r#"{
115 "Name": "Mainnet",
116 "L1": {
117 "ChainID": 1,
118 "PublicRPC": "https://ethereum-rpc.publicnode.com",
119 "Explorer": "https://etherscan.io"
120 },
121 "ProtocolVersionsAddr": "0x8062AbC286f5e7D9428a0Ccb9AbD71e50d93b935",
122 "SuperchainConfigAddr": "0x95703e0982140D16f8ebA6d158FccEde42f04a4C"
123 }"#;
124 let cfg: SuperchainConfig = serde_json::from_str(cfg_str).unwrap();
125 assert_eq!(cfg, ref_config());
126 }
127
128 #[test]
129 fn test_superchain_serde() {
130 let superchain_str = r#"{
131 "name": "Mainnet",
132 "config": {
133 "Name": "Mainnet",
134 "L1": {
135 "ChainID": 1,
136 "PublicRPC": "https://ethereum-rpc.publicnode.com",
137 "Explorer": "https://etherscan.io"
138 },
139 "ProtocolVersionsAddr": "0x8062AbC286f5e7D9428a0Ccb9AbD71e50d93b935",
140 "SuperchainConfigAddr": "0x95703e0982140D16f8ebA6d158FccEde42f04a4C"
141 },
142 "chains": []
143 }"#;
144 let superchain: Superchain = serde_json::from_str(superchain_str).unwrap();
145 assert_eq!(superchain.name, "Mainnet");
146 assert_eq!(superchain.config, ref_config());
147 assert!(superchain.chains.is_empty());
148 }
149}