@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 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 for [`SolidityTestRunnerConfigArgs::include_traces`] that
978
- * controls execution trace decoding and inclusion in test results.
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 in any test result. */
998
+ /** No traces will be included at all. */
982
999
  None = 0,
983
- /** Traces will be included only on the results of failed tests. */
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 in all test results. */
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(): SolidityStackTrace | null
1590
- /**Returns the raw traces of executed contracts. This maybe contain zero or more traces. */
1591
- get traces(): Array<RawTrace>
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, getLatestSupportedSolcVersion } = nativeBinding
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.24",
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.24",
62
- "@nomicfoundation/edr-darwin-x64": "0.12.0-next.24",
63
- "@nomicfoundation/edr-linux-arm64-gnu": "0.12.0-next.24",
64
- "@nomicfoundation/edr-linux-arm64-musl": "0.12.0-next.24",
65
- "@nomicfoundation/edr-linux-x64-gnu": "0.12.0-next.24",
66
- "@nomicfoundation/edr-linux-x64-musl": "0.12.0-next.24",
67
- "@nomicfoundation/edr-win32-x64-msvc": "0.12.0-next.24"
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",
@@ -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, subscription::SubscriptionConfig,
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
- ..edr_provider::observability::Config::default()
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(edr_solidity::artifacts::ArtifactId::try_from)
254
+ .map(edr_artifact::ArtifactId::try_from)
255
255
  .collect::<Result<Vec<_>, _>>());
256
256
 
