revm_primitives/
specification.rs

1#![allow(non_camel_case_types)]
2
3pub use SpecId::*;
4
5/// Specification IDs and their activation block.
6///
7/// Information was obtained from the [Ethereum Execution Specifications](https://github.com/ethereum/execution-specs)
8#[cfg(not(feature = "optimism"))]
9#[repr(u8)]
10#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, enumn::N)]
11#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
12pub enum SpecId {
13    FRONTIER = 0,         // Frontier               0
14    FRONTIER_THAWING = 1, // Frontier Thawing       200000
15    HOMESTEAD = 2,        // Homestead              1150000
16    DAO_FORK = 3,         // DAO Fork               1920000
17    TANGERINE = 4,        // Tangerine Whistle      2463000
18    SPURIOUS_DRAGON = 5,  // Spurious Dragon        2675000
19    BYZANTIUM = 6,        // Byzantium              4370000
20    CONSTANTINOPLE = 7,   // Constantinople         7280000 is overwritten with PETERSBURG
21    PETERSBURG = 8,       // Petersburg             7280000
22    ISTANBUL = 9,         // Istanbul	            9069000
23    MUIR_GLACIER = 10,    // Muir Glacier           9200000
24    BERLIN = 11,          // Berlin	                12244000
25    LONDON = 12,          // London	                12965000
26    ARROW_GLACIER = 13,   // Arrow Glacier          13773000
27    GRAY_GLACIER = 14,    // Gray Glacier           15050000
28    MERGE = 15,           // Paris/Merge            15537394 (TTD: 58750000000000000000000)
29    SHANGHAI = 16,        // Shanghai               17034870 (Timestamp: 1681338455)
30    CANCUN = 17,          // Cancun                 19426587 (Timestamp: 1710338135)
31    PRAGUE = 18,          // Prague                 TBD
32    OSAKA = 19,           // Prague+EOF             TBD
33    #[default]
34    LATEST = u8::MAX,
35}
36
37/// Specification IDs and their activation block.
38///
39/// Information was obtained from the [Ethereum Execution Specifications](https://github.com/ethereum/execution-specs)
40#[cfg(feature = "optimism")]
41#[repr(u8)]
42#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, enumn::N)]
43#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
44pub enum SpecId {
45    FRONTIER = 0,
46    FRONTIER_THAWING = 1,
47    HOMESTEAD = 2,
48    DAO_FORK = 3,
49    TANGERINE = 4,
50    SPURIOUS_DRAGON = 5,
51    BYZANTIUM = 6,
52    CONSTANTINOPLE = 7,
53    PETERSBURG = 8,
54    ISTANBUL = 9,
55    MUIR_GLACIER = 10,
56    BERLIN = 11,
57    LONDON = 12,
58    ARROW_GLACIER = 13,
59    GRAY_GLACIER = 14,
60    MERGE = 15,
61    BEDROCK = 16,
62    REGOLITH = 17,
63    SHANGHAI = 18,
64    CANYON = 19,
65    CANCUN = 20,
66    ECOTONE = 21,
67    FJORD = 22,
68    GRANITE = 23,
69    HOLOCENE = 24,
70    PRAGUE = 25,
71    OSAKA = 26,
72    #[default]
73    LATEST = u8::MAX,
74}
75
76impl SpecId {
77    /// Returns the `SpecId` for the given `u8`.
78    #[inline]
79    pub fn try_from_u8(spec_id: u8) -> Option<Self> {
80        Self::n(spec_id)
81    }
82
83    /// Returns `true` if the given specification ID is enabled in this spec.
84    #[inline]
85    pub const fn is_enabled_in(self, other: Self) -> bool {
86        Self::enabled(self, other)
87    }
88
89    /// Returns `true` if the given specification ID is enabled in this spec.
90    #[inline]
91    pub const fn enabled(our: SpecId, other: SpecId) -> bool {
92        our as u8 >= other as u8
93    }
94}
95
96impl From<&str> for SpecId {
97    fn from(name: &str) -> Self {
98        match name {
99            "Frontier" => Self::FRONTIER,
100            "Homestead" => Self::HOMESTEAD,
101            "Tangerine" => Self::TANGERINE,
102            "Spurious" => Self::SPURIOUS_DRAGON,
103            "Byzantium" => Self::BYZANTIUM,
104            "Constantinople" => Self::CONSTANTINOPLE,
105            "Petersburg" => Self::PETERSBURG,
106            "Istanbul" => Self::ISTANBUL,
107            "MuirGlacier" => Self::MUIR_GLACIER,
108            "Berlin" => Self::BERLIN,
109            "London" => Self::LONDON,
110            "Merge" => Self::MERGE,
111            "Shanghai" => Self::SHANGHAI,
112            "Cancun" => Self::CANCUN,
113            "Prague" => Self::PRAGUE,
114            "Osaka" => Self::OSAKA,
115            #[cfg(feature = "optimism")]
116            "Bedrock" => SpecId::BEDROCK,
117            #[cfg(feature = "optimism")]
118            "Regolith" => SpecId::REGOLITH,
119            #[cfg(feature = "optimism")]
120            "Canyon" => SpecId::CANYON,
121            #[cfg(feature = "optimism")]
122            "Ecotone" => SpecId::ECOTONE,
123            #[cfg(feature = "optimism")]
124            "Fjord" => SpecId::FJORD,
125            #[cfg(feature = "optimism")]
126            "Granite" => SpecId::GRANITE,
127            #[cfg(feature = "optimism")]
128            "Holocene" => SpecId::HOLOCENE,
129            _ => Self::LATEST,
130        }
131    }
132}
133
134impl From<SpecId> for &'static str {
135    fn from(spec_id: SpecId) -> Self {
136        match spec_id {
137            SpecId::FRONTIER => "Frontier",
138            SpecId::FRONTIER_THAWING => "Frontier Thawing",
139            SpecId::HOMESTEAD => "Homestead",
140            SpecId::DAO_FORK => "DAO Fork",
141            SpecId::TANGERINE => "Tangerine",
142            SpecId::SPURIOUS_DRAGON => "Spurious",
143            SpecId::BYZANTIUM => "Byzantium",
144            SpecId::CONSTANTINOPLE => "Constantinople",
145            SpecId::PETERSBURG => "Petersburg",
146            SpecId::ISTANBUL => "Istanbul",
147            SpecId::MUIR_GLACIER => "MuirGlacier",
148            SpecId::BERLIN => "Berlin",
149            SpecId::LONDON => "London",
150            SpecId::ARROW_GLACIER => "Arrow Glacier",
151            SpecId::GRAY_GLACIER => "Gray Glacier",
152            SpecId::MERGE => "Merge",
153            SpecId::SHANGHAI => "Shanghai",
154            SpecId::CANCUN => "Cancun",
155            SpecId::PRAGUE => "Prague",
156            SpecId::OSAKA => "Osaka",
157            #[cfg(feature = "optimism")]
158            SpecId::BEDROCK => "Bedrock",
159            #[cfg(feature = "optimism")]
160            SpecId::REGOLITH => "Regolith",
161            #[cfg(feature = "optimism")]
162            SpecId::CANYON => "Canyon",
163            #[cfg(feature = "optimism")]
164            SpecId::ECOTONE => "Ecotone",
165            #[cfg(feature = "optimism")]
166            SpecId::FJORD => "Fjord",
167            #[cfg(feature = "optimism")]
168            SpecId::GRANITE => "Granite",
169            #[cfg(feature = "optimism")]
170            SpecId::HOLOCENE => "Holocene",
171            SpecId::LATEST => "Latest",
172        }
173    }
174}
175
176pub trait Spec: Sized + 'static {
177    /// The specification ID.
178    const SPEC_ID: SpecId;
179
180    /// Returns `true` if the given specification ID is enabled in this spec.
181    #[inline]
182    fn enabled(spec_id: SpecId) -> bool {
183        SpecId::enabled(Self::SPEC_ID, spec_id)
184    }
185}
186
187macro_rules! spec {
188    ($spec_id:ident, $spec_name:ident) => {
189        #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
190        pub struct $spec_name;
191
192        impl Spec for $spec_name {
193            const SPEC_ID: SpecId = $spec_id;
194        }
195    };
196}
197
198spec!(FRONTIER, FrontierSpec);
199// FRONTIER_THAWING no EVM spec change
200spec!(HOMESTEAD, HomesteadSpec);
201// DAO_FORK no EVM spec change
202spec!(TANGERINE, TangerineSpec);
203spec!(SPURIOUS_DRAGON, SpuriousDragonSpec);
204spec!(BYZANTIUM, ByzantiumSpec);
205// CONSTANTINOPLE was overridden with PETERSBURG
206spec!(PETERSBURG, PetersburgSpec);
207spec!(ISTANBUL, IstanbulSpec);
208// MUIR_GLACIER no EVM spec change
209spec!(BERLIN, BerlinSpec);
210spec!(LONDON, LondonSpec);
211// ARROW_GLACIER no EVM spec change
212// GRAY_GLACIER no EVM spec change
213spec!(MERGE, MergeSpec);
214spec!(SHANGHAI, ShanghaiSpec);
215spec!(CANCUN, CancunSpec);
216spec!(PRAGUE, PragueSpec);
217spec!(OSAKA, OsakaSpec);
218
219spec!(LATEST, LatestSpec);
220
221// Optimism Hardforks
222#[cfg(feature = "optimism")]
223spec!(BEDROCK, BedrockSpec);
224#[cfg(feature = "optimism")]
225spec!(REGOLITH, RegolithSpec);
226#[cfg(feature = "optimism")]
227spec!(CANYON, CanyonSpec);
228#[cfg(feature = "optimism")]
229spec!(ECOTONE, EcotoneSpec);
230#[cfg(feature = "optimism")]
231spec!(FJORD, FjordSpec);
232#[cfg(feature = "optimism")]
233spec!(GRANITE, GraniteSpec);
234#[cfg(feature = "optimism")]
235spec!(HOLOCENE, HoloceneSpec);
236
237#[cfg(not(feature = "optimism"))]
238#[macro_export]
239macro_rules! spec_to_generic {
240    ($spec_id:expr, $e:expr) => {{
241        match $spec_id {
242            $crate::SpecId::FRONTIER | SpecId::FRONTIER_THAWING => {
243                use $crate::FrontierSpec as SPEC;
244                $e
245            }
246            $crate::SpecId::HOMESTEAD | SpecId::DAO_FORK => {
247                use $crate::HomesteadSpec as SPEC;
248                $e
249            }
250            $crate::SpecId::TANGERINE => {
251                use $crate::TangerineSpec as SPEC;
252                $e
253            }
254            $crate::SpecId::SPURIOUS_DRAGON => {
255                use $crate::SpuriousDragonSpec as SPEC;
256                $e
257            }
258            $crate::SpecId::BYZANTIUM => {
259                use $crate::ByzantiumSpec as SPEC;
260                $e
261            }
262            $crate::SpecId::PETERSBURG | $crate::SpecId::CONSTANTINOPLE => {
263                use $crate::PetersburgSpec as SPEC;
264                $e
265            }
266            $crate::SpecId::ISTANBUL | $crate::SpecId::MUIR_GLACIER => {
267                use $crate::IstanbulSpec as SPEC;
268                $e
269            }
270            $crate::SpecId::BERLIN => {
271                use $crate::BerlinSpec as SPEC;
272                $e
273            }
274            $crate::SpecId::LONDON
275            | $crate::SpecId::ARROW_GLACIER
276            | $crate::SpecId::GRAY_GLACIER => {
277                use $crate::LondonSpec as SPEC;
278                $e
279            }
280            $crate::SpecId::MERGE => {
281                use $crate::MergeSpec as SPEC;
282                $e
283            }
284            $crate::SpecId::SHANGHAI => {
285                use $crate::ShanghaiSpec as SPEC;
286                $e
287            }
288            $crate::SpecId::CANCUN => {
289                use $crate::CancunSpec as SPEC;
290                $e
291            }
292            $crate::SpecId::LATEST => {
293                use $crate::LatestSpec as SPEC;
294                $e
295            }
296            $crate::SpecId::PRAGUE => {
297                use $crate::PragueSpec as SPEC;
298                $e
299            }
300            $crate::SpecId::OSAKA => {
301                use $crate::OsakaSpec as SPEC;
302                $e
303            }
304        }
305    }};
306}
307
308#[cfg(feature = "optimism")]
309#[macro_export]
310macro_rules! spec_to_generic {
311    ($spec_id:expr, $e:expr) => {{
312        match $spec_id {
313            $crate::SpecId::FRONTIER | SpecId::FRONTIER_THAWING => {
314                use $crate::FrontierSpec as SPEC;
315                $e
316            }
317            $crate::SpecId::HOMESTEAD | SpecId::DAO_FORK => {
318                use $crate::HomesteadSpec as SPEC;
319                $e
320            }
321            $crate::SpecId::TANGERINE => {
322                use $crate::TangerineSpec as SPEC;
323                $e
324            }
325            $crate::SpecId::SPURIOUS_DRAGON => {
326                use $crate::SpuriousDragonSpec as SPEC;
327                $e
328            }
329            $crate::SpecId::BYZANTIUM => {
330                use $crate::ByzantiumSpec as SPEC;
331                $e
332            }
333            $crate::SpecId::PETERSBURG | $crate::SpecId::CONSTANTINOPLE => {
334                use $crate::PetersburgSpec as SPEC;
335                $e
336            }
337            $crate::SpecId::ISTANBUL | $crate::SpecId::MUIR_GLACIER => {
338                use $crate::IstanbulSpec as SPEC;
339                $e
340            }
341            $crate::SpecId::BERLIN => {
342                use $crate::BerlinSpec as SPEC;
343                $e
344            }
345            $crate::SpecId::LONDON
346            | $crate::SpecId::ARROW_GLACIER
347            | $crate::SpecId::GRAY_GLACIER => {
348                use $crate::LondonSpec as SPEC;
349                $e
350            }
351            $crate::SpecId::MERGE => {
352                use $crate::MergeSpec as SPEC;
353                $e
354            }
355            $crate::SpecId::SHANGHAI => {
356                use $crate::ShanghaiSpec as SPEC;
357                $e
358            }
359            $crate::SpecId::CANCUN => {
360                use $crate::CancunSpec as SPEC;
361                $e
362            }
363            $crate::SpecId::LATEST => {
364                use $crate::LatestSpec as SPEC;
365                $e
366            }
367            $crate::SpecId::PRAGUE => {
368                use $crate::PragueSpec as SPEC;
369                $e
370            }
371            $crate::SpecId::OSAKA => {
372                use $crate::OsakaSpec as SPEC;
373                $e
374            }
375            $crate::SpecId::BEDROCK => {
376                use $crate::BedrockSpec as SPEC;
377                $e
378            }
379            $crate::SpecId::REGOLITH => {
380                use $crate::RegolithSpec as SPEC;
381                $e
382            }
383            $crate::SpecId::CANYON => {
384                use $crate::CanyonSpec as SPEC;
385                $e
386            }
387            $crate::SpecId::ECOTONE => {
388                use $crate::EcotoneSpec as SPEC;
389                $e
390            }
391            $crate::SpecId::FJORD => {
392                use $crate::FjordSpec as SPEC;
393                $e
394            }
395            $crate::SpecId::GRANITE => {
396                use $crate::GraniteSpec as SPEC;
397                $e
398            }
399            $crate::SpecId::HOLOCENE => {
400                use $crate::HoloceneSpec as SPEC;
401                $e
402            }
403        }
404    }};
405}
406
407#[cfg(test)]
408mod tests {
409    use super::*;
410
411    #[test]
412    fn spec_to_generic() {
413        use SpecId::*;
414
415        spec_to_generic!(FRONTIER, assert_eq!(SPEC::SPEC_ID, FRONTIER));
416        spec_to_generic!(FRONTIER_THAWING, assert_eq!(SPEC::SPEC_ID, FRONTIER));
417        spec_to_generic!(HOMESTEAD, assert_eq!(SPEC::SPEC_ID, HOMESTEAD));
418        spec_to_generic!(DAO_FORK, assert_eq!(SPEC::SPEC_ID, HOMESTEAD));
419        spec_to_generic!(TANGERINE, assert_eq!(SPEC::SPEC_ID, TANGERINE));
420        spec_to_generic!(SPURIOUS_DRAGON, assert_eq!(SPEC::SPEC_ID, SPURIOUS_DRAGON));
421        spec_to_generic!(BYZANTIUM, assert_eq!(SPEC::SPEC_ID, BYZANTIUM));
422        spec_to_generic!(CONSTANTINOPLE, assert_eq!(SPEC::SPEC_ID, PETERSBURG));
423        spec_to_generic!(PETERSBURG, assert_eq!(SPEC::SPEC_ID, PETERSBURG));
424        spec_to_generic!(ISTANBUL, assert_eq!(SPEC::SPEC_ID, ISTANBUL));
425        spec_to_generic!(MUIR_GLACIER, assert_eq!(SPEC::SPEC_ID, ISTANBUL));
426        spec_to_generic!(BERLIN, assert_eq!(SPEC::SPEC_ID, BERLIN));
427        spec_to_generic!(LONDON, assert_eq!(SPEC::SPEC_ID, LONDON));
428        spec_to_generic!(ARROW_GLACIER, assert_eq!(SPEC::SPEC_ID, LONDON));
429        spec_to_generic!(GRAY_GLACIER, assert_eq!(SPEC::SPEC_ID, LONDON));
430        spec_to_generic!(MERGE, assert_eq!(SPEC::SPEC_ID, MERGE));
431        #[cfg(feature = "optimism")]
432        spec_to_generic!(BEDROCK, assert_eq!(SPEC::SPEC_ID, BEDROCK));
433        #[cfg(feature = "optimism")]
434        spec_to_generic!(REGOLITH, assert_eq!(SPEC::SPEC_ID, REGOLITH));
435        spec_to_generic!(SHANGHAI, assert_eq!(SPEC::SPEC_ID, SHANGHAI));
436        #[cfg(feature = "optimism")]
437        spec_to_generic!(CANYON, assert_eq!(SPEC::SPEC_ID, CANYON));
438        spec_to_generic!(CANCUN, assert_eq!(SPEC::SPEC_ID, CANCUN));
439        #[cfg(feature = "optimism")]
440        spec_to_generic!(ECOTONE, assert_eq!(SPEC::SPEC_ID, ECOTONE));
441        #[cfg(feature = "optimism")]
442        spec_to_generic!(FJORD, assert_eq!(SPEC::SPEC_ID, FJORD));
443        #[cfg(feature = "optimism")]
444        spec_to_generic!(GRANITE, assert_eq!(SPEC::SPEC_ID, GRANITE));
445        #[cfg(feature = "optimism")]
446        spec_to_generic!(HOLOCENE, assert_eq!(SPEC::SPEC_ID, HOLOCENE));
447        spec_to_generic!(PRAGUE, assert_eq!(SPEC::SPEC_ID, PRAGUE));
448        spec_to_generic!(OSAKA, assert_eq!(SPEC::SPEC_ID, OSAKA));
449        spec_to_generic!(LATEST, assert_eq!(SPEC::SPEC_ID, LATEST));
450    }
451}
452
453#[cfg(feature = "optimism")]
454#[cfg(test)]
455mod optimism_tests {
456    use super::*;
457
458    #[test]
459    fn test_bedrock_post_merge_hardforks() {
460        assert!(BedrockSpec::enabled(SpecId::MERGE));
461        assert!(!BedrockSpec::enabled(SpecId::SHANGHAI));
462        assert!(!BedrockSpec::enabled(SpecId::CANCUN));
463        assert!(!BedrockSpec::enabled(SpecId::LATEST));
464        assert!(BedrockSpec::enabled(SpecId::BEDROCK));
465        assert!(!BedrockSpec::enabled(SpecId::REGOLITH));
466    }
467
468    #[test]
469    fn test_regolith_post_merge_hardforks() {
470        assert!(RegolithSpec::enabled(SpecId::MERGE));
471        assert!(!RegolithSpec::enabled(SpecId::SHANGHAI));
472        assert!(!RegolithSpec::enabled(SpecId::CANCUN));
473        assert!(!RegolithSpec::enabled(SpecId::LATEST));
474        assert!(RegolithSpec::enabled(SpecId::BEDROCK));
475        assert!(RegolithSpec::enabled(SpecId::REGOLITH));
476    }
477
478    #[test]
479    fn test_bedrock_post_merge_hardforks_spec_id() {
480        assert!(SpecId::enabled(SpecId::BEDROCK, SpecId::MERGE));
481        assert!(!SpecId::enabled(SpecId::BEDROCK, SpecId::SHANGHAI));
482        assert!(!SpecId::enabled(SpecId::BEDROCK, SpecId::CANCUN));
483        assert!(!SpecId::enabled(SpecId::BEDROCK, SpecId::LATEST));
484        assert!(SpecId::enabled(SpecId::BEDROCK, SpecId::BEDROCK));
485        assert!(!SpecId::enabled(SpecId::BEDROCK, SpecId::REGOLITH));
486    }
487
488    #[test]
489    fn test_regolith_post_merge_hardforks_spec_id() {
490        assert!(SpecId::enabled(SpecId::REGOLITH, SpecId::MERGE));
491        assert!(!SpecId::enabled(SpecId::REGOLITH, SpecId::SHANGHAI));
492        assert!(!SpecId::enabled(SpecId::REGOLITH, SpecId::CANCUN));
493        assert!(!SpecId::enabled(SpecId::REGOLITH, SpecId::LATEST));
494        assert!(SpecId::enabled(SpecId::REGOLITH, SpecId::BEDROCK));
495        assert!(SpecId::enabled(SpecId::REGOLITH, SpecId::REGOLITH));
496    }
497
498    #[test]
499    fn test_canyon_post_merge_hardforks() {
500        assert!(CanyonSpec::enabled(SpecId::MERGE));
501        assert!(CanyonSpec::enabled(SpecId::SHANGHAI));
502        assert!(!CanyonSpec::enabled(SpecId::CANCUN));
503        assert!(!CanyonSpec::enabled(SpecId::LATEST));
504        assert!(CanyonSpec::enabled(SpecId::BEDROCK));
505        assert!(CanyonSpec::enabled(SpecId::REGOLITH));
506        assert!(CanyonSpec::enabled(SpecId::CANYON));
507    }
508
509    #[test]
510    fn test_canyon_post_merge_hardforks_spec_id() {
511        assert!(SpecId::enabled(SpecId::CANYON, SpecId::MERGE));
512        assert!(SpecId::enabled(SpecId::CANYON, SpecId::SHANGHAI));
513        assert!(!SpecId::enabled(SpecId::CANYON, SpecId::CANCUN));
514        assert!(!SpecId::enabled(SpecId::CANYON, SpecId::LATEST));
515        assert!(SpecId::enabled(SpecId::CANYON, SpecId::BEDROCK));
516        assert!(SpecId::enabled(SpecId::CANYON, SpecId::REGOLITH));
517        assert!(SpecId::enabled(SpecId::CANYON, SpecId::CANYON));
518    }
519
520    #[test]
521    fn test_ecotone_post_merge_hardforks() {
522        assert!(EcotoneSpec::enabled(SpecId::MERGE));
523        assert!(EcotoneSpec::enabled(SpecId::SHANGHAI));
524        assert!(EcotoneSpec::enabled(SpecId::CANCUN));
525        assert!(!EcotoneSpec::enabled(SpecId::LATEST));
526        assert!(EcotoneSpec::enabled(SpecId::BEDROCK));
527        assert!(EcotoneSpec::enabled(SpecId::REGOLITH));
528        assert!(EcotoneSpec::enabled(SpecId::CANYON));
529        assert!(EcotoneSpec::enabled(SpecId::ECOTONE));
530    }
531
532    #[test]
533    fn test_ecotone_post_merge_hardforks_spec_id() {
534        assert!(SpecId::enabled(SpecId::ECOTONE, SpecId::MERGE));
535        assert!(SpecId::enabled(SpecId::ECOTONE, SpecId::SHANGHAI));
536        assert!(SpecId::enabled(SpecId::ECOTONE, SpecId::CANCUN));
537        assert!(!SpecId::enabled(SpecId::ECOTONE, SpecId::LATEST));
538        assert!(SpecId::enabled(SpecId::ECOTONE, SpecId::BEDROCK));
539        assert!(SpecId::enabled(SpecId::ECOTONE, SpecId::REGOLITH));
540        assert!(SpecId::enabled(SpecId::ECOTONE, SpecId::CANYON));
541        assert!(SpecId::enabled(SpecId::ECOTONE, SpecId::ECOTONE));
542    }
543
544    #[test]
545    fn test_fjord_post_merge_hardforks() {
546        assert!(FjordSpec::enabled(SpecId::MERGE));
547        assert!(FjordSpec::enabled(SpecId::SHANGHAI));
548        assert!(FjordSpec::enabled(SpecId::CANCUN));
549        assert!(!FjordSpec::enabled(SpecId::LATEST));
550        assert!(FjordSpec::enabled(SpecId::BEDROCK));
551        assert!(FjordSpec::enabled(SpecId::REGOLITH));
552        assert!(FjordSpec::enabled(SpecId::CANYON));
553        assert!(FjordSpec::enabled(SpecId::ECOTONE));
554        assert!(FjordSpec::enabled(SpecId::FJORD));
555    }
556
557    #[test]
558    fn test_fjord_post_merge_hardforks_spec_id() {
559        assert!(SpecId::enabled(SpecId::FJORD, SpecId::MERGE));
560        assert!(SpecId::enabled(SpecId::FJORD, SpecId::SHANGHAI));
561        assert!(SpecId::enabled(SpecId::FJORD, SpecId::CANCUN));
562        assert!(!SpecId::enabled(SpecId::FJORD, SpecId::LATEST));
563        assert!(SpecId::enabled(SpecId::FJORD, SpecId::BEDROCK));
564        assert!(SpecId::enabled(SpecId::FJORD, SpecId::REGOLITH));
565        assert!(SpecId::enabled(SpecId::FJORD, SpecId::CANYON));
566        assert!(SpecId::enabled(SpecId::FJORD, SpecId::ECOTONE));
567        assert!(SpecId::enabled(SpecId::FJORD, SpecId::FJORD));
568    }
569
570    #[test]
571    fn test_granite_post_merge_hardforks() {
572        assert!(GraniteSpec::enabled(SpecId::MERGE));
573        assert!(GraniteSpec::enabled(SpecId::SHANGHAI));
574        assert!(GraniteSpec::enabled(SpecId::CANCUN));
575        assert!(!GraniteSpec::enabled(SpecId::LATEST));
576        assert!(GraniteSpec::enabled(SpecId::BEDROCK));
577        assert!(GraniteSpec::enabled(SpecId::REGOLITH));
578        assert!(GraniteSpec::enabled(SpecId::CANYON));
579        assert!(GraniteSpec::enabled(SpecId::ECOTONE));
580        assert!(GraniteSpec::enabled(SpecId::FJORD));
581        assert!(GraniteSpec::enabled(SpecId::GRANITE));
582    }
583
584    #[test]
585    fn test_granite_post_merge_hardforks_spec_id() {
586        assert!(SpecId::enabled(SpecId::GRANITE, SpecId::MERGE));
587        assert!(SpecId::enabled(SpecId::GRANITE, SpecId::SHANGHAI));
588        assert!(SpecId::enabled(SpecId::GRANITE, SpecId::CANCUN));
589        assert!(!SpecId::enabled(SpecId::GRANITE, SpecId::LATEST));
590        assert!(SpecId::enabled(SpecId::GRANITE, SpecId::BEDROCK));
591        assert!(SpecId::enabled(SpecId::GRANITE, SpecId::REGOLITH));
592        assert!(SpecId::enabled(SpecId::GRANITE, SpecId::CANYON));
593        assert!(SpecId::enabled(SpecId::GRANITE, SpecId::ECOTONE));
594        assert!(SpecId::enabled(SpecId::GRANITE, SpecId::FJORD));
595        assert!(SpecId::enabled(SpecId::GRANITE, SpecId::GRANITE));
596    }
597
598    #[test]
599    fn test_holocene_post_merge_hardforks() {
600        // from MERGE to HOLOCENE
601        for i in 15..=24 {
602            if let Some(spec) = SpecId::try_from_u8(i) {
603                assert!(HoloceneSpec::enabled(spec));
604            }
605        }
606        assert!(!HoloceneSpec::enabled(SpecId::LATEST));
607    }
608
609    #[test]
610    fn test_holocene_post_merge_hardforks_spec_id() {
611        // from MERGE to HOLOCENE
612        for i in 15..=24 {
613            if let Some(spec) = SpecId::try_from_u8(i) {
614                assert!(SpecId::enabled(SpecId::HOLOCENE, spec));
615            }
616        }
617        assert!(!SpecId::enabled(SpecId::HOLOCENE, SpecId::LATEST));
618    }
619}