How to read a smart contract audit report, section by section
What each section of an audit report establishes and what it leaves open, how to check that deployed bytecode matches the audited commit, and the questions to ask before relying on a report.
- Written by
- Quantix Research, Smart Contract Security
- Published
- Reading time
- 11 minutes
- Category
- Smart Contract Vulnerabilities
Primer. Explains a known class of issue. Code is simplified and illustrative, not for production use.

Contents
- Scope: the commit, the files and the exclusions
- Dates and effort
- Methodology, threat model and trust assumptions
- Severity: impact and likelihood
- Reading a finding
- Status, remediation review and residual risk
- The report on one page
- Is the audited code the code that runs?
- Four more questions to ask
- Red flags in a report
- Conclusions
- Recommendations
- Bibliography
An audit report is the document most often cited as evidence that a protocol is safe, and one of the most often misread. What it contains is narrower than “the protocol is audited”, and more useful: evidence about specific code, at a specific commit, reviewed for a stated period, under assumptions the report writes down.
This primer reads a report section by section, for people who rely on reports they did not commission: investors, integrators, users and founders comparing reviews. The examples come from two published Quantix research assessments, Fenwick Lending and Quillon Vaults.
Scope: the commit, the files and the exclusions
Every claim in a report is anchored to its scope: a repository, a commit hash and a list of files. A commit hash identifies one exact snapshot of the code, so “reviewed at commit 0ce97e1de9ab” can be checked by anyone with the repository; “reviewed the main branch” cannot. File sizes are usually given in nSLOC, a line count that leaves out comments and blank lines.
The Fenwick Lending scope table lists four Solidity files with their nSLOC (538, 96, 274 and 88; 996 in total) and a directory of formal rules without a count. Its out-of-scope list names the oracle router, the governance and timelock contracts, off-chain liquidation bots, and market listing and risk-parameter selection. Both assessments give a SHA-256 digest of every reviewed file in the appendix, so a copy of a file can be checked without trusting a repository link.
Scope does not say whether the deployed contracts were built from that commit, or anything about excluded components, even those the reviewed code depends on: Fenwick’s solvency results rely on the out-of-scope oracle router.
Dates and effort
Dates bound the snapshot: the Quillon Vaults review ran from 27 July to 7 August 2026, and nothing merged after its remediation commit is covered. Effort is stated in people and days (“two reviewers, ten working days, plus a three-day remediation review” for Quillon; “two verification engineers, fifteen working days” for Fenwick), which allows a rough intensity:
- Quillon Vaults: 1,840 nSLOC ÷ (2 × 10) reviewer-days = 92 nSLOC per reviewer-day, before the remediation review;
- Fenwick Lending: 996 nSLOC ÷ (2 × 15) engineer-days = 33.2 nSLOC per engineer-day.
There is no standard figure to compare these with, and they are not quality scores: Fenwick’s engineers wrote and proved formal properties rather than reading line by line. Use the ratio only to compare like with like.
Methodology, threat model and trust assumptions
The methodology lists how issues were looked for: for Quillon, line-by-line review by two reviewers, static analysis with manual triage, invariant fuzzing, an economic review of strategy valuation, an upgrade-path review and a remediation review; for Fenwick, twelve formal properties checked with an SMT-based prover and mutation-tested to show that each rule can fail.
A list of techniques does not show how far each one reached; the results do. Fenwick records 10 of 12 properties as proved at the remediation commit, one as holding only for bounded sequences, and one as an unproved assumption about oracle freshness. Quillon records its four fuzzed invariants as inconclusive, because it treats fuzzing as evidence, not proof. Questions specific to proofs are in our analysis of formal verification in DeFi.
The threat model names assets, actors and threats, and its trust assumptions are the lines a reader most needs, because every conclusion depends on them. Fenwick assumes fresh, positive oracle prices that are not used during sequencer downtime, an uncompromised timelocked multisig as reserve admin, and standard ERC-20 assets without transfer fees or rebasing. A market that lists a fee-on-transfer token is outside what the report examined, whatever its findings say.
Severity: impact and likelihood
A label means only what the report’s rubric says it means. The rubric on the Quantix methodology page rates impact (what an attacker gains or users lose) and likelihood (the preconditions, cost and privileges required) separately, as Low, Medium or High, and reads severity from a 3 × 3 matrix; findings without direct security impact are Informational. Each finding records both inputs, so a reader can dispute an input rather than the label.
| Impact | Low likelihood | Medium likelihood | High likelihood |
|---|---|---|---|
| High | Medium: QV-04, FL-02 | High: QV-02, FL-01 | Critical: QV-01 |
| Medium | Low: QV-07, QV-08 (and FL-05, labelled Informational) | Medium: QV-05, QV-06, FL-03 | High: QV-03 |
| Low | Low: FL-04 (and QV-09, QV-10, labelled Informational) | Low: none | Medium: none |
QV-04, a reentrancy in the withdrawal queue, has high impact but low likelihood because it needs a vault asset with transfer hooks: Medium. QV-03, a fee-recipient setter anyone can call, has medium impact and high likelihood: High. In a vault whose asset has such hooks, QV-04’s main precondition is always met, and it would arguably sit in the high-likelihood column, rated Critical. FL-05 is Informational, yet it records the assumption the solvency proofs rest on: “If the assumption fails in production, the solvency results do not apply.”
Other rubrics draw the lines elsewhere. The OWASP Risk Rating Methodology has the same shape but calls the low-impact, low-likelihood cell Note. Immunefi’s bug bounty classification is decided largely by impact: direct theft of user funds, permanent freezing of funds and protocol insolvency are Critical, and bugs that need elevated privileges may be downgraded. A Medium on one scale is not a Medium on another, and a scale that is never defined gives labels without content.
Reading a finding
Each finding has an identifier, severity, status, vulnerability class, a CWE reference where one applies and a location (QV-01: src/QuillonVault.sol:L188–L214), followed by the description, preconditions, exploit steps, impact, recommendation, fix and resolution.
Preconditions are where a finding meets a deployment. QV-02, a strategy valued at a manipulable pool spot price, requires among other things that the strategy holds a material share of vault assets: about 60% at the reviewed configuration. A later allocation changes the risk without changing a line of code. Compare each recommendation with the fix that was made; they are not always the same.
No finding can tell you what was not found. As Fenwick’s limitations put it, “The absence of a property is not evidence of safety.”
Status, remediation review and residual risk
After the review the team fixes what it decides to fix, and the reviewers check the result at a named commit. Each finding is then resolved (fixed and verified), partially resolved (mitigated, residual risk documented), acknowledged (accepted by the team with a stated rationale) or open. Quillon reports 8 of 10 findings resolved, one acknowledged, one partially resolved and none open at remediation commit a91c7e2d04b3.
Summary percentages hide those states. The remediation bar on the assessment pages counts resolved and acknowledged findings fully and partially resolved ones as half, and says so beneath the bar:
- Quillon Vaults: (8 + 1 + 0.5 × 1) ÷ 10 = 9.5 ÷ 10 = 95%;
- Fenwick Lending: (3 + 2 + 0.5 × 0) ÷ 5 = 5 ÷ 5 = 100%.
Fenwick’s 100% includes two findings whose code did not change: FL-04 was acknowledged by documenting a one-unit tolerance, and FL-05’s on-chain staleness check is “planned for the next release”. Quillon’s partially resolved item is a 24-hour timelock floor where the reviewers recommended 48 hours. The remediation review should test the fixes, not only read the diff: in the Fenwick assessment, every counterexample became a Foundry test that fails on the original commit and passes on the remediation commit.
Quillon places its residual risk in strategies added after the review, and its limitations are specific: external protocols were assumed to behave as documented, and shallower pool liquidity would change the cost of manipulation. Specific limitations are a list for the reader to check or accept. The general disclaimer that no assessment can show a system is free of vulnerabilities is true of every report, and cannot replace them.
The report on one page
| Section | What it tells you | What it does not tell you | Question to ask |
|---|---|---|---|
| Scope | Commit, files, size and exclusions | Whether that commit is deployed | Is every contract I use listed? |
| Dates and effort | Age of the snapshot and time spent | Depth on any one component | What changed after the review ended? |
| Methodology | Techniques applied | How far each one reached | Which results back each technique? |
| Threat model | Actors, threats and trust assumptions | Whether the assumptions hold in production | Do my tokens, oracles and admins fit them? |
| Severity definitions | How labels follow from impact and likelihood | How another rubric would label the issue | Are both inputs argued per finding? |
| Findings | Each defect, its exploit and its fix | What was not found | Do the preconditions apply to me? |
| Status and remediation | Which fixes were verified, at which commit | Later changes; whether accepted risks suit you | Why was each acknowledged item left? |
| Limitations and disclaimer | What was not covered or was assumed | That everything else is safe | Who covers what is listed? |
Is the audited code the code that runs?
A report covers source code at a commit; users call bytecode at an address. Four links join the two, and the report covers none of them.
- Verified source. On Etherscan, an Exact Match covers the deployed code and its constructor arguments. A Similar Match is applied automatically when the creation bytecode matches another verified contract and ignores constructor arguments, so addresses and parameters set at deployment may differ. On Sourcify, an exact match is identical byte for byte apart from libraries and immutables; a match differs only in the metadata hash.
- Compiler settings. Compare the compiler version and optimiser and EVM settings on the verified page with the build configuration at the audited commit.
- Source against commit. Diff the verified files against the remediation commit, or hash them against the report’s SHA-256 list.
- Proxies. A proxy only forwards calls; the audited logic lives in an implementation whose address ERC-1967 stores at slot
keccak256("eip1967.proxy.implementation") − 1=0x3608…2bbc. Verify the implementation, and read the slot as of the report’s date and today: a different address is an upgrade the report does not cover. Our primer on upgradeable proxies covers how upgrades fail.
The metadata hash is a fingerprint of the build. By default, solc appends to the runtime bytecode a CBOR block holding the IPFS hash of the metadata file, which records a hash of every source file and the compiler settings. A changed comment or file path changes it, and so the last bytes of the bytecode, while the executable code stays the same.
// Simplified, illustrative. Not production code.// Tail of the runtime bytecode from a solc 0.8.24 build with default settings:// a CBOR map with two entries, followed by its length. …executable code…a2 map, 2 entries64 69 70 66 73 text(4) "ipfs"58 22 bytes(34), then: 12 20 <32 bytes> IPFS hash (CIDv0) of the metadata file64 73 6f 6c 63 text(4) "solc"43 00 08 18 bytes(3) compiler version 0.8.2400 33 length of the CBOR data: 0x33 = 51 bytesThe last two bytes give the block’s length: 0x33 = 51 bytes = 1 (map header) + 5 (“ipfs”) + 36 (header and 34-byte hash) + 5 (“solc”) + 4 (header and 3-byte version). The Solidity documentation warns against relying on this layout, since the map can hold other keys: read the length and decode the block with a CBOR parser.
# Simplified, illustrative. Not production code.# Values in angle brackets and $VARIABLES stand for your own commits, addresses and endpoint. # 1. What changed in the contracts after the remediation review?git diff --stat <remediation-commit> <release-tag> -- src/ # 2. Which implementation does the proxy delegate to now, and at the date of the report?cast implementation $PROXY --rpc-url $RPC_URLcast storage $PROXY 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc \ --block <block-at-publication> --rpc-url $RPC_URL # 3. Are the verified source files the reviewed files? Compare with the SHA-256 list in the report.sha256sum <verified-source-files>Four more questions to ask
Were acknowledged findings accepted for good reasons? Acknowledging a finding is the team’s decision, not the reviewers’. A good rationale names a compensating control and says when the risk could change. QV-07, missing storage gaps in an upgradeable base contract, came with a storage-layout check in continuous integration and a planned move to namespaced storage; it matters at the next upgrade that adds state. Ask whether the planned work happened.
What changed after the audit? Diff the remediation commit against the deployed release. Quillon excludes “Strategies other than AmmLpStrategy, including those added after the review commit”: each new strategy is unreviewed code with access to depositor funds.
Were privileged roles and upgrade paths in scope? Whoever can upgrade or reconfigure a contract can change everything a report examined. Quillon’s scope includes its timelock and upgradeable base, and its methodology an upgrade-path review. Fenwick excludes the governance and timelock contracts, so its report cannot say what governance can change after deployment, or how quickly.
Is it one review or several? Reports from different firms, contests, fix reviews and later versions each cover their own commit and scope; they do not add up unless one covers the deployed commit. Line them up by commit and find that one. Within a document, check the version and history: as the technical publications page sets out, version 1.0 is the first published document and later versions record remediation re-reviews.
Red flags in a report
These describe a document, not the review behind it, but each makes a report hard or impossible to check:
- no commit hash, or only a branch name or a date;
- no list of files in scope, and no exclusions;
- every finding resolved, with no remediation commit or account of how the fixes were checked;
- severity labels without definitions, or without impact and likelihood for each finding;
- no trust assumptions, and no limitations beyond a general disclaimer.
For what the review itself should cover, see our smart contract audit checklist; the assessment catalogue lists every Quantix research assessment in the structure used here.
Conclusions
An audit report is a dated, scoped and conditional statement, and its value to a reader grows with how much of it can be checked: a commit to compare with deployed code, exclusions, trust assumptions, a defined severity scale, a status for every finding at a remediation commit, and specific limitations. With those in place, most of its claims can be tested with a block explorer and a few commands.
Most misreadings come from summary figures: a finding count, a remediation percentage, a label. Each is defined in the report, and the definition decides what it means.
Recommendations
Investors, integrators and users
- Match the report’s commit to the deployed bytecode, including the implementation behind any proxy.
- Read trust assumptions and preconditions against your own tokens, oracles, configuration and administrators.
- Treat acknowledged and partially resolved findings as open until you have read and accepted the rationale.
Protocol teams and founders
- Publish deployed addresses with the commit and report that cover each one, and update the list at every upgrade.
- Ask for a remediation review against a named commit, and record a rationale for every acknowledged finding.
- Have code added after the last report reviewed before it holds funds.
Report authors
- Define the severity scale, and record impact and likelihood with reasoning for each finding.
- State exclusions, assumptions and limitations specifically enough for a reader to act on them.
Bibliography
Primary sources: standards, official documentation, incident reports and papers.
- 1Contract metadata: encoding of the metadata hash in the bytecode(opens in a new tab)Solidity documentation
- 2Exact Match vs Match(opens in a new tab)Sourcify documentation
- 3Types of Contract Verification(opens in a new tab)Etherscan Information Center
- 4ERC-1967: Proxy Storage Slots(opens in a new tab)Ethereum Improvement Proposals
- 5Immunefi Vulnerability Severity Classification System v2.3(opens in a new tab)Immunefi
- 6OWASP Risk Rating Methodology(opens in a new tab)OWASP Foundation
Applied on this site
Assessments, case studies and tools that apply this publication.







