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",