To prepare for a smart contract audit, freeze the code on a specific commit, document what the system is supposed to do, describe the architecture and privileged roles, deliver a test suite that runs, fix what automated tools already detect, and list the issues you already know about. A well-prepared project lets auditors spend their time on real risks instead of reconstructing intent from the code. It also reduces the cost and the duration of the audit, and it makes the report more useful.
Why preparation matters
Preparation matters because auditors are paid by the day, and every hour spent understanding undocumented code or fixing a broken build is an hour not spent looking for vulnerabilities. An unprepared codebase does not only cost more; it is also reviewed less deeply for the same budget.
Preparation also affects scheduling. Auditors often book engagements weeks ahead. If the code is not ready on the start date, the slot may be lost, or the audit may start on code that keeps changing, which weakens its conclusions. Our guide to the smart contract audit process explains each stage of the engagement that follows.
Freeze the code on a commit
A code freeze means that the files in scope stop changing from the moment the audit starts, and the review is anchored to one commit hash. This is the single most important preparation step.
In practice:
- Choose the commit to be audited and share its hash with the auditor before the start date.
- Finish the features first. Do not submit code with open pull requests, placeholders or "to do" comments on critical paths.
- Continue any new development on a separate branch, which will need its own review later.
- Remove dead code and unused contracts from the scope, or exclude them explicitly.
The code freeze protects the value of the report: its conclusions apply to that commit and to nothing else.
Document the specification, architecture and roles
Auditors need three things in writing before they start: what the system should do, how its contracts fit together, and who holds which powers.
Specification
Documentation tells the auditor what the code is supposed to do, which is the only way to detect code that does something else. Many serious findings are logic errors: the code runs correctly, but not as intended.
A useful specification covers:
- The purpose of the system and its main user flows, in plain language.
- Each contract's responsibility and its public and external functions.
- The expected behavior in edge cases: zero amounts, empty pools, paused states, maximum values.
- The formulas used (fees, interest, rewards, prices), with units and rounding direction.
- The assumptions about external systems: which oracle, which token standards, which chains.
Inline comments (NatSpec comments in Solidity) complement the specification; they do not replace it. The format matters less than completeness and accuracy.
Architecture and privileged roles
Auditors need a clear picture of how contracts interact and who can do what. A simple diagram and a list of roles save hours of analysis.
Describe:
- The contracts and how they call each other, including external protocols.
- Every privileged role (owner, admin, minter, pauser, upgrader, keeper) and each function it can call.
- Who will hold each role at launch: a single key, a multisig, a timelock, a governance contract.
- Upgradeability: which contracts are upgradeable, through which proxy pattern, and who authorizes an upgrade.
- The trust assumptions: what users must trust the team or third parties not to do.
Access control errors are among the most common causes of losses, and auditors can only judge them if they know the intended permissions.
Tests, coverage and static analysis
A test suite that runs and a clean static analysis report show the auditor that the basics are covered, so the review can go deeper.
Tests and coverage
A working test suite shows the auditor how the system is meant to behave and gives them a base to write their own tests. It is also a strong signal of maturity.
Before the audit:
- Make sure the project compiles and all tests pass from a clean clone, with written setup instructions.
- Cover the main flows and the edge cases, not only the "happy path".
- Measure line and branch coverage, and explain any significant gap.
- Add fuzz tests and invariant tests for the core accounting if possible.
- For integrations, include fork tests against the real external contracts where relevant.
Tests do not prove the absence of bugs, but a project with good tests typically needs fewer auditor-days, and its findings are easier to reproduce and fix.
Run static analysis first
Run static analysis tools and compiler warnings before the audit, and fix or document everything they report. Paying an auditor to report issues that a free tool finds in minutes is a poor use of budget.
Good practice:
- Resolve all compiler warnings and use a fixed, recent compiler version.
- Run at least one static analyzer and triage every result: fix it, or explain why it is a false positive.
- Apply a linter and a consistent formatting style.
- Remove unused imports, variables and functions.
Share the triaged results with the auditor. It shows what has already been checked and lets them focus on deeper issues.
Known issues and deployment setup
Two short documents complete the preparation: a list of known issues and a description of how the system will be deployed and administered.
Known issues list
List the limitations and risks the team already knows and accepts, with a justification for each. For example: a centralization risk during the first months, a dependency on a single oracle, or a known rounding loss below a threshold. This avoids paying for findings you already know about and clarifies which risks are design decisions.
Deployment and admin setup
Provide the deployment scripts, the initial parameters (fees, limits, addresses) and the target chains. Explain how admin keys will be held and how emergency actions work (pause, upgrade, parameter changes), including any multisig threshold or timelock delay. Many incidents stem from deployment or configuration mistakes rather than from the contract code itself. If deployment scripts are in scope, say so explicitly.
Smart contract audit readiness checklist
The checklist below summarizes the preparation. Share it with the auditor along with the repository.
- Commit hash chosen and shared; code freeze declared on the files in scope
- Files in scope and files excluded listed, with the size of the code
- Specification describing purpose, flows, edge cases and formulas
- Architecture diagram and list of contracts and their interactions
- List of privileged roles, their functions and who will hold them
- Upgradeability pattern and upgrade authorization described
- Project builds and all tests pass from a clean clone, with instructions
- Coverage measured; fuzz or invariant tests on core accounting
- Compiler warnings resolved; static analysis run and triaged
- Known issues list with justifications
- Deployment scripts, initial parameters and admin setup documented
- A developer available for questions during the audit and for the fixes
How readiness lowers cost and duration
Readiness lowers the cost of an audit directly, because it reduces the number of auditor-days needed. In the site's indicative model, readiness is a multiplier on effort: 0.9 when tests and documentation are good, 1.0 when they are partial, and 1.2 when they are missing. Without preparation, a review needs about a third more effort than with good preparation.
For example, for a 1,500 nSLOC DeFi codebase in Solidity reviewed by an independent auditor, the model gives about 6 auditor-days with partial readiness, about 5 with good readiness and about 7 with none. These are indicative ranges from the site's public model; real quotes depend on the scope. You can test your own case with the audit cost calculator, and our guide on smart contract audit cost explains the other factors.
Readiness also reduces indirect costs. Frozen code avoids scope changes and new estimates. Clear documentation leads to fewer false positives and clearer findings. Good tests make fixes faster and the re-audit shorter, which matters since the re-audit is budgeted at about 20% of the first audit price in the same model. Finally, a well-prepared project is easier to schedule, and it avoids the urgency premium charged when an audit must start within one or two weeks.
Key takeaways
- Freeze the code on a single commit before the audit starts; the report only applies to that commit.
- Give auditors a specification, an architecture overview and the full list of privileged roles, so they can detect code that does not do what it should.
- Deliver a test suite that runs from a clean clone, and fix what compilers and static analysis tools already report.
- Document known issues and the deployment and admin setup to avoid paying for findings you already know.
- In the site's indicative model, good readiness needs about 25% less audit effort than no preparation, and it shortens fixes and re-audit.