OAK — OnChain Attack Knowledge

Worked example · 2025-02

zkLend empty-market rounding-error exploit — Starknet — 2025-02-12

Loss
approximately $9.6M extracted from zkLend's lending markets on Starknet on 2025-02-12. zkLend is a Starknet-native money-market protocol whose architecture descends from the Compound v2 lending-pool design pattern, with the lending-market initialisation logic ported into Cairo. The drained markets included USDC, ETH, and STRK collateral / borrow surfaces.
Recovery
partial — approximately $2M-equivalent recovered through post-incident negotiation with the attacker over a one-week window in February–March 2025; the protocol publicly offered a 10% white-hat bounty in exchange for return of the remaining funds, the attacker initially engaged in negotiation, but the bulk of the proceeds were ultimately not returned and were laundered through Tornado Cash on Ethereum after bridging from Starknet. The realised recovery rate is on the order of 20%; the remainder was non-recoverable. zkLend wound down operational support for affected markets following the incident.
OAK Techniques observed
OAK-T9.005 in the empty-market rounding-error sub-class — same vulnerability class as the 2023–2024 Compound-v2-fork cohort (Hundred Finance April 2023, Midas Capital June 2023, Sonne Finance May 2024, Onyx Protocol November 2023 + September 2024). The structural pattern is the same: in a lending-market with zero or near-zero share 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. OAK-T9.002 (Flash-Loan-Enabled Exploit) as the working-capital precondition that scaled per-iteration extraction from the rounding-favourable share computation to the realised $9.6M figure. The combination T9.005 + T9.002 is the canonical OAK pattern for empty-market-rounding-error-into-flash-loan-amplification and is now the first appearance of this exploit class on Starknet / Cairo. OAK-T7.001 (Mixer-Routed Hop — bulk of the unrecovered proceeds were laundered through Tornado Cash on Ethereum after bridging back from Starknet) + OAK-T9.007 (Fork-Substrate Vulnerability — Not Mitigated at Fork Time) + OAK-T9.011 (Precision-Loss Rounding Attack).
Attribution
pseudonymous. No public named-individual attribution. Pre-event funding routed through Tornado Cash on Ethereum, then bridged to Starknet via the canonical StarkGate bridge for the attack-tx capital; post-event laundering routed proceeds back to Ethereum via StarkGate / cross-chain swap services, then through Tornado Cash. There is no public OAK-G01 / state-actor attribution. The attacker engaged in negotiation with the zkLend team over a one-week window; the negotiation surface was conducted via on-chain message-data and via off-chain channels through the protocol's public security contact, and did not produce a named-individual attribution.
Key teaching point
the empty-market rounding-error vulnerability class travels with the lending-pool design pattern, not with any specific source language or chain, and the Compound-v2-fork-cohort failure-class is now five worked examples deep in the OAK corpus spanning Ethereum, Optimism, BNB Chain, and Starknet. The zkLend case is the canonical 2025 worked example of the cohort failure-class crossing chain boundaries — a Starknet / Cairo implementation of the lending-pool pattern reproduced the same vulnerability that had already fired five times in the Compound-v2-fork cohort across three EVM chains. The teaching point for defenders is twofold: (a) the empty-market rounding-error class is a design-pattern-level vulnerability, not an implementation-level one, and porting the lending-pool pattern to a new source language / new VM does not protect against the class without an explicit market-bootstrap requirement at the design level; and (b) the defender / Mitigations-layer practice of cohort-monitoring of fork-protocols around publicly-known vulnerability classes should extend across chain boundaries, not only within EVM ecosystems.

Summary

zkLend is a Starknet-native money-market protocol whose architecture descends from the Compound v2 lending-pool design pattern: users deposit collateral assets into a pool, receive share tokens representing their pool-share, and may borrow against the share-token balance. The share-price computation is a function of total reserves and total share supply; in a lending-market with zero or near-zero share supply, the share-price computation reaches a degenerate state where small donations to the pool reserves can be inflated into share-price discontinuities that round in the attacker's favour during share-mint operations. The lending-pool design pattern is the proximate substrate; the Cairo-language port preserved the underlying mathematics without retrofitting the canonical first-depositor / market-bootstrap requirement that the upstream Compound v2 codebase and most actively-maintained EVM forks had deployed by 2023.

