Smart Contract Audit Harnesses

Module S11 · Course 2A · Pillar 4 — Smart Contract Security

90 min · Detect · Patch · Exploit · EVMbench · Heimdallr · Cascaded Verification

Prerequisite: S00–S10

S11.1 — The EVM Audit Architecture

A smart contract security harness operates in three modes: Detect (find), Patch (fix), Exploit (build and run PoC). EVMbench scores all three.

EVMbench: 117 curated vulnerabilities across 40 repositories. Reentrancy, integer overflow, access control, flash loan, business logic.

Why LLMs alone fail on smart contracts

Three structural failures:

Hallucination on EVM semantics — overflow wraps at 2^256, transfer = 2300 gas. Model applies Python/JS intuitions to opcode-precise semantics.
Context overflow — DeFi protocols are 5K–50K LOC across dozens of files. Compaction drops the storage var 40 files away that makes the path exploitable.
False positives — flags every external call as reentrancy. Dozens of FPs a human must refute. Harness becomes a cost center.

The harness pipeline

Static analysis (Slither, Mythril, Semgrep) → structured candidates
LLM semantic reasoning (intent + exploitability, NOT from raw source)
Vulnerability hypothesis (confidence + rationale)
Cascaded verification (eliminates false positives)
Finding output (severity, PoC ref, remediation)

The LLM's job: "is this candidate real and exploitable in context" — not "find the bug from raw source."

Heimdallr — the anchor design

92.45% · $2.31/10K LOC · 17/20

Detection rate · cost per 10K lines · real-world attacks reconstructed (post-June 2025)

Three innovations: function-level reorganization (minimize context), heuristic reasoning (scaffold for business logic), cascaded verification (eliminate FPs before they reach the auditor).

S11.2 — Business Logic Vulnerability Detection

The hardest class: logic bugs that are syntactically valid, pass all static checks, economically exploitable. Beanstalk governance attack: $182M in a single flash-loan-funded transaction. No static analyzer flags that.

Static analysis checks patterns, not intent. The bug is not in any single line — it is in the relationship between code and the protocol's intended invariants.

Invariant extraction

Read source + docs → extract "what must always be true"
Formalize each invariant → runtime assertion / prover spec
Verify: fuzzing · symbolic execution · formal proof
Violation found → LLM confirms: economically exploitable?
Flash-loan reachable = CRITICAL · requires 51% ownership = theoretical

Flash loan attack paths

A flash loan lets a borrower act as a whale for one transaction. Any protocol whose safety depends on "an attacker cannot afford to manipulate the market" is vulnerable.

Harness traces data flow: external price source → state-changing operation. Spot DEX price = manipulable. TWAP over N blocks = resistant. Flags any protocol consuming a spot price in a value-transfer path.

Context budget: Heimdallr's function-level reorganization feeds the LLM the function + its call-graph neighbors, not the entire 2,000-line contract.

S11.3 — Exploit Chain Construction

Detection without exploitation is a hypothesis. EVMbench's Exploit mode scores whether the agent can write and run a working exploit, not just identify the bug.

1. Setup
Fork mainnet, fund attacker, deploy prerequisites
2. Attack tx
Reentrancy callback / flash-loan sequence / governance vote
3. Verify
Assert balance delta, calculate $ impact at fork-block prices

Structured exploit evidence

FieldContent
tx hashExploit transaction in forked environment
block numberThe forked block — state at which exploit is valid
state before/afterStorage slots and balances
call traceInternal + external call sequence
economic impactToken amounts + dollar value at fork prices
PoC fileReproducible with forge test

A client who receives a tx trace showing 10K ETH moved cannot argue the finding is theoretical.

S11.4 — Patch Generation and Cascaded Verification

Generating a fix is harder than finding the bug. The patch must remove the vulnerability while preserving every intended behavior. Removing withdraw() "fixes" reentrancy and breaks the protocol.

Heimdallr's cascaded verification: static analysis → test suite → exploit re-run → formal verification where feasible. A finding is output only if it survives.

The four verification gates

Gate 1: Slither/Mythril — original finding gone? no new findings?
Gate 2: Test suite / property tests — all pass? (behavior preserved)
Gate 3: Exploit PoC re-run — exploit now FAILS? (attack path closed)
Gate 4: Formal verification — property holds? (where expressible)

Survives all four → verified patch → human approval gate. The harness does NOT deploy.

The patch-that-fixes-the-PoC trap

A patch that addresses the specific PoC but leaves the underlying vulnerability. PoC used 10 ETH deposit; patch rejects exactly 10 ETH deposits. PoC fails — vulnerability remains (50 ETH still exploits).

Cure: static-analysis re-check and formal verification, not just exploit re-run. The exploit re-run alone is insufficient.

What you take into S12

The audit harness is operational: three-mode architecture, invariant extraction, exploit PoCs, cascaded patch verification.

S12 covers benchmarking against EVMbench (the 92% vs 34% gap), Solana and cross-chain security, and the audit as deliverable — client-ready reports in the format top firms publish.