Compare commits

...

6 Commits

Author SHA1 Message Date
PG Herveou 0421869e4b Replace release 0.1.0-dev.15 with 0.1.0-dev.16 (#314)
add missing patch and rename release
2025-05-08 15:26:10 +02:00
xermicus 32f55b976c update changelog (#313)
somehow went wrong

Signed-off-by: Cyrill Leutwiler <bigcyrill@hotmail.com>
2025-05-08 14:16:46 +02:00
PG Herveou 459a786299 v0.1.0-dev.15 release (#311)
Co-authored-by: xermicus <cyrill@parity.io>
2025-05-08 14:09:55 +02:00
xermicus fbaa45f283 support solc v0.8.30 (#308)
- Add support for solc `v0.8.30`. No changes in YUL or the binary
interface.
- Fix a semver bug in the NPM packages to correctly align their solc
dependencies with our last supported version.

---------

Signed-off-by: Cyrill Leutwiler <bigcyrill@hotmail.com>
2025-05-08 13:29:13 +02:00
xermicus f2fac85dae add npm package information to release checklist (#312)
Signed-off-by: Cyrill Leutwiler <bigcyrill@hotmail.com>
2025-05-08 13:14:28 +02:00
PG Herveou b8f3073e29 Run lint:fix (#309) 2025-05-08 12:36:11 +02:00
25 changed files with 1232 additions and 1075 deletions
+1 -1
View File
@@ -19,7 +19,7 @@ runs:
shell: bash shell: bash
run: | run: |
mkdir -p solc mkdir -p solc
curl -sSL --output solc/solc https://github.com/ethereum/solidity/releases/download/v0.8.29/${SOLC_NAME} curl -sSL --output solc/solc https://github.com/ethereum/solidity/releases/download/v0.8.30/${SOLC_NAME}
- name: Make Solc Executable - name: Make Solc Executable
if: ${{ runner.os == 'Windows' }} if: ${{ runner.os == 'Windows' }}
+1 -4
View File
@@ -181,7 +181,7 @@ jobs:
- name: Basic Sanity Check - name: Basic Sanity Check
run: | run: |
mkdir -p solc mkdir -p solc
curl -sSLo solc/soljson.js https://github.com/ethereum/solidity/releases/download/v0.8.29/soljson.js curl -sSLo solc/soljson.js https://github.com/ethereum/solidity/releases/download/v0.8.30/soljson.js
node -e " node -e "
const soljson = require('solc/soljson'); const soljson = require('solc/soljson');
const createRevive = require('./target/wasm32-unknown-emscripten/release/resolc.js'); const createRevive = require('./target/wasm32-unknown-emscripten/release/resolc.js');
@@ -311,9 +311,6 @@ jobs:
cp -f resolc.{wasm,js} js/resolc/src/resolc cp -f resolc.{wasm,js} js/resolc/src/resolc
npm -w js/resolc run build npm -w js/resolc run build
- name: Set version
run: npm -w js/resolc version --no-git-tag-version ${{github.event.release.tag_name}}
- name: npm pack - name: npm pack
run: npm -w js/resolc pack run: npm -w js/resolc pack
+1 -1
View File
@@ -2,5 +2,5 @@
"trailingComma": "es5", "trailingComma": "es5",
"tabWidth": 2, "tabWidth": 2,
"semi": false, "semi": false,
"singleQuote": false "singleQuote": true
} }
+46 -1
View File
@@ -15,10 +15,29 @@ Supported `polkadot-sdk` rev:`c29e72a8628835e34deb6aa7db9a78a2e4eabcee`
### Added ### Added
### Changed ### Changed
### Fixed
## v0.1.0-dev.16
This is a development pre-release.
Supported `polkadot-sdk` rev:`c29e72a8628835e34deb6aa7db9a78a2e4eabcee`
### Added
- Move the npm package from paritytech/js-revive, into this repo. The package `@parity/resolc` will be deployed to npm for each release.
- Support for solc v0.8.30
### Changed
- By default, heavy size optimizations are applied. - By default, heavy size optimizations are applied.
### Fixed ### Fixed
- @parity/resolc: The solc dependency package is constrained to the latest supported version, preventing breaking the package ever time a new solc package was released.
- The resolc npm package no longer ignores the optimizer settings
## v0.1.0-dev.14 ## v0.1.0-dev.14
This is a development pre-release. This is a development pre-release.
@@ -26,13 +45,16 @@ This is a development pre-release.
Supported `polkadot-sdk` rev:`c29e72a8628835e34deb6aa7db9a78a2e4eabcee` Supported `polkadot-sdk` rev:`c29e72a8628835e34deb6aa7db9a78a2e4eabcee`
### Added ### Added
- The `revive-runner` helper utility binary which helps to run contracts locally without a blockchain node. - The `revive-runner` helper utility binary which helps to run contracts locally without a blockchain node.
- Allow configuration of the EVM heap memory size and stack size via CLI flags and JSON input settings. - Allow configuration of the EVM heap memory size and stack size via CLI flags and JSON input settings.
### Changed ### Changed
- The default PVM stack memory size was increased from 16kb to 32kb. - The default PVM stack memory size was increased from 16kb to 32kb.
### Fixed ### Fixed
- Constructors avoid storing zero sized immutable data on exit. - Constructors avoid storing zero sized immutable data on exit.
## v0.1.0-dev.13 ## v0.1.0-dev.13
@@ -42,16 +64,19 @@ This is a development pre-release.
Supported `polkadot-sdk` rev:`c29e72a8628835e34deb6aa7db9a78a2e4eabcee` Supported `polkadot-sdk` rev:`c29e72a8628835e34deb6aa7db9a78a2e4eabcee`
### Added ### Added
- Support for solc v0.8.29 - Support for solc v0.8.29
- Decouples the solc JSON-input-output type definitions from the Solidity fronted and expose them via a dedicated crate. - Decouples the solc JSON-input-output type definitions from the Solidity fronted and expose them via a dedicated crate.
- `--supported-solc-versions` for `resolc` binary to return a `semver` range of supported `solc` versions. - `--supported-solc-versions` for `resolc` binary to return a `semver` range of supported `solc` versions.
- Support for passing LLVM command line options via the prcoess input or providing one or more `--llvm-arg='..'` resolc CLI flag. This allows more fine-grained control over the LLVM backend configuration. - Support for passing LLVM command line options via the prcoess input or providing one or more `--llvm-arg='..'` resolc CLI flag. This allows more fine-grained control over the LLVM backend configuration.
### Changed ### Changed
- Storage keys and values are big endian. This was a pre-mature optimization because for the contract itself it this is a no-op and thus not observable. However we should consider the storage layout as part of the contract ABI. The endianness of transient storage values are still kept as-is. - Storage keys and values are big endian. This was a pre-mature optimization because for the contract itself it this is a no-op and thus not observable. However we should consider the storage layout as part of the contract ABI. The endianness of transient storage values are still kept as-is.
- Running `resolc` using webkit is no longer supported. - Running `resolc` using webkit is no longer supported.
### Fixed ### Fixed
- A missing byte swap for the create2 salt value. - A missing byte swap for the create2 salt value.
## v0.1.0-dev.12 ## v0.1.0-dev.12
@@ -61,10 +86,12 @@ This is a development pre-release.
Supported `polkadot-sdk` rev: `21f6f0705e53c15aa2b8a5706b208200447774a9` Supported `polkadot-sdk` rev: `21f6f0705e53c15aa2b8a5706b208200447774a9`
### Added ### Added
- Per file output selection for `--standard-json` mode. - Per file output selection for `--standard-json` mode.
- The `ir` output selection option for `--standard-json` mode. - The `ir` output selection option for `--standard-json` mode.
### Changed ### Changed
- Improved code size: Large contracts compile to smaller code blobs when enabling aggressive size optimizations (`-Oz`). - Improved code size: Large contracts compile to smaller code blobs when enabling aggressive size optimizations (`-Oz`).
### Fixed ### Fixed
@@ -80,6 +107,7 @@ Supported `polkadot-sdk` rev: `274a781e8ca1a9432c7ec87593bd93214abbff50`
### Changed ### Changed
### Fixed ### Fixed
- A bug causing incorrect loads from the emulated EVM linear memory. - A bug causing incorrect loads from the emulated EVM linear memory.
- A missing integer truncate after switching to 64bit. - A missing integer truncate after switching to 64bit.
@@ -90,10 +118,12 @@ This is a development pre-release.
Supported `polkadot-sdk` rev: `274a781e8ca1a9432c7ec87593bd93214abbff50` Supported `polkadot-sdk` rev: `274a781e8ca1a9432c7ec87593bd93214abbff50`
### Added ### Added
- Support for the `coinbase` opcode. - Support for the `coinbase` opcode.
- The resolc web JS version. - The resolc web JS version.
### Changed ### Changed
- Missing the `--overwrite` flag emits an error instead of a warning. - Missing the `--overwrite` flag emits an error instead of a warning.
- The `resolc` executable prints the help by default. - The `resolc` executable prints the help by default.
- Removed support for legacy EVM assembly (EVMLA) translation. - Removed support for legacy EVM assembly (EVMLA) translation.
@@ -103,6 +133,7 @@ Supported `polkadot-sdk` rev: `274a781e8ca1a9432c7ec87593bd93214abbff50`
If detected, the re-entrant call flag is not set and 0 deposit limit is endowed. If detected, the re-entrant call flag is not set and 0 deposit limit is endowed.
### Fixed ### Fixed
- Solidity: Add the solc `--libraries` files to sources. - Solidity: Add the solc `--libraries` files to sources.
- A data race in tests. - A data race in tests.
- Fix `broken pipe` errors. - Fix `broken pipe` errors.
@@ -116,9 +147,11 @@ This is a development pre-release.
### Added ### Added
### Changed ### Changed
- Syscalls with more than 6 arguments now pack them into registers. - Syscalls with more than 6 arguments now pack them into registers.
### Fixed ### Fixed
- Remove reloading of the resolc.js file (fix issue with relative path in web worker) - Remove reloading of the resolc.js file (fix issue with relative path in web worker)
## v0.1.0-dev.8 ## v0.1.0-dev.8
@@ -126,15 +159,18 @@ This is a development pre-release.
This is a development pre-release. This is a development pre-release.
### Added ### Added
- The `revive-llvm-builder` crate with the `revive-llvm` helper utility for streamlined management of the LLVM framework dependency. - The `revive-llvm-builder` crate with the `revive-llvm` helper utility for streamlined management of the LLVM framework dependency.
- Initial support for running `resolc` in the browser. - Initial support for running `resolc` in the browser.
### Changed ### Changed
- Suported contracts runtime is polkadot-sdk git version `d62a90c8c729acd98c7e9a5cab9803b8b211ffc5`. - Suported contracts runtime is polkadot-sdk git version `d62a90c8c729acd98c7e9a5cab9803b8b211ffc5`.
- The minimum supported Rust version is `1.81.0`. - The minimum supported Rust version is `1.81.0`.
- Error out early instead of invoking `solc` with invalid base or include path flags. - Error out early instead of invoking `solc` with invalid base or include path flags.
### Fixed ### Fixed
- Decouple the LLVM target dependency from the LLVM host dependency. - Decouple the LLVM target dependency from the LLVM host dependency.
- Do not error out if no files and no errors were produced. This aligns resolc closer to solc. - Do not error out if no files and no errors were produced. This aligns resolc closer to solc.
- Fixes input normalization in the Wasm version. - Fixes input normalization in the Wasm version.
@@ -144,17 +180,20 @@ This is a development pre-release.
This is a development pre-release. This is a development pre-release.
### Added ### Added
- Implement the `GASPRICE` opcode. - Implement the `GASPRICE` opcode.
- Implement the `BASEFEE` opcode. - Implement the `BASEFEE` opcode.
- Implement the `GASLIMIT` opcode. - Implement the `GASLIMIT` opcode.
### Changed ### Changed
- The `GAS` opcode now returns the remaining `ref_time`. - The `GAS` opcode now returns the remaining `ref_time`.
- Contracts can now be supplied call data input of arbitrary size. - Contracts can now be supplied call data input of arbitrary size.
- Some syscalls now return the value in a register, slightly improving emitted contract code. - Some syscalls now return the value in a register, slightly improving emitted contract code.
- Calls forward maximum weight limits instead of 0, anticipating a change in polkadot-sdk where weight limits of 0 no longer interprets as uncapped limit. - Calls forward maximum weight limits instead of 0, anticipating a change in polkadot-sdk where weight limits of 0 no longer interprets as uncapped limit.
### Fixed ### Fixed
- A linker bug which was preventing certain contracts from linking with the PVM linker. - A linker bug which was preventing certain contracts from linking with the PVM linker.
- JS: Fix encoding conversion from JS string (UTF-16) to UTF-8. - JS: Fix encoding conversion from JS string (UTF-16) to UTF-8.
- The git commit hash slug is always displayed in the version string. - The git commit hash slug is always displayed in the version string.
@@ -164,6 +203,7 @@ This is a development pre-release.
This is a development pre-release. This is a development pre-release.
# Added # Added
- Implement the `BLOCKHASH` opcode. - Implement the `BLOCKHASH` opcode.
- Implement delegate calls. - Implement delegate calls.
- Implement the `GASPRICE` opcode. Currently hard-coded to return `1`. - Implement the `GASPRICE` opcode. Currently hard-coded to return `1`.
@@ -171,21 +211,24 @@ This is a development pre-release.
- Initial support for emitting debug info (opt in via the `-g` flag) - Initial support for emitting debug info (opt in via the `-g` flag)
# Changed # Changed
- resolc now emits 64bit PolkaVM blobs, reducing contract code size and execution time. - resolc now emits 64bit PolkaVM blobs, reducing contract code size and execution time.
- The RISC-V bit-manipulation target feature (`zbb`) is enabled. - The RISC-V bit-manipulation target feature (`zbb`) is enabled.
# Fixed # Fixed
- Compilation to Wasm (for usage in node and web browsers)
- Compilation to Wasm (for usage in node and web browsers)
## v0.1.0-dev.5 ## v0.1.0-dev.5
This is development pre-release. This is development pre-release.
# Added # Added
- Implement the `CODESIZE` and `EXTCODESIZE` opcodes. - Implement the `CODESIZE` and `EXTCODESIZE` opcodes.
# Changed # Changed
- Include the full revive version in the contract metadata. - Include the full revive version in the contract metadata.
# Fixed # Fixed
@@ -195,9 +238,11 @@ This is development pre-release.
This is development pre-release. This is development pre-release.
# Added # Added
- Support the `ORIGIN` opcode. - Support the `ORIGIN` opcode.
# Changed # Changed
- Update polkavm to `v0.14.0`. - Update polkavm to `v0.14.0`.
- Enable the `a`, `fast-unaligned-access` and `xtheadcondmov` LLVM target features, decreasing the code size for some contracts. - Enable the `a`, `fast-unaligned-access` and `xtheadcondmov` LLVM target features, decreasing the code size for some contracts.
Generated
+15 -15
View File
@@ -4553,7 +4553,7 @@ checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104"
[[package]] [[package]]
name = "lld-sys" name = "lld-sys"
version = "0.1.0-dev.14" version = "0.1.0-dev.16"
dependencies = [ dependencies = [
"cc", "cc",
"libc", "libc",
@@ -8266,7 +8266,7 @@ dependencies = [
[[package]] [[package]]
name = "revive-benchmarks" name = "revive-benchmarks"
version = "0.1.0-dev.14" version = "0.1.0-dev.16"
dependencies = [ dependencies = [
"alloy-primitives", "alloy-primitives",
"criterion", "criterion",
@@ -8278,18 +8278,18 @@ dependencies = [
[[package]] [[package]]
name = "revive-build-utils" name = "revive-build-utils"
version = "0.1.0-dev.14" version = "0.1.0-dev.16"
[[package]] [[package]]
name = "revive-builtins" name = "revive-builtins"
version = "0.1.0-dev.14" version = "0.1.0-dev.16"
dependencies = [ dependencies = [
"revive-build-utils", "revive-build-utils",
] ]
[[package]] [[package]]
name = "revive-common" name = "revive-common"
version = "0.1.0-dev.14" version = "0.1.0-dev.16"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"serde", "serde",
@@ -8299,7 +8299,7 @@ dependencies = [
[[package]] [[package]]
name = "revive-differential" name = "revive-differential"
version = "0.1.0-dev.14" version = "0.1.0-dev.16"
dependencies = [ dependencies = [
"alloy-genesis", "alloy-genesis",
"alloy-primitives", "alloy-primitives",
@@ -8312,7 +8312,7 @@ dependencies = [
[[package]] [[package]]
name = "revive-integration" name = "revive-integration"
version = "0.1.0-dev.14" version = "0.1.0-dev.16"
dependencies = [ dependencies = [
"alloy-primitives", "alloy-primitives",
"alloy-sol-types", "alloy-sol-types",
@@ -8328,7 +8328,7 @@ dependencies = [
[[package]] [[package]]
name = "revive-linker" name = "revive-linker"
version = "0.1.0-dev.14" version = "0.1.0-dev.16"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"libc", "libc",
@@ -8340,7 +8340,7 @@ dependencies = [
[[package]] [[package]]
name = "revive-llvm-builder" name = "revive-llvm-builder"
version = "0.1.0-dev.14" version = "0.1.0-dev.16"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"assert_cmd", "assert_cmd",
@@ -8362,7 +8362,7 @@ dependencies = [
[[package]] [[package]]
name = "revive-llvm-context" name = "revive-llvm-context"
version = "0.1.0-dev.14" version = "0.1.0-dev.16"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"hex", "hex",
@@ -8384,7 +8384,7 @@ dependencies = [
[[package]] [[package]]
name = "revive-runner" name = "revive-runner"
version = "0.1.0-dev.14" version = "0.1.0-dev.16"
dependencies = [ dependencies = [
"alloy-primitives", "alloy-primitives",
"anyhow", "anyhow",
@@ -8403,7 +8403,7 @@ dependencies = [
[[package]] [[package]]
name = "revive-runtime-api" name = "revive-runtime-api"
version = "0.1.0-dev.14" version = "0.1.0-dev.16"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"inkwell", "inkwell",
@@ -8413,7 +8413,7 @@ dependencies = [
[[package]] [[package]]
name = "revive-solc-json-interface" name = "revive-solc-json-interface"
version = "0.1.0-dev.14" version = "0.1.0-dev.16"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"rayon", "rayon",
@@ -8425,7 +8425,7 @@ dependencies = [
[[package]] [[package]]
name = "revive-solidity" name = "revive-solidity"
version = "0.1.0-dev.14" version = "0.1.0-dev.16"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"clap", "clap",
@@ -8452,7 +8452,7 @@ dependencies = [
[[package]] [[package]]
name = "revive-stdlib" name = "revive-stdlib"
version = "0.1.0-dev.14" version = "0.1.0-dev.16"
dependencies = [ dependencies = [
"inkwell", "inkwell",
"revive-build-utils", "revive-build-utils",
+15 -15
View File
@@ -3,7 +3,7 @@ resolver = "2"
members = ["crates/*"] members = ["crates/*"]
[workspace.package] [workspace.package]
version = "0.1.0-dev.14" version = "0.1.0-dev.16"
authors = [ authors = [
"Cyrill Leutwiler <cyrill@parity.io>", "Cyrill Leutwiler <cyrill@parity.io>",
"Parity Technologies <admin@parity.io>", "Parity Technologies <admin@parity.io>",
@@ -14,20 +14,20 @@ repository = "https://github.com/paritytech/revive"
rust-version = "1.81.0" rust-version = "1.81.0"
[workspace.dependencies] [workspace.dependencies]
revive-benchmarks = { version = "0.1.0-dev.14", path = "crates/benchmarks" } revive-benchmarks = { version = "0.1.0-dev.16", path = "crates/benchmarks" }
revive-builtins = { version = "0.1.0-dev.14", path = "crates/builtins" } revive-builtins = { version = "0.1.0-dev.16", path = "crates/builtins" }
revive-common = { version = "0.1.0-dev.14", path = "crates/common" } revive-common = { version = "0.1.0-dev.16", path = "crates/common" }
revive-differential = { version = "0.1.0-dev.14", path = "crates/differential" } revive-differential = { version = "0.1.0-dev.16", path = "crates/differential" }
revive-integration = { version = "0.1.0-dev.14", path = "crates/integration" } revive-integration = { version = "0.1.0-dev.16", path = "crates/integration" }
revive-linker = { version = "0.1.0-dev.14", path = "crates/linker" } revive-linker = { version = "0.1.0-dev.16", path = "crates/linker" }
lld-sys = { version = "0.1.0-dev.14", path = "crates/lld-sys" } lld-sys = { version = "0.1.0-dev.16", path = "crates/lld-sys" }
revive-llvm-context = { version = "0.1.0-dev.14", path = "crates/llvm-context" } revive-llvm-context = { version = "0.1.0-dev.16", path = "crates/llvm-context" }
revive-runtime-api = { version = "0.1.0-dev.14", path = "crates/runtime-api" } revive-runtime-api = { version = "0.1.0-dev.16", path = "crates/runtime-api" }
revive-runner = { version = "0.1.0-dev.14", path = "crates/runner" } revive-runner = { version = "0.1.0-dev.16", path = "crates/runner" }
revive-solc-json-interface = { version = "0.1.0-dev.14", path = "crates/solc-json-interface" } revive-solc-json-interface = { version = "0.1.0-dev.16", path = "crates/solc-json-interface" }
revive-solidity = { version = "0.1.0-dev.14", path = "crates/solidity" } revive-solidity = { version = "0.1.0-dev.16", path = "crates/solidity" }
revive-stdlib = { version = "0.1.0-dev.14", path = "crates/stdlib" } revive-stdlib = { version = "0.1.0-dev.16", path = "crates/stdlib" }
revive-build-utils = { version = "0.1.0-dev.14", path = "crates/build-utils" } revive-build-utils = { version = "0.1.0-dev.16", path = "crates/build-utils" }
hex = "0.4.3" hex = "0.4.3"
cc = "1.2" cc = "1.2"
+4
View File
@@ -13,6 +13,10 @@ To create a new pre-release:
7. After the release is published, another workflow should start automatically and update json files in https://github.com/paritytech/resolc-bin. Check the changes. 7. After the release is published, another workflow should start automatically and update json files in https://github.com/paritytech/resolc-bin. Check the changes.
8. Update the [contract-docs](https://github.com/paritytech/contract-docs/) accordingly 8. Update the [contract-docs](https://github.com/paritytech/contract-docs/) accordingly
# `resolc` NPM package release
Will happen automatically.
# LLVM release # LLVM release
To create a new LLVM release, run "Release LLVM" workflow. Use current LLVM version as parameter, e.g. `18.1.8`. To create a new LLVM release, run "Release LLVM" workflow. Use current LLVM version as parameter, e.g. `18.1.8`.
+1 -1
View File
@@ -19,7 +19,7 @@ use self::version::Version;
pub const FIRST_SUPPORTED_VERSION: semver::Version = semver::Version::new(0, 8, 0); pub const FIRST_SUPPORTED_VERSION: semver::Version = semver::Version::new(0, 8, 0);
/// The last supported version of `solc`. /// The last supported version of `solc`.
pub const LAST_SUPPORTED_VERSION: semver::Version = semver::Version::new(0, 8, 29); pub const LAST_SUPPORTED_VERSION: semver::Version = semver::Version::new(0, 8, 30);
/// `--include-path` was introduced in solc `0.8.8` <https://github.com/ethereum/solidity/releases/tag/v0.8.8> /// `--include-path` was introduced in solc `0.8.8` <https://github.com/ethereum/solidity/releases/tag/v0.8.8>
pub const FIRST_INCLUDE_PATH_VERSION: semver::Version = semver::Version::new(0, 8, 8); pub const FIRST_INCLUDE_PATH_VERSION: semver::Version = semver::Version::new(0, 8, 8);
@@ -1,19 +1,33 @@
import * as path from 'path'; import * as path from 'path'
const outputDir = 'artifacts'; const outputDir = 'artifacts'
const binExtension = ':C.pvm'; const binExtension = ':C.pvm'
const asmExtension = ':C.pvmasm'; const asmExtension = ':C.pvmasm'
const llvmExtension = '.ll'; const llvmExtension = '.ll'
const contractSolFilename = 'contract.sol'; const contractSolFilename = 'contract.sol'
const contractYulFilename = 'contract.yul'; const contractYulFilename = 'contract.yul'
const contractOptimizedLLVMFilename = contractSolFilename + '.C.optimized'; const contractOptimizedLLVMFilename = contractSolFilename + '.C.optimized'
const contractUnoptimizedLLVMFilename = contractSolFilename + '.C.unoptimized'; const contractUnoptimizedLLVMFilename = contractSolFilename + '.C.unoptimized'
const pathToOutputDir = path.join(__dirname, '..', outputDir); const pathToOutputDir = path.join(__dirname, '..', outputDir)
const pathToContracts = path.join(__dirname, '..', 'src', 'contracts'); const pathToContracts = path.join(__dirname, '..', 'src', 'contracts')
const pathToBasicYulContract = path.join(pathToContracts, 'yul', contractYulFilename); const pathToBasicYulContract = path.join(
const pathToBasicSolContract = path.join(pathToContracts, 'solidity', contractSolFilename); pathToContracts,
const pathToSolBinOutputFile = path.join(pathToOutputDir, contractSolFilename + binExtension); 'yul',
const pathToSolAsmOutputFile = path.join(pathToOutputDir, contractSolFilename + asmExtension); contractYulFilename
)
const pathToBasicSolContract = path.join(
pathToContracts,
'solidity',
contractSolFilename
)
const pathToSolBinOutputFile = path.join(
pathToOutputDir,
contractSolFilename + binExtension
)
const pathToSolAsmOutputFile = path.join(
pathToOutputDir,
contractSolFilename + asmExtension
)
export const paths = { export const paths = {
outputDir: outputDir, outputDir: outputDir,
@@ -30,4 +44,4 @@ export const paths = {
pathToBasicYulContract: pathToBasicYulContract, pathToBasicYulContract: pathToBasicYulContract,
pathToSolBinOutputFile: pathToSolBinOutputFile, pathToSolBinOutputFile: pathToSolBinOutputFile,
pathToSolAsmOutputFile: pathToSolAsmOutputFile, pathToSolAsmOutputFile: pathToSolAsmOutputFile,
}; }
@@ -1,44 +1,51 @@
import * as shell from 'shelljs'; import * as shell from 'shelljs'
import * as fs from 'fs'; import * as fs from 'fs'
import { spawnSync } from 'child_process'; import { spawnSync } from 'child_process'
interface CommandResult { interface CommandResult {
output: string; output: string
exitCode: number; exitCode: number
} }
export const executeCommand = (command: string, stdin?: string): CommandResult => { export const executeCommand = (
command: string,
stdin?: string
): CommandResult => {
if (stdin) { if (stdin) {
const process = spawnSync(command, [], { const process = spawnSync(command, [], {
input: stdin, input: stdin,
shell: true, shell: true,
encoding: 'utf8', encoding: 'utf8',
maxBuffer: 30 * 1024 * 1024 maxBuffer: 30 * 1024 * 1024,
}); })
return { return {
exitCode: process.status || 0, exitCode: process.status || 0,
output: (process.stdout || process.stderr || '').toString() output: (process.stdout || process.stderr || '').toString(),
}; }
} }
const result = shell.exec(command, { silent: true, async: false }); const result = shell.exec(command, { silent: true, async: false })
return { return {
exitCode: result.code, exitCode: result.code,
output: result.stdout || result.stderr || '' output: result.stdout || result.stderr || '',
}; }
}; }
export const isFolderExist = (folder: string): boolean => { export const isFolderExist = (folder: string): boolean => {
return shell.test('-d', folder); return shell.test('-d', folder)
}; }
export const isFileExist = (pathToFileDir: string, fileName: string, fileExtension: string): boolean => { export const isFileExist = (
return shell.ls(pathToFileDir).stdout.includes(fileName + fileExtension); pathToFileDir: string,
}; fileName: string,
fileExtension: string
): boolean => {
return shell.ls(pathToFileDir).stdout.includes(fileName + fileExtension)
}
export const isFileEmpty = (file: string): boolean => { export const isFileEmpty = (file: string): boolean => {
if (fs.existsSync(file)) { if (fs.existsSync(file)) {
return (fs.readFileSync(file).length === 0); return fs.readFileSync(file).length === 0
}
} }
};
@@ -1,43 +1,44 @@
import {executeCommand} from "../src/helper"; import { executeCommand } from '../src/helper'
import { paths } from '../src/entities'; import { paths } from '../src/entities'
//id1746 //id1746
describe("Run with --asm by default", () => { describe('Run with --asm by default', () => {
const command = `resolc ${paths.pathToBasicSolContract} --asm`; const command = `resolc ${paths.pathToBasicSolContract} --asm`
const result = executeCommand(command); const result = executeCommand(command)
const commandInvalid = 'resolc --asm'; const commandInvalid = 'resolc --asm'
const resultInvalid = executeCommand(commandInvalid); const resultInvalid = executeCommand(commandInvalid)
it("Valid command exit code = 0", () => { it('Valid command exit code = 0', () => {
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0)
}); })
it("--asm output is presented", () => { it('--asm output is presented', () => {
const expectedPatterns = [/(deploy)/i, /(call)/i, /(seal_return)/i]; const expectedPatterns = [/(deploy)/i, /(call)/i, /(seal_return)/i]
for (const pattern of expectedPatterns) { for (const pattern of expectedPatterns) {
expect(result.output).toMatch(pattern); expect(result.output).toMatch(pattern)
} }
}); })
it("solc exit code == resolc exit code", () => { it('solc exit code == resolc exit code', () => {
const command = `solc ${paths.pathToBasicSolContract} --asm`; const command = `solc ${paths.pathToBasicSolContract} --asm`
const solcResult = executeCommand(command); const solcResult = executeCommand(command)
expect(solcResult.exitCode).toBe(result.exitCode); expect(solcResult.exitCode).toBe(result.exitCode)
}); })
it("run invalid: resolc --asm", () => { it('run invalid: resolc --asm', () => {
expect(resultInvalid.output).toMatch(/(No input sources specified|Compilation aborted)/i); expect(resultInvalid.output).toMatch(
}); /(No input sources specified|Compilation aborted)/i
)
})
it("Invalid command exit code = 1", () => { it('Invalid command exit code = 1', () => {
expect(resultInvalid.exitCode).toBe(1); expect(resultInvalid.exitCode).toBe(1)
}); })
it("Invalid solc exit code == Invalid resolc exit code", () => { it('Invalid solc exit code == Invalid resolc exit code', () => {
const command = 'solc --asm'; const command = 'solc --asm'
const solcResult = executeCommand(command); const solcResult = executeCommand(command)
expect(solcResult.exitCode).toBe(resultInvalid.exitCode); expect(solcResult.exitCode).toBe(resultInvalid.exitCode)
}); })
}); })
@@ -1,191 +1,241 @@
import { executeCommand, isFolderExist, isFileExist, isFileEmpty } from "../src/helper"; import {
import { paths } from '../src/entities'; executeCommand,
import * as shell from 'shelljs'; isFolderExist,
import * as path from 'path'; isFileExist,
isFileEmpty,
} from '../src/helper'
import { paths } from '../src/entities'
import * as shell from 'shelljs'
import * as path from 'path'
//id1762 //id1762
describe("Run resolc without any options", () => { describe('Run resolc without any options', () => {
const command = 'resolc'; const command = 'resolc'
const result = executeCommand(command); const result = executeCommand(command)
it("Info with help is presented", () => { it('Info with help is presented', () => {
expect(result.output).toMatch(/(Usage: resolc)/i); expect(result.output).toMatch(/(Usage: resolc)/i)
}); })
it("Exit code = 1", () => { it('Exit code = 1', () => {
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1)
}); })
it("solc exit code == resolc exit code", () => {
const command = 'solc';
const solcResult = executeCommand(command);
expect(solcResult.exitCode).toBe(result.exitCode);
});
});
it('solc exit code == resolc exit code', () => {
const command = 'solc'
const solcResult = executeCommand(command)
expect(solcResult.exitCode).toBe(result.exitCode)
})
})
//#1713 //#1713
describe("Default run a command from the help", () => { describe('Default run a command from the help', () => {
const command = `resolc ${paths.pathToBasicSolContract} --overwrite -O3 --bin --output-dir "${paths.pathToOutputDir}"` // potential issue on resolc with full path on Windows cmd
const result = executeCommand(command)
const command = `resolc ${paths.pathToBasicSolContract} --overwrite -O3 --bin --output-dir "${paths.pathToOutputDir}"`; // potential issue on resolc with full path on Windows cmd it('Compiler run successful', () => {
const result = executeCommand(command); expect(result.output).toMatch(/(Compiler run successful.)/i)
})
it("Compiler run successful", () => { it('Exit code = 0', () => {
expect(result.output).toMatch(/(Compiler run successful.)/i); expect(result.exitCode).toBe(0)
}); })
it("Exit code = 0", () => { it('Output dir is created', () => {
expect(result.exitCode).toBe(0); expect(isFolderExist(paths.pathToOutputDir)).toBe(true)
}); })
it("Output dir is created", () => { xit('Output file is created', () => {
expect(isFolderExist(paths.pathToOutputDir)).toBe(true); // a bug on windows
}); expect(
xit("Output file is created", () => { // a bug on windows isFileExist(
expect(isFileExist(paths.pathToOutputDir, paths.contractSolFilename, paths.binExtension)).toBe(true); paths.pathToOutputDir,
}); paths.contractSolFilename,
it("the output file is not empty", () => { paths.binExtension
expect(isFileEmpty(paths.pathToSolBinOutputFile)).toBe(false); )
}); ).toBe(true)
})
it('the output file is not empty', () => {
expect(isFileEmpty(paths.pathToSolBinOutputFile)).toBe(false)
})
it("No 'Error'/'Warning'/'Fail' in the output", () => { it("No 'Error'/'Warning'/'Fail' in the output", () => {
expect(result.output).not.toMatch(/([Ee]rror|[Ww]arning|[Ff]ail)/i); expect(result.output).not.toMatch(/([Ee]rror|[Ww]arning|[Ff]ail)/i)
}); })
}); })
//#1818 //#1818
describe("Default run a command from the help", () => { describe('Default run a command from the help', () => {
const command = `resolc ${paths.pathToBasicSolContract} --overwrite -O3 --bin --asm --output-dir "${paths.pathToOutputDir}"` // potential issue on resolc with full path on Windows cmd
const result = executeCommand(command)
const command = `resolc ${paths.pathToBasicSolContract} --overwrite -O3 --bin --asm --output-dir "${paths.pathToOutputDir}"`; // potential issue on resolc with full path on Windows cmd it('Compiler run successful', () => {
const result = executeCommand(command); expect(result.output).toMatch(/(Compiler run successful.)/i)
})
it("Compiler run successful", () => { it('Exit code = 0', () => {
expect(result.output).toMatch(/(Compiler run successful.)/i); expect(result.exitCode).toBe(0)
}); })
it("Exit code = 0", () => { it('Output dir is created', () => {
expect(result.exitCode).toBe(0); expect(isFolderExist(paths.pathToOutputDir)).toBe(true)
}); })
it("Output dir is created", () => { xit('Output files are created', () => {
expect(isFolderExist(paths.pathToOutputDir)).toBe(true); // a bug on windows
}); expect(
xit("Output files are created", () => { // a bug on windows isFileExist(
expect(isFileExist(paths.pathToOutputDir, paths.contractSolFilename, paths.binExtension)).toBe(true); paths.pathToOutputDir,
expect(isFileExist(paths.pathToOutputDir, paths.contractSolFilename, paths.asmExtension)).toBe(true); paths.contractSolFilename,
}); paths.binExtension
it("the output files are not empty", () => { )
expect(isFileEmpty(paths.pathToSolBinOutputFile)).toBe(false); ).toBe(true)
expect(isFileEmpty(paths.pathToSolAsmOutputFile)).toBe(false); expect(
}); isFileExist(
paths.pathToOutputDir,
paths.contractSolFilename,
paths.asmExtension
)
).toBe(true)
})
it('the output files are not empty', () => {
expect(isFileEmpty(paths.pathToSolBinOutputFile)).toBe(false)
expect(isFileEmpty(paths.pathToSolAsmOutputFile)).toBe(false)
})
it("No 'Error'/'Warning'/'Fail' in the output", () => { it("No 'Error'/'Warning'/'Fail' in the output", () => {
expect(result.output).not.toMatch(/([Ee]rror|[Ww]arning|[Ff]ail)/i); expect(result.output).not.toMatch(/([Ee]rror|[Ww]arning|[Ff]ail)/i)
}); })
}); })
describe("Run resolc with source debug information", () => { describe('Run resolc with source debug information', () => {
const commands = [ const commands = [
`resolc -g ${paths.pathToBasicSolContract} --overwrite --bin --asm --output-dir "${paths.pathToOutputDir}"`, `resolc -g ${paths.pathToBasicSolContract} --overwrite --bin --asm --output-dir "${paths.pathToOutputDir}"`,
`resolc --disable-solc-optimizer -g ${paths.pathToBasicSolContract} --overwrite --bin --asm --output-dir "${paths.pathToOutputDir}"` `resolc --disable-solc-optimizer -g ${paths.pathToBasicSolContract} --overwrite --bin --asm --output-dir "${paths.pathToOutputDir}"`,
]; // potential issue on resolc with full path on Windows cmd`; ] // potential issue on resolc with full path on Windows cmd`;
for (var idx in commands) { for (var idx in commands) {
const command = commands[idx]; const command = commands[idx]
const result = executeCommand(command); const result = executeCommand(command)
it("Compiler run successful", () => { it('Compiler run successful', () => {
expect(result.output).toMatch(/(Compiler run successful.)/i); expect(result.output).toMatch(/(Compiler run successful.)/i)
}); })
it("Exit code = 0", () => { it('Exit code = 0', () => {
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0)
}); })
it("Output dir is created", () => { it('Output dir is created', () => {
expect(isFolderExist(paths.pathToOutputDir)).toBe(true); expect(isFolderExist(paths.pathToOutputDir)).toBe(true)
}); })
it("Output files are created", () => { // a bug on windows it('Output files are created', () => {
expect(isFileExist(paths.pathToOutputDir, paths.contractSolFilename, paths.binExtension)).toBe(true); // a bug on windows
expect(isFileExist(paths.pathToOutputDir, paths.contractSolFilename, paths.asmExtension)).toBe(true); expect(
}); isFileExist(
it("the output files are not empty", () => { paths.pathToOutputDir,
expect(isFileEmpty(paths.pathToSolBinOutputFile)).toBe(false); paths.contractSolFilename,
expect(isFileEmpty(paths.pathToSolAsmOutputFile)).toBe(false); paths.binExtension
}); )
).toBe(true)
expect(
isFileExist(
paths.pathToOutputDir,
paths.contractSolFilename,
paths.asmExtension
)
).toBe(true)
})
it('the output files are not empty', () => {
expect(isFileEmpty(paths.pathToSolBinOutputFile)).toBe(false)
expect(isFileEmpty(paths.pathToSolAsmOutputFile)).toBe(false)
})
it("No 'Error'/'Fail' in the output", () => { it("No 'Error'/'Fail' in the output", () => {
expect(result.output).not.toMatch(/([Ee]rror|[Ff]ail)/i); expect(result.output).not.toMatch(/([Ee]rror|[Ff]ail)/i)
}); })
} }
}); })
describe("Run resolc with source debug information, check LLVM debug-info", () => { describe('Run resolc with source debug information, check LLVM debug-info', () => {
const commands = [ const commands = [
`resolc -g ${paths.pathToBasicSolContract} --overwrite --debug-output-dir="${paths.pathToOutputDir}"`, `resolc -g ${paths.pathToBasicSolContract} --overwrite --debug-output-dir="${paths.pathToOutputDir}"`,
`resolc -g --disable-solc-optimizer ${paths.pathToBasicSolContract} --overwrite --debug-output-dir="${paths.pathToOutputDir}"` `resolc -g --disable-solc-optimizer ${paths.pathToBasicSolContract} --overwrite --debug-output-dir="${paths.pathToOutputDir}"`,
]; // potential issue on resolc with full path on Windows cmd`; ] // potential issue on resolc with full path on Windows cmd`;
for (var idx in commands) { for (var idx in commands) {
const command = commands[idx]; const command = commands[idx]
const result = executeCommand(command); const result = executeCommand(command)
it("Compiler run successful", () => { it('Compiler run successful', () => {
expect(result.output).toMatch(/(Compiler run successful.)/i); expect(result.output).toMatch(/(Compiler run successful.)/i)
}); })
it("Exit code = 0", () => { it('Exit code = 0', () => {
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0)
}); })
it("Output dir is created", () => { it('Output dir is created', () => {
expect(isFolderExist(paths.pathToOutputDir)).toBe(true); expect(isFolderExist(paths.pathToOutputDir)).toBe(true)
}); })
it("Output files are created", () => { // a bug on windows it('Output files are created', () => {
expect(isFileExist(paths.pathToOutputDir, paths.contractOptimizedLLVMFilename, paths.llvmExtension)).toBe(true); // a bug on windows
expect(isFileExist(paths.pathToOutputDir, paths.contractUnoptimizedLLVMFilename, paths.llvmExtension)).toBe(true); expect(
}); isFileExist(
it("the output files are not empty", () => { paths.pathToOutputDir,
expect(isFileEmpty(paths.pathToSolBinOutputFile)).toBe(false); paths.contractOptimizedLLVMFilename,
expect(isFileEmpty(paths.pathToSolAsmOutputFile)).toBe(false); paths.llvmExtension
}); )
).toBe(true)
expect(
isFileExist(
paths.pathToOutputDir,
paths.contractUnoptimizedLLVMFilename,
paths.llvmExtension
)
).toBe(true)
})
it('the output files are not empty', () => {
expect(isFileEmpty(paths.pathToSolBinOutputFile)).toBe(false)
expect(isFileEmpty(paths.pathToSolAsmOutputFile)).toBe(false)
})
it("No 'Error'/'Fail' in the output", () => { it("No 'Error'/'Fail' in the output", () => {
expect(result.output).not.toMatch(/([Ee]rror|[Ff]ail)/i); expect(result.output).not.toMatch(/([Ee]rror|[Ff]ail)/i)
}); })
} }
}); })
describe('Standard JSON compilation with path options', () => {
const contractsDir = path.join(shell.tempdir(), 'contracts-test')
describe("Standard JSON compilation with path options", () => { const inputFile = path.join(__dirname, '..', 'src/contracts/compiled/1.json')
const contractsDir = path.join(shell.tempdir(), 'contracts-test');
const inputFile = path.join(__dirname, '..', 'src/contracts/compiled/1.json');
beforeAll(() => { beforeAll(() => {
shell.mkdir('-p', contractsDir); shell.mkdir('-p', contractsDir)
const input = JSON.parse(shell.cat(inputFile).toString()); const input = JSON.parse(shell.cat(inputFile).toString())
Object.entries(input.sources).forEach(([sourcePath, source]: [string, any]) => { Object.entries(input.sources).forEach(
const filePath = path.join(contractsDir, sourcePath); ([sourcePath, source]: [string, any]) => {
shell.mkdir('-p', path.dirname(filePath)); const filePath = path.join(contractsDir, sourcePath)
shell.ShellString(source.content).to(filePath); shell.mkdir('-p', path.dirname(filePath))
}); shell.ShellString(source.content).to(filePath)
}); }
)
})
afterAll(() => { afterAll(() => {
shell.rm('-rf', contractsDir); shell.rm('-rf', contractsDir)
}); })
describe("Output with all path options", () => { describe('Output with all path options', () => {
let result: { exitCode: number; output: string }; let result: { exitCode: number; output: string }
beforeAll(() => { beforeAll(() => {
const tempInputFile = path.join(contractsDir, 'temp-input.json'); const tempInputFile = path.join(contractsDir, 'temp-input.json')
shell.cp(inputFile, tempInputFile); shell.cp(inputFile, tempInputFile)
const inputContent = shell.cat(inputFile).toString(); const inputContent = shell.cat(inputFile).toString()
const command = `resolc --standard-json --base-path "${contractsDir}" --include-path "${contractsDir}" --allow-paths "${contractsDir}"`; const command = `resolc --standard-json --base-path "${contractsDir}" --include-path "${contractsDir}" --allow-paths "${contractsDir}"`
result = executeCommand(command, inputContent); result = executeCommand(command, inputContent)
shell.rm(tempInputFile); shell.rm(tempInputFile)
})
}); it('Compiler run successful without emiting warnings', () => {
it("Compiler run successful without emiting warnings", () => {
const parsedResults = JSON.parse(result.output) const parsedResults = JSON.parse(result.output)
expect(parsedResults.errors.filter((error: { type: string; }) => error.type != 'Warning')).toEqual([]); expect(
}); parsedResults.errors.filter(
}); (error: { type: string }) => error.type != 'Warning'
}); )
).toEqual([])
})
})
})
@@ -1,40 +1,39 @@
import {executeCommand} from "../src/helper"; import { executeCommand } from '../src/helper'
import { paths } from '../src/entities'; import { paths } from '../src/entities'
//id1743 //id1743
describe("Run with --yul by default", () => { describe('Run with --yul by default', () => {
const command = `resolc ${paths.pathToBasicYulContract} --yul`; const command = `resolc ${paths.pathToBasicYulContract} --yul`
const result = executeCommand(command); const result = executeCommand(command)
const commandInvalid = 'resolc --yul'; const commandInvalid = 'resolc --yul'
const resultInvalid = executeCommand(commandInvalid); const resultInvalid = executeCommand(commandInvalid)
it("Valid command exit code = 0", () => { it('Valid command exit code = 0', () => {
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0)
}); })
it("--yul output is presented", () => { it('--yul output is presented', () => {
expect(result.output).toMatch(/(Compiler run successful)/i); expect(result.output).toMatch(/(Compiler run successful)/i)
expect(result.output).toMatch(/(No output requested)/i); expect(result.output).toMatch(/(No output requested)/i)
}); })
xit('solc exit code == resolc exit code', () => {
// unknown solc issue for datatype of the contract
const command = `solc ${paths.pathToBasicSolContract} --yul`
const solcResult = executeCommand(command)
expect(solcResult.exitCode).toBe(result.exitCode)
})
xit("solc exit code == resolc exit code", () => { // unknown solc issue for datatype of the contract it('run invalid: resolc --yul', () => {
const command = `solc ${paths.pathToBasicSolContract} --yul`; expect(resultInvalid.output).toMatch(/(The input file is missing)/i)
const solcResult = executeCommand(command); })
expect(solcResult.exitCode).toBe(result.exitCode); it('Invalid command exit code = 1', () => {
}); expect(resultInvalid.exitCode).toBe(1)
})
it("run invalid: resolc --yul", () => { it('Invalid solc exit code == Invalid resolc exit code', () => {
expect(resultInvalid.output).toMatch(/(The input file is missing)/i); const command = 'solc --yul'
}); const solcResult = executeCommand(command)
it("Invalid command exit code = 1", () => { expect(solcResult.exitCode).toBe(resultInvalid.exitCode)
expect(resultInvalid.exitCode).toBe(1); })
}); })
it("Invalid solc exit code == Invalid resolc exit code", () => {
const command = 'solc --yul';
const solcResult = executeCommand(command);
expect(solcResult.exitCode).toBe(resultInvalid.exitCode);
});
});
+134 -99
View File
@@ -1,153 +1,188 @@
import { executeCommand } from "../src/helper"; import { executeCommand } from '../src/helper'
import { paths } from '../src/entities'; import { paths } from '../src/entities'
describe('Set of --combined-json tests', () => {
describe("Set of --combined-json tests", () => { const zksolcCommand = 'zksolc'
const zksolcCommand = 'zksolc'; const solcCommand = 'solc'
const solcCommand = 'solc'; const json_args: string[] = [
const json_args: string[] = [`abi`, `hashes`, `metadata`, `devdoc`, `userdoc`, `storage-layout`, `ast`, `asm`, `bin`, `bin-runtime`]; `abi`,
`hashes`,
`metadata`,
`devdoc`,
`userdoc`,
`storage-layout`,
`ast`,
`asm`,
`bin`,
`bin-runtime`,
]
//id1742:I //id1742:I
describe(`Run ${zksolcCommand} with just --combined-json`, () => { describe(`Run ${zksolcCommand} with just --combined-json`, () => {
const args = [`--combined-json`]; const args = [`--combined-json`]
const result = executeCommand(zksolcCommand, args); const result = executeCommand(zksolcCommand, args)
it("Valid command exit code = 1", () => { it('Valid command exit code = 1', () => {
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1)
}); })
it("--combined-json error is presented", () => { it('--combined-json error is presented', () => {
expect(result.output).toMatch(/(requires a value but none was supplied)/i); expect(result.output).toMatch(/(requires a value but none was supplied)/i)
}); })
it("solc exit code == zksolc exit code", () => { it('solc exit code == zksolc exit code', () => {
const solcResult = executeCommand(solcCommand, args); const solcResult = executeCommand(solcCommand, args)
expect(solcResult.exitCode).toBe(result.exitCode); expect(solcResult.exitCode).toBe(result.exitCode)
}); })
}); })
//id1742:II //id1742:II
describe(`Run ${zksolcCommand} with Sol contract and --combined-json`, () => { describe(`Run ${zksolcCommand} with Sol contract and --combined-json`, () => {
const args = [`${paths.pathToBasicSolContract}`, `--combined-json`]; const args = [`${paths.pathToBasicSolContract}`, `--combined-json`]
const result = executeCommand(zksolcCommand, args); const result = executeCommand(zksolcCommand, args)
it("Valid command exit code = 1", () => { it('Valid command exit code = 1', () => {
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1)
}); })
it("--combined-json error is presented", () => { it('--combined-json error is presented', () => {
expect(result.output).toMatch(/(requires a value but none was supplied)/i); expect(result.output).toMatch(/(requires a value but none was supplied)/i)
}); })
it("solc exit code == zksolc exit code", () => { it('solc exit code == zksolc exit code', () => {
const solcResult = executeCommand(solcCommand, args); const solcResult = executeCommand(solcCommand, args)
expect(solcResult.exitCode).toBe(result.exitCode); expect(solcResult.exitCode).toBe(result.exitCode)
}); })
}); })
//id1742:III //id1742:III
for (let i = 0; i < json_args.length; i++) { for (let i = 0; i < json_args.length; i++) {
describe(`Run ${zksolcCommand} with Sol, --combined-json and ARG: ${json_args[i]}`, () => { describe(`Run ${zksolcCommand} with Sol, --combined-json and ARG: ${json_args[i]}`, () => {
const args = [`${paths.pathToBasicSolContract}`, `--combined-json`, `${json_args[i]}`]; const args = [
const result = executeCommand(zksolcCommand, args); `${paths.pathToBasicSolContract}`,
`--combined-json`,
`${json_args[i]}`,
]
const result = executeCommand(zksolcCommand, args)
it("Valid command exit code = 0", () => { it('Valid command exit code = 0', () => {
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0)
}); })
it("--combined-json error is presented", () => { it('--combined-json error is presented', () => {
expect(result.output).toMatch(/(contracts)/i); expect(result.output).toMatch(/(contracts)/i)
}); })
it("solc exit code == zksolc exit code", () => { it('solc exit code == zksolc exit code', () => {
const solcResult = executeCommand(solcCommand, args); const solcResult = executeCommand(solcCommand, args)
expect(solcResult.exitCode).toBe(result.exitCode); expect(solcResult.exitCode).toBe(result.exitCode)
}); })
}); })
} }
//id1829:I //id1829:I
for (let i = 0; i < json_args.length; i++) { for (let i = 0; i < json_args.length; i++) {
describe(`Run ${zksolcCommand} with Sol, --combined-json and wrong ARG: --${json_args[i]}`, () => { describe(`Run ${zksolcCommand} with Sol, --combined-json and wrong ARG: --${json_args[i]}`, () => {
const args = [`${paths.pathToBasicSolContract}`, `--combined-json`, `--${json_args[i]}`]; const args = [
const result = executeCommand(zksolcCommand, args); `${paths.pathToBasicSolContract}`,
`--combined-json`,
`--${json_args[i]}`,
]
const result = executeCommand(zksolcCommand, args)
it("Valid command exit code = 1", () => { it('Valid command exit code = 1', () => {
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1)
}); })
it("--combined-json error is presented", () => { it('--combined-json error is presented', () => {
expect(result.output).toMatch(/(Invalid option|error)/i); expect(result.output).toMatch(/(Invalid option|error)/i)
}); })
it("solc exit code == zksolc exit code", () => { it('solc exit code == zksolc exit code', () => {
const solcResult = executeCommand(solcCommand, args); const solcResult = executeCommand(solcCommand, args)
expect(solcResult.exitCode).toBe(result.exitCode); expect(solcResult.exitCode).toBe(result.exitCode)
}); })
}); })
} }
//id1829:II //id1829:II
for (let i = 0; i < json_args.length; i++) { for (let i = 0; i < json_args.length; i++) {
describe(`Run ${zksolcCommand} with Sol, --combined-json and multiple ARG: ${json_args[i]} ${json_args[i]}`, () => { describe(`Run ${zksolcCommand} with Sol, --combined-json and multiple ARG: ${json_args[i]} ${json_args[i]}`, () => {
const args = [`${paths.pathToBasicSolContract}`, `--combined-json`, `${json_args[i]}`, `${json_args[i]}`]; const args = [
const result = executeCommand(zksolcCommand, args); `${paths.pathToBasicSolContract}`,
`--combined-json`,
`${json_args[i]}`,
`${json_args[i]}`,
]
const result = executeCommand(zksolcCommand, args)
xit("Valid command exit code = 1", () => { xit('Valid command exit code = 1', () => {
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1)
}); })
it("--combined-json error is presented", () => { it('--combined-json error is presented', () => {
expect(result.output).toMatch(/(No such file or directory|cannot find the file specified)/i); // Hopefully we should have more precise message here! expect(result.output).toMatch(
}); /(No such file or directory|cannot find the file specified)/i
) // Hopefully we should have more precise message here!
})
xit("solc exit code == zksolc exit code", () => { xit('solc exit code == zksolc exit code', () => {
const solcResult = executeCommand(solcCommand, args); const solcResult = executeCommand(solcCommand, args)
expect(solcResult.exitCode).toBe(result.exitCode); expect(solcResult.exitCode).toBe(result.exitCode)
}); })
}); })
} }
//id1829:III //id1829:III
for (let i = 0; i < json_args.length; i++) { for (let i = 0; i < json_args.length; i++) {
describe(`Run ${zksolcCommand} with Sol, and multiple (--combined-json ${json_args[i]})`, () => { describe(`Run ${zksolcCommand} with Sol, and multiple (--combined-json ${json_args[i]})`, () => {
const args = [`${paths.pathToBasicSolContract}`, `--combined-json`, `${json_args[i]}`, `--combined-json`, `${json_args[i]}`]; const args = [
const result = executeCommand(zksolcCommand, args); `${paths.pathToBasicSolContract}`,
`--combined-json`,
`${json_args[i]}`,
`--combined-json`,
`${json_args[i]}`,
]
const result = executeCommand(zksolcCommand, args)
it("Valid command exit code = 1", () => { it('Valid command exit code = 1', () => {
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1)
}); })
it("--combined-json error is presented", () => { it('--combined-json error is presented', () => {
expect(result.output).toMatch(/(cannot be used multiple times)/i); expect(result.output).toMatch(/(cannot be used multiple times)/i)
}); })
it("solc exit code == zksolc exit code", () => { it('solc exit code == zksolc exit code', () => {
const solcResult = executeCommand(solcCommand, args); const solcResult = executeCommand(solcCommand, args)
expect(solcResult.exitCode).toBe(result.exitCode); expect(solcResult.exitCode).toBe(result.exitCode)
}); })
}); })
} }
//id1830 //id1830
for (let i = 0; i < json_args.length; i++) { for (let i = 0; i < json_args.length; i++) {
describe(`Run ${zksolcCommand} with Yul, and --combined-json ${json_args[i]}`, () => { describe(`Run ${zksolcCommand} with Yul, and --combined-json ${json_args[i]}`, () => {
const args = [`${paths.pathToBasicYulContract}`, `--combined-json`, `${json_args[i]}`]; const args = [
const result = executeCommand(zksolcCommand, args); `${paths.pathToBasicYulContract}`,
`--combined-json`,
`${json_args[i]}`,
]
const result = executeCommand(zksolcCommand, args)
it("Valid command exit code = 1", () => { it('Valid command exit code = 1', () => {
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1)
}); })
it("--combined-json error is presented", () => { it('--combined-json error is presented', () => {
expect(result.output).toMatch(/(ParserError: Expected identifier)/i); expect(result.output).toMatch(/(ParserError: Expected identifier)/i)
}); })
asd asd
it("solc exit code == zksolc exit code", () => { it('solc exit code == zksolc exit code', () => {
const solcResult = executeCommand(solcCommand, args); const solcResult = executeCommand(solcCommand, args)
expect(solcResult.exitCode).toBe(result.exitCode); expect(solcResult.exitCode).toBe(result.exitCode)
}); })
}); })
} }
}); })
+1 -1
View File
@@ -3,7 +3,7 @@ const path = require("path");
const { minify } = require("terser"); const { minify } = require("terser");
const SOLJSON_URI = const SOLJSON_URI =
"https://binaries.soliditylang.org/wasm/soljson-v0.8.29+commit.ab55807c.js"; "https://binaries.soliditylang.org/wasm/soljson-v0.8.30+commit.73712a01.js";
const RESOLC_WASM_URI = const RESOLC_WASM_URI =
process.env.RELEASE_RESOLC_WASM_URI || "http://127.0.0.1:8080/resolc.wasm"; process.env.RELEASE_RESOLC_WASM_URI || "http://127.0.0.1:8080/resolc.wasm";
const RESOLC_WASM_TARGET_DIR = path.join( const RESOLC_WASM_TARGET_DIR = path.join(
+1 -1
View File
@@ -2,7 +2,7 @@
"name": "revive", "name": "revive",
"private": true, "private": true,
"dependencies": { "dependencies": {
"solc": "^0.8.29" "solc": ">=0.8.0 <=0.8.30"
}, },
"scripts": { "scripts": {
"example:web": "http-server ./examples/web/", "example:web": "http-server ./examples/web/",
+106 -110
View File
@@ -1,142 +1,138 @@
import { expect } from "chai"; import { expect } from 'chai'
import { compile } from "../examples/node/revive.js"; import { compile } from '../examples/node/revive.js'
import { fileURLToPath } from "url"; import { fileURLToPath } from 'url'
import path from "path"; import path from 'path'
import fs from "fs"; import fs from 'fs'
const __filename = fileURLToPath(import.meta.url); const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename); const __dirname = path.dirname(__filename)
function loadFixture(fixture) { function loadFixture(fixture) {
const fixturePath = path.resolve(__dirname, `../fixtures/${fixture}`); const fixturePath = path.resolve(__dirname, `../fixtures/${fixture}`)
return JSON.parse(fs.readFileSync(fixturePath, "utf-8")); return JSON.parse(fs.readFileSync(fixturePath, 'utf-8'))
} }
describe("Compile Function Tests", function () { describe('Compile Function Tests', function () {
it("should successfully compile valid Solidity code", async function () { it('should successfully compile valid Solidity code', async function () {
const standardInput = loadFixture("storage.json"); const standardInput = loadFixture('storage.json')
const result = await compile(standardInput); const result = await compile(standardInput)
expect(result).to.be.a("string"); expect(result).to.be.a('string')
const output = JSON.parse(result); const output = JSON.parse(result)
expect(output).to.have.property("contracts"); expect(output).to.have.property('contracts')
expect(output.contracts["fixtures/storage.sol"]).to.have.property( expect(output.contracts['fixtures/storage.sol']).to.have.property('Storage')
"Storage", expect(output.contracts['fixtures/storage.sol'].Storage).to.have.property(
); 'abi'
expect(output.contracts["fixtures/storage.sol"].Storage).to.have.property( )
"abi", expect(output.contracts['fixtures/storage.sol'].Storage).to.have.property(
); 'evm'
expect(output.contracts["fixtures/storage.sol"].Storage).to.have.property( )
"evm",
);
expect( expect(
output.contracts["fixtures/storage.sol"].Storage.evm, output.contracts['fixtures/storage.sol'].Storage.evm
).to.have.property("bytecode"); ).to.have.property('bytecode')
}); })
if (typeof globalThis.Bun == "undefined") { if (typeof globalThis.Bun == 'undefined') {
// Running this test with Bun on a Linux host causes: // Running this test with Bun on a Linux host causes:
// RuntimeError: Out of bounds memory access (evaluating 'getWasmTableEntry(index)(a1, a2, a3, a4, a5)') // RuntimeError: Out of bounds memory access (evaluating 'getWasmTableEntry(index)(a1, a2, a3, a4, a5)')
// Once this issue is resolved, the test will be re-enabled. // Once this issue is resolved, the test will be re-enabled.
it("should successfully compile large Solidity code", async function () { it('should successfully compile large Solidity code', async function () {
const standardInput = loadFixture("token.json"); const standardInput = loadFixture('token.json')
const result = await compile(standardInput); const result = await compile(standardInput)
expect(result).to.be.a("string"); expect(result).to.be.a('string')
const output = JSON.parse(result); const output = JSON.parse(result)
expect(output).to.have.property("contracts"); expect(output).to.have.property('contracts')
expect(output.contracts["fixtures/token.sol"]).to.have.property( expect(output.contracts['fixtures/token.sol']).to.have.property('MyToken')
"MyToken", expect(output.contracts['fixtures/token.sol'].MyToken).to.have.property(
); 'abi'
expect(output.contracts["fixtures/token.sol"].MyToken).to.have.property( )
"abi", expect(output.contracts['fixtures/token.sol'].MyToken).to.have.property(
); 'evm'
expect(output.contracts["fixtures/token.sol"].MyToken).to.have.property( )
"evm",
);
expect( expect(
output.contracts["fixtures/token.sol"].MyToken.evm, output.contracts['fixtures/token.sol'].MyToken.evm
).to.have.property("bytecode"); ).to.have.property('bytecode')
}); })
it("should successfully compile a valid Solidity contract that instantiates the token contracts", async function () { it('should successfully compile a valid Solidity contract that instantiates the token contracts', async function () {
const standardInput = loadFixture("instantiate_tokens.json"); const standardInput = loadFixture('instantiate_tokens.json')
const result = await compile(standardInput); const result = await compile(standardInput)
expect(result).to.be.a("string"); expect(result).to.be.a('string')
const output = JSON.parse(result); const output = JSON.parse(result)
expect(output).to.have.property("contracts"); expect(output).to.have.property('contracts')
expect( expect(
output.contracts["fixtures/instantiate_tokens.sol"], output.contracts['fixtures/instantiate_tokens.sol']
).to.have.property("TokensFactory"); ).to.have.property('TokensFactory')
expect( expect(
output.contracts["fixtures/instantiate_tokens.sol"].TokensFactory, output.contracts['fixtures/instantiate_tokens.sol'].TokensFactory
).to.have.property("abi"); ).to.have.property('abi')
expect( expect(
output.contracts["fixtures/instantiate_tokens.sol"].TokensFactory, output.contracts['fixtures/instantiate_tokens.sol'].TokensFactory
).to.have.property("evm"); ).to.have.property('evm')
expect( expect(
output.contracts["fixtures/instantiate_tokens.sol"].TokensFactory.evm, output.contracts['fixtures/instantiate_tokens.sol'].TokensFactory.evm
).to.have.property("bytecode"); ).to.have.property('bytecode')
}); })
} }
it("should throw an error for invalid Solidity code", async function () { it('should throw an error for invalid Solidity code', async function () {
const standardInput = loadFixture("invalid_contract_content.json"); const standardInput = loadFixture('invalid_contract_content.json')
const result = await compile(standardInput); const result = await compile(standardInput)
expect(result).to.be.a("string"); expect(result).to.be.a('string')
const output = JSON.parse(result); const output = JSON.parse(result)
expect(output).to.have.property("errors"); expect(output).to.have.property('errors')
expect(output.errors).to.be.an("array"); expect(output.errors).to.be.an('array')
expect(output.errors.length).to.be.greaterThan(0); expect(output.errors.length).to.be.greaterThan(0)
expect(output.errors[0].type).to.exist; expect(output.errors[0].type).to.exist
expect(output.errors[0].type).to.contain("ParserError"); expect(output.errors[0].type).to.contain('ParserError')
}); })
it("should return not found error for missing imports", async function () { it('should return not found error for missing imports', async function () {
const standardInput = loadFixture("missing_import.json"); const standardInput = loadFixture('missing_import.json')
const result = await compile(standardInput); const result = await compile(standardInput)
const output = JSON.parse(result); const output = JSON.parse(result)
expect(output).to.have.property("errors"); expect(output).to.have.property('errors')
expect(output.errors).to.be.an("array"); expect(output.errors).to.be.an('array')
expect(output.errors.length).to.be.greaterThan(0); expect(output.errors.length).to.be.greaterThan(0)
expect(output.errors[0].message).to.exist; expect(output.errors[0].message).to.exist
expect(output.errors[0].message).to.include( expect(output.errors[0].message).to.include(
'Source "nonexistent/console.sol" not found', 'Source "nonexistent/console.sol" not found'
); )
}); })
it("should successfully compile a valid Solidity contract that instantiates another contract", async function () { it('should successfully compile a valid Solidity contract that instantiates another contract', async function () {
const standardInput = loadFixture("instantiate.json"); const standardInput = loadFixture('instantiate.json')
const result = await compile(standardInput); const result = await compile(standardInput)
expect(result).to.be.a("string"); expect(result).to.be.a('string')
const output = JSON.parse(result); const output = JSON.parse(result)
expect(output).to.have.property("contracts"); expect(output).to.have.property('contracts')
expect(output.contracts["fixtures/instantiate.sol"]).to.have.property( expect(output.contracts['fixtures/instantiate.sol']).to.have.property(
"ChildContract", 'ChildContract'
); )
expect( expect(
output.contracts["fixtures/instantiate.sol"].ChildContract, output.contracts['fixtures/instantiate.sol'].ChildContract
).to.have.property("abi"); ).to.have.property('abi')
expect( expect(
output.contracts["fixtures/instantiate.sol"].ChildContract, output.contracts['fixtures/instantiate.sol'].ChildContract
).to.have.property("evm"); ).to.have.property('evm')
expect( expect(
output.contracts["fixtures/instantiate.sol"].ChildContract.evm, output.contracts['fixtures/instantiate.sol'].ChildContract.evm
).to.have.property("bytecode"); ).to.have.property('bytecode')
expect(output.contracts["fixtures/instantiate.sol"]).to.have.property( expect(output.contracts['fixtures/instantiate.sol']).to.have.property(
"MainContract", 'MainContract'
); )
expect( expect(
output.contracts["fixtures/instantiate.sol"].MainContract, output.contracts['fixtures/instantiate.sol'].MainContract
).to.have.property("abi"); ).to.have.property('abi')
expect( expect(
output.contracts["fixtures/instantiate.sol"].MainContract, output.contracts['fixtures/instantiate.sol'].MainContract
).to.have.property("evm"); ).to.have.property('evm')
expect( expect(
output.contracts["fixtures/instantiate.sol"].MainContract.evm, output.contracts['fixtures/instantiate.sol'].MainContract.evm
).to.have.property("bytecode"); ).to.have.property('bytecode')
}); })
}); })
+2 -2
View File
@@ -1,7 +1,7 @@
{ {
"name": "@parity/resolc", "name": "@parity/resolc",
"license": "Apache-2.0", "license": "Apache-2.0",
"version": "0.0.0-updated-via-gh-releases", "version": "0.1.0-dev.16",
"author": "Parity <admin@parity.io> (https://parity.io)", "author": "Parity <admin@parity.io> (https://parity.io)",
"module": "index.ts", "module": "index.ts",
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
@@ -32,6 +32,6 @@
"@types/node": "^22.9.0", "@types/node": "^22.9.0",
"commander": "^13.1.0", "commander": "^13.1.0",
"package-json": "^10.0.1", "package-json": "^10.0.1",
"solc": "^0.8.29" "solc": ">=0.8.0 <=0.8.30"
} }
} }
+2 -5
View File
@@ -169,8 +169,7 @@ async function main() {
writeFile( writeFile(
contractFileName + '.polkavm', contractFileName + '.polkavm',
Buffer.from( Buffer.from(
output.contracts[fileName][contractName].evm.bytecode output.contracts[fileName][contractName].evm.bytecode.object,
.object,
'hex' 'hex'
) )
) )
@@ -179,9 +178,7 @@ async function main() {
if (options.abi) { if (options.abi) {
writeFile( writeFile(
contractFileName + '.abi', contractFileName + '.abi',
toFormattedJson( toFormattedJson(output.contracts[fileName][contractName].abi)
output.contracts[fileName][contractName].abi
)
) )
} }
} }
+7 -6
View File
@@ -4,7 +4,6 @@ import assert from 'node:assert'
import { compile, tryResolveImport } from '.' import { compile, tryResolveImport } from '.'
import { resolve } from 'node:path' import { resolve } from 'node:path'
const compileOptions = [{}] const compileOptions = [{}]
if (existsSync('../../target/release/resolc')) { if (existsSync('../../target/release/resolc')) {
compileOptions.push({ bin: '../../target/release/resolc' }) compileOptions.push({ bin: '../../target/release/resolc' })
@@ -57,9 +56,7 @@ test('check Err from stderr', async () => {
assert(false, 'Expected error') assert(false, 'Expected error')
} catch (error) { } catch (error) {
assert( assert(
String(error).includes( String(error).includes('Source file requires different compiler version')
'Source file requires different compiler version'
)
) )
} }
}) })
@@ -74,12 +71,16 @@ test('resolve import', () => {
// scopped module with version // scopped module with version
{ {
file: '@openzeppelin/contracts@5.1.0/token/ERC20/ERC20.sol', file: '@openzeppelin/contracts@5.1.0/token/ERC20/ERC20.sol',
expected: require.resolve('@openzeppelin/contracts/token/ERC20/ERC20.sol'), expected: require.resolve(
'@openzeppelin/contracts/token/ERC20/ERC20.sol'
),
}, },
// scopped module without version // scopped module without version
{ {
file: '@openzeppelin/contracts/token/ERC20/ERC20.sol', file: '@openzeppelin/contracts/token/ERC20/ERC20.sol',
expected: require.resolve('@openzeppelin/contracts/token/ERC20/ERC20.sol'), expected: require.resolve(
'@openzeppelin/contracts/token/ERC20/ERC20.sol'
),
}, },
// scopped module with wrong version // scopped module with wrong version
{ {
+18 -7
View File
@@ -93,13 +93,26 @@ export function version(): string {
export async function compile( export async function compile(
sources: SolcInput, sources: SolcInput,
option: { bin?: string } = {} option: {
optimizer?: Record<string, unknown>
bin?: string
} = {}
): Promise<SolcOutput> { ): Promise<SolcOutput> {
const {
optimizer = {
mode: 'z',
fallback_to_optimizing_for_size: true,
enabled: true,
runs: 200,
},
bin,
} = option
const input = JSON.stringify({ const input = JSON.stringify({
language: 'Solidity', language: 'Solidity',
sources: resolveInputs(sources), sources: resolveInputs(sources),
settings: { settings: {
optimizer: { enabled: true, runs: 200 }, optimizer,
outputSelection: { outputSelection: {
'*': { '*': {
'*': ['abi'], '*': ['abi'],
@@ -108,8 +121,8 @@ export async function compile(
}, },
}) })
if (option.bin) { if (bin) {
return compileWithBin(input, option.bin) return compileWithBin(input, bin)
} }
return resolc(input) return resolc(input)
@@ -138,9 +151,7 @@ export function tryResolveImport(importPath: string) {
let packageJsonPath let packageJsonPath
try { try {
packageJsonPath = require.resolve( packageJsonPath = require.resolve(path.join(basePackage, 'package.json'))
path.join(basePackage, 'package.json')
)
} catch { } catch {
throw new Error(`Could not resolve package ${basePackage}`) throw new Error(`Could not resolve package ${basePackage}`)
} }
+3 -3
View File
@@ -31,7 +31,7 @@
"js/emscripten": { "js/emscripten": {
"name": "revive", "name": "revive",
"dependencies": { "dependencies": {
"solc": "^0.8.29" "solc": ">=0.8.0 <=0.8.30"
}, },
"devDependencies": { "devDependencies": {
"@playwright/test": "^1.49.1", "@playwright/test": "^1.49.1",
@@ -44,13 +44,13 @@
}, },
"js/resolc": { "js/resolc": {
"name": "@parity/resolc", "name": "@parity/resolc",
"version": "1.0.0", "version": "0.0.0-updated-via-gh-releases",
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@types/node": "^22.9.0", "@types/node": "^22.9.0",
"commander": "^13.1.0", "commander": "^13.1.0",
"package-json": "^10.0.1", "package-json": "^10.0.1",
"solc": "^0.8.29" "solc": ">=0.8.0 <=0.8.30"
}, },
"bin": { "bin": {
"resolc": "dist/bin.js" "resolc": "dist/bin.js"