@nomicfoundation/edr 0.11.3 → 0.12.0-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/Cargo.toml +61 -27
  2. package/LICENSE +5 -1
  3. package/index.d.ts +875 -137
  4. package/index.js +61 -3
  5. package/package.json +20 -16
  6. package/src/account.rs +109 -32
  7. package/src/block.rs +2 -103
  8. package/src/call_override.rs +7 -7
  9. package/src/cast.rs +47 -17
  10. package/src/chains/generic.rs +51 -0
  11. package/src/chains/l1.rs +262 -0
  12. package/src/chains/op.rs +425 -0
  13. package/src/chains.rs +7 -0
  14. package/src/config.rs +537 -67
  15. package/src/context.rs +374 -17
  16. package/src/debug_trace.rs +2 -2
  17. package/src/instrument.rs +109 -0
  18. package/src/lib.rs +38 -14
  19. package/src/log.rs +12 -14
  20. package/src/logger.rs +77 -1177
  21. package/src/mock.rs +68 -0
  22. package/src/precompile.rs +50 -0
  23. package/src/provider/factory.rs +22 -0
  24. package/src/provider/response.rs +73 -0
  25. package/src/provider.rs +64 -325
  26. package/src/result.rs +60 -69
  27. package/src/scenarios.rs +11 -17
  28. package/src/serde.rs +57 -0
  29. package/src/solidity_tests/artifact.rs +184 -0
  30. package/src/solidity_tests/config.rs +725 -0
  31. package/src/solidity_tests/factory.rs +22 -0
  32. package/src/solidity_tests/l1.rs +68 -0
  33. package/src/solidity_tests/op.rs +69 -0
  34. package/src/solidity_tests/runner.rs +51 -0
  35. package/src/solidity_tests/test_results.rs +668 -0
  36. package/src/solidity_tests.rs +56 -0
  37. package/src/subscription.rs +32 -0
  38. package/src/trace/debug.rs +1 -1
  39. package/src/trace/exit.rs +12 -13
  40. package/src/trace/library_utils.rs +1 -1
  41. package/src/trace/return_data.rs +11 -11
  42. package/src/trace/solidity_stack_trace.rs +11 -8
  43. package/src/trace.rs +37 -44
  44. package/src/withdrawal.rs +4 -4
  45. package/src/provider/config.rs +0 -291
  46. package/src/subscribe.rs +0 -63
