Skip to main content

reth_chainspec/
lib.rs

1//! The spec of an Ethereum network
2
3#![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
14/// Chain specific constants
15mod constants;
16pub use constants::*;
17
18mod api;
19/// The chain info module.
20mod info;
21/// The chain spec module.
22mod spec;
23
24pub use alloy_chains::{Chain, ChainKind, NamedChain};
25/// Re-export for convenience
26pub use reth_ethereum_forks::*;
27
28pub use api::EthChainSpec;
29pub use info::ChainInfo;
30#[cfg(any(test, feature = "test-utils"))]
31pub use spec::test_fork_ids;
32pub use spec::{
33    blob_params_to_schedule, create_chain_config, mainnet_chain_config, make_genesis_header,
34    BaseFeeParams, BaseFeeParamsKind, ChainSpec, ChainSpecBuilder, ChainSpecProvider,
35    DepositContract, ForkBaseFeeParams, DEV, HOLESKY, HOODI, MAINNET, SEPOLIA,
36};
37
38#[cfg(test)]
39mod tests {
40    use super::*;
41    use crate::{ChainSpec, EthChainSpec};
42    use alloy_consensus::Header;
43    use alloy_eips::eip1559::INITIAL_BASE_FEE;
44    use alloy_primitives::U256;
45    use alloy_rlp::Encodable;
46    use std::str::FromStr;
47
48    #[test]
49    fn test_id() {
50        let chain = Chain::from(1234);
51        assert_eq!(chain.id(), 1234);
52    }
53
54    #[test]
55    fn test_named_id() {
56        let chain = Chain::holesky();
57        assert_eq!(chain.id(), 17000);
58    }
59
60    #[test]
61    fn test_display_named_chain() {
62        let chain = Chain::mainnet();
63        assert_eq!(format!("{chain}"), "mainnet");
64    }
65
66    #[test]
67    fn test_display_id_chain() {
68        let chain = Chain::from(1234);
69        assert_eq!(format!("{chain}"), "1234");
70    }
71
72    #[test]
73    fn test_from_u256() {
74        let n = U256::from(1234);
75        let chain = Chain::from(n.to::<u64>());
76        let expected = Chain::from(1234);
77
78        assert_eq!(chain, expected);
79    }
80
81    #[test]
82    fn test_into_u256() {
83        let chain = Chain::holesky();
84        let n: U256 = U256::from(chain.id());
85        let expected = U256::from(17000);
86
87        assert_eq!(n, expected);
88    }
89
90    #[test]
91    fn test_from_str_named_chain() {
92        let result = Chain::from_str("mainnet");
93        let expected = Chain::mainnet();
94
95        assert!(result.is_ok());
96        assert_eq!(result.unwrap(), expected);
97    }
98
99    #[test]
100    fn test_from_str_named_chain_error() {
101        let result = Chain::from_str("chain");
102
103        assert!(result.is_err());
104    }
105
106    #[test]
107    fn test_from_str_id_chain() {
108        let result = Chain::from_str("1234");
109        let expected = Chain::from(1234);
110
111        assert!(result.is_ok());
112        assert_eq!(result.unwrap(), expected);
113    }
114
115    #[test]
116    fn test_default() {
117        let default = Chain::default();
118        let expected = Chain::mainnet();
119
120        assert_eq!(default, expected);
121    }
122
123    #[test]
124    fn test_id_chain_encodable_length() {
125        let chain = Chain::from(1234);
126
127        assert_eq!(chain.length(), 3);
128    }
129
130    #[test]
131    fn test_dns_main_network() {
132        let s = "enrtree://AKA3AM6LPBYEUDMVNU3BSVQJ5AD45Y7YPOHJLEF6W26QOE4VTUDPE@all.mainnet.ethdisco.net";
133        let chain = Chain::mainnet();
134        assert_eq!(s, chain.public_dns_network_protocol().unwrap().as_str());
135    }
136
137    #[test]
138    fn test_dns_holesky_network() {
139        let s = "enrtree://AKA3AM6LPBYEUDMVNU3BSVQJ5AD45Y7YPOHJLEF6W26QOE4VTUDPE@all.holesky.ethdisco.net";
140        let chain = Chain::holesky();
141        assert_eq!(s, chain.public_dns_network_protocol().unwrap().as_str());
142    }
143
144    #[test]
145    fn test_centralized_base_fee_calculation() {
146        fn parent_header() -> Header {
147            Header {
148                gas_used: 15_000_000,
149                gas_limit: 30_000_000,
150                base_fee_per_gas: Some(INITIAL_BASE_FEE),
151                timestamp: 1_000,
152                ..Default::default()
153            }
154        }
155
156        let spec = ChainSpec::default();
157        let parent = parent_header();
158
159        // For testing, assume next block has timestamp 12 seconds later
160        let next_timestamp = parent.timestamp + 12;
161
162        let expected = parent
163            .next_block_base_fee(spec.base_fee_params_at_timestamp(next_timestamp))
164            .unwrap_or_default();
165
166        let got = spec.next_block_base_fee(&parent, next_timestamp).unwrap_or_default();
167        assert_eq!(expected, got, "Base fee calculation does not match expected value");
168    }
169}