reth_optimism_evm/
config.rs1use alloy_consensus::BlockHeader;
2use op_revm::OpSpecId;
3use reth_optimism_forks::OpHardforks;
4use revm::primitives::{Address, Bytes, B256};
5
6#[derive(Debug, Clone, PartialEq, Eq)]
8pub struct OpNextBlockEnvAttributes {
9 pub timestamp: u64,
11 pub suggested_fee_recipient: Address,
13 pub prev_randao: B256,
15 pub gas_limit: u64,
17 pub parent_beacon_block_root: Option<B256>,
19 pub extra_data: Bytes,
21}
22
23pub fn revm_spec(chain_spec: impl OpHardforks, header: impl BlockHeader) -> OpSpecId {
25 revm_spec_by_timestamp_after_bedrock(chain_spec, header.timestamp())
26}
27
28pub fn revm_spec_by_timestamp_after_bedrock(
35 chain_spec: impl OpHardforks,
36 timestamp: u64,
37) -> OpSpecId {
38 if chain_spec.is_interop_active_at_timestamp(timestamp) {
39 OpSpecId::INTEROP
40 } else if chain_spec.is_isthmus_active_at_timestamp(timestamp) {
41 OpSpecId::ISTHMUS
42 } else if chain_spec.is_holocene_active_at_timestamp(timestamp) {
43 OpSpecId::HOLOCENE
44 } else if chain_spec.is_granite_active_at_timestamp(timestamp) {
45 OpSpecId::GRANITE
46 } else if chain_spec.is_fjord_active_at_timestamp(timestamp) {
47 OpSpecId::FJORD
48 } else if chain_spec.is_ecotone_active_at_timestamp(timestamp) {
49 OpSpecId::ECOTONE
50 } else if chain_spec.is_canyon_active_at_timestamp(timestamp) {
51 OpSpecId::CANYON
52 } else if chain_spec.is_regolith_active_at_timestamp(timestamp) {
53 OpSpecId::REGOLITH
54 } else {
55 OpSpecId::BEDROCK
56 }
57}
58
59#[cfg(feature = "rpc")]
60impl<H: alloy_consensus::BlockHeader> reth_rpc_eth_api::helpers::pending_block::BuildPendingEnv<H>
61 for OpNextBlockEnvAttributes
62{
63 fn build_pending_env(parent: &crate::SealedHeader<H>) -> Self {
64 Self {
65 timestamp: parent.timestamp().saturating_add(12),
66 suggested_fee_recipient: parent.beneficiary(),
67 prev_randao: alloy_primitives::B256::random(),
68 gas_limit: parent.gas_limit(),
69 parent_beacon_block_root: parent.parent_beacon_block_root(),
70 extra_data: parent.extra_data().clone(),
71 }
72 }
73}
74
75#[cfg(test)]
76mod tests {
77 use super::*;
78 use alloy_consensus::Header;
79 use reth_chainspec::ChainSpecBuilder;
80 use reth_optimism_chainspec::{OpChainSpec, OpChainSpecBuilder};
81
82 #[test]
83 fn test_revm_spec_by_timestamp_after_merge() {
84 #[inline(always)]
85 fn op_cs(f: impl FnOnce(OpChainSpecBuilder) -> OpChainSpecBuilder) -> OpChainSpec {
86 let cs = ChainSpecBuilder::mainnet().chain(reth_chainspec::Chain::from_id(10)).into();
87 f(cs).build()
88 }
89 assert_eq!(
90 revm_spec_by_timestamp_after_bedrock(op_cs(|cs| cs.interop_activated()), 0),
91 OpSpecId::INTEROP
92 );
93 assert_eq!(
94 revm_spec_by_timestamp_after_bedrock(op_cs(|cs| cs.isthmus_activated()), 0),
95 OpSpecId::ISTHMUS
96 );
97 assert_eq!(
98 revm_spec_by_timestamp_after_bedrock(op_cs(|cs| cs.holocene_activated()), 0),
99 OpSpecId::HOLOCENE
100 );
101 assert_eq!(
102 revm_spec_by_timestamp_after_bedrock(op_cs(|cs| cs.granite_activated()), 0),
103 OpSpecId::GRANITE
104 );
105 assert_eq!(
106 revm_spec_by_timestamp_after_bedrock(op_cs(|cs| cs.fjord_activated()), 0),
107 OpSpecId::FJORD
108 );
109 assert_eq!(
110 revm_spec_by_timestamp_after_bedrock(op_cs(|cs| cs.ecotone_activated()), 0),
111 OpSpecId::ECOTONE
112 );
113 assert_eq!(
114 revm_spec_by_timestamp_after_bedrock(op_cs(|cs| cs.canyon_activated()), 0),
115 OpSpecId::CANYON
116 );
117 assert_eq!(
118 revm_spec_by_timestamp_after_bedrock(op_cs(|cs| cs.bedrock_activated()), 0),
119 OpSpecId::BEDROCK
120 );
121 assert_eq!(
122 revm_spec_by_timestamp_after_bedrock(op_cs(|cs| cs.regolith_activated()), 0),
123 OpSpecId::REGOLITH
124 );
125 }
126
127 #[test]
128 fn test_to_revm_spec() {
129 #[inline(always)]
130 fn op_cs(f: impl FnOnce(OpChainSpecBuilder) -> OpChainSpecBuilder) -> OpChainSpec {
131 let cs = ChainSpecBuilder::mainnet().chain(reth_chainspec::Chain::from_id(10)).into();
132 f(cs).build()
133 }
134 assert_eq!(
135 revm_spec(op_cs(|cs| cs.isthmus_activated()), Header::default()),
136 OpSpecId::ISTHMUS
137 );
138 assert_eq!(
139 revm_spec(op_cs(|cs| cs.holocene_activated()), Header::default()),
140 OpSpecId::HOLOCENE
141 );
142 assert_eq!(
143 revm_spec(op_cs(|cs| cs.granite_activated()), Header::default()),
144 OpSpecId::GRANITE
145 );
146 assert_eq!(revm_spec(op_cs(|cs| cs.fjord_activated()), Header::default()), OpSpecId::FJORD);
147 assert_eq!(
148 revm_spec(op_cs(|cs| cs.ecotone_activated()), Header::default()),
149 OpSpecId::ECOTONE
150 );
151 assert_eq!(
152 revm_spec(op_cs(|cs| cs.canyon_activated()), Header::default()),
153 OpSpecId::CANYON
154 );
155 assert_eq!(
156 revm_spec(op_cs(|cs| cs.bedrock_activated()), Header::default()),
157 OpSpecId::BEDROCK
158 );
159 assert_eq!(
160 revm_spec(op_cs(|cs| cs.regolith_activated()), Header::default()),
161 OpSpecId::REGOLITH
162 );
163 }
164}