@nomicfoundation/edr 0.12.0-next.9 → 0.12.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.
Files changed (52) hide show
  1. package/coverage.sol +38 -0
  2. package/dist/src/ts/coverage.d.ts +6 -0
  3. package/dist/src/ts/coverage.d.ts.map +1 -0
  4. package/dist/src/ts/coverage.js +51 -0
  5. package/dist/src/ts/coverage.js.map +1 -0
  6. package/index.d.ts +286 -27
  7. package/index.js +6 -2
  8. package/package.json +21 -19
  9. package/src/account.rs +0 -124
  10. package/src/block.rs +0 -28
  11. package/src/call_override.rs +0 -116
  12. package/src/cast.rs +0 -165
  13. package/src/chains/generic.rs +0 -58
  14. package/src/chains/l1.rs +0 -268
  15. package/src/chains/op.rs +0 -424
  16. package/src/chains.rs +0 -7
  17. package/src/config.rs +0 -700
  18. package/src/context.rs +0 -447
  19. package/src/contract_decoder.rs +0 -57
  20. package/src/debug_trace.rs +0 -40
  21. package/src/gas_report.rs +0 -92
  22. package/src/instrument.rs +0 -109
  23. package/src/lib.rs +0 -50
  24. package/src/log.rs +0 -28
  25. package/src/logger.rs +0 -120
  26. package/src/mock/time.rs +0 -134
  27. package/src/mock.rs +0 -71
  28. package/src/precompile.rs +0 -50
  29. package/src/provider/factory.rs +0 -22
  30. package/src/provider/response.rs +0 -73
  31. package/src/provider.rs +0 -162
  32. package/src/result.rs +0 -212
  33. package/src/scenarios.rs +0 -53
  34. package/src/serde.rs +0 -57
  35. package/src/solidity_tests/artifact.rs +0 -184
  36. package/src/solidity_tests/config.rs +0 -793
  37. package/src/solidity_tests/factory.rs +0 -22
  38. package/src/solidity_tests/l1.rs +0 -68
  39. package/src/solidity_tests/op.rs +0 -69
  40. package/src/solidity_tests/runner.rs +0 -51
  41. package/src/solidity_tests/test_results.rs +0 -736
  42. package/src/solidity_tests.rs +0 -56
  43. package/src/subscription.rs +0 -32
  44. package/src/trace/debug.rs +0 -61
  45. package/src/trace/exit.rs +0 -89
  46. package/src/trace/library_utils.rs +0 -11
  47. package/src/trace/model.rs +0 -59
  48. package/src/trace/return_data.rs +0 -96
  49. package/src/trace/solidity_stack_trace.rs +0 -869
  50. package/src/trace.rs +0 -199
  51. package/src/ts/solidity_tests.ts +0 -46
  52. 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
- }