Skip to content

⚒️ Start your next Solidity project with Foundry in seconds

License

Notifications You must be signed in to change notification settings

BreadchainCoop/solidity-foundry-boilerplate

 
 

Repository files navigation

wonderland banner


Start your next Solidity project with Foundry in seconds
A highly scalable foundation focused on DX and best practices

Forked by Breadchain

Breadchain Developers

Basic Setup
  • Use `yarn add`, not `forge install`
  • Use yarn scripts, not forge scripts (Look at the `package.json`!).
  • Add scripts to the `package.json` as needed.
  • Required Contracts
  • Every contract is required to have a full interface.
  • The contract should inherit it's own interface.
  • The contract should reference it's interface with `@inheritdoc`
  • The interface should contain other tags, including `@notice, @param, @return, @dev`
  • The contract should be free of clutter, whereas the interface should act as a guide to the contract.
  • Errors, Events, and Structs should be located in interfaces, not in contracts.
  • Required Testing
  • Integration/E2E - should fork chain intended for deployment (likely gnosis or optimism) and should use the deploy script found in `Script/Common.sol` in the `test/integration/IntegrationBase.sol`.
  • Unit - should test and branch all contract functionality, with mock contracts or mock function calls added as needed to mock inter-contract calls. `.tree` files are there for example, but not necessary.
  • Test Coverage
  • Run `yarn coverage` to generate a coverage report for tests
  • Unit and Integration should be 100%, with branch testing reasonably high
  • Advice for Writing Tests
  • Make use of `setUp` overrides and inheritance to cut down on redundant setups.
  • Make use of helper functions with obvious names (e.g. `_fundUsersWithTokens()`) to reduce complexity for other developers that will review the code.
  • Make use of Modifiers within test contracts to constrain fuzzing variables or any other use case
  • Make multiple testing contracts in one file that all test the same contract (e.g. E2EGreeterTestSetup, E2EGreeterTestAccessControl, E2EGreeterTestCore, etc.) where contracts inherit the same base setup.
  • Make use of constant variables placed in base test setup, so that updating test variables is simple and easy.
  • Keep tests organized! Break complexity down and make it readable!
  • Required Formatting
  • Commits cannot be made without passing the linter!
  • Run `yarn lint:check`
  • Check `package.json` for more linter commands
  • Internal variables start with an underscore ('_exampleOfInternalVar').
  • Run `lint:natspec` to check contracts and interfaces for correct natspec.
  • Commit Messages
  • Example: `feat: added liquidation method to buttered-bread contract`
  • Example: `test: added unit tests`
  • List of commit types: `[build, chore, ci, docs, feat, fix, perf, refactor, revert, style, test]`
  • For more specific details, checkout `https://www.conventionalcommits.org/en/v1.0.0-beta.4/`
  • End of Breadchain Notes
    Continue Reading Wonderland Outline

    Features

    Sample contracts
    Basic Greeter contract with an external interface.
    Foundry setup
    Foundry configuration with multiple custom profiles and remappings.
    Deployment scripts
    Sample scripts to deploy contracts on both mainnet and testnet.
    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.
    Find missing natspec automatically.
    Github workflows CI
    Run all tests and see the coverage as you push your changes.
    Export your Solidity interfaces and contracts as packages, and publish them to NPM.

    Setup

    1. Install Foundry by following the instructions from their repository.
    2. Copy the .env.example file to .env and fill in the variables.
    3. Install the dependencies by running: yarn install. In case there is an error with the commands, run foundryup and try them again.

    Build

    The default way to build the code is suboptimal but fast, you can run it via:

    yarn build

    In order to build a more optimized code (via IR), run:

    yarn build:optimized

    Running tests

    Unit tests should be isolated from any externalities, while Integration usually run in a fork of the blockchain. In this boilerplate you will find example of both.

    In order to run both unit and integration tests, run:

    yarn test

    In order to just run unit tests, run:

    yarn test:unit

    In order to run unit tests and run way more fuzzing than usual (5x), run:

    yarn test:unit:deep

    In order to just run integration tests, run:

    yarn test:integration

    In order to just run the echidna fuzzing campaign (requires Echidna installed), run:

    yarn test:fuzz

    In order to just run the symbolic execution tests (requires Halmos installed), run:

    yarn test:symbolic

    In order to check your current code coverage, run:

    yarn coverage

    Deploy & verify

    Setup

    Configure the .env variables and source them:

    source .env

    Import your private keys into Foundry's encrypted keystore:

    cast wallet import $OPTIMISM_DEPLOYER_NAME --interactive
    cast wallet import $SEPOLIA_DEPLOYER_NAME --interactive

    Sepolia

    yarn deploy:sepolia

    Mainnet

    yarn deploy:mainnet

    The deployments are stored in ./broadcast

    See the Foundry Book for available options.

    Export And Publish

    Export TypeScript interfaces from Solidity contracts and interfaces providing compatibility with TypeChain. Publish the exported packages to NPM.

    To enable this feature, make sure you've set the NPM_TOKEN on your org's secrets. Then set the job's conditional to true:

    jobs:
      export:
        name: Generate Interfaces And Contracts
        # Remove the following line if you wish to export your Solidity contracts and interfaces and publish them to NPM
        if: true
        ...

    Also, remember to update the package_name param to your package name:

    - name: Export Solidity - ${{ matrix.export_type }}
      uses: defi-wonderland/solidity-exporter-action@1dbf5371c260add4a354e7a8d3467e5d3b9580b8
      with:
        # Update package_name with your package name
        package_name: "my-cool-project"
        ...
    
    
    - name: Publish to NPM - ${{ matrix.export_type }}
      # Update `my-cool-project` with your package name
      run: cd export/my-cool-project-${{ matrix.export_type }} && npm publish --access public
      ...

    You can take a look at our solidity-exporter-action repository for more information and usage examples.

    Licensing

    The primary license for the boilerplate is PPL, see LICENSE

    About

    ⚒️ Start your next Solidity project with Foundry in seconds

    Resources

    License

    Stars

    Watchers

    Forks

    Releases

    No releases published

    Packages

    No packages published

    Languages

    • Solidity 97.6%
    • JavaScript 2.4%