@nomicfoundation/edr 0.12.0-next.5 → 0.12.0-next.7
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 +79 -31
- package/index.js +3 -1
- package/package.json +8 -8
- package/src/chains/generic.rs +1 -2
- package/src/chains/l1.rs +62 -62
- package/src/chains/op.rs +15 -14
- package/src/config.rs +62 -21
- package/src/context.rs +3 -3
- package/src/contract_decoder.rs +57 -0
- package/src/debug_trace.rs +2 -0
- package/src/lib.rs +2 -0
- package/src/log.rs +2 -2
- package/src/mock/time.rs +8 -7
- package/src/mock.rs +2 -10
- package/src/provider/response.rs +4 -4
- package/src/provider.rs +28 -7
- package/src/result.rs +24 -48
- package/src/solidity_tests/config.rs +31 -1
- package/src/solidity_tests/l1.rs +6 -6
- package/src/solidity_tests/op.rs +4 -4
- package/src/solidity_tests/runner.rs +1 -1
- package/src/solidity_tests/test_results.rs +46 -32
- package/src/trace/debug.rs +3 -1
- package/src/trace/exit.rs +9 -8
- package/src/trace/return_data.rs +3 -5
- package/src/trace.rs +5 -4
package/src/config.rs
CHANGED
|
@@ -2,16 +2,13 @@ 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
|
-
use
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
};
|
|
14
|
-
use edr_solidity::contract_decoder::ContractDecoder;
|
|
9
|
+
use edr_eip1559::{BaseFeeActivation, ConstantBaseFeeParams};
|
|
10
|
+
use edr_eth::{Bytes, HashMap, HashSet};
|
|
11
|
+
use edr_signer::{secret_key_from_str, SecretKey};
|
|
15
12
|
use napi::{
|
|
16
13
|
bindgen_prelude::{BigInt, Promise, Reference, Uint8Array},
|
|
17
14
|
threadsafe_function::{
|
|
@@ -27,6 +24,49 @@ use crate::{
|
|
|
27
24
|
precompile::Precompile, subscription::SubscriptionConfig,
|
|
28
25
|
};
|
|
29
26
|
|
|
27
|
+
/// Configuration for EIP-1559 parameters
|
|
28
|
+
#[napi(object)]
|
|
29
|
+
pub struct BaseFeeParamActivation {
|
|
30
|
+
pub activation: Either<BaseFeeActivationByBlockNumber, BaseFeeActivationByHardfork>,
|
|
31
|
+
pub max_change_denominator: BigInt,
|
|
32
|
+
pub elasticity_multiplier: BigInt,
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
#[napi(object)]
|
|
36
|
+
pub struct BaseFeeActivationByBlockNumber {
|
|
37
|
+
/// The block number at which the `base_fee_params` is activated
|
|
38
|
+
pub block_number: BigInt,
|
|
39
|
+
}
|
|
40
|
+
#[napi(object)]
|
|
41
|
+
pub struct BaseFeeActivationByHardfork {
|
|
42
|
+
/// The hardfork at which the `base_fee_params` is activated
|
|
43
|
+
pub hardfork: String,
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
impl TryFrom<BaseFeeParamActivation> for (BaseFeeActivation<String>, ConstantBaseFeeParams) {
|
|
47
|
+
type Error = napi::Error;
|
|
48
|
+
|
|
49
|
+
fn try_from(value: BaseFeeParamActivation) -> Result<Self, Self::Error> {
|
|
50
|
+
let base_fee_params = ConstantBaseFeeParams {
|
|
51
|
+
max_change_denominator: value.max_change_denominator.try_cast()?,
|
|
52
|
+
elasticity_multiplier: value.elasticity_multiplier.try_cast()?,
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
match value.activation {
|
|
56
|
+
Either::A(BaseFeeActivationByBlockNumber { block_number }) => {
|
|
57
|
+
let activation_block_number: u64 = block_number.try_cast()?;
|
|
58
|
+
Ok((
|
|
59
|
+
BaseFeeActivation::BlockNumber(activation_block_number),
|
|
60
|
+
base_fee_params,
|
|
61
|
+
))
|
|
62
|
+
}
|
|
63
|
+
Either::B(BaseFeeActivationByHardfork { hardfork }) => {
|
|
64
|
+
Ok((BaseFeeActivation::Hardfork(hardfork), base_fee_params))
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
30
70
|
/// Specification of a chain with possible overrides.
|
|
31
71
|
#[napi(object)]
|
|
32
72
|
pub struct ChainOverride {
|
|
@@ -142,6 +182,15 @@ pub struct ProviderConfig {
|
|
|
142
182
|
pub bail_on_call_failure: bool,
|
|
143
183
|
/// Whether to return an `Err` when a `eth_sendTransaction` fails
|
|
144
184
|
pub bail_on_transaction_failure: bool,
|
|
185
|
+
/// EIP-1559 base fee parameters activations to be used to calculate the
|
|
186
|
+
/// block base fee.
|
|
187
|
+
///
|
|
188
|
+
/// Provide an ordered list of `base_fee_params` to be
|
|
189
|
+
/// used starting from the specified activation point (hardfork or block
|
|
190
|
+
/// number).
|
|
191
|
+
/// If not provided, the default values from the chain spec
|
|
192
|
+
/// will be used.
|
|
193
|
+
pub base_fee_config: Option<Vec<BaseFeeParamActivation>>,
|
|
145
194
|
/// The gas limit of each block
|
|
146
195
|
pub block_gas_limit: BigInt,
|
|
147
196
|
/// The chain ID of the blockchain
|
|
@@ -423,7 +472,7 @@ impl ProviderConfig {
|
|
|
423
472
|
// This is the only place in production code where it's allowed to use
|
|
424
473
|
// `DangerousSecretKeyStr`.
|
|
425
474
|
#[allow(deprecated)]
|
|
426
|
-
use
|
|
475
|
+
use edr_signer::DangerousSecretKeyStr;
|
|
427
476
|
|
|
428
477
|
static_assertions::assert_not_impl_all!(JsString: Debug, Display, serde::Serialize);
|
|
429
478
|
static_assertions::assert_not_impl_all!(JsStringUtf8: Debug, Display, serde::Serialize);
|
|
@@ -443,6 +492,11 @@ impl ProviderConfig {
|
|
|
443
492
|
})
|
|
444
493
|
.collect::<napi::Result<Vec<_>>>()?;
|
|
445
494
|
|
|
495
|
+
let base_fee_params: Option<Vec<(BaseFeeActivation<String>, ConstantBaseFeeParams)>> = self
|
|
496
|
+
.base_fee_config
|
|
497
|
+
.map(|vec| vec.into_iter().map(TryInto::try_into).collect())
|
|
498
|
+
.transpose()?;
|
|
499
|
+
|
|
446
500
|
let block_gas_limit =
|
|
447
501
|
NonZeroU64::new(self.block_gas_limit.try_cast()?).ok_or_else(|| {
|
|
448
502
|
napi::Error::new(
|
|
@@ -468,6 +522,7 @@ impl ProviderConfig {
|
|
|
468
522
|
allow_unlimited_contract_size: self.allow_unlimited_contract_size,
|
|
469
523
|
bail_on_call_failure: self.bail_on_call_failure,
|
|
470
524
|
bail_on_transaction_failure: self.bail_on_transaction_failure,
|
|
525
|
+
base_fee_params,
|
|
471
526
|
block_gas_limit,
|
|
472
527
|
chain_id: self.chain_id.try_cast()?,
|
|
473
528
|
coinbase: self.coinbase.try_cast()?,
|
|
@@ -549,7 +604,6 @@ impl From<BuildInfoAndOutput> for edr_napi_core::solidity::config::BuildInfoAndO
|
|
|
549
604
|
|
|
550
605
|
/// Result of [`resolve_configs`].
|
|
551
606
|
pub struct ConfigResolution {
|
|
552
|
-
pub contract_decoder: Arc<ContractDecoder>,
|
|
553
607
|
pub logger_config: edr_napi_core::logger::Config,
|
|
554
608
|
pub provider_config: edr_napi_core::provider::Config,
|
|
555
609
|
pub subscription_callback: edr_napi_core::subscription::Callback,
|
|
@@ -562,28 +616,15 @@ pub fn resolve_configs(
|
|
|
562
616
|
provider_config: ProviderConfig,
|
|
563
617
|
logger_config: LoggerConfig,
|
|
564
618
|
subscription_config: SubscriptionConfig,
|
|
565
|
-
tracing_config: TracingConfigWithBuffers,
|
|
566
619
|
) -> napi::Result<ConfigResolution> {
|
|
567
620
|
let provider_config = provider_config.resolve(env, runtime)?;
|
|
568
621
|
let logger_config = logger_config.resolve(env)?;
|
|
569
622
|
|
|
570
|
-
// TODO: https://github.com/NomicFoundation/edr/issues/760
|
|
571
|
-
let build_info_config = edr_solidity::artifacts::BuildInfoConfig::parse_from_buffers(
|
|
572
|
-
(&edr_napi_core::solidity::config::TracingConfigWithBuffers::from(tracing_config)).into(),
|
|
573
|
-
)
|
|
574
|
-
.map_err(|error| napi::Error::from_reason(error.to_string()))?;
|
|
575
|
-
|
|
576
|
-
let contract_decoder = ContractDecoder::new(&build_info_config).map_or_else(
|
|
577
|
-
|error| Err(napi::Error::from_reason(error.to_string())),
|
|
578
|
-
|contract_decoder| Ok(Arc::new(contract_decoder)),
|
|
579
|
-
)?;
|
|
580
|
-
|
|
581
623
|
let subscription_config = edr_napi_core::subscription::Config::from(subscription_config);
|
|
582
624
|
let subscription_callback =
|
|
583
625
|
edr_napi_core::subscription::Callback::new(env, subscription_config.subscription_callback)?;
|
|
584
626
|
|
|
585
627
|
Ok(ConfigResolution {
|
|
586
|
-
contract_decoder,
|
|
587
628
|
logger_config,
|
|
588
629
|
provider_config,
|
|
589
630
|
subscription_callback,
|
package/src/context.rs
CHANGED
|
@@ -19,6 +19,7 @@ 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::{
|
|
@@ -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(
|
|
@@ -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
package/src/lib.rs
CHANGED
|
@@ -17,6 +17,8 @@ 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;
|
|
21
23
|
/// Types and functions related to code coverage instrumentation.
|
|
22
24
|
pub mod instrument;
|
package/src/log.rs
CHANGED
|
@@ -9,8 +9,8 @@ pub struct ExecutionLog {
|
|
|
9
9
|
pub data: Uint8Array,
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
impl From<&
|
|
13
|
-
fn from(value: &
|
|
12
|
+
impl From<&edr_receipt::log::ExecutionLog> for ExecutionLog {
|
|
13
|
+
fn from(value: &edr_receipt::log::ExecutionLog) -> Self {
|
|
14
14
|
let topics = value
|
|
15
15
|
.topics()
|
|
16
16
|
.iter()
|
package/src/mock/time.rs
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
use std::sync::Arc;
|
|
2
2
|
|
|
3
|
-
use edr_eth::
|
|
3
|
+
use edr_eth::B256;
|
|
4
4
|
use edr_evm::spec::RuntimeSpec;
|
|
5
|
+
use edr_evm_spec::ChainSpec;
|
|
5
6
|
use edr_generic::GenericChainSpec;
|
|
6
7
|
use edr_napi_core::logger::Logger;
|
|
7
8
|
use edr_rpc_eth::RpcSpec;
|
|
@@ -10,7 +11,8 @@ use napi_derive::napi;
|
|
|
10
11
|
|
|
11
12
|
use crate::{
|
|
12
13
|
cast::TryCast as _,
|
|
13
|
-
config::{resolve_configs, ConfigResolution, ProviderConfig
|
|
14
|
+
config::{resolve_configs, ConfigResolution, ProviderConfig},
|
|
15
|
+
contract_decoder::ContractDecoder,
|
|
14
16
|
logger::LoggerConfig,
|
|
15
17
|
provider::Provider,
|
|
16
18
|
subscription::SubscriptionConfig,
|
|
@@ -49,7 +51,7 @@ pub fn create_provider_with_mock_timer(
|
|
|
49
51
|
provider_config: ProviderConfig,
|
|
50
52
|
logger_config: LoggerConfig,
|
|
51
53
|
subscription_config: SubscriptionConfig,
|
|
52
|
-
|
|
54
|
+
contract_decoder: &ContractDecoder,
|
|
53
55
|
time: &MockTime,
|
|
54
56
|
) -> napi::Result<JsObject> {
|
|
55
57
|
let (deferred, promise) = env.create_deferred()?;
|
|
@@ -69,7 +71,6 @@ pub fn create_provider_with_mock_timer(
|
|
|
69
71
|
let runtime = runtime::Handle::current();
|
|
70
72
|
|
|
71
73
|
let ConfigResolution {
|
|
72
|
-
contract_decoder,
|
|
73
74
|
logger_config,
|
|
74
75
|
provider_config,
|
|
75
76
|
subscription_callback,
|
|
@@ -79,9 +80,9 @@ pub fn create_provider_with_mock_timer(
|
|
|
79
80
|
provider_config,
|
|
80
81
|
logger_config,
|
|
81
82
|
subscription_config,
|
|
82
|
-
tracing_config,
|
|
83
83
|
));
|
|
84
84
|
|
|
85
|
+
let contract_decoder = Arc::clone(contract_decoder.as_inner());
|
|
85
86
|
let timer = Arc::clone(&time.inner);
|
|
86
87
|
|
|
87
88
|
runtime.clone().spawn_blocking(move || {
|
|
@@ -95,7 +96,7 @@ pub fn create_provider_with_mock_timer(
|
|
|
95
96
|
)?;
|
|
96
97
|
|
|
97
98
|
let provider_config =
|
|
98
|
-
edr_provider::ProviderConfig::<
|
|
99
|
+
edr_provider::ProviderConfig::<edr_chain_l1::Hardfork>::try_from(provider_config)?;
|
|
99
100
|
|
|
100
101
|
let provider =
|
|
101
102
|
edr_provider::Provider::<GenericChainSpec, Arc<edr_provider::time::MockTime>>::new(
|
|
@@ -111,7 +112,7 @@ pub fn create_provider_with_mock_timer(
|
|
|
111
112
|
subscription_callback.call(event);
|
|
112
113
|
}),
|
|
113
114
|
provider_config,
|
|
114
|
-
|
|
115
|
+
Arc::clone(&contract_decoder),
|
|
115
116
|
timer,
|
|
116
117
|
)
|
|
117
118
|
.map_err(|error| napi::Error::from_reason(error.to_string()))?;
|
package/src/mock.rs
CHANGED
|
@@ -2,6 +2,7 @@ pub mod time;
|
|
|
2
2
|
|
|
3
3
|
use std::sync::Arc;
|
|
4
4
|
|
|
5
|
+
use edr_evm_spec::EvmHaltReason;
|
|
5
6
|
use edr_napi_core::provider::SyncProvider;
|
|
6
7
|
use edr_rpc_client::jsonrpc;
|
|
7
8
|
use edr_solidity::contract_decoder::ContractDecoder;
|
|
@@ -22,20 +23,11 @@ impl MockProvider {
|
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
impl SyncProvider for MockProvider {
|
|
25
|
-
fn add_compilation_result(
|
|
26
|
-
&self,
|
|
27
|
-
_solc_version: String,
|
|
28
|
-
_compiler_input: edr_solidity::artifacts::CompilerInput,
|
|
29
|
-
_compiler_output: edr_solidity::artifacts::CompilerOutput,
|
|
30
|
-
) -> napi::Result<bool> {
|
|
31
|
-
Ok(false) // Mock provider does not handle compilation results
|
|
32
|
-
}
|
|
33
|
-
|
|
34
26
|
fn handle_request(
|
|
35
27
|
&self,
|
|
36
28
|
_request: String,
|
|
37
29
|
_contract_decoder: Arc<ContractDecoder>,
|
|
38
|
-
) -> napi::Result<edr_napi_core::spec::Response<
|
|
30
|
+
) -> napi::Result<edr_napi_core::spec::Response<EvmHaltReason>> {
|
|
39
31
|
let response = jsonrpc::ResponseData::Success {
|
|
40
32
|
result: self.mocked_response.clone(),
|
|
41
33
|
};
|
package/src/provider/response.rs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
use
|
|
1
|
+
use edr_evm_spec::EvmHaltReason;
|
|
2
2
|
use edr_napi_core::spec::SolidityTraceData;
|
|
3
3
|
use edr_solidity::contract_decoder::NestedTraceDecoder as _;
|
|
4
4
|
use napi::Either;
|
|
@@ -11,11 +11,11 @@ use crate::{
|
|
|
11
11
|
|
|
12
12
|
#[napi]
|
|
13
13
|
pub struct Response {
|
|
14
|
-
inner: edr_napi_core::spec::Response<
|
|
14
|
+
inner: edr_napi_core::spec::Response<EvmHaltReason>,
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
impl From<edr_napi_core::spec::Response<
|
|
18
|
-
fn from(value: edr_napi_core::spec::Response<
|
|
17
|
+
impl From<edr_napi_core::spec::Response<EvmHaltReason>> for Response {
|
|
18
|
+
fn from(value: edr_napi_core::spec::Response<EvmHaltReason>) -> Self {
|
|
19
19
|
Self { inner: value }
|
|
20
20
|
}
|
|
21
21
|
}
|
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> {
|
package/src/result.rs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
use edr_evm::trace::AfterMessage;
|
|
2
|
+
use edr_evm_spec::EvmHaltReason;
|
|
2
3
|
use napi::{
|
|
3
4
|
bindgen_prelude::{BigInt, Either3, Uint8Array},
|
|
4
5
|
Either,
|
|
@@ -99,61 +100,36 @@ pub enum ExceptionalHalt {
|
|
|
99
100
|
CreateInitCodeSizeLimit,
|
|
100
101
|
}
|
|
101
102
|
|
|
102
|
-
impl From<
|
|
103
|
-
fn from(halt:
|
|
103
|
+
impl From<EvmHaltReason> for ExceptionalHalt {
|
|
104
|
+
fn from(halt: EvmHaltReason) -> Self {
|
|
104
105
|
match halt {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
}
|
|
119
|
-
edr_eth::l1::HaltReason::CreateContractStartingWithEF => {
|
|
106
|
+
EvmHaltReason::OutOfGas(..) => ExceptionalHalt::OutOfGas,
|
|
107
|
+
EvmHaltReason::OpcodeNotFound => ExceptionalHalt::OpcodeNotFound,
|
|
108
|
+
EvmHaltReason::InvalidFEOpcode => ExceptionalHalt::InvalidFEOpcode,
|
|
109
|
+
EvmHaltReason::InvalidJump => ExceptionalHalt::InvalidJump,
|
|
110
|
+
EvmHaltReason::NotActivated => ExceptionalHalt::NotActivated,
|
|
111
|
+
EvmHaltReason::StackUnderflow => ExceptionalHalt::StackUnderflow,
|
|
112
|
+
EvmHaltReason::StackOverflow => ExceptionalHalt::StackOverflow,
|
|
113
|
+
EvmHaltReason::OutOfOffset => ExceptionalHalt::OutOfOffset,
|
|
114
|
+
EvmHaltReason::CreateCollision => ExceptionalHalt::CreateCollision,
|
|
115
|
+
EvmHaltReason::PrecompileError => ExceptionalHalt::PrecompileError,
|
|
116
|
+
EvmHaltReason::NonceOverflow => ExceptionalHalt::NonceOverflow,
|
|
117
|
+
EvmHaltReason::CreateContractSizeLimit => ExceptionalHalt::CreateContractSizeLimit,
|
|
118
|
+
EvmHaltReason::CreateContractStartingWithEF => {
|
|
120
119
|
ExceptionalHalt::CreateContractStartingWithEF
|
|
121
120
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
|
127
|
-
|
|
|
128
|
-
| edr_eth::l1::HaltReason::OutOfFunds
|
|
129
|
-
| edr_eth::l1::HaltReason::CallTooDeep => {
|
|
121
|
+
EvmHaltReason::CreateInitCodeSizeLimit => ExceptionalHalt::CreateInitCodeSizeLimit,
|
|
122
|
+
EvmHaltReason::OverflowPayment
|
|
123
|
+
| EvmHaltReason::StateChangeDuringStaticCall
|
|
124
|
+
| EvmHaltReason::CallNotAllowedInsideStatic
|
|
125
|
+
| EvmHaltReason::OutOfFunds
|
|
126
|
+
| EvmHaltReason::CallTooDeep => {
|
|
130
127
|
unreachable!("Internal halts that can be only found inside Inspector: {halt:?}")
|
|
131
128
|
}
|
|
132
129
|
}
|
|
133
130
|
}
|
|
134
131
|
}
|
|
135
132
|
|
|
136
|
-
impl From<ExceptionalHalt> for edr_eth::l1::HaltReason {
|
|
137
|
-
fn from(value: ExceptionalHalt) -> Self {
|
|
138
|
-
match value {
|
|
139
|
-
ExceptionalHalt::OutOfGas => Self::OutOfGas(edr_eth::l1::OutOfGasError::Basic),
|
|
140
|
-
ExceptionalHalt::OpcodeNotFound => Self::OpcodeNotFound,
|
|
141
|
-
ExceptionalHalt::InvalidFEOpcode => Self::InvalidFEOpcode,
|
|
142
|
-
ExceptionalHalt::InvalidJump => Self::InvalidJump,
|
|
143
|
-
ExceptionalHalt::NotActivated => Self::NotActivated,
|
|
144
|
-
ExceptionalHalt::StackUnderflow => Self::StackUnderflow,
|
|
145
|
-
ExceptionalHalt::StackOverflow => Self::StackOverflow,
|
|
146
|
-
ExceptionalHalt::OutOfOffset => Self::OutOfOffset,
|
|
147
|
-
ExceptionalHalt::CreateCollision => Self::CreateCollision,
|
|
148
|
-
ExceptionalHalt::PrecompileError => Self::PrecompileError,
|
|
149
|
-
ExceptionalHalt::NonceOverflow => Self::NonceOverflow,
|
|
150
|
-
ExceptionalHalt::CreateContractSizeLimit => Self::CreateContractSizeLimit,
|
|
151
|
-
ExceptionalHalt::CreateContractStartingWithEF => Self::CreateContractStartingWithEF,
|
|
152
|
-
ExceptionalHalt::CreateInitCodeSizeLimit => Self::CreateInitCodeSizeLimit,
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
133
|
/// The result when the EVM terminates due to an exceptional halt.
|
|
158
134
|
#[napi(object)]
|
|
159
135
|
pub struct HaltResult {
|
|
@@ -173,8 +149,8 @@ pub struct ExecutionResult {
|
|
|
173
149
|
pub contract_address: Option<Uint8Array>,
|
|
174
150
|
}
|
|
175
151
|
|
|
176
|
-
impl From<&AfterMessage<
|
|
177
|
-
fn from(value: &AfterMessage<
|
|
152
|
+
impl From<&AfterMessage<EvmHaltReason>> for ExecutionResult {
|
|
153
|
+
fn from(value: &AfterMessage<EvmHaltReason>) -> Self {
|
|
178
154
|
let AfterMessage {
|
|
179
155
|
execution_result,
|
|
180
156
|
contract_address,
|
|
@@ -109,7 +109,7 @@ pub struct SolidityTestRunnerConfigArgs {
|
|
|
109
109
|
/// Defaults to false.
|
|
110
110
|
pub disable_block_gas_limit: Option<bool>,
|
|
111
111
|
/// The memory limit of the EVM in bytes.
|
|
112
|
-
/// Defaults to 33_554_432 (2^25 = 32MiB).
|
|
112
|
+
/// Defaults to `33_554_432` (2^25 = 32MiB).
|
|
113
113
|
#[serde(serialize_with = "serialize_optional_bigint_as_struct")]
|
|
114
114
|
pub memory_limit: Option<BigInt>,
|
|
115
115
|
/// The predeploys applied in local mode. Defaults to no predeploys.
|
|
@@ -143,6 +143,8 @@ pub struct SolidityTestRunnerConfigArgs {
|
|
|
143
143
|
/// If an invariant config setting is not set, but a corresponding fuzz
|
|
144
144
|
/// config value is set, then the fuzz config value will be used.
|
|
145
145
|
pub invariant: Option<InvariantConfigArgs>,
|
|
146
|
+
/// Whether to collect stack traces.
|
|
147
|
+
pub collect_stack_traces: Option<CollectStackTraces>,
|
|
146
148
|
/// Controls which test results should include execution traces. Defaults to
|
|
147
149
|
/// None.
|
|
148
150
|
pub include_traces: Option<IncludeTraces>,
|
|
@@ -194,6 +196,7 @@ impl SolidityTestRunnerConfigArgs {
|
|
|
194
196
|
prompt_timeout,
|
|
195
197
|
fuzz,
|
|
196
198
|
invariant,
|
|
199
|
+
collect_stack_traces,
|
|
197
200
|
include_traces,
|
|
198
201
|
observability,
|
|
199
202
|
test_pattern,
|
|
@@ -296,6 +299,10 @@ impl SolidityTestRunnerConfigArgs {
|
|
|
296
299
|
cheatcode,
|
|
297
300
|
fuzz,
|
|
298
301
|
invariant,
|
|
302
|
+
collect_stack_traces: collect_stack_traces.map_or(
|
|
303
|
+
edr_solidity_tests::CollectStackTraces::OnFailure,
|
|
304
|
+
edr_solidity_tests::CollectStackTraces::from,
|
|
305
|
+
),
|
|
299
306
|
on_collected_coverage_fn,
|
|
300
307
|
test_pattern,
|
|
301
308
|
};
|
|
@@ -721,6 +728,29 @@ pub struct AddressLabel {
|
|
|
721
728
|
pub label: String,
|
|
722
729
|
}
|
|
723
730
|
|
|
731
|
+
/// A type that controls when stack traces are collected.
|
|
732
|
+
#[napi]
|
|
733
|
+
#[derive(Debug, serde::Serialize)]
|
|
734
|
+
pub enum CollectStackTraces {
|
|
735
|
+
/// Always collects stack traces, adding performance overhead.
|
|
736
|
+
Always,
|
|
737
|
+
/// Only collects stack traces upon failure, re-executing the test. This
|
|
738
|
+
/// minimizes performance overhead.
|
|
739
|
+
///
|
|
740
|
+
/// Not all tests can be re-executed since certain cheatcodes contain
|
|
741
|
+
/// non-deterministic side-effects.
|
|
742
|
+
OnFailure,
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
impl From<CollectStackTraces> for edr_solidity_tests::CollectStackTraces {
|
|
746
|
+
fn from(value: CollectStackTraces) -> Self {
|
|
747
|
+
match value {
|
|
748
|
+
CollectStackTraces::Always => edr_solidity_tests::CollectStackTraces::Always,
|
|
749
|
+
CollectStackTraces::OnFailure => edr_solidity_tests::CollectStackTraces::OnFailure,
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
|
|
724
754
|
/// Configuration for [`SolidityTestRunnerConfigArgs::include_traces`] that
|
|
725
755
|
/// controls execution trace decoding and inclusion in test results.
|
|
726
756
|
#[napi]
|
package/src/solidity_tests/l1.rs
CHANGED
|
@@ -8,7 +8,7 @@ use edr_napi_core::solidity::{
|
|
|
8
8
|
use edr_solidity::artifacts::ArtifactId;
|
|
9
9
|
use edr_solidity_tests::{
|
|
10
10
|
contracts::ContractsByArtifact, decode::RevertDecoder, evm_context::L1EvmBuilder,
|
|
11
|
-
multi_runner::TestContract,
|
|
11
|
+
multi_runner::TestContract, MultiContractRunner,
|
|
12
12
|
};
|
|
13
13
|
use napi::tokio;
|
|
14
14
|
use napi_derive::napi;
|
|
@@ -33,14 +33,14 @@ impl SyncTestRunnerFactory for L1TestRunnerFactory {
|
|
|
33
33
|
let runner = tokio::task::block_in_place(|| {
|
|
34
34
|
runtime
|
|
35
35
|
.block_on(MultiContractRunner::<
|
|
36
|
-
|
|
36
|
+
edr_chain_l1::BlockEnv,
|
|
37
37
|
(),
|
|
38
38
|
L1EvmBuilder,
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
edr_chain_l1::HaltReason,
|
|
40
|
+
edr_chain_l1::Hardfork,
|
|
41
41
|
_,
|
|
42
|
-
|
|
43
|
-
TxEnv,
|
|
42
|
+
edr_chain_l1::InvalidTransaction,
|
|
43
|
+
edr_chain_l1::TxEnv,
|
|
44
44
|
>::new(
|
|
45
45
|
config.try_into()?,
|
|
46
46
|
contracts,
|