@nomicfoundation/edr 0.12.0-next.6 → 0.12.0-next.8
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/index.d.ts +127 -44
- package/index.js +4 -1
- package/package.json +1 -10
- package/src/account.rs +6 -5
- package/src/block.rs +1 -1
- package/src/call_override.rs +1 -1
- package/src/cast.rs +1 -1
- package/src/chains/op.rs +11 -20
- package/src/config.rs +75 -23
- package/src/context.rs +32 -17
- package/src/contract_decoder.rs +57 -0
- package/src/debug_trace.rs +2 -0
- package/src/gas_report.rs +92 -0
- package/src/lib.rs +3 -0
- package/src/logger.rs +1 -1
- package/src/mock/time.rs +7 -7
- package/src/mock.rs +0 -9
- package/src/precompile.rs +1 -1
- package/src/provider.rs +28 -7
- package/src/result.rs +11 -11
- package/src/serde.rs +1 -1
- package/src/solidity_tests/config.rs +39 -2
- package/src/solidity_tests/l1.rs +1 -1
- package/src/solidity_tests/op.rs +1 -1
- package/src/solidity_tests/test_results.rs +63 -32
- package/src/solidity_tests.rs +1 -1
- package/src/trace/debug.rs +3 -1
- package/src/trace/return_data.rs +3 -5
- package/src/trace/solidity_stack_trace.rs +3 -2
- package/src/trace.rs +2 -2
- package/src/withdrawal.rs +5 -5
package/src/config.rs
CHANGED
|
@@ -2,15 +2,14 @@ use core::fmt::{Debug, Display};
|
|
|
2
2
|
use std::{
|
|
3
3
|
num::NonZeroU64,
|
|
4
4
|
path::PathBuf,
|
|
5
|
-
sync::Arc,
|
|
6
5
|
time::{Duration, SystemTime},
|
|
7
6
|
};
|
|
8
7
|
|
|
9
8
|
use edr_coverage::reporter::SyncOnCollectedCoverageCallback;
|
|
10
9
|
use edr_eip1559::{BaseFeeActivation, ConstantBaseFeeParams};
|
|
11
|
-
use
|
|
10
|
+
use edr_gas_report::SyncOnCollectedGasReportCallback;
|
|
11
|
+
use edr_primitives::{Bytes, HashMap, HashSet};
|
|
12
12
|
use edr_signer::{secret_key_from_str, SecretKey};
|
|
13
|
-
use edr_solidity::contract_decoder::ContractDecoder;
|
|
14
13
|
use napi::{
|
|
15
14
|
bindgen_prelude::{BigInt, Promise, Reference, Uint8Array},
|
|
16
15
|
threadsafe_function::{
|
|
@@ -22,8 +21,8 @@ use napi::{
|
|
|
22
21
|
use napi_derive::napi;
|
|
23
22
|
|
|
24
23
|
use crate::{
|
|
25
|
-
account::AccountOverride, block::BlobGas, cast::TryCast,
|
|
26
|
-
precompile::Precompile, subscription::SubscriptionConfig,
|
|
24
|
+
account::AccountOverride, block::BlobGas, cast::TryCast, gas_report::GasReport,
|
|
25
|
+
logger::LoggerConfig, precompile::Precompile, subscription::SubscriptionConfig,
|
|
27
26
|
};
|
|
28
27
|
|
|
29
28
|
/// Configuration for EIP-1559 parameters
|
|
@@ -36,12 +35,12 @@ pub struct BaseFeeParamActivation {
|
|
|
36
35
|
|
|
37
36
|
#[napi(object)]
|
|
38
37
|
pub struct BaseFeeActivationByBlockNumber {
|
|
39
|
-
/// The block number at which the base_fee_params is activated
|
|
38
|
+
/// The block number at which the `base_fee_params` is activated
|
|
40
39
|
pub block_number: BigInt,
|
|
41
40
|
}
|
|
42
41
|
#[napi(object)]
|
|
43
42
|
pub struct BaseFeeActivationByHardfork {
|
|
44
|
-
/// The hardfork at which the base_fee_params is activated
|
|
43
|
+
/// The hardfork at which the `base_fee_params` is activated
|
|
45
44
|
pub hardfork: String,
|
|
46
45
|
}
|
|
47
46
|
|
|
@@ -94,6 +93,17 @@ pub struct CodeCoverageConfig {
|
|
|
94
93
|
pub on_collected_coverage_callback: JsFunction,
|
|
95
94
|
}
|
|
96
95
|
|
|
96
|
+
#[napi(object)]
|
|
97
|
+
pub struct GasReportConfig {
|
|
98
|
+
/// Gas reports are collected after a block is mined or `eth_call` is
|
|
99
|
+
/// executed.
|
|
100
|
+
///
|
|
101
|
+
/// Exceptions thrown in the callback will be propagated to the original
|
|
102
|
+
/// caller.
|
|
103
|
+
#[napi(ts_type = "(gasReport: GasReport) => Promise<void>")]
|
|
104
|
+
pub on_collected_gas_report_callback: JsFunction,
|
|
105
|
+
}
|
|
106
|
+
|
|
97
107
|
/// Configuration for forking a blockchain
|
|
98
108
|
#[napi(object)]
|
|
99
109
|
pub struct ForkConfig {
|
|
@@ -171,6 +181,8 @@ pub struct MiningConfig {
|
|
|
171
181
|
pub struct ObservabilityConfig {
|
|
172
182
|
/// If present, configures runtime observability to collect code coverage.
|
|
173
183
|
pub code_coverage: Option<CodeCoverageConfig>,
|
|
184
|
+
/// If present, configures runtime observability to collect gas reports.
|
|
185
|
+
pub gas_report: Option<GasReportConfig>,
|
|
174
186
|
}
|
|
175
187
|
|
|
176
188
|
/// Configuration for a provider
|
|
@@ -187,7 +199,7 @@ pub struct ProviderConfig {
|
|
|
187
199
|
/// EIP-1559 base fee parameters activations to be used to calculate the
|
|
188
200
|
/// block base fee.
|
|
189
201
|
///
|
|
190
|
-
/// Provide an ordered list of base_fee_params to be
|
|
202
|
+
/// Provide an ordered list of `base_fee_params` to be
|
|
191
203
|
/// used starting from the specified activation point (hardfork or block
|
|
192
204
|
/// number).
|
|
193
205
|
/// If not provided, the default values from the chain spec
|
|
@@ -387,6 +399,8 @@ impl ObservabilityConfig {
|
|
|
387
399
|
.code_coverage
|
|
388
400
|
.map(
|
|
389
401
|
|code_coverage| -> napi::Result<Box<dyn SyncOnCollectedCoverageCallback>> {
|
|
402
|
+
let runtime = runtime.clone();
|
|
403
|
+
|
|
390
404
|
let mut on_collected_coverage_callback: ThreadsafeFunction<
|
|
391
405
|
_,
|
|
392
406
|
ErrorStrategy::Fatal,
|
|
@@ -452,9 +466,61 @@ impl ObservabilityConfig {
|
|
|
452
466
|
},
|
|
453
467
|
)
|
|
454
468
|
.transpose()?;
|
|
469
|
+
let on_collected_gas_report_fn = self.gas_report.map(
|
|
470
|
+
|gas_report| -> napi::Result<Box<dyn SyncOnCollectedGasReportCallback>> {
|
|
471
|
+
let mut on_collected_gas_report_callback: ThreadsafeFunction<
|
|
472
|
+
_,
|
|
473
|
+
ErrorStrategy::Fatal,
|
|
474
|
+
> = gas_report
|
|
475
|
+
.on_collected_gas_report_callback
|
|
476
|
+
.create_threadsafe_function(
|
|
477
|
+
0,
|
|
478
|
+
|ctx: ThreadSafeCallContext<GasReport>| {
|
|
479
|
+
let report = ctx.value;
|
|
480
|
+
Ok(vec![report])
|
|
481
|
+
}
|
|
482
|
+
,
|
|
483
|
+
)?;
|
|
484
|
+
// Maintain a weak reference to the function to avoid blocking the event loop
|
|
485
|
+
// from exiting.
|
|
486
|
+
on_collected_gas_report_callback.unref(env)?;
|
|
487
|
+
|
|
488
|
+
let on_collected_gas_report_fn: Box<dyn SyncOnCollectedGasReportCallback> =
|
|
489
|
+
Box::new(move |report| {
|
|
490
|
+
let runtime = runtime.clone();
|
|
491
|
+
|
|
492
|
+
let (sender, receiver) = std::sync::mpsc::channel();
|
|
493
|
+
|
|
494
|
+
// Convert the report to the N-API representation
|
|
495
|
+
let status = on_collected_gas_report_callback
|
|
496
|
+
.call_with_return_value(GasReport::from(report), ThreadsafeFunctionCallMode::Blocking, move |result: Promise<()>| {
|
|
497
|
+
// We spawn a background task to handle the async callback
|
|
498
|
+
runtime.spawn(async move {
|
|
499
|
+
let result = result.await;
|
|
500
|
+
sender.send(result).map_err(|_error| {
|
|
501
|
+
napi::Error::new(
|
|
502
|
+
napi::Status::GenericFailure,
|
|
503
|
+
"Failed to send result from on_collected_gas_report_callback",
|
|
504
|
+
)
|
|
505
|
+
})
|
|
506
|
+
});
|
|
507
|
+
Ok(())
|
|
508
|
+
});
|
|
509
|
+
|
|
510
|
+
assert_eq!(status, napi::Status::Ok);
|
|
511
|
+
|
|
512
|
+
let () = receiver.recv().expect("Receive can only fail if the channel is closed")?;
|
|
513
|
+
|
|
514
|
+
Ok(())
|
|
515
|
+
});
|
|
516
|
+
|
|
517
|
+
Ok(on_collected_gas_report_fn)
|
|
518
|
+
},
|
|
519
|
+
).transpose()?;
|
|
455
520
|
|
|
456
521
|
Ok(edr_provider::observability::Config {
|
|
457
522
|
on_collected_coverage_fn,
|
|
523
|
+
on_collected_gas_report_fn,
|
|
458
524
|
..edr_provider::observability::Config::default()
|
|
459
525
|
})
|
|
460
526
|
}
|
|
@@ -511,7 +577,7 @@ impl ProviderConfig {
|
|
|
511
577
|
.genesis_state
|
|
512
578
|
.into_iter()
|
|
513
579
|
.map(TryInto::try_into)
|
|
514
|
-
.collect::<napi::Result<HashMap<
|
|
580
|
+
.collect::<napi::Result<HashMap<edr_primitives::Address, edr_provider::AccountOverride>>>()?;
|
|
515
581
|
|
|
516
582
|
let precompile_overrides = self
|
|
517
583
|
.precompile_overrides
|
|
@@ -606,7 +672,6 @@ impl From<BuildInfoAndOutput> for edr_napi_core::solidity::config::BuildInfoAndO
|
|
|
606
672
|
|
|
607
673
|
/// Result of [`resolve_configs`].
|
|
608
674
|
pub struct ConfigResolution {
|
|
609
|
-
pub contract_decoder: Arc<ContractDecoder>,
|
|
610
675
|
pub logger_config: edr_napi_core::logger::Config,
|
|
611
676
|
pub provider_config: edr_napi_core::provider::Config,
|
|
612
677
|
pub subscription_callback: edr_napi_core::subscription::Callback,
|
|
@@ -619,28 +684,15 @@ pub fn resolve_configs(
|
|
|
619
684
|
provider_config: ProviderConfig,
|
|
620
685
|
logger_config: LoggerConfig,
|
|
621
686
|
subscription_config: SubscriptionConfig,
|
|
622
|
-
tracing_config: TracingConfigWithBuffers,
|
|
623
687
|
) -> napi::Result<ConfigResolution> {
|
|
624
688
|
let provider_config = provider_config.resolve(env, runtime)?;
|
|
625
689
|
let logger_config = logger_config.resolve(env)?;
|
|
626
690
|
|
|
627
|
-
// TODO: https://github.com/NomicFoundation/edr/issues/760
|
|
628
|
-
let build_info_config = edr_solidity::artifacts::BuildInfoConfig::parse_from_buffers(
|
|
629
|
-
(&edr_napi_core::solidity::config::TracingConfigWithBuffers::from(tracing_config)).into(),
|
|
630
|
-
)
|
|
631
|
-
.map_err(|error| napi::Error::from_reason(error.to_string()))?;
|
|
632
|
-
|
|
633
|
-
let contract_decoder = ContractDecoder::new(&build_info_config).map_or_else(
|
|
634
|
-
|error| Err(napi::Error::from_reason(error.to_string())),
|
|
635
|
-
|contract_decoder| Ok(Arc::new(contract_decoder)),
|
|
636
|
-
)?;
|
|
637
|
-
|
|
638
691
|
let subscription_config = edr_napi_core::subscription::Config::from(subscription_config);
|
|
639
692
|
let subscription_callback =
|
|
640
693
|
edr_napi_core::subscription::Callback::new(env, subscription_config.subscription_callback)?;
|
|
641
694
|
|
|
642
695
|
Ok(ConfigResolution {
|
|
643
|
-
contract_decoder,
|
|
644
696
|
logger_config,
|
|
645
697
|
provider_config,
|
|
646
698
|
subscription_callback,
|
package/src/context.rs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
use std::sync::Arc;
|
|
2
2
|
|
|
3
|
-
use edr_eth::HashMap;
|
|
4
3
|
use edr_napi_core::{provider::SyncProviderFactory, solidity};
|
|
4
|
+
use edr_primitives::HashMap;
|
|
5
5
|
use edr_solidity_tests::{
|
|
6
6
|
decode::RevertDecoder,
|
|
7
7
|
multi_runner::{SuiteResultAndArtifactId, TestContract, TestContracts},
|
|
@@ -19,13 +19,14 @@ use tracing_subscriber::{prelude::*, EnvFilter, Registry};
|
|
|
19
19
|
|
|
20
20
|
use crate::{
|
|
21
21
|
config::{resolve_configs, ConfigResolution, ProviderConfig, TracingConfigWithBuffers},
|
|
22
|
+
contract_decoder::ContractDecoder,
|
|
22
23
|
logger::LoggerConfig,
|
|
23
24
|
provider::{Provider, ProviderFactory},
|
|
24
25
|
solidity_tests::{
|
|
25
26
|
artifact::{Artifact, ArtifactId},
|
|
26
27
|
config::SolidityTestRunnerConfigArgs,
|
|
27
28
|
factory::SolidityTestRunnerFactory,
|
|
28
|
-
test_results::SuiteResult,
|
|
29
|
+
test_results::{SolidityTestResult, SuiteResult},
|
|
29
30
|
LinkingOutput,
|
|
30
31
|
},
|
|
31
32
|
subscription::SubscriptionConfig,
|
|
@@ -38,7 +39,7 @@ pub struct EdrContext {
|
|
|
38
39
|
|
|
39
40
|
#[napi]
|
|
40
41
|
impl EdrContext {
|
|
41
|
-
|
|
42
|
+
/// Creates a new [`EdrContext`] instance. Should only be called once!
|
|
42
43
|
#[napi(catch_unwind, constructor)]
|
|
43
44
|
pub fn new() -> napi::Result<Self> {
|
|
44
45
|
let context = Context::new()?;
|
|
@@ -48,7 +49,7 @@ impl EdrContext {
|
|
|
48
49
|
})
|
|
49
50
|
}
|
|
50
51
|
|
|
51
|
-
|
|
52
|
+
/// Constructs a new provider with the provided configuration.
|
|
52
53
|
#[napi(catch_unwind, ts_return_type = "Promise<Provider>")]
|
|
53
54
|
pub fn create_provider(
|
|
54
55
|
&self,
|
|
@@ -57,7 +58,7 @@ impl EdrContext {
|
|
|
57
58
|
provider_config: ProviderConfig,
|
|
58
59
|
logger_config: LoggerConfig,
|
|
59
60
|
subscription_config: SubscriptionConfig,
|
|
60
|
-
|
|
61
|
+
contract_decoder: &ContractDecoder,
|
|
61
62
|
) -> napi::Result<JsObject> {
|
|
62
63
|
let (deferred, promise) = env.create_deferred()?;
|
|
63
64
|
|
|
@@ -76,7 +77,6 @@ impl EdrContext {
|
|
|
76
77
|
let runtime = runtime::Handle::current();
|
|
77
78
|
|
|
78
79
|
let ConfigResolution {
|
|
79
|
-
contract_decoder,
|
|
80
80
|
logger_config,
|
|
81
81
|
provider_config,
|
|
82
82
|
subscription_callback,
|
|
@@ -86,7 +86,6 @@ impl EdrContext {
|
|
|
86
86
|
provider_config,
|
|
87
87
|
logger_config,
|
|
88
88
|
subscription_config,
|
|
89
|
-
tracing_config
|
|
90
89
|
));
|
|
91
90
|
|
|
92
91
|
#[cfg(feature = "scenarios")]
|
|
@@ -105,6 +104,7 @@ impl EdrContext {
|
|
|
105
104
|
try_or_reject_promise!(context.get_provider_factory(&chain_type))
|
|
106
105
|
};
|
|
107
106
|
|
|
107
|
+
let contract_decoder = Arc::clone(contract_decoder.as_inner());
|
|
108
108
|
runtime.clone().spawn_blocking(move || {
|
|
109
109
|
let result = factory
|
|
110
110
|
.create_provider(
|
|
@@ -130,7 +130,7 @@ impl EdrContext {
|
|
|
130
130
|
Ok(promise)
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
-
|
|
133
|
+
/// Registers a new provider factory for the provided chain type.
|
|
134
134
|
#[napi(catch_unwind)]
|
|
135
135
|
pub async fn register_provider_factory(
|
|
136
136
|
&self,
|
|
@@ -153,14 +153,29 @@ impl EdrContext {
|
|
|
153
153
|
Ok(())
|
|
154
154
|
}
|
|
155
155
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
156
|
+
/// Executes Solidity tests
|
|
157
|
+
///
|
|
158
|
+
/// The function will return a promise that resolves to a
|
|
159
|
+
/// [`SolidityTestResult`].
|
|
160
|
+
///
|
|
161
|
+
/// Arguments:
|
|
162
|
+
/// - `chainType`: the same chain type that was passed to
|
|
163
|
+
/// `registerProviderFactory`.
|
|
164
|
+
/// - `artifacts`: the project's compilation output artifacts. It's
|
|
165
|
+
/// important to include include all artifacts here, otherwise cheatcodes
|
|
166
|
+
/// that access artifacts and other functionality (e.g. auto-linking, gas
|
|
167
|
+
/// reports) can break.
|
|
168
|
+
/// - `testSuites`: the test suite ids that specify which test suites to
|
|
169
|
+
/// execute. The test suite artifacts must be present in `artifacts`.
|
|
170
|
+
/// - `configArgs`: solidity test runner configuration. See the struct docs
|
|
171
|
+
/// for details.
|
|
172
|
+
/// - `tracingConfig`: the build infos used for stack trace generation.
|
|
173
|
+
/// These are lazily parsed and it's important that they're passed as
|
|
174
|
+
/// Uint8 arrays for performance.
|
|
175
|
+
/// - `onTestSuiteCompletedCallback`: The progress callback will be called
|
|
176
|
+
/// with the results of each test suite as soon as it finished executing.
|
|
162
177
|
#[allow(clippy::too_many_arguments)]
|
|
163
|
-
#[napi(catch_unwind, ts_return_type = "Promise<
|
|
178
|
+
#[napi(catch_unwind, ts_return_type = "Promise<SolidityTestResult>")]
|
|
164
179
|
pub fn run_solidity_tests(
|
|
165
180
|
&self,
|
|
166
181
|
env: Env,
|
|
@@ -291,7 +306,7 @@ impl EdrContext {
|
|
|
291
306
|
.expect("Failed to join test runner factory thread"));
|
|
292
307
|
|
|
293
308
|
let runtime_for_runner = runtime.clone();
|
|
294
|
-
let
|
|
309
|
+
let test_result = try_or_reject_deferred!(runtime
|
|
295
310
|
.clone()
|
|
296
311
|
.spawn_blocking(move || {
|
|
297
312
|
test_runner.run_tests(
|
|
@@ -323,7 +338,7 @@ impl EdrContext {
|
|
|
323
338
|
.await
|
|
324
339
|
.expect("Failed to join test runner thread"));
|
|
325
340
|
|
|
326
|
-
deferred.resolve(move |_env| Ok(()));
|
|
341
|
+
deferred.resolve(move |_env| Ok(SolidityTestResult::from(test_result)));
|
|
327
342
|
});
|
|
328
343
|
|
|
329
344
|
Ok(promise)
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
use std::sync::Arc;
|
|
2
|
+
|
|
3
|
+
use napi_derive::napi;
|
|
4
|
+
|
|
5
|
+
use crate::config::TracingConfigWithBuffers;
|
|
6
|
+
|
|
7
|
+
#[napi]
|
|
8
|
+
pub struct ContractDecoder {
|
|
9
|
+
inner: Arc<edr_solidity::contract_decoder::ContractDecoder>,
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
#[napi]
|
|
13
|
+
impl ContractDecoder {
|
|
14
|
+
#[doc = "Creates an empty instance."]
|
|
15
|
+
#[napi(constructor, catch_unwind)]
|
|
16
|
+
// Following TS convention for the constructor without arguments to be `new()`.
|
|
17
|
+
#[allow(clippy::new_without_default)]
|
|
18
|
+
pub fn new() -> Self {
|
|
19
|
+
Self {
|
|
20
|
+
inner: Arc::new(edr_solidity::contract_decoder::ContractDecoder::default()),
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
#[doc = "Creates a new instance with the provided configuration."]
|
|
25
|
+
#[napi(factory, catch_unwind)]
|
|
26
|
+
pub fn with_contracts(config: TracingConfigWithBuffers) -> napi::Result<Self> {
|
|
27
|
+
let build_info_config = edr_solidity::artifacts::BuildInfoConfig::parse_from_buffers(
|
|
28
|
+
(&edr_napi_core::solidity::config::TracingConfigWithBuffers::from(config)).into(),
|
|
29
|
+
)
|
|
30
|
+
.map_err(|error| napi::Error::from_reason(error.to_string()))?;
|
|
31
|
+
|
|
32
|
+
let contract_decoder =
|
|
33
|
+
edr_solidity::contract_decoder::ContractDecoder::new(&build_info_config).map_or_else(
|
|
34
|
+
|error| Err(napi::Error::from_reason(error.to_string())),
|
|
35
|
+
|contract_decoder| Ok(Arc::new(contract_decoder)),
|
|
36
|
+
)?;
|
|
37
|
+
|
|
38
|
+
Ok(Self {
|
|
39
|
+
inner: contract_decoder,
|
|
40
|
+
})
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
impl ContractDecoder {
|
|
45
|
+
/// Returns a reference to the inner contract decoder.
|
|
46
|
+
pub fn as_inner(&self) -> &Arc<edr_solidity::contract_decoder::ContractDecoder> {
|
|
47
|
+
&self.inner
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
impl From<Arc<edr_solidity::contract_decoder::ContractDecoder>> for ContractDecoder {
|
|
52
|
+
fn from(contract_decoder: Arc<edr_solidity::contract_decoder::ContractDecoder>) -> Self {
|
|
53
|
+
Self {
|
|
54
|
+
inner: contract_decoder,
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
package/src/debug_trace.rs
CHANGED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
use std::collections::HashMap;
|
|
2
|
+
|
|
3
|
+
use napi::bindgen_prelude::BigInt;
|
|
4
|
+
use napi_derive::napi;
|
|
5
|
+
|
|
6
|
+
#[napi(object)]
|
|
7
|
+
pub struct GasReport {
|
|
8
|
+
pub contracts: HashMap<String, ContractGasReport>,
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
#[napi(object)]
|
|
12
|
+
pub struct ContractGasReport {
|
|
13
|
+
pub deployments: Vec<DeploymentGasReport>,
|
|
14
|
+
pub functions: HashMap<String, Vec<FunctionGasReport>>,
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
#[napi]
|
|
18
|
+
pub enum GasReportExecutionStatus {
|
|
19
|
+
Success,
|
|
20
|
+
Revert,
|
|
21
|
+
Halt,
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
#[napi(object)]
|
|
25
|
+
pub struct DeploymentGasReport {
|
|
26
|
+
pub gas: BigInt,
|
|
27
|
+
pub size: BigInt,
|
|
28
|
+
pub status: GasReportExecutionStatus,
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
#[napi(object)]
|
|
32
|
+
pub struct FunctionGasReport {
|
|
33
|
+
pub gas: BigInt,
|
|
34
|
+
pub status: GasReportExecutionStatus,
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
impl From<edr_gas_report::GasReport> for GasReport {
|
|
38
|
+
fn from(value: edr_gas_report::GasReport) -> Self {
|
|
39
|
+
Self {
|
|
40
|
+
contracts: value
|
|
41
|
+
.into_inner()
|
|
42
|
+
.into_iter()
|
|
43
|
+
.map(|(k, v)| (k, v.into()))
|
|
44
|
+
.collect(),
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
impl From<edr_gas_report::ContractGasReport> for ContractGasReport {
|
|
50
|
+
fn from(value: edr_gas_report::ContractGasReport) -> Self {
|
|
51
|
+
Self {
|
|
52
|
+
deployments: value.deployments.into_iter().map(Into::into).collect(),
|
|
53
|
+
functions: value
|
|
54
|
+
.functions
|
|
55
|
+
.into_iter()
|
|
56
|
+
.map(|(k, v)| {
|
|
57
|
+
let function_reports = v.into_iter().map(FunctionGasReport::from).collect();
|
|
58
|
+
(k, function_reports)
|
|
59
|
+
})
|
|
60
|
+
.collect(),
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
impl From<edr_gas_report::GasReportExecutionStatus> for GasReportExecutionStatus {
|
|
66
|
+
fn from(value: edr_gas_report::GasReportExecutionStatus) -> Self {
|
|
67
|
+
match value {
|
|
68
|
+
edr_gas_report::GasReportExecutionStatus::Success => Self::Success,
|
|
69
|
+
edr_gas_report::GasReportExecutionStatus::Revert => Self::Revert,
|
|
70
|
+
edr_gas_report::GasReportExecutionStatus::Halt => Self::Halt,
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
impl From<edr_gas_report::DeploymentGasReport> for DeploymentGasReport {
|
|
76
|
+
fn from(value: edr_gas_report::DeploymentGasReport) -> Self {
|
|
77
|
+
Self {
|
|
78
|
+
gas: BigInt::from(value.gas),
|
|
79
|
+
size: BigInt::from(value.size),
|
|
80
|
+
status: value.status.into(),
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
impl From<edr_gas_report::FunctionGasReport> for FunctionGasReport {
|
|
86
|
+
fn from(value: edr_gas_report::FunctionGasReport) -> Self {
|
|
87
|
+
Self {
|
|
88
|
+
gas: BigInt::from(value.gas),
|
|
89
|
+
status: value.status.into(),
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
package/src/lib.rs
CHANGED
|
@@ -17,7 +17,10 @@ pub mod chains;
|
|
|
17
17
|
pub mod config;
|
|
18
18
|
/// Types related to an EDR N-API context.
|
|
19
19
|
pub mod context;
|
|
20
|
+
/// Types for decoding smart contract data.
|
|
21
|
+
pub mod contract_decoder;
|
|
20
22
|
mod debug_trace;
|
|
23
|
+
pub mod gas_report;
|
|
21
24
|
/// Types and functions related to code coverage instrumentation.
|
|
22
25
|
pub mod instrument;
|
|
23
26
|
/// Types for EVM execution logs.
|
package/src/logger.rs
CHANGED
package/src/mock/time.rs
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
use std::sync::Arc;
|
|
2
2
|
|
|
3
|
-
use edr_eth::B256;
|
|
4
3
|
use edr_evm::spec::RuntimeSpec;
|
|
5
4
|
use edr_evm_spec::ChainSpec;
|
|
6
5
|
use edr_generic::GenericChainSpec;
|
|
7
6
|
use edr_napi_core::logger::Logger;
|
|
8
|
-
use
|
|
7
|
+
use edr_primitives::B256;
|
|
8
|
+
use edr_rpc_spec::RpcSpec;
|
|
9
9
|
use napi::{bindgen_prelude::BigInt, tokio::runtime, Env, JsObject};
|
|
10
10
|
use napi_derive::napi;
|
|
11
11
|
|
|
12
12
|
use crate::{
|
|
13
13
|
cast::TryCast as _,
|
|
14
|
-
config::{resolve_configs, ConfigResolution, ProviderConfig
|
|
14
|
+
config::{resolve_configs, ConfigResolution, ProviderConfig},
|
|
15
|
+
contract_decoder::ContractDecoder,
|
|
15
16
|
logger::LoggerConfig,
|
|
16
17
|
provider::Provider,
|
|
17
18
|
subscription::SubscriptionConfig,
|
|
@@ -50,7 +51,7 @@ pub fn create_provider_with_mock_timer(
|
|
|
50
51
|
provider_config: ProviderConfig,
|
|
51
52
|
logger_config: LoggerConfig,
|
|
52
53
|
subscription_config: SubscriptionConfig,
|
|
53
|
-
|
|
54
|
+
contract_decoder: &ContractDecoder,
|
|
54
55
|
time: &MockTime,
|
|
55
56
|
) -> napi::Result<JsObject> {
|
|
56
57
|
let (deferred, promise) = env.create_deferred()?;
|
|
@@ -70,7 +71,6 @@ pub fn create_provider_with_mock_timer(
|
|
|
70
71
|
let runtime = runtime::Handle::current();
|
|
71
72
|
|
|
72
73
|
let ConfigResolution {
|
|
73
|
-
contract_decoder,
|
|
74
74
|
logger_config,
|
|
75
75
|
provider_config,
|
|
76
76
|
subscription_callback,
|
|
@@ -80,9 +80,9 @@ pub fn create_provider_with_mock_timer(
|
|
|
80
80
|
provider_config,
|
|
81
81
|
logger_config,
|
|
82
82
|
subscription_config,
|
|
83
|
-
tracing_config,
|
|
84
83
|
));
|
|
85
84
|
|
|
85
|
+
let contract_decoder = Arc::clone(contract_decoder.as_inner());
|
|
86
86
|
let timer = Arc::clone(&time.inner);
|
|
87
87
|
|
|
88
88
|
runtime.clone().spawn_blocking(move || {
|
|
@@ -112,7 +112,7 @@ pub fn create_provider_with_mock_timer(
|
|
|
112
112
|
subscription_callback.call(event);
|
|
113
113
|
}),
|
|
114
114
|
provider_config,
|
|
115
|
-
|
|
115
|
+
Arc::clone(&contract_decoder),
|
|
116
116
|
timer,
|
|
117
117
|
)
|
|
118
118
|
.map_err(|error| napi::Error::from_reason(error.to_string()))?;
|
package/src/mock.rs
CHANGED
|
@@ -23,15 +23,6 @@ impl MockProvider {
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
impl SyncProvider for MockProvider {
|
|
26
|
-
fn add_compilation_result(
|
|
27
|
-
&self,
|
|
28
|
-
_solc_version: String,
|
|
29
|
-
_compiler_input: edr_solidity::artifacts::CompilerInput,
|
|
30
|
-
_compiler_output: edr_solidity::artifacts::CompilerOutput,
|
|
31
|
-
) -> napi::Result<bool> {
|
|
32
|
-
Ok(false) // Mock provider does not handle compilation results
|
|
33
|
-
}
|
|
34
|
-
|
|
35
26
|
fn handle_request(
|
|
36
27
|
&self,
|
|
37
28
|
_request: String,
|
package/src/precompile.rs
CHANGED
package/src/provider.rs
CHANGED
|
@@ -5,18 +5,18 @@ mod response;
|
|
|
5
5
|
use std::sync::Arc;
|
|
6
6
|
|
|
7
7
|
use edr_napi_core::provider::SyncProvider;
|
|
8
|
-
use edr_solidity::
|
|
8
|
+
use edr_solidity::compiler::create_models_and_decode_bytecodes;
|
|
9
9
|
use napi::{tokio::runtime, Env, JsFunction, JsObject, Status};
|
|
10
10
|
use napi_derive::napi;
|
|
11
11
|
|
|
12
12
|
pub use self::factory::ProviderFactory;
|
|
13
13
|
use self::response::Response;
|
|
14
|
-
use crate::call_override::CallOverrideCallback;
|
|
14
|
+
use crate::{call_override::CallOverrideCallback, contract_decoder::ContractDecoder};
|
|
15
15
|
|
|
16
16
|
/// A JSON-RPC provider for Ethereum.
|
|
17
17
|
#[napi]
|
|
18
18
|
pub struct Provider {
|
|
19
|
-
contract_decoder: Arc<ContractDecoder>,
|
|
19
|
+
contract_decoder: Arc<edr_solidity::contract_decoder::ContractDecoder>,
|
|
20
20
|
provider: Arc<dyn SyncProvider>,
|
|
21
21
|
runtime: runtime::Handle,
|
|
22
22
|
#[cfg(feature = "scenarios")]
|
|
@@ -28,7 +28,7 @@ impl Provider {
|
|
|
28
28
|
pub fn new(
|
|
29
29
|
provider: Arc<dyn SyncProvider>,
|
|
30
30
|
runtime: runtime::Handle,
|
|
31
|
-
contract_decoder: Arc<ContractDecoder>,
|
|
31
|
+
contract_decoder: Arc<edr_solidity::contract_decoder::ContractDecoder>,
|
|
32
32
|
#[cfg(feature = "scenarios")] scenario_file: Option<
|
|
33
33
|
napi::tokio::sync::Mutex<napi::tokio::fs::File>,
|
|
34
34
|
>,
|
|
@@ -54,8 +54,8 @@ impl Provider {
|
|
|
54
54
|
solc_version: String,
|
|
55
55
|
compiler_input: serde_json::Value,
|
|
56
56
|
compiler_output: serde_json::Value,
|
|
57
|
-
) -> napi::Result<
|
|
58
|
-
let
|
|
57
|
+
) -> napi::Result<()> {
|
|
58
|
+
let contract_decoder = self.contract_decoder.clone();
|
|
59
59
|
|
|
60
60
|
self.runtime
|
|
61
61
|
.spawn_blocking(move || {
|
|
@@ -65,12 +65,33 @@ impl Provider {
|
|
|
65
65
|
let compiler_output = serde_json::from_value(compiler_output)
|
|
66
66
|
.map_err(|error| napi::Error::from_reason(error.to_string()))?;
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
let contracts = match create_models_and_decode_bytecodes(
|
|
69
|
+
solc_version,
|
|
70
|
+
&compiler_input,
|
|
71
|
+
&compiler_output,
|
|
72
|
+
) {
|
|
73
|
+
Ok(contracts) => contracts,
|
|
74
|
+
Err(error) => {
|
|
75
|
+
return Err(napi::Error::from_reason(format!("Contract decoder failed to be updated. Please report this to help us improve Hardhat.\n{error}")));
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
for contract in contracts {
|
|
80
|
+
contract_decoder.add_contract_metadata(contract);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
Ok(())
|
|
69
84
|
})
|
|
70
85
|
.await
|
|
71
86
|
.map_err(|error| napi::Error::new(Status::GenericFailure, error.to_string()))?
|
|
72
87
|
}
|
|
73
88
|
|
|
89
|
+
#[doc = "Retrieves the instance's contract decoder."]
|
|
90
|
+
#[napi(catch_unwind)]
|
|
91
|
+
pub fn contract_decoder(&self) -> ContractDecoder {
|
|
92
|
+
ContractDecoder::from(Arc::clone(&self.contract_decoder))
|
|
93
|
+
}
|
|
94
|
+
|
|
74
95
|
#[doc = "Handles a JSON-RPC request and returns a JSON-RPC response."]
|
|
75
96
|
#[napi(catch_unwind)]
|
|
76
97
|
pub async fn handle_request(&self, request: String) -> napi::Result<Response> {
|