Dev.to Security 🔐 Cybersecurity 👁 0 📖 4 min read

What to have ready before your first smart contract audit

An audit is usually the biggest single check an early team writes. And a good part of the first days of most audits goes to things that have nothing to do with finding bugs: figuring out what the protocol is supposed to

An audit is usually the biggest single check an early team writes. And a good part of the first days of most audits goes to things that have nothing to do with finding bugs: figuring out what the protocol is supposed to do, which files are in scope, why the tests don't run, which commit we're even looking at.

You pay for those days either way. The difference is whether they go into understanding your setup or into attacking your logic.

So this is the list I'd go through before the audit starts. None of it needs a big budget. Most of it is a few evenings of work.

1. Write down what the code is supposed to do

If the auditor has to reverse engineer your intent from the code, part of the audit is spent guessing.

NatSpec on every public and external function. @notice, @param, @return. It sounds boring, but it's one of the best bug finders there is. If the comment says "takes a 1% fee" and the code computes 0.1%, that mismatch jumps out the moment someone reads both. Without the comment, the code is just the code, and a wrong number looks like a design choice.

A short theory of operation. How the money moves, who can do what, and what must never happen. A call graph and a state machine diagram help a lot if you have lifecycles (governance, vesting, auctions, liquidations).

A one page threat model. Who is trusted (owner, keepers, oracles), what each of them could break if they went rogue, and the single assumption you're most nervous about. This is the page I'd want first. A finding is only real relative to your trust assumptions, and without them every report turns into a debate about what counts as "in scope for an attacker".

A 20 to 30 minute video walkthrough. The lead dev screen-sharing the architecture and the flow of funds. It's the fastest way to get someone from zero to useful.

2. Clean the house

Noise hides bugs. It also costs reading time, because every line has to be read before anyone can say it doesn't matter.

  • Run a linter (Solhint or prettier-plugin-solidity). Style comments in an audit report are money spent on things a free tool does.
  • Delete dead code. Unused functions, commented out blocks, leftover test helpers in production contracts. Dead code isn't always dead: an internal helper that later gets exposed by a refactor is a classic way for old assumptions to come back.
  • Pin your compiler and your dependencies. pragma solidity 0.8.x; with an exact version, not ^0.8.0, and locked dependency versions. The bytecode you deploy should come from exactly the code that was reviewed.

3. Test the sad paths

Low test coverage is the clearest sign a codebase isn't ready.

Branch coverage, not line coverage. Line coverage tells you the code ran. Branch coverage tells you that every require and every if was hit both ways. Most of the interesting bugs live in the paths that are supposed to revert and don't.

Run static analysis and deal with every warning. Slither takes seconds. Fix the warnings or write down why each one is a false positive. Handing over 50 untriaged warnings means someone you're paying will triage them for you.

Run an AI pass too. Finding the obvious stuff got very cheap this year, for you and for anyone who looks at your code after deploy. Do it before the audit, fix what's real, and you'll get more out of the humans.

Write invariants and fuzz them. Unit tests check the cases you thought of. Invariant tests check the cases you didn't. With Foundry or Echidna, write down the properties that must always hold (something like "the sum of user balances never exceeds what the contract holds") and let the fuzzer try to break them. Even a handful of good invariants tells the auditor a lot about how you think about your system.

4. Freeze the code

Tag the commit (git tag audit-v1) and don't touch it. Pushing "small fixes" during the audit moves line numbers, invalidates notes, and turns into a diff review you pay for on top. If you find something yourself mid-audit, write it down and fix it in the remediation round. Better yet, tell the auditors, so they look at the area around it.

Write the scope down. A scope.txt with the exact files. Exclude mocks, deploy scripts and unmodified libraries like OpenZeppelin. If you modified a library, say so explicitly, because that's exactly the kind of thing that hides in "we just use OZ".

The short version

Area Ready when
Docs NatSpec on every public function, a theory of operation, a one page threat model
Code Linter clean, no dead code, compiler and dependencies pinned
Tests High branch coverage, sad paths tested, a few invariants fuzzed for a long run
Tools Slither and an AI pass run, every warning fixed or explained
Ops Commit tagged and frozen, scope file written, walkthrough recorded

One more thing

An audit covers a commit. Not your deploy scripts, not your config, not the three PRs you merge the week after. So plan the launch too: caps you can raise later, a pause you've actually tested, alerts that reach a human.

If you only do one thing this week, run Slither on your core contracts tonight. If it flags things you've never looked at, that's your answer on whether you're ready.

What's on your own pre-audit list that I didn't cover? Curious what other teams do before they book.

Adapted from a checklist our team published on zealynx.io.

I wrote this with help from AI for drafting and editing. The opinions and the audit experience are mine.

📰 Read the original article on Dev.to Security

Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.