Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions audit-readiness-checklist.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
# Audit Readiness Checklist

- [ ] If your contracts interact with arbitrary ERC20 tokens, explicitly test behavior with fee-on-transfer, rebasing, pausable, and blacklistable tokens (e.g. USDC, USDT). These have caused numerous exploits.
### Bare minimum quality checklist

- [ ] Use the [latest](https://docs.soliditylang.org/en/latest/) major version of Solidity.
- [ ] Use known/established libraries where possible. [OpenZeppelin contracts](https://github.com/OpenZeppelin/openzeppelin-contracts/) are preferred because they prioritize security above all else, and most auditors are already familiar with them. [Solmate contracts](https://github.com/Rari-Capital/solmate) can be a good alternative for functions where gas optimization is paramount.
- [ ] Use known/established libraries where possible. [OpenZeppelin contracts](https://github.com/OpenZeppelin/openzeppelin-contracts/) are preferred because they prioritize security above all else, and most auditors are already familiar with them. [Solmate contracts](https://github.com/transmissions11/solmate) can be a good alternative for functions where gas optimization is paramount.
- [ ] Have tests for "happy path" user stories and tests that expect reverts for actions that are supposed to fail. All tests should be passing.
- [ ] Incorporate fuzz tests. Fuzzing has proven to be highly effective in uncovering bugs. Tools like [Foundry](https://github.com/foundry-rs/foundry) and [Echidna](https://github.com/crytic/echidna) allow both stateless and stateful fuzzing. The [Foundry Invariants reference guide](https://book.getfoundry.sh/forge/invariant-testing?highlight=invariant#invariant-testing) provides an overview of how to set up your contract invariants for fuzzing. If you're using [Hardhat](https://github.com/NomicFoundation/hardhat), it is worthwhile to also include one of the above tools to enhance your testing capabilities.
- [ ] Run a static analysis tool ([Slither](https://github.com/crytic/slither) preferred, [MythX](https://mythx.io/) is an alternative) on your code and consider what it tells you. They very often raise flags for non-issues, but they can sometimes catch low-hanging fruit, so it's worth doing.
- [ ] Run a static analysis tool ([Slither](https://github.com/crytic/slither) preferred, [Aderyn by Cyfrin](https://github.com/semgrep/semgrep-solidity) and
[Semgrep with Solidity](https://github.com/Cyfrin/aderyn) rules are good alternatives. [MythX](https://mythx.io/) is deprecated) on your code and consider what it tells you. They very often raise flags for non-issues, but they can sometimes catch low-hanging fruit, so it's worth doing.
- [ ] Prepare the deploy script and mock upgrade scripts (if applicable) and include them as part of audit scope. Deployments and upgrades are as important as runtime code and require the same amount of security attention.
- [ ] Document all functions. Use [NatSpec documentation](https://docs.soliditylang.org/en/develop/natspec-format.html) for `public`/`external` functions. Consider this part of the public interface of the contract.
- [ ] Contracts compile without any errors or warnings from the compiler.
Expand All @@ -16,7 +17,7 @@
- [ ] Any `public` function that can be made `external` should be made `external`. This is not just a gas consideration, but it also reduces the cognitive overhead for auditors because it reduces the number of possible contexts in which the function can be called.
- [ ] Use the [Function Requirements-Effects-Interactions-Protocol Invariants (FREI-PI) pattern](https://www.nascent.xyz/idea/youre-writing-require-statements-wrong) everywhere possible. Treat all token and ETH transfers as 'interactions'. Verify your system-level protocol invariants still hold at the end of each interaction.
- [ ] Have at least one trusted Solidity dev or security person outside your organization sanity check your contracts. If your code is a tire fire and in need of major changes, you want to hear about that early and from a trusted friend (for free) rather than after an expensive audit.

- [ ] If using upgradeable contracts (proxies), verify storage layout compatibility between versions, ensure initializer functions have proper guards, and run `slither --check-upgradeability` before audit.

### Nice to haves

Expand Down