diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..897f65b --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,24 @@ +name: build + +# Simple CI Workflow for Building on Push + +on: [push] + +jobs: + tests: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Install Foundry + uses: onbjerg/foundry-toolchain@v1 + with: + version: nightly + + - name: Install dependencies + run: forge install + + - name: Check contract sizes + run: forge build --sizes diff --git a/.github/workflows/foundry-forge-tests.yaml b/.github/workflows/foundry-forge-tests.yaml index dbfe62f..72d2fe3 100644 --- a/.github/workflows/foundry-forge-tests.yaml +++ b/.github/workflows/foundry-forge-tests.yaml @@ -9,10 +9,12 @@ env: FOUNDRY_PROFILE: ci RPC_MAINNET: ${{ secrets.RPC_MAINNET }} ETHERSCAN_API_KEY: ${{ secrets.ETHERSCAN_API_KEY }} + jobs: check: strategy: fail-fast: true + name: Forge Tests runs-on: ubuntu-latest steps: @@ -20,18 +22,27 @@ jobs: uses: actions/checkout@v3 with: submodules: recursive + - name: Install Nix uses: cachix/install-nix-action@v20 + - name: Execute direnv + uses: HatsuneMiku3939/direnv-action@v1 + - name: Check formatting run: forge fmt --check + - name: Run Forge build run: | forge --version forge build --sizes id: build + - name: Run Forge tests run: | forge test --fork-url "$RPC_MAINNET" --etherscan-api-key $ETHERSCAN_API_KEY -vvv id: test + env: + # Only fuzz intensely if we're running this action on a push to main or for a PR going into main: + FOUNDRY_PROFILE: ${{ (github.ref == 'refs/heads/main' || github.base_ref == 'main') && 'intense' }} diff --git a/.github/workflows/slither.yml b/.github/workflows/slither.yml new file mode 100644 index 0000000..57ce63f --- /dev/null +++ b/.github/workflows/slither.yml @@ -0,0 +1,65 @@ +name: slither + +on: + push: + paths: + - "**.sol" + - ".github/workflows/slither.yml" + + pull_request_target: + branches: + - main + - develop + +# ensure permissions are explicitly defined +# by configuring one we disable the remaining permissions +# see: https://docs.github.com/en/actions/learn-github-actions/workflow-syntax-for-github-actions#jobsjob_idpermissions +# permissions: +# contents: read + +# ensure multiple CI processes are not running analysis on contracts +concurrency: + group: ${{ github.workflow }}-${{ github.event_name == 'pull_request_target' && github.head_ref || github.ref }} + cancel-in-progress: true + +env: + COMMIT_SHA: ${{ github.event.pull_request.head.sha }} + PULL_NUMBER: ${{ github.event.pull_request.number }} + RUN_ID: ${{ github.run_id }} + +jobs: + slither: + runs-on: ubuntu-latest + outputs: + SLITHER_COVERAGE: ${{ steps.slither.outputs.sarif }} + + strategy: + fail-fast: false + matrix: + node: ["16.x"] + os: ["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: forge install contract + id: forge + run: forge install + + - name: Compile contracts + run: forge build --sizes + + - name: Run Slither + uses: crytic/slither-action@v0.3.0 + id: slither + with: + sarif: results.sarif + fail-on: none diff --git a/.gitmodules b/.gitmodules index 5251474..a9e2489 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,12 +1,16 @@ [submodule "lib/forge-std"] path = lib/forge-std url = https://github.com/foundry-rs/forge-std + branch = v1.5.6 [submodule "lib/solmate"] path = lib/solmate url = https://github.com/transmissions11/solmate + branch = 1b3adf677e7e383cc684b5d5bd441da86bf4bf1c [submodule "lib/solady"] path = lib/solady url = https://github.com/Vectorized/solady + branch = v0.0.98 [submodule "lib/openzeppelin-contracts"] path = lib/openzeppelin-contracts - url = git@github.com:OpenZeppelin/openzeppelin-contracts.git + url = https://github.com/OpenZeppelin/openzeppelin-contracts + branch = v4.9.0 diff --git a/dapptest.yml b/dapptest.yml new file mode 100644 index 0000000..2c3b6b3 --- /dev/null +++ b/dapptest.yml @@ -0,0 +1 @@ +testMode: dapptest diff --git a/echidna.config.yml b/echidna.config.yml new file mode 100644 index 0000000..64a761d --- /dev/null +++ b/echidna.config.yml @@ -0,0 +1,74 @@ +#format can be "text" or "json" for different output (human or machine readable) +format: 'text' +#checkAsserts checks assertions +checkAsserts: true +#coverage controls coverage guided testing +coverage: false +# #psender is the sender for property transactions; by default intentionally +# #the same as contract deployer +# psender: "0x00a329c0648769a73afac7f9381e08fb43dbea70" +# #prefix is the prefix for Boolean functions that are properties to be checked +# prefix: "echidna_" +# #propMaxGas defines gas cost at which a property fails +# propMaxGas: 8000030 +# #testMaxGas is a gas limit; does not cause failure, but terminates sequence +# testMaxGas: 8000030 +# #maxGasprice is the maximum gas price +# maxGasprice: 100000000000 +# #testLimit is the number of test sequences to run +# testLimit: 50000 +# #stopOnFail makes echidna terminate as soon as any property fails and has been shrunk +# stopOnFail: false +# #estimateGas makes echidna perform analysis of maximum gas costs for functions (experimental) +# estimateGas: false +# #seqLen defines how many transactions are in a test sequence +# seqLen: 100 +# #shrinkLimit determines how much effort is spent shrinking failing sequences +# shrinkLimit: 5000 +# #contractAddr is the address of the contract itself +# contractAddr: "0x00a329c0648769a73afac7f9381e08fb43dbea72" +# #deployer is address of the contract deployer (who often is privileged owner, etc.) +# deployer: "0x00a329c0648769a73afac7f9381e08fb43dbea70" +# #sender is set of addresses transactions may originate from +# sender: ["0x10000", "0x20000", "0x00a329c0648769a73afac7f9381e08fb43dbea70"] +# #balanceAddr is default balance for addresses +# balanceAddr: 0xffffffff +# #balanceContract overrides balanceAddr for the contract address +# balanceContract: 0 +# #solcArgs allows special args to solc +# solcArgs: "" +# #solcLibs is solc libraries +# solcLibs: [] +# #cryticArgs allows special args to crytic +# cryticArgs: [] +# #quiet produces (much) less verbose output +# quiet: false +# #initialize the blockchain with some data +# initialize: null +# #whether ot not to use the multi-abi mode of testing +# multi-abi: false +# #benchmarkMode enables benchmark mode +# benchmarkMode: false +# #timeout controls test timeout settings +# timeout: null +# #seed not defined by default, is the random seed +# #seed: 0 +# #dictFreq controls how often to use echidna's internal dictionary vs random +# #values +# dictFreq: 0.40 +# maxTimeDelay: 604800 +# #maximum time between generated txs; default is one week +# maxBlockDelay: 60480 +# #maximum number of blocks elapsed between generated txs; default is expected increment in one week +# # timeout: +# #campaign timeout (in seconds) +# # list of methods to filter +# filterFunctions: [] +# # by default, blacklist methods in filterFunctions +# filterBlacklist: true +# #directory to save the corpus; by default is disabled +# corpusDir: null +# # constants for corpus mutations (for experimentation only) +# mutConsts: [100, 1, 1] +# # maximum value to send to payable functions +# maxValue: 100000000000000000000 # 100 eth