1#![doc(
4 html_logo_url = "https://raw.githubusercontent.com/paradigmxyz/reth/main/assets/reth-docs.png",
5 html_favicon_url = "https://avatars0.githubusercontent.com/u/97369466?s=256",
6 issue_tracker_base_url = "https://github.com/paradigmxyz/reth/issues/"
7)]
8#![cfg_attr(not(test), warn(unused_crate_dependencies))]
9#![cfg_attr(docsrs, feature(doc_cfg))]
10#![cfg_attr(not(feature = "std"), no_std)]
11
12extern crate alloc;
13
14mod constants;
16pub use constants::*;
17
18mod api;
19mod info;
21mod spec;
23
24pub use alloy_chains::{Chain, ChainKind, NamedChain};
25pub use reth_ethereum_forks::*;
27
28pub use alloy_evm::EvmLimitParams;
29pub use api::EthChainSpec;
30pub use info::ChainInfo;
31#[cfg(any(test, feature = "test-utils"))]
32pub use spec::test_fork_ids;
33pub use spec::{
34 blob_params_to_schedule, create_chain_config, mainnet_chain_config, make_genesis_header,
35 BaseFeeParams, BaseFeeParamsKind, ChainSpec, ChainSpecBuilder, ChainSpecProvider,
36 DepositContract, ForkBaseFeeParams, DEV, HOLESKY, HOODI, MAINNET, SEPOLIA,
37};
38
39use reth_primitives_traits::sync::OnceLock;
40
41pub fn once_cell_set<T>(value: T) -> OnceLock<T> {
43 let once = OnceLock::new();
44 let _ = once.set(value);
45 once
46}
47
48#[cfg(test)]
49mod tests {
50 use super::*;
51 use alloy_primitives::U256;
52 use alloy_rlp::Encodable;
53 use std::str::FromStr;
54
55 #[test]
56 fn test_id() {
57 let chain = Chain::from(1234);
58 assert_eq!(chain.id(), 1234);
59 }
60
61 #[test]
62 fn test_named_id() {
63 let chain = Chain::from_named(NamedChain::Holesky);
64 assert_eq!(chain.id(), 17000);
65 }
66
67 #[test]
68 fn test_display_named_chain() {
69 let chain = Chain::from_named(NamedChain::Mainnet);
70 assert_eq!(format!("{chain}"), "mainnet");
71 }
72
73 #[test]
74 fn test_display_id_chain() {
75 let chain = Chain::from(1234);
76 assert_eq!(format!("{chain}"), "1234");
77 }
78
79 #[test]
80 fn test_from_u256() {
81 let n = U256::from(1234);
82 let chain = Chain::from(n.to::<u64>());
83 let expected = Chain::from(1234);
84
85 assert_eq!(chain, expected);
86 }
87
88 #[test]
89 fn test_into_u256() {
90 let chain = Chain::from_named(NamedChain::Holesky);
91 let n: U256 = U256::from(chain.id());
92 let expected = U256::from(17000);
93
94 assert_eq!(n, expected);
95 }
96
97 #[test]
98 fn test_from_str_named_chain() {
99 let result = Chain::from_str("mainnet");
100 let expected = Chain::from_named(NamedChain::Mainnet);
101
102 assert!(result.is_ok());
103 assert_eq!(result.unwrap(), expected);
104 }
105
106 #[test]
107 fn test_from_str_named_chain_error() {
108 let result = Chain::from_str("chain");
109
110 assert!(result.is_err());
111 }
112
113 #[test]
114 fn test_from_str_id_chain() {
115 let result = Chain::from_str("1234");
116 let expected = Chain::from(1234);
117
118 assert!(result.is_ok());
119 assert_eq!(result.unwrap(), expected);
120 }
121
122 #[test]
123 fn test_default() {
124 let default = Chain::default();
125 let expected = Chain::from_named(NamedChain::Mainnet);
126
127 assert_eq!(default, expected);
128 }
129
130 #[test]
131 fn test_id_chain_encodable_length() {
132 let chain = Chain::from(1234);
133
134 assert_eq!(chain.length(), 3);
135 }
136
137 #[test]
138 fn test_dns_main_network() {
139 let s = "enrtree://AKA3AM6LPBYEUDMVNU3BSVQJ5AD45Y7YPOHJLEF6W26QOE4VTUDPE@all.mainnet.ethdisco.net";
140 let chain: Chain = NamedChain::Mainnet.into();
141 assert_eq!(s, chain.public_dns_network_protocol().unwrap().as_str());
142 }
143
144 #[test]
145 fn test_dns_holesky_network() {
146 let s = "enrtree://AKA3AM6LPBYEUDMVNU3BSVQJ5AD45Y7YPOHJLEF6W26QOE4VTUDPE@all.holesky.ethdisco.net";
147 let chain: Chain = NamedChain::Holesky.into();
148 assert_eq!(s, chain.public_dns_network_protocol().unwrap().as_str());
149 }
150
151 #[test]
152 fn test_centralized_base_fee_calculation() {
153 use crate::{ChainSpec, EthChainSpec};
154 use alloy_consensus::Header;
155 use alloy_eips::eip1559::INITIAL_BASE_FEE;
156
157 fn parent_header() -> Header {
158 Header {
159 gas_used: 15_000_000,
160 gas_limit: 30_000_000,
161 base_fee_per_gas: Some(INITIAL_BASE_FEE),
162 timestamp: 1_000,
163 ..Default::default()
164 }
165 }
166
167 let spec = ChainSpec::default();
168 let parent = parent_header();
169
170 let next_timestamp = parent.timestamp + 12;
172
173 let expected = parent
174 .next_block_base_fee(spec.base_fee_params_at_timestamp(next_timestamp))
175 .unwrap_or_default();
176
177 let got = spec.next_block_base_fee(&parent, next_timestamp).unwrap_or_default();
178 assert_eq!(expected, got, "Base fee calculation does not match expected value");
179 }
180}