Worked example · 2023-04
Hundred Finance empty-market rounding-error exploit — Gnosis Chain — 2023-04-15
Summary
Hundred Finance was a Compound v2-fork lending protocol operating across multiple chains, with its Gnosis Chain deployment as one of several active fronts. On 2023-04-15, an attacker exploited an empty-market rounding-error in Hundred's Gnosis Chain lending-market initialisation path to drain approximately $7.4M.
The proximate cause — per Halborn, BlockSec, PeckShield, and academic post-incident write-ups, all converging on the same root-cause description — is the empty-market rounding-error pattern intrinsic to Compound v2 cToken markets in their initial-state code path. In a Compound v2 cToken market that has zero or near-zero supply, the share-price computation involves a division by total-supply-like values that, under specific donation / share-mint sequences, can be manipulated by a relatively small attacker deposit followed by a direct-token donation to the market contract. The donation inflates the apparent reserves without minting new shares; subsequent share-mint computations round in the attacker's favour by amounts that, when scaled by flash-loaned working capital, yield extraction in the millions.
The Hundred attack proceeded by (i) flash-loaning the working capital, (ii) draining most of an existing market down to near-zero supply (or finding such a market in its naturally-low-utilisation state), (iii) minting a single share at minimum quantity, (iv) donating substantial collateral directly to the cToken contract address (bypassing the mint path), (v) using the now-inflated exchange-rate to mint shares of low cost in other markets at favourable ratios, and (vi) redeeming those shares for collateral at the inflated rate, repaying the flash loan, and netting ~$7.4M.
For OAK's purposes the incident is a clean T9.005 (rounding-error sub-class) extraction with a T9.002 (flash-loan) precondition. The novel OAK contribution of the worked example is establishing the cohort: Hundred is the first publicly-disclosed appearance of the bug class against a Compound v2 fork in production at meaningful scale. The cohort lessons that subsequently inform the Midas, Onyx (Nov 2023), and Onyx (Sep 2024) cases all derive from Hundred as the disclosure moment.
Timeline (UTC)
| When | Event | OAK ref |
|---|---|---|
| Pre-event | Compound v2 fork architecture deployed across multiple protocols (Hundred Finance, Midas Capital, Onyx, others); empty-market rounding-error vulnerability latent in the initialisation path of cTokens with zero or near-zero supply | T9.005 surface (latent across cohort) |
| 2023-04-15 (attack tx window) | Attacker takes flash loan; manipulates a Hundred Gnosis Chain market to near-zero supply; mints minimum share; donates collateral directly to cToken contract; uses inflated exchange-rate to mint shares cheaply in other markets; redeems at inflated rate; repays flash loan; nets ~$7.4M | T9.005 + T9.002 extraction |
| 2023-04-15 (within hour) | Hundred Finance operations team detects the drain; pauses Gnosis Chain markets; communicates with Gnosis Chain team and forensic firms | (operator response) |
| 2023-04-15 onward | Halborn, BlockSec, PeckShield publish post-incident write-ups converging on the same empty-market rounding-error root cause; the bug class enters the public-knowledge corpus at function-and-line level | (disclosure event for cohort) |
| 2023-04 → 2023-Q3 | Compound upstream and most actively-maintained Compound v2 forks deploy the canonical "first-depositor" / market-bootstrap patch | (cohort mitigation deployed, partially) |
| 2023-06-16 | Midas Capital exploited via the same empty-market rounding-error class on BNB Chain, ~$600K extracted; cohort vulnerability re-confirmed | T9.005 cohort case 2 |
| 2023-11-01 | Onyx Protocol exploited via the same class, ~$2.1M | T9.005 cohort case 3 |
| 2024-09-26 | Onyx Protocol exploited again via the same class, ~$3.8M; canonical known-vulnerability-not-fixed case (see /examples/2024-09-onyx.md) |
T9.005 cohort case 4 |
| Continuing | Hundred operations: Gnosis Chain operations did not resume in pre-incident form; partial-coverage operations on other chains continued under altered governance posture; no public recovery of stolen proceeds | (recovery state) |
What defenders observed
- The bug class was not novel at the time of the Hundred incident in the sense of "no-one-knew-this-was-possible"; the Compound v2 codebase had been studied extensively, and rounding-error donations against share-price computations were a known family of vulnerabilities in fixed-point share systems generally. What Hundred established was the publicly-disclosed first-appearance against a Compound v2 fork in production at meaningful loss scale. The defender lesson is that generic vulnerability families remain latent across fork-protocol cohorts until a high-loss public incident converts them into actively-monitored attack surface — and that the gap between "academic-knowable" and "cohort-monitored" is the realistic working window for the defender community.
- The canonical patch was deployable within months of the disclosure. The "first-depositor" / market-bootstrap requirement (deposit a non-trivial initial mint at market deployment and lock it away from withdrawal, so that the empty-market state is unreachable as a steady-state condition) is a small, auditable change to the cToken market deployment workflow. Compound upstream and most actively-maintained forks deployed it in 2023-Q2 and 2023-Q3. The cohort failure is not in the patch's deployability or in the disclosure quality; it is in the patch-status verification across the full cohort of Compound v2 forks in production. As of the Onyx September 2024 incident, that verification was still incomplete — the canonical known-vulnerability-not-fixed outcome at cohort level.
- Flash-loaned working capital was the precondition that scaled the attack to its useful size. The per-iteration profit from a single rounding-error-favourable share-computation cycle is small. T9.002 converts the per-iteration profit into a single-transaction-window multi-million-dollar extraction. Defender monitoring focused only on the extraction Technique (T9.005) without the precondition (T9.002) misses half the structure.
- Detection latency was operator-acceptable; recovery latency was effectively infinite. Hundred paused Gnosis Chain markets within an hour of the on-chain attack window. By that time the funds were already routed toward Tornado Cash. The protocol-pause primitive on Gnosis Chain protects future drains but does not unwind completed extraction; once funds reach a public mixer in the same transaction window, on-chain recovery is structurally foreclosed.
- The attribution is pseudonymous and is the realistic attribution status for this class. Funding was routed through Tornado Cash pre-event; laundering was routed through Tornado Cash post-event; no industry forensics provider has converted the on-chain analysis into a named-individual claim.
What this example tells contributors writing future Technique pages
- T9.005 (Reentrancy and arithmetic-correctness) needs explicit sub-classification for the empty-market-rounding-error sub-class and Hundred is the canonical first-appearance reference. Canonical T9.005 reentrancy (the DAO 2016, Cream 2021) is one sub-class; the Curve-Vyper 2023 compiler-level reentrancy is another (see
/examples/2023-07-curve-vyper.md); the empty-market-rounding-error sub-class against Compound v2 forks is a third. Hundred is the v0.1 reference for the third sub-class. T9.005 contributors should distinguish these explicitly and link Hundred / Midas / Onyx as the empty-market-rounding-error cohort. - The defender-side Mitigation for the empty-market-rounding-error sub-class is cohort patch-status verification. When a high-loss public incident discloses a vulnerability class in a fork-protocol's upstream codebase, the defender-relevant Mitigation is not just "patch the upstream"; it is "enumerate every fork in production, query whether each has deployed the canonical patch, and operate a cohort-level monitoring discipline against the un-patched residual". Hundred is the disclosure moment; Midas / Onyx (Nov 2023) / Onyx (Sep 2024) are the cohort-level patch-status-verification failures. The Mitigation belongs at the Tactic-or-cross-cutting level, not at the per-Technique level, because it applies to every T9 Technique whose vulnerability is shared across a fork-protocol cohort.
- T9.002 is the precondition that makes per-unit rounding-error profits useful at scale. The Hundred, Midas, Onyx, Penpie, Beanstalk, and bZx worked examples all share the same precondition / extraction structure. Worked examples should preserve the distinction between the precondition Technique (T9.002 flash-loan working capital) and the extraction Technique (T9.005 / T9.003 / T9.004 / T9.001) rather than collapsing them.
- Cohort framing should be a contributor discipline. When a Technique fires across multiple protocols sharing an upstream codebase or a structural pattern, worked examples should explicitly cross-reference the cohort. Hundred should reference Midas and Onyx (and vice versa); the Curve-Vyper case should reference any subsequent compiler-level cases that emerge; the rescue-path-function sub-pattern of T9.004 (Platypus / Euler) should cross-reference within the cohort. This discipline strengthens the Mitigations layer's ability to argue cross-cutting Mitigations on the basis of recurring cohort-level evidence rather than per-incident anomaly.
Public references
[halbornhundred2023]— Halborn post-incident technical write-up of the Hundred Finance empty-market exploit; the canonical disclosure-quality reference for the bug class.[blocksechundred2023]— BlockSec forensic analysis of the Hundred attack including the flash-loan + donation-rounding transaction-trace breakdown.[peckshieldhundred2023]— PeckShield headline figures and on-chain analytics for the Hundred Gnosis Chain drain.[hundredpostmortem2023]— Hundred Finance operations-team post-incident statement and Gnosis Chain operations status.[blocksecmidas2023]— BlockSec forensic analysis of the June 2023 Midas Capital exploit, the second cohort case after Hundred.[zhou2023sok]— academic taxonomy classifying arithmetic-correctness as a primary DeFi vulnerability class.
Citations
[halbornhundred2023]— Halborn Hundred Finance post-mortem.[blocksechundred2023]— BlockSec Hundred forensic.[peckshieldhundred2023]— PeckShield Hundred figures.[hundredpostmortem2023]— Hundred operator post-mortem.[blocksecmidas2023]— BlockSec Midas Capital forensic.[zhou2023sok]— academic SoK classification.
Discussion
Hundred Finance is OAK's cohort-establishing reference case for the empty-market-rounding-error sub-class of T9.005 against Compound v2 forks. The cohort that subsequently emerged — Hundred (April 2023) → Midas Capital (June 2023) → Onyx (November 2023) → Onyx (September 2024) — is the v0.1 canonical case study for known-vulnerability-not-fixed operating across a fork-protocol layer rather than within a single protocol.
The structurally important feature of the cohort is the patch-deployability / patch-status-verification asymmetry. The canonical patch was small, auditable, and deployable within weeks of the Hundred disclosure; Compound upstream and most actively-maintained forks deployed it. The cohort failure is in the verification layer: the question "which Compound v2 forks in production have deployed the canonical patch" was answerable on-chain at any point from May 2023 onward, but no defender-side practice was operating with sufficient coverage to flag the un-patched residual. Onyx (November 2023) was an un-patched residual; Onyx (September 2024) was the same protocol still un-patched ten months later despite an intra-protocol prior incident.
The OAK Mitigations layer should treat the cohort failure, not the bug class, as the primary contribution of the Hundred case to the corpus. The bug class is documented; the cohort failure is the recurring pattern that worked examples in the corpus need to surface explicitly so that downstream readers internalise it as a category-level discipline rather than re-discover it incident by incident.
Two open questions remain for OAK v0.x. First, whether the empty-market-rounding-error sub-class of T9.005 warrants its own Technique ID — promoting arithmetic-correctness to first-class status — or stays within the broad T9.005 construction with sub-class footnoting. The author's lean is to revisit in v0.x once Cetus 2025 (a different arithmetic-correctness sub-class on Sui) and the Hundred-Midas-Onyx cohort are both formally cross-referenced. Second, whether cohort patch-status verification is a Mitigation or a Tactic-level capability. The author's lean is to surface it as a cross-cutting Mitigation entry with Hundred / Midas / Onyx as the canonical worked-example references and v0.x to revisit if more cohort cases accumulate.