1use revm::primitives::{
23 eip4844::{BLOB_BASE_FEE_UPDATE_FRACTION_CANCUN, BLOB_BASE_FEE_UPDATE_FRACTION_PRAGUE},
24 hardfork::SpecId,
25};
26use std::collections::BTreeMap;
27use std::sync::LazyLock;
28
29static MAINNET_HARDFORKS: LazyLock<BTreeMap<u64, SpecId>> = LazyLock::new(|| {
32 [
33 (0, SpecId::FRONTIER),
34 (1_150_000, SpecId::HOMESTEAD),
35 (2_463_000, SpecId::TANGERINE),
36 (2_675_000, SpecId::SPURIOUS_DRAGON),
37 (4_370_000, SpecId::BYZANTIUM),
38 (7_280_000, SpecId::PETERSBURG),
41 (9_069_000, SpecId::ISTANBUL),
42 (12_244_000, SpecId::BERLIN),
43 (12_965_000, SpecId::LONDON),
44 (13_773_000, SpecId::ARROW_GLACIER),
45 (15_050_000, SpecId::GRAY_GLACIER),
46 (15_537_394, SpecId::MERGE),
47 (17_034_870, SpecId::SHANGHAI),
48 (19_426_589, SpecId::CANCUN),
49 (22_431_084, SpecId::PRAGUE),
51 ]
52 .into_iter()
53 .collect()
54});
55
56pub fn get_mainnet_spec_id(block_number: u64) -> SpecId {
63 MAINNET_HARDFORKS
65 .range(..=block_number)
66 .last()
67 .map(|(_, spec_id)| *spec_id)
68 .unwrap_or(SpecId::FRONTIER)
69}
70
71pub fn get_hardfork_info(spec_id: SpecId) -> (&'static str, u64) {
73 match spec_id {
74 SpecId::FRONTIER => ("Frontier", 0),
75 SpecId::HOMESTEAD => ("Homestead", 1_150_000),
76 SpecId::TANGERINE => ("Tangerine Whistle", 2_463_000),
77 SpecId::SPURIOUS_DRAGON => ("Spurious Dragon", 2_675_000),
78 SpecId::BYZANTIUM => ("Byzantium", 4_370_000),
79 SpecId::CONSTANTINOPLE => ("Constantinople", 7_280_000), SpecId::PETERSBURG => ("Petersburg", 7_280_000),
81 SpecId::ISTANBUL => ("Istanbul", 9_069_000),
82 SpecId::BERLIN => ("Berlin", 12_244_000),
83 SpecId::LONDON => ("London", 12_965_000),
84 SpecId::ARROW_GLACIER => ("Arrow Glacier", 13_773_000),
85 SpecId::GRAY_GLACIER => ("Gray Glacier", 15_050_000),
86 SpecId::MERGE => ("The Merge", 15_537_394),
87 SpecId::SHANGHAI => ("Shanghai", 17_034_870),
88 SpecId::CANCUN => ("Cancun", 19_426_589),
89 SpecId::PRAGUE => ("Prague (Pectra EL)", 22_431_084),
90 _ => ("Unknown", 0),
91 }
92}
93
94pub fn get_blob_base_fee_update_fraction_by_spec_id(spec: SpecId) -> u64 {
96 if spec >= SpecId::PRAGUE {
97 BLOB_BASE_FEE_UPDATE_FRACTION_PRAGUE
98 } else {
99 BLOB_BASE_FEE_UPDATE_FRACTION_CANCUN
100 }
101}
102
103#[cfg(test)]
104mod tests {
105 use super::*;
106
107 #[test]
108 fn test_mainnet_spec_id() {
109 assert_eq!(get_mainnet_spec_id(0), SpecId::FRONTIER);
111 assert_eq!(get_mainnet_spec_id(1), SpecId::FRONTIER);
112
113 assert_eq!(get_mainnet_spec_id(1_149_999), SpecId::FRONTIER);
115 assert_eq!(get_mainnet_spec_id(1_150_000), SpecId::HOMESTEAD);
116 assert_eq!(get_mainnet_spec_id(1_150_001), SpecId::HOMESTEAD);
117
118 assert_eq!(get_mainnet_spec_id(7_279_999), SpecId::BYZANTIUM);
120 assert_eq!(get_mainnet_spec_id(7_280_000), SpecId::PETERSBURG); assert_eq!(get_mainnet_spec_id(7_280_001), SpecId::PETERSBURG);
122
123 assert_eq!(get_mainnet_spec_id(15_537_394), SpecId::MERGE);
125 assert_eq!(get_mainnet_spec_id(17_034_870), SpecId::SHANGHAI);
126 assert_eq!(get_mainnet_spec_id(19_426_589), SpecId::CANCUN);
127
128 assert_eq!(get_mainnet_spec_id(20_000_000), SpecId::CANCUN);
130 assert_eq!(get_mainnet_spec_id(u64::MAX), SpecId::CANCUN);
131 }
132}