@nomicfoundation/edr 0.12.0-next.2 → 0.12.0-next.20

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.
@@ -18,6 +18,7 @@ use napi_derive::napi;
18
18
 
19
19
  use crate::{
20
20
  cast::TryCast,
21
+ gas_report::GasReport,
21
22
  solidity_tests::{artifact::ArtifactId, config::IncludeTraces},
22
23
  trace::{solidity_stack_trace::SolidityStackTraceEntry, u256_to_bigint},
23
24
  };
@@ -42,7 +43,7 @@ pub struct ValueSnapshotEntry {
42
43
  pub value: String,
43
44
  }
44
45
 
45
- /// See [edr_solidity_tests::result::SuiteResult]
46
+ /// See [`edr_solidity_tests::result::SuiteResult`]
46
47
  #[napi]
47
48
  #[derive(Clone, Debug)]
48
49
  pub struct SuiteResult {
@@ -50,13 +51,13 @@ pub struct SuiteResult {
50
51
  /// callback
51
52
  #[napi(readonly)]
52
53
  pub id: ArtifactId,
53
- /// See [edr_solidity_tests::result::SuiteResult::duration]
54
+ /// See [`edr_solidity_tests::result::SuiteResult::duration`]
54
55
  #[napi(readonly)]
55
56
  pub duration_ns: BigInt,
56
- /// See [edr_solidity_tests::result::SuiteResult::test_results]
57
+ /// See [`edr_solidity_tests::result::SuiteResult::test_results`]
57
58
  #[napi(readonly)]
58
59
  pub test_results: Vec<TestResult>,
59
- /// See [edr_solidity_tests::result::SuiteResult::warnings]
60
+ /// See [`edr_solidity_tests::result::SuiteResult::warnings`]
60
61
  #[napi(readonly)]
61
62
  pub warnings: Vec<String>,
62
63
  }
@@ -80,29 +81,29 @@ impl SuiteResult {
80
81
  }
81
82
  }
82
83
 
83
- /// See [edr_solidity_tests::result::TestResult]
84
+ /// See [`edr_solidity_tests::result::TestResult`]
84
85
  #[napi]
85
86
  #[derive(Clone, Debug)]
86
87
  pub struct TestResult {
87
88
  /// The name of the test.
88
89
  #[napi(readonly)]
89
90
  pub name: String,
90
- /// See [edr_solidity_tests::result::TestResult::status]
91
+ /// See [`edr_solidity_tests::result::TestResult::status`]
91
92
  #[napi(readonly)]
92
93
  pub status: TestStatus,
93
- /// See [edr_solidity_tests::result::TestResult::reason]
94
+ /// See [`edr_solidity_tests::result::TestResult::reason`]
94
95
  #[napi(readonly)]
95
96
  pub reason: Option<String>,
96
- /// See [edr_solidity_tests::result::TestResult::counterexample]
97
+ /// See [`edr_solidity_tests::result::TestResult::counterexample`]
97
98
  #[napi(readonly)]
98
99
  pub counterexample: Option<Either<BaseCounterExample, CounterExampleSequence>>,
99
- /// See [edr_solidity_tests::result::TestResult::decoded_logs]
100
+ /// See [`edr_solidity_tests::result::TestResult::decoded_logs`]
100
101
  #[napi(readonly)]
101
102
  pub decoded_logs: Vec<String>,
102
- /// See [edr_solidity_tests::result::TestResult::kind]
103
+ /// See [`edr_solidity_tests::result::TestResult::kind`]
103
104
  #[napi(readonly)]
104
105
  pub kind: Either3<StandardTestKind, FuzzTestKind, InvariantTestKind>,
105
- /// See [edr_solidity_tests::result::TestResult::duration]
106
+ /// See [`edr_solidity_tests::result::TestResult::duration`]
106
107
  #[napi(readonly)]
107
108
  pub duration_ns: BigInt,
108
109
  /// Groups of value snapshot entries (incl. gas).
@@ -263,7 +264,7 @@ impl TestResult {
263
264
  }),
264
265
  decoded_logs: test_result.decoded_logs,
