Worked example · 2024-09
Onyx Protocol empty-market rounding exploit — Ethereum — 2024-09-26
Summary
Onyx Protocol is a Compound v2 fork operating on Ethereum, originally launched in 2022 and continuing operations through subsequent years across multiple lending markets. On 2024-09-26, an attacker exploited an empty-market rounding-error in Onyx's lending-market initialisation path to drain approximately $3.8M from Onyx's pools.
The proximate cause — per Halborn, BlockSec, and Cyfrin post-incident write-ups, all converging on the same root-cause description — is the same vulnerability class that drained Hundred Finance in April 2023 and Midas Capital in June 2023. 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 canonical patch — applied to the Compound upstream and to most actively-maintained forks after the Hundred Finance disclosure — requires a non-trivial initial mint at market deployment (often called the "first depositor" or "market bootstrap" requirement), which prevents the empty-market state from being reachable as a steady-state condition in a deployed market. Onyx's affected markets had not been retrofitted with this patch.
For OAK's purposes the incident is a clean T9.005 (arithmetic / rounding-error sub-class) extraction with a T9.002 (flash-loan) working-capital precondition. The novel OAK contribution of the worked example is not the bug class — that is already documented at Hundred Finance — but the repeat-failure framing: Onyx had been publicly alerted to the exposure, the canonical patch existed and was deployable, and the protocol nevertheless went into the September 2024 exploit window without it. This is the canonical 2024 Compound-v2-fork case for known-vulnerability-not-fixed, with Wintermute (September 2022, Profanity-vanity-address rotation) as the historical precedent in a different sub-class (off-chain key-derivation rather than on-chain rounding) but the same operational shape: a publicly-known vulnerability with a deployable fix, not deployed in time.
Timeline (UTC)
| When | Event | OAK ref |
|---|---|---|
| Pre-2023-04 | 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 | Hundred Finance exploited via empty-market rounding-error on Optimism, ~$7.4M extracted; root cause disclosed publicly within days | T9.005 cohort case 1 |
| 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-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-11-01 | Onyx Protocol suffers prior empty-market exploit, ~$2.1M extracted; protocol does not subsequently retrofit the canonical patch across all affected markets | (Onyx repeat-failure precondition) |
| 2024-09-26 (attack tx window) | Attacker funds wallet via Tornado Cash; opens flash loan; deposits dust into a target Onyx market; donates tokens directly to the cToken contract; mints / redeems share-priced positions taking advantage of the rounding-favourable computation; repays flash loan; extracts ~$3.8M in the same transaction window | T9.005 + T9.002 extraction |
| 2024-09-26 (within hour) | Onyx operations team detects the drain; pauses affected markets | (operator response) |
| 2024-09-26 onward | Halborn, BlockSec, Cyfrin, SlowMist publish post-incident write-ups converging on the same empty-market rounding-error root cause | (transparency / cohort signal) |
| Days following | Attacker laundering routes proceeds through Tornado Cash | T7.001 (off this example's framing) |
| Continuing | No public recovery; no civil-forfeiture action | (recovery state) |
What defenders observed
- The bug shape was identical to Hundred Finance and Midas Capital — same class, same patch, different fork. Onyx is a Compound v2 fork; Hundred Finance was a Compound v2 fork; Midas Capital was a Compound v2 fork. The empty-market rounding-error pattern was disclosed publicly at the function-and-line-number level after the April 2023 Hundred Finance incident, with a canonical patch documented and deployed to the upstream and to most actively-maintained forks. The September 2024 Onyx incident drained ~$3.8M against a market that had not been retrofitted with that patch. The defender lesson is not "this is a novel vulnerability" — it explicitly is not — but "the cohort-level patch-status verification did not happen for this protocol on this market."
- The repeat-failure pattern is documented within Onyx itself. The November 2023 Onyx exploit (~$2.1M) was in the same vulnerability family. The protocol's response after the November 2023 incident did not extend to comprehensive retrofit of the empty-market patch across all subsequently-deployed markets; the September 2024 incident drained a market that had been added or had remained unpatched in the interim. Within-protocol repeat-failure on the same vulnerability class — separated by ~ten months — is the strongest single-protocol signal that the protocol-level patch-management process was not effective on this surface.
- Flash-loaned working capital scaled the attack to its useful size. Without flash-loaned working capital, the per-iteration profit from the rounding-error favourable share computation would have been small. T9.002 is the precondition Technique that converts a per-unit rounding-error into a multi-million-dollar single-transaction extraction. Defender monitoring focused on the entry-vector Technique (T9.005 rounding-error) without the precondition (T9.002 flash-loan-enabled scaling) misses half the structure; the Penpie 2024 case at
/examples/2024-09-penpie.mdmakes the same precondition / extraction distinction explicit and is the directly comparable 2024 example. - Detection latency was operator-acceptable but recovery latency was effectively infinite. Onyx paused within roughly an hour of the on-chain attack window. By that time the funds were already laundered into Tornado Cash. The protocol-pause primitive on EVM mainnet 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 contrast with the Cetus incident at
/examples/2025-05-cetus.mdis instructive: on Sui, a validator-coordinated freeze was operationally available and was invoked; on Ethereum, no analogous primitive exists at scale and the protocol-pause-only response is the operational ceiling. - 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. There is no public OAK-G01 attribution. Contributors should not over-claim attribution simply because the on-chain forensics are detailed.
What this example tells contributors writing future Technique pages
- Known-vulnerability-not-fixed is a recurring OAK failure mode and should be made explicit as a cross-cutting pattern in the corpus. Onyx is the canonical 2024 worked example. The historical precedent is Wintermute (September 2022) at
/examples/2022-09-wintermute.md— vanity-address-derivation rotation that should have happened after the Profanity vulnerability disclosure, did not happen, and resulted in ~$160M loss on the off-chain key-derivation surface. The shape repeats across sub-classes: a publicly-known vulnerability with a deployable fix, plus an operational gap between disclosure and deployment in a specific operator's environment. Contributors writing the Mitigations layer should consider a cross-cutting Mitigation entry for publicly-disclosed-vulnerability cohort-monitoring that points back at Onyx (cohort patch-status verification on fork-protocols) and Wintermute (key-derivation-tooling rotation after upstream disclosure) as the canonical worked examples. - T9.005 covers more than reentrancy. The Onyx case is the canonical 2024 worked example for the precision-loss / rounding-error sub-class of T9.005. The Cetus 2025 example at
/examples/2025-05-cetus.mdis the Sui-side companion in the broader arithmetic-correctness sub-class. The two together with Penpie at/examples/2024-09-penpie.md(the 2024 reentrancy-sub-class example) span the visible T9.005 sub-classes for the 2024–2025 cohort. A future v0.x update may warrant promoting the arithmetic-correctness sub-class to its own technique ID; until then the broad construction holds. - T9.002 is the precondition that makes per-unit bug profits useful at scale. The 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 into a single classification.
- Cohort-monitoring of fork-protocols around publicly-known vulnerability classes is a discoverable defender practice, not a niche specialism. The empty-market rounding-error pattern was public knowledge from April 2023 onward. The set of Compound v2 forks in production at any time was discoverable through DefiLlama, Etherscan, and on-chain TVL analytics. The set of those forks that had deployed the canonical patch was checkable on-chain (presence or absence of a non-trivial initial mint at market deployment). The defender-side lesson the Onyx case carries is that this cohort-monitoring discipline existed in principle but was not operationalised at coverage sufficient to catch Onyx before the September 2024 incident. Contributors writing future T9.005 worked examples should treat "cohort patch-status verification" as a first-class Mitigation reference.
Public references
[onyxpostmortem2024]— Onyx Protocol post-incident statement on the September 2024 exploit, including the affected markets and the operator timeline.[halbornonyx2024]— Halborn post-incident technical write-up of the Onyx empty-market rounding-error exploit.[blocksecsuionyx2024]— BlockSec forensic analysis of the Onyx attack including the flash-loan + donation-rounding transaction-trace breakdown.[cyfrinonyx2024]— Cyfrin / Solodit post-incident technical commentary cross-referencing the Hundred Finance / Midas Capital cohort.[slowmistonyx2024]— SlowMist incident analysis covering funding-source tracking and Tornado Cash laundering.[halbornhundred2023]— Halborn post-incident write-up of the April 2023 Hundred Finance empty-market exploit, the original public root-cause for the cohort vulnerability class.[blocksecmidas2023]— BlockSec forensic analysis of the June 2023 Midas Capital exploit, the second cohort case prior to Onyx.[peckshieldonyx2024]— PeckShield headline figures and on-chain analytics for the Onyx September 2024 drain.
Discussion
Onyx is OAK's canonical 2024 case for known-vulnerability-not-fixed, paired with Wintermute (September 2022) as the historical precedent in a different sub-class. The two together illustrate the same operational shape — a publicly-known vulnerability with a deployable fix, not deployed in time, in a specific operator's environment — across the contract layer (Onyx) and the off-chain key-derivation layer (Wintermute). Contributors writing the OAK corpus should treat this as a recurring cross-cutting pattern, not as a per-incident anomaly.
The cohort framing is the analytically important feature. The empty-market rounding-error vulnerability was disclosed at function-and-line level in April 2023; the canonical patch was documented and deployed to the upstream and to most actively-maintained Compound v2 forks within months. The September 2024 Onyx incident shows that "most actively-maintained forks" was not "all forks in production with non-trivial TVL", and that no cohort-level monitoring practice was operating with sufficient coverage to flag the gap before the second Onyx incident. Improvements in this dimension since 2024 — including more aggressive proactive vulnerability-disclosure outreach by audit firms to the full cohort of forks of a given upstream — are downstream of the Onyx case and similar 2024 incidents.
The within-protocol repeat-failure dimension at Onyx is the strongest single-protocol signal in the case. The November 2023 Onyx incident ($2.1M) was already an empty-market-class exploit; the September 2024 incident ($3.8M) was the same class. Whatever the protocol's internal patch-management process produced after the November 2023 incident, it did not extend to comprehensive retrofit across all subsequently-relevant markets within the next ten months. Worked examples that capture this dimension explicitly are more useful to defender practice than examples that report only the September 2024 incident in isolation; the contributor handbook should encourage explicit within-protocol prior-incident framing in cases like this.
For OAK's broader credibility, including Onyx in v0.1 closes two gaps: it adds a 2024 Compound-v2-fork worked example to a corpus that otherwise jumps from Hundred Finance / Midas Capital (2023) to Penpie / other 2024 reentrancy cases without documenting the rounding-error sub-class continuing to fire, and it pairs with Wintermute as the cross-cutting known-vulnerability-not-fixed evidence that the OAK Mitigations layer needs to address explicitly rather than as an implicit inference from individual incidents.