OAK — OnChain Attack Knowledge

Worked example · 2024-03

Prisma Finance MigrateTroveZap delegatecall exploit — Ethereum — 2024-03-28

Loss
approximately $11.6M extracted from Prisma Finance's user troves on Ethereum on 2024-03-28. Prisma Finance is a CDP-style stablecoin protocol — a Liquity-fork architecture issuing the mkUSD stablecoin against LST collateral (wstETH, cbETH, sfrxETH, rETH). The drained surface was not a protocol-controlled treasury or AMM pool but the union of user-owned troves: the attacker used a vulnerable Zap-style helper contract to drain individual user collateral positions, with the loss distribution following the cohort of users who had interacted with the helper contract.
Recovery
partial, via on-chain message-channel negotiation. The attacker engaged with Prisma's negotiation channel post-exploit and ultimately returned a portion of the drained funds; the protocol absorbed the residual loss into its insurance / treasury mechanism. The recovery shape parallels Euler Finance 2023 at /examples/2023-03-euler-finance.md but at smaller scale and with only partial-recovery rather than full-recovery outcome.
OAK Techniques observed
OAK-T9.004 (Access-Control Misconfiguration) — primary, in the delegatecall-permission sub-class: the MigrateTroveZap helper contract executed a delegatecall against caller-supplied target / call-data without sufficiently constraining the target/call-data pair to a known-safe migration path. Because users had granted the Zap the trove-management privilege required to migrate troves on their behalf, the unconstrained delegatecall let the attacker invoke arbitrary trove-management operations against any approved user trove. OAK-T9.002 is not the primary precondition here — the exploit did not require flash-loan working capital; the working capital was the pre-existing user trove privilege graph that the Zap inherited.
Attribution
pseudonymous, with negotiation-channel engagement. No public named-individual attribution. The attacker's wallet was funded through standard mixers; post-exploit the attacker engaged with Prisma's on-chain negotiation message channel and returned a portion of funds. There is no public OAK-G01 / state-actor attribution.
Key teaching point
Zap / helper contracts that hold privileged-call status against user positions are a delegatecall-pattern T9.004 surface that needs explicit allowlist-constrained call-data validation. The Prisma case is the canonical 2024 worked example for the delegatecall-pattern access-control misconfiguration sub-class, distinct from the diamond-pattern facet sub-class (Li.Fi 2024 at /examples/2024-07-li-finance.md). The shared root-pattern across both is "a contract executes external calls with caller-supplied target/call-data, against a privileged authority context, without constraining the interaction set"; the Prisma case differs in that the privileged context is delegatecall (executing in the caller-of-Zap's storage / authority frame against trove operations) and in that the privilege graph is per-user-trove rather than per-token-approval.

Summary

Prisma Finance is a Liquity-fork CDP stablecoin protocol on Ethereum that issues mkUSD against liquid-staking-token collateral (wstETH, cbETH, sfrxETH, rETH). Its core primitive is the trove — a per-user collateralised debt position with collateral, debt, and a per-user owner that maps to the depositing wallet. To support common user workflows (migrating between collateral types, refinancing, integrating with surrounding LST flows), Prisma deploys helper / Zap contracts that operate on the user's trove on the user's behalf, given an explicit user-side privilege grant.

On 2024-03-28 an attacker exploited the MigrateTroveZap helper contract by invoking its external-call entrypoint with a target address and call-data pair that did not correspond to a legitimate migration step. The Zap executed a delegatecall against the attacker-supplied parameters; because the Zap had been granted trove-management privilege by the affected users, the delegatecall executed in a context that could perform arbitrary trove operations against those users' troves. The attacker drained collateral from approximately a dozen of the largest affected user troves, extracting ~$11.6M in aggregate.

The proximate cause — per Cyfrin, Prisma-team, and BlockSec post-incident write-ups, all converging on the same root-cause description — is that the MigrateTroveZap's external-call entrypoint did not constrain the caller-supplied target/call-data pair to a known-safe migration interaction set. The legitimate use case for the Zap was a specific migration call sequence (close source trove, open target trove, transfer collateral with adjusted accounting); the implementation accepted any target/call-data pair under the Zap's delegatecall context, with the result that the Zap inherited the same generality-of-callable-action that wallet-drainer kits achieve through phishing-induced approvals.

For OAK's purposes the case is a clean T9.004 delegatecall-pattern access-control misconfiguration. The novel OAK contribution of the worked example is documenting the delegatecall-pattern sub-class as distinct from the diamond-pattern facet sub-class at Li.Fi 2024, distinct from the canonical access-control-modifier-missing sub-class at Poly Network 2021, and as a recurring CDP-and-Zap helper-contract surface that is structurally similar to but operationally distinct from the diamond-pattern surface.

Timeline (UTC)

When Event OAK ref
Pre-event Prisma Finance deploys core protocol on Ethereum; users grant MigrateTroveZap the trove-management privilege required for the helper to operate on their troves (T9.004 surface — privileged Zap context)
Pre-event MigrateTroveZap deployed with external-call entrypoint that accepts caller-supplied target / call-data without constraining to a known-safe migration interaction set; bug latent T9.004 surface (latent)
Pre-event Attacker funds wallet via standard mixers; analyses Prisma helper-contract surface and identifies the unconstrained-delegatecall path (off-OAK pre-event observation)
2024-03-28 (attack tx window) Attacker calls MigrateTroveZap external-call entrypoint with a target address corresponding to a Prisma trove-management operation and call-data designed to extract collateral; the Zap executes delegatecall with the privilege context of an affected user trove; collateral exfiltrated to attacker-controlled wallet T9.004 extraction
2024-03-28 (window) Attacker repeats the pattern across approximately a dozen of the largest affected user troves; cumulative outflow ~$11.6M T9.004 repeat
2024-03-28 (within hours) On-chain monitoring (Cyfrin, BlockSec PhalconHQ, Prisma-team operations) flags anomalous trove operations (defender response / community detection)
2024-03-28 (within hours) Prisma operations team confirms the exploit; pauses MigrateTroveZap; protocol publishes urgent revoke-Zap-permissions guidance for users still holding active grants (operator response)
2024-03-28 onward Cyfrin, BlockSec, SlowMist publish post-incident write-ups converging on the unconstrained-delegatecall root cause (transparency / cohort signal)
2024-03-28 onward Attacker engages with Prisma's on-chain message-channel negotiation; partial-return negotiation initiated (negotiation engagement)
Days following Attacker returns a portion of drained funds via on-chain negotiation; residual loss absorbed by Prisma's insurance / treasury mechanism (partial recovery)
2024-04 onward Prisma redeploys MigrateTroveZap with explicit allowlist-constrained target/call-data pair; user-facing approval-grant flow updated (operator response)
Continuing Pseudonymous attribution; no civil-forfeiture action; no named-individual claim (recovery state)

What defenders observed

  • The bug shape was missing input validation on a delegatecall-pattern Zap entrypoint. The MigrateTroveZap accepted caller-supplied target/call-data parameters and executed delegatecall against them under the user-trove privilege context. The legitimate use case was a single specific migration sequence; the implementation generalised the call surface to any target/call-data, with the result that the Zap inherited the full set of callable actions the user trove privilege graph permitted. This is the same root-pattern as the Li.Fi 2024 facet bug at /examples/2024-07-li-finance.md — caller-supplied target/call-data without constrained interaction set — but in a delegatecall execution context rather than a diamond-facet external-call context.
  • Privileged Zap / helper contracts are a discrete T9.004 surface that audit checklists need to cover explicitly. The CDP-and-Zap pattern (a CDP protocol plus user-facing helper contracts that operate on user positions) is common across Liquity, Liquity forks (Prisma, Lybra, others), Maker, and similar protocols. The attack surface is the union of (a) the helper's privilege grant from the user — typically a position-management privilege on the user's trove / vault — and (b) the helper's own external-call entrypoint validation. When (b) is permissive, (a) becomes the loss-multiplying graph. Defender threat models for CDP-and-Zap protocols should treat helper-contract validation as a first-class audit-checklist item, not as an implementation-specific helper detail.
  • The user-grant graph was the loss-multiplying surface, structurally similar to the approval-graph at Li.Fi. Prisma users had granted trove-management privilege to MigrateTroveZap on a per-trove basis, similar to how Li.Fi users had granted unlimited token approval to the Li.Fi diamond on a per-token basis. The Prisma compromise turned the per-user-trove grant into the loss surface; the Li.Fi compromise turned the per-token approval into the loss surface. The two cases together establish a cross-cutting OAK pattern: any privileged contract that accumulates per-user grants becomes a multi-user drainer if its own validation is permissive. Worked examples for both should cross-reference the other, and the Mitigations layer for T9.004 / T4.004 should treat per-user-grant graphs as a unified surface.
  • Negotiation-channel engagement with the attacker is operationally meaningful and documented in the case. Unlike Li.Fi 2024 (no recovery) and Onyx 2024 (no recovery), the Prisma case produced a partial-recovery outcome via on-chain message-channel negotiation. The shape parallels Euler Finance 2023 at /examples/2023-03-euler-finance.md (full recovery via negotiation) but at smaller scale and with only partial-recovery outcome. Worked examples that capture the negotiation-channel-engagement dimension are more useful to defender practice than examples that report only the on-chain extraction in isolation; the contributor handbook should encourage explicit recovery-state framing.
  • Detection latency was operator-acceptable; partial-recovery latency was on the order of days, not infinite. Prisma paused within hours; user-revoke-grant guidance circulated within hours; the negotiation channel engaged within days. The contrast with the recover-nothing-via-Tornado-Cash pattern at Li.Fi 2024 and Onyx 2024 is structural: the attacker chose to engage rather than launder. Whether the choice was risk-aversion (insufficient operational obfuscation), economic-self-interest (negotiated bounty exceeding expected laundered value), or other factors is not publicly resolved; the worked-example contribution is documenting that the negotiation channel exists and is sometimes used.

What this example tells contributors writing future Technique pages

  • T9.004 covers delegatecall-pattern access-control misconfigurations as a distinct sub-class. Prisma 2024 is the canonical 2024 worked example for the delegatecall-pattern sub-class. The diamond-pattern facet sub-class at Li.Fi 2024 and the access-control-modifier-missing sub-class at Poly Network 2021 are the other two principal T9.004 sub-classes for which 2024-era worked examples exist; the T9.004 technique page should distinguish all three explicitly.
  • CDP-and-Zap protocols (Liquity, Liquity-forks, Maker, others) are a discrete cohort for cohort-monitoring purposes. The architectural pattern is shared; the per-user-trove-privilege-grant graph is shared; the helper-contract-validation surface is shared. Cohort-level monitoring of helper-contract upgrades within this cohort is a discoverable defender practice; the Prisma case is the canonical 2024 evidence that it was not yet operational at coverage sufficient to catch the MigrateTroveZap bug pre-deployment.
  • Per-user-grant graphs are a unified attack surface across approve-pattern and trove-management-privilege variants. The Mitigations layer for T9.004 / T4.004 should treat per-user-grant graphs as a unified surface, with sub-pattern documentation for the principal grant types: ERC-20 approve/setApprovalForAll, EIP-2612 permit signatures, NFT operator approvals, CDP / vault management privileges, and similar. Prisma 2024 is the canonical case for the CDP-management-privilege sub-pattern; Li.Fi 2024 is the canonical case for the unlimited-token-approval sub-pattern.
  • Negotiation-channel engagement is a recoverable-state outcome that should be reported explicitly. The OAK corpus includes recover-nothing cases (Onyx, Li.Fi), full-recovery cases (Euler Finance, Munchables), and partial-recovery cases (Prisma). Worked examples should capture the recovery-state outcome explicitly in the front-matter rather than burying it in the narrative; the corpus's value to defender practice is partly in the realistic distribution of recovery outcomes by case class.
  • Pseudonymous attribution with negotiation-channel engagement is a hybrid attribution status. The attacker is pseudonymous in the strict OAK sense (no named-individual claim, funding through mixers), but the negotiation-channel engagement establishes a communication graph the attacker chose to enter. Future contributor framing should distinguish pseudonymous-engaged from pseudonymous-laundered as operationally distinct sub-statuses with different downstream implications for forensic-cooperation availability.

Public references

  • [prismapostmortem2024] — Prisma Finance protocol-side post-incident statement covering the MigrateTroveZap exploit, partial-recovery negotiation outcome, and remediation timeline.
  • [cyfrinprisma2024] — Cyfrin / Solodit post-incident technical write-up emphasising the unconstrained-delegatecall root cause and the Zap-helper-contract audit-process implications.
  • [blocksecprisma2024] — BlockSec PhalconHQ forensic analysis of the Prisma exploit including transaction-trace breakdown of the delegatecall extraction sequence.
  • [slowmistprisma2024] — SlowMist incident analysis covering funding-source tracking and the negotiation-channel engagement pattern.
  • [rektprisma2024] — Rekt News public-facing summary framing the case as a Zap-helper delegatecall exploit with partial-return outcome.
  • [prismanegotiation2024] — On-chain message-channel negotiation transcript / Etherscan record between the Prisma operations team and the attacker.

Citations

  • [prismapostmortem2024] — Operator post-incident statement; primary source for affected-Zap identification, recovery-state outcome, and operator timeline.
  • [cyfrinprisma2024] — Forensic technical analysis; primary technical source for the unconstrained-delegatecall root cause framing.
  • [blocksecprisma2024] — Transaction-trace forensic breakdown; primary source for the per-trove drain sequence.
  • [slowmistprisma2024] — Funding-source tracking and negotiation pattern; primary source for pseudonymous-engaged attribution sub-status.
  • [rektprisma2024] — Public-facing summary; secondary source for partial-recovery framing.
  • [prismanegotiation2024] — Negotiation-channel transcript; primary source for the negotiation-engagement dimension of the case.

Discussion

Prisma Finance 2024 is OAK's canonical case for the delegatecall-pattern access-control misconfiguration sub-class of T9.004 and for the CDP-and-Zap helper-contract surface as a discrete cohort-monitoring target. The case shares structural features with the Li.Fi 2024 diamond-pattern facet exploit at /examples/2024-07-li-finance.md — caller-supplied target/call-data without constrained interaction set, in a privileged execution context, against a per-user-grant graph — but differs in the privilege-context type (delegatecall versus diamond-facet external-call) and in the grant-graph type (per-trove management privilege versus per-token approval).

The cohort framing applies to CDP-and-Zap protocols. Liquity, Prisma, Lybra, and similar Liquity-fork protocols share the architectural pattern of a CDP protocol plus user-facing helper contracts that operate on user positions. The shared property creates a shared threat surface (helper-contract-validation gaps) and a shared mitigation surface (allowlist-constrained target/call-data pairs in helper external-call entrypoints, integrated audit of helper contracts alongside core protocol audit, user-side guidance about minimising helper grant duration). The Prisma case is the canonical 2024 evidence that the cohort-level monitoring discipline was not yet operational across the cohort; subsequent helper-contract upgrades across the cohort have presumably tightened the surface but the cohort-level surveillance question is ongoing.

The negotiation-channel-engagement outcome is the analytically distinctive feature of the case. Unlike most 2024 EVM exploits, the Prisma attacker engaged with the operator's on-chain message channel and returned a portion of funds, with residual loss absorbed by the protocol's insurance / treasury mechanism. The recovery-state outcome is partial-recovery, sitting between the full-recovery shape at Euler Finance 2023 ($197M, fully returned via negotiation) and the recover-nothing shape at Li.Fi / Onyx / WOOFi 2024 (proceeds laundered via Tornado Cash, no recovery). The corpus value of capturing this outcome explicitly is documenting the realistic distribution of post-exploit attacker behaviours; not every pseudonymous attacker chooses to launder, and the cases where negotiation succeeds even partially are useful to defender practice as evidence that negotiation infrastructure (on-chain message channels, public bounty offers, civil-cooperation pathways) sometimes produces recovery outcomes that on-chain forensics-only would not.

For OAK's broader credibility, including Prisma 2024 in v0.1 closes a gap: it adds a 2024 CDP-and-Zap-cohort worked example, documents the delegatecall-pattern sub-class of T9.004 explicitly, and contributes a partial-recovery case to balance the recovery-state distribution in the 2024 examples corpus.

Techniques demonstrated (2)