@nomicfoundation/edr 0.6.5 → 0.8.0

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.
@@ -1,234 +0,0 @@
1
- use std::rc::Rc;
2
-
3
- use edr_solidity::{
4
- artifacts::BuildInfo,
5
- build_model::{Bytecode, ContractFunctionType},
6
- compiler::create_models_and_decode_bytecodes,
7
- contracts_identifier::ContractsIdentifier,
8
- };
9
- use napi::{
10
- bindgen_prelude::{ClassInstance, Either3, Either4, Uint8Array, Undefined},
11
- Either, Env,
12
- };
13
- use napi_derive::napi;
14
- use serde::{Deserialize, Serialize};
15
-
16
- use super::{
17
- message_trace::{CallMessageTrace, CreateMessageTrace, PrecompileMessageTrace},
18
- solidity_stack_trace::{
19
- FALLBACK_FUNCTION_NAME, RECEIVE_FUNCTION_NAME, UNRECOGNIZED_CONTRACT_NAME,
20
- UNRECOGNIZED_FUNCTION_NAME,
21
- },
22
- };
23
- use crate::trace::model::BytecodeWrapper;
24
-
25
- #[derive(Deserialize, Serialize)]
26
- #[serde(rename_all = "camelCase")]
27
- pub struct TracingConfig {
28
- pub build_infos: Option<Vec<BuildInfo>>,
29
- pub ignore_contracts: Option<bool>,
30
- }
31
-
32
- #[derive(Default)]
33
- #[napi]
34
- pub struct VmTraceDecoder {
35
- contracts_identifier: ContractsIdentifier,
36
- }
37
-
38
- #[napi]
39
- impl VmTraceDecoder {
40
- #[napi(constructor)]
41
- pub fn new() -> Self {
42
- Self::default()
43
- }
44
-
45
- #[napi(catch_unwind)]
46
- pub fn add_bytecode(&mut self, bytecode: ClassInstance<BytecodeWrapper>) {
47
- self.add_bytecode_inner(bytecode.inner().clone());
48
- }
49
-
50
- pub fn add_bytecode_inner(&mut self, bytecode: Rc<Bytecode>) {
51
- self.contracts_identifier.add_bytecode(bytecode);
52
- }
53
-
54
- #[napi(catch_unwind)]
55
- pub fn try_to_decode_message_trace(
56
- &mut self,
57
- message_trace: Either3<PrecompileMessageTrace, CallMessageTrace, CreateMessageTrace>,
58
- env: Env,
59
- ) -> napi::Result<Either3<PrecompileMessageTrace, CallMessageTrace, CreateMessageTrace>> {
60
- match message_trace {
61
- precompile @ Either3::A(..) => Ok(precompile),
62
- // NOTE: The branches below are the same with the difference of `is_create`
63
- Either3::B(mut call) => {
64
- let is_create = false;
65
-
66
- let bytecode = self
67
- .contracts_identifier
68
- .get_bytecode_for_call(call.code.as_ref(), is_create);
69
-
70
- let steps: Vec<_> = call
71
- .steps
72
- .into_iter()
73
- .map(|step| {
74
- let trace = match step {
75
- Either4::A(step) => return Ok(Either4::A(step)),
76
- Either4::B(precompile) => Either3::A(precompile),
77
- Either4::C(create) => Either3::B(create),
78
- Either4::D(call) => Either3::C(call),
79
- };
80
-
81
- Ok(match self.try_to_decode_message_trace(trace, env)? {
82
- Either3::A(precompile) => Either4::B(precompile),
83
- Either3::B(create) => Either4::C(create),
84
- Either3::C(call) => Either4::D(call),
85
- })
86
- })
87
- .collect::<napi::Result<_>>()?;
88
-
89
- let bytecode = bytecode
90
- .map(|b| BytecodeWrapper::new(b).into_instance(env))
91
- .transpose()?;
92
-
93
- call.bytecode = bytecode;
94
- call.steps = steps;
95
-
96
- Ok(Either3::B(call))
97
- }
98
- Either3::C(mut create @ CreateMessageTrace { .. }) => {
99
- let is_create = true;
100
-
101
- let bytecode = self
102
- .contracts_identifier
103
- .get_bytecode_for_call(create.code.as_ref(), is_create);
104
-
105
- let steps: Vec<_> = create
106
- .steps
107
- .into_iter()
108
- .map(|step| {
109
- let trace = match step {
110
- Either4::A(step) => return Ok(Either4::A(step)),
111
- Either4::B(precompile) => Either3::A(precompile),
112
- Either4::C(create) => Either3::B(create),
113
- Either4::D(call) => Either3::C(call),
114
- };
115
-
116
- Ok(match self.try_to_decode_message_trace(trace, env)? {
117
- Either3::A(precompile) => Either4::B(precompile),
118
- Either3::B(create) => Either4::C(create),
119
- Either3::C(call) => Either4::D(call),
120
- })
121
- })
122
- .collect::<napi::Result<_>>()?;
123
-
124
- let bytecode = bytecode
125
- .map(|b| BytecodeWrapper::new(b).into_instance(env))
126
- .transpose()?;
127
- create.bytecode = bytecode;
128
- create.steps = steps;
129
-
130
- Ok(Either3::C(create))
131
- }
132
- }
133
- }
134
-
135
- #[napi]
136
- pub fn get_contract_and_function_names_for_call(
137
- &mut self,
138
- code: Uint8Array,
139
- calldata: Either<Uint8Array, Undefined>,
140
- ) -> napi::Result<ContractAndFunctionName> {
141
- let is_create = matches!(calldata, Either::B(()));
142
- let bytecode = self
143
- .contracts_identifier
144
- .get_bytecode_for_call(code.as_ref(), is_create);
145
-
146
- let contract = bytecode.map(|bytecode| bytecode.contract.clone());
147
- let contract = contract.as_ref().map(|c| c.borrow());
148
-
149
- let contract_name = contract.as_ref().map_or_else(
150
- || UNRECOGNIZED_CONTRACT_NAME.to_string(),
151
- |c| c.name.clone(),
152
- );
153
-
154
- if is_create {
155
- Ok(ContractAndFunctionName {
156
- contract_name,
157
- function_name: Either::B(()),
158
- })
159
- } else {
160
- match contract {
161
- None => Ok(ContractAndFunctionName {
162
- contract_name,
163
- function_name: Either::A("".to_string()),
164
- }),
165
- Some(contract) => {
166
- let calldata = match calldata {
167
- Either::A(calldata) => calldata,
168
- Either::B(_) => {
169
- unreachable!("calldata should be Some if is_create is false")
170
- }
171
- };
172
-
173
- let selector = &calldata.get(..4).unwrap_or(&calldata[..]);
174
-
175
- let func = contract.get_function_from_selector(selector);
176
-
177
- let function_name = match func {
178
- Some(func) => match func.r#type {
179
- ContractFunctionType::Fallback => FALLBACK_FUNCTION_NAME.to_string(),
180
- ContractFunctionType::Receive => RECEIVE_FUNCTION_NAME.to_string(),
181
- _ => func.name.clone(),
182
- },
183
- None => UNRECOGNIZED_FUNCTION_NAME.to_string(),
184
- };
185
-
186
- Ok(ContractAndFunctionName {
187
- contract_name,
188
- function_name: Either::A(function_name),
189
- })
190
- }
191
- }
192
- }
193
- }
194
- }
195
-
196
- #[napi(object)]
197
- pub struct ContractAndFunctionName {
198
- pub contract_name: String,
199
- pub function_name: Either<String, Undefined>,
200
- }
201
-
202
- #[napi(catch_unwind)]
203
- pub fn initialize_vm_trace_decoder(
204
- mut vm_trace_decoder: ClassInstance<VmTraceDecoder>,
205
- tracing_config: serde_json::Value,
206
- ) -> napi::Result<()> {
207
- let config = serde_json::from_value::<TracingConfig>(tracing_config).map_err(|e| {
208
- napi::Error::from_reason(format!("Failed to deserialize tracing config: {e:?}"))
209
- })?;
210
-
211
- let Some(build_infos) = config.build_infos else {
212
- return Ok(());
213
- };
214
-
215
- for build_info in &build_infos {
216
- let bytecodes = create_models_and_decode_bytecodes(
217
- build_info.solc_version.clone(),
218
- &build_info.input,
219
- &build_info.output,
220
- )?;
221
-
222
- for bytecode in bytecodes {
223
- if config.ignore_contracts == Some(true)
224
- && bytecode.contract.borrow().name.starts_with("Ignored")
225
- {
226
- continue;
227
- }
228
-
229
- vm_trace_decoder.add_bytecode_inner(Rc::new(bytecode));
230
- }
231
- }
232
-
233
- Ok(())
234
- }
@@ -1,71 +0,0 @@
1
- //! N-API bindings for the Rust port of `VMTracer` from Hardhat.
2
-
3
- use napi::{
4
- bindgen_prelude::{Either3, Either4, Undefined},
5
- Either, Env, JsError,
6
- };
7
- use napi_derive::napi;
8
-
9
- use crate::trace::{
10
- message_trace::{
11
- message_trace_to_napi, CallMessageTrace, CreateMessageTrace, PrecompileMessageTrace,
12
- },
13
- RawTrace,
14
- };
15
-
16
- /// N-API bindings for the Rust port of `VMTracer` from Hardhat.
17
- #[napi]
18
- pub struct VMTracer(edr_solidity::vm_tracer::VmTracer);
19
-
20
- #[napi]
21
- impl VMTracer {
22
- #[napi(constructor)]
23
- pub fn new() -> napi::Result<Self> {
24
- Ok(Self(edr_solidity::vm_tracer::VmTracer::new()))
25
- }
26
-
27
- /// Observes a trace, collecting information about the execution of the EVM.
28
- #[napi]
29
- pub fn observe(&mut self, trace: &RawTrace) {
30
- self.0.observe(&trace.inner);
31
- }
32
-
33
- // Explicitly return undefined as `Option<T>` by default returns `null` in JS
34
- // and the null/undefined checks we use in JS are strict
35
- #[napi]
36
- pub fn get_last_top_level_message_trace(
37
- &self,
38
- env: Env,
39
- ) -> napi::Result<
40
- Either4<PrecompileMessageTrace, CallMessageTrace, CreateMessageTrace, Undefined>,
41
- > {
42
- Ok(
43
- match self
44
- .0
45
- .get_last_top_level_message_trace_ref()
46
- .map(|x| {
47
- x.try_borrow()
48
- .expect("cannot be executed concurrently with `VMTracer::observe`")
49
- .clone()
50
- })
51
- .map(|msg| message_trace_to_napi(msg, env))
52
- .transpose()?
53
- {
54
- Some(Either3::A(precompile)) => Either4::A(precompile),
55
- Some(Either3::B(call)) => Either4::B(call),
56
- Some(Either3::C(create)) => Either4::C(create),
57
- None => Either4::D(()),
58
- },
59
- )
60
- }
61
-
62
- // Explicitly return undefined as `Option<T>` by default returns `null` in JS
63
- // and the null/undefined checks we use in JS are strict
64
- #[napi]
65
- pub fn get_last_error(&self) -> Either<JsError, Undefined> {
66
- match self.0.get_last_error() {
67
- Some(err) => Either::A(napi::Error::from_reason(err).into()),
68
- None => Either::B(()),
69
- }
70
- }
71
- }