// methodology · how to read a score · limitations

Methodology & Limitations

REVERT is a bytecode-only Tier-1 risk pre-filter — calibrated to agree with Slither's contract-level signal, but running on the unverified contracts Slither can't open — to triage which contracts a human or a Slither/Mythril stack should review first. It is a triage signal, not an audit, and it is complementary to Slither, never a replacement. This page explains exactly how the score is produced, how to read it, and — most importantly — what it does not do. If you take one thing away: treat a high score as a reason to look harder, and never treat a low score as proof of safety.

How the score is produced

  1. You submit a contract address (or raw runtime bytecode).
  2. REVERT fetches the on-chain runtime bytecode via RPC — no source code required, which is the whole point: ~95% of mainnet has no verified source.
  3. An opcode/structure feature extractor turns the bytecode into 70 hand-engineered features (control-flow, external-call patterns, arithmetic, gas/DoS indicators, …).
  4. An XGBoost classifier trained on 117,091 Slither-labelled Ethereum contracts outputs a single risk-surface / attack-surface exposure score in [0, 1] — how strongly the bytecode shape resembles the patterns Slither flags (high = review priority, low does not mean safe). Served model: XGBoost, binary any-vulnerability F1 = 0.948 (95% bootstrap CI [0.944, 0.951], B=1000) on 11,670 held-out Slither-labelled contracts — agreement-with-Slither on held-out data, not ground truth. Method submitted to ICICPE 2026 (open preprint + data).
  5. TreeSHAP attributes the score to the specific features that drove this contract — the "what drove this score" panel. These are real per-contract attributions, not a generic importance chart.

How to read the verdict

BucketMeansDo
high surface
review priority
> 0.85
The bytecode strongly matches the patterns associated with vulnerable contracts in training. A review-priority signal, not a confirmed bug — complex, audited infra (DEX routers, aggregators) also scores high. Route to manual review / deeper tools first. This is where to look, not what is broken.
elevated
0.3–0.85
Ambiguous. Mixed signals.Review if the contract matters to you.
low-risk
< 0.3
Only that no known bytecode-risk pattern fired. Not a statement that the contract is safe.Do not interpret as "safe". Audit anyway if value is at stake.
model signal ≠ contract verdict A high-surface result is the model raising its hand, not a proven exploit. Well-known, audited contracts — Uniswap routers, DEX aggregators, minimal-proxy or delegatecall-heavy patterns — score high because their bytecode looks risky (lots of external calls, complex control flow). That is a true model signal worth checking. It tells you where to look first, not what is broken.
low-risk ≠ safe Read low-risk as: "the model did not see a known bytecode risk pattern here." It says nothing about business logic, economics, or governance.

What REVERT does NOT do (limitations)

1. It reasons over bytecode shape, not business logic

It cannot evaluate oracle logic, liquidation/AMM math, access-control intent, governance, upgrade paths, MEV, or cross-contract invariants. Most large DeFi losses live in logic, which a single contract's runtime bytecode does not encode.

2. Proxy / implementation split

A proxy's own bytecode is tiny and benign-looking, so a proxy address can score low while its implementation scores high. REVERT now detects EIP-1967/1822/1167 proxies and also scans the implementation, showing a banner — but always confirm you scanned the contract that actually holds the logic. If you only scan the proxy, you can get false comfort.

3. Single-bytecode boundaries (cross-contract / proxy logic)

A boundary of the method, by design — not a bug. The Euler-related eDAI address 0xe025…D9DC scores low-risk despite figuring in the Euler incident: the exploitable condition lived in proxy-routed module logic that a single contract's runtime bytecode does not encode — no bytecode-only tool can see logic that isn't in the bytecode. We report these boundaries openly; treat low-risk on complex, proxy-routed protocols with appropriate scepticism, and lean on proxy→implementation resolution.

4. It is not a replacement for an audit

Use REVERT alongside, never instead of: proxy→implementation resolution, owner/admin/role inspection, upgradeability review, verified-source reading, transaction-history and incident lookup, and Slither / Aderyn / Foundry tests / manual review.

5. The headline metric is measured in-domain — the unverified production domain is not directly validated yet

F1 0.948 is agreement with Slither on verified contracts (the held-out set has source, so Slither can label it). The product runs on the unverified ~95%, where there is no Slither ground truth to measure against — a structural distribution shift. The signal is expected to transfer because the features are compiler/opcode-level (same solc → similar bytecode), but we do not yet publish a direct out-of-domain validation. Until we do, read the score as attack-surface / complexity triage — which our own Slither head-to-head confirms it behaves as (audited blue-chips and an exploited bridge can score alike) — rather than a calibrated vulnerability probability on unverified code. A direct out-of-domain study on later-verified contracts is on the roadmap.

Where it is genuinely useful

Privacy

The public "recent scans" feed is address-anonymized: each address is replaced with a salted, non-reversible hash before it leaves the server, so a scan never reveals which contract you looked at. Anonymous demo scans are logged without identity; signed-in scans are tied to your account for quota only. See /privacy.

Reproducibility

Paper, feature extractor, dataset reference, and the trained model are public: GitHub. The live API is documented at /api/scan (GET returns a usage reference; POST scores). Status: /status.

Questions or a sample report? Contact us.