OAK — OnChain Attack Knowledge

Worked example · 2024-07

Li.Fi cross-chain aggregator facet exploit — multi-chain — 2024-07-16

Loss
approximately $11.6M extracted from wallets that had granted unlimited token approvals to the Li.Fi diamond contract on Ethereum and Arbitrum. Li.Fi is a cross-chain DEX-and-bridge aggregator that routes user swaps across underlying liquidity venues; wallets typically pre-approve the Li.Fi diamond's underlying facets to spend specific tokens to make routing efficient, and wallets that had set unlimited approvals were the principal victim cohort. The drained set was a subset of all approved wallets — approximately 150 addresses, with a long-tail distribution and the largest single victim losing several million.
Recovery
none of material consequence on the on-chain layer. Proceeds were laundered through Tornado Cash within the days following the incident. Li.Fi paused the affected facet and revoked-approval guidance was published; users still showing unlimited approval to the affected facet at the time of the exploit were the loss-bearing population.
OAK Techniques observed
OAK-T9.004 (Access-Control Misconfiguration) — primary, in the diamond-pattern facet sub-vector: a facet of the Li.Fi diamond contract exposed an external-call entrypoint that did not validate caller-supplied call-data sufficiently, allowing an attacker to embed arbitrary external calls within the facet path. OAK-T4.004 (Allowance / Approve-Pattern Drainer) — downstream, in the pre-existing-approval-amplification sub-pattern: the diamond's facet, once compromised, could call transferFrom against any wallet that had granted unlimited approval to the diamond, effectively converting the facet bug into a drainer for the pre-existing approval graph. OAK-T7.001 (Mixer-Routed Hop — proceeds were laundered through Tornado Cash) + OAK-T9.008 (Diamond-Pattern Facet-Audit Incomplete) + OAK-T7.007 (DEX-Aggregator Routing Laundering).
Attribution
pseudonymous. No public named-individual attribution. Pre-event funding routed through Tornado Cash; post-event laundering also routed through Tornado Cash. There is no public OAK-G01 / state-actor attribution for this incident.
Key teaching point
diamond-pattern facet auditing as a discrete pre-deployment check class, plus users-with-pre-existing-unlimited-approvals as a downstream T4.004 amplification surface for any contract-side bug in an approved aggregator/router/bridge contract. The Li.Fi case is the canonical 2024 worked example for both — the bug class (a facet-level access-control gap in a diamond-pattern proxy / multi-facet contract) and the amplification mechanism (an aggregator's pre-existing approval graph turning the per-contract bug into an N-wallet drain). The structural parallel is Inferno Drainer / Wallet Drainer Kit operations at /examples/2024-10-inferno-drainer-handover.md for the user-side approval-graph attack surface generalisation; the Li.Fi case is the protocol-side companion case where the protocol's own contract — not the user's signed approval to a phishing site — is the entrypoint into the same approval graph.

Summary

Li.Fi is a cross-chain DEX-and-bridge aggregator deployed across multiple EVM chains. Its core contract uses the EIP-2535 diamond-proxy pattern: a single diamond contract delegates calls to multiple facet contracts, and each facet implements a slice of the protocol's surface (swap routing, bridge integration, fee handling, etc.). Users typically grant token approvals to the diamond contract — often unlimited approvals, to avoid per-swap re-approvals on the Li.Fi UI flow.

On 2024-07-16 an attacker exploited a missing-input-validation bug in one of the Li.Fi facets. The affected facet's external-call entrypoint accepted caller-supplied parameters that included both a target address and call-data; the facet did not constrain the target/call-data pair to a known-safe set, with the result that an attacker could embed arbitrary external calls into the facet's execution path. By embedding transferFrom(victim, attacker, amount) calls — using the diamond's own address as the spender, leveraging the pre-existing unlimited approvals — the attacker drained ~$11.6M from approximately 150 wallets that had pre-existing unlimited approvals to the Li.Fi diamond.

The proximate cause — per Cyfrin, BlockSec, and Halborn post-incident write-ups, all converging on the same root-cause description — is a missing validation step in the facet that should have constrained the caller-supplied target/call-data pair to a known-safe interaction set (e.g., known DEX-router addresses with known function selectors). The diamond pattern itself is not the bug; the bug is in a single facet's input-handling logic. But the diamond pattern materially amplifies the impact, because the bug-bearing facet inherits the diamond's spender-of-record status against the approval graph that users have built up over months of routine Li.Fi use.

For OAK's purposes the case is a clean T9.004 (access-control / input-validation misconfiguration) extraction with a T4.004 (approve-pattern drainer) downstream amplification. The novel OAK contribution of the worked example is documenting the diamond-pattern facet-auditing surface as a discrete pre-deployment check class — facets are not always covered uniformly by audit work, especially when added incrementally to an already-audited diamond, and the attack surface of a diamond is the union of its facets, not the intersection — and the pre-existing-approval-graph amplification mechanism that makes any compromise of an approved aggregator / router / bridge contract a multi-wallet drainer rather than a per-protocol single-pool drain.

Timeline (UTC)

When Event OAK ref
Pre-event Li.Fi deploys diamond contract on Ethereum and other EVM chains; users grant approvals (often unlimited) to the diamond as part of routine Li.Fi swap-routing flow; approval graph builds up over time across hundreds of thousands of wallets (T4.004 surface — pre-existing approval graph)
Pre-event Li.Fi adds / updates a facet whose external-call entrypoint accepts caller-supplied target / call-data pair without constraining the interaction set; bug latent in deployed diamond T9.004 surface (latent)
Pre-event Attacker funds wallet via Tornado Cash; analyses Li.Fi diamond and the affected facet to identify the missing-validation surface (off-OAK pre-event observation)
2024-07-16 (attack tx window) First attack tx: attacker calls the affected facet with a target address set to a victim ERC-20 token contract and call-data set to transferFrom(victim, attacker, amount); the facet executes the call as if it were a routing-step interaction; ERC-20 honours the call because the diamond is the approved spender; tokens move to attacker T9.004 + T4.004 extraction
2024-07-16 (window) Attacker repeats the pattern across approximately 150 victim wallets and multiple token contracts; cumulative outflow ~$11.6M T9.004 / T4.004 repeat
2024-07-16 (within hour) On-chain monitoring (BlockSec PhalconHQ, Hypernative, others) flags anomalous transfer patterns from the Li.Fi diamond surface (defender response / community detection)
2024-07-16 (within hour) Li.Fi operations team confirms the exploit; pauses the affected facet via the diamond's facet-management mechanism (operator response)
2024-07-16 (~hours) Li.Fi publishes public acknowledgement; user-facing communication includes urgent-revoke-approval guidance for users still holding unlimited approvals to the diamond on affected chains (operator response)
2024-07-16 onward Cyfrin, BlockSec, Halborn, SlowMist publish post-incident write-ups converging on the missing-input-validation root cause (transparency / cohort signal)
Days following Attacker laundering routes proceeds through Tornado Cash T7.001 (off this example's framing)
2024-07-17 onward Li.Fi facet patched and redeployed via the diamond's upgrade mechanism; protocol resumed (operator response)
Continuing No public recovery; no civil-forfeiture action (recovery state)

What defenders observed

  • The bug shape was missing input validation on a facet-level external-call entrypoint. The facet accepted caller-supplied parameters that defined an external call to be executed as part of the routing step, but did not constrain the target/call-data pair to a known-safe interaction set. Constrained interaction sets are the standard mitigation for this pattern: the facet should accept only target addresses from a curated allowlist (e.g., known DEX routers) and only function selectors corresponding to known-safe routing-step calls. Li.Fi's affected facet did neither at the time of the exploit. Cyfrin's post-incident write-up emphasises that this validation pattern is well-known and is a standard audit-checklist item for cross-chain aggregator / router contracts; the gap was implementation-side, not novel-vulnerability-side.
  • The diamond pattern materially amplified the impact. A standalone single-contract version of the same bug would have drained only assets actually held by the bug-bearing contract. The diamond pattern, by giving every facet the diamond's spender-of-record status against the approval graph, converted a per-contract bug into a per-wallet-with-approval drainer. The approval graph that users had built up over routine Li.Fi swap usage — typically with unlimited approvals — was the loss-multiplying surface. Defender threat models for diamond-pattern aggregators / bridges / routers should treat the approval graph as in-scope for any single-facet bug, not as a separate amplification surface that activates only under approve-pattern phishing.
  • Diamond-pattern audit coverage is not always uniform across facets. When facets are added incrementally to an already-audited diamond — a common operational pattern, since adding a new integration is typically a facet-level change — the new facet may be audited in isolation but not as part of an integrated re-audit of the full diamond. The integrated re-audit is what catches integration-level invariants like "the facet's external-call entrypoint must constrain its interaction set to be compatible with the diamond's spender-of-record status." Cyfrin's post-incident commentary flags this as the principal audit-process improvement the case suggests: incremental facet additions should trigger integrated diamond-level re-audit, not isolated facet-level audit.
  • The user-facing mitigation — revoke-unlimited-approvals — is well-known but operationally under-deployed. The defender lesson on the user side is the same lesson that the broader 2022–2024 wallet-drainer corpus has been pushing for years: setting unlimited approvals to any contract is a per-contract trust assumption, and any compromise of that contract turns into a wallet drainer against the user's full token balance for that approved token. The operational reality is that most users grant unlimited approvals to aggregators/routers/bridges because the per-swap re-approval flow is friction; the result is that the user's loss exposure to any specific aggregator / router / bridge is the user's full balance for any approved token, not the per-transaction notional. Tools like Revoke.cash that surface per-wallet approval-graph state are operationally available; user uptake is the limiting factor.
  • Detection latency was operator-acceptable; recovery latency was effectively infinite. Li.Fi paused within roughly an hour of the on-chain attack window. By that time the funds were already moving toward 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 same shape as Onyx 2024 at /examples/2024-09-onyx.md and most 2024 EVM-mainnet exploit cases.

What this example tells contributors writing future Technique pages

  • T9.004 covers diamond-pattern facet-level access-control misconfigurations as a distinct sub-class. The Li.Fi case is the canonical 2024 worked example. Diamond-pattern contracts (EIP-2535) are increasingly common on aggregators / routers / bridges; the audit and threat-modelling discipline for them is structurally different from monolithic contract auditing. T9.004 worked examples should preserve the sub-class distinction; future contributors writing the T9.004 technique page should consider a "Diamond-Pattern Facet Sub-Class" section with Li.Fi 2024 as the primary worked example.
  • T4.004 is amplified by pre-existing approval graphs and that amplification is structural, not a phishing-only phenomenon. The standard T4.004 framing is approve-pattern phishing — a user signs an approval to an attacker-controlled or attacker-impersonating contract. The Li.Fi case is the canonical OAK example that the same approval-graph amplification mechanism activates when a legitimate contract — to which the user has granted approval in good faith — is compromised. The user's loss exposure is the same in both cases: the full balance of approved tokens. Worked examples for T4.004 should make the legitimate-contract-compromise sub-pattern explicit alongside the phishing-driven sub-pattern. Tools and Mitigations entries that surface per-wallet approval-graph state (Revoke.cash, wallet-side approval dashboards) should be cross-referenced under both.
  • Pre-deployment audit checklists for aggregators / routers / bridges should include a "facet interaction-set constraint" item. The Li.Fi affected facet's specific gap — accepting caller-supplied target/call-data without constraining to a known-safe interaction set — is a standard pattern that audit firms have well-documented checklists for. The case is not "a novel bug class auditors had not seen"; it is "a known bug class that the specific audit pass on the specific facet did not catch under the operational pattern of incremental facet addition." The Mitigations layer should treat this as an audit-process surface, not as a code-pattern surface.
  • Pseudonymous attribution is the realistic attribution status for this class. No FBI / Treasury attribution applies; no industry forensics provider has converted on-chain analysis into a named-individual claim; the incident is pseudonymous in OAK terms. Contributors writing the worked-example layer should not over-claim attribution simply because the on-chain forensics are detailed.
  • The structural parallel with wallet-drainer-kit operations is real but distinct. The Inferno Drainer 2024 handover at /examples/2024-10-inferno-drainer-handover.md is the canonical user-side approval-graph attack-surface example; the Li.Fi case is the protocol-side companion. The two together delineate the corpus's understanding of "approval-graph attacks" across the entry-vector dimension: phishing-induced signature (Inferno Drainer surface) versus protocol-side compromise (Li.Fi surface). Contributors writing future T4.004 worked examples should preserve the sub-vector distinction.

Public references

  • [lifipostmortem2024] — Li.Fi protocol-side post-incident statement covering the affected facet, the patch, and user-facing revoke-approval guidance.
  • [cyfrinlifi2024] — Cyfrin / Solodit post-incident technical write-up emphasising the missing-input-validation root cause and the diamond-pattern facet-audit-process implications.
  • [blocksecsuilifi2024] — BlockSec PhalconHQ / forensic analysis of the Li.Fi attack including the transaction-trace breakdown of the embedded transferFrom calls.
  • [halbornlifi2024] — Halborn post-incident technical analysis of the Li.Fi exploit including the affected-facet identification.
  • [slowmistlifi2024] — SlowMist incident analysis including funding-source tracking and Tornado Cash laundering pattern.
  • [peckshieldlifi2024] — PeckShield headline figures and on-chain analytics for the Li.Fi 2024 drain (~150 victim addresses, ~$11.6M).
  • [rektlifi2024] — Rekt News public-facing summary framing the case as a diamond-pattern facet exploit.
  • [trailofbitsdiamond2023] for the diamond-pattern audit-process technical foundations referenced by Cyfrin's analysis.

Discussion

Li.Fi 2024 is OAK's canonical case for the diamond-pattern facet-level access-control sub-class of T9.004 and the legitimate-contract-compromise amplification sub-pattern of T4.004. The case sits at the intersection of two structurally distinct OAK Techniques and is the cleanest 2024 worked example for both intersections.

The diamond-pattern dimension deserves particular contributor attention. EIP-2535 diamonds are increasingly common across cross-chain aggregators (Li.Fi, Socket, others), bridge protocols, and complex DeFi primitives. The pattern's core property — a single contract address delegating to multiple facets — has structural advantages (modular upgrades, smaller per-deployment bytecode, integrated multi-facet workflows) that account for its adoption. The corresponding security property is that the diamond's surface area is the union of its facets, not the intersection: any access-control gap in any facet is reachable through the diamond's external interface, and any spender-of-record privilege the diamond holds is available to any facet's execution path. Audit firms working on diamonds need to apply integrated diamond-level threat modelling in addition to per-facet code review; the Li.Fi case is the 2024 evidence that the integrated discipline was not yet uniform across the audit ecosystem.

The approval-graph dimension generalises beyond Li.Fi. Any aggregator / router / bridge / DeFi-money-Lego protocol that accumulates unlimited approvals over months of routine user interaction inherits a structural property: a compromise of the approved contract becomes a multi-wallet drainer rather than a single-pool drain. The operational ecosystem-level mitigations are well-known: Revoke.cash for user-side approval-graph hygiene, Permit2 (where applicable) for time-bounded approvals, and per-protocol approval-budget guidance. The Li.Fi case is not novel evidence for the existence of this surface — wallet-drainer-kit cases have been demonstrating it for years — but it is the cleanest 2024 protocol-side worked example, where the entrypoint is a legitimate contract bug rather than a phishing-induced user signature.

The structural parallel and distinction with Inferno Drainer / Wallet Drainer Kit operations at /examples/2024-10-inferno-drainer-handover.md is the corpus-level framing point. Inferno Drainer represents the user-side approval-graph attack surface — phishing pages that solicit approve-pattern signatures from victims via fake mints, fake airdrops, fake protocol UIs. Li.Fi represents the protocol-side approval-graph attack surface — a legitimate aggregator's contract bug becoming the entrypoint into the approval graph the protocol has accumulated. The two cases together delineate the OAK approval-graph attack-surface taxonomy: same loss mechanism (T4.004 approve-pattern drainer activates against user wallets), different entry vector (T6 / T11 phishing-style versus T9.004 protocol-contract bug). Worked examples for either should cross-reference the other.

For OAK's broader credibility, including Li.Fi 2024 in v0.1 closes two gaps: it adds a 2024 cross-chain-aggregator worked example to a corpus that otherwise emphasises lending / AMM / bridge incidents, and it documents the diamond-pattern-facet-auditing surface as a discrete Mitigation-relevant audit-process surface that the 2024–2025 contributor layer should treat explicitly rather than implicitly.

Techniques demonstrated (5)