Worked example · 2022-20
Smart-Contract Architecture Exploit Cohort — 2022–2025
Summary
Timeline
T9.008 from ~2022-07 (Li.Fi v1) to 2024-07 (Li.Fi ~$10M); T9.009 from 2023 onward (post-UUPS/transparent-proxy proliferation); T9.010 from 2022 (class characterised; Market.xyz on QuickSwap, October 2022 canonical anchor).
T9.008 — Diamond-Pattern Facet-Audit Incomplete
The diamond proxy (EIP-2535) pattern's multi-facet architecture creates a structural audit-scope gap: an audit of Facets A, B, C does not cover Facet D added post-audit. The audited facets match their audited bytecode; the gap is the unaudited facets.
Canonical case: Li.Fi — July 2024 — ~$10M. A post-audit facet addition (a new bridge integration facet) introduced a call-verification gap. The diamond's existing facets had been audited; the newly added facet was not covered by the audit scope. The audit claim was truthful about the audited facets but misleading about the diamond's overall security posture. Earlier Li.Fi exploit (March 2022, ~$600K) was also a diamond-pattern facet-addition vulnerability.
Two sub-patterns:
- Post-audit facet addition introduces exploit surface. New facet holds treasury-routing, fee-extraction, or upgrade-authority functionality.
- Facet-selector collision. Post-audit facet shadows an audited facet's function selectors, redirecting calls to unaudited logic.
T9.009 — Cross-Contract Reinitialization Attack
The attacker triggers the initialisation function of a target contract via a callback from a peer contract, exploiting the absence of reinitialisation guards across the cross-contract boundary. The target contract's initializer modifier sets a storage flag after the first successful initialisation — but the flag is set at the end of the initialiser's execution, not before external calls made during initialisation.
The structural parallel to T9.005 (Reentrancy): in T9.005, the defence is checks-effects-interactions; in T9.009, the defence is initialise-then-interact — performing all external calls after the initialisation state flag has been set.
The attack is a specific failure of the UUPS/Transparent proxy initialisation discipline but generalises to any contract with a once-only initialisation path that makes external calls before setting the "already initialised" flag.
T9.010 — Read-Only Reentrancy
The attacker re-enters a view/pure function on a target contract while the target is mid-execution, reading state that is temporarily inconsistent. The re-entry is a staticcall (EVM-enforced as read-only), and no state is double-spent on the target — the loss is realised on a third protocol that consumes the stale view-function output for pricing, accounting, or liquidation decisions.
Canonical case: Market.xyz — QuickSwap (Polygon), October 2022. Market.xyz priced Curve LP-token collateral via get_virtual_price() — a view function. Curve's remove_liquidity transfers a native asset to the caller before settling the pool's accounting, so during that callback get_virtual_price() returns an inflated value; the attacker re-entered Market.xyz's borrow path in that window and extended a loan against inflated collateral (~$220K, flash-loan-funded). The Curve pool itself lost nothing; Market.xyz lost the loan principal. See examples/2022-10-market-xyz-curve-lp-oracle-read-only-reentrancy.md. (Distinct from the July 2023 Curve/Vyper compiler-lock event, whose primary losses were direct-drain reentrancy — T9.005 — and did not involve Market.xyz.)
Additional cases: Cygnus Finance — March 2024 — read-only reentrancy in DeFi lending via Balancer LP integration. See examples/2024-03-cygnus-finance-read-only-reentrancy.md.
The T9.005 mitigation (checks-effects-interactions + ReentrancyGuard) does not close T9.010 because ReentrancyGuard does not block staticcall to view functions. The mitigation is at the consumer-protocol layer: only read view functions from target contracts whose outermost call frames have returned in the current transaction.
Public references
[lifi2024july]— Li.Fi July 2024 post-mortem (~$10M diamond facet exploit)[lifi2022march]— Li.Fi March 2022 post-mortem (~$600K diamond facet exploit)[eip2535]— EIP-2535 Diamond Proxy standard[openzeppelininitializable]— OpenZeppelin Initializable contract andinitializermodifier[curvevyper2023]— Curve Finance Vyper compiler reentrancy incident (July 2023)[quillauditsmarketxyz2022]— Market.xyz (QuickSwap / Polygon) Curve LP-oracle read-only reentrancy, October 2022, ~$220K (seeexamples/2022-10-market-xyz-curve-lp-oracle-read-only-reentrancy.md)[cygnus2024]— Cygnus Finance read-only reentrancy (March 2024)