mirror of
https://github.com/pezkuwichain/revive.git
synced 2026-06-14 23:51:06 +00:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 046455db06 | |||
| 70037e1136 | |||
| c0cdde5a5a | |||
| df1921ba93 | |||
| 84018c18ae | |||
| 42cac55be8 | |||
| 6549a4f825 | |||
| f46bea6a96 |
+18
-1
@@ -4,7 +4,24 @@
|
|||||||
|
|
||||||
This is a development pre-release.
|
This is a development pre-release.
|
||||||
|
|
||||||
Supported `polkadot-sdk` rev: `2503.0.1`
|
Supported `polkadot-sdk` rev: `2509.0.0`
|
||||||
|
|
||||||
|
## v0.5.0
|
||||||
|
|
||||||
|
This is a development pre-release.
|
||||||
|
|
||||||
|
Supported `polkadot-sdk` rev: `2509.0.0`
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Support for `SELFDESTRUCT`.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Emulated EVM heap memory accesses of zero length are never out of bounds.
|
||||||
|
- Switched to newer and cheaper storage syscalls (omits reads and writes of `0` values).
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Introduced a workaround avoiding compiler crashes caused by a bug in LLVM affecting `SDIV`.
|
||||||
|
- An off-by-one bug affecting `SDIV` overflow semantics.
|
||||||
|
|
||||||
## v0.4.1
|
## v0.4.1
|
||||||
|
|
||||||
|
|||||||
Generated
+2201
-1664
File diff suppressed because it is too large
Load Diff
+16
-16
@@ -15,21 +15,21 @@ rust-version = "1.85.0"
|
|||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
lld-sys = { version = "0.1.0", path = "crates/lld-sys" }
|
lld-sys = { version = "0.1.0", path = "crates/lld-sys" }
|
||||||
resolc = { version = "0.4.0", path = "crates/resolc", default-features = false }
|
resolc = { version = "0.5.0", path = "crates/resolc", default-features = false }
|
||||||
revive-benchmarks = { version = "0.1.0", path = "crates/benchmarks" }
|
revive-benchmarks = { version = "0.1.0", path = "crates/benchmarks" }
|
||||||
revive-build-utils = { version = "0.2.0", path = "crates/build-utils" }
|
revive-build-utils = { version = "0.2.0", path = "crates/build-utils" }
|
||||||
revive-builtins = { version = "0.1.0", path = "crates/builtins" }
|
revive-builtins = { version = "0.1.0", path = "crates/builtins" }
|
||||||
revive-common = { version = "0.2.1", path = "crates/common" }
|
revive-common = { version = "0.2.1", path = "crates/common" }
|
||||||
revive-differential = { version = "0.2.0", path = "crates/differential" }
|
revive-differential = { version = "0.2.0", path = "crates/differential" }
|
||||||
revive-explorer = { version = "0.1.0", path = "crates/explore" }
|
revive-explorer = { version = "0.1.0", path = "crates/explore" }
|
||||||
revive-integration = { version = "0.2.0", path = "crates/integration" }
|
revive-integration = { version = "0.3.0", path = "crates/integration" }
|
||||||
revive-linker = { version = "0.2.0", path = "crates/linker" }
|
revive-linker = { version = "0.2.0", path = "crates/linker" }
|
||||||
revive-llvm-context = { version = "0.4.1", path = "crates/llvm-context" }
|
revive-llvm-context = { version = "0.5.0", path = "crates/llvm-context" }
|
||||||
revive-runner = { version = "0.2.0", path = "crates/runner" }
|
revive-runner = { version = "0.3.0", path = "crates/runner" }
|
||||||
revive-runtime-api = { version = "0.3.0", path = "crates/runtime-api" }
|
revive-runtime-api = { version = "0.4.0", path = "crates/runtime-api" }
|
||||||
revive-solc-json-interface = { version = "0.4.0", path = "crates/solc-json-interface", default-features = false }
|
revive-solc-json-interface = { version = "0.4.0", path = "crates/solc-json-interface", default-features = false }
|
||||||
revive-stdlib = { version = "0.2.0", path = "crates/stdlib" }
|
revive-stdlib = { version = "0.2.0", path = "crates/stdlib" }
|
||||||
revive-yul = { version = "0.3.1", path = "crates/yul" }
|
revive-yul = { version = "0.4.0", path = "crates/yul" }
|
||||||
|
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
cc = "1.2"
|
cc = "1.2"
|
||||||
@@ -46,21 +46,21 @@ num = "0.4.3"
|
|||||||
sha1 = "0.10"
|
sha1 = "0.10"
|
||||||
sha3 = "0.10"
|
sha3 = "0.10"
|
||||||
thiserror = "2.0"
|
thiserror = "2.0"
|
||||||
which = "7.0"
|
which = "8.0"
|
||||||
path-slash = "0.2"
|
path-slash = "0.2"
|
||||||
rayon = "1.10"
|
rayon = "1.10"
|
||||||
clap = { version = "4", default-features = false, features = ["derive"] }
|
clap = { version = "4", default-features = false, features = ["derive"] }
|
||||||
polkavm-common = "0.24.0"
|
polkavm-common = "0.29.0"
|
||||||
polkavm-linker = "0.24.0"
|
polkavm-linker = "0.29.0"
|
||||||
polkavm-disassembler = "0.24.0"
|
polkavm-disassembler = "0.29.0"
|
||||||
polkavm = "0.24.0"
|
polkavm = "0.29.0"
|
||||||
alloy-primitives = { version = "1.1", features = ["serde"] }
|
alloy-primitives = { version = "1.1", features = ["serde"] }
|
||||||
alloy-sol-types = "1.1"
|
alloy-sol-types = "1.1"
|
||||||
alloy-genesis = "1.0"
|
alloy-genesis = "1.0.41"
|
||||||
alloy-serde = "1.0"
|
alloy-serde = "1.0"
|
||||||
env_logger = { version = "0.11.8", default-features = false }
|
env_logger = { version = "0.11.8", default-features = false }
|
||||||
serde_stacker = "0.1.12"
|
serde_stacker = "0.1.12"
|
||||||
criterion = { version = "0.6", features = ["html_reports"] }
|
criterion = { version = "0.7", features = ["html_reports"] }
|
||||||
log = { version = "0.4.27" }
|
log = { version = "0.4.27" }
|
||||||
git2 = { version = "0.20.2", default-features = false }
|
git2 = { version = "0.20.2", default-features = false }
|
||||||
downloader = "0.2.8"
|
downloader = "0.2.8"
|
||||||
@@ -68,15 +68,15 @@ flate2 = "1.1"
|
|||||||
fs_extra = "1.3"
|
fs_extra = "1.3"
|
||||||
num_cpus = "1"
|
num_cpus = "1"
|
||||||
tar = "0.4"
|
tar = "0.4"
|
||||||
toml = "0.8"
|
toml = "0.9"
|
||||||
assert_cmd = "2.0"
|
assert_cmd = "2"
|
||||||
assert_fs = "1.1"
|
assert_fs = "1.1"
|
||||||
normpath = "1.3"
|
normpath = "1.3"
|
||||||
|
|
||||||
# polkadot-sdk and friends
|
# polkadot-sdk and friends
|
||||||
codec = { version = "3.7.5", default-features = false, package = "parity-scale-codec" }
|
codec = { version = "3.7.5", default-features = false, package = "parity-scale-codec" }
|
||||||
scale-info = { version = "2.11.6", default-features = false }
|
scale-info = { version = "2.11.6", default-features = false }
|
||||||
polkadot-sdk = { version = "2503.0.1" }
|
polkadot-sdk = { version = "2509.0.0" }
|
||||||
|
|
||||||
# llvm
|
# llvm
|
||||||
[workspace.dependencies.inkwell]
|
[workspace.dependencies.inkwell]
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "revive-integration"
|
name = "revive-integration"
|
||||||
version = "0.2.0"
|
version = "0.3.0"
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
repository.workspace = true
|
repository.workspace = true
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
{
|
{
|
||||||
"Baseline": 932,
|
"Baseline": 914,
|
||||||
"Computation": 2313,
|
"Computation": 2295,
|
||||||
"DivisionArithmetics": 9103,
|
"DivisionArithmetics": 14496,
|
||||||
"ERC20": 17479,
|
"ERC20": 17482,
|
||||||
"Events": 1692,
|
"Events": 1674,
|
||||||
"FibonacciIterative": 1508,
|
"FibonacciIterative": 1490,
|
||||||
"Flipper": 2098,
|
"Flipper": 2086,
|
||||||
"SHA1": 8176
|
"SHA1": 8158
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
pragma solidity ^0.8.24;
|
||||||
|
|
||||||
|
/* runner.json
|
||||||
|
{
|
||||||
|
"differential": true,
|
||||||
|
"actions": [
|
||||||
|
{
|
||||||
|
"Instantiate": {
|
||||||
|
"code": {
|
||||||
|
"Solidity": {
|
||||||
|
"contract": "MemoryBounds"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Call": {
|
||||||
|
"dest": {
|
||||||
|
"Instantiated": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
contract MemoryBounds {
|
||||||
|
fallback() external {
|
||||||
|
assembly {
|
||||||
|
// Accessing OOB offsets should always work when the length is 0.
|
||||||
|
return(100000, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
pragma solidity ^0.8;
|
||||||
|
|
||||||
|
// TODO: This currently fails the differential test.
|
||||||
|
// The pallet doesn't send the correct balance back.
|
||||||
|
|
||||||
|
/* runner.json
|
||||||
|
{
|
||||||
|
"differential": false,
|
||||||
|
"actions": [
|
||||||
|
{
|
||||||
|
"Upload": {
|
||||||
|
"code": {
|
||||||
|
"Solidity": {
|
||||||
|
"contract": "SelfdestructTester"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Instantiate": {
|
||||||
|
"code": {
|
||||||
|
"Solidity": {
|
||||||
|
"contract": "Selfdestruct"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"value": 123456789
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Call": {
|
||||||
|
"dest": {
|
||||||
|
"Instantiated": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
contract Selfdestruct {
|
||||||
|
address tester;
|
||||||
|
uint value;
|
||||||
|
|
||||||
|
constructor() payable {
|
||||||
|
require(msg.value > 0, "the test should have value");
|
||||||
|
value = msg.value;
|
||||||
|
|
||||||
|
SelfdestructTester s = new SelfdestructTester{value: msg.value}();
|
||||||
|
tester = address(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
fallback() external {
|
||||||
|
(bool success, ) = tester.call(hex"");
|
||||||
|
require(success, "the call to the self destructing contract should succeed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
contract SelfdestructTester {
|
||||||
|
constructor() payable {}
|
||||||
|
|
||||||
|
fallback() external {
|
||||||
|
selfdestruct(payable(msg.sender));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -62,6 +62,8 @@ test_spec!(function_type, "FunctionType", "FunctionType.sol");
|
|||||||
test_spec!(layout_at, "LayoutAt", "LayoutAt.sol");
|
test_spec!(layout_at, "LayoutAt", "LayoutAt.sol");
|
||||||
test_spec!(shift_arithmetic_right, "SAR", "SAR.sol");
|
test_spec!(shift_arithmetic_right, "SAR", "SAR.sol");
|
||||||
test_spec!(add_mod_mul_mod, "AddModMulModTester", "AddModMulMod.sol");
|
test_spec!(add_mod_mul_mod, "AddModMulModTester", "AddModMulMod.sol");
|
||||||
|
test_spec!(memory_bounds, "MemoryBounds", "MemoryBounds.sol");
|
||||||
|
test_spec!(selfdestruct, "Selfdestruct", "Selfdestruct.sol");
|
||||||
|
|
||||||
fn instantiate(path: &str, contract: &str) -> Vec<SpecsAction> {
|
fn instantiate(path: &str, contract: &str) -> Vec<SpecsAction> {
|
||||||
vec![Instantiate {
|
vec![Instantiate {
|
||||||
@@ -168,6 +170,8 @@ fn signed_division() {
|
|||||||
(minus_five, two),
|
(minus_five, two),
|
||||||
(I256::MINUS_ONE, I256::MIN),
|
(I256::MINUS_ONE, I256::MIN),
|
||||||
(one, I256::ZERO),
|
(one, I256::ZERO),
|
||||||
|
(I256::MIN, I256::MINUS_ONE),
|
||||||
|
(I256::MIN + I256::ONE, I256::MINUS_ONE),
|
||||||
] {
|
] {
|
||||||
actions.push(Call {
|
actions.push(Call {
|
||||||
origin: TestAddress::Alice,
|
origin: TestAddress::Alice,
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ authors = [
|
|||||||
"Anton Baliasnikov <aba@matterlabs.dev>",
|
"Anton Baliasnikov <aba@matterlabs.dev>",
|
||||||
"Cyrill Leutwiler <cyrill@parity.io>",
|
"Cyrill Leutwiler <cyrill@parity.io>",
|
||||||
]
|
]
|
||||||
version = "0.3.0"
|
version = "0.4.0"
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
repository.workspace = true
|
repository.workspace = true
|
||||||
|
|||||||
@@ -2,20 +2,20 @@ pub mod common;
|
|||||||
|
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
|
||||||
use assert_cmd::prelude::*;
|
use assert_cmd::{cargo, prelude::*};
|
||||||
|
|
||||||
/// This test verifies that the LLVM repository can be successfully cloned, built, and cleaned.
|
/// This test verifies that the LLVM repository can be successfully cloned, built, and cleaned.
|
||||||
#[test]
|
#[test]
|
||||||
fn clone_build_and_clean() -> anyhow::Result<()> {
|
fn clone_build_and_clean() -> anyhow::Result<()> {
|
||||||
let test_dir = common::TestDir::with_lockfile(None)?;
|
let test_dir = common::TestDir::with_lockfile(None)?;
|
||||||
|
|
||||||
Command::cargo_bin(common::REVIVE_LLVM)?
|
Command::new(cargo::cargo_bin!("revive-llvm"))
|
||||||
.current_dir(test_dir.path())
|
.current_dir(test_dir.path())
|
||||||
.arg("clone")
|
.arg("clone")
|
||||||
.assert()
|
.assert()
|
||||||
.success();
|
.success();
|
||||||
|
|
||||||
Command::cargo_bin(common::REVIVE_LLVM)?
|
Command::new(cargo::cargo_bin!("revive-llvm"))
|
||||||
.current_dir(test_dir.path())
|
.current_dir(test_dir.path())
|
||||||
.arg("build")
|
.arg("build")
|
||||||
.arg("--llvm-projects")
|
.arg("--llvm-projects")
|
||||||
@@ -25,13 +25,13 @@ fn clone_build_and_clean() -> anyhow::Result<()> {
|
|||||||
.assert()
|
.assert()
|
||||||
.success();
|
.success();
|
||||||
|
|
||||||
Command::cargo_bin(common::REVIVE_LLVM)?
|
Command::new(cargo::cargo_bin!("revive-llvm"))
|
||||||
.current_dir(test_dir.path())
|
.current_dir(test_dir.path())
|
||||||
.arg("builtins")
|
.arg("builtins")
|
||||||
.assert()
|
.assert()
|
||||||
.success();
|
.success();
|
||||||
|
|
||||||
Command::cargo_bin(common::REVIVE_LLVM)?
|
Command::new(cargo::cargo_bin!("revive-llvm"))
|
||||||
.current_dir(test_dir.path())
|
.current_dir(test_dir.path())
|
||||||
.arg("clean")
|
.arg("clean")
|
||||||
.assert()
|
.assert()
|
||||||
@@ -47,13 +47,13 @@ fn clone_build_and_clean() -> anyhow::Result<()> {
|
|||||||
fn clone_build_and_clean_musl() -> anyhow::Result<()> {
|
fn clone_build_and_clean_musl() -> anyhow::Result<()> {
|
||||||
let test_dir = common::TestDir::with_lockfile(None)?;
|
let test_dir = common::TestDir::with_lockfile(None)?;
|
||||||
|
|
||||||
Command::cargo_bin(common::REVIVE_LLVM)?
|
Command::new(cargo::cargo_bin!("revive-llvm"))
|
||||||
.arg("clone")
|
.arg("clone")
|
||||||
.current_dir(test_dir.path())
|
.current_dir(test_dir.path())
|
||||||
.assert()
|
.assert()
|
||||||
.success();
|
.success();
|
||||||
|
|
||||||
Command::cargo_bin(common::REVIVE_LLVM)?
|
Command::new(cargo::cargo_bin!("revive-llvm"))
|
||||||
.current_dir(test_dir.path())
|
.current_dir(test_dir.path())
|
||||||
.arg("build")
|
.arg("build")
|
||||||
.arg("--llvm-projects")
|
.arg("--llvm-projects")
|
||||||
@@ -63,7 +63,7 @@ fn clone_build_and_clean_musl() -> anyhow::Result<()> {
|
|||||||
.assert()
|
.assert()
|
||||||
.success();
|
.success();
|
||||||
|
|
||||||
Command::cargo_bin(common::REVIVE_LLVM)?
|
Command::new(cargo::cargo_bin!("revive-llvm"))
|
||||||
.arg("--target-env")
|
.arg("--target-env")
|
||||||
.arg("musl")
|
.arg("musl")
|
||||||
.arg("build")
|
.arg("build")
|
||||||
@@ -75,7 +75,7 @@ fn clone_build_and_clean_musl() -> anyhow::Result<()> {
|
|||||||
.assert()
|
.assert()
|
||||||
.success();
|
.success();
|
||||||
|
|
||||||
Command::cargo_bin(common::REVIVE_LLVM)?
|
Command::new(cargo::cargo_bin!("revive-llvm"))
|
||||||
.current_dir(test_dir.path())
|
.current_dir(test_dir.path())
|
||||||
.arg("clean")
|
.arg("clean")
|
||||||
.assert()
|
.assert()
|
||||||
@@ -91,13 +91,13 @@ fn clone_build_and_clean_musl() -> anyhow::Result<()> {
|
|||||||
fn debug_build_with_tests_coverage() -> anyhow::Result<()> {
|
fn debug_build_with_tests_coverage() -> anyhow::Result<()> {
|
||||||
let test_dir = common::TestDir::with_lockfile(None)?;
|
let test_dir = common::TestDir::with_lockfile(None)?;
|
||||||
|
|
||||||
Command::cargo_bin(common::REVIVE_LLVM)?
|
Command::new(cargo::cargo_bin!("revive-llvm"))
|
||||||
.current_dir(test_dir.path())
|
.current_dir(test_dir.path())
|
||||||
.arg("clone")
|
.arg("clone")
|
||||||
.assert()
|
.assert()
|
||||||
.success();
|
.success();
|
||||||
|
|
||||||
Command::cargo_bin(common::REVIVE_LLVM)?
|
Command::new(cargo::cargo_bin!("revive-llvm"))
|
||||||
.current_dir(test_dir.path())
|
.current_dir(test_dir.path())
|
||||||
.arg("build")
|
.arg("build")
|
||||||
.arg("--enable-coverage")
|
.arg("--enable-coverage")
|
||||||
@@ -120,13 +120,13 @@ fn debug_build_with_tests_coverage() -> anyhow::Result<()> {
|
|||||||
fn build_with_sanitizers() -> anyhow::Result<()> {
|
fn build_with_sanitizers() -> anyhow::Result<()> {
|
||||||
let test_dir = common::TestDir::with_lockfile(None)?;
|
let test_dir = common::TestDir::with_lockfile(None)?;
|
||||||
|
|
||||||
Command::cargo_bin(common::REVIVE_LLVM)?
|
Command::new(cargo::cargo_bin!("revive-llvm"))
|
||||||
.current_dir(test_dir.path())
|
.current_dir(test_dir.path())
|
||||||
.arg("clone")
|
.arg("clone")
|
||||||
.assert()
|
.assert()
|
||||||
.success();
|
.success();
|
||||||
|
|
||||||
Command::cargo_bin(common::REVIVE_LLVM)?
|
Command::new(cargo::cargo_bin!("revive-llvm"))
|
||||||
.current_dir(test_dir.path())
|
.current_dir(test_dir.path())
|
||||||
.arg("build")
|
.arg("build")
|
||||||
.arg("--sanitizer")
|
.arg("--sanitizer")
|
||||||
@@ -146,16 +146,16 @@ fn build_with_sanitizers() -> anyhow::Result<()> {
|
|||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
fn clone_build_and_clean_emscripten() -> anyhow::Result<()> {
|
fn clone_build_and_clean_emscripten() -> anyhow::Result<()> {
|
||||||
let test_dir = common::TestDir::with_lockfile(None)?;
|
let test_dir = common::TestDir::with_lockfile(None)?;
|
||||||
let command = Command::cargo_bin(common::REVIVE_LLVM)?;
|
let command = Command::new(cargo::cargo_bin!("revive-llvm"));
|
||||||
let program = command.get_program().to_string_lossy();
|
let program = command.get_program().to_string_lossy();
|
||||||
|
|
||||||
Command::cargo_bin(common::REVIVE_LLVM)?
|
Command::new(cargo::cargo_bin!("revive-llvm"))
|
||||||
.current_dir(test_dir.path())
|
.current_dir(test_dir.path())
|
||||||
.arg("clone")
|
.arg("clone")
|
||||||
.assert()
|
.assert()
|
||||||
.success();
|
.success();
|
||||||
|
|
||||||
Command::cargo_bin(common::REVIVE_LLVM)?
|
Command::new(cargo::cargo_bin!("revive-llvm"))
|
||||||
.current_dir(test_dir.path())
|
.current_dir(test_dir.path())
|
||||||
.arg("build")
|
.arg("build")
|
||||||
.arg("--llvm-projects")
|
.arg("--llvm-projects")
|
||||||
@@ -183,7 +183,7 @@ fn clone_build_and_clean_emscripten() -> anyhow::Result<()> {
|
|||||||
.assert()
|
.assert()
|
||||||
.success();
|
.success();
|
||||||
|
|
||||||
Command::cargo_bin(common::REVIVE_LLVM)?
|
Command::new(cargo::cargo_bin!("revive-llvm"))
|
||||||
.arg("clean")
|
.arg("clean")
|
||||||
.current_dir(test_dir.path())
|
.current_dir(test_dir.path())
|
||||||
.assert()
|
.assert()
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ pub mod common;
|
|||||||
|
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
|
||||||
use assert_cmd::prelude::*;
|
use assert_cmd::{cargo, prelude::*};
|
||||||
|
|
||||||
/// This test verifies that after cloning the LLVM repository, checking out a specific branch
|
/// This test verifies that after cloning the LLVM repository, checking out a specific branch
|
||||||
/// or reference works as expected.
|
/// or reference works as expected.
|
||||||
@@ -10,13 +10,13 @@ use assert_cmd::prelude::*;
|
|||||||
fn checkout_after_clone() -> anyhow::Result<()> {
|
fn checkout_after_clone() -> anyhow::Result<()> {
|
||||||
let test_dir = common::TestDir::with_lockfile(None)?;
|
let test_dir = common::TestDir::with_lockfile(None)?;
|
||||||
|
|
||||||
Command::cargo_bin(common::REVIVE_LLVM)?
|
Command::new(cargo::cargo_bin!("revive-llvm"))
|
||||||
.current_dir(test_dir.path())
|
.current_dir(test_dir.path())
|
||||||
.arg("clone")
|
.arg("clone")
|
||||||
.assert()
|
.assert()
|
||||||
.success();
|
.success();
|
||||||
|
|
||||||
Command::cargo_bin(common::REVIVE_LLVM)?
|
Command::new(cargo::cargo_bin!("revive-llvm"))
|
||||||
.current_dir(test_dir.path())
|
.current_dir(test_dir.path())
|
||||||
.arg("checkout")
|
.arg("checkout")
|
||||||
.assert()
|
.assert()
|
||||||
@@ -31,13 +31,13 @@ fn checkout_after_clone() -> anyhow::Result<()> {
|
|||||||
fn force_checkout() -> anyhow::Result<()> {
|
fn force_checkout() -> anyhow::Result<()> {
|
||||||
let test_dir = common::TestDir::with_lockfile(None)?;
|
let test_dir = common::TestDir::with_lockfile(None)?;
|
||||||
|
|
||||||
Command::cargo_bin(common::REVIVE_LLVM)?
|
Command::new(cargo::cargo_bin!("revive-llvm"))
|
||||||
.current_dir(test_dir.path())
|
.current_dir(test_dir.path())
|
||||||
.arg("clone")
|
.arg("clone")
|
||||||
.assert()
|
.assert()
|
||||||
.success();
|
.success();
|
||||||
|
|
||||||
Command::cargo_bin(common::REVIVE_LLVM)?
|
Command::new(cargo::cargo_bin!("revive-llvm"))
|
||||||
.current_dir(test_dir.path())
|
.current_dir(test_dir.path())
|
||||||
.arg("checkout")
|
.arg("checkout")
|
||||||
.arg("--force")
|
.arg("--force")
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ pub mod common;
|
|||||||
|
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
|
||||||
use assert_cmd::prelude::*;
|
use assert_cmd::{cargo, prelude::*};
|
||||||
|
|
||||||
/// This test verifies that the LLVM repository can be successfully cloned using a specific branch
|
/// This test verifies that the LLVM repository can be successfully cloned using a specific branch
|
||||||
/// and reference.
|
/// and reference.
|
||||||
@@ -10,7 +10,7 @@ use assert_cmd::prelude::*;
|
|||||||
fn clone() -> anyhow::Result<()> {
|
fn clone() -> anyhow::Result<()> {
|
||||||
let test_dir = common::TestDir::with_lockfile(None)?;
|
let test_dir = common::TestDir::with_lockfile(None)?;
|
||||||
|
|
||||||
Command::cargo_bin(common::REVIVE_LLVM)?
|
Command::new(cargo::cargo_bin!("revive-llvm"))
|
||||||
.current_dir(test_dir.path())
|
.current_dir(test_dir.path())
|
||||||
.arg("clone")
|
.arg("clone")
|
||||||
.assert()
|
.assert()
|
||||||
@@ -25,7 +25,7 @@ fn clone() -> anyhow::Result<()> {
|
|||||||
fn clone_deep() -> anyhow::Result<()> {
|
fn clone_deep() -> anyhow::Result<()> {
|
||||||
let test_dir = common::TestDir::with_lockfile(None)?;
|
let test_dir = common::TestDir::with_lockfile(None)?;
|
||||||
|
|
||||||
Command::cargo_bin(common::REVIVE_LLVM)?
|
Command::new(cargo::cargo_bin!("revive-llvm"))
|
||||||
.current_dir(test_dir.path())
|
.current_dir(test_dir.path())
|
||||||
.arg("clone")
|
.arg("clone")
|
||||||
.arg("--deep")
|
.arg("--deep")
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "revive-llvm-context"
|
name = "revive-llvm-context"
|
||||||
version = "0.4.1"
|
version = "0.5.0"
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
repository.workspace = true
|
repository.workspace = true
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ impl RuntimeFunction for SignedDivision {
|
|||||||
"max_uint",
|
"max_uint",
|
||||||
)?;
|
)?;
|
||||||
let is_operand_1_overflow = context.builder().build_int_compare(
|
let is_operand_1_overflow = context.builder().build_int_compare(
|
||||||
inkwell::IntPredicate::EQ,
|
inkwell::IntPredicate::SLT,
|
||||||
operand_1,
|
operand_1,
|
||||||
context.builder().build_int_neg(max_uint, "min_uint")?,
|
context.builder().build_int_neg(max_uint, "min_uint")?,
|
||||||
"is_operand_1_overflow",
|
"is_operand_1_overflow",
|
||||||
|
|||||||
@@ -47,6 +47,17 @@ impl RuntimeFunction for Sbrk {
|
|||||||
let offset = Self::paramater(context, 0).into_int_value();
|
let offset = Self::paramater(context, 0).into_int_value();
|
||||||
let size = Self::paramater(context, 1).into_int_value();
|
let size = Self::paramater(context, 1).into_int_value();
|
||||||
|
|
||||||
|
let return_block = context.append_basic_block("return_pointer");
|
||||||
|
let body_block = context.append_basic_block("body");
|
||||||
|
let is_size_zero = context.builder().build_int_compare(
|
||||||
|
inkwell::IntPredicate::EQ,
|
||||||
|
size,
|
||||||
|
context.xlen_type().const_zero(),
|
||||||
|
"is_size_zero",
|
||||||
|
)?;
|
||||||
|
context.build_conditional_branch(is_size_zero, return_block, body_block)?;
|
||||||
|
|
||||||
|
context.set_basic_block(body_block);
|
||||||
let trap_block = context.append_basic_block("trap");
|
let trap_block = context.append_basic_block("trap");
|
||||||
let offset_in_bounds_block = context.append_basic_block("offset_in_bounds");
|
let offset_in_bounds_block = context.append_basic_block("offset_in_bounds");
|
||||||
let is_offset_out_of_bounds = context.builder().build_int_compare(
|
let is_offset_out_of_bounds = context.builder().build_int_compare(
|
||||||
@@ -91,7 +102,6 @@ impl RuntimeFunction for Sbrk {
|
|||||||
)?;
|
)?;
|
||||||
|
|
||||||
context.set_basic_block(size_in_bounds_block);
|
context.set_basic_block(size_in_bounds_block);
|
||||||
let return_block = context.append_basic_block("return_pointer");
|
|
||||||
let new_size_block = context.append_basic_block("new_size");
|
let new_size_block = context.append_basic_block("new_size");
|
||||||
let is_new_size = context.builder().build_int_compare(
|
let is_new_size = context.builder().build_int_compare(
|
||||||
inkwell::IntPredicate::UGT,
|
inkwell::IntPredicate::UGT,
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ use inkwell::debug_info::AsDIScope;
|
|||||||
use inkwell::debug_info::DIScope;
|
use inkwell::debug_info::DIScope;
|
||||||
use inkwell::types::BasicType;
|
use inkwell::types::BasicType;
|
||||||
use inkwell::values::BasicValue;
|
use inkwell::values::BasicValue;
|
||||||
|
use inkwell::values::InstructionOpcode;
|
||||||
use revive_solc_json_interface::PolkaVMDefaultHeapMemorySize;
|
use revive_solc_json_interface::PolkaVMDefaultHeapMemorySize;
|
||||||
use revive_solc_json_interface::PolkaVMDefaultStackMemorySize;
|
use revive_solc_json_interface::PolkaVMDefaultStackMemorySize;
|
||||||
use revive_solc_json_interface::SolcStandardJsonInputSettingsPolkaVMMemory;
|
use revive_solc_json_interface::SolcStandardJsonInputSettingsPolkaVMMemory;
|
||||||
@@ -288,6 +289,17 @@ impl<'ctx> Context<'ctx> {
|
|||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
// Remove MinSize on functions that perform large integer div/rem to
|
||||||
|
// avoid compiler crash that happens when large integer div/rem by
|
||||||
|
// power-of-2 are not being expanded by ExpandLargeIntDivRem pass as
|
||||||
|
// it expects peephole from DAGCombine, which doesn't happen due to the
|
||||||
|
// MinSize attribute being set on the function.
|
||||||
|
// NOTE: As soon as it strips attribute from a function where large
|
||||||
|
// integer div/rem is used, it's crucial to call it after inlining.
|
||||||
|
// TODO: Remove this once LLVM fix is backported to LLVM 21 and we
|
||||||
|
// switch to corresponding inkwell version.
|
||||||
|
self.strip_minsize_for_divrem();
|
||||||
|
|
||||||
self.debug_config
|
self.debug_config
|
||||||
.dump_llvm_ir_optimized(contract_path, self.module())?;
|
.dump_llvm_ir_optimized(contract_path, self.module())?;
|
||||||
|
|
||||||
@@ -1394,4 +1406,38 @@ impl<'ctx> Context<'ctx> {
|
|||||||
name.to_string()
|
name.to_string()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Scans all functions in the module and removes the `MinSize` attribute
|
||||||
|
/// if the function contains any large sdiv, udiv, srem, urem instructions with either unknown
|
||||||
|
/// NOTE: The check here could be relaxed by checking denominator: if the denominator is
|
||||||
|
/// unknown or is a power-of-2 constant, then need to strip the `minsize` attribute; otherwise
|
||||||
|
/// instruction can be ignored as backend will expand it correctly.
|
||||||
|
fn strip_minsize_for_divrem(&self) {
|
||||||
|
self.module().get_functions().for_each(|func| {
|
||||||
|
let has_divrem = func.get_basic_block_iter().any(|b| {
|
||||||
|
b.get_instructions().any(|inst| match inst.get_opcode() {
|
||||||
|
InstructionOpcode::SDiv
|
||||||
|
| InstructionOpcode::UDiv
|
||||||
|
| InstructionOpcode::SRem
|
||||||
|
| InstructionOpcode::URem => {
|
||||||
|
inst.get_type().into_int_type().get_bit_width() >= 256
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
})
|
||||||
|
});
|
||||||
|
if has_divrem
|
||||||
|
&& func
|
||||||
|
.get_enum_attribute(
|
||||||
|
inkwell::attributes::AttributeLoc::Function,
|
||||||
|
Attribute::MinSize as u32,
|
||||||
|
)
|
||||||
|
.is_some()
|
||||||
|
{
|
||||||
|
func.remove_enum_attribute(
|
||||||
|
inkwell::attributes::AttributeLoc::Function,
|
||||||
|
Attribute::MinSize as u32,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -157,6 +157,10 @@ fn emit_load<'ctx>(
|
|||||||
key: BasicValueEnum<'ctx>,
|
key: BasicValueEnum<'ctx>,
|
||||||
transient: bool,
|
transient: bool,
|
||||||
) -> anyhow::Result<BasicValueEnum<'ctx>> {
|
) -> anyhow::Result<BasicValueEnum<'ctx>> {
|
||||||
|
let is_transient = context.xlen_type().const_int(transient as u64, false);
|
||||||
|
let key_pointer = context.build_alloca_at_entry(context.word_type(), "key_pointer");
|
||||||
|
let value_pointer = context.build_alloca_at_entry(context.word_type(), "value_pointer");
|
||||||
|
|
||||||
let mut key = context.build_load(
|
let mut key = context.build_load(
|
||||||
super::Pointer::new(
|
super::Pointer::new(
|
||||||
context.word_type(),
|
context.word_type(),
|
||||||
@@ -168,33 +172,17 @@ fn emit_load<'ctx>(
|
|||||||
if !transient {
|
if !transient {
|
||||||
key = context.build_byte_swap(key)?;
|
key = context.build_byte_swap(key)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let key_pointer = context.build_alloca_at_entry(context.word_type(), "key_pointer");
|
|
||||||
let value_pointer = context.build_alloca_at_entry(context.word_type(), "value_pointer");
|
|
||||||
let length_pointer = context.build_alloca_at_entry(context.xlen_type(), "length_pointer");
|
|
||||||
|
|
||||||
context.builder().build_store(key_pointer.value, key)?;
|
context.builder().build_store(key_pointer.value, key)?;
|
||||||
context.build_store(value_pointer, context.word_const(0))?;
|
|
||||||
context.build_store(
|
|
||||||
length_pointer,
|
|
||||||
context
|
|
||||||
.xlen_type()
|
|
||||||
.const_int(revive_common::BYTE_LENGTH_WORD as u64, false),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let is_transient = context.xlen_type().const_int(transient as u64, false);
|
|
||||||
|
|
||||||
let arguments = [
|
let arguments = [
|
||||||
is_transient.into(),
|
is_transient.into(),
|
||||||
key_pointer.to_int(context).into(),
|
key_pointer.to_int(context).into(),
|
||||||
context.xlen_type().const_all_ones().into(),
|
|
||||||
value_pointer.to_int(context).into(),
|
value_pointer.to_int(context).into(),
|
||||||
length_pointer.to_int(context).into(),
|
|
||||||
];
|
];
|
||||||
context.build_runtime_call(revive_runtime_api::polkavm_imports::GET_STORAGE, &arguments);
|
context.build_runtime_call(revive_runtime_api::polkavm_imports::GET_STORAGE, &arguments);
|
||||||
|
|
||||||
// We do not to check the return value: Solidity assumes infallible loads.
|
// We do not to check the return value: Solidity assumes infallible loads.
|
||||||
// If a key doesn't exist the "zero" value is returned (ensured by above write).
|
// If a key doesn't exist the syscall returns zero.
|
||||||
|
|
||||||
let value = context.build_load(value_pointer, "storage_value")?;
|
let value = context.build_load(value_pointer, "storage_value")?;
|
||||||
Ok(if transient {
|
Ok(if transient {
|
||||||
@@ -210,6 +198,10 @@ fn emit_store<'ctx>(
|
|||||||
value: BasicValueEnum<'ctx>,
|
value: BasicValueEnum<'ctx>,
|
||||||
transient: bool,
|
transient: bool,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
|
let is_transient = context.xlen_type().const_int(transient as u64, false);
|
||||||
|
let key_pointer = context.build_alloca_at_entry(context.word_type(), "key_pointer");
|
||||||
|
let value_pointer = context.build_alloca_at_entry(context.word_type(), "value_pointer");
|
||||||
|
|
||||||
let mut key = context.build_load(
|
let mut key = context.build_load(
|
||||||
super::Pointer::new(
|
super::Pointer::new(
|
||||||
context.word_type(),
|
context.word_type(),
|
||||||
@@ -224,27 +216,20 @@ fn emit_store<'ctx>(
|
|||||||
Default::default(),
|
Default::default(),
|
||||||
value.into_pointer_value(),
|
value.into_pointer_value(),
|
||||||
),
|
),
|
||||||
"key",
|
"value",
|
||||||
)?;
|
)?;
|
||||||
if !transient {
|
if !transient {
|
||||||
key = context.build_byte_swap(key)?;
|
key = context.build_byte_swap(key)?;
|
||||||
value = context.build_byte_swap(value)?;
|
value = context.build_byte_swap(value)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let key_pointer = context.build_alloca_at_entry(context.word_type(), "key_pointer");
|
|
||||||
let value_pointer = context.build_alloca_at_entry(context.word_type(), "value_pointer");
|
|
||||||
|
|
||||||
context.build_store(key_pointer, key)?;
|
context.build_store(key_pointer, key)?;
|
||||||
context.build_store(value_pointer, value)?;
|
context.build_store(value_pointer, value)?;
|
||||||
|
|
||||||
let is_transient = context.xlen_type().const_int(transient as u64, false);
|
|
||||||
|
|
||||||
let arguments = [
|
let arguments = [
|
||||||
is_transient.into(),
|
is_transient.into(),
|
||||||
key_pointer.to_int(context).into(),
|
key_pointer.to_int(context).into(),
|
||||||
context.xlen_type().const_all_ones().into(),
|
|
||||||
value_pointer.to_int(context).into(),
|
value_pointer.to_int(context).into(),
|
||||||
context.integer_const(crate::polkavm::XLEN, 32).into(),
|
|
||||||
];
|
];
|
||||||
context.build_runtime_call(revive_runtime_api::polkavm_imports::SET_STORAGE, &arguments);
|
context.build_runtime_call(revive_runtime_api::polkavm_imports::SET_STORAGE, &arguments);
|
||||||
|
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ pub fn call<'ctx>(
|
|||||||
let is_success = context.builder().build_int_compare(
|
let is_success = context.builder().build_int_compare(
|
||||||
inkwell::IntPredicate::EQ,
|
inkwell::IntPredicate::EQ,
|
||||||
success,
|
success,
|
||||||
context.integer_const(revive_common::BIT_LENGTH_X64, 0),
|
context.integer_const(revive_common::BIT_LENGTH_X32, 0),
|
||||||
"is_success",
|
"is_success",
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
@@ -178,7 +178,7 @@ pub fn delegate_call<'ctx>(
|
|||||||
let is_success = context.builder().build_int_compare(
|
let is_success = context.builder().build_int_compare(
|
||||||
inkwell::IntPredicate::EQ,
|
inkwell::IntPredicate::EQ,
|
||||||
success,
|
success,
|
||||||
context.integer_const(revive_common::BIT_LENGTH_X64, 0),
|
context.integer_const(revive_common::BIT_LENGTH_X32, 0),
|
||||||
"is_success",
|
"is_success",
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
|||||||
@@ -60,3 +60,16 @@ pub fn invalid(context: &mut Context) -> anyhow::Result<()> {
|
|||||||
context.build_call(context.intrinsics().trap, &[], "invalid_trap");
|
context.build_call(context.intrinsics().trap, &[], "invalid_trap");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Translates the `selfdestruct` instruction.
|
||||||
|
pub fn selfdestruct<'ctx>(
|
||||||
|
context: &mut Context<'ctx>,
|
||||||
|
address: inkwell::values::IntValue<'ctx>,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
let address_pointer = context.build_address_argument_store(address)?;
|
||||||
|
context.build_runtime_call(
|
||||||
|
revive_runtime_api::polkavm_imports::TERMINATE,
|
||||||
|
&[address_pointer.to_int(context).into()],
|
||||||
|
);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "resolc"
|
name = "resolc"
|
||||||
version = "0.4.1"
|
version = "0.5.0"
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
repository.workspace = true
|
repository.workspace = true
|
||||||
|
|||||||
@@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
use crate::tests::cli::utils::{
|
use crate::tests::cli::utils::{
|
||||||
self, assert_command_failure, assert_command_success, assert_equal_exit_codes, execute_resolc,
|
self, assert_command_failure, assert_command_success, assert_equal_exit_codes, execute_resolc,
|
||||||
execute_solc, RESOLC_YUL_FLAG, SOLIDITY_CONTRACT_PATH, YUL_MEMSET_CONTRACT_PATH,
|
execute_solc, RESOLC_YUL_FLAG, SOLIDITY_CONTRACT_PATH, SOLIDITY_LARGE_DIV_REM_CONTRACT_PATH,
|
||||||
|
YUL_MEMSET_CONTRACT_PATH,
|
||||||
};
|
};
|
||||||
|
|
||||||
const LEVELS: &[char] = &['0', '1', '2', '3', 's', 'z'];
|
const LEVELS: &[char] = &['0', '1', '2', '3', 's', 'z'];
|
||||||
@@ -56,3 +57,26 @@ fn disable_solc_optimzer() {
|
|||||||
|
|
||||||
assert_ne!(enabled.stdout, disabled.stdout);
|
assert_ne!(enabled.stdout, disabled.stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_large_div_rem_expansion() {
|
||||||
|
for level in LEVELS {
|
||||||
|
let optimization_argument = format!("-O{level}");
|
||||||
|
let arguments = &[SOLIDITY_LARGE_DIV_REM_CONTRACT_PATH, &optimization_argument];
|
||||||
|
let resolc_result = utils::execute_resolc(arguments);
|
||||||
|
assert!(
|
||||||
|
resolc_result.success,
|
||||||
|
"Providing the level `{optimization_argument}` should succeed with exit code {}, got {}.\nDetails: {}",
|
||||||
|
revive_common::EXIT_CODE_SUCCESS,
|
||||||
|
resolc_result.code,
|
||||||
|
resolc_result.stderr
|
||||||
|
);
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
resolc_result
|
||||||
|
.stderr
|
||||||
|
.contains("Compiler run successful. No output requested"),
|
||||||
|
"Expected the output to contain a success message when providing the level `{optimization_argument}`."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -22,6 +22,10 @@ pub const YUL_MEMSET_CONTRACT_PATH: &str = "src/tests/data/yul/memset.yul";
|
|||||||
pub const STANDARD_JSON_CONTRACTS_PATH: &str =
|
pub const STANDARD_JSON_CONTRACTS_PATH: &str =
|
||||||
"src/tests/data/standard_json/solidity_contracts.json";
|
"src/tests/data/standard_json/solidity_contracts.json";
|
||||||
|
|
||||||
|
/// The simple Solidity contract containing i256 divisions and remains that should be compiled
|
||||||
|
/// correctly
|
||||||
|
pub const SOLIDITY_LARGE_DIV_REM_CONTRACT_PATH: &str = "src/tests/data/solidity/large_div_rem.sol";
|
||||||
|
|
||||||
/// The `resolc` YUL mode flag.
|
/// The `resolc` YUL mode flag.
|
||||||
pub const RESOLC_YUL_FLAG: &str = "--yul";
|
pub const RESOLC_YUL_FLAG: &str = "--yul";
|
||||||
/// The `--yul` option was deprecated in Solidity 0.8.27 in favor of `--strict-assembly`.
|
/// The `--yul` option was deprecated in Solidity 0.8.27 in favor of `--strict-assembly`.
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
pragma solidity ^0.8;
|
||||||
|
|
||||||
|
contract LargeDivRem {
|
||||||
|
function rem_2(int n) public pure returns (int q) {
|
||||||
|
assembly {
|
||||||
|
q := smod(n, 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function div_2(int n) public pure returns (int q) {
|
||||||
|
assembly {
|
||||||
|
q := sdiv(n, 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function rem_7(int n) public pure returns (int q) {
|
||||||
|
assembly {
|
||||||
|
q := smod(n, 7)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function div_7(int n) public pure returns (int q) {
|
||||||
|
assembly {
|
||||||
|
q := sdiv(n, 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function rem_k(int n, int k) public pure returns (int q) {
|
||||||
|
assembly {
|
||||||
|
q := smod(n, k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function div_k(int n, int k) public pure returns (int q) {
|
||||||
|
assembly {
|
||||||
|
q := sdiv(n, k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -98,26 +98,3 @@ contract ExternalCodeCopy {
|
|||||||
|
|
||||||
build_solidity(sources(&[("test.sol", code)])).unwrap();
|
build_solidity(sources(&[("test.sol", code)])).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[should_panic(expected = "The `SELFDESTRUCT` instruction is not supported")]
|
|
||||||
fn selfdestruct_yul() {
|
|
||||||
let solidity = r#"
|
|
||||||
// SPDX-License-Identifier: MIT
|
|
||||||
pragma solidity ^0.8.0;
|
|
||||||
|
|
||||||
contract MinimalDestructible {
|
|
||||||
address payable public owner;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
owner = payable(msg.sender);
|
|
||||||
}
|
|
||||||
|
|
||||||
function destroy() public {
|
|
||||||
require(msg.sender == owner, "Only the owner can call this function.");
|
|
||||||
selfdestruct(owner);
|
|
||||||
}
|
|
||||||
}"#;
|
|
||||||
|
|
||||||
build_solidity(sources(&[("test.sol", solidity)])).unwrap();
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "revive-runner"
|
name = "revive-runner"
|
||||||
version = "0.2.0"
|
version = "0.3.0"
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
repository.workspace = true
|
repository.workspace = true
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ use std::time::Duration;
|
|||||||
|
|
||||||
use hex::{FromHex, ToHex};
|
use hex::{FromHex, ToHex};
|
||||||
use pallet_revive::{AddressMapper, ExecReturnValue, InstantiateReturnValue};
|
use pallet_revive::{AddressMapper, ExecReturnValue, InstantiateReturnValue};
|
||||||
|
use polkadot_sdk::frame_support::traits::Currency;
|
||||||
|
use polkadot_sdk::pallet_revive::{Config, Pallet};
|
||||||
use polkadot_sdk::*;
|
use polkadot_sdk::*;
|
||||||
use polkadot_sdk::{
|
use polkadot_sdk::{
|
||||||
pallet_revive::ContractResult,
|
pallet_revive::ContractResult,
|
||||||
@@ -58,6 +60,8 @@ pub const CHARLIE: H160 = H160([3u8; 20]);
|
|||||||
pub const GAS_LIMIT: Weight = Weight::from_parts(100_000_000_000_000, 3 * 1024 * 1024 * 1024);
|
pub const GAS_LIMIT: Weight = Weight::from_parts(100_000_000_000_000, 3 * 1024 * 1024 * 1024);
|
||||||
/// Default deposit limit
|
/// Default deposit limit
|
||||||
pub const DEPOSIT_LIMIT: Balance = 10_000_000;
|
pub const DEPOSIT_LIMIT: Balance = 10_000_000;
|
||||||
|
/// The native to ETH balance factor.
|
||||||
|
pub const ETH_RATIO: Balance = 1_000_000;
|
||||||
|
|
||||||
/// Externalities builder
|
/// Externalities builder
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
@@ -80,18 +84,28 @@ impl ExtBuilder {
|
|||||||
/// Build the externalities
|
/// Build the externalities
|
||||||
pub fn build(self) -> sp_io::TestExternalities {
|
pub fn build(self) -> sp_io::TestExternalities {
|
||||||
sp_tracing::try_init_simple();
|
sp_tracing::try_init_simple();
|
||||||
|
|
||||||
let mut t = frame_system::GenesisConfig::<Runtime>::default()
|
let mut t = frame_system::GenesisConfig::<Runtime>::default()
|
||||||
.build_storage()
|
.build_storage()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
pallet_balances::GenesisConfig::<Runtime> {
|
pallet_balances::GenesisConfig::<Runtime> {
|
||||||
balances: self.balance_genesis_config,
|
balances: self.balance_genesis_config,
|
||||||
dev_accounts: None,
|
dev_accounts: None,
|
||||||
}
|
}
|
||||||
.assimilate_storage(&mut t)
|
.assimilate_storage(&mut t)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let mut ext = sp_io::TestExternalities::new(t);
|
let mut ext = sp_io::TestExternalities::new(t);
|
||||||
ext.register_extension(KeystoreExt::new(MemoryKeystore::new()));
|
ext.register_extension(KeystoreExt::new(MemoryKeystore::new()));
|
||||||
ext.execute_with(|| System::set_block_number(1));
|
ext.execute_with(|| {
|
||||||
|
let _ = <Runtime as Config>::Currency::deposit_creating(
|
||||||
|
&Pallet::<Runtime>::account_id(),
|
||||||
|
<Runtime as Config>::Currency::minimum_balance(),
|
||||||
|
);
|
||||||
|
|
||||||
|
System::set_block_number(1);
|
||||||
|
});
|
||||||
|
|
||||||
ext
|
ext
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,19 +74,18 @@ parameter_types! {
|
|||||||
impl pallet_revive::Config for Runtime {
|
impl pallet_revive::Config for Runtime {
|
||||||
type Time = Timestamp;
|
type Time = Timestamp;
|
||||||
type Currency = Balances;
|
type Currency = Balances;
|
||||||
type CallFilter = ();
|
|
||||||
type ChainExtension = ();
|
|
||||||
type DepositPerByte = DepositPerByte;
|
type DepositPerByte = DepositPerByte;
|
||||||
type DepositPerItem = DepositPerItem;
|
type DepositPerItem = DepositPerItem;
|
||||||
type AddressMapper = AccountId32Mapper<Self>;
|
type AddressMapper = AccountId32Mapper<Self>;
|
||||||
type RuntimeMemory = ConstU32<{ 512 * 1024 * 1024 }>;
|
type RuntimeMemory = ConstU32<{ 512 * 1024 * 1024 }>;
|
||||||
type PVFMemory = ConstU32<{ 1024 * 1024 * 1024 }>;
|
type PVFMemory = ConstU32<{ 1024 * 1024 * 1024 }>;
|
||||||
type UnsafeUnstableInterface = UnstableInterface;
|
type UnsafeUnstableInterface = UnstableInterface;
|
||||||
type UploadOrigin = EnsureSigned<AccountId32>;
|
type UploadOrigin = EnsureSigned<Self::AccountId>;
|
||||||
type InstantiateOrigin = EnsureSigned<AccountId32>;
|
type InstantiateOrigin = EnsureSigned<Self::AccountId>;
|
||||||
type CodeHashLockupDepositPercent = CodeHashLockupDepositPercent;
|
type CodeHashLockupDepositPercent = CodeHashLockupDepositPercent;
|
||||||
type ChainId = ConstU64<420_420_420>;
|
type ChainId = ConstU64<420_420_420>;
|
||||||
type FindAuthor = Self;
|
type FindAuthor = Self;
|
||||||
|
type NativeToEthRatio = ConstU32<{ crate::ETH_RATIO as u32 }>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FindAuthor<<Runtime as frame_system::Config>::AccountId> for Runtime {
|
impl FindAuthor<<Runtime as frame_system::Config>::AccountId> for Runtime {
|
||||||
|
|||||||
+12
-11
@@ -1,5 +1,6 @@
|
|||||||
use std::{str::FromStr, time::Instant};
|
use std::{str::FromStr, time::Instant};
|
||||||
|
|
||||||
|
use polkadot_sdk::pallet_revive::Pallet;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::*;
|
use crate::*;
|
||||||
@@ -445,12 +446,13 @@ impl Specs {
|
|||||||
let time_start = Instant::now();
|
let time_start = Instant::now();
|
||||||
let result = Contracts::bare_instantiate(
|
let result = Contracts::bare_instantiate(
|
||||||
origin,
|
origin,
|
||||||
value,
|
value.into(),
|
||||||
gas_limit.unwrap_or(GAS_LIMIT),
|
gas_limit.unwrap_or(GAS_LIMIT),
|
||||||
storage_deposit_limit.unwrap_or(DEPOSIT_LIMIT).into(),
|
storage_deposit_limit.unwrap_or(DEPOSIT_LIMIT).into(),
|
||||||
code,
|
code,
|
||||||
data,
|
data,
|
||||||
salt.0,
|
salt.0,
|
||||||
|
pallet_revive::BumpNonce::No,
|
||||||
);
|
);
|
||||||
results.push(CallResult::Instantiate {
|
results.push(CallResult::Instantiate {
|
||||||
result,
|
result,
|
||||||
@@ -483,7 +485,7 @@ impl Specs {
|
|||||||
let result = Contracts::bare_call(
|
let result = Contracts::bare_call(
|
||||||
RuntimeOrigin::signed(origin.to_account_id(&results)),
|
RuntimeOrigin::signed(origin.to_account_id(&results)),
|
||||||
dest.to_eth_addr(&results),
|
dest.to_eth_addr(&results),
|
||||||
value,
|
value.into(),
|
||||||
gas_limit.unwrap_or(GAS_LIMIT),
|
gas_limit.unwrap_or(GAS_LIMIT),
|
||||||
storage_deposit_limit.unwrap_or(DEPOSIT_LIMIT).into(),
|
storage_deposit_limit.unwrap_or(DEPOSIT_LIMIT).into(),
|
||||||
data,
|
data,
|
||||||
@@ -497,8 +499,10 @@ impl Specs {
|
|||||||
expectation.verify(results.last().expect("No call to verify"));
|
expectation.verify(results.last().expect("No call to verify"));
|
||||||
}
|
}
|
||||||
VerifyBalance { origin, expected } => {
|
VerifyBalance { origin, expected } => {
|
||||||
let balance = Balances::usable_balance(origin.to_account_id(&results));
|
assert_eq!(
|
||||||
assert_eq!(balance, expected);
|
Pallet::<Runtime>::evm_balance(&origin.to_eth_addr(&results)),
|
||||||
|
expected.into()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
VerifyStorage {
|
VerifyStorage {
|
||||||
contract,
|
contract,
|
||||||
@@ -506,13 +510,10 @@ impl Specs {
|
|||||||
expected,
|
expected,
|
||||||
} => {
|
} => {
|
||||||
let address = contract.to_eth_addr(&results);
|
let address = contract.to_eth_addr(&results);
|
||||||
let Ok(value) = Contracts::get_storage(address, key) else {
|
let value = Contracts::get_storage(address, key)
|
||||||
panic!("error reading storage for address {address}");
|
.unwrap_or_else(|error| panic!("at {address}: {error:?}"))
|
||||||
};
|
.unwrap_or_else(|| vec![0; 32]);
|
||||||
let Some(value) = value else {
|
assert_eq!(value, expected, "at {address} key 0x{}", hex::encode(key));
|
||||||
panic!("no value at {address} key 0x{}", hex::encode(key));
|
|
||||||
};
|
|
||||||
assert_eq!(value, expected, "at key 0x{}", hex::encode(key));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "revive-runtime-api"
|
name = "revive-runtime-api"
|
||||||
version = "0.3.0"
|
version = "0.4.0"
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
repository.workspace = true
|
repository.workspace = true
|
||||||
|
|||||||
@@ -53,11 +53,11 @@ POLKAVM_IMPORT(void, block_hash, uint32_t, uint32_t)
|
|||||||
|
|
||||||
POLKAVM_IMPORT(void, block_number, uint32_t)
|
POLKAVM_IMPORT(void, block_number, uint32_t)
|
||||||
|
|
||||||
POLKAVM_IMPORT(uint64_t, call, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t)
|
POLKAVM_IMPORT(uint32_t, call, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t)
|
||||||
|
|
||||||
POLKAVM_IMPORT(uint64_t, call_data_copy, uint32_t, uint32_t, uint32_t)
|
POLKAVM_IMPORT(void, call_data_copy, uint32_t, uint32_t, uint32_t)
|
||||||
|
|
||||||
POLKAVM_IMPORT(uint64_t, call_data_load, uint32_t, uint32_t)
|
POLKAVM_IMPORT(void, call_data_load, uint32_t, uint32_t)
|
||||||
|
|
||||||
POLKAVM_IMPORT(uint64_t, call_data_size)
|
POLKAVM_IMPORT(uint64_t, call_data_size)
|
||||||
|
|
||||||
@@ -69,7 +69,7 @@ POLKAVM_IMPORT(uint64_t, code_size, uint32_t)
|
|||||||
|
|
||||||
POLKAVM_IMPORT(void, code_hash, uint32_t, uint32_t)
|
POLKAVM_IMPORT(void, code_hash, uint32_t, uint32_t)
|
||||||
|
|
||||||
POLKAVM_IMPORT(uint64_t, delegate_call, uint64_t, uint64_t, uint64_t, uint32_t, uint64_t, uint64_t)
|
POLKAVM_IMPORT(uint32_t, delegate_call, uint64_t, uint64_t, uint64_t, uint32_t, uint64_t, uint64_t)
|
||||||
|
|
||||||
POLKAVM_IMPORT(void, deposit_event, uint32_t, uint32_t, uint32_t, uint32_t)
|
POLKAVM_IMPORT(void, deposit_event, uint32_t, uint32_t, uint32_t, uint32_t)
|
||||||
|
|
||||||
@@ -79,11 +79,11 @@ POLKAVM_IMPORT(uint64_t, gas_price);
|
|||||||
|
|
||||||
POLKAVM_IMPORT(void, get_immutable_data, uint32_t, uint32_t);
|
POLKAVM_IMPORT(void, get_immutable_data, uint32_t, uint32_t);
|
||||||
|
|
||||||
POLKAVM_IMPORT(uint64_t, get_storage, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t)
|
POLKAVM_IMPORT(void, get_storage_or_zero, uint32_t, uint32_t, uint32_t)
|
||||||
|
|
||||||
POLKAVM_IMPORT(void, hash_keccak_256, uint32_t, uint32_t, uint32_t)
|
POLKAVM_IMPORT(void, hash_keccak_256, uint32_t, uint32_t, uint32_t)
|
||||||
|
|
||||||
POLKAVM_IMPORT(uint64_t, instantiate, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t)
|
POLKAVM_IMPORT(uint32_t, instantiate, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t)
|
||||||
|
|
||||||
POLKAVM_IMPORT(void, now, uint32_t)
|
POLKAVM_IMPORT(void, now, uint32_t)
|
||||||
|
|
||||||
@@ -99,8 +99,8 @@ POLKAVM_IMPORT(uint64_t, return_data_size)
|
|||||||
|
|
||||||
POLKAVM_IMPORT(void, set_immutable_data, uint32_t, uint32_t);
|
POLKAVM_IMPORT(void, set_immutable_data, uint32_t, uint32_t);
|
||||||
|
|
||||||
POLKAVM_IMPORT(uint64_t, set_storage, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t)
|
POLKAVM_IMPORT(uint32_t, set_storage_or_clear, uint32_t, uint32_t, uint32_t)
|
||||||
|
|
||||||
|
POLKAVM_IMPORT(void, terminate, uint32_t)
|
||||||
|
|
||||||
POLKAVM_IMPORT(void, value_transferred, uint32_t)
|
POLKAVM_IMPORT(void, value_transferred, uint32_t)
|
||||||
|
|
||||||
POLKAVM_IMPORT(void, weight_to_fee, uint64_t, uint64_t, uint32_t);
|
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ pub static GAS_PRICE: &str = "gas_price";
|
|||||||
|
|
||||||
pub static GET_IMMUTABLE_DATA: &str = "get_immutable_data";
|
pub static GET_IMMUTABLE_DATA: &str = "get_immutable_data";
|
||||||
|
|
||||||
pub static GET_STORAGE: &str = "get_storage";
|
pub static GET_STORAGE: &str = "get_storage_or_zero";
|
||||||
|
|
||||||
pub static HASH_KECCAK_256: &str = "hash_keccak_256";
|
pub static HASH_KECCAK_256: &str = "hash_keccak_256";
|
||||||
|
|
||||||
@@ -62,12 +62,12 @@ pub static RETURNDATASIZE: &str = "return_data_size";
|
|||||||
|
|
||||||
pub static SET_IMMUTABLE_DATA: &str = "set_immutable_data";
|
pub static SET_IMMUTABLE_DATA: &str = "set_immutable_data";
|
||||||
|
|
||||||
pub static SET_STORAGE: &str = "set_storage";
|
pub static SET_STORAGE: &str = "set_storage_or_clear";
|
||||||
|
|
||||||
|
pub static TERMINATE: &str = "terminate";
|
||||||
|
|
||||||
pub static VALUE_TRANSFERRED: &str = "value_transferred";
|
pub static VALUE_TRANSFERRED: &str = "value_transferred";
|
||||||
|
|
||||||
pub static WEIGHT_TO_FEE: &str = "weight_to_fee";
|
|
||||||
|
|
||||||
/// All imported runtime API symbols.
|
/// All imported runtime API symbols.
|
||||||
/// Useful for configuring common attributes and linkage.
|
/// Useful for configuring common attributes and linkage.
|
||||||
pub static IMPORTS: [&str; 33] = [
|
pub static IMPORTS: [&str; 33] = [
|
||||||
@@ -102,8 +102,8 @@ pub static IMPORTS: [&str; 33] = [
|
|||||||
RETURNDATASIZE,
|
RETURNDATASIZE,
|
||||||
SET_IMMUTABLE_DATA,
|
SET_IMMUTABLE_DATA,
|
||||||
SET_STORAGE,
|
SET_STORAGE,
|
||||||
|
TERMINATE,
|
||||||
VALUE_TRANSFERRED,
|
VALUE_TRANSFERRED,
|
||||||
WEIGHT_TO_FEE,
|
|
||||||
];
|
];
|
||||||
|
|
||||||
/// Creates a LLVM module from the [BITCODE].
|
/// Creates a LLVM module from the [BITCODE].
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "revive-yul"
|
name = "revive-yul"
|
||||||
description = "The revive YUL parser library."
|
description = "The revive YUL parser library."
|
||||||
version = "0.3.1"
|
version = "0.4.0"
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
|
|||||||
@@ -661,6 +661,14 @@ impl FunctionCall {
|
|||||||
Name::Invalid => {
|
Name::Invalid => {
|
||||||
revive_llvm_context::polkavm_evm_return::invalid(context).map(|_| None)
|
revive_llvm_context::polkavm_evm_return::invalid(context).map(|_| None)
|
||||||
}
|
}
|
||||||
|
Name::SelfDestruct => {
|
||||||
|
let arguments = self.pop_arguments_llvm::<1>(context)?;
|
||||||
|
revive_llvm_context::polkavm_evm_return::selfdestruct(
|
||||||
|
context,
|
||||||
|
arguments[0].into_int_value(),
|
||||||
|
)
|
||||||
|
.map(|_| None)
|
||||||
|
}
|
||||||
|
|
||||||
Name::Log0 => {
|
Name::Log0 => {
|
||||||
let arguments = self.pop_arguments_llvm::<2>(context)?;
|
let arguments = self.pop_arguments_llvm::<2>(context)?;
|
||||||
@@ -962,13 +970,6 @@ impl FunctionCall {
|
|||||||
location
|
location
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Name::SelfDestruct => {
|
|
||||||
let _arguments = self.pop_arguments_llvm::<1>(context)?;
|
|
||||||
anyhow::bail!(
|
|
||||||
"{} The `SELFDESTRUCT` instruction is not supported",
|
|
||||||
location
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@parity/resolc",
|
"name": "@parity/resolc",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"version": "0.4.1",
|
"version": "0.5.0",
|
||||||
"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",
|
||||||
|
|||||||
Generated
+6
-1
@@ -31,7 +31,7 @@
|
|||||||
},
|
},
|
||||||
"js/resolc": {
|
"js/resolc": {
|
||||||
"name": "@parity/resolc",
|
"name": "@parity/resolc",
|
||||||
"version": "0.4.1",
|
"version": "0.5.0",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/node": "^22.9.0",
|
"@types/node": "^22.9.0",
|
||||||
@@ -1585,6 +1585,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.32.1.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.32.1.tgz",
|
||||||
"integrity": "sha512-LKMrmwCPoLhM45Z00O1ulb6jwyVr2kr3XJp+G+tSEZcbauNnScewcQwtJqXDhXeYPDEjZ8C1SjXm015CirEmGg==",
|
"integrity": "sha512-LKMrmwCPoLhM45Z00O1ulb6jwyVr2kr3XJp+G+tSEZcbauNnScewcQwtJqXDhXeYPDEjZ8C1SjXm015CirEmGg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/scope-manager": "8.32.1",
|
"@typescript-eslint/scope-manager": "8.32.1",
|
||||||
"@typescript-eslint/types": "8.32.1",
|
"@typescript-eslint/types": "8.32.1",
|
||||||
@@ -1752,6 +1753,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz",
|
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz",
|
||||||
"integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==",
|
"integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"acorn": "bin/acorn"
|
"acorn": "bin/acorn"
|
||||||
},
|
},
|
||||||
@@ -2361,6 +2363,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.27.0.tgz",
|
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.27.0.tgz",
|
||||||
"integrity": "sha512-ixRawFQuMB9DZ7fjU3iGGganFDp3+45bPOdaRurcFHSXO1e/sYwUX/FtQZpLZJR6SjMoJH8hR2pPEAfDyCoU2Q==",
|
"integrity": "sha512-ixRawFQuMB9DZ7fjU3iGGganFDp3+45bPOdaRurcFHSXO1e/sYwUX/FtQZpLZJR6SjMoJH8hR2pPEAfDyCoU2Q==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/eslint-utils": "^4.2.0",
|
"@eslint-community/eslint-utils": "^4.2.0",
|
||||||
"@eslint-community/regexpp": "^4.12.1",
|
"@eslint-community/regexpp": "^4.12.1",
|
||||||
@@ -2519,6 +2522,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ethersproject/abi": "5.8.0",
|
"@ethersproject/abi": "5.8.0",
|
||||||
"@ethersproject/abstract-provider": "5.8.0",
|
"@ethersproject/abstract-provider": "5.8.0",
|
||||||
@@ -4393,6 +4397,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
|
||||||
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
|
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
|
"peer": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"tsc": "bin/tsc",
|
"tsc": "bin/tsc",
|
||||||
"tsserver": "bin/tsserver"
|
"tsserver": "bin/tsserver"
|
||||||
|
|||||||
Reference in New Issue
Block a user