1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
#![allow(non_camel_case_types)]
// enumn has missing docs. Should be replaced in the future https://github.com/bluealloy/revm/issues/2402
#![allow(missing_docs)]
use core::str::FromStr;
pub use num_enum::TryFromPrimitive;
pub use std::string::{String, ToString};
pub use SpecId::*;
/// Specification IDs and their activation block
///
/// Information was obtained from the [Ethereum Execution Specifications](https://github.com/ethereum/execution-specs).
#[repr(u8)]
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, TryFromPrimitive)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum SpecId {
/// Frontier hard fork
/// Activated at block 0
FRONTIER = 0,
/// Frontier Thawing hard fork
/// Activated at block 200000
FRONTIER_THAWING,
/// Homestead hard fork
/// Activated at block 1150000
HOMESTEAD,
/// DAO Fork hard fork
/// Activated at block 1920000
DAO_FORK,
/// Tangerine Whistle hard fork
/// Activated at block 2463000
TANGERINE,
/// Spurious Dragon hard fork
/// Activated at block 2675000
SPURIOUS_DRAGON,
/// Byzantium hard fork
/// Activated at block 4370000
BYZANTIUM,
/// Constantinople hard fork
/// Activated at block 7280000 is overwritten with PETERSBURG
CONSTANTINOPLE,
/// Petersburg hard fork
/// Activated at block 7280000
PETERSBURG,
/// Istanbul hard fork
/// Activated at block 9069000
ISTANBUL,
/// Muir Glacier hard fork
/// Activated at block 9200000
MUIR_GLACIER,
/// Berlin hard fork
/// Activated at block 12244000
BERLIN,
/// London hard fork
/// Activated at block 12965000
LONDON,
/// Arrow Glacier hard fork
/// Activated at block 13773000
ARROW_GLACIER,
/// Gray Glacier hard fork
/// Activated at block 15050000
GRAY_GLACIER,
/// Paris/Merge hard fork
/// Activated at block 15537394 (TTD: 58750000000000000000000)
MERGE,
/// Shanghai hard fork
/// Activated at block 17034870 (Timestamp: 1681338455)
SHANGHAI,
/// Cancun hard fork
/// Activated at block 19426587 (Timestamp: 1710338135)
CANCUN,
/// Prague hard fork
/// Activated at block 22431084 (Timestamp: 1746612311)
PRAGUE,
/// Osaka hard fork
/// Activated at slot 13164544 (Timestamp: 1764798551)
#[default]
OSAKA,
/// Amsterdam hard fork
/// Activated at block TBD
AMSTERDAM,
}
impl SpecId {
/// Returns the [`SpecId`] for the given [`u8`].
#[inline]
pub fn try_from_u8(spec_id: u8) -> Option<Self> {
Self::try_from(spec_id).ok()
}
/// Returns `true` if the given specification ID is enabled in this spec.
#[inline]
pub const fn is_enabled_in(self, other: Self) -> bool {
self as u8 >= other as u8
}
}
/// String identifiers for hardforks.
pub mod name {
/// String identifier for the Frontier hardfork
pub const FRONTIER: &str = "Frontier";
/// String identifier for the Frontier Thawing hardfork
pub const FRONTIER_THAWING: &str = "Frontier Thawing";
/// String identifier for the Homestead hardfork
pub const HOMESTEAD: &str = "Homestead";
/// String identifier for the DAO Fork hardfork
pub const DAO_FORK: &str = "DAO Fork";
/// String identifier for the Tangerine Whistle hardfork
pub const TANGERINE: &str = "Tangerine";
/// String identifier for the Spurious Dragon hardfork
pub const SPURIOUS_DRAGON: &str = "Spurious";
/// String identifier for the Byzantium hardfork
pub const BYZANTIUM: &str = "Byzantium";
/// String identifier for the Constantinople hardfork
pub const CONSTANTINOPLE: &str = "Constantinople";
/// String identifier for the Petersburg hardfork
pub const PETERSBURG: &str = "Petersburg";
/// String identifier for the Istanbul hardfork
pub const ISTANBUL: &str = "Istanbul";
/// String identifier for the Muir Glacier hardfork
pub const MUIR_GLACIER: &str = "MuirGlacier";
/// String identifier for the Berlin hardfork
pub const BERLIN: &str = "Berlin";
/// String identifier for the London hardfork
pub const LONDON: &str = "London";
/// String identifier for the Arrow Glacier hardfork
pub const ARROW_GLACIER: &str = "Arrow Glacier";
/// String identifier for the Gray Glacier hardfork
pub const GRAY_GLACIER: &str = "Gray Glacier";
/// String identifier for the Paris/Merge hardfork
pub const MERGE: &str = "Merge";
/// String identifier for the Shanghai hardfork
pub const SHANGHAI: &str = "Shanghai";
/// String identifier for the Cancun hardfork
pub const CANCUN: &str = "Cancun";
/// String identifier for the Prague hardfork
pub const PRAGUE: &str = "Prague";
/// String identifier for the Osaka hardfork
pub const OSAKA: &str = "Osaka";
/// String identifier for the Amsterdam hardfork
pub const AMSTERDAM: &str = "Amsterdam";
/// String identifier for the latest hardfork
pub const LATEST: &str = "Latest";
}
/// Error type for unknown hardfork names. Returned by [`SpecId::from_str`].
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct UnknownHardfork;
impl FromStr for SpecId {
type Err = UnknownHardfork;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
name::FRONTIER => Ok(Self::FRONTIER),
name::FRONTIER_THAWING => Ok(Self::FRONTIER_THAWING),
name::HOMESTEAD => Ok(Self::HOMESTEAD),
name::DAO_FORK => Ok(Self::DAO_FORK),
name::TANGERINE => Ok(Self::TANGERINE),
name::SPURIOUS_DRAGON => Ok(Self::SPURIOUS_DRAGON),
name::BYZANTIUM => Ok(Self::BYZANTIUM),
name::CONSTANTINOPLE => Ok(Self::CONSTANTINOPLE),
name::PETERSBURG => Ok(Self::PETERSBURG),
name::ISTANBUL => Ok(Self::ISTANBUL),
name::MUIR_GLACIER => Ok(Self::MUIR_GLACIER),
name::BERLIN => Ok(Self::BERLIN),
name::LONDON => Ok(Self::LONDON),
name::ARROW_GLACIER => Ok(Self::ARROW_GLACIER),
name::GRAY_GLACIER => Ok(Self::GRAY_GLACIER),
name::MERGE => Ok(Self::MERGE),
name::SHANGHAI => Ok(Self::SHANGHAI),
name::CANCUN => Ok(Self::CANCUN),
name::PRAGUE => Ok(Self::PRAGUE),
name::OSAKA => Ok(Self::OSAKA),
name::AMSTERDAM => Ok(Self::AMSTERDAM),
_ => Err(UnknownHardfork),
}
}
}
impl From<SpecId> for &'static str {
fn from(spec_id: SpecId) -> Self {
match spec_id {
SpecId::FRONTIER => name::FRONTIER,
SpecId::FRONTIER_THAWING => name::FRONTIER_THAWING,
SpecId::HOMESTEAD => name::HOMESTEAD,
SpecId::DAO_FORK => name::DAO_FORK,
SpecId::TANGERINE => name::TANGERINE,
SpecId::SPURIOUS_DRAGON => name::SPURIOUS_DRAGON,
SpecId::BYZANTIUM => name::BYZANTIUM,
SpecId::CONSTANTINOPLE => name::CONSTANTINOPLE,
SpecId::PETERSBURG => name::PETERSBURG,
SpecId::ISTANBUL => name::ISTANBUL,
SpecId::MUIR_GLACIER => name::MUIR_GLACIER,
SpecId::BERLIN => name::BERLIN,
SpecId::LONDON => name::LONDON,
SpecId::ARROW_GLACIER => name::ARROW_GLACIER,
SpecId::GRAY_GLACIER => name::GRAY_GLACIER,
SpecId::MERGE => name::MERGE,
SpecId::SHANGHAI => name::SHANGHAI,
SpecId::CANCUN => name::CANCUN,
SpecId::PRAGUE => name::PRAGUE,
SpecId::OSAKA => name::OSAKA,
SpecId::AMSTERDAM => name::AMSTERDAM,
}
}
}
impl core::fmt::Display for SpecId {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{}", <&'static str>::from(*self))
}
}