@@ -0,0 +1,262 @@
1
+ use std::{str::FromStr, sync::Arc};
2
+
3
+ use edr_eth::l1::{self, L1ChainSpec};
4
+ use edr_evm::eips::{
5
+ eip2935::{HISTORY_STORAGE_ADDRESS, HISTORY_STORAGE_UNSUPPORTED_BYTECODE},
6
+ eip4788::{BEACON_ROOTS_ADDRESS, BEACON_ROOTS_BYTECODE},
7
+ };
8
+ use edr_napi_core::{
9
+ logger::Logger,
10
+ provider::{self, ProviderBuilder, SyncProviderFactory},
11
+ spec::SyncNapiSpec as _,
12
+ subscription,
13
+ };
14
+ use edr_solidity::contract_decoder::ContractDecoder;
15
+ use napi::bindgen_prelude::{BigInt, Uint8Array};
16
+ use napi_derive::napi;
17
+
18
+ use crate::{account::AccountOverride, provider::ProviderFactory};
19
+
20
+ pub struct L1ProviderFactory;
21
+
22
+ impl SyncProviderFactory for L1ProviderFactory {
23
+ fn create_provider_builder(
24
+ &self,
25
+ env: &napi::Env,
26
+ provider_config: edr_napi_core::provider::Config,
27
+ logger_config: edr_napi_core::logger::Config,
28
+ subscription_config: edr_napi_core::subscription::Config,
29
+ contract_decoder: Arc<ContractDecoder>,
30
+ ) -> napi::Result<Box<dyn provider::Builder>> {
31
+ let logger = Logger::<L1ChainSpec>::new(logger_config, Arc::clone(&contract_decoder))?;
32
+
33
+ let provider_config =
34
+ edr_provider::ProviderConfig::<l1::SpecId>::try_from(provider_config)?;
35
+
36
+ let subscription_callback =
37
+ subscription::Callback::new(env, subscription_config.subscription_callback)?;
38
+
39
+ Ok(Box::new(ProviderBuilder::new(
40
+ contract_decoder,
41
+ Box::new(logger),
42
+ provider_config,
43
+ subscription_callback,
44
+ )))
45
+ }
46
+ }
47
+
48
+ #[napi]
49
+ pub const L1_CHAIN_TYPE: &str = L1ChainSpec::CHAIN_TYPE;
50
+
51
+ #[napi(catch_unwind)]
52
+ pub fn l1_genesis_state(hardfork: SpecId) -> Vec<AccountOverride> {
53
+ // Use closures for lazy execution
54
+ let beacon_roots_account_constructor = || AccountOverride {
55
+ address: Uint8Array::with_data_copied(BEACON_ROOTS_ADDRESS),
56
+ balance: Some(BigInt::from(0u64)),
57
+ nonce: Some(BigInt::from(0u64)),
58
+ code: Some(Uint8Array::with_data_copied(&BEACON_ROOTS_BYTECODE)),
59
+ storage: Some(Vec::new()),
60
+ };
61
+
62
+ let history_storage_account_constructor = || AccountOverride {
63
+ address: Uint8Array::with_data_copied(HISTORY_STORAGE_ADDRESS),
64
+ balance: Some(BigInt::from(0u64)),
65
+ nonce: Some(BigInt::from(0u64)),
66
+ code: Some(Uint8Array::with_data_copied(
67
+ &HISTORY_STORAGE_UNSUPPORTED_BYTECODE,
68
+ )),
69
+ storage: Some(Vec::new()),
70
+ };
71
+
72
+ if hardfork < SpecId::Cancun {
73
+ Vec::new()
74
+ } else if hardfork < SpecId::Prague {
75
+ vec![beacon_roots_account_constructor()]
76
+ } else {
77
+ vec![
78
+ beacon_roots_account_constructor(),
79
+ history_storage_account_constructor(),
80
+ ]
81
+ }
82
+ }
83
+
84
+ #[napi(catch_unwind)]
85
+ pub fn l1_provider_factory() -> ProviderFactory {
86
+ let factory: Arc<dyn SyncProviderFactory> = Arc::new(L1ProviderFactory);
87
+ factory.into()
88
+ }
89
+
90
+ /// Identifier for the Ethereum spec.
91
+ #[napi]
92
+ #[derive(PartialEq, Eq, PartialOrd, Ord)]
93
+ pub enum SpecId {
94
+ /// Frontier
95
+ Frontier = 0,
96
+ /// Frontier Thawing
97
+ FrontierThawing = 1,
98
+ /// Homestead
99
+ Homestead = 2,
100
+ /// DAO Fork
101
+ DaoFork = 3,
102
+ /// Tangerine
103
+ Tangerine = 4,
104
+ /// Spurious Dragon
105
+ SpuriousDragon = 5,
106
+ /// Byzantium
107
+ Byzantium = 6,
108
+ /// Constantinople
109
+ Constantinople = 7,
110
+ /// Petersburg
111
+ Petersburg = 8,
112
+ /// Istanbul
113
+ Istanbul = 9,
114
+ /// Muir Glacier
115
+ MuirGlacier = 10,
116
+ /// Berlin
117
+ Berlin = 11,
118
+ /// London
119
+ London = 12,
120
+ /// Arrow Glacier
121
+ ArrowGlacier = 13,
122
+ /// Gray Glacier
123
+ GrayGlacier = 14,
124
+ /// Merge
125
+ Merge = 15,
126
+ /// Shanghai
127
+ Shanghai = 16,
128
+ /// Cancun
129
+ Cancun = 17,
130
+ /// Prague
131
+ Prague = 18,
132
+ }
133
+
134
+ impl FromStr for SpecId {
135
+ type Err = napi::Error;
136
+
137
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
138
+ match s {
139
+ edr_eth::l1::hardfork::name::FRONTIER => Ok(SpecId::Frontier),
140
+ edr_eth::l1::hardfork::name::FRONTIER_THAWING => Ok(SpecId::FrontierThawing),
141
+ edr_eth::l1::hardfork::name::HOMESTEAD => Ok(SpecId::Homestead),
142
+ edr_eth::l1::hardfork::name::DAO_FORK => Ok(SpecId::DaoFork),
143
+ edr_eth::l1::hardfork::name::TANGERINE => Ok(SpecId::Tangerine),
144
+ edr_eth::l1::hardfork::name::SPURIOUS_DRAGON => Ok(SpecId::SpuriousDragon),
145
+ edr_eth::l1::hardfork::name::BYZANTIUM => Ok(SpecId::Byzantium),
146
+ edr_eth::l1::hardfork::name::CONSTANTINOPLE => Ok(SpecId::Constantinople),
147
+ edr_eth::l1::hardfork::name::PETERSBURG => Ok(SpecId::Petersburg),
148
+ edr_eth::l1::hardfork::name::ISTANBUL => Ok(SpecId::Istanbul),
149
+ edr_eth::l1::hardfork::name::MUIR_GLACIER => Ok(SpecId::MuirGlacier),
150
+ edr_eth::l1::hardfork::name::BERLIN => Ok(SpecId::Berlin),
151
+ edr_eth::l1::hardfork::name::LONDON => Ok(SpecId::London),
152
+ edr_eth::l1::hardfork::name::ARROW_GLACIER => Ok(SpecId::ArrowGlacier),
153
+ edr_eth::l1::hardfork::name::GRAY_GLACIER => Ok(SpecId::GrayGlacier),
154
+ edr_eth::l1::hardfork::name::MERGE => Ok(SpecId::Merge),
155
+ edr_eth::l1::hardfork::name::SHANGHAI => Ok(SpecId::Shanghai),
156
+ edr_eth::l1::hardfork::name::CANCUN => Ok(SpecId::Cancun),
157
+ edr_eth::l1::hardfork::name::PRAGUE => Ok(SpecId::Prague),
158
+ _ => Err(napi::Error::new(
159
+ napi::Status::InvalidArg,
160
+ format!("The provided hardfork `{s}` is not supported."),
161
+ )),
162
+ }
163
+ }
164
+ }
165
+
166
+ impl From<SpecId> for edr_eth::l1::SpecId {
167
+ fn from(value: SpecId) -> Self {
168
+ match value {
169
+ SpecId::Frontier => edr_eth::l1::SpecId::FRONTIER,
170
+ SpecId::FrontierThawing => edr_eth::l1::SpecId::FRONTIER_THAWING,
171
+ SpecId::Homestead => edr_eth::l1::SpecId::HOMESTEAD,
172
+ SpecId::DaoFork => edr_eth::l1::SpecId::DAO_FORK,
173
+ SpecId::Tangerine => edr_eth::l1::SpecId::TANGERINE,
174
+ SpecId::SpuriousDragon => edr_eth::l1::SpecId::SPURIOUS_DRAGON,
175
+ SpecId::Byzantium => edr_eth::l1::SpecId::BYZANTIUM,
176
+ SpecId::Constantinople => edr_eth::l1::SpecId::CONSTANTINOPLE,
177
+ SpecId::Petersburg => edr_eth::l1::SpecId::PETERSBURG,
178
+ SpecId::Istanbul => edr_eth::l1::SpecId::ISTANBUL,
179
+ SpecId::MuirGlacier => edr_eth::l1::SpecId::MUIR_GLACIER,
180
+ SpecId::Berlin => edr_eth::l1::SpecId::BERLIN,
181
+ SpecId::London => edr_eth::l1::SpecId::LONDON,
182
+ SpecId::ArrowGlacier => edr_eth::l1::SpecId::ARROW_GLACIER,
183
+ SpecId::GrayGlacier => edr_eth::l1::SpecId::GRAY_GLACIER,
184
+ SpecId::Merge => edr_eth::l1::SpecId::MERGE,
185
+ SpecId::Shanghai => edr_eth::l1::SpecId::SHANGHAI,
186
+ SpecId::Cancun => edr_eth::l1::SpecId::CANCUN,
187
+ SpecId::Prague => edr_eth::l1::SpecId::PRAGUE,
188
+ }
189
+ }
190
+ }
191
+
192
+ /// Tries to parse the provided string to create a [`SpecId`] instance.
193
+ ///
194
+ /// Returns an error if the string does not match any known hardfork.
195
+ #[napi(catch_unwind)]
196
+ pub fn l1_hardfork_from_string(hardfork: String) -> napi::Result<SpecId> {
197
+ hardfork.parse()
198
+ }
199
+
200
+ #[napi(catch_unwind)]
201
+ pub fn l1_hardfork_to_string(harfork: SpecId) -> &'static str {
202
+ match harfork {
203
+ SpecId::Frontier => edr_eth::l1::hardfork::name::FRONTIER,
204
+ SpecId::FrontierThawing => edr_eth::l1::hardfork::name::FRONTIER_THAWING,
205
+ SpecId::Homestead => edr_eth::l1::hardfork::name::HOMESTEAD,
206
+ SpecId::DaoFork => edr_eth::l1::hardfork::name::DAO_FORK,
207
+ SpecId::Tangerine => edr_eth::l1::hardfork::name::TANGERINE,
208
+ SpecId::SpuriousDragon => edr_eth::l1::hardfork::name::SPURIOUS_DRAGON,
209
+ SpecId::Byzantium => edr_eth::l1::hardfork::name::BYZANTIUM,
210
+ SpecId::Constantinople => edr_eth::l1::hardfork::name::CONSTANTINOPLE,
211
+ SpecId::Petersburg => edr_eth::l1::hardfork::name::PETERSBURG,
212
+ SpecId::Istanbul => edr_eth::l1::hardfork::name::ISTANBUL,
213
+ SpecId::MuirGlacier => edr_eth::l1::hardfork::name::MUIR_GLACIER,
214
+ SpecId::Berlin => edr_eth::l1::hardfork::name::BERLIN,
215
+ SpecId::London => edr_eth::l1::hardfork::name::LONDON,
216
+ SpecId::ArrowGlacier => edr_eth::l1::hardfork::name::ARROW_GLACIER,
217
+ SpecId::GrayGlacier => edr_eth::l1::hardfork::name::GRAY_GLACIER,
218
+ SpecId::Merge => edr_eth::l1::hardfork::name::MERGE,
219
+ SpecId::Shanghai => edr_eth::l1::hardfork::name::SHANGHAI,
220
+ SpecId::Cancun => edr_eth::l1::hardfork::name::CANCUN,
221
+ SpecId::Prague => edr_eth::l1::hardfork::name::PRAGUE,
222
+ }
223
+ }
224
+
225
+ /// Returns the latest supported OP hardfork.
226
+ ///
227
+ /// The returned value will be updated after each network upgrade.
228
+ #[napi]
229
+ pub fn l1_hardfork_latest() -> SpecId {
230
+ SpecId::Prague
231
+ }
232
+
233
+ macro_rules! export_spec_id {
234
+ ($($variant:ident),*) => {
235
+ $(
236
+ #[napi]
237
+ pub const $variant: &str = edr_eth::l1::hardfork::name::$variant;
238
+ )*
239
+ };
240
+ }
241
+
242
+ export_spec_id!(
243
+ FRONTIER,
244
+ FRONTIER_THAWING,
245
+ HOMESTEAD,
246
+ DAO_FORK,
247
+ TANGERINE,
248
+ SPURIOUS_DRAGON,
249
+ BYZANTIUM,
250
+ CONSTANTINOPLE,
251
+ PETERSBURG,
252
+ ISTANBUL,
253
+ MUIR_GLACIER,
254
+ BERLIN,
255
+ LONDON,
256
+ ARROW_GLACIER,
257
+ GRAY_GLACIER,
258
+ MERGE,
259
+ SHANGHAI,
260
+ CANCUN,
261
+ PRAGUE
262
+ );
@@ -0,0 +1,425 @@
1
+ use std::{str::FromStr, sync::Arc};
2
+
3
+ use edr_eth::hex;
4
+ use edr_napi_core::{
5
+ logger::{self, Logger},
6
+ provider::{self, ProviderBuilder, SyncProviderFactory},
7
+ subscription,
8
+ };
9
+ use edr_op::{predeploys::GAS_PRICE_ORACLE_ADDRESS, OpChainSpec, OpSpecId};
10
+ use edr_solidity::contract_decoder::ContractDecoder;
11
+ use napi::bindgen_prelude::{BigInt, Uint8Array};
12
+ use napi_derive::napi;
13
+
14
+ use crate::{
15
+ account::{AccountOverride, StorageSlot},
16
+ provider::ProviderFactory,
17
+ };
18
+
19
+ pub struct OpProviderFactory;
20
+
21
+ impl SyncProviderFactory for OpProviderFactory {
22
+ fn create_provider_builder(
23
+ &self,
24
+ env: &napi::Env,
25
+ provider_config: provider::Config,
26
+ logger_config: logger::Config,
27
+ subscription_config: subscription::Config,
28
+ contract_decoder: Arc<ContractDecoder>,
29
+ ) -> napi::Result<Box<dyn provider::Builder>> {
30
+ let logger = Logger::<OpChainSpec>::new(logger_config, Arc::clone(&contract_decoder))?;
31
+
32
+ let provider_config = edr_provider::ProviderConfig::<OpSpecId>::try_from(provider_config)?;
33
+
34
+ let subscription_callback =
35
+ subscription::Callback::new(env, subscription_config.subscription_callback)?;
36
+
37
+ Ok(Box::new(ProviderBuilder::new(
38
+ contract_decoder,
39
+ Box::new(logger),
40
+ provider_config,
41
+ subscription_callback,
42
+ )))
43
+ }
44
+ }
45
+
46
+ /// Enumeration of supported OP hardforks.
47
+ #[napi]
48
+ pub enum OpHardfork {
49
+ Bedrock = 100,
50
+ Regolith = 101,
51
+ Canyon = 102,
52
+ Ecotone = 103,
53
+ Fjord = 104,
54
+ Granite = 105,
55
+ Holocene = 106,
56
+ Isthmus = 107,
57
+ }
58
+
59
+ impl From<OpHardfork> for OpSpecId {
60
+ fn from(hardfork: OpHardfork) -> Self {
61
+ match hardfork {
62
+ OpHardfork::Bedrock => OpSpecId::BEDROCK,
63
+ OpHardfork::Regolith => OpSpecId::REGOLITH,
64
+ OpHardfork::Canyon => OpSpecId::CANYON,
65
+ OpHardfork::Ecotone => OpSpecId::ECOTONE,
66
+ OpHardfork::Fjord => OpSpecId::FJORD,
67
+ OpHardfork::Granite => OpSpecId::GRANITE,
68
+ OpHardfork::Holocene => OpSpecId::HOLOCENE,
69
+ OpHardfork::Isthmus => OpSpecId::ISTHMUS,
70
+ }
71
+ }
72
+ }
73
+
74
+ impl FromStr for OpHardfork {
75
+ type Err = napi::Error;
76
+
77
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
78
+ match s {
79
+ edr_op::hardfork::name::BEDROCK => Ok(OpHardfork::Bedrock),
80
+ edr_op::hardfork::name::REGOLITH => Ok(OpHardfork::Regolith),
81
+ edr_op::hardfork::name::CANYON => Ok(OpHardfork::Canyon),
82
+ edr_op::hardfork::name::ECOTONE => Ok(OpHardfork::Ecotone),
83
+ edr_op::hardfork::name::FJORD => Ok(OpHardfork::Fjord),
84
+ edr_op::hardfork::name::GRANITE => Ok(OpHardfork::Granite),
85
+ edr_op::hardfork::name::HOLOCENE => Ok(OpHardfork::Holocene),
86
+ edr_op::hardfork::name::ISTHMUS => Ok(OpHardfork::Isthmus),
87
+ _ => Err(napi::Error::new(
88
+ napi::Status::InvalidArg,
89
+ format!("The provided OP hardfork `{s}` is not supported."),
90
+ )),
91
+ }
92
+ }
93
+ }
94
+
95
+ /// Tries to parse the provided string to create an [`OpHardfork`]
96
+ /// instance.
97
+ ///
98
+ /// Returns an error if the string does not match any known hardfork.
99
+ #[napi(catch_unwind)]
100
+ pub fn op_hardfork_from_string(hardfork: String) -> napi::Result<OpHardfork> {
101
+ hardfork.parse()
102
+ }
103
+
104
+ /// Returns the string representation of the provided OP hardfork.
105
+ #[napi(catch_unwind)]
106
+ pub fn op_hardfork_to_string(hardfork: OpHardfork) -> &'static str {
107
+ match hardfork {
108
+ OpHardfork::Bedrock => edr_op::hardfork::name::BEDROCK,
109
+ OpHardfork::Regolith => edr_op::hardfork::name::REGOLITH,
110
+ OpHardfork::Canyon => edr_op::hardfork::name::CANYON,
111
+ OpHardfork::Ecotone => edr_op::hardfork::name::ECOTONE,
112
+ OpHardfork::Fjord => edr_op::hardfork::name::FJORD,
113
+ OpHardfork::Granite => edr_op::hardfork::name::GRANITE,
114
+ OpHardfork::Holocene => edr_op::hardfork::name::HOLOCENE,
115
+ OpHardfork::Isthmus => edr_op::hardfork::name::ISTHMUS,
116
+ }
117
+ }
118
+
119
+ /// Returns the latest supported OP hardfork.
120
+ ///
121
+ /// The returned value will be updated after each network upgrade.
122
+ #[napi(catch_unwind)]
123
+ pub fn op_latest_hardfork() -> OpHardfork {
124
+ OpHardfork::Holocene
125
+ }
126
+
127
+ #[napi]
128
+ pub const OP_CHAIN_TYPE: &str = edr_op::CHAIN_TYPE;
129
+
130
+ #[napi(catch_unwind)]
131
+ pub fn op_genesis_state(hardfork: OpHardfork) -> Vec<AccountOverride> {
132
+ let l1_block_code = hex::decode(include_str!("../../data/op/predeploys/l1_block.txt"))
133
+ .expect("The bytecode for the L1Block predeploy should be a valid hex string");
134
+ let l1_block = AccountOverride {
135
+ address: hex!("4200000000000000000000000000000000000015").into(),
136
+ balance: Some(BigInt::from(0u64)),
137
+ nonce: Some(BigInt::from(0u64)),
138
+ code: Some(l1_block_code.into()),
139
+ storage: Some(vec![
140
+ StorageSlot {
141
+ index: BigInt::from(0u64),
142
+ // uint64 public number = 1
143
+ // uint64 public timestamp = 1
144
+ value: BigInt {
145
+ words: vec![
146
+ 0x0000000000000001_u64, // least significative
147
+ 0x0000000000000001_u64,
148
+ ],
149
+ sign_bit: false,
150
+ },
151
+ },
152
+ StorageSlot {
153
+ index: BigInt::from(1u64),
154
+ // uint256 baseFee = 10 gwei
155
+ value: BigInt::from(0x00000002540be400_u64),
156
+ },
157
+ StorageSlot {
158
+ index: BigInt::from(2u64),
159
+ // bytes32 hash = 0
160
+ value: BigInt::from(0u64),
161
+ },
162
+ StorageSlot {
163
+ index: BigInt::from(3u64),
164
+ // uint64 sequenceNumber = 0
165
+ // uint32 blobBaseFeeScalar = 1014213
166
+ // uint32 baseFeeScalar = 5227
167
+ value: BigInt {
168
+ words: vec![
169
+ 0x0000000000000000_u64, // least significative
170
+ 0x0000000000000000_u64,
171
+ 0x00000000000f79c5_u64,
172
+ 0x000000000000146b_u64,
173
+ ],
174
+ sign_bit: false,
175
+ },
176
+ },
177
+ StorageSlot {
178
+ index: BigInt::from(4u64),
179
+ // bytes32 batcherHash = 0
180
+ value: BigInt::from(0u64),
181
+ },
182
+ StorageSlot {
183
+ index: BigInt::from(5u64),
184
+ // uint256 l1FeeOverhead = 0
185
+ value: BigInt::from(0u64),
186
+ },
187
+ StorageSlot {
188
+ index: BigInt::from(6u64),
189
+ // uint256 l1FeeScalar = 0
190
+ value: BigInt::from(0u64),
191
+ },
192
+ StorageSlot {
193
+ index: BigInt::from(7u64),
194
+ // uint256 blobBaseFee = 10 gwei
195
+ value: BigInt::from(0x00000002540be400_u64),
196
+ },
197
+ ]),
198
+ };
199
+
200
+ /* The rest of the predeploys use a stubbed bytecode that reverts with a
201
+ message indicating that the predeploy is not supported. For each of
202
+ them, the Solidity code that generates the bytecode is:
203
+
204
+ // SPDX-License-Identifier: Unlicense
205
+ pragma solidity ^0.8.0;
206
+
207
+ contract NotSupported {
208
+ fallback() external payable {
209
+ revert("Predeploy <PredeployName> is not supported.");
210
+ }
211
+ }
212
+ */
213
+ let stubbed_predeploys_data = vec![
214
+ (
215
+ "LegacyMessagePasser",
216
+ hex!("4200000000000000000000000000000000000000"),
217
+ "0x60806040526040517f08c379a000000000000000000000000000000000000000000000000000000000815260040160349060a1565b60405180910390fd5b60006048602f8360bf565b91507f5072656465706c6f79204c65676163794d65737361676550617373657220697360008301527f206e6f7420737570706f727465642e00000000000000000000000000000000006020830152604082019050919050565b6000602082019050818103600083015260b881603d565b9050919050565b60008282526020820190509291505056fea26469706673582212206ba272e31c33ce6fe2612b534c5aa5ed8905e1bed8a757ff1a74cc06509a17f664736f6c63430008000033",
218
+ ),
219
+ (
220
+ "DeployerWhitelist",
221
+ hex!("4200000000000000000000000000000000000002"),
222
+ "0x60806040526040517f08c379a000000000000000000000000000000000000000000000000000000000815260040160349060a1565b60405180910390fd5b60006048602d8360bf565b91507f5072656465706c6f79204465706c6f79657257686974656c697374206973206e60008301527f6f7420737570706f727465642e000000000000000000000000000000000000006020830152604082019050919050565b6000602082019050818103600083015260b881603d565b9050919050565b60008282526020820190509291505056fea26469706673582212206af5fc0549e5db963a08cb2864cbbf5c4e27efb08219fc0e29bda83f84b121ac64736f6c63430008000033",
223
+ ),
224
+ (
225
+ "LegacyERC20ETH",
226
+ hex!("DeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000"),
227
+ "0x60806040526040517f08c379a000000000000000000000000000000000000000000000000000000000815260040160349060a1565b60405180910390fd5b60006048602a8360bf565b91507f5072656465706c6f79204c65676163794552433230455448206973206e6f742060008301527f737570706f727465642e000000000000000000000000000000000000000000006020830152604082019050919050565b6000602082019050818103600083015260b881603d565b9050919050565b60008282526020820190509291505056fea264697066735822122054e7f9d6c12400d5b4b67aed39be8c44a8b1461519e96a0e7764c69417239c7964736f6c63430008000033",
228
+ ),
229
+ (
230
+ "WETH9",
231
+ hex!("4200000000000000000000000000000000000006"),
232
+ "0x60806040526040517f08c379a000000000000000000000000000000000000000000000000000000000815260040160349060a1565b60405180910390fd5b6000604860218360bf565b91507f5072656465706c6f79205745544839206973206e6f7420737570706f7274656460008301527f2e000000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000602082019050818103600083015260b881603d565b9050919050565b60008282526020820190509291505056fea2646970667358221220860ec43d585e1b040780713555b6fc492d748c73586bdb8f2b9af441c4452dbf64736f6c63430008000033",
233
+ ),
234
+ (
235
+ "L2CrossDomainMessenger",
236
+ hex!("4200000000000000000000000000000000000007"),
237
+ "0x60806040526040517f08c379a000000000000000000000000000000000000000000000000000000000815260040160349060a1565b60405180910390fd5b6000604860328360bf565b91507f5072656465706c6f79204c3243726f7373446f6d61696e4d657373656e67657260008301527f206973206e6f7420737570706f727465642e00000000000000000000000000006020830152604082019050919050565b6000602082019050818103600083015260b881603d565b9050919050565b60008282526020820190509291505056fea26469706673582212200fadec69889de49a1a3a14d4e7e477e00921681e12650f510863d0077c16f58864736f6c63430008000033",
238
+ ),
239
+ (
240
+ "L2StandardBridge",
241
+ hex!("4200000000000000000000000000000000000010"),
242
+ "0x60806040526040517f08c379a000000000000000000000000000000000000000000000000000000000815260040160349060a1565b60405180910390fd5b60006048602c8360bf565b91507f5072656465706c6f79204c325374616e64617264427269646765206973206e6f60008301527f7420737570706f727465642e00000000000000000000000000000000000000006020830152604082019050919050565b6000602082019050818103600083015260b881603d565b9050919050565b60008282526020820190509291505056fea2646970667358221220ce5c24ee894b04d974b95cd204ab35f85906430ba6f49d1ea70d3d0c9c204cb764736f6c63430008000033",
243
+ ),
244
+ (
245
+ "SequencerFeeVault",
246
+ hex!("4200000000000000000000000000000000000011"),
247
+ "0x60806040526040517f08c379a000000000000000000000000000000000000000000000000000000000815260040160349060a1565b60405180910390fd5b60006048602d8360bf565b91507f5072656465706c6f792053657175656e6365724665655661756c74206973206e60008301527f6f7420737570706f727465642e000000000000000000000000000000000000006020830152604082019050919050565b6000602082019050818103600083015260b881603d565b9050919050565b60008282526020820190509291505056fea26469706673582212203990ed752a94bb02bd5162fef116c1b62079e8207c5164b3ae5a115f5cf0b31164736f6c63430008000033",
248
+ ),
249
+ (
250
+ "OptimismMintableERC20Factory",
251
+ hex!("4200000000000000000000000000000000000012"),
252
+ "0x60806040526040517f08c379a000000000000000000000000000000000000000000000000000000000815260040160349060a1565b60405180910390fd5b6000604860388360bf565b91507f5072656465706c6f79204f7074696d69736d4d696e7461626c6545524332304660008301527f6163746f7279206973206e6f7420737570706f727465642e00000000000000006020830152604082019050919050565b6000602082019050818103600083015260b881603d565b9050919050565b60008282526020820190509291505056fea2646970667358221220240605543d69b93641a24f1d153969c3969089a04a162fc9f18f95de926b385564736f6c63430008000033",
253
+ ),
254
+ (
255
+ "L1BlockNumber",
256
+ hex!("4200000000000000000000000000000000000013"),
257
+ "0x60806040526040517f08c379a000000000000000000000000000000000000000000000000000000000815260040160349060a1565b60405180910390fd5b6000604860298360bf565b91507f5072656465706c6f79204c31426c6f636b4e756d626572206973206e6f74207360008301527f7570706f727465642e00000000000000000000000000000000000000000000006020830152604082019050919050565b6000602082019050818103600083015260b881603d565b9050919050565b60008282526020820190509291505056fea264697066735822122099ba6da366313d162bab19a497fab2200808ddd24935b9f8be496c3622110b1164736f6c63430008000033",
258
+ ),
259
+ (
260
+ "GovernanceToken",
261
+ hex!("4200000000000000000000000000000000000042"),
262
+ "0x60806040526040517f08c379a000000000000000000000000000000000000000000000000000000000815260040160349060a1565b60405180910390fd5b60006048602b8360bf565b91507f5072656465706c6f7920476f7665726e616e6365546f6b656e206973206e6f7460008301527f20737570706f727465642e0000000000000000000000000000000000000000006020830152604082019050919050565b6000602082019050818103600083015260b881603d565b9050919050565b60008282526020820190509291505056fea26469706673582212205a22322e97c15d3a28eb86abac215ed31bcf6e0cf562e2679ce5fb3495953cfc64736f6c63430008000033",
263
+ ),
264
+ (
265
+ "L2ToL1MessagePasser",
266
+ hex!("4200000000000000000000000000000000000016"),
267
+ "0x60806040526040517f08c379a000000000000000000000000000000000000000000000000000000000815260040160349060a1565b60405180910390fd5b60006048602f8360bf565b91507f5072656465706c6f79204c32546f4c314d65737361676550617373657220697360008301527f206e6f7420737570706f727465642e00000000000000000000000000000000006020830152604082019050919050565b6000602082019050818103600083015260b881603d565b9050919050565b60008282526020820190509291505056fea26469706673582212205b2ed2ecc932d0e4a45e97ae7ac256e58848453ac06733b27890587962871a1864736f6c63430008000033",
268
+ ),
269
+ (
270
+ "L2ERC721Bridge",
271
+ hex!("4200000000000000000000000000000000000014"),
272
+ "0x60806040526040517f08c379a000000000000000000000000000000000000000000000000000000000815260040160349060a1565b60405180910390fd5b60006048602a8360bf565b91507f5072656465706c6f79204c32455243373231427269646765206973206e6f742060008301527f737570706f727465642e000000000000000000000000000000000000000000006020830152604082019050919050565b6000602082019050818103600083015260b881603d565b9050919050565b60008282526020820190509291505056fea26469706673582212203f9de306b34383b29e9dfb174fd424d7e11d31e8859d0e96a2aa3a46609e826c64736f6c63430008000033",
273
+ ),
274
+ (
275
+ "OptimismMintableERC721Factory",
276
+ hex!("4200000000000000000000000000000000000017"),
277
+ "0x60806040526040517f08c379a000000000000000000000000000000000000000000000000000000000815260040160349060a1565b60405180910390fd5b6000604860398360bf565b91507f5072656465706c6f79204f7074696d69736d4d696e7461626c6545524337323160008301527f466163746f7279206973206e6f7420737570706f727465642e000000000000006020830152604082019050919050565b6000602082019050818103600083015260b881603d565b9050919050565b60008282526020820190509291505056fea264697066735822122033131ae0c34f3246f5031971388431bd1dfb1b92d6b08d92a0a905911c1eeeeb64736f6c63430008000033",
278
+ ),
279
+ (
280
+ "ProxyAdmin",
281
+ hex!("4200000000000000000000000000000000000018"),
282
+ "0x60806040526040517f08c379a000000000000000000000000000000000000000000000000000000000815260040160349060a1565b60405180910390fd5b6000604860268360bf565b91507f5072656465706c6f792050726f787941646d696e206973206e6f74207375707060008301527f6f727465642e00000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000602082019050818103600083015260b881603d565b9050919050565b60008282526020820190509291505056fea2646970667358221220c7b191ff1b21c73fb6a26fd1e972d6844631a700b7a316ca2d9e04905af44dbb64736f6c63430008000033",
283
+ ),
284
+ (
285
+ "BaseFeeVault",
286
+ hex!("4200000000000000000000000000000000000019"),
287
+ "0x60806040526040517f08c379a000000000000000000000000000000000000000000000000000000000815260040160349060a1565b60405180910390fd5b6000604860288360bf565b91507f5072656465706c6f7920426173654665655661756c74206973206e6f7420737560008301527f70706f727465642e0000000000000000000000000000000000000000000000006020830152604082019050919050565b6000602082019050818103600083015260b881603d565b9050919050565b60008282526020820190509291505056fea2646970667358221220535ae2b8a6393c0be4de1dce095f5e17fc0c7a46b40ac7793db894328f1799e764736f6c63430008000033",
288
+ ),
289
+ (
290
+ "L1FeeVault",
291
+ hex!("420000000000000000000000000000000000001a"),
292
+ "0x60806040526040517f08c379a000000000000000000000000000000000000000000000000000000000815260040160349060a1565b60405180910390fd5b6000604860268360bf565b91507f5072656465706c6f79204c314665655661756c74206973206e6f74207375707060008301527f6f727465642e00000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000602082019050818103600083015260b881603d565b9050919050565b60008282526020820190509291505056fea2646970667358221220dac6ab093c79da782b6e98ec67c48758f6c1cb80cba58e080c114a9b8c93befc64736f6c63430008000033",
293
+ ),
294
+ (
295
+ "SchemaRegistry",
296
+ hex!("4200000000000000000000000000000000000020"),
297
+ "0x60806040526040517f08c379a000000000000000000000000000000000000000000000000000000000815260040160349060a1565b60405180910390fd5b60006048602a8360bf565b91507f5072656465706c6f7920536368656d615265676973747279206973206e6f742060008301527f737570706f727465642e000000000000000000000000000000000000000000006020830152604082019050919050565b6000602082019050818103600083015260b881603d565b9050919050565b60008282526020820190509291505056fea2646970667358221220b3daf5355920b581943cabb92a7cc67123467fdd1b054cb0c5f0e587c08da1be64736f6c63430008000033",
298
+ ),
299
+ (
300
+ "EAS",
301
+ hex!("4200000000000000000000000000000000000021"),
302
+ "0x60806040526040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401603490607b565b60405180910390fd5b60006048601f836099565b91507f5072656465706c6f7920454153206973206e6f7420737570706f727465642e006000830152602082019050919050565b60006020820190508181036000830152609281603d565b9050919050565b60008282526020820190509291505056fea2646970667358221220afa6c1aa54a8b3f4f979e1297db5838a94353f3b77b5ecc164da19db26ea89f564736f6c63430008000033",
303
+ ),
304
+ ];
305
+
306
+ let stubbed_predeploys = stubbed_predeploys_data
307
+ .iter()
308
+ .map(|(name, address, code)| AccountOverride {
309
+ address: address.into(),
310
+ balance: Some(BigInt::from(0u64)),
311
+ nonce: Some(BigInt::from(0u64)),
312
+ code: Some(
313
+ hex::decode(code)
314
+ .unwrap_or_else(|e| panic!("The bytecode for the {name} predeploy should be a valid hex string, got error: {e}"))
315
+ .into(),
316
+ ),
317
+ storage: Some(vec![]),
318
+ });
319
+
320
+ let predeploys = vec![gas_price_oracle_override(hardfork.into()), l1_block];
321
+
322
+ predeploys.into_iter().chain(stubbed_predeploys).collect()
323
+ }
324
+
325
+ #[napi(catch_unwind)]
326
+ pub fn op_provider_factory() -> ProviderFactory {
327
+ let factory: Arc<dyn SyncProviderFactory> = Arc::new(OpProviderFactory);
328
+ factory.into()
329
+ }
330
+
331
+ fn gas_price_oracle_override(hardfork: OpSpecId) -> AccountOverride {
332
+ if hardfork >= OpSpecId::ISTHMUS {
333
+ gas_price_oracle_isthmus()
334
+ } else if hardfork >= OpSpecId::FJORD {
335
+ gas_price_oracle_fjord()
336
+ } else {
337
+ gas_price_oracle_ecotone()
338
+ }
339
+ }
340
+
341
+ fn gas_price_oracle_ecotone() -> AccountOverride {
342
+ let gas_price_oracle_code = hex::decode(include_str!(
343
+ "../../data/op/predeploys/gas_price_oracle/ecotone.txt"
344
+ ))
345
+ .expect("The bytecode for the GasPriceOracle predeploy should be a valid hex string");
346
+
347
+ AccountOverride {
348
+ address: Uint8Array::with_data_copied(GAS_PRICE_ORACLE_ADDRESS),
349
+ balance: None,
350
+ nonce: None,
351
+ code: Some(gas_price_oracle_code.into()),
352
+ storage: Some(vec![StorageSlot {
353
+ index: BigInt::from(0u64),
354
+ // bool isEcotone = true
355
+ value: BigInt::from(
356
+ 0x0000000000000000000000000000000000000000000000000000000000000001u64,
357
+ ),
358
+ }]),
359
+ }
360
+ }
361
+
362
+ fn gas_price_oracle_fjord() -> AccountOverride {
363
+ let gas_price_oracle_code = hex::decode(include_str!(
364
+ "../../data/op/predeploys/gas_price_oracle/fjord.txt"
365
+ ))
366
+ .expect("The bytecode for the GasPriceOracle predeploy should be a valid hex string");
367
+
368
+ AccountOverride {
369
+ address: Uint8Array::with_data_copied(GAS_PRICE_ORACLE_ADDRESS),
370
+ balance: None,
371
+ nonce: None,
372
+ code: Some(gas_price_oracle_code.into()),
373
+ storage: Some(vec![StorageSlot {
374
+ index: BigInt::from(0u64),
375
+ // bool isEcotone = true
376
+ // bool isFjord = true
377
+ value: BigInt::from(
378
+ 0x0000000000000000000000000000000000000000000000000000000000000101u64,
379
+ ),
380
+ }]),
381
+ }
382
+ }
383
+
384
+ fn gas_price_oracle_isthmus() -> AccountOverride {
385
+ let gas_price_oracle_code = hex::decode(include_str!(
386
+ "../../data/op/predeploys/gas_price_oracle/isthmus.txt"
387
+ ))
388
+ .expect("The bytecode for the GasPriceOracle predeploy should be a valid hex string");
389
+
390
+ AccountOverride {
391
+ address: Uint8Array::with_data_copied(GAS_PRICE_ORACLE_ADDRESS),
392
+ balance: None,
393
+ nonce: None,
394
+ code: Some(gas_price_oracle_code.into()),
395
+ storage: Some(vec![StorageSlot {
396
+ index: BigInt::from(0u64),
397
+ // bool isEcotone = true
398
+ // bool isFjord = true
399
+ // bool isIsthmus = true
400
+ value: BigInt::from(
401
+ 0x0000000000000000000000000000000000000000000000000000000000010101u64,
402
+ ),
403
+ }]),
404
+ }
405
+ }
406
+
407
+ macro_rules! export_spec_id {
408
+ ($($variant:ident,)*) => {
409
+ $(
410
+ #[napi]
411
+ pub const $variant: &str = edr_op::hardfork::name::$variant;
412
+ )*
413
+ };
414
+ }
415
+
416
+ export_spec_id! {
417
+ BEDROCK,
418
+ REGOLITH,
419
+ CANYON,
420
+ ECOTONE,
421
+ FJORD,
422
+ GRANITE,
423
+ HOLOCENE,
424
+ ISTHMUS,
425
+ }