@nomicfoundation/edr 0.12.0-next.24 → 0.12.0-next.26
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 +34 -13
- package/index.js +1 -2
- package/package.json +8 -8
- package/src/chains/generic.rs +2 -1
- package/src/chains/l1.rs +2 -1
- package/src/chains/op.rs +2 -1
- package/src/config.rs +14 -2
- package/src/context.rs +2 -2
- package/src/contract_decoder.rs +9 -6
- package/src/gas_report.rs +6 -0
- package/src/mock.rs +4 -10
- package/src/provider/response.rs +45 -43
- package/src/provider.rs +5 -5
- package/src/solidity_tests/artifact.rs +4 -4
- package/src/solidity_tests/config.rs +18 -14
- package/src/solidity_tests/l1.rs +2 -2
- package/src/solidity_tests/op.rs +2 -2
- package/src/solidity_tests/runner.rs +7 -4
- package/src/solidity_tests/test_results.rs +21 -24
- package/src/trace/solidity_stack_trace.rs +216 -186
- package/src/trace.rs +0 -7
package/index.d.ts
CHANGED
|
@@ -273,6 +273,13 @@ export interface ObservabilityConfig {
|
|
|
273
273
|
codeCoverage?: CodeCoverageConfig
|
|
274
274
|
/** If present, configures runtime observability to collect gas reports. */
|
|
275
275
|
gasReport?: GasReportConfig
|
|
276
|
+
/**
|
|
277
|
+
* Controls when to include call traces in the results of transaction
|
|
278
|
+
* execution.
|
|
279
|
+
*
|
|
280
|
+
* Defaults to `IncludeTraces.None`.
|
|
281
|
+
*/
|
|
282
|
+
includeCallTraces?: IncludeTraces
|
|
276
283
|
}
|
|
277
284
|
/** Configuration for a provider */
|
|
278
285
|
export interface ProviderConfig {
|
|
@@ -415,6 +422,13 @@ export interface DeploymentGasReport {
|
|
|
415
422
|
export interface FunctionGasReport {
|
|
416
423
|
gas: bigint
|
|
417
424
|
status: GasReportExecutionStatus
|
|
425
|
+
/**
|
|
426
|
+
* The proxy delegation chain for this call, if the called contract is a
|
|
427
|
+
* proxy. Contains contract identifiers from outermost proxy to final
|
|
428
|
+
* implementation, e.g. `["Proxy", "Implementation"]`.
|
|
429
|
+
* Empty if the call is not through a proxy.
|
|
430
|
+
*/
|
|
431
|
+
proxyChain: Array<string>
|
|
418
432
|
}
|
|
419
433
|
export interface InstrumentationResult {
|
|
420
434
|
/** The generated source code with coverage instrumentation. */
|
|
@@ -974,15 +988,21 @@ export enum CollectStackTraces {
|
|
|
974
988
|
OnFailure = 1
|
|
975
989
|
}
|
|
976
990
|
/**
|
|
977
|
-
* Configuration
|
|
978
|
-
*
|
|
991
|
+
* Configuration that controls whether execution traces are decoded and
|
|
992
|
+
* included in results.
|
|
993
|
+
*
|
|
994
|
+
* This can either be for Solidity test results or provider transaction
|
|
995
|
+
* execution results.
|
|
979
996
|
*/
|
|
980
997
|
export enum IncludeTraces {
|
|
981
|
-
/** No traces will be included
|
|
998
|
+
/** No traces will be included at all. */
|
|
982
999
|
None = 0,
|
|
983
|
-
/**
|
|
1000
|
+
/**
|
|
1001
|
+
* Traces will be included only on the results of failed tests or
|
|
1002
|
+
* execution.
|
|
1003
|
+
*/
|
|
984
1004
|
Failing = 1,
|
|
985
|
-
/** Traces will be included
|
|
1005
|
+
/** Traces will be included for all test results or executed transactions. */
|
|
986
1006
|
All = 2
|
|
987
1007
|
}
|
|
988
1008
|
/** Test function level config override. */
|
|
@@ -1523,11 +1543,6 @@ export interface TracingMessageResult {
|
|
|
1523
1543
|
/** Execution result */
|
|
1524
1544
|
readonly executionResult: ExecutionResult
|
|
1525
1545
|
}
|
|
1526
|
-
/**
|
|
1527
|
-
* Returns the latest version of solc that EDR officially
|
|
1528
|
-
* supports and is tested against.
|
|
1529
|
-
*/
|
|
1530
|
-
export declare function getLatestSupportedSolcVersion(): string
|
|
1531
1546
|
export interface Withdrawal {
|
|
1532
1547
|
/** The index of withdrawal */
|
|
1533
1548
|
index: bigint
|
|
@@ -1586,9 +1601,15 @@ export declare class Response {
|
|
|
1586
1601
|
/**Returns the response data as a JSON string or a JSON object. */
|
|
1587
1602
|
get data(): string | any
|
|
1588
1603
|
/**Compute the error stack trace. Return the stack trace if it can be decoded, otherwise returns none. Throws if there was an error computing the stack trace. */
|
|
1589
|
-
stackTrace():
|
|
1590
|
-
/**
|
|
1591
|
-
|
|
1604
|
+
stackTrace(): StackTrace | UnexpectedError | HeuristicFailed | null
|
|
1605
|
+
/**
|
|
1606
|
+
* Constructs the execution traces for the request. Returns an empty array
|
|
1607
|
+
* if traces are not enabled for this provider according to
|
|
1608
|
+
* [`crate::solidity_tests::config::SolidityTestRunnerConfigArgs::include_traces`]. Otherwise, returns
|
|
1609
|
+
* an array of the root calls of the trace, which always includes the
|
|
1610
|
+
* request's call itself.
|
|
1611
|
+
*/
|
|
1612
|
+
callTraces(): Array<CallTrace>
|
|
1592
1613
|
}
|
|
1593
1614
|
/** A JSON-RPC provider for Ethereum. */
|
|
1594
1615
|
export declare class Provider {
|
package/index.js
CHANGED
|
@@ -310,7 +310,7 @@ if (!nativeBinding) {
|
|
|
310
310
|
throw new Error(`Failed to load native binding`)
|
|
311
311
|
}
|
|
312
312
|
|
|
313
|
-
const { GENERIC_CHAIN_TYPE, genericChainProviderFactory, L1_CHAIN_TYPE, l1GenesisState, l1ProviderFactory, SpecId, l1HardforkFromString, l1HardforkToString, l1HardforkLatest, FRONTIER, FRONTIER_THAWING, HOMESTEAD, DAO_FORK, TANGERINE, SPURIOUS_DRAGON, BYZANTIUM, CONSTANTINOPLE, PETERSBURG, ISTANBUL, MUIR_GLACIER, BERLIN, LONDON, ARROW_GLACIER, GRAY_GLACIER, MERGE, SHANGHAI, CANCUN, PRAGUE, OSAKA, OpHardfork, opHardforkFromString, opHardforkToString, opLatestHardfork, OP_CHAIN_TYPE, opGenesisState, opProviderFactory, BEDROCK, REGOLITH, CANYON, ECOTONE, FJORD, GRANITE, HOLOCENE, ISTHMUS, MineOrdering, EdrContext, ContractDecoder, GasReportExecutionStatus, addStatementCoverageInstrumentation, latestSupportedSolidityVersion, Precompile, precompileP256Verify, ProviderFactory, Response, Provider, SuccessReason, ExceptionalHalt, CheatcodeErrorCode, CachedChains, CachedEndpoints, FsAccessPermission, CollectStackTraces, IncludeTraces, SolidityTestRunnerFactory, l1SolidityTestRunnerFactory, opSolidityTestRunnerFactory, SuiteResult, TestResult, TestStatus, CallKind, LogKind, linkHexStringBytecode, printStackTrace, Exit, ExitCode, BytecodeWrapper, ContractFunctionType, ReturnData, StackTraceEntryType, stackTraceEntryTypeToString, FALLBACK_FUNCTION_NAME, RECEIVE_FUNCTION_NAME, CONSTRUCTOR_FUNCTION_NAME, UNRECOGNIZED_FUNCTION_NAME, UNKNOWN_FUNCTION_NAME, PRECOMPILE_FUNCTION_NAME, UNRECOGNIZED_CONTRACT_NAME, RawTrace
|
|
313
|
+
const { GENERIC_CHAIN_TYPE, genericChainProviderFactory, L1_CHAIN_TYPE, l1GenesisState, l1ProviderFactory, SpecId, l1HardforkFromString, l1HardforkToString, l1HardforkLatest, FRONTIER, FRONTIER_THAWING, HOMESTEAD, DAO_FORK, TANGERINE, SPURIOUS_DRAGON, BYZANTIUM, CONSTANTINOPLE, PETERSBURG, ISTANBUL, MUIR_GLACIER, BERLIN, LONDON, ARROW_GLACIER, GRAY_GLACIER, MERGE, SHANGHAI, CANCUN, PRAGUE, OSAKA, OpHardfork, opHardforkFromString, opHardforkToString, opLatestHardfork, OP_CHAIN_TYPE, opGenesisState, opProviderFactory, BEDROCK, REGOLITH, CANYON, ECOTONE, FJORD, GRANITE, HOLOCENE, ISTHMUS, MineOrdering, EdrContext, ContractDecoder, GasReportExecutionStatus, addStatementCoverageInstrumentation, latestSupportedSolidityVersion, Precompile, precompileP256Verify, ProviderFactory, Response, Provider, SuccessReason, ExceptionalHalt, CheatcodeErrorCode, CachedChains, CachedEndpoints, FsAccessPermission, CollectStackTraces, IncludeTraces, SolidityTestRunnerFactory, l1SolidityTestRunnerFactory, opSolidityTestRunnerFactory, SuiteResult, TestResult, TestStatus, CallKind, LogKind, linkHexStringBytecode, printStackTrace, Exit, ExitCode, BytecodeWrapper, ContractFunctionType, ReturnData, StackTraceEntryType, stackTraceEntryTypeToString, FALLBACK_FUNCTION_NAME, RECEIVE_FUNCTION_NAME, CONSTRUCTOR_FUNCTION_NAME, UNRECOGNIZED_FUNCTION_NAME, UNKNOWN_FUNCTION_NAME, PRECOMPILE_FUNCTION_NAME, UNRECOGNIZED_CONTRACT_NAME, RawTrace } = nativeBinding
|
|
314
314
|
|
|
315
315
|
module.exports.GENERIC_CHAIN_TYPE = GENERIC_CHAIN_TYPE
|
|
316
316
|
module.exports.genericChainProviderFactory = genericChainProviderFactory
|
|
@@ -400,4 +400,3 @@ module.exports.UNKNOWN_FUNCTION_NAME = UNKNOWN_FUNCTION_NAME
|
|
|
400
400
|
module.exports.PRECOMPILE_FUNCTION_NAME = PRECOMPILE_FUNCTION_NAME
|
|
401
401
|
module.exports.UNRECOGNIZED_CONTRACT_NAME = UNRECOGNIZED_CONTRACT_NAME
|
|
402
402
|
module.exports.RawTrace = RawTrace
|
|
403
|
-
module.exports.getLatestSupportedSolcVersion = getLatestSupportedSolcVersion
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nomicfoundation/edr",
|
|
3
|
-
"version": "0.12.0-next.
|
|
3
|
+
"version": "0.12.0-next.26",
|
|
4
4
|
"devDependencies": {
|
|
5
5
|
"@napi-rs/cli": "^2.18.4",
|
|
6
6
|
"@nomicfoundation/ethereumjs-util": "^9.0.4",
|
|
@@ -58,13 +58,13 @@
|
|
|
58
58
|
"repository": "NomicFoundation/edr.git",
|
|
59
59
|
"types": "index.d.ts",
|
|
60
60
|
"dependencies": {
|
|
61
|
-
"@nomicfoundation/edr-darwin-arm64": "0.12.0-next.
|
|
62
|
-
"@nomicfoundation/edr-darwin-x64": "0.12.0-next.
|
|
63
|
-
"@nomicfoundation/edr-linux-arm64-gnu": "0.12.0-next.
|
|
64
|
-
"@nomicfoundation/edr-linux-arm64-musl": "0.12.0-next.
|
|
65
|
-
"@nomicfoundation/edr-linux-x64-gnu": "0.12.0-next.
|
|
66
|
-
"@nomicfoundation/edr-linux-x64-musl": "0.12.0-next.
|
|
67
|
-
"@nomicfoundation/edr-win32-x64-msvc": "0.12.0-next.
|
|
61
|
+
"@nomicfoundation/edr-darwin-arm64": "0.12.0-next.26",
|
|
62
|
+
"@nomicfoundation/edr-darwin-x64": "0.12.0-next.26",
|
|
63
|
+
"@nomicfoundation/edr-linux-arm64-gnu": "0.12.0-next.26",
|
|
64
|
+
"@nomicfoundation/edr-linux-arm64-musl": "0.12.0-next.26",
|
|
65
|
+
"@nomicfoundation/edr-linux-x64-gnu": "0.12.0-next.26",
|
|
66
|
+
"@nomicfoundation/edr-linux-x64-musl": "0.12.0-next.26",
|
|
67
|
+
"@nomicfoundation/edr-win32-x64-msvc": "0.12.0-next.26"
|
|
68
68
|
},
|
|
69
69
|
"scripts": {
|
|
70
70
|
"artifacts": "napi artifacts",
|
package/src/chains/generic.rs
CHANGED
|
@@ -10,6 +10,7 @@ use edr_provider::time::CurrentTime;
|
|
|
10
10
|
use edr_solidity::contract_decoder::ContractDecoder;
|
|
11
11
|
use napi::tokio::runtime;
|
|
12
12
|
use napi_derive::napi;
|
|
13
|
+
use parking_lot::RwLock;
|
|
13
14
|
|
|
14
15
|
use crate::provider::ProviderFactory;
|
|
15
16
|
|
|
@@ -22,7 +23,7 @@ impl SyncProviderFactory for GenericChainProviderFactory {
|
|
|
22
23
|
provider_config: edr_napi_core::provider::Config,
|
|
23
24
|
logger_config: edr_napi_core::logger::Config,
|
|
24
25
|
subscription_callback: edr_napi_core::subscription::Callback,
|
|
25
|
-
contract_decoder: Arc<ContractDecoder
|
|
26
|
+
contract_decoder: Arc<RwLock<ContractDecoder>>,
|
|
26
27
|
) -> napi::Result<Arc<dyn SyncProvider>> {
|
|
27
28
|
let logger = Logger::<GenericChainSpec, CurrentTime>::new(
|
|
28
29
|
logger_config,
|
package/src/chains/l1.rs
CHANGED
|
@@ -17,6 +17,7 @@ use napi::{
|
|
|
17
17
|
tokio::runtime,
|
|
18
18
|
};
|
|
19
19
|
use napi_derive::napi;
|
|
20
|
+
use parking_lot::RwLock;
|
|
20
21
|
|
|
21
22
|
use crate::{account::AccountOverride, provider::ProviderFactory};
|
|
22
23
|
|
|
@@ -29,7 +30,7 @@ impl SyncProviderFactory for L1ProviderFactory {
|
|
|
29
30
|
provider_config: edr_napi_core::provider::Config,
|
|
30
31
|
logger_config: edr_napi_core::logger::Config,
|
|
31
32
|
subscription_callback: edr_napi_core::subscription::Callback,
|
|
32
|
-
contract_decoder: Arc<ContractDecoder
|
|
33
|
+
contract_decoder: Arc<RwLock<ContractDecoder>>,
|
|
33
34
|
) -> napi::Result<Arc<dyn SyncProvider>> {
|
|
34
35
|
let logger =
|
|
35
36
|
Logger::<L1ChainSpec, CurrentTime>::new(logger_config, Arc::clone(&contract_decoder))?;
|
package/src/chains/op.rs
CHANGED
|
@@ -21,6 +21,7 @@ use napi::{
|
|
|
21
21
|
tokio::runtime,
|
|
22
22
|
};
|
|
23
23
|
use napi_derive::napi;
|
|
24
|
+
use parking_lot::RwLock;
|
|
24
25
|
|
|
25
26
|
use crate::{
|
|
26
27
|
account::{AccountOverride, StorageSlot},
|
|
@@ -36,7 +37,7 @@ impl SyncProviderFactory for OpProviderFactory {
|
|
|
36
37
|
provider_config: edr_napi_core::provider::Config,
|
|
37
38
|
logger_config: edr_napi_core::logger::Config,
|
|
38
39
|
subscription_callback: edr_napi_core::subscription::Callback,
|
|
39
|
-
contract_decoder: Arc<ContractDecoder
|
|
40
|
+
contract_decoder: Arc<RwLock<ContractDecoder>>,
|
|
40
41
|
) -> napi::Result<Arc<dyn SyncProvider>> {
|
|
41
42
|
let logger =
|
|
42
43
|
Logger::<OpChainSpec, CurrentTime>::new(logger_config, Arc::clone(&contract_decoder))?;
|
package/src/config.rs
CHANGED
|
@@ -22,7 +22,8 @@ use napi_derive::napi;
|
|
|
22
22
|
|
|
23
23
|
use crate::{
|
|
24
24
|
account::AccountOverride, block::BlobGas, cast::TryCast, gas_report::GasReport,
|
|
25
|
-
logger::LoggerConfig, precompile::Precompile,
|
|
25
|
+
logger::LoggerConfig, precompile::Precompile, solidity_tests::config::IncludeTraces,
|
|
26
|
+
subscription::SubscriptionConfig,
|
|
26
27
|
};
|
|
27
28
|
|
|
28
29
|
/// Configuration for EIP-1559 parameters
|
|
@@ -183,6 +184,11 @@ pub struct ObservabilityConfig {
|
|
|
183
184
|
pub code_coverage: Option<CodeCoverageConfig>,
|
|
184
185
|
/// If present, configures runtime observability to collect gas reports.
|
|
185
186
|
pub gas_report: Option<GasReportConfig>,
|
|
187
|
+
/// Controls when to include call traces in the results of transaction
|
|
188
|
+
/// execution.
|
|
189
|
+
///
|
|
190
|
+
/// Defaults to `IncludeTraces.None`.
|
|
191
|
+
pub include_call_traces: Option<IncludeTraces>,
|
|
186
192
|
}
|
|
187
193
|
|
|
188
194
|
/// Configuration for a provider
|
|
@@ -524,10 +530,16 @@ impl ObservabilityConfig {
|
|
|
524
530
|
},
|
|
525
531
|
).transpose()?;
|
|
526
532
|
|
|
533
|
+
let default_config = edr_provider::observability::Config::default();
|
|
527
534
|
Ok(edr_provider::observability::Config {
|
|
535
|
+
call_override: default_config.call_override,
|
|
536
|
+
include_call_traces: self.include_call_traces.map_or(
|
|
537
|
+
default_config.include_call_traces,
|
|
538
|
+
edr_solidity::config::IncludeTraces::from,
|
|
539
|
+
),
|
|
528
540
|
on_collected_coverage_fn,
|
|
529
541
|
on_collected_gas_report_fn,
|
|
530
|
-
|
|
542
|
+
verbose_raw_tracing: default_config.verbose_raw_tracing,
|
|
531
543
|
})
|
|
532
544
|
}
|
|
533
545
|
}
|
package/src/context.rs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
use std::sync::Arc;
|
|
2
2
|
|
|
3
|
+
use edr_decoder_revert::RevertDecoder;
|
|
3
4
|
use edr_napi_core::{provider::SyncProviderFactory, solidity};
|
|
4
5
|
use edr_primitives::HashMap;
|
|
5
6
|
use edr_solidity_tests::{
|
|
6
|
-
decode::RevertDecoder,
|
|
7
7
|
multi_runner::{SuiteResultAndArtifactId, TestContract, TestContracts},
|
|
8
8
|
TestFilterConfig,
|
|
9
9
|
};
|
|
@@ -251,7 +251,7 @@ impl EdrContext {
|
|
|
251
251
|
|
|
252
252
|
let test_suites = try_or_reject_deferred!(test_suites
|
|
253
253
|
.into_iter()
|
|
254
|
-
.map(
|
|
254
|
+
.map(edr_artifact::ArtifactId::try_from)
|
|
255
255
|
.collect::<Result<Vec<_>, _>>());
|
|
256
256
|
|
|
257
257
|
let contracts = try_or_reject_deferred!(test_suites
|
package/src/contract_decoder.rs
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
use std::sync::Arc;
|
|
2
2
|
|
|
3
3
|
use napi_derive::napi;
|
|
4
|
+
use parking_lot::RwLock;
|
|
4
5
|
|
|
5
6
|
use crate::config::TracingConfigWithBuffers;
|
|
6
7
|
|
|
7
8
|
#[napi]
|
|
8
9
|
pub struct ContractDecoder {
|
|
9
|
-
inner: Arc<edr_solidity::contract_decoder::ContractDecoder
|
|
10
|
+
inner: Arc<RwLock<edr_solidity::contract_decoder::ContractDecoder>>,
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
#[napi]
|
|
@@ -17,7 +18,7 @@ impl ContractDecoder {
|
|
|
17
18
|
#[allow(clippy::new_without_default)]
|
|
18
19
|
pub fn new() -> Self {
|
|
19
20
|
Self {
|
|
20
|
-
inner: Arc::
|
|
21
|
+
inner: Arc::default(),
|
|
21
22
|
}
|
|
22
23
|
}
|
|
23
24
|
|
|
@@ -32,7 +33,7 @@ impl ContractDecoder {
|
|
|
32
33
|
let contract_decoder =
|
|
33
34
|
edr_solidity::contract_decoder::ContractDecoder::new(&build_info_config).map_or_else(
|
|
34
35
|
|error| Err(napi::Error::from_reason(error.to_string())),
|
|
35
|
-
|contract_decoder| Ok(Arc::new(contract_decoder)),
|
|
36
|
+
|contract_decoder| Ok(Arc::new(RwLock::new(contract_decoder))),
|
|
36
37
|
)?;
|
|
37
38
|
|
|
38
39
|
Ok(Self {
|
|
@@ -43,13 +44,15 @@ impl ContractDecoder {
|
|
|
43
44
|
|
|
44
45
|
impl ContractDecoder {
|
|
45
46
|
/// Returns a reference to the inner contract decoder.
|
|
46
|
-
pub fn as_inner(&self) -> &Arc<edr_solidity::contract_decoder::ContractDecoder
|
|
47
|
+
pub fn as_inner(&self) -> &Arc<RwLock<edr_solidity::contract_decoder::ContractDecoder>> {
|
|
47
48
|
&self.inner
|
|
48
49
|
}
|
|
49
50
|
}
|
|
50
51
|
|
|
51
|
-
impl From<Arc<edr_solidity::contract_decoder::ContractDecoder
|
|
52
|
-
fn from(
|
|
52
|
+
impl From<Arc<RwLock<edr_solidity::contract_decoder::ContractDecoder>>> for ContractDecoder {
|
|
53
|
+
fn from(
|
|
54
|
+
contract_decoder: Arc<RwLock<edr_solidity::contract_decoder::ContractDecoder>>,
|
|
55
|
+
) -> Self {
|
|
53
56
|
Self {
|
|
54
57
|
inner: contract_decoder,
|
|
55
58
|
}
|
package/src/gas_report.rs
CHANGED
|
@@ -32,6 +32,11 @@ pub struct DeploymentGasReport {
|
|
|
32
32
|
pub struct FunctionGasReport {
|
|
33
33
|
pub gas: BigInt,
|
|
34
34
|
pub status: GasReportExecutionStatus,
|
|
35
|
+
/// The proxy delegation chain for this call, if the called contract is a
|
|
36
|
+
/// proxy. Contains contract identifiers from outermost proxy to final
|
|
37
|
+
/// implementation, e.g. `["Proxy", "Implementation"]`.
|
|
38
|
+
/// Empty if the call is not through a proxy.
|
|
39
|
+
pub proxy_chain: Vec<String>,
|
|
35
40
|
}
|
|
36
41
|
|
|
37
42
|
impl From<edr_gas_report::GasReport> for GasReport {
|
|
@@ -87,6 +92,7 @@ impl From<edr_gas_report::FunctionGasReport> for FunctionGasReport {
|
|
|
87
92
|
Self {
|
|
88
93
|
gas: BigInt::from(value.gas),
|
|
89
94
|
status: value.status.into(),
|
|
95
|
+
proxy_chain: value.proxy_chain,
|
|
90
96
|
}
|
|
91
97
|
}
|
|
92
98
|
}
|
package/src/mock.rs
CHANGED
|
@@ -2,10 +2,8 @@ pub mod time;
|
|
|
2
2
|
|
|
3
3
|
use std::sync::Arc;
|
|
4
4
|
|
|
5
|
-
use edr_chain_spec::EvmHaltReason;
|
|
6
5
|
use edr_napi_core::provider::SyncProvider;
|
|
7
6
|
use edr_rpc_client::jsonrpc;
|
|
8
|
-
use edr_solidity::contract_decoder::ContractDecoder;
|
|
9
7
|
use napi::tokio::runtime;
|
|
10
8
|
use napi_derive::napi;
|
|
11
9
|
|
|
@@ -23,19 +21,15 @@ impl MockProvider {
|
|
|
23
21
|
}
|
|
24
22
|
|
|
25
23
|
impl SyncProvider for MockProvider {
|
|
26
|
-
fn handle_request(
|
|
27
|
-
&self,
|
|
28
|
-
_request: String,
|
|
29
|
-
_contract_decoder: Arc<ContractDecoder>,
|
|
30
|
-
) -> napi::Result<edr_napi_core::spec::Response<EvmHaltReason>> {
|
|
24
|
+
fn handle_request(&self, _request: String) -> napi::Result<edr_napi_core::spec::Response> {
|
|
31
25
|
let response = jsonrpc::ResponseData::Success {
|
|
32
26
|
result: self.mocked_response.clone(),
|
|
33
27
|
};
|
|
34
28
|
edr_napi_core::spec::marshal_response_data(response)
|
|
35
29
|
.map(|data| edr_napi_core::spec::Response {
|
|
36
|
-
solidity_trace: None,
|
|
37
30
|
data,
|
|
38
|
-
|
|
31
|
+
stack_trace_result: None,
|
|
32
|
+
call_trace_arenas: Vec::new(),
|
|
39
33
|
})
|
|
40
34
|
.map_err(|error| napi::Error::new(napi::Status::GenericFailure, error.to_string()))
|
|
41
35
|
}
|
|
@@ -61,7 +55,7 @@ impl EdrContext {
|
|
|
61
55
|
let provider = Provider::new(
|
|
62
56
|
Arc::new(MockProvider::new(mocked_response)),
|
|
63
57
|
runtime::Handle::current(),
|
|
64
|
-
Arc::
|
|
58
|
+
Arc::default(),
|
|
65
59
|
#[cfg(feature = "scenarios")]
|
|
66
60
|
None,
|
|
67
61
|
);
|
package/src/provider/response.rs
CHANGED
|
@@ -1,21 +1,22 @@
|
|
|
1
|
-
use
|
|
2
|
-
use
|
|
3
|
-
use edr_solidity::contract_decoder::NestedTraceDecoder as _;
|
|
4
|
-
use napi::Either;
|
|
1
|
+
use edr_solidity::solidity_stack_trace::StackTraceCreationResult;
|
|
2
|
+
use napi::{bindgen_prelude::Either3, Either};
|
|
5
3
|
use napi_derive::napi;
|
|
6
4
|
|
|
7
5
|
use crate::{
|
|
8
|
-
|
|
9
|
-
trace::
|
|
6
|
+
solidity_tests::test_results::{CallTrace, HeuristicFailed, StackTrace, UnexpectedError},
|
|
7
|
+
trace::solidity_stack_trace::{
|
|
8
|
+
solidity_stack_trace_error_to_napi, solidity_stack_trace_heuristic_failed_to_napi,
|
|
9
|
+
solidity_stack_trace_success_to_napi,
|
|
10
|
+
},
|
|
10
11
|
};
|
|
11
12
|
|
|
12
13
|
#[napi]
|
|
13
14
|
pub struct Response {
|
|
14
|
-
inner: edr_napi_core::spec::Response
|
|
15
|
+
inner: edr_napi_core::spec::Response,
|
|
15
16
|
}
|
|
16
17
|
|
|
17
|
-
impl From<edr_napi_core::spec::Response
|
|
18
|
-
fn from(value: edr_napi_core::spec::Response
|
|
18
|
+
impl From<edr_napi_core::spec::Response> for Response {
|
|
19
|
+
fn from(value: edr_napi_core::spec::Response) -> Self {
|
|
19
20
|
Self { inner: value }
|
|
20
21
|
}
|
|
21
22
|
}
|
|
@@ -28,46 +29,47 @@ impl Response {
|
|
|
28
29
|
self.inner.data.clone()
|
|
29
30
|
}
|
|
30
31
|
|
|
31
|
-
// Rust port of https://github.com/NomicFoundation/hardhat/blob/c20bf195a6efdc2d74e778b7a4a7799aac224841/packages/hardhat-core/src/internal/hardhat-network/provider/provider.ts#L590
|
|
32
32
|
#[doc = "Compute the error stack trace. Return the stack trace if it can be decoded, otherwise returns none. Throws if there was an error computing the stack trace."]
|
|
33
33
|
#[napi(catch_unwind)]
|
|
34
|
-
pub fn stack_trace(&self) ->
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
.try_to_decode_nested_trace(vm_trace)
|
|
50
|
-
.map_err(|err| napi::Error::from_reason(err.to_string()))?;
|
|
51
|
-
let stack_trace = edr_solidity::solidity_tracer::get_stack_trace(decoded_trace)
|
|
52
|
-
.map_err(|err| napi::Error::from_reason(err.to_string()))?;
|
|
53
|
-
let stack_trace = stack_trace
|
|
54
|
-
.into_iter()
|
|
55
|
-
.map(TryCast::try_cast)
|
|
56
|
-
.collect::<Result<Vec<_>, _>>()?;
|
|
57
|
-
|
|
58
|
-
Ok(Some(stack_trace))
|
|
59
|
-
} else {
|
|
60
|
-
Ok(None)
|
|
61
|
-
}
|
|
34
|
+
pub fn stack_trace(&self) -> Option<Either3<StackTrace, UnexpectedError, HeuristicFailed>> {
|
|
35
|
+
self.inner
|
|
36
|
+
.stack_trace_result
|
|
37
|
+
.as_ref()
|
|
38
|
+
.map(|stack_trace_result| match stack_trace_result {
|
|
39
|
+
StackTraceCreationResult::Success(stack_trace) => {
|
|
40
|
+
Either3::A(solidity_stack_trace_success_to_napi(stack_trace))
|
|
41
|
+
}
|
|
42
|
+
StackTraceCreationResult::Error(error) => {
|
|
43
|
+
Either3::B(solidity_stack_trace_error_to_napi(error))
|
|
44
|
+
}
|
|
45
|
+
StackTraceCreationResult::HeuristicFailed => {
|
|
46
|
+
Either3::C(solidity_stack_trace_heuristic_failed_to_napi())
|
|
47
|
+
}
|
|
48
|
+
})
|
|
62
49
|
}
|
|
63
50
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
51
|
+
/// Constructs the execution traces for the request. Returns an empty array
|
|
52
|
+
/// if traces are not enabled for this provider according to
|
|
53
|
+
/// [`crate::solidity_tests::config::SolidityTestRunnerConfigArgs::include_traces`]. Otherwise, returns
|
|
54
|
+
/// an array of the root calls of the trace, which always includes the
|
|
55
|
+
/// request's call itself.
|
|
56
|
+
#[napi(catch_unwind)]
|
|
57
|
+
pub fn call_traces(&self) -> Vec<CallTrace> {
|
|
67
58
|
self.inner
|
|
68
|
-
.
|
|
59
|
+
.call_trace_arenas
|
|
69
60
|
.iter()
|
|
70
|
-
.map(|
|
|
61
|
+
.map(|call_trace_arena| CallTrace::from_arena_node(call_trace_arena, 0))
|
|
71
62
|
.collect()
|
|
72
63
|
}
|
|
64
|
+
|
|
65
|
+
// TODO(#1288): Add backwards compatibility layer for Hardhat 2
|
|
66
|
+
// #[doc = "Returns the raw traces of executed contracts. This maybe contain
|
|
67
|
+
// zero or more traces."] #[napi(catch_unwind, getter)]
|
|
68
|
+
// pub fn traces(&self) -> Vec<RawTrace> {
|
|
69
|
+
// self.inner
|
|
70
|
+
// .call_trace_arenas
|
|
71
|
+
// .iter()
|
|
72
|
+
// .map(|trace| RawTrace::from(trace.clone()))
|
|
73
|
+
// .collect()
|
|
74
|
+
// }
|
|
73
75
|
}
|
package/src/provider.rs
CHANGED
|
@@ -8,6 +8,7 @@ use edr_napi_core::provider::SyncProvider;
|
|
|
8
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
|
+
use parking_lot::RwLock;
|
|
11
12
|
|
|
12
13
|
pub use self::factory::ProviderFactory;
|
|
13
14
|
use self::response::Response;
|
|
@@ -16,7 +17,7 @@ use crate::{call_override::CallOverrideCallback, contract_decoder::ContractDecod
|
|
|
16
17
|
/// A JSON-RPC provider for Ethereum.
|
|
17
18
|
#[napi]
|
|
18
19
|
pub struct Provider {
|
|
19
|
-
contract_decoder: Arc<edr_solidity::contract_decoder::ContractDecoder
|
|
20
|
+
contract_decoder: Arc<RwLock<edr_solidity::contract_decoder::ContractDecoder>>,
|
|
20
21
|
provider: Arc<dyn SyncProvider>,
|
|
21
22
|
runtime: runtime::Handle,
|
|
22
23
|
#[cfg(feature = "scenarios")]
|
|
@@ -28,7 +29,7 @@ impl Provider {
|
|
|
28
29
|
pub fn new(
|
|
29
30
|
provider: Arc<dyn SyncProvider>,
|
|
30
31
|
runtime: runtime::Handle,
|
|
31
|
-
contract_decoder: Arc<edr_solidity::contract_decoder::ContractDecoder
|
|
32
|
+
contract_decoder: Arc<RwLock<edr_solidity::contract_decoder::ContractDecoder>>,
|
|
32
33
|
#[cfg(feature = "scenarios")] scenario_file: Option<
|
|
33
34
|
napi::tokio::sync::Mutex<napi::tokio::fs::File>,
|
|
34
35
|
>,
|
|
@@ -76,6 +77,7 @@ impl Provider {
|
|
|
76
77
|
}
|
|
77
78
|
};
|
|
78
79
|
|
|
80
|
+
let mut contract_decoder = contract_decoder.write();
|
|
79
81
|
for contract in contracts {
|
|
80
82
|
contract_decoder.add_contract_metadata(contract);
|
|
81
83
|
}
|
|
@@ -102,10 +104,8 @@ impl Provider {
|
|
|
102
104
|
crate::scenarios::write_request(scenario_file, &request).await?;
|
|
103
105
|
}
|
|
104
106
|
|
|
105
|
-
let contract_decoder = Arc::clone(&self.contract_decoder);
|
|
106
|
-
|
|
107
107
|
self.runtime
|
|
108
|
-
.spawn_blocking(move || provider.handle_request(request
|
|
108
|
+
.spawn_blocking(move || provider.handle_request(request))
|
|
109
109
|
.await
|
|
110
110
|
.map_err(|error| napi::Error::new(Status::GenericFailure, error.to_string()))?
|
|
111
111
|
.map(Response::from)
|
|
@@ -27,8 +27,8 @@ pub struct ArtifactId {
|
|
|
27
27
|
pub solc_version: String,
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
impl From<
|
|
31
|
-
fn from(value:
|
|
30
|
+
impl From<edr_artifact::ArtifactId> for ArtifactId {
|
|
31
|
+
fn from(value: edr_artifact::ArtifactId) -> Self {
|
|
32
32
|
Self {
|
|
33
33
|
name: value.name,
|
|
34
34
|
source: value.source.to_string_lossy().to_string(),
|
|
@@ -37,11 +37,11 @@ impl From<edr_solidity::artifacts::ArtifactId> for ArtifactId {
|
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
impl TryFrom<ArtifactId> for
|
|
40
|
+
impl TryFrom<ArtifactId> for edr_artifact::ArtifactId {
|
|
41
41
|
type Error = napi::Error;
|
|
42
42
|
|
|
43
43
|
fn try_from(value: ArtifactId) -> napi::Result<Self> {
|
|
44
|
-
Ok(
|
|
44
|
+
Ok(edr_artifact::ArtifactId {
|
|
45
45
|
name: value.name,
|
|
46
46
|
source: value.source.parse().map_err(|_err| {
|
|
47
47
|
napi::Error::new(napi::Status::GenericFailure, "Invalid source path")
|
|
@@ -822,36 +822,40 @@ impl From<CollectStackTraces> for edr_solidity_tests::CollectStackTraces {
|
|
|
822
822
|
}
|
|
823
823
|
}
|
|
824
824
|
|
|
825
|
-
/// Configuration
|
|
826
|
-
///
|
|
825
|
+
/// Configuration that controls whether execution traces are decoded and
|
|
826
|
+
/// included in results.
|
|
827
|
+
///
|
|
828
|
+
/// This can either be for Solidity test results or provider transaction
|
|
829
|
+
/// execution results.
|
|
827
830
|
#[napi]
|
|
828
831
|
#[derive(Debug, Default, PartialEq, Eq, serde::Serialize)]
|
|
829
832
|
pub enum IncludeTraces {
|
|
830
|
-
/// No traces will be included
|
|
833
|
+
/// No traces will be included at all.
|
|
831
834
|
#[default]
|
|
832
835
|
None,
|
|
833
|
-
/// Traces will be included only on the results of failed tests
|
|
836
|
+
/// Traces will be included only on the results of failed tests or
|
|
837
|
+
/// execution.
|
|
834
838
|
Failing,
|
|
835
|
-
/// Traces will be included
|
|
839
|
+
/// Traces will be included for all test results or executed transactions.
|
|
836
840
|
All,
|
|
837
841
|
}
|
|
838
842
|
|
|
839
|
-
impl From<IncludeTraces> for
|
|
843
|
+
impl From<IncludeTraces> for edr_solidity::config::IncludeTraces {
|
|
840
844
|
fn from(value: IncludeTraces) -> Self {
|
|
841
845
|
match value {
|
|
842
|
-
IncludeTraces::None =>
|
|
843
|
-
IncludeTraces::Failing =>
|
|
844
|
-
IncludeTraces::All =>
|
|
846
|
+
IncludeTraces::None => edr_solidity::config::IncludeTraces::None,
|
|
847
|
+
IncludeTraces::Failing => edr_solidity::config::IncludeTraces::Failing,
|
|
848
|
+
IncludeTraces::All => edr_solidity::config::IncludeTraces::All,
|
|
845
849
|
}
|
|
846
850
|
}
|
|
847
851
|
}
|
|
848
852
|
|
|
849
|
-
impl From<
|
|
850
|
-
fn from(value:
|
|
853
|
+
impl From<edr_solidity::config::IncludeTraces> for IncludeTraces {
|
|
854
|
+
fn from(value: edr_solidity::config::IncludeTraces) -> Self {
|
|
851
855
|
match value {
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
856
|
+
edr_solidity::config::IncludeTraces::None => IncludeTraces::None,
|
|
857
|
+
edr_solidity::config::IncludeTraces::Failing => IncludeTraces::Failing,
|
|
858
|
+
edr_solidity::config::IncludeTraces::All => IncludeTraces::All,
|
|
855
859
|
}
|
|
856
860
|
}
|
|
857
861
|
}
|
package/src/solidity_tests/l1.rs
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
use std::{collections::BTreeMap, sync::Arc};
|
|
2
2
|
|
|
3
|
+
use edr_artifact::ArtifactId;
|
|
4
|
+
use edr_decoder_revert::RevertDecoder;
|
|
3
5
|
use edr_napi_core::solidity::{
|
|
4
6
|
config::{TestRunnerConfig, TracingConfigWithBuffers},
|
|
5
7
|
SyncTestRunner, SyncTestRunnerFactory,
|
|
6
8
|
};
|
|
7
9
|
use edr_primitives::Bytes;
|
|
8
|
-
use edr_solidity::artifacts::ArtifactId;
|
|
9
10
|
use edr_solidity_tests::{
|
|
10
11
|
contracts::ContractsByArtifact,
|
|
11
|
-
decode::RevertDecoder,
|
|
12
12
|
evm_context::L1EvmBuilder,
|
|
13
13
|
multi_runner::TestContract,
|
|
14
14
|
revm::context::{BlockEnv, TxEnv},
|
package/src/solidity_tests/op.rs
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
use std::{collections::BTreeMap, sync::Arc};
|
|
2
2
|
|
|
3
|
+
use edr_artifact::ArtifactId;
|
|
4
|
+
use edr_decoder_revert::RevertDecoder;
|
|
3
5
|
use edr_napi_core::solidity::{
|
|
4
6
|
config::{TestRunnerConfig, TracingConfigWithBuffers},
|
|
5
7
|
SyncTestRunner, SyncTestRunnerFactory,
|
|
6
8
|
};
|
|
7
9
|
use edr_op::{solidity_tests::OpEvmBuilder, transaction::OpTxEnv};
|
|
8
10
|
use edr_primitives::Bytes;
|
|
9
|
-
use edr_solidity::artifacts::ArtifactId;
|
|
10
11
|
use edr_solidity_tests::{
|
|
11
12
|
contracts::ContractsByArtifact,
|
|
12
|
-
decode::RevertDecoder,
|
|
13
13
|
multi_runner::TestContract,
|
|
14
14
|
revm::context::{BlockEnv, TxEnv},
|
|
15
15
|
MultiContractRunner,
|
|
@@ -4,9 +4,12 @@ use edr_chain_spec::HaltReasonTrait;
|
|
|
4
4
|
use edr_napi_core::solidity::config::TracingConfigWithBuffers;
|
|
5
5
|
use edr_solidity::{
|
|
6
6
|
artifacts::BuildInfoConfigWithBuffers,
|
|
7
|
-
contract_decoder::{
|
|
7
|
+
contract_decoder::{
|
|
8
|
+
ContractDecoder, ContractDecoderError, NestedTraceDecoder, NestedTraceDecoderMut as _,
|
|
9
|
+
},
|
|
8
10
|
nested_trace::NestedTrace,
|
|
9
11
|
};
|
|
12
|
+
use parking_lot::RwLock;
|
|
10
13
|
|
|
11
14
|
/// Only parses the tracing config which is very expensive if the contract
|
|
12
15
|
/// decoder is used.
|
|
@@ -15,7 +18,7 @@ pub(crate) struct LazyContractDecoder {
|
|
|
15
18
|
// We need the `Mutex`, because `Uint8Array` is not `Sync`
|
|
16
19
|
tracing_config: Mutex<TracingConfigWithBuffers>,
|
|
17
20
|
// Storing the result so that we can propagate the error
|
|
18
|
-
contract_decoder: OnceLock<Result<ContractDecoder
|
|
21
|
+
contract_decoder: OnceLock<Result<RwLock<ContractDecoder>, ContractDecoderError>>,
|
|
19
22
|
}
|
|
20
23
|
|
|
21
24
|
impl LazyContractDecoder {
|
|
@@ -42,10 +45,10 @@ impl<HaltReasonT: HaltReasonTrait> NestedTraceDecoder<HaltReasonT> for LazyContr
|
|
|
42
45
|
BuildInfoConfigWithBuffers::from(&*tracing_config),
|
|
43
46
|
)
|
|
44
47
|
.map_err(|err| ContractDecoderError::Initialization(err.to_string()))
|
|
45
|
-
.and_then(|config| ContractDecoder::new(&config))
|
|
48
|
+
.and_then(|config| ContractDecoder::new(&config).map(RwLock::new))
|
|
46
49
|
})
|
|
47
50
|
.as_ref()
|
|
48
51
|
.map_err(Clone::clone)
|
|
49
|
-
.and_then(|decoder| decoder.
|
|
52
|
+
.and_then(|decoder| decoder.write().try_to_decode_nested_trace_mut(nested_trace))
|
|
50
53
|
}
|
|
51
54
|
}
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
use std::{
|
|
2
2
|
borrow::Cow,
|
|
3
|
-
convert::Infallible,
|
|
4
3
|
fmt::{Debug, Formatter},
|
|
5
4
|
sync::Arc,
|
|
6
5
|
};
|
|
7
6
|
|
|
8
7
|
use edr_solidity_tests::{
|
|
9
8
|
constants::CHEATCODE_ADDRESS,
|
|
10
|
-
executors::stack_trace::
|
|
9
|
+
executors::stack_trace::SolidityTestStackTraceResult,
|
|
11
10
|
traces::{self, CallTraceArena, SparsedTraceArena},
|
|
12
11
|
};
|
|
13
12
|
use napi::{
|
|
@@ -17,10 +16,15 @@ use napi::{
|
|
|
17
16
|
use napi_derive::napi;
|
|
18
17
|
|
|
19
18
|
use crate::{
|
|
20
|
-
cast::TryCast,
|
|
21
19
|
gas_report::GasReport,
|
|
22
20
|
solidity_tests::{artifact::ArtifactId, config::IncludeTraces},
|
|
23
|
-
trace::{
|
|
21
|
+
trace::{
|
|
22
|
+
solidity_stack_trace::{
|
|
23
|
+
solidity_stack_trace_error_to_napi, solidity_stack_trace_heuristic_failed_to_napi,
|
|
24
|
+
solidity_stack_trace_success_to_napi, SolidityStackTraceEntry,
|
|
25
|
+
},
|
|
26
|
+
u256_to_bigint,
|
|
27
|
+
},
|
|
24
28
|
};
|
|
25
29
|
|
|
26
30
|
/// A grouping of value snapshot entries for a test.
|
|
@@ -64,7 +68,7 @@ pub struct SuiteResult {
|
|
|
64
68
|
|
|
65
69
|
impl SuiteResult {
|
|
66
70
|
pub fn new(
|
|
67
|
-
id:
|
|
71
|
+
id: edr_artifact::ArtifactId,
|
|
68
72
|
suite_result: edr_solidity_tests::result::SuiteResult<String>,
|
|
69
73
|
include_traces: IncludeTraces,
|
|
70
74
|
) -> Self {
|
|
@@ -113,7 +117,7 @@ pub struct TestResult {
|
|
|
113
117
|
#[napi(readonly)]
|
|
114
118
|
pub value_snapshot_groups: Option<Vec<ValueSnapshotGroup>>,
|
|
115
119
|
|
|
116
|
-
stack_trace_result: Option<Arc<
|
|
120
|
+
stack_trace_result: Option<Arc<SolidityTestStackTraceResult<String>>>,
|
|
117
121
|
call_trace_arenas: Vec<(traces::TraceKind, SparsedTraceArena)>,
|
|
118
122
|
}
|
|
119
123
|
|
|
@@ -180,23 +184,16 @@ impl TestResult {
|
|
|
180
184
|
) -> Option<Either4<StackTrace, UnexpectedError, HeuristicFailed, UnsafeToReplay>> {
|
|
181
185
|
self.stack_trace_result.as_ref().map(|stack_trace_result| {
|
|
182
186
|
match stack_trace_result.as_ref() {
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
kind: "UnexpectedError",
|
|
194
|
-
error_message: error.to_string(),
|
|
195
|
-
}),
|
|
196
|
-
StackTraceResult::HeuristicFailed => Either4::C(HeuristicFailed {
|
|
197
|
-
kind: "HeuristicFailed",
|
|
198
|
-
}),
|
|
199
|
-
StackTraceResult::UnsafeToReplay {
|
|
187
|
+
SolidityTestStackTraceResult::Success(stack_trace) => {
|
|
188
|
+
Either4::A(solidity_stack_trace_success_to_napi(stack_trace))
|
|
189
|
+
}
|
|
190
|
+
SolidityTestStackTraceResult::Error(error) => {
|
|
191
|
+
Either4::B(solidity_stack_trace_error_to_napi(error))
|
|
192
|
+
}
|
|
193
|
+
SolidityTestStackTraceResult::HeuristicFailed => {
|
|
194
|
+
Either4::C(solidity_stack_trace_heuristic_failed_to_napi())
|
|
195
|
+
}
|
|
196
|
+
SolidityTestStackTraceResult::UnsafeToReplay {
|
|
200
197
|
global_fork_latest,
|
|
201
198
|
impure_cheatcodes,
|
|
202
199
|
} => Either4::D(UnsafeToReplay {
|
|
@@ -636,7 +633,7 @@ impl CallTrace {
|
|
|
636
633
|
}
|
|
637
634
|
|
|
638
635
|
/// Creates a tree of `CallTrace` rooted at some node in a trace arena.
|
|
639
|
-
fn from_arena_node(arena: &CallTraceArena, arena_index: usize) -> Self {
|
|
636
|
+
pub(crate) fn from_arena_node(arena: &CallTraceArena, arena_index: usize) -> Self {
|
|
640
637
|
struct StackItem {
|
|
641
638
|
visited: bool,
|
|
642
639
|
parent_stack_index: Option<usize>,
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
//! Naive rewrite of `hardhat-network/stack-traces/solidity-stack-traces.ts`
|
|
2
2
|
//! from Hardhat.
|
|
3
3
|
|
|
4
|
-
use std::convert::Infallible;
|
|
5
|
-
|
|
6
4
|
use edr_primitives::{hex, U256};
|
|
7
5
|
use napi::bindgen_prelude::{BigInt, Either25, FromNapiValue, ToNapiValue, Uint8Array, Undefined};
|
|
8
6
|
use napi_derive::napi;
|
|
@@ -10,7 +8,11 @@ use serde::{Serialize, Serializer};
|
|
|
10
8
|
|
|
11
9
|
use super::model::ContractFunctionType;
|
|
12
10
|
use crate::{
|
|
13
|
-
|
|
11
|
+
solidity_tests::{
|
|
12
|
+
cheatcode_errors::CheatcodeErrorDetails,
|
|
13
|
+
test_results::{HeuristicFailed, StackTrace, UnexpectedError},
|
|
14
|
+
},
|
|
15
|
+
trace::u256_to_bigint,
|
|
14
16
|
};
|
|
15
17
|
|
|
16
18
|
#[napi]
|
|
@@ -637,219 +639,247 @@ pub type SolidityStackTraceEntry = Either25<
|
|
|
637
639
|
CheatcodeErrorStackTraceEntry,
|
|
638
640
|
>;
|
|
639
641
|
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
642
|
+
/// Converts an `edr_solidity::solidity_stack_trace::StackTraceEntry` to an
|
|
643
|
+
/// N-API compatible `SolidityStackTraceEntry`.
|
|
644
|
+
fn solidity_stack_trace_entry_to_napi(
|
|
645
|
+
entry: edr_solidity::solidity_stack_trace::StackTraceEntry,
|
|
646
|
+
) -> SolidityStackTraceEntry {
|
|
647
|
+
use edr_solidity::solidity_stack_trace::StackTraceEntry;
|
|
648
|
+
match entry {
|
|
649
|
+
StackTraceEntry::CallstackEntry {
|
|
650
|
+
source_reference,
|
|
651
|
+
function_type,
|
|
652
|
+
} => CallstackEntryStackTraceEntry {
|
|
653
|
+
type_: StackTraceEntryTypeConst,
|
|
654
|
+
source_reference: source_reference.into(),
|
|
655
|
+
function_type: function_type.into(),
|
|
656
|
+
}
|
|
657
|
+
.into(),
|
|
658
|
+
StackTraceEntry::UnrecognizedCreateCallstackEntry => {
|
|
659
|
+
UnrecognizedCreateCallstackEntryStackTraceEntry {
|
|
650
660
|
type_: StackTraceEntryTypeConst,
|
|
651
|
-
source_reference:
|
|
652
|
-
function_type: function_type.into(),
|
|
653
|
-
}
|
|
654
|
-
.into(),
|
|
655
|
-
StackTraceEntry::UnrecognizedCreateCallstackEntry => {
|
|
656
|
-
UnrecognizedCreateCallstackEntryStackTraceEntry {
|
|
657
|
-
type_: StackTraceEntryTypeConst,
|
|
658
|
-
source_reference: None,
|
|
659
|
-
}
|
|
660
|
-
.into()
|
|
661
|
-
}
|
|
662
|
-
StackTraceEntry::UnrecognizedContractCallstackEntry { address } => {
|
|
663
|
-
UnrecognizedContractCallstackEntryStackTraceEntry {
|
|
664
|
-
type_: StackTraceEntryTypeConst,
|
|
665
|
-
address: Uint8Array::with_data_copied(address),
|
|
666
|
-
source_reference: None,
|
|
667
|
-
}
|
|
668
|
-
.into()
|
|
661
|
+
source_reference: None,
|
|
669
662
|
}
|
|
670
|
-
|
|
663
|
+
.into()
|
|
664
|
+
}
|
|
665
|
+
StackTraceEntry::UnrecognizedContractCallstackEntry { address } => {
|
|
666
|
+
UnrecognizedContractCallstackEntryStackTraceEntry {
|
|
671
667
|
type_: StackTraceEntryTypeConst,
|
|
672
|
-
|
|
668
|
+
address: Uint8Array::with_data_copied(address),
|
|
673
669
|
source_reference: None,
|
|
674
670
|
}
|
|
675
|
-
.into()
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
671
|
+
.into()
|
|
672
|
+
}
|
|
673
|
+
StackTraceEntry::PrecompileError { precompile } => PrecompileErrorStackTraceEntry {
|
|
674
|
+
type_: StackTraceEntryTypeConst,
|
|
675
|
+
precompile,
|
|
676
|
+
source_reference: None,
|
|
677
|
+
}
|
|
678
|
+
.into(),
|
|
679
|
+
StackTraceEntry::RevertError {
|
|
680
|
+
return_data,
|
|
681
|
+
source_reference,
|
|
682
|
+
is_invalid_opcode_error,
|
|
683
|
+
} => RevertErrorStackTraceEntry {
|
|
684
|
+
type_: StackTraceEntryTypeConst,
|
|
685
|
+
return_data: return_data.into(),
|
|
686
|
+
source_reference: source_reference.into(),
|
|
687
|
+
is_invalid_opcode_error,
|
|
688
|
+
}
|
|
689
|
+
.into(),
|
|
690
|
+
StackTraceEntry::PanicError {
|
|
691
|
+
error_code,
|
|
692
|
+
source_reference,
|
|
693
|
+
} => PanicErrorStackTraceEntry {
|
|
694
|
+
type_: StackTraceEntryTypeConst,
|
|
695
|
+
error_code: u256_to_bigint(&error_code),
|
|
696
|
+
source_reference: source_reference.map(std::convert::Into::into),
|
|
697
|
+
}
|
|
698
|
+
.into(),
|
|
699
|
+
StackTraceEntry::CheatCodeError {
|
|
700
|
+
message,
|
|
701
|
+
source_reference,
|
|
702
|
+
details,
|
|
703
|
+
} => CheatcodeErrorStackTraceEntry {
|
|
704
|
+
type_: StackTraceEntryTypeConst,
|
|
705
|
+
message,
|
|
706
|
+
source_reference: source_reference.into(),
|
|
707
|
+
details: details.map(std::convert::Into::into),
|
|
708
|
+
}
|
|
709
|
+
.into(),
|
|
710
|
+
StackTraceEntry::CustomError {
|
|
711
|
+
message,
|
|
712
|
+
source_reference,
|
|
713
|
+
} => CustomErrorStackTraceEntry {
|
|
714
|
+
type_: StackTraceEntryTypeConst,
|
|
715
|
+
message,
|
|
716
|
+
source_reference: source_reference.into(),
|
|
717
|
+
}
|
|
718
|
+
.into(),
|
|
719
|
+
StackTraceEntry::FunctionNotPayableError {
|
|
720
|
+
value,
|
|
721
|
+
source_reference,
|
|
722
|
+
} => FunctionNotPayableErrorStackTraceEntry {
|
|
723
|
+
type_: StackTraceEntryTypeConst,
|
|
724
|
+
value: u256_to_bigint(&value),
|
|
725
|
+
source_reference: source_reference.into(),
|
|
726
|
+
}
|
|
727
|
+
.into(),
|
|
728
|
+
StackTraceEntry::InvalidParamsError { source_reference } => {
|
|
729
|
+
InvalidParamsErrorStackTraceEntry {
|
|
681
730
|
type_: StackTraceEntryTypeConst,
|
|
682
|
-
return_data: return_data.into(),
|
|
683
731
|
source_reference: source_reference.into(),
|
|
684
|
-
is_invalid_opcode_error,
|
|
685
732
|
}
|
|
686
|
-
.into()
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
733
|
+
.into()
|
|
734
|
+
}
|
|
735
|
+
StackTraceEntry::FallbackNotPayableError {
|
|
736
|
+
value,
|
|
737
|
+
source_reference,
|
|
738
|
+
} => FallbackNotPayableErrorStackTraceEntry {
|
|
739
|
+
type_: StackTraceEntryTypeConst,
|
|
740
|
+
value: u256_to_bigint(&value),
|
|
741
|
+
source_reference: source_reference.into(),
|
|
742
|
+
}
|
|
743
|
+
.into(),
|
|
744
|
+
StackTraceEntry::FallbackNotPayableAndNoReceiveError {
|
|
745
|
+
value,
|
|
746
|
+
source_reference,
|
|
747
|
+
} => FallbackNotPayableAndNoReceiveErrorStackTraceEntry {
|
|
748
|
+
type_: StackTraceEntryTypeConst,
|
|
749
|
+
value: u256_to_bigint(&value),
|
|
750
|
+
source_reference: source_reference.into(),
|
|
751
|
+
}
|
|
752
|
+
.into(),
|
|
753
|
+
StackTraceEntry::UnrecognizedFunctionWithoutFallbackError { source_reference } => {
|
|
754
|
+
UnrecognizedFunctionWithoutFallbackErrorStackTraceEntry {
|
|
701
755
|
type_: StackTraceEntryTypeConst,
|
|
702
|
-
message,
|
|
703
756
|
source_reference: source_reference.into(),
|
|
704
|
-
details: details.map(std::convert::Into::into),
|
|
705
757
|
}
|
|
706
|
-
.into()
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
} => CustomErrorStackTraceEntry {
|
|
758
|
+
.into()
|
|
759
|
+
}
|
|
760
|
+
StackTraceEntry::MissingFallbackOrReceiveError { source_reference } => {
|
|
761
|
+
MissingFallbackOrReceiveErrorStackTraceEntry {
|
|
711
762
|
type_: StackTraceEntryTypeConst,
|
|
712
|
-
message,
|
|
713
763
|
source_reference: source_reference.into(),
|
|
714
764
|
}
|
|
715
|
-
.into()
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
} => FunctionNotPayableErrorStackTraceEntry {
|
|
765
|
+
.into()
|
|
766
|
+
}
|
|
767
|
+
StackTraceEntry::ReturndataSizeError { source_reference } => {
|
|
768
|
+
ReturndataSizeErrorStackTraceEntry {
|
|
720
769
|
type_: StackTraceEntryTypeConst,
|
|
721
|
-
value: u256_to_bigint(&value),
|
|
722
770
|
source_reference: source_reference.into(),
|
|
723
771
|
}
|
|
724
|
-
.into()
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
source_reference: source_reference.into(),
|
|
729
|
-
}
|
|
730
|
-
.into()
|
|
731
|
-
}
|
|
732
|
-
StackTraceEntry::FallbackNotPayableError {
|
|
733
|
-
value,
|
|
734
|
-
source_reference,
|
|
735
|
-
} => FallbackNotPayableErrorStackTraceEntry {
|
|
772
|
+
.into()
|
|
773
|
+
}
|
|
774
|
+
StackTraceEntry::NoncontractAccountCalledError { source_reference } => {
|
|
775
|
+
NonContractAccountCalledErrorStackTraceEntry {
|
|
736
776
|
type_: StackTraceEntryTypeConst,
|
|
737
|
-
value: u256_to_bigint(&value),
|
|
738
777
|
source_reference: source_reference.into(),
|
|
739
778
|
}
|
|
740
|
-
.into()
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
779
|
+
.into()
|
|
780
|
+
}
|
|
781
|
+
StackTraceEntry::CallFailedError { source_reference } => CallFailedErrorStackTraceEntry {
|
|
782
|
+
type_: StackTraceEntryTypeConst,
|
|
783
|
+
source_reference: source_reference.into(),
|
|
784
|
+
}
|
|
785
|
+
.into(),
|
|
786
|
+
StackTraceEntry::DirectLibraryCallError { source_reference } => {
|
|
787
|
+
DirectLibraryCallErrorStackTraceEntry {
|
|
745
788
|
type_: StackTraceEntryTypeConst,
|
|
746
|
-
value: u256_to_bigint(&value),
|
|
747
789
|
source_reference: source_reference.into(),
|
|
748
790
|
}
|
|
749
|
-
.into()
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
}
|
|
776
|
-
.into()
|
|
777
|
-
}
|
|
778
|
-
StackTraceEntry::CallFailedError { source_reference } => {
|
|
779
|
-
CallFailedErrorStackTraceEntry {
|
|
780
|
-
type_: StackTraceEntryTypeConst,
|
|
781
|
-
source_reference: source_reference.into(),
|
|
782
|
-
}
|
|
783
|
-
.into()
|
|
784
|
-
}
|
|
785
|
-
StackTraceEntry::DirectLibraryCallError { source_reference } => {
|
|
786
|
-
DirectLibraryCallErrorStackTraceEntry {
|
|
787
|
-
type_: StackTraceEntryTypeConst,
|
|
788
|
-
source_reference: source_reference.into(),
|
|
789
|
-
}
|
|
790
|
-
.into()
|
|
791
|
-
}
|
|
792
|
-
StackTraceEntry::UnrecognizedCreateError {
|
|
793
|
-
return_data,
|
|
794
|
-
is_invalid_opcode_error,
|
|
795
|
-
} => UnrecognizedCreateErrorStackTraceEntry {
|
|
791
|
+
.into()
|
|
792
|
+
}
|
|
793
|
+
StackTraceEntry::UnrecognizedCreateError {
|
|
794
|
+
return_data,
|
|
795
|
+
is_invalid_opcode_error,
|
|
796
|
+
} => UnrecognizedCreateErrorStackTraceEntry {
|
|
797
|
+
type_: StackTraceEntryTypeConst,
|
|
798
|
+
return_data: return_data.into(),
|
|
799
|
+
is_invalid_opcode_error,
|
|
800
|
+
source_reference: None,
|
|
801
|
+
}
|
|
802
|
+
.into(),
|
|
803
|
+
StackTraceEntry::UnrecognizedContractError {
|
|
804
|
+
address,
|
|
805
|
+
return_data,
|
|
806
|
+
is_invalid_opcode_error,
|
|
807
|
+
} => UnrecognizedContractErrorStackTraceEntry {
|
|
808
|
+
type_: StackTraceEntryTypeConst,
|
|
809
|
+
address: Uint8Array::with_data_copied(address),
|
|
810
|
+
return_data: return_data.into(),
|
|
811
|
+
is_invalid_opcode_error,
|
|
812
|
+
source_reference: None,
|
|
813
|
+
}
|
|
814
|
+
.into(),
|
|
815
|
+
StackTraceEntry::OtherExecutionError { source_reference } => {
|
|
816
|
+
OtherExecutionErrorStackTraceEntry {
|
|
796
817
|
type_: StackTraceEntryTypeConst,
|
|
797
|
-
|
|
798
|
-
is_invalid_opcode_error,
|
|
799
|
-
source_reference: None,
|
|
818
|
+
source_reference: source_reference.map(std::convert::Into::into),
|
|
800
819
|
}
|
|
801
|
-
.into()
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
is_invalid_opcode_error,
|
|
806
|
-
} => UnrecognizedContractErrorStackTraceEntry {
|
|
820
|
+
.into()
|
|
821
|
+
}
|
|
822
|
+
StackTraceEntry::UnmappedSolc0_6_3RevertError { source_reference } => {
|
|
823
|
+
UnmappedSolc063RevertErrorStackTraceEntry {
|
|
807
824
|
type_: StackTraceEntryTypeConst,
|
|
808
|
-
|
|
809
|
-
return_data: return_data.into(),
|
|
810
|
-
is_invalid_opcode_error,
|
|
811
|
-
source_reference: None,
|
|
812
|
-
}
|
|
813
|
-
.into(),
|
|
814
|
-
StackTraceEntry::OtherExecutionError { source_reference } => {
|
|
815
|
-
OtherExecutionErrorStackTraceEntry {
|
|
816
|
-
type_: StackTraceEntryTypeConst,
|
|
817
|
-
source_reference: source_reference.map(std::convert::Into::into),
|
|
818
|
-
}
|
|
819
|
-
.into()
|
|
820
|
-
}
|
|
821
|
-
StackTraceEntry::UnmappedSolc0_6_3RevertError { source_reference } => {
|
|
822
|
-
UnmappedSolc063RevertErrorStackTraceEntry {
|
|
823
|
-
type_: StackTraceEntryTypeConst,
|
|
824
|
-
source_reference: source_reference.map(std::convert::Into::into),
|
|
825
|
-
}
|
|
826
|
-
.into()
|
|
827
|
-
}
|
|
828
|
-
StackTraceEntry::ContractTooLargeError { source_reference } => {
|
|
829
|
-
ContractTooLargeErrorStackTraceEntry {
|
|
830
|
-
type_: StackTraceEntryTypeConst,
|
|
831
|
-
source_reference: source_reference.map(std::convert::Into::into),
|
|
832
|
-
}
|
|
833
|
-
.into()
|
|
825
|
+
source_reference: source_reference.map(std::convert::Into::into),
|
|
834
826
|
}
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
827
|
+
.into()
|
|
828
|
+
}
|
|
829
|
+
StackTraceEntry::ContractTooLargeError { source_reference } => {
|
|
830
|
+
ContractTooLargeErrorStackTraceEntry {
|
|
839
831
|
type_: StackTraceEntryTypeConst,
|
|
840
|
-
|
|
841
|
-
source_reference: source_reference.into(),
|
|
832
|
+
source_reference: source_reference.map(std::convert::Into::into),
|
|
842
833
|
}
|
|
843
|
-
.into()
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
834
|
+
.into()
|
|
835
|
+
}
|
|
836
|
+
StackTraceEntry::InternalFunctionCallstackEntry {
|
|
837
|
+
pc,
|
|
838
|
+
source_reference,
|
|
839
|
+
} => InternalFunctionCallStackEntry {
|
|
840
|
+
type_: StackTraceEntryTypeConst,
|
|
841
|
+
pc,
|
|
842
|
+
source_reference: source_reference.into(),
|
|
843
|
+
}
|
|
844
|
+
.into(),
|
|
845
|
+
StackTraceEntry::ContractCallRunOutOfGasError { source_reference } => {
|
|
846
|
+
ContractCallRunOutOfGasError {
|
|
847
|
+
type_: StackTraceEntryTypeConst,
|
|
848
|
+
source_reference: source_reference.map(std::convert::Into::into),
|
|
850
849
|
}
|
|
851
|
-
|
|
852
|
-
|
|
850
|
+
.into()
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
/// Converts the contents of a `SolidityTestStackTraceResult::Success` to an
|
|
856
|
+
/// N-API compatible `StackTrace`.
|
|
857
|
+
pub fn solidity_stack_trace_success_to_napi(
|
|
858
|
+
stack_trace: &[edr_solidity::solidity_stack_trace::StackTraceEntry],
|
|
859
|
+
) -> StackTrace {
|
|
860
|
+
StackTrace {
|
|
861
|
+
kind: "StackTrace",
|
|
862
|
+
entries: stack_trace
|
|
863
|
+
.iter()
|
|
864
|
+
.cloned()
|
|
865
|
+
.map(solidity_stack_trace_entry_to_napi)
|
|
866
|
+
.collect(),
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
/// Converts an error from `SolidityTestStackTraceResult::UnexpectedError` to
|
|
871
|
+
/// an N-API compatible `UnexpectedError`.
|
|
872
|
+
pub fn solidity_stack_trace_error_to_napi<ErrorT: ToString>(error: ErrorT) -> UnexpectedError {
|
|
873
|
+
UnexpectedError {
|
|
874
|
+
kind: "UnexpectedError",
|
|
875
|
+
error_message: error.to_string(),
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
/// Constructs a `HeuristicFailed` N-API object.
|
|
880
|
+
pub fn solidity_stack_trace_heuristic_failed_to_napi() -> HeuristicFailed {
|
|
881
|
+
HeuristicFailed {
|
|
882
|
+
kind: "HeuristicFailed",
|
|
853
883
|
}
|
|
854
884
|
}
|
|
855
885
|
|
package/src/trace.rs
CHANGED