## 1. What happened

**Date:** March 25, 2025 (March 26 per rekt.news publication date; the rekt.news homepage says "March 26" but web3isgoinggreat catalogues it as March 25 -- the two dates likely reflect timezone differences between the attack and the write-up).

**Chain:** Arbitrum (also referenced as Ethereum; the GMX v2 cauldrons operated across Arbitrum and Ethereum). SlowMist's hacked archive and web3isgoinggreat both list Ethereum as the chain. The cauldron contracts interacting with GMX v2 were deployed on Arbitrum; stolen funds were bridged/swapped to ETH on Ethereum mainnet.

**Amount lost:** Approximately $13M USD at the time. The attacker made off with roughly 6,262 ETH (web3isgoinggreat, SlowMist). This was the second Abracadabra exploit, following a $6.5M theft in January 2024 (DeFiLlama hacks database).

**What was taken:** Magic Internet Money (MIM) stablecoin and other assets held in Abracadabra's GMX v2 cauldrons. The attacker used flash-loaned funds to exploit a liquidation loophole, draining value from the cauldrons against collateral that no longer existed.

## 2. Root cause

The exploit was a smart-contract logic bug in Abracadabra's GMX v2 cauldron contracts. After a user's position was liquidated, the cauldron's internal accounting failed to properly invalidate or dereference the collateral record. An attacker could borrow against these already-liquidated positions -- "phantom collateral" (rekt.news) -- by manipulating the liquidation and borrowing flow within a single atomic transaction using flash loans. The liquidation reduced a position's health but did not prevent the same (now-empty) position slot from being referenced in a subsequent borrow, allowing the attacker to mint MIM against collateral that had already been seized and sold.

## 3. Pattern

**Vulnerability class:** Liquidation state-accounting desynchronization / stale state after liquidation (a form of unvalidated state transition).

In pseudocode, the vulnerable shape:

```
// A position P has collateral C and debt D.
// Liquidator calls liquidate(P). The cauldron seizes C, repays D.
// BUT the record for P is not deleted, only its fields are zeroed,
// and the borrowing path does not re-check that P.collateral > 0.

liquidate(position P):
    seize(P.collateral)
    repay(P.debt)
    // P.collateral and P.debt are set to zero but P still "exists"

borrow(position P, amount A):
    // Bug: checks P.debt + A <= limit but P.debt was reset to 0
    // after liquidation, so P.collateral (which should be 0) is
    // never validated as > 0.
    P.debt += A
    mint(A)
```

The attacker flash-loaned assets, liquidated a set of positions, then borrowed from the same (now-empty) positions against phantom collateral, repaying the flash loan and keeping the borrowed MIM.

## 4. The check that would have caught it

1. **Invariant test:** Assert an invariant that after every `liquidate()` call, a liquidated position cannot be passed to `borrow()` and return a non-zero amount. A fuzzer or formal verification tool (Certora, Echidna, Foundry invariant test) running randomized sequences of liquidate-then-borrow would surface this in seconds.

2. **Review rule:** Every state-mutating function that can empty a record (liquidate, close, repay-in-full) must also set an explicit `isActive` or `exists` flag, and every function that reads that record (borrow, addCollateral) must revert if the flag is false. The reviewer should check that there is no code path where a record reaches a zero-collateral/zero-debt state without being explicitly marked inactive.

## 5. Sources

- rekt.news: "Abracadabra - Rekt II" (March 26, 2025) -- https://rekt.news/ (home page archive via web.archive.org, March 26, 2025 snapshot). Provided the "phantom collateral" characterisation, the $13M figure, and the "liquidation loophole" framing.
- web3isgoinggreat.com: "Abracadabra loses $13 million in Magic Internet Money" (March 25, 2025) -- https://www.web3isgoinggreat.com/?id=abracadabra-exploit-2 (archived via web.archive.org, April 5, 2025 snapshot). Confirmed the flash-loan technique, the ~6,262 ETH figure, and the smart-contract-bug root cause.
- SlowMist Hacked Archive: Abracadabra Money entry -- https://hacked.slowmist.io/ (archived via web.archive.org, April 5, 2025 snapshot). Confirmed the $13M amount, flash-loan attack, and ~6,262 ETH figure.
- DeFiLlama Hacks Database: Abracadabra (January 2024 exploit entry for historical context) -- https://defillama.com/hacks (archived via web.archive.org, April 7, 2025 snapshot).

Note: Abracadabra's own post-mortem at abracadabra.money was not available via web.archive.org; it was a Vue.js single-page application whose blog content was not captured. No separate analyses from BlockSec, CertiK, Halborn, Verichains, or QuillAudits specific to this exploit were found in accessible archives. The exact technical mechanism (stale position state after liquidation) is inferred from the "phantom collateral" and "liquidation loophole" descriptions published by rekt.news, combined with the flash-loan pattern reported by web3isgoinggreat and SlowMist.
