@nomicfoundation/edr 0.12.0-alpha.0 → 0.12.0-next.1
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/Cargo.toml +47 -16
- package/LICENSE +5 -1
- package/index.d.ts +794 -104
- package/index.js +31 -1
- package/package.json +20 -17
- package/src/account.rs +102 -55
- package/src/block.rs +2 -103
- package/src/call_override.rs +8 -8
- package/src/cast.rs +7 -29
- package/src/chains/generic.rs +1 -1
- package/src/chains/l1.rs +20 -18
- package/src/chains/op.rs +95 -38
- package/src/config.rs +305 -161
- package/src/context.rs +260 -21
- package/src/debug_trace.rs +2 -2
- package/src/instrument.rs +109 -0
- package/src/lib.rs +10 -0
- package/src/log.rs +12 -14
- package/src/logger.rs +28 -30
- package/src/mock.rs +68 -0
- package/src/precompile.rs +50 -0
- package/src/provider/response.rs +8 -5
- package/src/provider.rs +14 -8
- package/src/result.rs +18 -27
- package/src/scenarios.rs +2 -2
- package/src/serde.rs +57 -0
- package/src/solidity_tests/artifact.rs +184 -0
- package/src/solidity_tests/config.rs +725 -0
- package/src/solidity_tests/factory.rs +22 -0
- package/src/solidity_tests/l1.rs +68 -0
- package/src/solidity_tests/op.rs +69 -0
- package/src/solidity_tests/runner.rs +51 -0
- package/src/solidity_tests/test_results.rs +707 -0
- package/src/solidity_tests.rs +56 -0
- package/src/subscription.rs +1 -1
- package/src/trace/debug.rs +1 -1
- package/src/trace/exit.rs +4 -4
- package/src/trace/library_utils.rs +7 -2
- package/src/trace/return_data.rs +10 -10
- package/src/trace/solidity_stack_trace.rs +7 -5
- package/src/trace.rs +29 -38
- package/src/withdrawal.rs +3 -3
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
pub mod artifact;
|
|
2
|
+
pub mod config;
|
|
3
|
+
pub mod factory;
|
|
4
|
+
pub mod l1;
|
|
5
|
+
#[cfg(feature = "op")]
|
|
6
|
+
pub mod op;
|
|
7
|
+
pub mod runner;
|
|
8
|
+
pub mod test_results;
|
|
9
|
+
|
|
10
|
+
use std::path::Path;
|
|
11
|
+
|
|
12
|
+
use edr_eth::Bytes;
|
|
13
|
+
use edr_solidity::linker::{LinkOutput, Linker};
|
|
14
|
+
use edr_solidity_tests::{constants::LIBRARY_DEPLOYER, contracts::ContractsByArtifact};
|
|
15
|
+
use foundry_compilers::artifacts::Libraries;
|
|
16
|
+
|
|
17
|
+
use crate::solidity_tests::artifact::Artifact;
|
|
18
|
+
|
|
19
|
+
pub(crate) struct LinkingOutput {
|
|
20
|
+
pub libs_to_deploy: Vec<Bytes>,
|
|
21
|
+
pub known_contracts: ContractsByArtifact,
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
impl LinkingOutput {
|
|
25
|
+
pub fn link(project_root: &Path, artifacts: Vec<Artifact>) -> napi::Result<Self> {
|
|
26
|
+
let artifact_contracts = artifacts
|
|
27
|
+
.into_iter()
|
|
28
|
+
.map(|artifact| Ok((artifact.id.try_into()?, artifact.contract.try_into()?)))
|
|
29
|
+
.collect::<napi::Result<Vec<_>>>()?;
|
|
30
|
+
|
|
31
|
+
let linker = Linker::new(project_root, artifact_contracts);
|
|
32
|
+
|
|
33
|
+
let LinkOutput {
|
|
34
|
+
libraries,
|
|
35
|
+
libs_to_deploy,
|
|
36
|
+
} = linker
|
|
37
|
+
.link_with_nonce_or_address(
|
|
38
|
+
Libraries::default(),
|
|
39
|
+
LIBRARY_DEPLOYER,
|
|
40
|
+
0,
|
|
41
|
+
linker.contracts.keys(),
|
|
42
|
+
)
|
|
43
|
+
.map_err(|error| napi::Error::from_reason(error.to_string()))?;
|
|
44
|
+
|
|
45
|
+
let linked_contracts = linker
|
|
46
|
+
.get_linked_artifacts(&libraries)
|
|
47
|
+
.map_err(|error| napi::Error::from_reason(error.to_string()))?;
|
|
48
|
+
|
|
49
|
+
let known_contracts = ContractsByArtifact::new(linked_contracts);
|
|
50
|
+
|
|
51
|
+
Ok(LinkingOutput {
|
|
52
|
+
libs_to_deploy,
|
|
53
|
+
known_contracts,
|
|
54
|
+
})
|
|
55
|
+
}
|
|
56
|
+
}
|
package/src/subscription.rs
CHANGED
package/src/trace/debug.rs
CHANGED
|
@@ -6,7 +6,7 @@ use napi_derive::napi;
|
|
|
6
6
|
use super::solidity_stack_trace::{RevertErrorStackTraceEntry, SolidityStackTrace};
|
|
7
7
|
use crate::trace::return_data::ReturnData;
|
|
8
8
|
|
|
9
|
-
#[napi]
|
|
9
|
+
#[napi(catch_unwind)]
|
|
10
10
|
fn print_stack_trace(trace: SolidityStackTrace) -> napi::Result<()> {
|
|
11
11
|
let entry_values = trace
|
|
12
12
|
.into_iter()
|
package/src/trace/exit.rs
CHANGED
|
@@ -64,24 +64,24 @@ impl From<edr_solidity::exit_code::ExitCode<edr_eth::l1::HaltReason>> for ExitCo
|
|
|
64
64
|
ExitCode::Halt(edr_eth::l1::HaltReason::StackUnderflow) => Self::STACK_UNDERFLOW,
|
|
65
65
|
ExitCode::Halt(edr_eth::l1::HaltReason::CreateContractSizeLimit) => Self::CODESIZE_EXCEEDS_MAXIMUM,
|
|
66
66
|
ExitCode::Halt(edr_eth::l1::HaltReason::CreateCollision) => Self::CREATE_COLLISION,
|
|
67
|
-
|
|
67
|
+
_ => Self::UNKNOWN_HALT_REASON,
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
#[napi]
|
|
73
73
|
impl Exit {
|
|
74
|
-
#[napi(getter)]
|
|
74
|
+
#[napi(catch_unwind, getter)]
|
|
75
75
|
pub fn kind(&self) -> ExitCode {
|
|
76
76
|
self.0
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
#[napi]
|
|
79
|
+
#[napi(catch_unwind)]
|
|
80
80
|
pub fn is_error(&self) -> bool {
|
|
81
81
|
!matches!(self.0, ExitCode::SUCCESS)
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
-
#[napi]
|
|
84
|
+
#[napi(catch_unwind)]
|
|
85
85
|
pub fn get_reason(&self) -> String {
|
|
86
86
|
self.0.to_string()
|
|
87
87
|
}
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
use napi_derive::napi;
|
|
2
2
|
|
|
3
|
-
#[napi]
|
|
4
|
-
pub fn link_hex_string_bytecode(
|
|
3
|
+
#[napi(catch_unwind)]
|
|
4
|
+
pub fn link_hex_string_bytecode(
|
|
5
|
+
code: String,
|
|
6
|
+
address: String,
|
|
7
|
+
position: u32,
|
|
8
|
+
) -> napi::Result<String> {
|
|
5
9
|
edr_solidity::library_utils::link_hex_string_bytecode(code, &address, position)
|
|
10
|
+
.map_err(|err| napi::Error::from_reason(err.to_string()))
|
|
6
11
|
}
|
package/src/trace/return_data.rs
CHANGED
|
@@ -20,7 +20,7 @@ pub struct ReturnData {
|
|
|
20
20
|
|
|
21
21
|
#[napi]
|
|
22
22
|
impl ReturnData {
|
|
23
|
-
#[napi(constructor)]
|
|
23
|
+
#[napi(catch_unwind, constructor)]
|
|
24
24
|
pub fn new(value: Uint8Array) -> Self {
|
|
25
25
|
let selector = if value.len() >= 4 {
|
|
26
26
|
Some(value[0..4].try_into().unwrap())
|
|
@@ -31,7 +31,7 @@ impl ReturnData {
|
|
|
31
31
|
Self { value, selector }
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
#[napi]
|
|
34
|
+
#[napi(catch_unwind)]
|
|
35
35
|
pub fn is_empty(&self) -> bool {
|
|
36
36
|
self.value.is_empty()
|
|
37
37
|
}
|
|
@@ -41,35 +41,35 @@ impl ReturnData {
|
|
|
41
41
|
.is_some_and(|value| value == selector.as_ref())
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
#[napi]
|
|
44
|
+
#[napi(catch_unwind)]
|
|
45
45
|
pub fn is_error_return_data(&self) -> bool {
|
|
46
46
|
self.selector == Some(Error::SELECTOR)
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
#[napi]
|
|
49
|
+
#[napi(catch_unwind)]
|
|
50
50
|
pub fn is_panic_return_data(&self) -> bool {
|
|
51
51
|
self.selector == Some(Panic::SELECTOR)
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
#[napi]
|
|
54
|
+
#[napi(catch_unwind)]
|
|
55
55
|
pub fn decode_error(&self) -> napi::Result<String> {
|
|
56
56
|
if self.is_empty() {
|
|
57
57
|
return Ok(String::new());
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
let result = Error::abi_decode(&self.value[..]
|
|
60
|
+
let result = Error::abi_decode(&self.value[..]).map_err(|_err| {
|
|
61
61
|
napi::Error::new(
|
|
62
62
|
napi::Status::InvalidArg,
|
|
63
63
|
"Expected return data to be a Error(string) and contain a valid string",
|
|
64
64
|
)
|
|
65
65
|
})?;
|
|
66
66
|
|
|
67
|
-
Ok(result.
|
|
67
|
+
Ok(result.0)
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
#[napi]
|
|
70
|
+
#[napi(catch_unwind)]
|
|
71
71
|
pub fn decode_panic(&self) -> napi::Result<BigInt> {
|
|
72
|
-
let result = Panic::abi_decode(&self.value[..]
|
|
72
|
+
let result = Panic::abi_decode(&self.value[..]).map_err(|_err| {
|
|
73
73
|
napi::Error::new(
|
|
74
74
|
napi::Status::InvalidArg,
|
|
75
75
|
"Expected return data to be a Error(string) and contain a valid string",
|
|
@@ -78,7 +78,7 @@ impl ReturnData {
|
|
|
78
78
|
|
|
79
79
|
Ok(BigInt {
|
|
80
80
|
sign_bit: false,
|
|
81
|
-
words: result.
|
|
81
|
+
words: result.0.as_limbs().to_vec(),
|
|
82
82
|
})
|
|
83
83
|
}
|
|
84
84
|
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
//! Naive rewrite of `hardhat-network/stack-traces/solidity-stack-traces.ts`
|
|
2
2
|
//! from Hardhat.
|
|
3
3
|
|
|
4
|
-
use
|
|
4
|
+
use std::convert::Infallible;
|
|
5
|
+
|
|
6
|
+
use edr_eth::{hex, U256};
|
|
5
7
|
use napi::bindgen_prelude::{BigInt, Either24, FromNapiValue, ToNapiValue, Uint8Array, Undefined};
|
|
6
8
|
use napi_derive::napi;
|
|
7
9
|
use serde::{Serialize, Serializer};
|
|
@@ -45,7 +47,7 @@ pub enum StackTraceEntryType {
|
|
|
45
47
|
CONTRACT_CALL_RUN_OUT_OF_GAS_ERROR,
|
|
46
48
|
}
|
|
47
49
|
|
|
48
|
-
#[napi]
|
|
50
|
+
#[napi(catch_unwind)]
|
|
49
51
|
pub fn stack_trace_entry_type_to_string(val: StackTraceEntryType) -> &'static str {
|
|
50
52
|
val.into()
|
|
51
53
|
}
|
|
@@ -606,7 +608,7 @@ pub type SolidityStackTraceEntry = Either24<
|
|
|
606
608
|
>;
|
|
607
609
|
|
|
608
610
|
impl TryCast<SolidityStackTraceEntry> for edr_solidity::solidity_stack_trace::StackTraceEntry {
|
|
609
|
-
type Error =
|
|
611
|
+
type Error = Infallible;
|
|
610
612
|
|
|
611
613
|
fn try_cast(self) -> Result<SolidityStackTraceEntry, Self::Error> {
|
|
612
614
|
use edr_solidity::solidity_stack_trace::StackTraceEntry;
|
|
@@ -630,7 +632,7 @@ impl TryCast<SolidityStackTraceEntry> for edr_solidity::solidity_stack_trace::St
|
|
|
630
632
|
StackTraceEntry::UnrecognizedContractCallstackEntry { address } => {
|
|
631
633
|
UnrecognizedContractCallstackEntryStackTraceEntry {
|
|
632
634
|
type_: StackTraceEntryTypeConst,
|
|
633
|
-
address: Uint8Array::
|
|
635
|
+
address: Uint8Array::with_data_copied(address),
|
|
634
636
|
source_reference: None,
|
|
635
637
|
}
|
|
636
638
|
.into()
|
|
@@ -762,7 +764,7 @@ impl TryCast<SolidityStackTraceEntry> for edr_solidity::solidity_stack_trace::St
|
|
|
762
764
|
is_invalid_opcode_error,
|
|
763
765
|
} => UnrecognizedContractErrorStackTraceEntry {
|
|
764
766
|
type_: StackTraceEntryTypeConst,
|
|
765
|
-
address: Uint8Array::
|
|
767
|
+
address: Uint8Array::with_data_copied(address),
|
|
766
768
|
return_data: return_data.into(),
|
|
767
769
|
is_invalid_opcode_error,
|
|
768
770
|
source_reference: None,
|
package/src/trace.rs
CHANGED
|
@@ -9,10 +9,7 @@ use std::sync::Arc;
|
|
|
9
9
|
|
|
10
10
|
use edr_eth::{bytecode::opcode::OpCode, l1};
|
|
11
11
|
use edr_evm::trace::BeforeMessage;
|
|
12
|
-
use napi::{
|
|
13
|
-
Env, JsBuffer, JsBufferValue,
|
|
14
|
-
bindgen_prelude::{BigInt, Buffer, Either3},
|
|
15
|
-
};
|
|
12
|
+
use napi::bindgen_prelude::{BigInt, Either3, Uint8Array};
|
|
16
13
|
use napi_derive::napi;
|
|
17
14
|
|
|
18
15
|
use crate::result::ExecutionResult;
|
|
@@ -29,11 +26,11 @@ pub mod solidity_stack_trace;
|
|
|
29
26
|
pub struct TracingMessage {
|
|
30
27
|
/// Sender address
|
|
31
28
|
#[napi(readonly)]
|
|
32
|
-
pub caller:
|
|
29
|
+
pub caller: Uint8Array,
|
|
33
30
|
|
|
34
31
|
/// Recipient address. None if it is a Create message.
|
|
35
32
|
#[napi(readonly)]
|
|
36
|
-
pub to: Option<
|
|
33
|
+
pub to: Option<Uint8Array>,
|
|
37
34
|
|
|
38
35
|
/// Whether it's a static call
|
|
39
36
|
#[napi(readonly)]
|
|
@@ -49,7 +46,7 @@ pub struct TracingMessage {
|
|
|
49
46
|
|
|
50
47
|
/// Input data of the message
|
|
51
48
|
#[napi(readonly)]
|
|
52
|
-
pub data:
|
|
49
|
+
pub data: Uint8Array,
|
|
53
50
|
|
|
54
51
|
/// Value sent in the message
|
|
55
52
|
#[napi(readonly)]
|
|
@@ -58,41 +55,37 @@ pub struct TracingMessage {
|
|
|
58
55
|
/// Address of the code that is being executed. Can be different from `to`
|
|
59
56
|
/// if a delegate call is being done.
|
|
60
57
|
#[napi(readonly)]
|
|
61
|
-
pub code_address: Option<
|
|
58
|
+
pub code_address: Option<Uint8Array>,
|
|
62
59
|
|
|
63
60
|
/// Code of the contract that is being executed.
|
|
64
61
|
#[napi(readonly)]
|
|
65
|
-
pub code: Option<
|
|
62
|
+
pub code: Option<Uint8Array>,
|
|
66
63
|
}
|
|
67
64
|
|
|
68
|
-
impl TracingMessage {
|
|
69
|
-
|
|
65
|
+
impl From<&BeforeMessage> for TracingMessage {
|
|
66
|
+
fn from(value: &BeforeMessage) -> Self {
|
|
70
67
|
// Deconstruct to make sure all fields are handled
|
|
71
68
|
let BeforeMessage {
|
|
72
69
|
depth,
|
|
73
70
|
caller,
|
|
74
|
-
to
|
|
71
|
+
to,
|
|
75
72
|
is_static_call,
|
|
76
73
|
gas_limit,
|
|
77
74
|
data,
|
|
78
75
|
value,
|
|
79
76
|
code_address,
|
|
80
77
|
code,
|
|
81
|
-
} =
|
|
78
|
+
} = value;
|
|
82
79
|
|
|
83
|
-
let data =
|
|
84
|
-
.create_buffer_with_data(data.to_vec())
|
|
85
|
-
.map(JsBufferValue::into_raw)?;
|
|
80
|
+
let data = Uint8Array::with_data_copied(data);
|
|
86
81
|
|
|
87
|
-
let code = code
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
.map(Some)
|
|
91
|
-
})?;
|
|
82
|
+
let code = code
|
|
83
|
+
.as_ref()
|
|
84
|
+
.map(|code| Uint8Array::with_data_copied(code.original_bytes()));
|
|
92
85
|
|
|
93
|
-
|
|
94
|
-
caller:
|
|
95
|
-
to:
|
|
86
|
+
TracingMessage {
|
|
87
|
+
caller: Uint8Array::with_data_copied(caller),
|
|
88
|
+
to: to.as_ref().map(Uint8Array::with_data_copied),
|
|
96
89
|
gas_limit: BigInt::from(*gas_limit),
|
|
97
90
|
is_static_call: *is_static_call,
|
|
98
91
|
depth: *depth as u8,
|
|
@@ -101,9 +94,9 @@ impl TracingMessage {
|
|
|
101
94
|
sign_bit: false,
|
|
102
95
|
words: value.into_limbs().to_vec(),
|
|
103
96
|
},
|
|
104
|
-
code_address: code_address.map(
|
|
97
|
+
code_address: code_address.as_ref().map(Uint8Array::with_data_copied),
|
|
105
98
|
code,
|
|
106
|
-
}
|
|
99
|
+
}
|
|
107
100
|
}
|
|
108
101
|
}
|
|
109
102
|
|
|
@@ -125,7 +118,7 @@ pub struct TracingStep {
|
|
|
125
118
|
pub stack: Vec<BigInt>,
|
|
126
119
|
/// The memory at the step. None if verbose tracing is disabled.
|
|
127
120
|
#[napi(readonly)]
|
|
128
|
-
pub memory: Option<
|
|
121
|
+
pub memory: Option<Uint8Array>,
|
|
129
122
|
}
|
|
130
123
|
|
|
131
124
|
impl TracingStep {
|
|
@@ -139,7 +132,7 @@ impl TracingStep {
|
|
|
139
132
|
},
|
|
140
133
|
|stack| stack.iter().map(u256_to_bigint).collect(),
|
|
141
134
|
);
|
|
142
|
-
let memory = step.memory.as_ref().
|
|
135
|
+
let memory = step.memory.as_ref().map(Uint8Array::with_data_copied);
|
|
143
136
|
|
|
144
137
|
Self {
|
|
145
138
|
depth: step.depth as u8,
|
|
@@ -179,23 +172,21 @@ impl From<Arc<edr_evm::trace::Trace<l1::HaltReason>>> for RawTrace {
|
|
|
179
172
|
|
|
180
173
|
#[napi]
|
|
181
174
|
impl RawTrace {
|
|
182
|
-
#[napi]
|
|
183
|
-
pub fn trace(
|
|
184
|
-
&self,
|
|
185
|
-
env: Env,
|
|
186
|
-
) -> napi::Result<Vec<Either3<TracingMessage, TracingStep, TracingMessageResult>>> {
|
|
175
|
+
#[napi(getter)]
|
|
176
|
+
pub fn trace(&self) -> Vec<Either3<TracingMessage, TracingStep, TracingMessageResult>> {
|
|
187
177
|
self.inner
|
|
188
178
|
.messages
|
|
189
179
|
.iter()
|
|
190
180
|
.map(|message| match message {
|
|
191
181
|
edr_evm::trace::TraceMessage::Before(message) => {
|
|
192
|
-
TracingMessage::
|
|
182
|
+
Either3::A(TracingMessage::from(message))
|
|
193
183
|
}
|
|
194
|
-
edr_evm::trace::TraceMessage::Step(step) =>
|
|
195
|
-
edr_evm::trace::TraceMessage::After(message) =>
|
|
196
|
-
|
|
184
|
+
edr_evm::trace::TraceMessage::Step(step) => Either3::B(TracingStep::new(step)),
|
|
185
|
+
edr_evm::trace::TraceMessage::After(message) => Either3::C(TracingMessageResult {
|
|
186
|
+
execution_result: ExecutionResult::from(message),
|
|
187
|
+
}),
|
|
197
188
|
})
|
|
198
|
-
.collect
|
|
189
|
+
.collect()
|
|
199
190
|
}
|
|
200
191
|
}
|
|
201
192
|
|
package/src/withdrawal.rs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
use edr_eth::Address;
|
|
2
|
-
use napi::bindgen_prelude::{BigInt,
|
|
2
|
+
use napi::bindgen_prelude::{BigInt, Uint8Array};
|
|
3
3
|
use napi_derive::napi;
|
|
4
4
|
|
|
5
5
|
use crate::cast::TryCast as _;
|
|
@@ -11,7 +11,7 @@ pub struct Withdrawal {
|
|
|
11
11
|
/// The index of the validator that generated the withdrawal
|
|
12
12
|
pub validator_index: BigInt,
|
|
13
13
|
/// The recipient address for withdrawal value
|
|
14
|
-
pub address:
|
|
14
|
+
pub address: Uint8Array,
|
|
15
15
|
/// The value contained in withdrawal
|
|
16
16
|
pub amount: BigInt,
|
|
17
17
|
}
|
|
@@ -21,7 +21,7 @@ impl From<edr_eth::withdrawal::Withdrawal> for Withdrawal {
|
|
|
21
21
|
Self {
|
|
22
22
|
index: BigInt::from(withdrawal.index),
|
|
23
23
|
validator_index: BigInt::from(withdrawal.validator_index),
|
|
24
|
-
address:
|
|
24
|
+
address: Uint8Array::with_data_copied(withdrawal.address),
|
|
25
25
|
amount: BigInt {
|
|
26
26
|
sign_bit: false,
|
|
27
27
|
words: withdrawal.amount.as_limbs().to_vec(),
|