diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..3248848 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,158 @@ +name: CI + +on: + workflow_dispatch: + pull_request: + push: + branches: + - main + +env: + FOUNDRY_PROFILE: ci + MAINNET_RPC_URL: ${{ secrets.MAINNET_RPC_URL }} + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1 + + - name: Build contracts + run: | + forge --version + forge build --sizes + + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1 + + # https://twitter.com/PaulRBerg/status/1611116650664796166 + - name: Generate fuzz seed with 1 day TTL + run: > + echo "FOUNDRY_FUZZ_SEED=$( + echo $(($EPOCHSECONDS - $EPOCHSECONDS % 86400)) + )" >> $GITHUB_ENV + + - name: Run tests + run: forge test + + coverage: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1 + + # https://twitter.com/PaulRBerg/status/1611116650664796166 + - name: Generate fuzz seed with 1 day TTL + run: > + echo "FOUNDRY_FUZZ_SEED=$( + echo $(($EPOCHSECONDS - $EPOCHSECONDS % 86400)) + )" >> $GITHUB_ENV + + - name: Run coverage + run: forge coverage --report summary --report lcov + + # To ignore coverage for certain directories modify the paths in this step as needed. The + # below default ignores coverage results for the test and script directories. Alternatively, + # to include coverage in all directories, comment out this step. Note that because this + # filtering applies to the lcov file, the summary table generated in the previous step will + # still include all files and directories. + # The `--rc lcov_branch_coverage=1` part keeps branch info in the filtered report, since lcov + # defaults to removing branch info. + - name: Filter directories + run: | + sudo apt update && sudo apt install -y lcov + lcov --remove lcov.info 'test/*' 'script/*' --output-file lcov.info --rc lcov_branch_coverage=1 + + # This step posts a detailed coverage report as a comment and deletes previous comments on + # each push. The below step is used to fail coverage if the specified coverage threshold is + # not met. The below step can post a comment (when it's `github-token` is specified) but it's + # not as useful, and this action cannot fail CI based on a minimum coverage threshold, which + # is why we use both in this way. + - name: Post coverage report + if: github.event_name == 'pull_request' # This action fails when ran outside of a pull request. + uses: romeovs/lcov-reporter-action@v0.3.1 + with: + delete-old-comments: true + lcov-file: ./lcov.info + github-token: ${{ secrets.GITHUB_TOKEN }} # Adds a coverage summary comment to the PR. + + - name: Verify minimum coverage + uses: zgosalvez/github-actions-report-lcov@v2 + with: + coverage-files: ./lcov.info + minimum-coverage: 100 + + lint: + runs-on: ubuntu-latest + steps: + - name: "Check out the repo" + uses: actions/checkout@v3 + with: + submodules: recursive + - name: "Install Node.js" + uses: actions/setup-node@v3 + with: + node-version: lts/* + + - name: "Install the Node.js dependencies" + run: npm install + + - name: Run linter and check for errors + id: lint + run: | + LINT_OUTCOME=$(npm run lint 2>&1 || true) # Prevent the step from failing immediately + echo "$LINT_OUTCOME" + echo "LINT_OUTCOME<> $GITHUB_ENV + echo "$LINT_OUTCOME" >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + if echo "$LINT_OUTCOME" | grep -q " error "; then + echo "## Lint result" >> $GITHUB_STEP_SUMMARY + echo "❌ Failed due to errors" >> $GITHUB_STEP_SUMMARY + exit 1 + else + echo "## Lint result" >> $GITHUB_STEP_SUMMARY + echo "✅ Passed or warnings found" >> $GITHUB_STEP_SUMMARY + fi + + slither-analyze: + runs-on: "ubuntu-latest" + permissions: + actions: "read" + contents: "read" + security-events: "write" + steps: + - name: "Check out the repo" + uses: "actions/checkout@v4" + + - name: "Install Bun" + uses: "oven-sh/setup-bun@v1" + + - name: "Install the Node.js dependencies" + run: "bun install --frozen-lockfile" + + - name: "Run Slither analysis" + uses: "crytic/slither-action@v0.3.0" + id: "slither" + with: + fail-on: "none" + sarif: "results.sarif" + + - name: "Upload SARIF file to GitHub code scanning" + uses: "github/codeql-action/upload-sarif@v2" + with: + sarif_file: ${{ steps.slither.outputs.sarif }} + + - name: "Add summary" + run: | + echo "## Slither result" >> $GITHUB_STEP_SUMMARY + echo "✅ Uploaded to GitHub code scanning" >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml deleted file mode 100644 index 9b98781..0000000 --- a/.github/workflows/lint.yml +++ /dev/null @@ -1,43 +0,0 @@ -name: "Lint" - -env: - FOUNDRY_PROFILE: "ci" - -on: - workflow_dispatch: - push: - branches: - - "main" - -jobs: - lint: - runs-on: ubuntu-latest - steps: - - name: "Check out the repo" - uses: actions/checkout@v3 - with: - submodules: recursive - - name: "Install Node.js" - uses: actions/setup-node@v3 - with: - node-version: lts/* - - - name: "Install the Node.js dependencies" - run: npm install - - - name: Run linter and check for errors - id: lint - run: | - LINT_OUTCOME=$(npm run lint 2>&1 || true) # Prevent the step from failing immediately - echo "$LINT_OUTCOME" - echo "LINT_OUTCOME<> $GITHUB_ENV - echo "$LINT_OUTCOME" >> $GITHUB_ENV - echo "EOF" >> $GITHUB_ENV - if echo "$LINT_OUTCOME" | grep -q " error "; then - echo "## Lint result" >> $GITHUB_STEP_SUMMARY - echo "❌ Failed due to errors" >> $GITHUB_STEP_SUMMARY - exit 1 - else - echo "## Lint result" >> $GITHUB_STEP_SUMMARY - echo "✅ Passed or warnings found" >> $GITHUB_STEP_SUMMARY - fi diff --git a/.github/workflows/slither-analyze.yml b/.github/workflows/slither-analyze.yml deleted file mode 100644 index 24b6b79..0000000 --- a/.github/workflows/slither-analyze.yml +++ /dev/null @@ -1,41 +0,0 @@ -name: "Slither Analyze" - -on: - workflow_dispatch: - push: - branches: - - "main" - -jobs: - slither-analyze: - runs-on: "ubuntu-latest" - permissions: - actions: "read" - contents: "read" - security-events: "write" - steps: - - name: "Check out the repo" - uses: "actions/checkout@v4" - - - name: "Install Bun" - uses: "oven-sh/setup-bun@v1" - - - name: "Install the Node.js dependencies" - run: "bun install --frozen-lockfile" - - - name: "Run Slither analysis" - uses: "crytic/slither-action@v0.3.0" - id: "slither" - with: - fail-on: "none" - sarif: "results.sarif" - - - name: "Upload SARIF file to GitHub code scanning" - uses: "github/codeql-action/upload-sarif@v2" - with: - sarif_file: ${{ steps.slither.outputs.sarif }} - - - name: "Add summary" - run: | - echo "## Slither result" >> $GITHUB_STEP_SUMMARY - echo "✅ Uploaded to GitHub code scanning" >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml deleted file mode 100644 index 9b485dd..0000000 --- a/.github/workflows/test.yml +++ /dev/null @@ -1,38 +0,0 @@ -name: "Test" - -on: - workflow_dispatch: - push: - branches: - - "main" - -env: - FOUNDRY_PROFILE: ci - -jobs: - check: - strategy: - fail-fast: true - - name: Foundry project - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - submodules: recursive - - - name: Install Foundry - uses: foundry-rs/foundry-toolchain@v1 - with: - version: nightly - - - name: Run Forge build - run: | - forge --version - forge build --sizes - id: build - - - name: Run Forge tests - run: | - forge test -vvv - id: test diff --git a/test/Staking.t.sol b/test/Staking.t.sol index 39d1d8d..58fb259 100644 --- a/test/Staking.t.sol +++ b/test/Staking.t.sol @@ -351,7 +351,7 @@ contract Stake is StakingTest { _stake(_depositor2, _amount); - assertGt( + assertGe( staking.balanceOf(_depositor1), staking.balanceOf(_depositor2), "Wrong balance" @@ -918,6 +918,11 @@ contract Unstake is StakingTest { _amount = _boundToRealisticStake(_amount); _jump = _boundRealisticTimeAhead(_jump); + vm.assume( + _anyone != address(0) && + _anyone != ProxyUtils.getAdminAddress(address(staking)) + ); + _mintGovToken(_depositor, _amount); _setKeyper(_depositor, true);