@nomicfoundation/edr 0.12.0-alpha.0 → 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.
- package/Cargo.toml +47 -16
- package/LICENSE +5 -1
- package/index.d.ts +773 -104
- package/index.js +31 -1
- package/package.json +20 -17
- package/src/account.rs +102 -55
- package/src/block.rs +2 -103
- package/src/call_override.rs +8 -8
- package/src/cast.rs +7 -29
- package/src/chains/generic.rs +1 -1
- package/src/chains/l1.rs +20 -18
- package/src/chains/op.rs +95 -38
- package/src/config.rs +305 -161
- package/src/context.rs +260 -21
- package/src/debug_trace.rs +2 -2
- package/src/instrument.rs +109 -0
- package/src/lib.rs +10 -0
- package/src/log.rs +12 -14
- package/src/logger.rs +28 -30
- package/src/mock.rs +68 -0
- package/src/precompile.rs +50 -0
- package/src/provider/response.rs +8 -5
- package/src/provider.rs +14 -8
- package/src/result.rs +18 -27
- package/src/scenarios.rs +2 -2
- package/src/serde.rs +57 -0
- package/src/solidity_tests/artifact.rs +184 -0
- package/src/solidity_tests/config.rs +725 -0
- package/src/solidity_tests/factory.rs +22 -0
- package/src/solidity_tests/l1.rs +68 -0
- package/src/solidity_tests/op.rs +69 -0
- package/src/solidity_tests/runner.rs +51 -0
- package/src/solidity_tests/test_results.rs +668 -0
- package/src/solidity_tests.rs +56 -0
- package/src/subscription.rs +1 -1
- package/src/trace/debug.rs +1 -1
- package/src/trace/exit.rs +4 -4
- package/src/trace/library_utils.rs +7 -2
- package/src/trace/return_data.rs +10 -10
- package/src/trace/solidity_stack_trace.rs +7 -5
- package/src/trace.rs +29 -38
- package/src/withdrawal.rs +3 -3
package/src/config.rs
CHANGED
|
@@ -1,40 +1,66 @@
|
|
|
1
|
+
use core::fmt::{Debug, Display};
|
|
1
2
|
use std::{
|
|
2
3
|
num::NonZeroU64,
|
|
4
|
+
path::PathBuf,
|
|
3
5
|
time::{Duration, SystemTime},
|
|
4
6
|
};
|
|
5
7
|
|
|
6
|
-
use
|
|
8
|
+
use edr_coverage::reporter::SyncOnCollectedCoverageCallback;
|
|
9
|
+
use edr_eth::{
|
|
10
|
+
signature::{secret_key_from_str, SecretKey},
|
|
11
|
+
Bytes, HashMap, HashSet,
|
|
12
|
+
};
|
|
7
13
|
use napi::{
|
|
8
|
-
|
|
9
|
-
|
|
14
|
+
bindgen_prelude::{BigInt, Promise, Reference, Uint8Array},
|
|
15
|
+
threadsafe_function::{
|
|
16
|
+
ErrorStrategy, ThreadSafeCallContext, ThreadsafeFunction, ThreadsafeFunctionCallMode,
|
|
17
|
+
},
|
|
18
|
+
tokio::runtime,
|
|
19
|
+
Either, JsFunction, JsString, JsStringUtf8,
|
|
10
20
|
};
|
|
11
21
|
use napi_derive::napi;
|
|
12
22
|
|
|
13
|
-
use crate::{
|
|
14
|
-
account::{Account, OwnedAccount, StorageSlot},
|
|
15
|
-
block::BlobGas,
|
|
16
|
-
cast::TryCast,
|
|
17
|
-
};
|
|
23
|
+
use crate::{account::AccountOverride, block::BlobGas, cast::TryCast, precompile::Precompile};
|
|
18
24
|
|
|
19
|
-
///
|
|
25
|
+
/// Specification of a chain with possible overrides.
|
|
20
26
|
#[napi(object)]
|
|
21
|
-
pub struct
|
|
27
|
+
pub struct ChainOverride {
|
|
22
28
|
/// The chain ID
|
|
23
29
|
pub chain_id: BigInt,
|
|
24
|
-
/// The chain's
|
|
25
|
-
pub
|
|
30
|
+
/// The chain's name
|
|
31
|
+
pub name: String,
|
|
32
|
+
/// If present, overrides for the chain's supported hardforks
|
|
33
|
+
pub hardfork_activation_overrides: Option<Vec<HardforkActivation>>,
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/// Configuration for a code coverage reporter.
|
|
37
|
+
#[napi(object)]
|
|
38
|
+
pub struct CodeCoverageConfig {
|
|
39
|
+
/// The callback to be called when coverage has been collected.
|
|
40
|
+
///
|
|
41
|
+
/// The callback receives an array of unique coverage hit markers (i.e. no
|
|
42
|
+
/// repetition) per transaction.
|
|
43
|
+
///
|
|
44
|
+
/// Exceptions thrown in the callback will be propagated to the original
|
|
45
|
+
/// caller.
|
|
46
|
+
#[napi(ts_type = "(coverageHits: Uint8Array[]) => Promise<void>")]
|
|
47
|
+
pub on_collected_coverage_callback: JsFunction,
|
|
26
48
|
}
|
|
27
49
|
|
|
28
50
|
/// Configuration for forking a blockchain
|
|
29
51
|
#[napi(object)]
|
|
30
52
|
pub struct ForkConfig {
|
|
31
|
-
/// The URL of the JSON-RPC endpoint to fork from
|
|
32
|
-
pub json_rpc_url: String,
|
|
33
53
|
/// The block number to fork from. If not provided, the latest safe block is
|
|
34
54
|
/// used.
|
|
35
55
|
pub block_number: Option<BigInt>,
|
|
56
|
+
/// The directory to cache remote JSON-RPC responses
|
|
57
|
+
pub cache_dir: Option<String>,
|
|
58
|
+
/// Overrides for the configuration of chains.
|
|
59
|
+
pub chain_overrides: Option<Vec<ChainOverride>>,
|
|
36
60
|
/// The HTTP headers to use when making requests to the JSON-RPC endpoint
|
|
37
61
|
pub http_headers: Option<Vec<HttpHeader>>,
|
|
62
|
+
/// The URL of the JSON-RPC endpoint to fork from
|
|
63
|
+
pub url: String,
|
|
38
64
|
}
|
|
39
65
|
|
|
40
66
|
#[napi(object)]
|
|
@@ -46,10 +72,22 @@ pub struct HttpHeader {
|
|
|
46
72
|
/// Configuration for a hardfork activation
|
|
47
73
|
#[napi(object)]
|
|
48
74
|
pub struct HardforkActivation {
|
|
75
|
+
/// The condition for the hardfork activation
|
|
76
|
+
pub condition: Either<HardforkActivationByBlockNumber, HardforkActivationByTimestamp>,
|
|
77
|
+
/// The activated hardfork
|
|
78
|
+
pub hardfork: String,
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
#[napi(object)]
|
|
82
|
+
pub struct HardforkActivationByBlockNumber {
|
|
49
83
|
/// The block number at which the hardfork is activated
|
|
50
84
|
pub block_number: BigInt,
|
|
51
|
-
|
|
52
|
-
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
#[napi(object)]
|
|
88
|
+
pub struct HardforkActivationByTimestamp {
|
|
89
|
+
/// The timestamp at which the hardfork is activated
|
|
90
|
+
pub timestamp: BigInt,
|
|
53
91
|
}
|
|
54
92
|
|
|
55
93
|
#[napi(string_enum)]
|
|
@@ -81,6 +119,13 @@ pub struct MiningConfig {
|
|
|
81
119
|
pub mem_pool: MemPoolConfig,
|
|
82
120
|
}
|
|
83
121
|
|
|
122
|
+
/// Configuration for runtime observability.
|
|
123
|
+
#[napi(object)]
|
|
124
|
+
pub struct ObservabilityConfig {
|
|
125
|
+
/// If present, configures runtime observability to collect code coverage.
|
|
126
|
+
pub code_coverage: Option<CodeCoverageConfig>,
|
|
127
|
+
}
|
|
128
|
+
|
|
84
129
|
/// Configuration for a provider
|
|
85
130
|
#[napi(object)]
|
|
86
131
|
pub struct ProviderConfig {
|
|
@@ -94,21 +139,15 @@ pub struct ProviderConfig {
|
|
|
94
139
|
pub bail_on_transaction_failure: bool,
|
|
95
140
|
/// The gas limit of each block
|
|
96
141
|
pub block_gas_limit: BigInt,
|
|
97
|
-
/// The directory to cache remote JSON-RPC responses
|
|
98
|
-
pub cache_dir: Option<String>,
|
|
99
142
|
/// The chain ID of the blockchain
|
|
100
143
|
pub chain_id: BigInt,
|
|
101
|
-
/// The configuration for chains
|
|
102
|
-
pub chains: Vec<ChainConfig>,
|
|
103
144
|
/// The address of the coinbase
|
|
104
|
-
pub coinbase:
|
|
105
|
-
/// Enables RIP-7212
|
|
106
|
-
pub enable_rip_7212: bool,
|
|
145
|
+
pub coinbase: Uint8Array,
|
|
107
146
|
/// The configuration for forking a blockchain. If not provided, a local
|
|
108
147
|
/// blockchain will be created
|
|
109
148
|
pub fork: Option<ForkConfig>,
|
|
110
149
|
/// The genesis state of the blockchain
|
|
111
|
-
pub genesis_state: Vec<
|
|
150
|
+
pub genesis_state: Vec<AccountOverride>,
|
|
112
151
|
/// The hardfork of the blockchain
|
|
113
152
|
pub hardfork: String,
|
|
114
153
|
/// The initial base fee per gas of the blockchain. Required for EIP-1559
|
|
@@ -120,22 +159,93 @@ pub struct ProviderConfig {
|
|
|
120
159
|
pub initial_date: Option<BigInt>,
|
|
121
160
|
/// The initial parent beacon block root of the blockchain. Required for
|
|
122
161
|
/// EIP-4788
|
|
123
|
-
pub initial_parent_beacon_block_root: Option<
|
|
162
|
+
pub initial_parent_beacon_block_root: Option<Uint8Array>,
|
|
124
163
|
/// The minimum gas price of the next block.
|
|
125
164
|
pub min_gas_price: BigInt,
|
|
126
165
|
/// The configuration for the miner
|
|
127
166
|
pub mining: MiningConfig,
|
|
128
167
|
/// The network ID of the blockchain
|
|
129
168
|
pub network_id: BigInt,
|
|
130
|
-
///
|
|
131
|
-
pub
|
|
169
|
+
/// The configuration for the provider's observability
|
|
170
|
+
pub observability: ObservabilityConfig,
|
|
171
|
+
// Using JsString here as it doesn't have `Debug`, `Display` and `Serialize` implementation
|
|
172
|
+
// which prevents accidentally leaking the secret keys to error messages and logs.
|
|
173
|
+
/// Secret keys of owned accounts
|
|
174
|
+
pub owned_accounts: Vec<JsString>,
|
|
175
|
+
/// Overrides for precompiles
|
|
176
|
+
pub precompile_overrides: Vec<Reference<Precompile>>,
|
|
132
177
|
}
|
|
133
178
|
|
|
134
|
-
impl TryFrom<ForkConfig> for edr_provider::
|
|
179
|
+
impl TryFrom<ForkConfig> for edr_provider::ForkConfig<String> {
|
|
135
180
|
type Error = napi::Error;
|
|
136
181
|
|
|
137
182
|
fn try_from(value: ForkConfig) -> Result<Self, Self::Error> {
|
|
138
183
|
let block_number: Option<u64> = value.block_number.map(TryCast::try_cast).transpose()?;
|
|
184
|
+
|
|
185
|
+
let cache_dir = PathBuf::from(
|
|
186
|
+
value
|
|
187
|
+
.cache_dir
|
|
188
|
+
.unwrap_or(edr_defaults::CACHE_DIR.to_owned()),
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
let chain_overrides = value
|
|
192
|
+
.chain_overrides
|
|
193
|
+
.map(|chain_overrides| {
|
|
194
|
+
chain_overrides
|
|
195
|
+
.into_iter()
|
|
196
|
+
.map(
|
|
197
|
+
|ChainOverride {
|
|
198
|
+
chain_id,
|
|
199
|
+
name,
|
|
200
|
+
hardfork_activation_overrides,
|
|
201
|
+
}| {
|
|
202
|
+
let hardfork_activation_overrides =
|
|
203
|
+
hardfork_activation_overrides
|
|
204
|
+
.map(|hardfork_activations| {
|
|
205
|
+
hardfork_activations
|
|
206
|
+
.into_iter()
|
|
207
|
+
.map(
|
|
208
|
+
|HardforkActivation {
|
|
209
|
+
condition,
|
|
210
|
+
hardfork,
|
|
211
|
+
}| {
|
|
212
|
+
let condition = match condition {
|
|
213
|
+
Either::A(HardforkActivationByBlockNumber {
|
|
214
|
+
block_number,
|
|
215
|
+
}) => edr_evm::hardfork::ForkCondition::Block(
|
|
216
|
+
block_number.try_cast()?,
|
|
217
|
+
),
|
|
218
|
+
Either::B(HardforkActivationByTimestamp {
|
|
219
|
+
timestamp,
|
|
220
|
+
}) => edr_evm::hardfork::ForkCondition::Timestamp(
|
|
221
|
+
timestamp.try_cast()?,
|
|
222
|
+
),
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
Ok(edr_evm::hardfork::Activation {
|
|
226
|
+
condition,
|
|
227
|
+
hardfork,
|
|
228
|
+
})
|
|
229
|
+
},
|
|
230
|
+
)
|
|
231
|
+
.collect::<napi::Result<Vec<_>>>()
|
|
232
|
+
.map(edr_evm::hardfork::Activations::new)
|
|
233
|
+
})
|
|
234
|
+
.transpose()?;
|
|
235
|
+
|
|
236
|
+
let chain_config = edr_evm::hardfork::ChainOverride {
|
|
237
|
+
name,
|
|
238
|
+
hardfork_activation_overrides,
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
let chain_id = chain_id.try_cast()?;
|
|
242
|
+
Ok((chain_id, chain_config))
|
|
243
|
+
},
|
|
244
|
+
)
|
|
245
|
+
.collect::<napi::Result<_>>()
|
|
246
|
+
})
|
|
247
|
+
.transpose()?;
|
|
248
|
+
|
|
139
249
|
let http_headers = value.http_headers.map(|http_headers| {
|
|
140
250
|
http_headers
|
|
141
251
|
.into_iter()
|
|
@@ -144,9 +254,11 @@ impl TryFrom<ForkConfig> for edr_provider::hardhat_rpc_types::ForkConfig {
|
|
|
144
254
|
});
|
|
145
255
|
|
|
146
256
|
Ok(Self {
|
|
147
|
-
json_rpc_url: value.json_rpc_url,
|
|
148
257
|
block_number,
|
|
258
|
+
cache_dir,
|
|
259
|
+
chain_overrides: chain_overrides.unwrap_or_default(),
|
|
149
260
|
http_headers,
|
|
261
|
+
url: value.url,
|
|
150
262
|
})
|
|
151
263
|
}
|
|
152
264
|
}
|
|
@@ -207,133 +319,178 @@ impl TryFrom<MiningConfig> for edr_provider::MiningConfig {
|
|
|
207
319
|
}
|
|
208
320
|
}
|
|
209
321
|
|
|
210
|
-
impl
|
|
211
|
-
|
|
322
|
+
impl ObservabilityConfig {
|
|
323
|
+
/// Resolves the instance, converting it to a
|
|
324
|
+
/// [`edr_provider::observability::Config`].
|
|
325
|
+
pub fn resolve(
|
|
326
|
+
self,
|
|
327
|
+
env: &napi::Env,
|
|
328
|
+
runtime: runtime::Handle,
|
|
329
|
+
) -> napi::Result<edr_provider::observability::Config> {
|
|
330
|
+
let on_collected_coverage_fn = self
|
|
331
|
+
.code_coverage
|
|
332
|
+
.map(
|
|
333
|
+
|code_coverage| -> napi::Result<Box<dyn SyncOnCollectedCoverageCallback>> {
|
|
334
|
+
let mut on_collected_coverage_callback: ThreadsafeFunction<
|
|
335
|
+
_,
|
|
336
|
+
ErrorStrategy::Fatal,
|
|
337
|
+
> = code_coverage
|
|
338
|
+
.on_collected_coverage_callback
|
|
339
|
+
.create_threadsafe_function(
|
|
340
|
+
0,
|
|
341
|
+
|ctx: ThreadSafeCallContext<HashSet<Bytes>>| {
|
|
342
|
+
let hits = ctx
|
|
343
|
+
.env
|
|
344
|
+
.create_array_with_length(ctx.value.len())
|
|
345
|
+
.and_then(|mut hits| {
|
|
346
|
+
for (idx, hit) in ctx.value.into_iter().enumerate() {
|
|
347
|
+
ctx.env
|
|
348
|
+
.create_buffer_with_data(hit.to_vec())
|
|
349
|
+
.and_then(|hit| {
|
|
350
|
+
let idx = u32::try_from(idx).unwrap_or_else(|_| panic!("Number of hits should not exceed '{}'",
|
|
351
|
+
u32::MAX));
|
|
352
|
+
|
|
353
|
+
hits.set_element(idx, hit.into_raw())
|
|
354
|
+
})?;
|
|
355
|
+
}
|
|
356
|
+
Ok(hits)
|
|
357
|
+
})?;
|
|
358
|
+
|
|
359
|
+
Ok(vec![hits])
|
|
360
|
+
},
|
|
361
|
+
)?;
|
|
362
|
+
|
|
363
|
+
// Maintain a weak reference to the function to avoid blocking the event loop
|
|
364
|
+
// from exiting.
|
|
365
|
+
on_collected_coverage_callback.unref(env)?;
|
|
366
|
+
|
|
367
|
+
let on_collected_coverage_fn: Box<dyn SyncOnCollectedCoverageCallback> =
|
|
368
|
+
Box::new(move |hits| {
|
|
369
|
+
let runtime = runtime.clone();
|
|
370
|
+
|
|
371
|
+
let (sender, receiver) = std::sync::mpsc::channel();
|
|
372
|
+
|
|
373
|
+
let status = on_collected_coverage_callback
|
|
374
|
+
.call_with_return_value(hits, ThreadsafeFunctionCallMode::Blocking, move |result: Promise<()>| {
|
|
375
|
+
// We spawn a background task to handle the async callback
|
|
376
|
+
runtime.spawn(async move {
|
|
377
|
+
let result = result.await;
|
|
378
|
+
sender.send(result).map_err(|_error| {
|
|
379
|
+
napi::Error::new(
|
|
380
|
+
napi::Status::GenericFailure,
|
|
381
|
+
"Failed to send result from on_collected_coverage_callback",
|
|
382
|
+
)
|
|
383
|
+
})
|
|
384
|
+
});
|
|
385
|
+
Ok(())
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
let () = receiver.recv().expect("Receive can only fail if the channel is closed")?;
|
|
389
|
+
|
|
390
|
+
assert_eq!(status, napi::Status::Ok);
|
|
391
|
+
|
|
392
|
+
Ok(())
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
Ok(on_collected_coverage_fn)
|
|
396
|
+
},
|
|
397
|
+
)
|
|
398
|
+
.transpose()?;
|
|
399
|
+
|
|
400
|
+
Ok(edr_provider::observability::Config {
|
|
401
|
+
on_collected_coverage_fn,
|
|
402
|
+
..edr_provider::observability::Config::default()
|
|
403
|
+
})
|
|
404
|
+
}
|
|
405
|
+
}
|
|
212
406
|
|
|
213
|
-
|
|
214
|
-
|
|
407
|
+
impl ProviderConfig {
|
|
408
|
+
/// Resolves the instance to a [`edr_napi_core::provider::Config`].
|
|
409
|
+
pub fn resolve(
|
|
410
|
+
self,
|
|
411
|
+
env: &napi::Env,
|
|
412
|
+
runtime: runtime::Handle,
|
|
413
|
+
) -> napi::Result<edr_napi_core::provider::Config> {
|
|
414
|
+
let owned_accounts = self
|
|
215
415
|
.owned_accounts
|
|
216
416
|
.into_iter()
|
|
217
|
-
.map(
|
|
417
|
+
.map(|secret_key| {
|
|
418
|
+
// This is the only place in production code where it's allowed to use
|
|
419
|
+
// `DangerousSecretKeyStr`.
|
|
420
|
+
#[allow(deprecated)]
|
|
421
|
+
use edr_eth::signature::DangerousSecretKeyStr;
|
|
422
|
+
|
|
423
|
+
static_assertions::assert_not_impl_all!(JsString: Debug, Display, serde::Serialize);
|
|
424
|
+
static_assertions::assert_not_impl_all!(JsStringUtf8: Debug, Display, serde::Serialize);
|
|
425
|
+
// `SecretKey` has `Debug` implementation, but it's opaque (only shows the
|
|
426
|
+
// type name)
|
|
427
|
+
static_assertions::assert_not_impl_any!(SecretKey: Display, serde::Serialize);
|
|
428
|
+
|
|
429
|
+
let secret_key = secret_key.into_utf8()?;
|
|
430
|
+
// This is the only place in production code where it's allowed to use
|
|
431
|
+
// `DangerousSecretKeyStr`.
|
|
432
|
+
#[allow(deprecated)]
|
|
433
|
+
let secret_key_str = DangerousSecretKeyStr(secret_key.as_str()?);
|
|
434
|
+
let secret_key: SecretKey = secret_key_from_str(secret_key_str)
|
|
435
|
+
.map_err(|error| napi::Error::new(napi::Status::InvalidArg, error))?;
|
|
436
|
+
|
|
437
|
+
Ok(secret_key)
|
|
438
|
+
})
|
|
218
439
|
.collect::<napi::Result<Vec<_>>>()?;
|
|
219
440
|
|
|
220
441
|
let block_gas_limit =
|
|
221
|
-
NonZeroU64::new(
|
|
442
|
+
NonZeroU64::new(self.block_gas_limit.try_cast()?).ok_or_else(|| {
|
|
222
443
|
napi::Error::new(
|
|
223
444
|
napi::Status::GenericFailure,
|
|
224
445
|
"Block gas limit must be greater than 0",
|
|
225
446
|
)
|
|
226
447
|
})?;
|
|
227
448
|
|
|
228
|
-
let
|
|
229
|
-
.chains
|
|
230
|
-
.into_iter()
|
|
231
|
-
.map(
|
|
232
|
-
|ChainConfig {
|
|
233
|
-
chain_id,
|
|
234
|
-
hardforks,
|
|
235
|
-
}| {
|
|
236
|
-
let hardforks = hardforks
|
|
237
|
-
.into_iter()
|
|
238
|
-
.map(
|
|
239
|
-
|HardforkActivation {
|
|
240
|
-
block_number,
|
|
241
|
-
spec_id: hardfork,
|
|
242
|
-
}| {
|
|
243
|
-
let block_number = block_number.try_cast()?;
|
|
244
|
-
|
|
245
|
-
Ok(edr_napi_core::provider::HardforkActivation {
|
|
246
|
-
block_number,
|
|
247
|
-
hardfork,
|
|
248
|
-
})
|
|
249
|
-
},
|
|
250
|
-
)
|
|
251
|
-
.collect::<napi::Result<Vec<_>>>()?;
|
|
252
|
-
|
|
253
|
-
let chain_id = chain_id.try_cast()?;
|
|
254
|
-
Ok((chain_id, hardforks))
|
|
255
|
-
},
|
|
256
|
-
)
|
|
257
|
-
.collect::<napi::Result<_>>()?;
|
|
258
|
-
|
|
259
|
-
let genesis_state = value
|
|
449
|
+
let genesis_state = self
|
|
260
450
|
.genesis_state
|
|
261
451
|
.into_iter()
|
|
262
|
-
.map(
|
|
263
|
-
|
|
264
|
-
address,
|
|
265
|
-
balance,
|
|
266
|
-
nonce,
|
|
267
|
-
code,
|
|
268
|
-
storage,
|
|
269
|
-
}| {
|
|
270
|
-
let code: Option<edr_eth::Bytecode> =
|
|
271
|
-
code.map(TryCast::try_cast).transpose()?;
|
|
272
|
-
|
|
273
|
-
let code_hash = code
|
|
274
|
-
.as_ref()
|
|
275
|
-
.map_or(KECCAK_EMPTY, edr_eth::Bytecode::hash_slow);
|
|
276
|
-
|
|
277
|
-
let info = edr_eth::account::AccountInfo {
|
|
278
|
-
balance: balance.try_cast()?,
|
|
279
|
-
nonce: nonce.try_cast()?,
|
|
280
|
-
code_hash,
|
|
281
|
-
code,
|
|
282
|
-
};
|
|
283
|
-
|
|
284
|
-
let storage = storage
|
|
285
|
-
.into_iter()
|
|
286
|
-
.map(|StorageSlot { index, value }| {
|
|
287
|
-
let value = value.try_cast()?;
|
|
288
|
-
let slot = edr_evm::state::EvmStorageSlot::new(value);
|
|
289
|
-
|
|
290
|
-
let index: edr_eth::U256 = index.try_cast()?;
|
|
291
|
-
Ok((index, slot))
|
|
292
|
-
})
|
|
293
|
-
.collect::<napi::Result<_>>()?;
|
|
294
|
-
|
|
295
|
-
let address: edr_eth::Address = address.try_cast()?;
|
|
296
|
-
let account = edr_provider::config::Account { info, storage };
|
|
452
|
+
.map(TryInto::try_into)
|
|
453
|
+
.collect::<napi::Result<HashMap<edr_eth::Address, edr_provider::AccountOverride>>>()?;
|
|
297
454
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
)
|
|
301
|
-
.
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
allow_blocks_with_same_timestamp:
|
|
306
|
-
allow_unlimited_contract_size:
|
|
307
|
-
bail_on_call_failure:
|
|
308
|
-
bail_on_transaction_failure:
|
|
455
|
+
let precompile_overrides = self
|
|
456
|
+
.precompile_overrides
|
|
457
|
+
.into_iter()
|
|
458
|
+
.map(|precompile| precompile.to_tuple())
|
|
459
|
+
.collect();
|
|
460
|
+
|
|
461
|
+
Ok(edr_napi_core::provider::Config {
|
|
462
|
+
allow_blocks_with_same_timestamp: self.allow_blocks_with_same_timestamp,
|
|
463
|
+
allow_unlimited_contract_size: self.allow_unlimited_contract_size,
|
|
464
|
+
bail_on_call_failure: self.bail_on_call_failure,
|
|
465
|
+
bail_on_transaction_failure: self.bail_on_transaction_failure,
|
|
309
466
|
block_gas_limit,
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
coinbase: value.coinbase.try_cast()?,
|
|
314
|
-
enable_rip_7212: value.enable_rip_7212,
|
|
315
|
-
fork: value.fork.map(TryInto::try_into).transpose()?,
|
|
467
|
+
chain_id: self.chain_id.try_cast()?,
|
|
468
|
+
coinbase: self.coinbase.try_cast()?,
|
|
469
|
+
fork: self.fork.map(TryInto::try_into).transpose()?,
|
|
316
470
|
genesis_state,
|
|
317
|
-
hardfork:
|
|
318
|
-
initial_base_fee_per_gas:
|
|
471
|
+
hardfork: self.hardfork,
|
|
472
|
+
initial_base_fee_per_gas: self
|
|
319
473
|
.initial_base_fee_per_gas
|
|
320
474
|
.map(TryCast::try_cast)
|
|
321
475
|
.transpose()?,
|
|
322
|
-
initial_blob_gas:
|
|
323
|
-
initial_date:
|
|
476
|
+
initial_blob_gas: self.initial_blob_gas.map(TryInto::try_into).transpose()?,
|
|
477
|
+
initial_date: self
|
|
324
478
|
.initial_date
|
|
325
479
|
.map(|date| {
|
|
326
480
|
let elapsed_since_epoch = Duration::from_secs(date.try_cast()?);
|
|
327
481
|
napi::Result::Ok(SystemTime::UNIX_EPOCH + elapsed_since_epoch)
|
|
328
482
|
})
|
|
329
483
|
.transpose()?,
|
|
330
|
-
initial_parent_beacon_block_root:
|
|
484
|
+
initial_parent_beacon_block_root: self
|
|
331
485
|
.initial_parent_beacon_block_root
|
|
332
486
|
.map(TryCast::try_cast)
|
|
333
487
|
.transpose()?,
|
|
334
|
-
mining:
|
|
335
|
-
min_gas_price:
|
|
336
|
-
network_id:
|
|
488
|
+
mining: self.mining.try_into()?,
|
|
489
|
+
min_gas_price: self.min_gas_price.try_cast()?,
|
|
490
|
+
network_id: self.network_id.try_cast()?,
|
|
491
|
+
observability: self.observability.resolve(env, runtime)?,
|
|
492
|
+
owned_accounts,
|
|
493
|
+
precompile_overrides,
|
|
337
494
|
})
|
|
338
495
|
}
|
|
339
496
|
}
|
|
@@ -349,6 +506,23 @@ pub struct TracingConfigWithBuffers {
|
|
|
349
506
|
pub ignore_contracts: Option<bool>,
|
|
350
507
|
}
|
|
351
508
|
|
|
509
|
+
impl From<TracingConfigWithBuffers> for edr_napi_core::solidity::config::TracingConfigWithBuffers {
|
|
510
|
+
fn from(value: TracingConfigWithBuffers) -> Self {
|
|
511
|
+
edr_napi_core::solidity::config::TracingConfigWithBuffers {
|
|
512
|
+
build_infos: value.build_infos.map(|infos| match infos {
|
|
513
|
+
Either::A(with_output) => Either::A(with_output),
|
|
514
|
+
Either::B(separate_output) => Either::B(
|
|
515
|
+
separate_output
|
|
516
|
+
.into_iter()
|
|
517
|
+
.map(edr_napi_core::solidity::config::BuildInfoAndOutput::from)
|
|
518
|
+
.collect(),
|
|
519
|
+
),
|
|
520
|
+
}),
|
|
521
|
+
ignore_contracts: value.ignore_contracts,
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
|
|
352
526
|
/// Hardhat V3 build info where the compiler output is not part of the build
|
|
353
527
|
/// info file.
|
|
354
528
|
#[napi(object)]
|
|
@@ -359,41 +533,11 @@ pub struct BuildInfoAndOutput {
|
|
|
359
533
|
pub output: Uint8Array,
|
|
360
534
|
}
|
|
361
535
|
|
|
362
|
-
impl<
|
|
363
|
-
|
|
364
|
-
{
|
|
365
|
-
fn from(value: &'a BuildInfoAndOutput) -> Self {
|
|
536
|
+
impl From<BuildInfoAndOutput> for edr_napi_core::solidity::config::BuildInfoAndOutput {
|
|
537
|
+
fn from(value: BuildInfoAndOutput) -> Self {
|
|
366
538
|
Self {
|
|
367
|
-
build_info: value.build_info
|
|
368
|
-
output: value.output
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
impl<'a> From<&'a TracingConfigWithBuffers>
|
|
374
|
-
for edr_solidity::artifacts::BuildInfoConfigWithBuffers<'a>
|
|
375
|
-
{
|
|
376
|
-
fn from(value: &'a TracingConfigWithBuffers) -> Self {
|
|
377
|
-
use edr_solidity::artifacts::{BuildInfoBufferSeparateOutput, BuildInfoBuffers};
|
|
378
|
-
|
|
379
|
-
let build_infos = value.build_infos.as_ref().map(|infos| match infos {
|
|
380
|
-
Either::A(with_output) => BuildInfoBuffers::WithOutput(
|
|
381
|
-
with_output
|
|
382
|
-
.iter()
|
|
383
|
-
.map(std::convert::AsRef::as_ref)
|
|
384
|
-
.collect(),
|
|
385
|
-
),
|
|
386
|
-
Either::B(separate_output) => BuildInfoBuffers::SeparateInputOutput(
|
|
387
|
-
separate_output
|
|
388
|
-
.iter()
|
|
389
|
-
.map(BuildInfoBufferSeparateOutput::from)
|
|
390
|
-
.collect(),
|
|
391
|
-
),
|
|
392
|
-
});
|
|
393
|
-
|
|
394
|
-
Self {
|
|
395
|
-
build_infos,
|
|
396
|
-
ignore_contracts: value.ignore_contracts,
|
|
539
|
+
build_info: value.build_info,
|
|
540
|
+
output: value.output,
|
|
397
541
|
}
|
|
398
542
|
}
|
|
399
543
|
}
|