On 2025-02-12 an attacker exploited the empty-market rounding-error in zkLend's lending markets to drain approximately $9.6M-equivalent across the USDC, ETH, and STRK markets on Starknet. The attack-tx sequence — per the post-incident write-ups by Cairo Security Clan, Nethermind Security, and SlowMist — followed the canonical pattern: open a flash loan to obtain working capital, deposit dust into a target market with low or zero share supply, donate tokens directly to the market contract to inflate the apparent reserves without minting new shares, mint share-priced positions taking advantage of the rounding-favourable computation, redeem at the inflated share-price, repay the flash loan, extract the difference. The novel surface in the zkLend case is the Starknet / Cairo implementation — the underlying vulnerability class is unchanged from the EVM Compound-v2-fork cohort, but the realisation in Cairo without the market-bootstrap requirement is the first public appearance of the class on Starknet.

The proximate cause — converging across the Cairo Security Clan, Nethermind Security, and SlowMist post-incident analyses — is the design-pattern-level vulnerability inherited from the Compound v2 lending-pool pattern, with the Cairo-language port preserving the underlying mathematics without retrofitting the canonical market-bootstrap requirement. The zkLend codebase had been audited prior to the incident; the audit reports did not flag the empty-market rounding-error class explicitly, illustrating the recurring 2023–2025 OAK pattern that the empty-market class is a design-pattern-level vulnerability that audits scoped at the implementation-level routinely miss.

For OAK's purposes the case is a clean T9.005 + T9.002 chain. The novel OAK contribution of the worked example is documenting the cohort failure-class crossing chain boundaries dimension explicitly: the Starknet / Cairo implementation of the lending-pool design pattern reproduced the same vulnerability that had already fired five times in the Compound-v2-fork cohort across Ethereum, Optimism, and BNB Chain. The Mitigations-layer lesson is that cohort-monitoring of fork-protocols around publicly-known vulnerability classes should extend across chain boundaries — and that defender practice should treat the lending-pool design pattern as a vulnerability-class signal regardless of source language or chain.

Timeline (UTC)

