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 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
39#[cfg(test)]
40mod tests {
41    use super::*;
42    use alloy_primitives::U256;
43    use alloy_rlp::Encodable;
44    use std::str::FromStr;
45
46    #[test]
47    fn test_id() {
48        let chain = Chain::from(1234);
49        assert_eq!(chain.id(), 1234);
50    }
51
52    #[test]
53    fn test_named_id() {
54        let chain = Chain::from_named(NamedChain::Holesky);
55        assert_eq!(chain.id(), 17000);
56    }
57
58    #[test]
59    fn test_display_named_chain() {
60        let chain = Chain::from_named(NamedChain::Mainnet);
61        assert_eq!(format!("{chain}"), "mainnet");
62    }
63
64    #[test]
65    fn test_display_id_chain() {
66        let chain = Chain::from(1234);
67        assert_eq!(format!("{chain}"), "1234");
68    }
69
70    #[test]
71    fn test_from_u256() {
72        let n = U256::from(1234);
73        let chain = Chain::from(n.to::<u64>());
74        let expected = Chain::from(1234);
75
76        assert_eq!(chain, expected);
77    }
78
79    #[test]
80    fn test_into_u256() {
81        let chain = Chain::from_named(NamedChain::Holesky);
82        let n: U256 = U256::from(chain.id());
83        let expected = U256::from(17000);
84
85        assert_eq!(n, expected);
86    }
87
88    #[test]
89    fn test_from_str_named_chain() {
90        let result = Chain::from_str("mainnet");
91        let expected = Chain::from_named(NamedChain::Mainnet);
92
93        assert!(result.is_ok());
94        assert_eq!(result.unwrap(), expected);
95    }
96
97    #[test]
98    fn test_from_str_named_chain_error() {
99        let result = Chain::from_str("chain");
100
101        assert!(result.is_err());
102    }
103
104    #[test]
105    fn test_from_str_id_chain() {
106        let result = Chain::from_str("1234");
107        let expected = Chain::from(1234);
108
109        assert!(result.is_ok());
110        assert_eq!(result.unwrap(), expected);
111    }
112
113    #[test]
114    fn test_default() {
115        let default = Chain::default();
116        let expected = Chain::from_named(NamedChain::Mainnet);
117
118        assert_eq!(default, expected);
119    }
120
121    #[test]
122    fn test_id_chain_encodable_length() {
123        let chain = Chain::from(1234);
124
125        assert_eq!(chain.length(), 3);
126    }
127
128    #[test]
129    fn test_dns_main_network() {
130        let s = "enrtree://AKA3AM6LPBYEUDMVNU3BSVQJ5AD45Y7YPOHJLEF6W26QOE4VTUDPE@all.mainnet.ethdisco.net";
131        let chain: Chain = NamedChain::Mainnet.into();
132        assert_eq!(s, chain.public_dns_network_protocol().unwrap().as_str());
133    }
134
135    #[test]
136    fn test_dns_holesky_network() {
137        let s = "enrtree://AKA3AM6LPBYEUDMVNU3BSVQJ5AD45Y7YPOHJLEF6W26QOE4VTUDPE@all.holesky.ethdisco.net";
138        let chain: Chain = NamedChain::Holesky.into();
139        assert_eq!(s, chain.public_dns_network_protocol().unwrap().as_str());
140    }
141
142    #[test]
143    fn test_centralized_base_fee_calculation() {
144        use crate::{ChainSpec, EthChainSpec};
145        use alloy_consensus::Header;
146        use alloy_eips::eip1559::INITIAL_BASE_FEE;
147
148        fn parent_header() -> Header {
149            Header {
150                gas_used: 15_000_000,
151                gas_limit: 30_000_000,
152                base_fee_per_gas: Some(INITIAL_BASE_FEE),
153                timestamp: 1_000,
154                ..Default::default()
155            }
156        }
157
158        let spec = ChainSpec::default();
159        let parent = parent_header();
160
161        // For testing, assume next block has timestamp 12 seconds later
162        let next_timestamp = parent.timestamp + 12;
163
164        let expected = parent
165            .next_block_base_fee(spec.base_fee_params_at_timestamp(next_timestamp))
166            .unwrap_or_default();
167
168        let got = spec.next_block_base_fee(&parent, next_timestamp).unwrap_or_default();
169        assert_eq!(expected, got, "Base fee calculation does not match expected value");
170    }
171}