How to Read a Smart Contract Audit Report (And What to Look For)
Most founders read audit reports wrong. They look for the 'safe' contracts and skip the parts that actually determine whether their protocol will get hacked. Here's how security researchers actually read audits.
You've raised a $3M seed round, deployed to mainnet, and now you need to get your contracts audited. The audit report comes back — 47 findings, 3 critical, 12 medium, the rest informational. You scan for the word "critical" and breathe. Green light, right?
Wrong. Here's how security researchers actually read audit reports.
The Finding Count Is Almost Irrelevant
The number of findings in an audit report tells you almost nothing useful on its own. A well-audited protocol with complex cross-contract interactions might have 60 findings that are all well-understood and mitigated. A protocol with 5 findings might have a single unmitigated reentrancy that drains all TVL.
What matters is:
Read the findings in this order: Critical → High → Medium → Low/Informational. But don't stop there.
Where to Actually Look First
1. The "Known Limitations" or "Out of Scope" Section
Every serious audit report has a section describing what's outside the scope of the audit. Read this carefully. If a finding requires exploiting something in the "out of scope" section, the auditors didn't look at it — and you might have a real problem there.
Common out-of-scope items:
If your protocol relies on an external oracle for price feeds and the oracle infrastructure is out of scope — that's your first question to the audit team.
2. The Access Control Findings
Access control is the most commonly exploited category in DeFi history. Before reading any critical findings, look for:
onlyRole modifiersmsg.senderThe question to ask: if every other finding in this report were fixed, could an unprivileged user drain funds through an access control gap?
3. The Oracle and Price Feed Section
Oracle manipulation is the single most common root cause of DeFi hacks in 2023-2025. Look for:
The pattern that gets protocols hacked: "We use Chainlink for price feeds" — but the Chainlink feed is only used for one side of the trade, while the other side uses a DEX TWAP that can be manipulated in the same block.
4. The Reentrancy Patterns
Reentrancy is the oldest vulnerability in smart contracts (The DAO, 2016) and still appears in new code. Look for:
tokensReceived hookssafeTransfer callbacksThe classic pattern: balanceOf[msg.sender] is checked AFTER an external call, allowing an attacker to drain funds in a loop. Check the Checks-Effects-Interactions pattern in every function that makes an external call.
What the Finding Severity Actually Means
Critical — Immediate action required
Funds are at direct risk. This finding must be fixed before mainnet deployment or a protocol upgrade. No exceptions.
High — Fix before production
Direct vulnerability that could lead to significant loss of funds under specific conditions. Fix before any production deployment.
Medium — Address or accept with justification
A vulnerability that could lead to moderate losses or requires specific conditions to exploit. Fix it, or document why you're accepting the risk with explicit mitigations in place.
Low/Informational — Consider fixing
Code quality, best practice deviations, or theoretical vulnerabilities with minimal exploitability.
The trap founders fall into: treating Medium findings as optional. Many of the most damaging hacks in DeFi history came from Medium-severity findings that were "accepted with justification" — and the justification was wrong.
How to Use the Finding List for Due Diligence
If you're evaluating whether to invest in or use a protocol, the finding list is just the starting point. Cross-reference it with:
A Real Example: What a Finding Looks Like When Done Right
Here's what our team considers a well-documented finding (simplified for illustration):
> Finding: Missing Oracle Staleness Check in getRate()
>
> Severity: HIGH
>
> Description: The StakedLBTCOracle.getRate() function returns lastRate without checking whether the rate has been updated recently. If the SUBMITTER_ROLE goes offline, getRate() continues returning a stale rate indefinitely.
>
> Impact: If SUBMITTER_ROLE becomes inactive due to key compromise or hardware failure, downstream lending contracts use a stale rate for collateral valuation. With a 5% price movement during staleness, the protocol accrues bad debt equal to 5% of exposed TVL.
>
> Proof of Concept: Foundry test demonstrating that getRate() returns stale rate with no revert after SUBMITTER_ROLE goes offline for 7 days.
>
> Remediation: Add require(block.timestamp - lastTimestamp <= MAX_STALENESS) check in getRate(). Emit events on every rate update for off-chain monitoring.
That's a finding you can act on. The one-line version ("missing staleness check") tells you nothing. The full version tells you exactly what the risk is, how it would play out, and how to fix it.
The Questions to Ask Before Using Any Protocol
If you can't answer all five questions affirmatively, you're taking on more risk than the audit report alone would suggest.
---
*Our team conducts smart contract security audits for protocols deploying to Ethereum, L2s, and Solana. We maintain live bug bounty pipelines across Immunefi, Cantina, and Sherlock. If you want a rigorous security review before mainnet launch, [reach out](/concierge).*