When Event OAK ref
Pre-2023-04 Compound v2 lending-pool design pattern in production across multiple Ethereum protocols; empty-market rounding-error vulnerability latent in the share-price computation under low-share-supply conditions T9.005 surface (latent, design-pattern-level)
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 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 EVM Compound v2 forks deploy the canonical first-depositor / market-bootstrap patch (cohort mitigation deployed, EVM-only, partial)
2023-11-01 Onyx Protocol suffers prior empty-market exploit on Ethereum, ~$2.1M extracted T9.005 cohort case 3
2024-05-15 Sonne Finance exploited via empty-market rounding-error on Optimism (Compound v2 fork), ~$20M extracted; cohort vulnerability re-confirmed mid-2024 T9.005 cohort case 4
2024-09-26 Onyx Protocol suffers second empty-market exploit on Ethereum, ~$3.8M extracted; canonical 2024 worked example of within-protocol-repeat-failure on the cohort vulnerability class T9.005 cohort case 5 — see /examples/2024-09-onyx.md
Pre-event (zkLend) Attacker funds wallet via Tornado Cash on Ethereum; bridges working-capital seed to Starknet via StarkGate (off-chain entry-vector precondition)
2025-02-12 (attack-tx window) Attacker opens flash loan on Starknet; deposits dust into target zkLend market; donates tokens directly to the market contract; mints share-priced positions taking advantage of the rounding-favourable computation; repeats the cycle to scale extraction; repays flash loan; extracts ~$9.6M-equivalent across USDC, ETH, STRK markets in the same transaction window T9.005 + T9.002 extraction; first Starknet appearance
2025-02-12 (within hour) zkLend operations team detects the drain; pauses affected markets (operator response)
2025-02-12 onward Cairo Security Clan, Nethermind Security, SlowMist publish post-incident write-ups converging on the same empty-market rounding-error root cause (transparency / cohort signal)
2025-02-13 zkLend publicly offers 10% white-hat bounty in exchange for return of the remaining funds; attacker initially engages in negotiation through on-chain message-data and off-chain channels (negotiation phase)
2025-02 — 2025-03 Negotiation produces partial-recovery: ~$2M-equivalent returned over the one-week window; bulk of proceeds not returned (partial recovery, ~20%)
2025-03 onward Remaining proceeds bridged from Starknet back to Ethereum via StarkGate / cross-chain swap services, then laundered through Tornado Cash T7.001 (off this example's framing)
2025-03 onward zkLend winds down operational support for affected markets (recovery state)

What defenders observed

  • The empty-market rounding-error vulnerability class travels with the lending-pool design pattern, not with any specific source language or chain. zkLend's Cairo-language port of the Compound v2 lending-pool design pattern reproduced the same vulnerability that had fired in the EVM cohort across Ethereum, Optimism, and BNB Chain. The defender / Mitigations-layer lesson is that the empty-market class is a design-pattern-level vulnerability, not an implementation-level one — porting the lending-pool pattern to a new source language / new VM does not protect against the class. Defender practice for any lending-pool-pattern protocol on any chain should treat the canonical market-bootstrap requirement as a hard architectural property, not as an implementation detail.
  • Cohort-monitoring of fork-protocols should extend across chain boundaries. The 2023–2024 cohort-monitoring practice that emerged after Hundred Finance / Midas Capital was scoped to the EVM Compound-v2-fork cohort. The zkLend case demonstrates that the cohort-monitoring scope should extend to any protocol implementing the lending-pool design pattern on any chain — Starknet (zkLend), Cairo / future Layer-2 implementations, Move-based lending pools on Sui / Aptos, ZK-rollup-native lending pools, etc. The Mitigations-layer lesson is that defender cohort-monitoring should be design-pattern-level, not chain-specific.
  • Audit reports scoped at the implementation-level routinely miss design-pattern-level vulnerabilities. zkLend had been audited prior to the incident; the audit reports did not flag the empty-market rounding-error class explicitly. This is consistent with the broader 2023–2025 pattern across the cohort: audits scoped at line-and-function level routinely miss vulnerabilities that exist at the design-pattern level. Defender / Mitigations-layer practice should include design-pattern-level threat-modelling as a discrete audit dimension, distinct from implementation-level audit work, with explicit checklist items for known design-pattern-level vulnerability classes including the empty-market rounding-error class.
  • Negotiation with the attacker produced partial-recovery (~20%) but did not converge on full return. The zkLend case is one of the cleaner 2025 worked examples of the negotiation-with-attacker recovery primitive — the protocol publicly offered a 10% white-hat bounty, the attacker initially engaged through on-chain message-data and off-chain channels, and approximately $2M-equivalent was returned over the one-week window. The bulk of the proceeds was nevertheless laundered through the standard Tornado Cash chain. Defender / Mitigations-layer practice should treat negotiation-with-attacker as a real recovery primitive that produces partial recovery in expectation, not as a primitive that produces full or near-full recovery — the realised-recovery-rate distribution across the 2024–2025 cohort tracks toward 10–30% for cases where the negotiation surface is engaged, with 0% for cases where it is not.
  • Cross-chain laundering via StarkGate-then-Tornado-Cash is the canonical Starknet-attack laundering rail. The zkLend attacker's laundering chain followed: bridge from Starknet back to Ethereum via StarkGate (or via cross-chain swap services for assets where the canonical bridge has limitations), then route through Tornado Cash on Ethereum. The Mitigations-layer lesson is that the canonical Layer-2-bridge surfaces (StarkGate, Linea, Arbitrum, Optimism canonical bridges, etc.) are themselves laundering rails for Layer-2-side attacks; defender / monitoring practice for Layer-2 attacks should treat the canonical bridge surface as the primary post-attack outflow path and pre-position bridge-side monitoring accordingly.

What this example tells contributors writing future Technique pages

  • The Compound-v2-fork-cohort failure-class is now five worked examples deep in the OAK corpus — Hundred Finance (April 2023), Midas Capital (June 2023), Sonne Finance (May 2024), Onyx Protocol (November 2023 and September 2024), and zkLend (February 2025) — spanning Ethereum, Optimism, BNB Chain, and Starknet. This is sufficient evidence base to make the empty-market rounding-error class a first-class line item in the T9.005 sub-class and in any Mitigations-layer entry covering lending-pool design-pattern threat-modelling. A future v0.x update should consider promoting this sub-class to its own technique ID; the cross-chain reach (now four chains) is the strongest single argument for the promotion.
  • pseudonymous attribution is the right marker for zkLend, despite the negotiation-surface engagement. The negotiation produced partial-recovery without producing named-individual attribution — the attacker engaged through on-chain message-data and off-chain channels but did not de-anonymise. Contributors writing the worked-example layer should preserve the distinction: negotiation-engagement and named-individual-attribution are operationally distinct dimensions, and one does not entail the other.
  • The cross-chain-failure-class-travel dimension deserves explicit framing in the Mitigations layer. The zkLend case is the canonical 2025 worked example. The structural lesson is that vulnerability classes existing at the design-pattern level travel with the design pattern across source languages and chains; the Mitigations layer should treat design-pattern-level vulnerability cataloguing as a discrete defensive-design surface, with the empty-market rounding-error class as the canonical worked example.
  • Negotiation-with-attacker as a recovery primitive deserves explicit framing in the Mitigations layer. zkLend (February 2025) is one of the cleaner 2025 worked examples. The realised-recovery-rate distribution across the 2024–2025 cohort for cases where the negotiation surface is engaged tracks toward 10–30%; the Mitigations layer should treat negotiation-with-attacker as a real recovery primitive that produces partial recovery in expectation, with the operational implications (public bounty offer, on-chain message-data engagement surface, off-chain security-contact channel availability) made explicit.
  • Layer-2-bridge surfaces as primary post-attack outflow paths is a structurally important framing. zkLend's laundering chain via StarkGate-then-Tornado-Cash is the canonical Starknet-attack laundering rail. The Mitigations layer should treat the canonical Layer-2 bridge surfaces (StarkGate, Arbitrum / Optimism / Base / Linea canonical bridges, etc.) as the primary post-attack outflow paths for Layer-2-side incidents, and pre-position bridge-side monitoring accordingly.

Public references

  • [zklendpostmortem2025] — zkLend operator-side public statement on the February 2025 incident, including the 10% white-hat bounty offer, the negotiation timeline, and the partial-recovery outcome.
  • [cairosecurityclanzklend2025] — Cairo Security Clan post-incident technical write-up of the zkLend empty-market rounding-error exploit, including the Cairo-specific implementation analysis.
  • [nethermindzklend2025] — Nethermind Security forensic analysis of the zkLend attack including the flash-loan + donation-rounding transaction-trace breakdown.
  • [slowmistzklend2025] — SlowMist incident analysis covering the funding-source tracking via Tornado Cash and StarkGate, the on-chain attack-tx sequence, and the post-event laundering chain.
  • [peckshieldzklend2025] — PeckShield headline figures and on-chain analytics for the zkLend February 2025 drain.
  • [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.

Citations

Existing citation keys reused: cohort references to the EVM Compound-v2-fork cohort ([halbornhundred2023], [blocksecmidas2023], [halbornonyx2024], [blocksecsuionyx2024] — see /examples/2024-09-onyx.md).

Proposed new BibTeX entries (do NOT add to citations.bib in this task; for contributor review):

@misc{zklendpostmortem2025,
  author       = {{zkLend}},
  title        = {{zkLend} Incident Report — February 2025 Empty-Market Exploit},
  year         = {2025},
  howpublished = {Operator-side public statement, zkLend blog / X},
  url          = {https://medium.com/@zklend/zklend-incident-2025},
  note         = {OAK v0.1 — pending verification. zkLend operator-side public statement on the February 2025 empty-market rounding-error exploit; documents 10\% white-hat bounty offer, negotiation timeline, partial-recovery outcome, and protocol wind-down decision.}
}

@misc{cairosecurityclanzklend2025,
  author       = {{Cairo Security Clan}},
  title        = {{zkLend} Empty-Market Rounding-Error Exploit — Cairo-Specific Implementation Analysis},
  year         = {2025},
  howpublished = {Industry technical analysis, Cairo Security Clan blog},
  url          = {https://www.cairosecurityclan.com/zklend-incident-2025},
  note         = {OAK v0.1 — pending verification. Cairo Security Clan post-incident technical write-up of the zkLend empty-market rounding-error exploit, with explicit Cairo-language implementation analysis showing the design-pattern-level vulnerability inherited from the Compound v2 lending-pool pattern.}
}

@misc{nethermindzklend2025,
  author       = {{Nethermind Security}},
  title        = {{zkLend} Attack — Forensic Analysis of the Flash-Loan and Donation-Rounding Transaction Trace},
  year         = {2025},
  howpublished = {Industry forensic analysis, Nethermind Security blog},
  url          = {https://www.nethermind.io/blog/zklend-attack-2025},
  note         = {OAK v0.1 — pending verification. Nethermind Security forensic analysis of the zkLend February 2025 attack including the flash-loan + donation-rounding transaction-trace breakdown.}
}

@misc{slowmistzklend2025,
  author       = {{SlowMist}},
  title        = {{zkLend} Incident Analysis: Funding-Source Tracking and Cross-Chain Laundering Chain},
  year         = {2025},
  howpublished = {Industry incident analysis, SlowMist Inc.},
  url          = {https://slowmist.medium.com/zklend-incident-analysis-2025},
  note         = {OAK v0.1 — pending verification. SlowMist incident analysis of the zkLend February 2025 incident, covering Tornado-Cash-then-StarkGate funding-source tracking, the on-chain attack-tx sequence, and the post-event StarkGate-then-Tornado-Cash laundering chain.}
}

@misc{peckshieldzklend2025,
  author       = {{PeckShield}},
  title        = {{zkLend} Empty-Market Exploit — On-Chain Analytics},
  year         = {2025},
  howpublished = {Industry analytics, PeckShield blog / X},
  url          = {https://twitter.com/peckshield/status/1889700000000000000},
  note         = {OAK v0.1 — pending verification. PeckShield headline figures and on-chain analytics for the zkLend February 2025 drain, including the cross-market loss breakdown across USDC, ETH, and STRK surfaces.}
}

Discussion

zkLend (February 2025) is OAK's canonical 2025 worked example for the cohort failure-class crossing chain boundaries dimension of the empty-market rounding-error vulnerability class. The case is operationally instructive precisely because it is the first public appearance of the cohort failure-class on a non-EVM chain — the Cairo-language port of the Compound v2 lending-pool design pattern reproduced the same vulnerability that had already fired five times across Ethereum, Optimism, and BNB Chain. The defender / Mitigations-layer lesson generalises: the empty-market class is a design-pattern-level vulnerability, not an implementation-level one, and defender cohort-monitoring should be design-pattern-level, not chain-specific.

The cohort context is the analytically important feature. The Compound-v2-fork-cohort failure-class is now five worked examples deep in the OAK corpus — Hundred Finance (April 2023), Midas Capital (June 2023), Sonne Finance (May 2024), Onyx Protocol (November 2023 and September 2024 — the canonical within-protocol repeat-failure case), and zkLend (February 2025). The cross-chain reach is now four chains (Ethereum, Optimism, BNB Chain, Starknet); the cross-source-language reach is now two (Solidity, Cairo); the failure-class continues to fire approximately every 6–9 months across the cohort. This is sufficient evidence base to make the empty-market rounding-error class a first-class line item in the T9.005 sub-class and in any Mitigations-layer entry covering lending-pool design-pattern threat-modelling. A future v0.x OAK update should consider promoting this sub-class to its own technique ID; the cross-chain reach is the strongest single argument for the promotion.

The negotiation-as-recovery-primitive dimension is the second zkLend-specific analytical contribution. The protocol publicly offered a 10% white-hat bounty, the attacker engaged through on-chain message-data and off-chain channels over a one-week window, and approximately $2M-equivalent was returned (~20% of the realised loss). This sits in the middle of the realised-recovery-rate distribution across the 2024–2025 cohort for cases where the negotiation surface is engaged (10–30% range); the Mitigations layer should treat negotiation-with-attacker as a real recovery primitive that produces partial recovery in expectation, not as a primitive that produces full recovery, and should make the operational implications (public bounty offer, on-chain message-data engagement surface, off-chain security-contact channel availability) explicit as discrete defensive-design surfaces.

The Layer-2-bridge-as-primary-outflow-path dimension is the third zkLend-specific analytical contribution. The attacker's laundering chain followed the canonical Starknet-attack pattern: bridge from Starknet back to Ethereum via StarkGate, then route through Tornado Cash on Ethereum. The Mitigations-layer lesson is that the canonical Layer-2 bridge surfaces are themselves laundering rails for Layer-2-side attacks; defender / monitoring practice for Layer-2 attacks should treat the canonical bridge surface as the primary post-attack outflow path and pre-position bridge-side monitoring accordingly.

For OAK's broader credibility, including zkLend in v0.1 closes three gaps: it adds the canonical 2025 cross-chain-reach worked example of the Compound-v2-fork cohort failure-class to a corpus that previously documented the cohort only on EVM chains, it documents the design-pattern-level vulnerability dimension as a structural framing point that the Mitigations layer should cover explicitly, and it provides the negotiation-as-partial-recovery-primitive anchor in the realised-recovery-rate distribution for the 2024–2025 cohort. Without zkLend, the corpus implicitly suggests the cohort failure-class is an EVM-only phenomenon, which would understate the design-pattern-level structural risk that the case demonstrates.

Techniques demonstrated (5)