265
266
  kind: match test_result.kind {
266
- edr_solidity_tests::result::TestKind::Standard(gas_consumed) => {
267
+ edr_solidity_tests::result::TestKind::Unit { gas: gas_consumed } => {
267
268
  Either3::A(StandardTestKind {
268
269
  consumed_gas: BigInt::from(gas_consumed),
269
270
  })
@@ -282,11 +283,27 @@ impl TestResult {
282
283
  runs,
283
284
  calls,
284
285
  reverts,
286
+ metrics,
287
+ failed_corpus_replays,
285
288
  } => Either3::C(InvariantTestKind {
286
289
  // usize as u64 is always safe
287
290
  runs: BigInt::from(runs as u64),
288
291
  calls: BigInt::from(calls as u64),
289
292
  reverts: BigInt::from(reverts as u64),
293
+ metrics: metrics
294
+ .into_iter()
295
+ .map(|(name, metric)| {
296
+ (
297
+ name,
298
+ InvariantMetrics {
299
+ calls: BigInt::from(metric.calls as u64),
300
+ reverts: BigInt::from(metric.reverts as u64),
301
+ discards: BigInt::from(metric.discards as u64),
302
+ },
303
+ )
304
+ })
305
+ .collect(),
306
+ failed_corpus_replays: BigInt::from(failed_corpus_replays as u64),
290
307
  }),
291
308
  },
292
309
  duration_ns: BigInt::from(test_result.duration.as_nanos()),
@@ -335,7 +352,7 @@ impl From<edr_solidity_tests::result::TestStatus> for TestStatus {
335
352
  }
336
353
  }
337
354
 
338
- /// See [edr_solidity_tests::result::TestKind::Standard]
355
+ /// See [`edr_solidity_tests::result::TestKind::Unit`]
339
356
  #[napi(object)]
340
357
  #[derive(Debug, Clone)]
341
358
  pub struct StandardTestKind {
@@ -344,22 +361,22 @@ pub struct StandardTestKind {
344
361
  pub consumed_gas: BigInt,
345
362
  }
346
363
 
347
- /// See [edr_solidity_tests::result::TestKind::Fuzz]
364
+ /// See [`edr_solidity_tests::result::TestKind::Fuzz`]
348
365
  #[napi(object)]
349
366
  #[derive(Debug, Clone)]
350
367
  pub struct FuzzTestKind {
351
- /// See [edr_solidity_tests::result::TestKind::Fuzz]
368
+ /// See [`edr_solidity_tests::result::TestKind::Fuzz`]
352
369
  #[napi(readonly)]
353
370
  pub runs: BigInt,
354
- /// See [edr_solidity_tests::result::TestKind::Fuzz]
371
+ /// See [`edr_solidity_tests::result::TestKind::Fuzz`]
355
372
  #[napi(readonly)]
356
373
  pub mean_gas: BigInt,
357
- /// See [edr_solidity_tests::result::TestKind::Fuzz]
374
+ /// See [`edr_solidity_tests::result::TestKind::Fuzz`]
358
375
  #[napi(readonly)]
359
376
  pub median_gas: BigInt,
360
377
  }
361
378
 
362
- /// See [edr_solidity_tests::fuzz::FuzzCase]
379
+ /// See [`edr_solidity_tests::fuzz::FuzzCase`]
363
380
  #[napi(object)]
364
381
  #[derive(Clone)]
365
382
  pub struct FuzzCase {
@@ -383,19 +400,40 @@ impl Debug for FuzzCase {
383
400
  }
384
401
  }
385
402
 
386
- /// See [edr_solidity_tests::result::TestKind::Invariant]
403
+ /// See [`edr_solidity_tests::result::TestKind::Invariant`]
387
404
  #[napi(object)]
388
405
  #[derive(Debug, Clone)]
389
406
  pub struct InvariantTestKind {
390
- /// See [edr_solidity_tests::result::TestKind::Invariant]
407
+ /// See [`edr_solidity_tests::result::TestKind::Invariant`]
391
408
  #[napi(readonly)]
392
409
  pub runs: BigInt,
393
- /// See [edr_solidity_tests::result::TestKind::Invariant]
410
+ /// See [`edr_solidity_tests::result::TestKind::Invariant`]
394
411
  #[napi(readonly)]
395
412
  pub calls: BigInt,
396
- /// See [edr_solidity_tests::result::TestKind::Invariant]
413
+ /// See [`edr_solidity_tests::result::TestKind::Invariant`]
397
414
  #[napi(readonly)]
398
415
  pub reverts: BigInt,
416
+ /// See [`edr_solidity_tests::result::TestKind::Invariant`]
417
+ #[napi(readonly)]
418
+ pub metrics: std::collections::HashMap<String, InvariantMetrics>,
419
+ /// See [`edr_solidity_tests::result::TestKind::Invariant`]
420
+ #[napi(readonly)]
421
+ pub failed_corpus_replays: BigInt,
422
+ }
423
+
424
+ /// See [`edr_solidity_tests::result::InvariantMetrics`]
425
+ #[napi(object)]
426
+ #[derive(Debug, Clone)]
427
+ pub struct InvariantMetrics {
428
+ // Count of fuzzed selector calls.
429
+ #[napi(readonly)]
430
+ pub calls: BigInt,
431
+ // Count of fuzzed selector reverts.
432
+ #[napi(readonly)]
433
+ pub reverts: BigInt,
434
+ // Count of fuzzed selector discards (through assume cheatcodes).
435
+ #[napi(readonly)]
436
+ pub discards: BigInt,
399
437
  }
400
438
 
401
439
  /// Original sequence size and sequence of calls used as a counter example
@@ -409,26 +447,26 @@ pub struct CounterExampleSequence {
409
447
  pub sequence: Vec<BaseCounterExample>,
410
448
  }
411
449
 
412
- /// See [edr_solidity_tests::fuzz::BaseCounterExample]
450
+ /// See [`edr_solidity_tests::fuzz::BaseCounterExample`]
413
451
  #[napi(object)]
414
452
  #[derive(Clone)]
415
453
  pub struct BaseCounterExample {
416
- /// See [edr_solidity_tests::fuzz::BaseCounterExample::sender]
454
+ /// See [`edr_solidity_tests::fuzz::BaseCounterExample::sender`]
417
455
  #[napi(readonly)]
418
456
  pub sender: Option<Uint8Array>,
419
- /// See [edr_solidity_tests::fuzz::BaseCounterExample::addr]
457
+ /// See [`edr_solidity_tests::fuzz::BaseCounterExample::addr`]
420
458
  #[napi(readonly)]
421
459
  pub address: Option<Uint8Array>,
422
- /// See [edr_solidity_tests::fuzz::BaseCounterExample::calldata]
460
+ /// See [`edr_solidity_tests::fuzz::BaseCounterExample::calldata`]
423
461
  #[napi(readonly)]
424
462
  pub calldata: Uint8Array,
425
- /// See [edr_solidity_tests::fuzz::BaseCounterExample::contract_name]
463
+ /// See [`edr_solidity_tests::fuzz::BaseCounterExample::contract_name`]
426
464
  #[napi(readonly)]
427
465
  pub contract_name: Option<String>,
428
- /// See [edr_solidity_tests::fuzz::BaseCounterExample::signature]
466
+ /// See [`edr_solidity_tests::fuzz::BaseCounterExample::signature`]
429
467
  #[napi(readonly)]
430
468
  pub signature: Option<String>,
431
- /// See [edr_solidity_tests::fuzz::BaseCounterExample::args]
469
+ /// See [`edr_solidity_tests::fuzz::BaseCounterExample::args`]
432
470
  #[napi(readonly)]
433
471
  pub args: Option<String>,
434
472
  }
@@ -542,10 +580,19 @@ impl CallTrace {
542
580
  /// Instantiates a `CallTrace` with the details from a node and the supplied
543
581
  /// children.
544
582
  fn new(node: &traces::CallTraceNode, children: Vec<Either<CallTrace, LogTrace>>) -> Self {
545
- let contract = node.trace.decoded.label.clone();
583
+ let contract = node
584
+ .trace
585
+ .decoded
586
+ .as_ref()
587
+ .and_then(|decoded| decoded.label.clone());
546
588
  let address = node.trace.address.to_checksum(None);
547
589
 
548
- let inputs = match &node.trace.decoded.call_data {
590
+ let inputs = match &node
591
+ .trace
592
+ .decoded
593
+ .as_ref()
594
+ .and_then(|decoded| decoded.call_data.as_ref())
595
+ {
549
596
  Some(traces::DecodedCallData { signature, args }) => {
550
597
  let name = signature
551
598
  .split('(')
@@ -558,7 +605,12 @@ impl CallTrace {
558
605
  None => Either::B(node.trace.data.as_ref().into()),
559
606
  };
560
607
 
561
- let outputs = match &node.trace.decoded.return_data {
608
+ let outputs = match node
609
+ .trace
610
+ .decoded
611
+ .as_ref()
612
+ .and_then(|decoded| decoded.return_data.as_ref())
613
+ {
562
614
  Some(outputs) => Either::A(outputs.clone()),
563
615
  None => {
564
616
  if node.kind().is_any_create() && node.trace.success {
@@ -604,7 +656,10 @@ impl CallTrace {
604
656
  loop {
605
657
  // We will break out of the loop before the stack goes empty.
606
658
  let mut item = stack.pop().unwrap();
607
- let node = &arena.nodes()[item.arena_index];
659
+ let node = arena
660
+ .nodes()
661
+ .get(item.arena_index)
662
+ .expect("Arena index should be valid");
608
663
 
609
664
  if item.visited {
610
665
  let mut logs = node
@@ -618,11 +673,20 @@ impl CallTrace {
618
673
  .iter()
619
674
  .filter_map(|ord| match *ord {
620
675
  traces::TraceMemberOrder::Log(i) => {
621
- let log = logs[i].take().unwrap();
676
+ let log = logs
677
+ .get_mut(i)
678
+ .expect("Log index should be valid")
679
+ .take()
680
+ .unwrap();
622
681
  Some(Either::B(log))
623
682
  }
624
683
  traces::TraceMemberOrder::Call(i) => {
625
- let child_trace = item.child_traces[i].take().unwrap();
684
+ let child_trace = item
685
+ .child_traces
686
+ .get_mut(i)
687
+ .expect("Child trace index should be valid")
688
+ .take()
689
+ .unwrap();
626
690
  Some(Either::A(child_trace))
627
691
  }
628
692
  traces::TraceMemberOrder::Step(_) => None,
@@ -632,7 +696,9 @@ impl CallTrace {
632
696
  let trace = CallTrace::new(node, children);
633
697
 
634
698
  if let Some(parent_stack_index) = item.parent_stack_index {
635
- let parent = &mut stack[parent_stack_index];
699
+ let parent = stack
700
+ .get_mut(parent_stack_index)
701
+ .expect("Parent stack index should be valid");
636
702
  parent.child_traces.push(Some(trace));
637
703
  } else {
638
704
  return trace;
@@ -661,7 +727,10 @@ impl CallTrace {
661
727
 
662
728
  impl From<&traces::CallLog> for LogTrace {
663
729
  fn from(log: &traces::CallLog) -> Self {
664
- let decoded_log = log.decoded.name.clone().zip(log.decoded.params.as_ref());
730
+ let decoded_log = log
731
+ .decoded
732
+ .as_ref()
733
+ .and_then(|decoded| decoded.name.clone().zip(decoded.params.as_ref()));
665
734
 
666
735
  let parameters = decoded_log.map_or_else(
667
736
  || {
@@ -703,3 +772,19 @@ impl From<traces::CallKind> for CallKind {
703
772
  }
704
773
  }
705
774
  }
775
+
776
+ /// The result of a Solidity test run.
777
+ #[napi(object)]
778
+ pub struct SolidityTestResult {
779
+ /// Gas report, if it was generated.
780
+ #[napi(readonly)]
781
+ pub gas_report: Option<GasReport>,
782
+ }
783
+
784
+ impl From<edr_solidity_tests::multi_runner::SolidityTestResult> for SolidityTestResult {
785
+ fn from(value: edr_solidity_tests::multi_runner::SolidityTestResult) -> Self {
786
+ Self {
787
+ gas_report: value.gas_report.map(GasReport::from),
788
+ }
789
+ }
790
+ }
@@ -9,7 +9,7 @@ pub mod test_results;
9
9
 
10
10
  use std::path::Path;
11
11
 
12
- use edr_eth::Bytes;
12
+ use edr_primitives::Bytes;
13
13
  use edr_solidity::linker::{LinkOutput, Linker};
14
14
  use edr_solidity_tests::{constants::LIBRARY_DEPLOYER, contracts::ContractsByArtifact};
15
15
  use foundry_compilers::artifacts::Libraries;
@@ -1,6 +1,6 @@
1
1
  //! Port of `hardhat-network/stack-traces/debug.ts` from Hardhat.
2
2
 
3
- use napi::bindgen_prelude::Either24;
3
+ use napi::bindgen_prelude::Either25;
4
4
  use napi_derive::napi;
5
5
 
6
6
  use super::solidity_stack_trace::{RevertErrorStackTraceEntry, SolidityStackTrace};
@@ -11,31 +11,32 @@ fn print_stack_trace(trace: SolidityStackTrace) -> napi::Result<()> {
11
11
  let entry_values = trace
12
12
  .into_iter()
13
13
  .map(|entry| match entry {
14
- Either24::A(entry) => serde_json::to_value(entry),
15
- Either24::B(entry) => serde_json::to_value(entry),
16
- Either24::C(entry) => serde_json::to_value(entry),
17
- Either24::D(entry) => serde_json::to_value(entry),
18
- Either24::F(entry) => serde_json::to_value(entry),
19
- Either24::G(entry) => serde_json::to_value(entry),
20
- Either24::H(entry) => serde_json::to_value(entry),
21
- Either24::I(entry) => serde_json::to_value(entry),
22
- Either24::J(entry) => serde_json::to_value(entry),
23
- Either24::K(entry) => serde_json::to_value(entry),
24
- Either24::L(entry) => serde_json::to_value(entry),
25
- Either24::M(entry) => serde_json::to_value(entry),
26
- Either24::N(entry) => serde_json::to_value(entry),
27
- Either24::O(entry) => serde_json::to_value(entry),
28
- Either24::P(entry) => serde_json::to_value(entry),
29
- Either24::Q(entry) => serde_json::to_value(entry),
30
- Either24::R(entry) => serde_json::to_value(entry),
31
- Either24::S(entry) => serde_json::to_value(entry),
32
- Either24::T(entry) => serde_json::to_value(entry),
33
- Either24::U(entry) => serde_json::to_value(entry),
34
- Either24::V(entry) => serde_json::to_value(entry),
35
- Either24::W(entry) => serde_json::to_value(entry),
36
- Either24::X(entry) => serde_json::to_value(entry),
14
+ Either25::A(entry) => serde_json::to_value(entry),
15
+ Either25::B(entry) => serde_json::to_value(entry),
16
+ Either25::C(entry) => serde_json::to_value(entry),
17
+ Either25::D(entry) => serde_json::to_value(entry),
18
+ Either25::F(entry) => serde_json::to_value(entry),
19
+ Either25::G(entry) => serde_json::to_value(entry),
20
+ Either25::H(entry) => serde_json::to_value(entry),
21
+ Either25::I(entry) => serde_json::to_value(entry),
22
+ Either25::J(entry) => serde_json::to_value(entry),
23
+ Either25::K(entry) => serde_json::to_value(entry),
24
+ Either25::L(entry) => serde_json::to_value(entry),
25
+ Either25::M(entry) => serde_json::to_value(entry),
26
+ Either25::N(entry) => serde_json::to_value(entry),
27
+ Either25::O(entry) => serde_json::to_value(entry),
28
+ Either25::P(entry) => serde_json::to_value(entry),
29
+ Either25::Q(entry) => serde_json::to_value(entry),
30
+ Either25::R(entry) => serde_json::to_value(entry),
31
+ Either25::S(entry) => serde_json::to_value(entry),
32
+ Either25::T(entry) => serde_json::to_value(entry),
33
+ Either25::U(entry) => serde_json::to_value(entry),
34
+ Either25::V(entry) => serde_json::to_value(entry),
35
+ Either25::W(entry) => serde_json::to_value(entry),
36
+ Either25::X(entry) => serde_json::to_value(entry),
37
+ Either25::Y(entry) => serde_json::to_value(entry),
37
38
  // Decode the error message from the return data
38
- Either24::E(entry @ RevertErrorStackTraceEntry { .. }) => {
39
+ Either25::E(entry @ RevertErrorStackTraceEntry { .. }) => {
39
40
  use serde::de::Error;
40
41
 
41
42
  let decoded_error_msg = ReturnData::new(entry.return_data.clone())
@@ -45,7 +46,9 @@ fn print_stack_trace(trace: SolidityStackTrace) -> napi::Result<()> {
45
46
  })?;
46
47
 
47
48
  let mut value = serde_json::to_value(entry)?;
48
- value["message"] = decoded_error_msg.into();
49
+ if let Some(obj) = value.as_object_mut() {
50
+ obj.insert("message".to_string(), decoded_error_msg.into());
51
+ }
49
52
  Ok(value)
50
53
  }
51
54
  })
package/src/trace/exit.rs CHANGED
@@ -3,6 +3,7 @@
3
3
 
4
4
  use std::fmt;
5
5
 
6
+ use edr_chain_spec::EvmHaltReason;
6
7
  use napi_derive::napi;
7
8
 
8
9
  #[napi]
@@ -50,20 +51,20 @@ impl fmt::Display for ExitCode {
50
51
  }
51
52
 
52
53
  #[allow(clippy::fallible_impl_from)] // naively ported for now
53
- impl From<edr_solidity::exit_code::ExitCode<edr_eth::l1::HaltReason>> for ExitCode {
54
- fn from(code: edr_solidity::exit_code::ExitCode<edr_eth::l1::HaltReason>) -> Self {
54
+ impl From<edr_solidity::exit_code::ExitCode<EvmHaltReason>> for ExitCode {
55
+ fn from(code: edr_solidity::exit_code::ExitCode<EvmHaltReason>) -> Self {
55
56
  use edr_solidity::exit_code::ExitCode;
56
57
 
57
58
  match code {
58
59
  ExitCode::Success => Self::SUCCESS,
59
60
  ExitCode::Revert => Self::REVERT,
60
- ExitCode::Halt(edr_eth::l1::HaltReason::OutOfGas(_)) => Self::OUT_OF_GAS,
61
- ExitCode::Halt(edr_eth::l1::HaltReason::OpcodeNotFound | edr_eth::l1::HaltReason::InvalidFEOpcode
61
+ ExitCode::Halt(EvmHaltReason::OutOfGas(_)) => Self::OUT_OF_GAS,
62
+ ExitCode::Halt(EvmHaltReason::OpcodeNotFound | EvmHaltReason::InvalidFEOpcode
62
63
  // Returned when an opcode is not implemented for the hardfork
63
- | edr_eth::l1::HaltReason::NotActivated) => Self::INVALID_OPCODE,
64
- ExitCode::Halt(edr_eth::l1::HaltReason::StackUnderflow) => Self::STACK_UNDERFLOW,
65
- ExitCode::Halt(edr_eth::l1::HaltReason::CreateContractSizeLimit) => Self::CODESIZE_EXCEEDS_MAXIMUM,
66
- ExitCode::Halt(edr_eth::l1::HaltReason::CreateCollision) => Self::CREATE_COLLISION,
64
+ | EvmHaltReason::NotActivated) => Self::INVALID_OPCODE,
65
+ ExitCode::Halt(EvmHaltReason::StackUnderflow) => Self::STACK_UNDERFLOW,
66
+ ExitCode::Halt(EvmHaltReason::CreateContractSizeLimit) => Self::CODESIZE_EXCEEDS_MAXIMUM,
67
+ ExitCode::Halt(EvmHaltReason::CreateCollision) => Self::CREATE_COLLISION,
67
68
  _ => Self::UNKNOWN_HALT_REASON,
68
69
  }
69
70
  }
@@ -22,11 +22,9 @@ pub struct ReturnData {
22
22
  impl ReturnData {
23
23
  #[napi(catch_unwind, constructor)]
24
24
  pub fn new(value: Uint8Array) -> Self {
25
- let selector = if value.len() >= 4 {
26
- Some(value[0..4].try_into().unwrap())
27
- } else {
28
- None
29
- };
25
+ let selector = value
26
+ .get(0..4)
27
+ .map(|selector| selector.try_into().expect("selector is 4 bytes"));
30
28
 
31
29
  Self { value, selector }
32
30
  }
@@ -57,10 +55,17 @@ impl ReturnData {
57
55
  return Ok(String::new());
58
56
  }
59
57
 
58
+ if !self.is_error_return_data() {
59
+ return Err(napi::Error::new(
60
+ napi::Status::InvalidArg,
61
+ "VM Exception while processing transaction: Expected return data to be a Error(string)",
62
+ ));
63
+ }
64
+
60
65
  let result = Error::abi_decode(&self.value[..]).map_err(|_err| {
61
66
  napi::Error::new(
62
67
  napi::Status::InvalidArg,
63
- "Expected return data to be a Error(string) and contain a valid string",
68
+ "VM Exception while processing transaction: Expected return data to contain a valid string",
64
69
  )
65
70
  })?;
66
71
 
@@ -69,10 +74,17 @@ impl ReturnData {
69
74
 
70
75
  #[napi(catch_unwind)]
71
76
  pub fn decode_panic(&self) -> napi::Result<BigInt> {
77
+ if !self.is_panic_return_data() {
78
+ return Err(napi::Error::new(
79
+ napi::Status::InvalidArg,
80
+ "VM Exception while processing transaction: Expected return data to be a Panic(uint256)",
81
+ ));
82
+ }
83
+
72
84
  let result = Panic::abi_decode(&self.value[..]).map_err(|_err| {
73
85
  napi::Error::new(
74
86
  napi::Status::InvalidArg,
75
- "Expected return data to be a Error(string) and contain a valid string",
87
+ "VM Exception while processing transaction: Expected return data to contain a valid uint256",
76
88
  )
77
89
  })?;
78
90