@nomicfoundation/edr 0.12.0-next.8 → 0.12.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.
- package/coverage.sol +38 -0
- package/dist/src/ts/coverage.d.ts +6 -0
- package/dist/src/ts/coverage.d.ts.map +1 -0
- package/dist/src/ts/coverage.js +51 -0
- package/dist/src/ts/coverage.js.map +1 -0
- package/index.d.ts +267 -27
- package/index.js +5 -2
- package/package.json +23 -12
- package/src/account.rs +0 -124
- package/src/block.rs +0 -28
- package/src/call_override.rs +0 -116
- package/src/cast.rs +0 -165
- package/src/chains/generic.rs +0 -58
- package/src/chains/l1.rs +0 -268
- package/src/chains/op.rs +0 -424
- package/src/chains.rs +0 -7
- package/src/config.rs +0 -700
- package/src/context.rs +0 -447
- package/src/contract_decoder.rs +0 -57
- package/src/debug_trace.rs +0 -40
- package/src/gas_report.rs +0 -92
- package/src/instrument.rs +0 -109
- package/src/lib.rs +0 -50
- package/src/log.rs +0 -28
- package/src/logger.rs +0 -120
- package/src/mock/time.rs +0 -134
- package/src/mock.rs +0 -71
- package/src/precompile.rs +0 -50
- package/src/provider/factory.rs +0 -22
- package/src/provider/response.rs +0 -73
- package/src/provider.rs +0 -162
- package/src/result.rs +0 -212
- package/src/scenarios.rs +0 -53
- package/src/serde.rs +0 -57
- package/src/solidity_tests/artifact.rs +0 -184
- package/src/solidity_tests/config.rs +0 -793
- package/src/solidity_tests/factory.rs +0 -22
- package/src/solidity_tests/l1.rs +0 -68
- package/src/solidity_tests/op.rs +0 -69
- package/src/solidity_tests/runner.rs +0 -51
- package/src/solidity_tests/test_results.rs +0 -736
- package/src/solidity_tests.rs +0 -56
- package/src/subscription.rs +0 -32
- package/src/trace/debug.rs +0 -61
- package/src/trace/exit.rs +0 -89
- package/src/trace/library_utils.rs +0 -11
- package/src/trace/model.rs +0 -59
- package/src/trace/return_data.rs +0 -96
- package/src/trace/solidity_stack_trace.rs +0 -869
- package/src/trace.rs +0 -199
- package/src/ts/solidity_tests.ts +0 -46
- package/src/withdrawal.rs +0 -49
package/src/provider.rs
DELETED
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
/// Types related to provider factories.
|
|
2
|
-
pub mod factory;
|
|
3
|
-
mod response;
|
|
4
|
-
|
|
5
|
-
use std::sync::Arc;
|
|
6
|
-
|
|
7
|
-
use edr_napi_core::provider::SyncProvider;
|
|
8
|
-
use edr_solidity::compiler::create_models_and_decode_bytecodes;
|
|
9
|
-
use napi::{tokio::runtime, Env, JsFunction, JsObject, Status};
|
|
10
|
-
use napi_derive::napi;
|
|
11
|
-
|
|
12
|
-
pub use self::factory::ProviderFactory;
|
|
13
|
-
use self::response::Response;
|
|
14
|
-
use crate::{call_override::CallOverrideCallback, contract_decoder::ContractDecoder};
|
|
15
|
-
|
|
16
|
-
/// A JSON-RPC provider for Ethereum.
|
|
17
|
-
#[napi]
|
|
18
|
-
pub struct Provider {
|
|
19
|
-
contract_decoder: Arc<edr_solidity::contract_decoder::ContractDecoder>,
|
|
20
|
-
provider: Arc<dyn SyncProvider>,
|
|
21
|
-
runtime: runtime::Handle,
|
|
22
|
-
#[cfg(feature = "scenarios")]
|
|
23
|
-
scenario_file: Option<napi::tokio::sync::Mutex<napi::tokio::fs::File>>,
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
impl Provider {
|
|
27
|
-
/// Constructs a new instance.
|
|
28
|
-
pub fn new(
|
|
29
|
-
provider: Arc<dyn SyncProvider>,
|
|
30
|
-
runtime: runtime::Handle,
|
|
31
|
-
contract_decoder: Arc<edr_solidity::contract_decoder::ContractDecoder>,
|
|
32
|
-
#[cfg(feature = "scenarios")] scenario_file: Option<
|
|
33
|
-
napi::tokio::sync::Mutex<napi::tokio::fs::File>,
|
|
34
|
-
>,
|
|
35
|
-
) -> Self {
|
|
36
|
-
Self {
|
|
37
|
-
contract_decoder,
|
|
38
|
-
provider,
|
|
39
|
-
runtime,
|
|
40
|
-
#[cfg(feature = "scenarios")]
|
|
41
|
-
scenario_file,
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
#[napi]
|
|
47
|
-
impl Provider {
|
|
48
|
-
#[doc = "Adds a compilation result to the instance."]
|
|
49
|
-
#[doc = ""]
|
|
50
|
-
#[doc = "For internal use only. Support for this method may be removed in the future."]
|
|
51
|
-
#[napi(catch_unwind)]
|
|
52
|
-
pub async fn add_compilation_result(
|
|
53
|
-
&self,
|
|
54
|
-
solc_version: String,
|
|
55
|
-
compiler_input: serde_json::Value,
|
|
56
|
-
compiler_output: serde_json::Value,
|
|
57
|
-
) -> napi::Result<()> {
|
|
58
|
-
let contract_decoder = self.contract_decoder.clone();
|
|
59
|
-
|
|
60
|
-
self.runtime
|
|
61
|
-
.spawn_blocking(move || {
|
|
62
|
-
let compiler_input = serde_json::from_value(compiler_input)
|
|
63
|
-
.map_err(|error| napi::Error::from_reason(error.to_string()))?;
|
|
64
|
-
|
|
65
|
-
let compiler_output = serde_json::from_value(compiler_output)
|
|
66
|
-
.map_err(|error| napi::Error::from_reason(error.to_string()))?;
|
|
67
|
-
|
|
68
|
-
let contracts = match create_models_and_decode_bytecodes(
|
|
69
|
-
solc_version,
|
|
70
|
-
&compiler_input,
|
|
71
|
-
&compiler_output,
|
|
72
|
-
) {
|
|
73
|
-
Ok(contracts) => contracts,
|
|
74
|
-
Err(error) => {
|
|
75
|
-
return Err(napi::Error::from_reason(format!("Contract decoder failed to be updated. Please report this to help us improve Hardhat.\n{error}")));
|
|
76
|
-
}
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
for contract in contracts {
|
|
80
|
-
contract_decoder.add_contract_metadata(contract);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
Ok(())
|
|
84
|
-
})
|
|
85
|
-
.await
|
|
86
|
-
.map_err(|error| napi::Error::new(Status::GenericFailure, error.to_string()))?
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
#[doc = "Retrieves the instance's contract decoder."]
|
|
90
|
-
#[napi(catch_unwind)]
|
|
91
|
-
pub fn contract_decoder(&self) -> ContractDecoder {
|
|
92
|
-
ContractDecoder::from(Arc::clone(&self.contract_decoder))
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
#[doc = "Handles a JSON-RPC request and returns a JSON-RPC response."]
|
|
96
|
-
#[napi(catch_unwind)]
|
|
97
|
-
pub async fn handle_request(&self, request: String) -> napi::Result<Response> {
|
|
98
|
-
let provider = self.provider.clone();
|
|
99
|
-
|
|
100
|
-
#[cfg(feature = "scenarios")]
|
|
101
|
-
if let Some(scenario_file) = &self.scenario_file {
|
|
102
|
-
crate::scenarios::write_request(scenario_file, &request).await?;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
let contract_decoder = Arc::clone(&self.contract_decoder);
|
|
106
|
-
|
|
107
|
-
self.runtime
|
|
108
|
-
.spawn_blocking(move || provider.handle_request(request, contract_decoder))
|
|
109
|
-
.await
|
|
110
|
-
.map_err(|error| napi::Error::new(Status::GenericFailure, error.to_string()))?
|
|
111
|
-
.map(Response::from)
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
#[napi(catch_unwind, ts_return_type = "Promise<void>")]
|
|
115
|
-
pub fn set_call_override_callback(
|
|
116
|
-
&self,
|
|
117
|
-
env: Env,
|
|
118
|
-
#[napi(
|
|
119
|
-
ts_arg_type = "(contract_address: ArrayBuffer, data: ArrayBuffer) => Promise<CallOverrideResult | undefined>"
|
|
120
|
-
)]
|
|
121
|
-
call_override_callback: JsFunction,
|
|
122
|
-
) -> napi::Result<JsObject> {
|
|
123
|
-
let (deferred, promise) = env.create_deferred()?;
|
|
124
|
-
|
|
125
|
-
let call_override_callback =
|
|
126
|
-
match CallOverrideCallback::new(&env, call_override_callback, self.runtime.clone()) {
|
|
127
|
-
Ok(callback) => callback,
|
|
128
|
-
Err(error) => {
|
|
129
|
-
deferred.reject(error);
|
|
130
|
-
return Ok(promise);
|
|
131
|
-
}
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
let call_override_callback =
|
|
135
|
-
Arc::new(move |address, data| call_override_callback.call_override(address, data));
|
|
136
|
-
|
|
137
|
-
let provider = self.provider.clone();
|
|
138
|
-
self.runtime.spawn_blocking(move || {
|
|
139
|
-
provider.set_call_override_callback(call_override_callback);
|
|
140
|
-
|
|
141
|
-
deferred.resolve(|_env| Ok(()));
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
Ok(promise)
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
/// Set to `true` to make the traces returned with `eth_call`,
|
|
148
|
-
/// `eth_estimateGas`, `eth_sendRawTransaction`, `eth_sendTransaction`,
|
|
149
|
-
/// `evm_mine`, `hardhat_mine` include the full stack and memory. Set to
|
|
150
|
-
/// `false` to disable this.
|
|
151
|
-
#[napi(catch_unwind)]
|
|
152
|
-
pub async fn set_verbose_tracing(&self, verbose_tracing: bool) -> napi::Result<()> {
|
|
153
|
-
let provider = self.provider.clone();
|
|
154
|
-
|
|
155
|
-
self.runtime
|
|
156
|
-
.spawn_blocking(move || {
|
|
157
|
-
provider.set_verbose_tracing(verbose_tracing);
|
|
158
|
-
})
|
|
159
|
-
.await
|
|
160
|
-
.map_err(|error| napi::Error::new(Status::GenericFailure, error.to_string()))
|
|
161
|
-
}
|
|
162
|
-
}
|
package/src/result.rs
DELETED
|
@@ -1,212 +0,0 @@
|
|
|
1
|
-
use edr_evm::trace::AfterMessage;
|
|
2
|
-
use edr_evm_spec::EvmHaltReason;
|
|
3
|
-
use napi::{
|
|
4
|
-
bindgen_prelude::{BigInt, Either3, Uint8Array},
|
|
5
|
-
Either,
|
|
6
|
-
};
|
|
7
|
-
use napi_derive::napi;
|
|
8
|
-
|
|
9
|
-
use crate::log::ExecutionLog;
|
|
10
|
-
|
|
11
|
-
/// The possible reasons for successful termination of the EVM.
|
|
12
|
-
#[napi]
|
|
13
|
-
pub enum SuccessReason {
|
|
14
|
-
/// The opcode `STOP` was called
|
|
15
|
-
Stop,
|
|
16
|
-
/// The opcode `RETURN` was called
|
|
17
|
-
Return,
|
|
18
|
-
/// The opcode `SELFDESTRUCT` was called
|
|
19
|
-
SelfDestruct,
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
impl From<edr_evm::result::SuccessReason> for SuccessReason {
|
|
23
|
-
fn from(eval: edr_evm::result::SuccessReason) -> Self {
|
|
24
|
-
match eval {
|
|
25
|
-
edr_evm::result::SuccessReason::Stop => Self::Stop,
|
|
26
|
-
edr_evm::result::SuccessReason::Return => Self::Return,
|
|
27
|
-
edr_evm::result::SuccessReason::SelfDestruct => Self::SelfDestruct,
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
impl From<SuccessReason> for edr_evm::result::SuccessReason {
|
|
33
|
-
fn from(value: SuccessReason) -> Self {
|
|
34
|
-
match value {
|
|
35
|
-
SuccessReason::Stop => Self::Stop,
|
|
36
|
-
SuccessReason::Return => Self::Return,
|
|
37
|
-
SuccessReason::SelfDestruct => Self::SelfDestruct,
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
#[napi(object)]
|
|
43
|
-
pub struct CallOutput {
|
|
44
|
-
/// Return value
|
|
45
|
-
pub return_value: Uint8Array,
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
#[napi(object)]
|
|
49
|
-
pub struct CreateOutput {
|
|
50
|
-
/// Return value
|
|
51
|
-
pub return_value: Uint8Array,
|
|
52
|
-
/// Optionally, a 160-bit address
|
|
53
|
-
pub address: Option<Uint8Array>,
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/// The result when the EVM terminates successfully.
|
|
57
|
-
#[napi(object)]
|
|
58
|
-
pub struct SuccessResult {
|
|
59
|
-
/// The reason for termination
|
|
60
|
-
pub reason: SuccessReason,
|
|
61
|
-
/// The amount of gas used
|
|
62
|
-
pub gas_used: BigInt,
|
|
63
|
-
/// The amount of gas refunded
|
|
64
|
-
pub gas_refunded: BigInt,
|
|
65
|
-
/// The logs
|
|
66
|
-
pub logs: Vec<ExecutionLog>,
|
|
67
|
-
/// The transaction output
|
|
68
|
-
pub output: Either<CallOutput, CreateOutput>,
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/// The result when the EVM terminates due to a revert.
|
|
72
|
-
#[napi(object)]
|
|
73
|
-
pub struct RevertResult {
|
|
74
|
-
/// The amount of gas used
|
|
75
|
-
pub gas_used: BigInt,
|
|
76
|
-
/// The transaction output
|
|
77
|
-
pub output: Uint8Array,
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/// Indicates that the EVM has experienced an exceptional halt. This causes
|
|
81
|
-
/// execution to immediately end with all gas being consumed.
|
|
82
|
-
#[napi]
|
|
83
|
-
pub enum ExceptionalHalt {
|
|
84
|
-
OutOfGas,
|
|
85
|
-
OpcodeNotFound,
|
|
86
|
-
InvalidFEOpcode,
|
|
87
|
-
InvalidJump,
|
|
88
|
-
NotActivated,
|
|
89
|
-
StackUnderflow,
|
|
90
|
-
StackOverflow,
|
|
91
|
-
OutOfOffset,
|
|
92
|
-
CreateCollision,
|
|
93
|
-
PrecompileError,
|
|
94
|
-
NonceOverflow,
|
|
95
|
-
/// Create init code size exceeds limit (runtime).
|
|
96
|
-
CreateContractSizeLimit,
|
|
97
|
-
/// Error on created contract that begins with EF
|
|
98
|
-
CreateContractStartingWithEF,
|
|
99
|
-
/// EIP-3860: Limit and meter initcode. Initcode size limit exceeded.
|
|
100
|
-
CreateInitCodeSizeLimit,
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
impl From<EvmHaltReason> for ExceptionalHalt {
|
|
104
|
-
fn from(halt: EvmHaltReason) -> Self {
|
|
105
|
-
match halt {
|
|
106
|
-
EvmHaltReason::OutOfGas(..) => ExceptionalHalt::OutOfGas,
|
|
107
|
-
EvmHaltReason::OpcodeNotFound => ExceptionalHalt::OpcodeNotFound,
|
|
108
|
-
EvmHaltReason::InvalidFEOpcode => ExceptionalHalt::InvalidFEOpcode,
|
|
109
|
-
EvmHaltReason::InvalidJump => ExceptionalHalt::InvalidJump,
|
|
110
|
-
EvmHaltReason::NotActivated => ExceptionalHalt::NotActivated,
|
|
111
|
-
EvmHaltReason::StackUnderflow => ExceptionalHalt::StackUnderflow,
|
|
112
|
-
EvmHaltReason::StackOverflow => ExceptionalHalt::StackOverflow,
|
|
113
|
-
EvmHaltReason::OutOfOffset => ExceptionalHalt::OutOfOffset,
|
|
114
|
-
EvmHaltReason::CreateCollision => ExceptionalHalt::CreateCollision,
|
|
115
|
-
EvmHaltReason::PrecompileError => ExceptionalHalt::PrecompileError,
|
|
116
|
-
EvmHaltReason::NonceOverflow => ExceptionalHalt::NonceOverflow,
|
|
117
|
-
EvmHaltReason::CreateContractSizeLimit => ExceptionalHalt::CreateContractSizeLimit,
|
|
118
|
-
EvmHaltReason::CreateContractStartingWithEF => {
|
|
119
|
-
ExceptionalHalt::CreateContractStartingWithEF
|
|
120
|
-
}
|
|
121
|
-
EvmHaltReason::CreateInitCodeSizeLimit => ExceptionalHalt::CreateInitCodeSizeLimit,
|
|
122
|
-
EvmHaltReason::OverflowPayment
|
|
123
|
-
| EvmHaltReason::StateChangeDuringStaticCall
|
|
124
|
-
| EvmHaltReason::CallNotAllowedInsideStatic
|
|
125
|
-
| EvmHaltReason::OutOfFunds
|
|
126
|
-
| EvmHaltReason::CallTooDeep => {
|
|
127
|
-
unreachable!("Internal halts that can be only found inside Inspector: {halt:?}")
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/// The result when the EVM terminates due to an exceptional halt.
|
|
134
|
-
#[napi(object)]
|
|
135
|
-
pub struct HaltResult {
|
|
136
|
-
/// The exceptional halt that occurred
|
|
137
|
-
pub reason: ExceptionalHalt,
|
|
138
|
-
/// Halting will spend all the gas and will thus be equal to the specified
|
|
139
|
-
/// gas limit
|
|
140
|
-
pub gas_used: BigInt,
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
/// The result of executing a transaction.
|
|
144
|
-
#[napi(object)]
|
|
145
|
-
pub struct ExecutionResult {
|
|
146
|
-
/// The transaction result
|
|
147
|
-
pub result: Either3<SuccessResult, RevertResult, HaltResult>,
|
|
148
|
-
/// Optional contract address if the transaction created a new contract.
|
|
149
|
-
pub contract_address: Option<Uint8Array>,
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
impl From<&AfterMessage<EvmHaltReason>> for ExecutionResult {
|
|
153
|
-
fn from(value: &AfterMessage<EvmHaltReason>) -> Self {
|
|
154
|
-
let AfterMessage {
|
|
155
|
-
execution_result,
|
|
156
|
-
contract_address,
|
|
157
|
-
} = value;
|
|
158
|
-
|
|
159
|
-
let result = match execution_result {
|
|
160
|
-
edr_evm::result::ExecutionResult::Success {
|
|
161
|
-
reason,
|
|
162
|
-
gas_used,
|
|
163
|
-
gas_refunded,
|
|
164
|
-
logs,
|
|
165
|
-
output,
|
|
166
|
-
} => {
|
|
167
|
-
let logs = logs.iter().map(ExecutionLog::from).collect();
|
|
168
|
-
|
|
169
|
-
Either3::A(SuccessResult {
|
|
170
|
-
reason: SuccessReason::from(*reason),
|
|
171
|
-
gas_used: BigInt::from(*gas_used),
|
|
172
|
-
gas_refunded: BigInt::from(*gas_refunded),
|
|
173
|
-
logs,
|
|
174
|
-
output: match output {
|
|
175
|
-
edr_evm::result::Output::Call(return_value) => {
|
|
176
|
-
let return_value = Uint8Array::with_data_copied(return_value);
|
|
177
|
-
|
|
178
|
-
Either::A(CallOutput { return_value })
|
|
179
|
-
}
|
|
180
|
-
edr_evm::result::Output::Create(return_value, address) => {
|
|
181
|
-
let return_value = Uint8Array::with_data_copied(return_value);
|
|
182
|
-
|
|
183
|
-
Either::B(CreateOutput {
|
|
184
|
-
return_value,
|
|
185
|
-
address: address.as_ref().map(Uint8Array::with_data_copied),
|
|
186
|
-
})
|
|
187
|
-
}
|
|
188
|
-
},
|
|
189
|
-
})
|
|
190
|
-
}
|
|
191
|
-
edr_evm::result::ExecutionResult::Revert { gas_used, output } => {
|
|
192
|
-
let output = Uint8Array::with_data_copied(output);
|
|
193
|
-
|
|
194
|
-
Either3::B(RevertResult {
|
|
195
|
-
gas_used: BigInt::from(*gas_used),
|
|
196
|
-
output,
|
|
197
|
-
})
|
|
198
|
-
}
|
|
199
|
-
edr_evm::result::ExecutionResult::Halt { reason, gas_used } => Either3::C(HaltResult {
|
|
200
|
-
reason: ExceptionalHalt::from(*reason),
|
|
201
|
-
gas_used: BigInt::from(*gas_used),
|
|
202
|
-
}),
|
|
203
|
-
};
|
|
204
|
-
|
|
205
|
-
let contract_address = contract_address.as_ref().map(Uint8Array::with_data_copied);
|
|
206
|
-
|
|
207
|
-
Self {
|
|
208
|
-
result,
|
|
209
|
-
contract_address,
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
}
|
package/src/scenarios.rs
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
use std::time::{SystemTime, UNIX_EPOCH};
|
|
2
|
-
|
|
3
|
-
use edr_scenarios::ScenarioConfig;
|
|
4
|
-
use napi::tokio::{fs::File, io::AsyncWriteExt, sync::Mutex};
|
|
5
|
-
use rand::{distributions::Alphanumeric, Rng};
|
|
6
|
-
|
|
7
|
-
const SCENARIO_FILE_PREFIX: &str = "EDR_SCENARIO_PREFIX";
|
|
8
|
-
|
|
9
|
-
/// Creates a scenario file with the provided configuration.
|
|
10
|
-
pub async fn scenario_file(
|
|
11
|
-
chain_type: String,
|
|
12
|
-
provider_config: edr_napi_core::provider::Config,
|
|
13
|
-
logger_enabled: bool,
|
|
14
|
-
) -> napi::Result<Option<Mutex<File>>> {
|
|
15
|
-
if let Ok(scenario_prefix) = std::env::var(SCENARIO_FILE_PREFIX) {
|
|
16
|
-
let timestamp = SystemTime::now()
|
|
17
|
-
.duration_since(UNIX_EPOCH)
|
|
18
|
-
.expect("Time went backwards")
|
|
19
|
-
.as_secs();
|
|
20
|
-
let suffix = rand::thread_rng()
|
|
21
|
-
.sample_iter(&Alphanumeric)
|
|
22
|
-
.take(4)
|
|
23
|
-
.map(char::from)
|
|
24
|
-
.collect::<String>();
|
|
25
|
-
|
|
26
|
-
let mut scenario_file =
|
|
27
|
-
File::create(format!("{scenario_prefix}_{timestamp}_{suffix}.json")).await?;
|
|
28
|
-
|
|
29
|
-
let config = ScenarioConfig {
|
|
30
|
-
chain_type: Some(chain_type),
|
|
31
|
-
logger_enabled,
|
|
32
|
-
provider_config: provider_config.try_into()?,
|
|
33
|
-
};
|
|
34
|
-
let mut line = serde_json::to_string(&config)?;
|
|
35
|
-
line.push('\n');
|
|
36
|
-
scenario_file.write_all(line.as_bytes()).await?;
|
|
37
|
-
|
|
38
|
-
Ok(Some(Mutex::new(scenario_file)))
|
|
39
|
-
} else {
|
|
40
|
-
Ok(None)
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/// Writes a JSON-RPC request to the scenario file.
|
|
45
|
-
pub async fn write_request(scenario_file: &Mutex<File>, request: &str) -> napi::Result<()> {
|
|
46
|
-
let mut line = request.to_string();
|
|
47
|
-
line.push('\n');
|
|
48
|
-
{
|
|
49
|
-
let mut scenario_file = scenario_file.lock().await;
|
|
50
|
-
scenario_file.write_all(line.as_bytes()).await?;
|
|
51
|
-
}
|
|
52
|
-
Ok(())
|
|
53
|
-
}
|
package/src/serde.rs
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
use edr_primitives::hex;
|
|
2
|
-
use napi::bindgen_prelude::{BigInt, Uint8Array};
|
|
3
|
-
use serde::Serializer;
|
|
4
|
-
|
|
5
|
-
/// Serialize a `Uint8Array` as a 0x-prefixed hex string
|
|
6
|
-
pub fn serialize_uint8array_as_hex<S>(buffer: &Uint8Array, serializer: S) -> Result<S::Ok, S::Error>
|
|
7
|
-
where
|
|
8
|
-
S: Serializer,
|
|
9
|
-
{
|
|
10
|
-
let hex_string = format!("0x{}", hex::encode(buffer));
|
|
11
|
-
serializer.serialize_str(&hex_string)
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/// Serialize an Option<Uint8Array> as a 0x-prefixed hex string or None
|
|
15
|
-
pub fn serialize_optional_uint8array_as_hex<S>(
|
|
16
|
-
buffer: &Option<Uint8Array>,
|
|
17
|
-
serializer: S,
|
|
18
|
-
) -> Result<S::Ok, S::Error>
|
|
19
|
-
where
|
|
20
|
-
S: Serializer,
|
|
21
|
-
{
|
|
22
|
-
match buffer {
|
|
23
|
-
Some(buf) => {
|
|
24
|
-
let hex_string = format!("0x{}", hex::encode(buf));
|
|
25
|
-
serializer.serialize_str(&hex_string)
|
|
26
|
-
}
|
|
27
|
-
None => serializer.serialize_none(),
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/// Serialize a `BigInt` as a struct with `sign_bit` and `words` fields
|
|
32
|
-
pub fn serialize_bigint_as_struct<S>(value: &BigInt, serializer: S) -> Result<S::Ok, S::Error>
|
|
33
|
-
where
|
|
34
|
-
S: Serializer,
|
|
35
|
-
{
|
|
36
|
-
use serde::ser::SerializeStruct;
|
|
37
|
-
|
|
38
|
-
let mut state = serializer.serialize_struct("BigInt", 2)?;
|
|
39
|
-
state.serialize_field("sign_bit", &value.sign_bit)?;
|
|
40
|
-
state.serialize_field("words", &value.words)?;
|
|
41
|
-
state.end()
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/// Serialize an Option<BigInt> as a struct with `sign_bit` and `words` fields
|
|
45
|
-
/// or None
|
|
46
|
-
pub fn serialize_optional_bigint_as_struct<S>(
|
|
47
|
-
value: &Option<BigInt>,
|
|
48
|
-
serializer: S,
|
|
49
|
-
) -> Result<S::Ok, S::Error>
|
|
50
|
-
where
|
|
51
|
-
S: Serializer,
|
|
52
|
-
{
|
|
53
|
-
match value {
|
|
54
|
-
Some(val) => serialize_bigint_as_struct(val, serializer),
|
|
55
|
-
None => serializer.serialize_none(),
|
|
56
|
-
}
|
|
57
|
-
}
|
|
@@ -1,184 +0,0 @@
|
|
|
1
|
-
use std::{
|
|
2
|
-
borrow::Cow,
|
|
3
|
-
collections::{BTreeMap, HashMap},
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
use napi_derive::napi;
|
|
7
|
-
|
|
8
|
-
/// A compilation artifact.
|
|
9
|
-
#[derive(Clone, Debug)]
|
|
10
|
-
#[napi(object)]
|
|
11
|
-
pub struct Artifact {
|
|
12
|
-
/// The identifier of the artifact.
|
|
13
|
-
pub id: ArtifactId,
|
|
14
|
-
/// The test contract.
|
|
15
|
-
pub contract: ContractData,
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/// The identifier of a Solidity contract.
|
|
19
|
-
#[derive(Clone, Debug)]
|
|
20
|
-
#[napi(object)]
|
|
21
|
-
pub struct ArtifactId {
|
|
22
|
-
/// The name of the contract.
|
|
23
|
-
pub name: String,
|
|
24
|
-
/// Original source file path.
|
|
25
|
-
pub source: String,
|
|
26
|
-
/// The solc semver string.
|
|
27
|
-
pub solc_version: String,
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
impl From<edr_solidity::artifacts::ArtifactId> for ArtifactId {
|
|
31
|
-
fn from(value: edr_solidity::artifacts::ArtifactId) -> Self {
|
|
32
|
-
Self {
|
|
33
|
-
name: value.name,
|
|
34
|
-
source: value.source.to_string_lossy().to_string(),
|
|
35
|
-
solc_version: value.version.to_string(),
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
impl TryFrom<ArtifactId> for edr_solidity::artifacts::ArtifactId {
|
|
41
|
-
type Error = napi::Error;
|
|
42
|
-
|
|
43
|
-
fn try_from(value: ArtifactId) -> napi::Result<Self> {
|
|
44
|
-
Ok(edr_solidity::artifacts::ArtifactId {
|
|
45
|
-
name: value.name,
|
|
46
|
-
source: value.source.parse().map_err(|_err| {
|
|
47
|
-
napi::Error::new(napi::Status::GenericFailure, "Invalid source path")
|
|
48
|
-
})?,
|
|
49
|
-
version: value.solc_version.parse().map_err(|_err| {
|
|
50
|
-
napi::Error::new(napi::Status::GenericFailure, "Invalid solc semver string")
|
|
51
|
-
})?,
|
|
52
|
-
})
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/// A test contract to execute.
|
|
57
|
-
#[derive(Clone, Debug)]
|
|
58
|
-
#[napi(object)]
|
|
59
|
-
pub struct ContractData {
|
|
60
|
-
/// Contract ABI as json string.
|
|
61
|
-
pub abi: String,
|
|
62
|
-
/// Contract creation code as hex string. It can be missing if the contract
|
|
63
|
-
/// is ABI only.
|
|
64
|
-
pub bytecode: Option<String>,
|
|
65
|
-
/// The link references of the deployment bytecode.
|
|
66
|
-
pub link_references: Option<HashMap<String, HashMap<String, Vec<LinkReference>>>>,
|
|
67
|
-
/// Contract runtime code as hex string. It can be missing if the contract
|
|
68
|
-
/// is ABI only.
|
|
69
|
-
pub deployed_bytecode: Option<String>,
|
|
70
|
-
/// The link references of the deployed bytecode.
|
|
71
|
-
pub deployed_link_references: Option<HashMap<String, HashMap<String, Vec<LinkReference>>>>,
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
impl TryFrom<ContractData> for foundry_compilers::artifacts::CompactContractBytecode {
|
|
75
|
-
type Error = napi::Error;
|
|
76
|
-
|
|
77
|
-
fn try_from(contract: ContractData) -> napi::Result<Self> {
|
|
78
|
-
Ok(foundry_compilers::artifacts::CompactContractBytecode {
|
|
79
|
-
abi: Some(serde_json::from_str(&contract.abi).map_err(|_err| {
|
|
80
|
-
napi::Error::new(napi::Status::GenericFailure, "Invalid JSON ABI")
|
|
81
|
-
})?),
|
|
82
|
-
bytecode: contract
|
|
83
|
-
.bytecode
|
|
84
|
-
.map(|bytecode| {
|
|
85
|
-
let link_references =
|
|
86
|
-
convert_link_references(contract.link_references.unwrap_or_default());
|
|
87
|
-
let object = convert_bytecode(bytecode, !link_references.is_empty())?;
|
|
88
|
-
Ok::<_, napi::Error>(foundry_compilers::artifacts::CompactBytecode {
|
|
89
|
-
object,
|
|
90
|
-
source_map: None,
|
|
91
|
-
link_references,
|
|
92
|
-
})
|
|
93
|
-
})
|
|
94
|
-
.transpose()?,
|
|
95
|
-
deployed_bytecode: contract
|
|
96
|
-
.deployed_bytecode
|
|
97
|
-
.map(|deployed_bytecode| {
|
|
98
|
-
let link_references = convert_link_references(
|
|
99
|
-
contract.deployed_link_references.unwrap_or_default(),
|
|
100
|
-
);
|
|
101
|
-
let object = convert_bytecode(deployed_bytecode, !link_references.is_empty())?;
|
|
102
|
-
let compact_bytecode = foundry_compilers::artifacts::CompactBytecode {
|
|
103
|
-
object,
|
|
104
|
-
source_map: None,
|
|
105
|
-
link_references,
|
|
106
|
-
};
|
|
107
|
-
Ok::<_, napi::Error>(foundry_compilers::artifacts::CompactDeployedBytecode {
|
|
108
|
-
bytecode: Some(compact_bytecode),
|
|
109
|
-
immutable_references: BTreeMap::default(),
|
|
110
|
-
})
|
|
111
|
-
})
|
|
112
|
-
.transpose()?,
|
|
113
|
-
})
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
impl TryFrom<ContractData> for foundry_compilers::artifacts::CompactContractBytecodeCow<'static> {
|
|
118
|
-
type Error = napi::Error;
|
|
119
|
-
|
|
120
|
-
fn try_from(contract: ContractData) -> napi::Result<Self> {
|
|
121
|
-
let c: foundry_compilers::artifacts::CompactContractBytecode = contract.try_into()?;
|
|
122
|
-
Ok(foundry_compilers::artifacts::CompactContractBytecodeCow {
|
|
123
|
-
abi: c.abi.map(Cow::Owned),
|
|
124
|
-
bytecode: c.bytecode.map(Cow::Owned),
|
|
125
|
-
deployed_bytecode: c.deployed_bytecode.map(Cow::Owned),
|
|
126
|
-
})
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
// The order of link references as supplied through the NAPI interface doesn't
|
|
131
|
-
// matter, but the order can matter downstream for deterministic address
|
|
132
|
-
// generation.
|
|
133
|
-
fn convert_link_references(
|
|
134
|
-
link_references: HashMap<String, HashMap<String, Vec<LinkReference>>>,
|
|
135
|
-
) -> BTreeMap<String, BTreeMap<String, Vec<foundry_compilers::artifacts::Offsets>>> {
|
|
136
|
-
link_references
|
|
137
|
-
.into_iter()
|
|
138
|
-
.map(|(file, libraries)| {
|
|
139
|
-
let lib_map = libraries
|
|
140
|
-
.into_iter()
|
|
141
|
-
.map(|(library_name, references)| {
|
|
142
|
-
let offsets = references.into_iter().map(Into::into).collect();
|
|
143
|
-
(library_name, offsets)
|
|
144
|
-
})
|
|
145
|
-
.collect();
|
|
146
|
-
(file, lib_map)
|
|
147
|
-
})
|
|
148
|
-
.collect()
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
fn convert_bytecode(
|
|
152
|
-
bytecode: String,
|
|
153
|
-
needs_linking: bool,
|
|
154
|
-
) -> napi::Result<foundry_compilers::artifacts::BytecodeObject> {
|
|
155
|
-
if needs_linking {
|
|
156
|
-
Ok(foundry_compilers::artifacts::BytecodeObject::Unlinked(
|
|
157
|
-
bytecode,
|
|
158
|
-
))
|
|
159
|
-
} else {
|
|
160
|
-
let bytes = bytecode.parse().map_err(|err| {
|
|
161
|
-
let message = format!("Hex decoding error while parsing bytecode: '{err}'. Maybe forgot to pass link references for a contract that needs linking?");
|
|
162
|
-
napi::Error::from_reason(message)
|
|
163
|
-
})?;
|
|
164
|
-
Ok(foundry_compilers::artifacts::BytecodeObject::Bytecode(
|
|
165
|
-
bytes,
|
|
166
|
-
))
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
#[derive(Clone, Debug)]
|
|
171
|
-
#[napi(object)]
|
|
172
|
-
pub struct LinkReference {
|
|
173
|
-
pub start: u32,
|
|
174
|
-
pub length: u32,
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
impl From<LinkReference> for foundry_compilers::artifacts::Offsets {
|
|
178
|
-
fn from(value: LinkReference) -> Self {
|
|
179
|
-
Self {
|
|
180
|
-
start: value.start,
|
|
181
|
-
length: value.length,
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
}
|