Solidity Pre-Audit Preparation: A Checklist for Web3 Teams
Prepare your Solidity codebase before engaging an auditor. This pre-audit preparation checklist reduces cost, improves coverage, and gets better results.
Most teams think about the audit as something that happens after the code is done. The teams that get the most value from their security review treat audit preparation as part of the development process, not a handoff ritual. An auditor reviewing well-prepared code finds more real vulnerabilities. An auditor reviewing unprepared code spends billable time on context-building and documentation that developers should have done themselves.
This checklist covers what to have in order before you open a conversation with a security firm.
Solidity Pre-Audit Preparation Checklist
Code Quality and Documentation
Lock your compiler version
Use a fixed Solidity version in every file (pragma solidity 0.8.24; not ^0.8.0). The caret syntax allows the contract to compile under future compiler versions with potentially different behavior. Auditors want to know exactly what compiler was used.
Write NatSpec comments for every external and public function
NatSpec is Ethereum's documentation standard. Every external and public function should have @notice (what it does for users) and @dev (technical implementation notes). Every parameter should be documented with @param and return values with @return. Auditors who can read what a function is supposed to do can immediately identify whether it actually does that.
Write an architecture overview document
One or two pages covering:
- What the protocol does and its economic design
- How the contracts relate to each other (a diagram helps)
- What external protocols are integrated and why
- What the key invariants of the system are (e.g., "the sum of all user balances should always equal the total supply token held by the contract")
- Known trade-offs or design decisions that are intentional
Define scope explicitly
List every file that is in scope and every file that is out of scope, with brief justification. If a library file is an unmodified copy of a previously audited dependency, say so.
Code Cleanliness
Remove all TODO and FIXME comments
If there are unresolved questions or incomplete implementations in the code, resolve them before the audit. Auditors who find TODOs may not know which are genuine planned work and which represent security gaps.
Remove unused imports, variables, and functions
Dead code creates noise and costs auditor time. Run a linter (Solhint or Slither's unused variable checks) and remove everything that is not needed.
Use named constants for magic numbers
Replace inline numbers with named constants that communicate intent. LIQUIDATION_THRESHOLD = 8000 is auditable; 8000 in the middle of a calculation is not.
Consistent error messages
Use custom errors rather than string revert messages where possible (cheaper gas, clearer intent). Custom errors should have descriptive names: InsufficientBalance() is auditable; E1() is not.
Testing
Achieve meaningful unit test coverage
Not necessarily 100%, but every critical path — deposits, withdrawals, liquidations, reward calculations — should have unit tests. Auditors use test suites to understand intended behavior.
Write at least basic invariant tests
Foundry's invariant testing feature and Echidna both let you define properties that should always hold and fuzz the contract looking for violations. Key invariants to cover:
- Token accounting: total supply equals sum of all balances
- Fund custody: ETH or tokens held by the contract match what accounting says should be there
- Authorization: no unauthorized address can trigger a privileged operation
Include negative test cases
Test that unauthorized callers are rejected. Test that operations fail correctly under invalid inputs. These tests document expected behavior under failure conditions and give auditors confidence that error handling is intentional.
Run all tests on the exact codebase being submitted
Do not submit code that does not pass its own test suite. Failing tests during an audit engagement are a red flag and waste auditor time.
Security Self-Review
Run Slither and address output
Slither is a free static analyzer that catches many common vulnerability patterns. Run it against your codebase and triage all findings before the audit. For findings you disagree with or have intentionally accepted, document your reasoning. Auditors who receive a list of pre-triaged Slither findings with explanations spend less time on known patterns and more time on novel issues.
Verify all external calls follow CEI
Check every external call in the codebase — ETH transfers, ERC-20 transfers, calls to external contracts. Confirm that all state updates happen before the external call. This is the Checks-Effects-Interactions pattern. Flag any place where this order is not followed and document why.
Verify access control on every function
Generate a list of all external and public functions and their access modifiers. Every function that should be restricted should have an explicit modifier enforcing that restriction. Functions with no access restriction should be deliberately public — not accidentally so.
Check for hardcoded addresses
Hardcoded addresses for token contracts, oracle feeds, or external protocols should be documented. If these are expected to change, the mechanism for updating them should be access-controlled.
Audit Engagement Logistics
Designate a technical point of contact
The auditing firm will have questions. A single senior developer who can respond within hours rather than days keeps the engagement moving and prevents delays.
Allocate time for remediation
Build calendar time into the release schedule for the remediation phase after the initial audit report. Fixing findings and having them retested takes time. Protocols that rush remediation introduce new bugs.
Budget for a retest
Confirm upfront that the engagement includes retesting of critical and high findings after remediation. A report with no retest is not a complete engagement.
A prepared codebase is a more auditable codebase. The audit result you get reflects the quality of the code and documentation you submit.
Clixo builds Web3 systems with audit-readiness built into delivery. If your team needs a technical partner who treats security as part of engineering — not a final gate — reach out.