Unchecked external callback before balance update
F-001 · critical · Vault.withdraw()
Grounded in INV-001 (supply = Σ balances), which the exploit violates.
Reproduced on a fork. The PoC ships with the finding — criticals get a working fork exploit.
How it works
Guardix doesn't trust its own model. This is the full path from git clone to a verdict — and exactly what
makes each KEEP and each KILL something you can check, not something you have to take on
faith.
Five stages, each emitting an artifact the next one consumes. No single prompt decides anything — every claim is built up, then torn down, before it reaches the report.
Pins the exact branch and commit, then walks the import graph so only in-scope Solidity enters the pipeline — vendored libraries and tests stay out.
→ emits commit e7b2f4a · 23 files in scope
Maps contracts, inheritance, the call graph, and state and role flows; extracts the invariants the system is meant to hold, plus trust assumptions and design decisions.
→ emits INV-001…007 · 5 assumptions · 3 decisions
Several complementary detectors run in parallel — not just a checklist. Checklist agents cover the known risk classes (reentrancy, oracle and price manipulation, access control, accounting and invariant drift); specialized skill agents and a Solidity vector scan go deeper; and adversarial passes probe numeric properties and cross-contract integration. Independent AI models propose — nothing is trusted yet.
→ emits 41 candidate findings
Every candidate goes on trial: grounded against the invariants, and — for criticals — reproduced as an exploit on a mainnet fork. A finding is killed only with a cited line.
→ emits KEEP / KILL / needs_manual per finding
Verdicts, exploit proofs, and architecture artifacts are assembled into one report pinned to the commit and diffable against the last scan.
→ emits report @ e7b2f4a
02 Stage 2
Pattern matchers flag transfer() before a
state write everywhere — including the dozens of places it's safe. Guardix first extracts
what your system is supposed to guarantee,
then judges every finding against that. An invariant the code is meant to hold is a
first-class artifact in the report — and the yardstick a finding is measured by.
Invariant — extracted from code
Total supply equals the sum of balances at all times.
Threat if broken: direct loss of depositor funds.
anchored at Vault.sol:118 · _mint / _burn
Every invariant is tied to the function that establishes it — so a later verdict can point at the exact code an attack would have to violate.
Call & role flow — inter-procedural
The graph is inter-procedural and crosses contract boundaries — so a reentrant path that hops through an external callback is visible, not hidden inside one function.
7 invariants · 5 trust assumptions · 3 design decisions extracted
03 Stage 4 · Validation
A model flagging a bug is a claim, not a finding. Guardix attacks every claim from two sides: it tries to prove it real by reproducing it, and tries to prove it false by finding the line of code that defeats it. The verdict is whatever survives.
Unchecked external callback before balance update
F-001 · critical · Vault.withdraw()
Grounded in INV-001 (supply = Σ balances), which the exploit violates.
Reproduced on a fork. The PoC ships with the finding — criticals get a working fork exploit.
Oracle staleness unchecked in PriceFeed.latest()
candidate · plausible
Attack step
Uses a price older than the staleness window.
Defeated by
require(updatedAt > block.timestamp - MAX_AGE);
PriceFeed.sol:88
A kill is only valid when the validator can quote the line that defeats the exact attack step. No citation, no kill.
Keeper can grief the liquidation queue
candidate · economic
No line of code defeats it — so it can't be killed.
No deterministic exploit reproduces it — so it can't be proven.
needs_manual · stays in front of a human
When neither side wins, Guardix does not silently drop it — it's surfaced for human review.
The classes below are where the verdict mechanism is strongest — reproducible attacks and citable defenses. Where neither exists, a human still wins, and Guardix says so.
Reliably in scope
Where a manual audit still wins
Guardix is the repeatable, provable layer — run it first and on every fix, then spend the human budget where it actually pays. See the full comparison →
Each scan is pinned to a commit, so re-running after a fix proves the fix — no false closure. The verdict isn't a one-time PDF; it's re-earned every time the code moves.
−2 critical, −4 high vs previous scan
Connect a repo, pick a commit, and read the verdicts — exploit proofs, cited refutations, and architecture artifacts in one report.