From a3f1de48ee0bd8143d71b958b2309653bb5f8cdc Mon Sep 17 00:00:00 2001
From: GoNoGo <83670532+drgorillamd@users.noreply.github.com>
Date: Fri, 31 May 2024 16:54:34 +0200
Subject: [PATCH 1/4] feat: formal verification & fuzz campaign (#69)
Co-authored-by: Gas <86567384+gas1cent@users.noreply.github.com>
---
.github/workflows/coverage_check.yml | 72 ++++++
.github/workflows/{ci.yml => tests.yml} | 62 ++++++
.solhint.tests.json | 6 +-
README.md | 16 +-
package.json | 3 +
remappings.txt | 1 +
test/invariants/PROPERTIES.md | 4 +
test/invariants/fuzz/Greeter.t.sol | 37 ++++
test/invariants/symbolic/Greeter.t.sol | 58 +++++
test/unit/Greeter.t.sol | 116 +++++-----
test/unit/Greeter.tree | 25 +++
yarn.lock | 281 ++++++++++++------------
12 files changed, 472 insertions(+), 209 deletions(-)
create mode 100644 .github/workflows/coverage_check.yml
rename .github/workflows/{ci.yml => tests.yml} (58%)
create mode 100644 test/invariants/PROPERTIES.md
create mode 100644 test/invariants/fuzz/Greeter.t.sol
create mode 100644 test/invariants/symbolic/Greeter.t.sol
create mode 100644 test/unit/Greeter.tree
diff --git a/.github/workflows/coverage_check.yml b/.github/workflows/coverage_check.yml
new file mode 100644
index 00000000..b17316ca
--- /dev/null
+++ b/.github/workflows/coverage_check.yml
@@ -0,0 +1,72 @@
+name: Coverage check on main push
+
+on: [push]
+
+env:
+ COVERAGE_SENSITIVITY_PERCENT: 1
+
+jobs:
+ upload-coverage:
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Install Foundry
+ uses: foundry-rs/foundry-toolchain@v1
+ with:
+ version: nightly
+
+ - name: Use Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: 18.x
+ cache: 'yarn'
+
+ - name: Install dependencies
+ run: yarn --frozen-lockfile --network-concurrency 1
+
+ - name: Run coverage
+ shell: bash
+ run: forge coverage --report summary --report lcov
+
+ - name: Setup LCOV
+ uses: hrishikesh-kadam/setup-lcov@v1
+
+ - name: Filter directories
+ run: lcov --remove lcov.info 'test/*' 'script/*' --output-file lcovNew.info --rc lcov_branch_coverage=1 --rc derive_function_end_line=0 --ignore-errors unused
+
+ - name: Capture coverage output
+ id: new-coverage
+ uses: zgosalvez/github-actions-report-lcov@v4
+ with:
+ coverage-files: lcovNew.info
+
+ - name: Retrieve previous coverage
+ uses: actions/download-artifact@v2
+ with:
+ name: coverage.info
+ continue-on-error: true
+
+ - name: Check if a previous coverage exists
+ run: |
+ if [ ! -f coverage.info ]; then
+ echo "Artifact not found. Initializing at 0"
+ echo "0" >> coverage.info
+ fi
+
+ - name: Compare previous coverage
+ run: |
+ old=$(cat coverage.info)
+ new=$(( ${{ steps.new-coverage.outputs.total-coverage }} + ${{ env.COVERAGE_SENSITIVITY_PERCENT }} ))
+ if [ "$new" -lt "$old" ]; then
+ echo "Coverage decreased from $old to $new"
+ exit 1
+ fi
+ mv lcovNew.info coverage.info
+
+ - name: Upload the new coverage
+ uses: actions/upload-artifact@v2
+ with:
+ name: coverage.info
+ path: ./coverage.info
\ No newline at end of file
diff --git a/.github/workflows/ci.yml b/.github/workflows/tests.yml
similarity index 58%
rename from .github/workflows/ci.yml
rename to .github/workflows/tests.yml
index e7b79eeb..52de2d36 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/tests.yml
@@ -64,6 +64,68 @@ jobs:
- name: Run tests
run: yarn test:integration
+ echidna-tests:
+ name: Echidna Test
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v3
+ with:
+ submodules: recursive
+
+ - name: Install Foundry
+ uses: foundry-rs/foundry-toolchain@v1
+ with:
+ version: nightly
+
+ - name: Use Node.js
+ uses: actions/setup-node@v3
+ with:
+ node-version: 18.x
+ cache: 'yarn'
+
+ - name: Install dependencies
+ run: yarn --frozen-lockfile --network-concurrency 1
+
+ - name: Compile contracts
+ run: |
+ forge build --build-info
+
+ - name: Run Echidna
+ uses: crytic/echidna-action@v2
+ with:
+ files: .
+ contract: InvariantGreeter
+ test-mode: assertion
+ crytic-args: --ignore-compile
+
+ halmos-tests:
+ name: Run symbolic execution tests
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v3
+
+ - name: Install Foundry
+ uses: foundry-rs/foundry-toolchain@v1
+ with:
+ version: nightly
+
+ - name: Use Node.js
+ uses: actions/setup-node@v3
+ with:
+ node-version: 18.x
+ cache: 'yarn'
+
+ - name: Install dependencies
+ run: yarn --frozen-lockfile --network-concurrency 1
+
+ - name: Precompile with via-ir=false
+ run: yarn build
+
+ - name: Run tests
+ run: yarn test:integration
+
lint:
name: Lint Commit Messages
runs-on: ubuntu-latest
diff --git a/.solhint.tests.json b/.solhint.tests.json
index e208b5f4..fb26b4ea 100644
--- a/.solhint.tests.json
+++ b/.solhint.tests.json
@@ -6,17 +6,17 @@
"quotes": ["error", "single"],
"func-visibility": ["warn", { "ignoreConstructors": true }],
"not-rely-on-time": "off",
- "func-name-mixedcase": "off",
+ "style-guide-casing": "off",
"var-name-mixedcase": "off",
"const-name-snakecase": "off",
"no-inline-assembly": "off",
- "no-empty-blocks": "off",
+ "no-empty-blocks": "error",
"definition-name-capwords": "off",
"named-parameters-function": "off",
"no-global-import": "off",
"max-states-count": "off",
"private-vars-leading-underscore": ["warn", { "strict": false }],
- "ordering": "warn",
+ "ordering": "off",
"immutable-name-snakecase": "warn",
"avoid-low-level-calls": "off",
"one-contract-per-file": "off",
diff --git a/README.md b/README.md
index 6c0f8467..7f350720 100644
--- a/README.md
+++ b/README.md
@@ -18,8 +18,10 @@
Deployment scripts
Sample scripts to deploy contracts on both mainnet and testnet.
- Sample Integration & Unit tests
+ Sample Integration, Unit, Property-based fuzzed and symbolic tests
Example tests showcasing mocking, assertions and configuration for mainnet forking. As well it includes everything needed in order to check code coverage.
+ Unit tests are built based on the Branched-Tree Technique, using Bulloak.
+ Formal verification and property-based fuzzing are achieved with Halmos and Echidna (resp.).
Linter
Simple and fast solidity linting thanks to forge fmt.
@@ -78,6 +80,18 @@ In order to just run integration tests, run:
yarn test:integration
```
+In order to just run the echidna fuzzing campaign (requires [Echidna](https://github.com/crytic/building-secure-contracts/blob/master/program-analysis/echidna/introduction/installation.md) installed), run:
+
+```bash
+yarn test:fuzz
+```
+
+In order to just run the symbolic execution tests (requires [Halmos](https://github.com/a16z/halmos/blob/main/README.md#installation) installed), run:
+
+```bash
+yarn test:symbolic
+```
+
In order to check your current code coverage, run:
```bash
diff --git a/package.json b/package.json
index a1866656..0c743777 100644
--- a/package.json
+++ b/package.json
@@ -22,7 +22,9 @@
"lint:sol-tests": "solhint -c .solhint.tests.json 'test/**/*.sol'",
"prepare": "husky install",
"test": "forge test -vvv",
+ "test:fuzz": "echidna test/invariants/fuzz/Greeter.t.sol --contract GreeterInvariant --corpus-dir test/invariants/fuzz/echidna_coverage/ --test-mode assertion",
"test:integration": "forge test --match-contract Integration -vvv",
+ "test:symbolic": "halmos",
"test:unit": "forge test --match-contract Unit -vvv",
"test:unit:deep": "FOUNDRY_FUZZ_RUNS=5000 yarn test:unit"
},
@@ -37,6 +39,7 @@
"@commitlint/config-conventional": "19.2.2",
"@defi-wonderland/natspec-smells": "1.1.1",
"forge-std": "github:foundry-rs/forge-std#1.8.2",
+ "halmos-cheatcodes": "github:a16z/halmos-cheatcodes#c0d8655",
"husky": ">=8",
"lint-staged": ">=10",
"solhint-community": "4.0.0",
diff --git a/remappings.txt b/remappings.txt
index 4a7cbdf9..0ba2eecd 100644
--- a/remappings.txt
+++ b/remappings.txt
@@ -1,4 +1,5 @@
forge-std/=node_modules/forge-std/src
+halmos-cheatcodes=node_modules/halmos-cheatcodes
contracts/=src/contracts
interfaces/=src/interfaces
diff --git a/test/invariants/PROPERTIES.md b/test/invariants/PROPERTIES.md
new file mode 100644
index 00000000..e48439c9
--- /dev/null
+++ b/test/invariants/PROPERTIES.md
@@ -0,0 +1,4 @@
+| Properties | Type |
+|---------------------------------------------------|------------|
+| Greeting should never be empty | Valid state |
+| Only the owner can set the greeting | State transition |
\ No newline at end of file
diff --git a/test/invariants/fuzz/Greeter.t.sol b/test/invariants/fuzz/Greeter.t.sol
new file mode 100644
index 00000000..96e2b1eb
--- /dev/null
+++ b/test/invariants/fuzz/Greeter.t.sol
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: UNLICENSED
+pragma solidity 0.8.23;
+
+import {Greeter, IERC20} from 'contracts/Greeter.sol';
+
+interface IHevm {
+ function prank(address) external;
+}
+
+contract InvariantGreeter {
+ IHevm internal _hevm = IHevm(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);
+
+ Greeter internal _targetContract;
+
+ constructor() {
+ _targetContract = new Greeter('a', IERC20(address(1)));
+ }
+
+ function checkGreeterNeverEmpty(string memory _newGreeting) public {
+ // Execution
+ (bool _success,) = address(_targetContract).call(abi.encodeCall(Greeter.setGreeting, _newGreeting));
+
+ // Check output condition
+ assert((_success && keccak256(bytes(_targetContract.greeting())) != keccak256(bytes(''))) || !_success);
+ }
+
+ function checkOnlyOwnerSetsGreeting(address _caller) public {
+ // Input conditions
+ _hevm.prank(_caller);
+
+ // Execution
+ (bool _success,) = address(this).call(abi.encodeCall(Greeter.setGreeting, 'hello'));
+
+ // Check output condition
+ assert((_success && msg.sender == _targetContract.OWNER()) || (!_success && msg.sender != _targetContract.OWNER()));
+ }
+}
diff --git a/test/invariants/symbolic/Greeter.t.sol b/test/invariants/symbolic/Greeter.t.sol
new file mode 100644
index 00000000..16a7edd0
--- /dev/null
+++ b/test/invariants/symbolic/Greeter.t.sol
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: UNLICENSED
+pragma solidity 0.8.23;
+
+import {Greeter, IERC20} from 'contracts/Greeter.sol';
+
+import {Test} from 'forge-std/Test.sol';
+import {SymTest} from 'halmos-cheatcodes/src/SymTest.sol'; // See https://github.com/a16z/halmos-cheatcodes?tab=readme-ov-file
+
+contract SymbolicGreeter is SymTest, Test {
+ Greeter public targetContract;
+
+ function setUp() public {
+ string memory _initialGreeting = svm.createString(64, 'initial greeting');
+ address _token = svm.createAddress('token');
+
+ targetContract = new Greeter(_initialGreeting, IERC20(_token));
+ }
+
+ function check_validState_greeterNeverEmpty(address _caller) public {
+ // Input conditions: any caller
+ vm.prank(_caller);
+
+ // Execution: Halmos cannot use a dynamic-sized array, iterate over multiple string lengths
+ bool _success;
+ for (uint256 i = 1; i < 3; i++) {
+ string memory greeting = svm.createString(i, 'greeting');
+ (_success,) = address(targetContract).call(abi.encodeCall(Greeter.setGreeting, (greeting)));
+
+ // Output condition check
+ vm.assume(_success); // discard failing calls
+ assert(keccak256(bytes(targetContract.greeting())) != keccak256(bytes('')));
+ }
+
+ // Add the empty string (bypass the non-empty check of svm.createString)
+ (_success,) = address(targetContract).call(abi.encodeCall(Greeter.setGreeting, ('')));
+
+ // Output condition check
+ vm.assume(_success); // discard failing calls
+ assert(keccak256(bytes(targetContract.greeting())) != keccak256(bytes('')));
+ }
+
+ function check_setGreeting_onlyOwnerSetsGreeting(address _caller) public {
+ // Input conditions
+ string memory _newGreeting = svm.createString(64, 'new greeting');
+
+ // Execution
+ vm.prank(_caller);
+ (bool _success,) = address(targetContract).call(abi.encodeCall(Greeter.setGreeting, (_newGreeting)));
+
+ // Output condition check
+ if (_success) {
+ assert(_caller == targetContract.OWNER());
+ assert(keccak256(bytes(targetContract.greeting())) == keccak256(bytes(_newGreeting)));
+ } else {
+ assert(_caller != targetContract.OWNER() || keccak256(bytes(_newGreeting)) == keccak256(bytes('')));
+ }
+ }
+}
diff --git a/test/unit/Greeter.t.sol b/test/unit/Greeter.t.sol
index 65efebb4..82f59c91 100644
--- a/test/unit/Greeter.t.sol
+++ b/test/unit/Greeter.t.sol
@@ -1,101 +1,99 @@
-// SPDX-License-Identifier: MIT
+// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.23;
import {Greeter, IGreeter} from 'contracts/Greeter.sol';
import {Test} from 'forge-std/Test.sol';
import {IERC20} from 'forge-std/interfaces/IERC20.sol';
-abstract contract Base is Test {
+contract UnitGreeter is Test {
address internal _owner = makeAddr('owner');
-
IERC20 internal _token = IERC20(makeAddr('token'));
+ uint256 internal _initialBalance = 100;
string internal _initialGreeting = 'hola';
- bytes32 internal _emptyString = keccak256(bytes(''));
+
Greeter internal _greeter;
- function setUp() public virtual {
- vm.etch(address(_token), new bytes(0x1)); // etch bytecode to avoid address collision problems
+ event GreetingSet(string _greeting);
+
+ function setUp() external {
vm.prank(_owner);
_greeter = new Greeter(_initialGreeting, _token);
+
+ vm.etch(address(_token), new bytes(0x1));
}
-}
-contract UnitGreeterConstructor is Base {
- function test_OwnerSet(address _owner) public {
+ function test_EmptyTestExample() external {
+ // it does nothing
+ vm.skip(true);
+ }
+
+ function test_ConstructorWhenPassingValidGreetingString() external {
vm.prank(_owner);
+
+ // it deploys
_greeter = new Greeter(_initialGreeting, _token);
- assertEq(_greeter.OWNER(), _owner);
- }
+ // it sets the greeting string
+ assertEq(_greeter.greeting(), _initialGreeting);
- function test_TokenSet(IERC20 _token) public {
- _greeter = new Greeter(_initialGreeting, _token);
+ // it sets the owner as sender
+ assertEq(_greeter.OWNER(), _owner);
+ // it sets the token used
assertEq(address(_greeter.token()), address(_token));
}
- function test_GreetingSet(string memory _greeting) public {
- vm.assume(keccak256(bytes(_greeting)) != _emptyString);
+ function test_ConstructorWhenPassingAnEmptyGreetingString() external {
+ vm.prank(_owner);
- _greeter = new Greeter(_greeting, _token);
- assertEq(_greeting, _greeter.greeting());
+ // it reverts
+ vm.expectRevert(IGreeter.Greeter_InvalidGreeting.selector);
+ _greeter = new Greeter('', _token);
}
-}
-contract UnitGreeterSetGreeting is Base {
- event GreetingSet(string _greeting);
+ function test_GreetWhenCalled() external {
+ vm.mockCall(address(_token), abi.encodeWithSelector(IERC20.balanceOf.selector), abi.encode(_initialBalance));
+ vm.expectCall(address(_token), abi.encodeWithSelector(IERC20.balanceOf.selector));
+ (string memory _greet, uint256 _balance) = _greeter.greet();
- function setUp() public override {
- super.setUp();
- vm.startPrank(_owner);
- }
-
- function test_RevertIfNotOwner(address _caller, string memory _greeting) public {
- vm.assume(keccak256(bytes(_greeting)) != _emptyString);
- vm.assume(_caller != _owner);
+ // it returns the greeting string
+ assertEq(_greet, _initialGreeting);
- vm.stopPrank();
- vm.prank(_caller);
-
- vm.expectRevert(IGreeter.Greeter_OnlyOwner.selector);
- _greeter.setGreeting(_greeting);
- }
-
- function test_RevertIfEmptyGreeting() public {
- vm.expectRevert(IGreeter.Greeter_InvalidGreeting.selector);
- _greeter.setGreeting('');
+ // it returns the token balance of the contract
+ assertEq(_balance, _initialBalance);
}
- function test_SetGreeting(string memory _greeting) public {
- vm.assume(keccak256(bytes(_greeting)) != _emptyString);
- _greeter.setGreeting(_greeting);
-
- assertEq(_greeting, _greeter.greeting());
+ modifier whenCalledByTheOwner() {
+ vm.startPrank(_owner);
+ _;
+ vm.stopPrank();
}
- function test_EmitEvent(string memory _greeting) public {
- vm.assume(keccak256(bytes(_greeting)) != _emptyString);
+ function test_SetGreetingWhenPassingAValidGreetingString() external whenCalledByTheOwner {
+ string memory _newGreeting = 'hello';
+ // it emit GreetingSet
vm.expectEmit(true, true, true, true, address(_greeter));
- emit GreetingSet(_greeting);
+ emit GreetingSet(_newGreeting);
- _greeter.setGreeting(_greeting);
- }
-}
+ _greeter.setGreeting(_newGreeting);
-contract UnitGreeterGreet is Base {
- function test_GetGreeting() public {
- vm.mockCall(address(_token), abi.encodeWithSelector(IERC20.balanceOf.selector), abi.encode(0));
-
- (string memory _greeting,) = _greeter.greet();
- assertEq(_initialGreeting, _greeting);
+ // it sets the greeting string
+ assertEq(_greeter.greeting(), _newGreeting);
}
- function test_GetTokenBalance(address _caller, uint256 _balance) public {
- vm.mockCall(address(_token), abi.encodeWithSelector(IERC20.balanceOf.selector, _caller), abi.encode(_balance));
+ function test_SetGreetingWhenPassingAnEmptyGreetingString() external whenCalledByTheOwner {
+ // it reverts
+ vm.expectRevert(IGreeter.Greeter_InvalidGreeting.selector);
+ _greeter.setGreeting('');
+ }
+ function test_SetGreetingWhenCalledByANon_owner(address _caller) external {
+ vm.assume(_caller != _owner);
vm.prank(_caller);
- (, uint256 _greetBalance) = _greeter.greet();
- assertEq(_balance, _greetBalance);
+
+ // it reverts
+ vm.expectRevert(IGreeter.Greeter_OnlyOwner.selector);
+ _greeter.setGreeting('new greeting');
}
}
diff --git a/test/unit/Greeter.tree b/test/unit/Greeter.tree
new file mode 100644
index 00000000..bbc74ea5
--- /dev/null
+++ b/test/unit/Greeter.tree
@@ -0,0 +1,25 @@
+Greeter::constructor
+├── when passing valid greeting string
+│ ├── it deploys
+│ ├── it sets the greeting string
+│ ├── it sets the owner as sender
+│ └── it sets the token used
+└── when passing an empty greeting string
+ └── it reverts
+
+
+Greeter::greet
+└── when called
+ ├── it returns the greeting string
+ └── it returns the token balance of the contract
+
+
+Greeter::setGreeting
+├── when called by the owner
+│ ├── when passing a valid greeting string
+│ │ ├── it sets the greeting string
+│ │ └── it emit GreetingSet
+│ └── when passing an empty greeting string
+│ └── it reverts
+└── when called by a non-owner
+ └── it reverts
\ No newline at end of file
diff --git a/yarn.lock b/yarn.lock
index 490e8a4d..7cdad647 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3,26 +3,27 @@
"@babel/code-frame@^7.0.0":
- version "7.23.4"
- resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.23.4.tgz#03ae5af150be94392cb5c7ccd97db5a19a5da6aa"
- integrity sha512-r1IONyb6Ia+jYR2vvIDhdWdlTGhqbBoFqLTQidzZ4kepUFH15ejXvFHxCVbtl7BOXIudsIubf4E81xeA3h3IXA==
+ version "7.24.2"
+ resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.2.tgz#718b4b19841809a58b29b68cde80bc5e1aa6d9ae"
+ integrity sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==
dependencies:
- "@babel/highlight" "^7.23.4"
- chalk "^2.4.2"
+ "@babel/highlight" "^7.24.2"
+ picocolors "^1.0.0"
-"@babel/helper-validator-identifier@^7.22.20":
- version "7.22.20"
- resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0"
- integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==
+"@babel/helper-validator-identifier@^7.24.5":
+ version "7.24.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.5.tgz#918b1a7fa23056603506370089bd990d8720db62"
+ integrity sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA==
-"@babel/highlight@^7.23.4":
- version "7.23.4"
- resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.23.4.tgz#edaadf4d8232e1a961432db785091207ead0621b"
- integrity sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==
+"@babel/highlight@^7.24.2":
+ version "7.24.5"
+ resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.5.tgz#bc0613f98e1dd0720e99b2a9ee3760194a704b6e"
+ integrity sha512-8lLmua6AVh/8SLJRRVD6V8p73Hir9w5mJrhE+IPpILG31KKlI9iz5zmBYKcWPS59qSfgP9RaSBQSHHE81WKuEw==
dependencies:
- "@babel/helper-validator-identifier" "^7.22.20"
+ "@babel/helper-validator-identifier" "^7.24.5"
chalk "^2.4.2"
js-tokens "^4.0.0"
+ picocolors "^1.0.0"
"@commitlint/cli@19.3.0":
version "19.3.0"
@@ -259,9 +260,9 @@
"@types/node" "*"
"@types/node@*":
- version "20.9.4"
- resolved "https://registry.yarnpkg.com/@types/node/-/node-20.9.4.tgz#cc8f970e869c26834bdb7ed480b30ede622d74c7"
- integrity sha512-wmyg8HUhcn6ACjsn8oKYjkN/zUzQeNtMy44weTJSM6p4MMzEOuKbA3OjJ267uPCOW7Xex9dyrNTful8XTQYoDA==
+ version "20.12.12"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-20.12.12.tgz#7cbecdf902085cec634fdb362172dfe12b8f2050"
+ integrity sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==
dependencies:
undici-types "~5.26.4"
@@ -288,17 +289,7 @@ ajv@^6.12.6:
json-schema-traverse "^0.4.1"
uri-js "^4.2.2"
-ajv@^8.0.1:
- version "8.12.0"
- resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1"
- integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==
- dependencies:
- fast-deep-equal "^3.1.1"
- json-schema-traverse "^1.0.0"
- require-from-string "^2.0.2"
- uri-js "^4.2.2"
-
-ajv@^8.11.0:
+ajv@^8.0.1, ajv@^8.11.0:
version "8.13.0"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.13.0.tgz#a3939eaec9fb80d217ddf0c3376948c023f28c91"
integrity sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA==
@@ -308,12 +299,10 @@ ajv@^8.11.0:
require-from-string "^2.0.2"
uri-js "^4.4.1"
-ansi-escapes@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-5.0.0.tgz#b6a0caf0eef0c41af190e9a749e0c00ec04bb2a6"
- integrity sha512-5GFMVX8HqE/TB+FuBJGuO5XG0WrsA6ptUqoODaT/n9mmUaZFkqnBueB4leqGBCmrUHnCnC4PCZTCd0E7QQ83bA==
- dependencies:
- type-fest "^1.0.2"
+ansi-escapes@^6.2.0:
+ version "6.2.1"
+ resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-6.2.1.tgz#76c54ce9b081dad39acec4b5d53377913825fb0f"
+ integrity sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==
ansi-regex@^5.0.1:
version "5.0.1"
@@ -339,7 +328,7 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0:
dependencies:
color-convert "^2.0.1"
-ansi-styles@^6.0.0, ansi-styles@^6.1.0:
+ansi-styles@^6.0.0, ansi-styles@^6.2.1:
version "6.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5"
integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==
@@ -387,9 +376,9 @@ available-typed-arrays@^1.0.7:
possible-typed-array-names "^1.0.0"
axios@^1.6.7:
- version "1.6.8"
- resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.8.tgz#66d294951f5d988a00e87a0ffb955316a619ea66"
- integrity sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==
+ version "1.7.1"
+ resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.1.tgz#522145622a09dfaf49359837db9649ff245a35b9"
+ integrity sha512-+LV37nQcd1EpFalkXksWNBiA17NZ5m5/WspmHGmZmdx1qBOg/VNq/c4eRJiA9VQQHBOs+N0ZhhdU10h2TyNK7Q==
dependencies:
follow-redirects "^1.15.6"
form-data "^4.0.0"
@@ -459,13 +448,13 @@ cli-cursor@^4.0.0:
dependencies:
restore-cursor "^4.0.0"
-cli-truncate@^3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-3.1.0.tgz#3f23ab12535e3d73e839bb43e73c9de487db1389"
- integrity sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==
+cli-truncate@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-4.0.0.tgz#6cc28a2924fee9e25ce91e973db56c7066e6172a"
+ integrity sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==
dependencies:
slice-ansi "^5.0.0"
- string-width "^5.0.0"
+ string-width "^7.0.0"
cliui@^8.0.1:
version "8.0.1"
@@ -523,9 +512,9 @@ commander@11.1.0, commander@^11.1.0:
integrity sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==
commander@^12.0.0:
- version "12.0.0"
- resolved "https://registry.yarnpkg.com/commander/-/commander-12.0.0.tgz#b929db6df8546080adfd004ab215ed48cf6f2592"
- integrity sha512-MwVNWlYjDTtOjX5PiD7o5pK0UrFU/OYgcJfjjK4RaHZETNtjJqrZa9Y9ds88+A+f+d5lv+561eZ+yCKoS3gbAA==
+ version "12.1.0"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-12.1.0.tgz#01423b36f501259fdaac4d0e4d60c96c991585d3"
+ integrity sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==
commander@^8.1.0:
version "8.3.0"
@@ -660,21 +649,16 @@ dot-prop@^5.1.0:
dependencies:
is-obj "^2.0.0"
-eastasianwidth@^0.2.0:
- version "0.2.0"
- resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb"
- integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==
+emoji-regex@^10.3.0:
+ version "10.3.0"
+ resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-10.3.0.tgz#76998b9268409eb3dae3de989254d456e70cfe23"
+ integrity sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==
emoji-regex@^8.0.0:
version "8.0.0"
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
-emoji-regex@^9.2.2:
- version "9.2.2"
- resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72"
- integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==
-
env-paths@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2"
@@ -773,9 +757,9 @@ fast-json-stable-stringify@^2.0.0:
integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
fastq@^1.6.0:
- version "1.15.0"
- resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a"
- integrity sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==
+ version "1.17.1"
+ resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47"
+ integrity sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==
dependencies:
reusify "^1.0.4"
@@ -805,12 +789,7 @@ findup-sync@^5.0.0:
micromatch "^4.0.4"
resolve-dir "^1.0.1"
-follow-redirects@^1.12.1:
- version "1.15.5"
- resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.5.tgz#54d4d6d062c0fa7d9d17feb008461550e3ba8020"
- integrity sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==
-
-follow-redirects@^1.15.6:
+follow-redirects@^1.12.1, follow-redirects@^1.15.6:
version "1.15.6"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b"
integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==
@@ -859,6 +838,11 @@ get-caller-file@^2.0.5:
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
+get-east-asian-width@^1.0.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz#5e6ebd9baee6fb8b7b6bd505221065f0cd91f64e"
+ integrity sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==
+
get-intrinsic@^1.1.3, get-intrinsic@^1.2.4:
version "1.2.4"
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd"
@@ -962,6 +946,10 @@ graceful-fs@^4.1.6, graceful-fs@^4.2.0:
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
+"halmos-cheatcodes@github:a16z/halmos-cheatcodes#c0d8655":
+ version "0.0.0"
+ resolved "https://codeload.github.com/a16z/halmos-cheatcodes/tar.gz/c0d865508c0fee0a11b97732c5e90f9cad6b65a5"
+
has-flag@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
@@ -1016,14 +1004,14 @@ human-signals@^5.0.0:
integrity sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==
husky@>=8:
- version "8.0.3"
- resolved "https://registry.yarnpkg.com/husky/-/husky-8.0.3.tgz#4936d7212e46d1dea28fef29bb3a108872cd9184"
- integrity sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==
+ version "9.0.11"
+ resolved "https://registry.yarnpkg.com/husky/-/husky-9.0.11.tgz#fc91df4c756050de41b3e478b2158b87c1e79af9"
+ integrity sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw==
ignore@^5.2.4:
- version "5.3.0"
- resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.0.tgz#67418ae40d34d6999c95ff56016759c718c82f78"
- integrity sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==
+ version "5.3.1"
+ resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef"
+ integrity sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==
import-fresh@^3.3.0:
version "3.3.0"
@@ -1034,9 +1022,9 @@ import-fresh@^3.3.0:
resolve-from "^4.0.0"
import-meta-resolve@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/import-meta-resolve/-/import-meta-resolve-4.0.0.tgz#0b1195915689f60ab00f830af0f15cc841e8919e"
- integrity sha512-okYUR7ZQPH+efeuMJGlq4f8ubUgO50kByRPyt/Cy1Io4PSRsPjxME+YlVaCOx+NIToW7hCsZNFJyTPFFKepRSA==
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz#f9db8bead9fafa61adb811db77a2bf22c5399706"
+ integrity sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==
inflight@^1.0.4:
version "1.0.6"
@@ -1094,6 +1082,13 @@ is-fullwidth-code-point@^4.0.0:
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz#fae3167c729e7463f8461ce512b080a49268aa88"
integrity sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==
+is-fullwidth-code-point@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz#9609efced7c2f97da7b60145ef481c787c7ba704"
+ integrity sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==
+ dependencies:
+ get-east-asian-width "^1.0.0"
+
is-generator-function@^1.0.7:
version "1.0.10"
resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72"
@@ -1208,10 +1203,10 @@ jsonparse@^1.2.0:
resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280"
integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==
-lilconfig@2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52"
- integrity sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==
+lilconfig@3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-3.0.0.tgz#f8067feb033b5b74dab4602a5f5029420be749bc"
+ integrity sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==
lines-and-columns@^1.1.6:
version "1.2.4"
@@ -1219,32 +1214,32 @@ lines-and-columns@^1.1.6:
integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==
lint-staged@>=10:
- version "15.1.0"
- resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-15.1.0.tgz#c0f8e4d96ac3c09beac5c76d08524d6000c207b4"
- integrity sha512-ZPKXWHVlL7uwVpy8OZ7YQjYDAuO5X4kMh0XgZvPNxLcCCngd0PO5jKQyy3+s4TL2EnHoIXIzP1422f/l3nZKMw==
+ version "15.2.2"
+ resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-15.2.2.tgz#ad7cbb5b3ab70e043fa05bff82a09ed286bc4c5f"
+ integrity sha512-TiTt93OPh1OZOsb5B7k96A/ATl2AjIZo+vnzFZ6oHK5FuTk63ByDtxGQpHm+kFETjEWqgkF95M8FRXKR/LEBcw==
dependencies:
chalk "5.3.0"
commander "11.1.0"
debug "4.3.4"
execa "8.0.1"
- lilconfig "2.1.0"
- listr2 "7.0.2"
+ lilconfig "3.0.0"
+ listr2 "8.0.1"
micromatch "4.0.5"
pidtree "0.6.0"
string-argv "0.3.2"
yaml "2.3.4"
-listr2@7.0.2:
- version "7.0.2"
- resolved "https://registry.yarnpkg.com/listr2/-/listr2-7.0.2.tgz#3aa3e1549dfaf3c57ab5eeaba754da3b87f33063"
- integrity sha512-rJysbR9GKIalhTbVL2tYbF2hVyDnrf7pFUZBwjPaMIdadYHmeT+EVi/Bu3qd7ETQPahTotg2WRCatXwRBW554g==
+listr2@8.0.1:
+ version "8.0.1"
+ resolved "https://registry.yarnpkg.com/listr2/-/listr2-8.0.1.tgz#4d3f50ae6cec3c62bdf0e94f5c2c9edebd4b9c34"
+ integrity sha512-ovJXBXkKGfq+CwmKTjluEqFi3p4h8xvkxGQQAQan22YCgef4KZ1mKGjzfGh6PL6AW5Csw0QiQPNuQyH+6Xk3hA==
dependencies:
- cli-truncate "^3.1.0"
+ cli-truncate "^4.0.0"
colorette "^2.0.20"
eventemitter3 "^5.0.1"
- log-update "^5.0.1"
+ log-update "^6.0.0"
rfdc "^1.3.0"
- wrap-ansi "^8.1.0"
+ wrap-ansi "^9.0.0"
locate-path@^7.2.0:
version "7.2.0"
@@ -1308,23 +1303,16 @@ lodash@^4.17.21:
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
-log-update@^5.0.1:
- version "5.0.1"
- resolved "https://registry.yarnpkg.com/log-update/-/log-update-5.0.1.tgz#9e928bf70cb183c1f0c9e91d9e6b7115d597ce09"
- integrity sha512-5UtUDQ/6edw4ofyljDNcOVJQ4c7OjDro4h3y8e1GQL5iYElYclVHJ3zeWchylvMaKnDbDilC8irOVyexnA/Slw==
- dependencies:
- ansi-escapes "^5.0.0"
- cli-cursor "^4.0.0"
- slice-ansi "^5.0.0"
- strip-ansi "^7.0.1"
- wrap-ansi "^8.0.1"
-
-lru-cache@^6.0.0:
+log-update@^6.0.0:
version "6.0.0"
- resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
- integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==
+ resolved "https://registry.yarnpkg.com/log-update/-/log-update-6.0.0.tgz#0ddeb7ac6ad658c944c1de902993fce7c33f5e59"
+ integrity sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==
dependencies:
- yallist "^4.0.0"
+ ansi-escapes "^6.2.0"
+ cli-cursor "^4.0.0"
+ slice-ansi "^7.0.0"
+ strip-ansi "^7.1.0"
+ wrap-ansi "^9.0.0"
memorystream@^0.3.1:
version "0.3.1"
@@ -1394,9 +1382,9 @@ ms@2.1.2:
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
npm-run-path@^5.1.0:
- version "5.1.0"
- resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-5.1.0.tgz#bc62f7f3f6952d9894bd08944ba011a6ee7b7e00"
- integrity sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==
+ version "5.3.0"
+ resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-5.3.0.tgz#e23353d0ebb9317f174e93417e4a4d82d0249e9f"
+ integrity sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==
dependencies:
path-key "^4.0.0"
@@ -1482,6 +1470,11 @@ path-type@^4.0.0:
resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
+picocolors@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1"
+ integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==
+
picomatch@^2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
@@ -1564,9 +1557,9 @@ reusify@^1.0.4:
integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
rfdc@^1.3.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b"
- integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.1.tgz#2b6d4df52dffe8bb346992a10ea9451f24373a8f"
+ integrity sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==
run-parallel@^1.1.9:
version "1.2.0"
@@ -1586,11 +1579,9 @@ semver@^6.3.0:
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
semver@^7.6.0:
- version "7.6.0"
- resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d"
- integrity sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==
- dependencies:
- lru-cache "^6.0.0"
+ version "7.6.2"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13"
+ integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==
set-function-length@^1.2.1:
version "1.2.2"
@@ -1648,6 +1639,14 @@ slice-ansi@^5.0.0:
ansi-styles "^6.0.0"
is-fullwidth-code-point "^4.0.0"
+slice-ansi@^7.0.0:
+ version "7.1.0"
+ resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-7.1.0.tgz#cd6b4655e298a8d1bdeb04250a433094b347b9a9"
+ integrity sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==
+ dependencies:
+ ansi-styles "^6.2.1"
+ is-fullwidth-code-point "^5.0.0"
+
solc-typed-ast@18.1.2:
version "18.1.2"
resolved "https://registry.yarnpkg.com/solc-typed-ast/-/solc-typed-ast-18.1.2.tgz#bc958fe3aead765cf6c2e06ce3d53c61fd06e70c"
@@ -1745,14 +1744,14 @@ string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.1"
-string-width@^5.0.0, string-width@^5.0.1:
- version "5.1.2"
- resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794"
- integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==
+string-width@^7.0.0:
+ version "7.1.0"
+ resolved "https://registry.yarnpkg.com/string-width/-/string-width-7.1.0.tgz#d994252935224729ea3719c49f7206dc9c46550a"
+ integrity sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==
dependencies:
- eastasianwidth "^0.2.0"
- emoji-regex "^9.2.2"
- strip-ansi "^7.0.1"
+ emoji-regex "^10.3.0"
+ get-east-asian-width "^1.0.0"
+ strip-ansi "^7.1.0"
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1"
@@ -1761,7 +1760,7 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1:
dependencies:
ansi-regex "^5.0.1"
-strip-ansi@^7.0.1:
+strip-ansi@^7.1.0:
version "7.1.0"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45"
integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==
@@ -1788,9 +1787,9 @@ supports-color@^7.1.0:
has-flag "^4.0.0"
table@^6.8.1:
- version "6.8.1"
- resolved "https://registry.yarnpkg.com/table/-/table-6.8.1.tgz#ea2b71359fe03b017a5fbc296204471158080bdf"
- integrity sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==
+ version "6.8.2"
+ resolved "https://registry.yarnpkg.com/table/-/table-6.8.2.tgz#c5504ccf201213fa227248bdc8c5569716ac6c58"
+ integrity sha512-w2sfv80nrAh2VCbqR5AK27wswXhqcck2AhfnNW76beQXskGZ1V12GwS//yYVa3d3fcvAip2OUnbDAjW2k3v9fA==
dependencies:
ajv "^8.0.1"
lodash.truncate "^4.4.2"
@@ -1827,11 +1826,6 @@ to-regex-range@^5.0.1:
dependencies:
is-number "^7.0.0"
-type-fest@^1.0.2:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-1.4.0.tgz#e9fb813fe3bf1744ec359d55d1affefa76f14be1"
- integrity sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==
-
undici-types@~5.26.4:
version "5.26.5"
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617"
@@ -1944,14 +1938,14 @@ wrap-ansi@^7.0.0:
string-width "^4.1.0"
strip-ansi "^6.0.0"
-wrap-ansi@^8.0.1, wrap-ansi@^8.1.0:
- version "8.1.0"
- resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"
- integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==
+wrap-ansi@^9.0.0:
+ version "9.0.0"
+ resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-9.0.0.tgz#1a3dc8b70d85eeb8398ddfb1e4a02cd186e58b3e"
+ integrity sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==
dependencies:
- ansi-styles "^6.1.0"
- string-width "^5.0.1"
- strip-ansi "^7.0.1"
+ ansi-styles "^6.2.1"
+ string-width "^7.0.0"
+ strip-ansi "^7.1.0"
wrappy@1:
version "1.0.2"
@@ -1963,11 +1957,6 @@ y18n@^5.0.5:
resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"
integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==
-yallist@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
- integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
-
yaml@2.3.4:
version "2.3.4"
resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.4.tgz#53fc1d514be80aabf386dc6001eb29bf3b7523b2"
@@ -1997,6 +1986,6 @@ yocto-queue@^1.0.0:
integrity sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==
zod@^3.21.4:
- version "3.23.6"
- resolved "https://registry.yarnpkg.com/zod/-/zod-3.23.6.tgz#c08a977e2255dab1fdba933651584a05fcbf19e1"
- integrity sha512-RTHJlZhsRbuA8Hmp/iNL7jnfc4nZishjsanDAfEY1QpDQZCahUp3xDzl+zfweE9BklxMUcgBgS1b7Lvie/ZVwA==
+ version "3.23.8"
+ resolved "https://registry.yarnpkg.com/zod/-/zod-3.23.8.tgz#e37b957b5d52079769fb8097099b592f0ef4067d"
+ integrity sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==
From 2dcd8fac9a29555a45f8e5306cc4d5f785e3d00a Mon Sep 17 00:00:00 2001
From: Hex <165055168+hexshire@users.noreply.github.com>
Date: Fri, 28 Jun 2024 12:39:39 -0300
Subject: [PATCH 2/4] chore: upgrade workflows dependencies (#71)
---
.github/workflows/canary.yml | 2 +-
.github/workflows/coverage_check.yml | 2 +-
.github/workflows/release.yml | 2 +-
.github/workflows/tests.yml | 32 ++++++++++++++--------------
4 files changed, 19 insertions(+), 19 deletions(-)
diff --git a/.github/workflows/canary.yml b/.github/workflows/canary.yml
index df99bf03..0c13f9c2 100644
--- a/.github/workflows/canary.yml
+++ b/.github/workflows/canary.yml
@@ -25,7 +25,7 @@ jobs:
uses: actions/setup-node@v4
with:
registry-url: 'https://registry.npmjs.org'
- node-version: 18.x
+ node-version: 20.x
cache: 'yarn'
- name: Install dependencies
diff --git a/.github/workflows/coverage_check.yml b/.github/workflows/coverage_check.yml
index b17316ca..69ea0b1e 100644
--- a/.github/workflows/coverage_check.yml
+++ b/.github/workflows/coverage_check.yml
@@ -20,7 +20,7 @@ jobs:
- name: Use Node.js
uses: actions/setup-node@v4
with:
- node-version: 18.x
+ node-version: 20.x
cache: 'yarn'
- name: Install dependencies
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 0ae154ef..b70ed1fe 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -27,7 +27,7 @@ jobs:
uses: actions/setup-node@v4
with:
registry-url: 'https://registry.npmjs.org'
- node-version: 18.x
+ node-version: 20.x
cache: 'yarn'
- name: Install dependencies
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 52de2d36..18624462 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -15,7 +15,7 @@ jobs:
name: Run Unit Tests
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
@@ -23,9 +23,9 @@ jobs:
version: nightly
- name: Use Node.js
- uses: actions/setup-node@v3
+ uses: actions/setup-node@v4
with:
- node-version: 18.x
+ node-version: 20.x
cache: 'yarn'
- name: Install dependencies
@@ -42,7 +42,7 @@ jobs:
name: Run Integration Tests
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
@@ -50,9 +50,9 @@ jobs:
version: nightly
- name: Use Node.js
- uses: actions/setup-node@v3
+ uses: actions/setup-node@v4
with:
- node-version: 18.x
+ node-version: 20.x
cache: 'yarn'
- name: Install dependencies
@@ -70,7 +70,7 @@ jobs:
steps:
- name: Checkout repository
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
with:
submodules: recursive
@@ -80,9 +80,9 @@ jobs:
version: nightly
- name: Use Node.js
- uses: actions/setup-node@v3
+ uses: actions/setup-node@v4
with:
- node-version: 18.x
+ node-version: 20.x
cache: 'yarn'
- name: Install dependencies
@@ -104,7 +104,7 @@ jobs:
name: Run symbolic execution tests
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
@@ -112,9 +112,9 @@ jobs:
version: nightly
- name: Use Node.js
- uses: actions/setup-node@v3
+ uses: actions/setup-node@v4
with:
- node-version: 18.x
+ node-version: 20.x
cache: 'yarn'
- name: Install dependencies
@@ -131,7 +131,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
with:
fetch-depth: 0
@@ -143,12 +143,12 @@ jobs:
version: nightly
- name: Use Node.js
- uses: actions/setup-node@v3
+ uses: actions/setup-node@v4
with:
- node-version: 18.x
+ node-version: 20.x
cache: 'yarn'
- name: Install dependencies
run: yarn --frozen-lockfile --network-concurrency 1
- - run: yarn lint:check
+ - run: yarn lint:check
\ No newline at end of file
From 9d36843665903ad893e06728c93a3eb3da3eea9a Mon Sep 17 00:00:00 2001
From: Gas <86567384+gas1cent@users.noreply.github.com>
Date: Thu, 4 Jul 2024 07:16:29 +0400
Subject: [PATCH 3/4] feat: improve coverage action (#73)
---
.../workflows/{coverage_check.yml => coverage.yml} | 11 ++++++-----
package.json | 2 +-
2 files changed, 7 insertions(+), 6 deletions(-)
rename .github/workflows/{coverage_check.yml => coverage.yml} (89%)
diff --git a/.github/workflows/coverage_check.yml b/.github/workflows/coverage.yml
similarity index 89%
rename from .github/workflows/coverage_check.yml
rename to .github/workflows/coverage.yml
index 69ea0b1e..2315a1bd 100644
--- a/.github/workflows/coverage_check.yml
+++ b/.github/workflows/coverage.yml
@@ -1,4 +1,4 @@
-name: Coverage check on main push
+name: Coverage Check
on: [push]
@@ -7,6 +7,7 @@ env:
jobs:
upload-coverage:
+ name: Upload Coverage
runs-on: ubuntu-latest
steps:
@@ -28,7 +29,7 @@ jobs:
- name: Run coverage
shell: bash
- run: forge coverage --report summary --report lcov
+ run: yarn coverage
- name: Setup LCOV
uses: hrishikesh-kadam/setup-lcov@v1
@@ -43,7 +44,7 @@ jobs:
coverage-files: lcovNew.info
- name: Retrieve previous coverage
- uses: actions/download-artifact@v2
+ uses: actions/download-artifact@v4
with:
name: coverage.info
continue-on-error: true
@@ -66,7 +67,7 @@ jobs:
mv lcovNew.info coverage.info
- name: Upload the new coverage
- uses: actions/upload-artifact@v2
+ uses: actions/upload-artifact@v4
with:
name: coverage.info
- path: ./coverage.info
\ No newline at end of file
+ path: ./coverage.info
diff --git a/package.json b/package.json
index 0c743777..246c5dd1 100644
--- a/package.json
+++ b/package.json
@@ -12,7 +12,7 @@
"scripts": {
"build": "forge build",
"build:optimized": "FOUNDRY_PROFILE=optimized forge build",
- "coverage": "forge coverage --match-contract Unit",
+ "coverage": "forge coverage --report summary --report lcov --match-path 'test/unit/*'",
"deploy:mainnet": "bash -c 'source .env && forge script Deploy -vvvvv --rpc-url $MAINNET_RPC --broadcast --chain mainnet --private-key $MAINNET_DEPLOYER_PK'",
"deploy:sepolia": "bash -c 'source .env && forge script Deploy -vvvvv --rpc-url $SEPOLIA_RPC --broadcast --chain sepolia --private-key $SEPOLIA_DEPLOYER_PK'",
"lint:check": "yarn lint:sol-tests && yarn lint:sol-logic && forge fmt --check",
From 2615e9cf522412cf1d4a3c058765f3e7c5af8932 Mon Sep 17 00:00:00 2001
From: Gas <86567384+gas1cent@users.noreply.github.com>
Date: Fri, 5 Jul 2024 18:57:56 +0400
Subject: [PATCH 4/4] feat: gitignore echidna corpus (#72)
---
.gitignore | 4 ++++
package.json | 2 +-
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/.gitignore b/.gitignore
index 9209344d..3c0f973b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,3 +19,7 @@ broadcast/*/*/*
# Out dir
out
+crytic-export
+
+# Echidna corpus
+test/invariants/fuzz/echidna_coverage
diff --git a/package.json b/package.json
index 246c5dd1..0ae14e9c 100644
--- a/package.json
+++ b/package.json
@@ -22,7 +22,7 @@
"lint:sol-tests": "solhint -c .solhint.tests.json 'test/**/*.sol'",
"prepare": "husky install",
"test": "forge test -vvv",
- "test:fuzz": "echidna test/invariants/fuzz/Greeter.t.sol --contract GreeterInvariant --corpus-dir test/invariants/fuzz/echidna_coverage/ --test-mode assertion",
+ "test:fuzz": "echidna test/invariants/fuzz/Greeter.t.sol --contract InvariantGreeter --corpus-dir test/invariants/fuzz/echidna_coverage/ --test-mode assertion",
"test:integration": "forge test --match-contract Integration -vvv",
"test:symbolic": "halmos",
"test:unit": "forge test --match-contract Unit -vvv",