Guide
How to read a smart contract audit report
Severity scales, scope statements, commit hashes, and the sections most people skip. Explained against reports you can open in the next tab.
In short
- Read the scope before the findings. A report is bounded by a commit hash and a file list, and the out-of-scope line is where it tells you what nobody looked at.
- Severity scales are not standardised. A report that does not define what it means by Critical is asking you to supply the meaning yourself.
- Status matters more than count. Findings are normal in a good codebase; findings the team accepted rather than fixed are the ones you are now deciding to live with.
- Audited means a named team read named code at a named commit. It does not mean secure, and no audit can prove the absence of a flaw.
Start at the scope, not the findings
Almost everyone opens an audit report at the findings table. It is the wrong end. A finding only means something against a scope, and the scope is where a report quietly tells you how much of the product nobody looked at.
Three things belong there. The commit hash, which pins the report to exact code. The file list, which tells you which contracts were read. And an out-of-scope line, which tells you what was not.
The commit hash is the one to check first. If the hash in the report is not the hash you deployed, the report describes different code — and the difference might be one line or six months of work. Nothing else in the document can tell you which.
The out-of-scope line is the one firms are tempted to leave vague. Ours on the technical sample reads: front-end, third-party bridge, off-chain keeper bots. That is three places an attacker can stand that the report says nothing about, stated plainly rather than left for you to infer.
Severity scales are not standardised
Critical, High, Medium, Low, Informational looks like an industry standard. It is a common convention, which is a different thing. Each firm defines its own, and two reports using the same five words can mean materially different things by them.
So the first question is not how many Criticals there are. It is whether the report defines what it means by Critical at all. A report that uses the labels without defining them is asking you to supply the meaning yourself.
Ours is impact-first — what happens if someone exploits it, rather than how likely they are to try:
| Severity | What we mean by it |
|---|---|
| Critical | Direct loss or freezing of user funds, exploitable by anyone |
| High | Loss under realistic conditions, or trust assumptions broken |
| Medium | Bounded loss, or requires unusual conditions to exploit |
| Low | Best-practice gap with indirect or operational risk |
| Informational | Code quality, gas and hardening notes; no direct risk |
Severity can be inflated, and it can be buried
Both directions happen. Some firms label low-severity issues high, because a report with three Criticals looks like better value than one with three Lows. Others downgrade, because a client reads a Critical as an accusation and the relationship is easier without one.
You can usually tell by reading the impact statement rather than the label. A Critical whose worst case is described as "could cause confusion" has been inflated. A Medium whose impact paragraph describes funds leaving has been buried.
The impact statement is harder to fake than the label, because it has to describe something specific.
The section most people skip
Privileged roles. Who holds admin keys, what those keys can do, and how fast they can do it.
This matters more than most findings, because it is not a bug. It is the system working as designed, and the design might be one multisig away from a rug. A protocol with flawless code and an unaccountable owner key is not safe; it is trusting.
The question to ask of that section is narrow: can any role move user funds directly? On our access control sample, the last row of the capability matrix answers it — no role, including Owner, can transfer user balances. Everything above that row is a question of degree. That row is categorical.
If a report does not contain that section at all, you have not been told whether anyone can empty the contract by design.
The anatomy of a finding worth reading
A finding that says "reentrancy risk in withdraw()" tells you a category. A finding worth reading tells you seven things, and you can check for them without understanding the code.
Where it is. A file, a function, a line range. If a finding cannot point at code, it is an opinion.
What it is. The mechanism, in the auditor's terms. This part is for your engineers.
What it is in plain terms. The same mechanism for everyone else — the people approving the budget and deciding whether to launch. A firm that cannot write this part may not have understood the finding either.
What it costs. Impact, stated as consequence rather than category. "Mispriced swaps whenever the upstream feed stalls, scaling with market movement" is an impact. "Could lead to loss of funds" is a shrug.
Proof. What was actually run. Ours on the stale-oracle finding: a 30-minute feed halt simulated on a fork while moving the market 12%, with the pool accepting swaps at the stale rate throughout. A finding with no proof has not been demonstrated, only suspected.
What to do. A specific remediation, not "follow best practice".
What happened. The resolution, re-tested. "Fixed and verified: the halt simulation now pauses the pool within one block" closes the loop. "Fixed" on its own does not say who checked.
Run those seven against any finding in any report. The ones that fail tend to fail at proof and at impact, which are the two that take real work.
Count tells you less than status
Findings are normal. A mature codebase reviewed properly produces them, and a report with none is more likely to indicate a shallow review than clean code.
What matters is what happened next. Every finding should carry a status, and the statuses that matter are the ones that are not "fixed": accepted, mitigated, or acknowledged without action. Those are the risks the team decided to live with, and you are now deciding whether to live with them too.
Our technical sample has one. TA-07, a medium, where long-term stakers could eventually be locked out of their own rewards. The team accepted it for launch with a capped epoch count and a refactor scheduled. We re-tested the cap and published the finding at full length anyway.
A report where everything was fixed is either a very short engagement or an incomplete account of one.
What "audited" does not mean
It does not mean secure. It means a named team read named code at a named commit, in a named window, and wrote down what they found.
It does not cover code changed after the review. It does not cover what was out of scope. It does not cover the parts of your system that are not code at all — the admin laptop, the deploy pipeline, the person with the hardware key.
And it cannot prove the absence of a flaw. An audit raises the cost of attacking you considerably. It does not reduce that cost to infinity, and a firm that implies otherwise is selling you something an audit cannot deliver.
The honest version of the claim is narrow, and it is the one worth looking for: these contracts, at this commit, were reviewed by these people, who found these things, of which these were fixed.
Red flags
None of these prove a bad audit on their own. Two or three together usually mean the report was written to be shown rather than read.
| What you see | What it usually means |
|---|---|
| No findings at all | A shallow review, or findings removed before publication |
| No severity definitions | The labels mean whatever the reader assumes |
| No per-finding status | You cannot tell what was fixed |
| A positive conclusion above unresolved Criticals | The summary and the body disagree; trust the body |
| No commit hash | Nothing ties the report to code |
| A badge on a website, no report | There may be a report. You have not read it |
| No privileged-roles section | Nobody has told you who can move the funds |
The checklist
Seven questions, in the order worth asking them. Run them against any report you are handed, including ours.
One. Does the commit hash in the report match the code that is deployed?
Two. Do the audited files cover the contracts that hold funds and control upgrades?
Three. What does the out-of-scope line say, and does anything in it hold value?
Four. Does the report define its own severity scale?
Five. Does every finding carry a status, and what did the team accept rather than fix?
Six. What can privileged roles do, and can any of them move user funds directly?
Seven. Was there a re-test after remediation, against a named commit?
A report that answers all seven is not necessarily a clean one. It is an honest one, which is the thing you can actually act on.
Questions
Is a critical finding a reason to walk away?
Usually not. Critical findings are found in good codebases by good auditors; that is what the engagement is for. What should concern you is a critical that is still open at launch, or one whose fix was never re-tested.
The commit hash does not match what is deployed. How bad is that?
It depends entirely on what changed, and the report cannot tell you. Ask for the diff between the audited commit and the deployed one. If the team cannot produce it, that is the answer.
Does a longer report mean a better audit?
No. Length tracks the number of informational notes more than the depth of review. Read the scope and the severity definitions; they tell you more about rigour than the page count does.
Should I trust an audit by a firm I have never heard of?
Judge the report rather than the name. The seven questions above work regardless of who wrote it, and a careful report from an unknown firm is worth more than a vague one from a famous one.
The work behind this
Web3 and protocol audit
Line-by-line review of contracts, chain layer and upgrade paths, with proof-of-concept for every finding.
Deployment verification
We check that what reached production matches what was actually reviewed.
Investor due diligence
Independent technical and regulatory review of a product before your capital moves.
Related reading
Guide
Access control and upgrade paths
Where the largest single losses sit, and the class least likely to be a bug. Most of it is the system working as designed, for the wrong person.
Guide
How to prepare for a smart contract audit
Preparation is the part of the engagement you control, and the part that moves the price. What to have ready before you ask for a quote.
Sample report
Technical audit report
A line-by-line security review, start to finish: twelve findings, the proof behind each one, and what happened after the team fixed them.