257
257
  let contracts = try_or_reject_deferred!(test_suites
@@ -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::new(edr_solidity::contract_decoder::ContractDecoder::default()),
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>> for ContractDecoder {
52
- fn from(contract_decoder: Arc<edr_solidity::contract_decoder::ContractDecoder>) -> Self {
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
- traces: Vec::new(),
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::new(ContractDecoder::default()),
58
+ Arc::default(),
65
59
  #[cfg(feature = "scenarios")]
66
60
  None,
67
61
  );
@@ -1,21 +1,22 @@
1
- use edr_chain_spec::EvmHaltReason;
2
- use edr_napi_core::spec::SolidityTraceData;
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
- cast::TryCast,
9
- trace::{solidity_stack_trace::SolidityStackTrace, RawTrace},
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<EvmHaltReason>,
15
+ inner: edr_napi_core::spec::Response,
15
16
  }
16
17
 
17
- impl From<edr_napi_core::spec::Response<EvmHaltReason>> for Response {
18
- fn from(value: edr_napi_core::spec::Response<EvmHaltReason>) -> Self {
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) -> napi::Result<Option<SolidityStackTrace>> {
35
- let Some(SolidityTraceData {
36
- trace,
37
- contract_decoder,
38
- }) = &self.inner.solidity_trace
39
- else {
40
- return Ok(None);
41
- };
42
- let nested_trace = edr_solidity::nested_tracer::convert_trace_messages_to_nested_trace(
43
- trace.as_ref().clone(),
44
- )
45
- .map_err(|err| napi::Error::from_reason(err.to_string()))?;
46
-
47
- if let Some(vm_trace) = nested_trace {
48
- let decoded_trace = contract_decoder
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
- #[doc = "Returns the raw traces of executed contracts. This maybe contain zero or more traces."]
65
- #[napi(catch_unwind, getter)]
66
- pub fn traces(&self) -> Vec<RawTrace> {
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
- .traces
59
+ .call_trace_arenas
69
60
  .iter()
70
- .map(|trace| RawTrace::from(trace.clone()))
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, contract_decoder))
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<edr_solidity::artifacts::ArtifactId> for ArtifactId {
31
- fn from(value: edr_solidity::artifacts::ArtifactId) -> Self {
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 edr_solidity::artifacts::ArtifactId {
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(edr_solidity::artifacts::ArtifactId {
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 for [`SolidityTestRunnerConfigArgs::include_traces`] that
826
- /// controls execution trace decoding and inclusion in test results.
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 in any test result.
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 in all test results.
839
+ /// Traces will be included for all test results or executed transactions.
836
840
  All,
837
841
  }
838
842
 
839
- impl From<IncludeTraces> for edr_solidity_tests::IncludeTraces {
843
+ impl From<IncludeTraces> for edr_solidity::config::IncludeTraces {
840
844
  fn from(value: IncludeTraces) -> Self {
841
845
  match value {
842
- IncludeTraces::None => edr_solidity_tests::IncludeTraces::None,
843
- IncludeTraces::Failing => edr_solidity_tests::IncludeTraces::Failing,
844
- IncludeTraces::All => edr_solidity_tests::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<edr_solidity_tests::IncludeTraces> for IncludeTraces {
850
- fn from(value: edr_solidity_tests::IncludeTraces) -> Self {
853
+ impl From<edr_solidity::config::IncludeTraces> for IncludeTraces {
854
+ fn from(value: edr_solidity::config::IncludeTraces) -> Self {
851
855
  match value {
852
- edr_solidity_tests::IncludeTraces::None => IncludeTraces::None,
853
- edr_solidity_tests::IncludeTraces::Failing => IncludeTraces::Failing,
854
- edr_solidity_tests::IncludeTraces::All => IncludeTraces::All,
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
  }
@@ -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},
@@ -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::{ContractDecoder, ContractDecoderError, NestedTraceDecoder},
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, ContractDecoderError>>,
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.try_to_decode_nested_trace(nested_trace))
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::StackTraceResult,
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::{solidity_stack_trace::SolidityStackTraceEntry, u256_to_bigint},
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: edr_solidity::artifacts::ArtifactId,
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<StackTraceResult<String>>>,
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
- StackTraceResult::Success(stack_trace) => Either4::A(StackTrace {
184
- kind: "StackTrace",
185
- entries: stack_trace
186
- .iter()
187
- .cloned()
188
- .map(TryCast::try_cast)
189
- .collect::<Result<Vec<_>, Infallible>>()
190
- .expect("infallible"),
191
- }),
192
- StackTraceResult::Error(error) => Either4::B(UnexpectedError {
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
- cast::TryCast, solidity_tests::cheatcode_errors::CheatcodeErrorDetails, trace::u256_to_bigint,
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
- impl TryCast<SolidityStackTraceEntry> for edr_solidity::solidity_stack_trace::StackTraceEntry {
641
- type Error = Infallible;
642
-
643
- fn try_cast(self) -> Result<SolidityStackTraceEntry, Self::Error> {
644
- use edr_solidity::solidity_stack_trace::StackTraceEntry;
645
- let result = match self {
646
- StackTraceEntry::CallstackEntry {
647
- source_reference,
648
- function_type,
649
- } => CallstackEntryStackTraceEntry {
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: source_reference.into(),
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
- StackTraceEntry::PrecompileError { precompile } => PrecompileErrorStackTraceEntry {
663
+ .into()
664
+ }
665
+ StackTraceEntry::UnrecognizedContractCallstackEntry { address } => {
666
+ UnrecognizedContractCallstackEntryStackTraceEntry {
671
667
  type_: StackTraceEntryTypeConst,
672
- precompile,
668
+ address: Uint8Array::with_data_copied(address),
673
669
  source_reference: None,
674
670
  }
675
- .into(),
676
- StackTraceEntry::RevertError {
677
- return_data,
678
- source_reference,
679
- is_invalid_opcode_error,
680
- } => RevertErrorStackTraceEntry {
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
- StackTraceEntry::PanicError {
688
- error_code,
689
- source_reference,
690
- } => PanicErrorStackTraceEntry {
691
- type_: StackTraceEntryTypeConst,
692
- error_code: u256_to_bigint(&error_code),
693
- source_reference: source_reference.map(std::convert::Into::into),
694
- }
695
- .into(),
696
- StackTraceEntry::CheatCodeError {
697
- message,
698
- source_reference,
699
- details,
700
- } => CheatcodeErrorStackTraceEntry {
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
- StackTraceEntry::CustomError {
708
- message,
709
- source_reference,
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
- StackTraceEntry::FunctionNotPayableError {
717
- value,
718
- source_reference,
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
- StackTraceEntry::InvalidParamsError { source_reference } => {
726
- InvalidParamsErrorStackTraceEntry {
727
- type_: StackTraceEntryTypeConst,
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
- StackTraceEntry::FallbackNotPayableAndNoReceiveError {
742
- value,
743
- source_reference,
744
- } => FallbackNotPayableAndNoReceiveErrorStackTraceEntry {
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
- StackTraceEntry::UnrecognizedFunctionWithoutFallbackError { source_reference } => {
751
- UnrecognizedFunctionWithoutFallbackErrorStackTraceEntry {
752
- type_: StackTraceEntryTypeConst,
753
- source_reference: source_reference.into(),
754
- }
755
- .into()
756
- }
757
- StackTraceEntry::MissingFallbackOrReceiveError { source_reference } => {
758
- MissingFallbackOrReceiveErrorStackTraceEntry {
759
- type_: StackTraceEntryTypeConst,
760
- source_reference: source_reference.into(),
761
- }
762
- .into()
763
- }
764
- StackTraceEntry::ReturndataSizeError { source_reference } => {
765
- ReturndataSizeErrorStackTraceEntry {
766
- type_: StackTraceEntryTypeConst,
767
- source_reference: source_reference.into(),
768
- }
769
- .into()
770
- }
771
- StackTraceEntry::NoncontractAccountCalledError { source_reference } => {
772
- NonContractAccountCalledErrorStackTraceEntry {
773
- type_: StackTraceEntryTypeConst,
774
- source_reference: source_reference.into(),
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
- return_data: return_data.into(),
798
- is_invalid_opcode_error,
799
- source_reference: None,
818
+ source_reference: source_reference.map(std::convert::Into::into),
800
819
  }
801
- .into(),
802
- StackTraceEntry::UnrecognizedContractError {
803
- address,
804
- return_data,
805
- is_invalid_opcode_error,
806
- } => UnrecognizedContractErrorStackTraceEntry {
820
+ .into()
821
+ }
822
+ StackTraceEntry::UnmappedSolc0_6_3RevertError { source_reference } => {
823
+ UnmappedSolc063RevertErrorStackTraceEntry {
807
824
  type_: StackTraceEntryTypeConst,
808
- address: Uint8Array::with_data_copied(address),
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
- StackTraceEntry::InternalFunctionCallstackEntry {
836
- pc,
837
- source_reference,
838
- } => InternalFunctionCallStackEntry {
827
+ .into()
828
+ }
829
+ StackTraceEntry::ContractTooLargeError { source_reference } => {
830
+ ContractTooLargeErrorStackTraceEntry {
839
831
  type_: StackTraceEntryTypeConst,
840
- pc,
841
- source_reference: source_reference.into(),
832
+ source_reference: source_reference.map(std::convert::Into::into),
842
833
  }
843
- .into(),
844
- StackTraceEntry::ContractCallRunOutOfGasError { source_reference } => {
845
- ContractCallRunOutOfGasError {
846
- type_: StackTraceEntryTypeConst,
847
- source_reference: source_reference.map(std::convert::Into::into),
848
- }
849
- .into()
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
- Ok(result)
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
@@ -190,10 +190,3 @@ impl RawTrace {
190
190
  .collect()
191
191
  }
192
192
  }
193
-
194
- #[napi]
195
- /// Returns the latest version of solc that EDR officially
196
- /// supports and is tested against.
197
- pub fn get_latest_supported_solc_version() -> String {
198
- "0.8.28".to_string()
199
- }