Blockchain security isn't optional.
Even seasoned protocols can fall to logic flaws. The Abracadabra hack proves that batching and state resets can bypass solvency checks. Donât wait for an exploit, get your lending and router logic reviewed. Request a DeFi audit today.

Introduction to MIM Spell (Abracadabra.money)
Abracadabra.money is a decentralized lending platform that allows users to deposit interest-bearing tokens (ibTKNs) as collateral to borrow Magic Internet Money (MIM), a USD-pegged stablecoin. The recent abracadabra hack shows how composable systems that accept yield-bearing collateral can be exploited when batching and router logic contain subtle flaws. By accepting ibTKNs (such as yVault tokens) as collateral, the protocol enables users to unlock additional liquidity from yield-generating assets that would otherwise remain idle. This capital efficiency has made MIM Spell a core building block in the DeFi ecosystem, especially within our broader look at DeFi money markets, but also a complex one, where layered integrations and modular design leave room for subtle logic risks.
This is precisely why comprehensive smart contract audits from reputable firms remain fundamental, especially after incidents like the abracadabra hack, which highlight how batched transaction systems and complex collateral accounting can fail for protocols that rely on batched transaction systems, oracle-driven pricing, and collateral accounting across multiple markets.
The Third MIM Spell Incident (a short post-mortem on the abracadabra hack)
This marks the third major incident affecting MIM Spell, following two earlier exploits that collectively underscore the architectural risks of modular lending systems and the mechanics of decentralized borrowing.
While this latest event resulted in a ~$1.7 million loss, significantly smaller than the first (~$6.49M) and second (~$13M) incidents, it reveals another dimension of how state handling flaws in the Cauldron router can bypass solvency enforcement.
For context and continuity, we strongly recommend revisiting the previous breakdowns before diving into this one:
- First incident: Abracadabra Money Exploit: Turning 1 ETH into $6.49 Million
- Second incident (GMX route): Draining the Cauldron: Inside the $13M Abracadabra GMX V2 Exploit
Together, these reports illustrate how small architectural oversights, such as improper debt accounting, deferred validation, or unchecked router extension logic, can lead to severe losses when combined with high-capital composability.
Under the Hood
Abracadabra operates through a modular system built on BentoBox technology, which provides the foundation for its non-custodial vaulting and lending mechanics:
- DegenBox, a non-custodial vault that stores collateral and tracks token shares.
- Cauldrons, isolated lending markets where users can borrow MIM against specific collateral types.
- Yield strategies, optional integrations that earn returns on idle collateral within DegenBox.
Users deposit collateral into a Cauldron and borrow MIM based on a collateralization ratio determined by oracles. If collateral value drops below the liquidation threshold, liquidators can repay debt to seize collateral, maintaining solvency across markets.
This modular architecture is powerful but demanding: with multiple components interacting atomically, even a single flag mismanagement or unchecked hook can cascade through the system, as demonstrated by the sequence of MIM Spell exploits. For teams building cross-chain or routed liquidity, commissioning a blockchain bridge audit.
For those running similar deployments or analyzing EVM forks, security guidance can be found in our Solidity audits. Additionally, we at Three Sigma offer Rust/Solana audits, Move audits, and dApp frontend audits to address language and layer-specific vulnerabilities.
Architecture Overview (Where to find it)
For a detailed visualization of how Abracadabraâs components interact, Cauldrons, DegenBox, oracles, and liquidation paths, refer to the Architecture Overview included in our second exploit breakdown:
Attack Analysis
On October 4, 2025 at 12:54:23 PM UTC, an attacker exploited Abracadabra.Moneyâs Cauldron V4 contract to drain ~1,793,755 MIM (Magic Internet Money, worth about $1.79 million) in a single transaction (tx hash: 0x842aae91c89a9e5043e64af34f53dc66daf0f033ad8afbf35ef0c93f99a9e5e6
). The exploit leveraged a flaw in the Cauldron cook()
function that allowed bypassing the protocolâs final insolvency check. By bundling specific actions in one cook
call, notably a borrow action followed by a rogue action ID 0, the attacker drew out an undercollateralized loan and avoided the solvent check that would normally prevent such unauthorized borrowing. The stolen MIM was then swapped through stablecoins and converted to Ether. In total, the attacker obtained ~395 ETH from the exploit, which was promptly withdrawn to external wallets and mixed via Tornado Cash to obfuscate the trail.

Vulnerability Exploitation
The exploit is rooted in a design flaw of the Cauldron V4 cook()
implementation, which processes batched actions but fails to preserve critical state flags when an unexpected action is included. Below is a deep technical breakdown of how the attacker abused this flaw.
Misuse of cook()
Function
Abracadabraâs cook()
function lets users queue up multiple actions (like adding collateral, borrowing, repayments, etc.) to execute in sequence within one atomic transaction. Normally, if any of those actions could put the loan in danger of insolvency (e.g. borrowing or removing collateral), a flag needsSolvencyCheck
is set, and a final check runs at the end to ensure the user remains solvent. The relevant code snippet (simplified for clarity) is shown below:

In the intended logic, ACTION_BORROW
(ID 5) sets status.needsSolvencyCheck = true
whenever a loan is taken (similarly removing collateral does the same). At the end of the loop, if this flag remains true, the contract invokes a solvency check to revert any transaction that left the user undercollateralized. However, the code also allowed for additional action IDs not defined in the base contract, via an _additionalCookAction
hook in Cauldron V4, primarily to support extended features in special Cauldrons (e.g. GMX market actions). In the default implementation, any unrecognized action
falls into the final else
branch, which calls the stub _additionalCookAction
and returns a default CookStatus(false, false)
, meaning no solvency check needed. This is the critical bug: the act of handling an unknown action resets the CookStatus
struct, clearing the needsSolvencyCheck
flag that was set by the prior borrow.
The attacker took advantage of this by crafting a cook
call with an action sequence [5, 0]
, i.e. borrow then a dummy action 0.

Action 5 (ACTION_BORROW) successfully borrowed MIM to the attackerâs address and set the insolvency-check flag.

Then action 0, not a standard action, triggered the fallback logic, which wiped the CookStatus
.

In the base CauldronV4
contract _additionalCookAction
is defined but empty (no implementation).

Invoking an unimplemented virtual that returns (bytes, uint8, CookStatus)
yields default zero values in Solidity:
returnData
âbytes("")
returnValues
â0
returnStatus
âCookStatus(false, false)
status
becomes CookStatus(false, false)
, overwriting both hasAccrued
and needsSolvencyCheck
to false
.
After the loop the code checks:

Since status.needsSolvencyCheck == false
(it was reset by the returned CookStatus
), the require
is not executed and the borrowed funds remain transferred out with no post-action solvency validation.
In other words, by the time cook()
exited the loop, the contract believed no risky actions had occurred. Consequently, the final solvency check if (status.needsSolvencyCheck)
was skipped entirely, and the protocol did not revert despite the loan leaving the account deeply insolvent.
Consequence: Bypass of Insolvency Checks
By resetting the internal CookStatus
flags, the attacker bypassed Abracadabraâs core safety mechanism. Normally, the solvency check at the end of cook()
would call the price oracle and run _isSolvent
to ensure the borrowerâs collateral value still exceeds their debt. If not, the transaction would revert with âCauldron: user insolvent.â In this exploit, that check was never executed because status.needsSolvencyCheck
remained false
after the crafted action 0. The attacker effectively tricked the contract into thinking no borrow had occurred.
As a result, the attackerâs account was able to incur a large debt (nearly $300k MIM per attack wallet) with insufficient collateral, and no immediate liquidation or revert was triggered. The state was updated to record the new debt, the Cauldronâs userBorrowPart
for the attacker increased and MIM stablecoins were minted to their address, but the usual invariant enforcement was absent. The screenshot below illustrates the state change: MIM tokens are transferred out from Abracadabraâs DegenBox (vault) to the attacker, with no error thrown.

Multiple Borrow Calls and Profit Extraction
The attacker repeated this cook([5,0]) trick across multiple wallets to maximize profit while evading per-address borrow limits. Six different attacker-controlled addresses each invoked the exploit, borrowing roughly 300,000 MIM per address (summing to ~1.8 million MIM total).

After draining the Cauldron contract of liquid funds, the attacker consolidated the stolen MIM and swapped them for more stable assets and eventually ETH:
- Swap to USDC/ETH: Approximately 1.58Â million MIM was swapped for ~1.58Â million USDC, then traded for about 347 ETH (via decentralized exchanges).
- Swap to USDT/ETH: Another ~215,000 MIM was swapped for ~215,000 USDT, then traded for about 48 ETH.
These swaps utilized aggregate DEX routes to minimize slippage, converting the stolen stablecoins into a total of â395 ETH. Finally, the attacker withdrew ~395 ETH to externally owned addresses. On-chain analysis shows the ETH was funneled into Tornado Cash shortly after, breaking the link between the funds and the exploit.

All six exploit transactions occurred in the same block timeframe. The Cauldron contracts were paused immediately after the team became aware of the issue
How the Attack Could Have Been Prevented
The Abracadabra CauldronV4 exploit stemmed from a logic flaw rather than a missing access control or oracle issue. Prevention would therefore have required robust internal consistency checks and safer design patterns for batching logic within cook()
. Below are the key defensive strategies that could have prevented this incident.
1. Immutable needsSolvencyCheck
Flag
A deep design-level fix would be to make the solvency check non-resettable within a single cook()
execution.
The current implementation used:

which resets the struct entirely. Instead, updates should preserve previously set flags:

This way, once a borrow or collateral-removal action marks the transaction as risky, no subsequent operation can override that flag, even if additional actions return false.
2. Internal Solvency Validation per Action
While batching is convenient, it concentrates risk into a single post-execution check.
Introducing inline solvency checks after each borrow or collateral removal action (rather than deferring all to the end) would have eliminated the exploit path.
Example pattern:

This guarantees invariant enforcement regardless of subsequent actions, ensuring that no borrow can occur without immediate solvency validation.
However, this approach does come with trade-offs:
- It reduces flexibility for legitimate complex user operations that depend on sequencing (e.g., borrowing and adding collateral within the same transaction).
- It increases gas costs, since multiple solvency checks may trigger oracle reads and rate updates several times in one batched call.
- It limits composability, as protocols relying on multi-step âatomicâ position management may need to redesign their batching logic or implement conditional checks off-chain.
In practice, the ideal solution would balance security and flexibility, for example, enforcing inline solvency checks only on high-risk actions (borrow, withdraw, leverage), while allowing low-risk operations (repay, add collateral, accrue interest) to remain batched.
Additional Best Practices
- **Rigorous Audits:** Any change that alters state ordering or accounting semantics (e.g., non-atomic sequences, âpaperâ collateral, deferred updates) should trigger deep accounting reviews focused on debt/collateral invariants and end-of-block state.
- Invariant-Driven Testing: Add property/invariant tests (unit + integration) that assert:
- âBorrow implies solvency check must occur,â
- âStatus flags cannot be cleared after risky actions,â
- âDebt cannot increase without matching collateral constraints.â
- Behavioral Fuzzing of Action Sequences: Fuzz over permutations of action arrays and edge cases (empty actions, duplicates, unknown IDs) to detect bypass of guards or inconsistent state transitions.
Consequences of the Abracadabra Hack
- Direct financial loss: ~1,793,755 MIM (~$1.79M) was withdrawn from the protocol and converted into ETH/stablecoins, then partially moved off-protocol. This is the immediate, quantifiable loss to the protocolâs treasury/market liquidity.
The Protocolâs Response
- Contracts paused: The protocol team has paused relevant Cauldron markets/contracts to prevent further borrowing and to contain additional loss.
- No official public announcement on socials: As of the latest checks, there is no official statement posted on the protocolâs verified social media channels or website clarifying the incident, the scope, or next steps.
- What is publicly visible on-chain: The exploit transactions, token flows, and subsequent swaps are observable on block explorers and forensic tools. The protocolâs pause state (on-chain) is visible where implemented.
Frequently Asked Questions (FAQ)
1) What is MIM and how does Abracadabra use it?
MIM (Magic Internet Money) is a stablecoin minted against over-collateralized positions inside Cauldron markets. Users deposit collateral, borrow MIM, and manage health based on exchange rates and protocol parameters.
2) Why was this latest incident significant?
A logic flaw in a batched-action router allowed an attacker to bypass a final solvency check, enabling under-collateralized borrowing and rapid extraction via swaps.
3) How can protocols reduce the risk of batching/routers?
Validate action IDs strictly, enforce per-action solvency checks on risk-bearing steps, and ensure flags like needsSolvencyCheck
cannot be cleared later in the same batch.
4) Do language ecosystems matter for security?
Yes, each stack has unique pitfalls. Deep reviews like Solidity audits help catch EVM-specific sequencing bugs (e.g., batched routers, delegatecall patterns, precision loss).
5) What about non-EVM protocols?
Non-EVM chains have different memory, signer, and tx models. Targeted Rust/Solana audits focus on account model abuse, CPI boundaries, and rent/ownership checks that donât exist on the EVM.
6) And Move-based chains?
Moveâs resource semantics prevent some classes of bugs but introduce others (capabilities, module upgrades). Dedicated Move audits validate resource safety, access control, and upgrade scripts.
7) Frontend risks are real too, what should teams do?
Phishing and UX mis-signing can be as damaging as contract bugs. dApp frontend audits check wallet prompts, domain integrity, RPC/provider flows, and signing surfaces to reduce user-level compromise.
8) Where can I learn how to choose an auditor?
This overview helps non-security teams evaluate fit, scope, and methodology: What is a smart contract audit and how to choose the right security partner.
9) Are there patterns across recent DeFi incidents?
Yes, router misconfigurations, liquidation edge-cases, price-source assumptions, and unchecked âextension hooksâ recur. See Top 2024 DeFi exploits & common vulnerabilities for a digest of patterns.
10) Where else can I read about past Abracadabra incidents?
Our two earlier breakdowns:
- First incident: Abracadabra Money Exploit: Turning 1 ETH into $6.49 Million
- Second incident (GMX route): Draining the Cauldron: Inside the $13M Abracadabra GMX V2 Exploit
11) Which Cauldron was affected in this exploit?
The exploit targeted an older, low-liquidity CauldronV4 deployment, a market that had largely fallen out of active use at the time of the attack. This specific Cauldron was still live on-chain but had minimal TVL, which explains why the total loss amounted to ~$1.7 million, significantly lower than the prior $6.49M and $13M incidents.
Because the vulnerable contract remained publicly accessible yet inactive, it effectively acted as an unmonitored attack surface. Although the design flaw existed in the cook()
implementation for months, the impact was limited only by the small collateral base still deposited in that legacy Cauldron.
12) How long had the vulnerability been live?
The vulnerable Cauldron contract was deployed on February 18, 2023, at 03:37:47 PM UTC. As of October 6, 2025, that means the contract had been live for 961 days, roughly 2 years and 7 months.
During this entire period, the flawed _additionalCookAction
fallback logic remained in production, unnoticed and unpatched. Because this branch was rarely invoked in active markets, the issue stayed dormant until the attacker specifically targeted it in this legacy Cauldron deployment.
Reference: contract source / verified code, https://etherscan.io/address/0x692887E8877C6Dd31593cda44c382DB5b289B684#code
13) Why was the loss smaller compared to past incidents?
The smaller impact (~$1.7M) was primarily due to:
- The low total value locked (TVL) in the affected Cauldron.
- The isolation of markets, meaning only this specific Cauldronâs liquidity was at risk.
- The quick pause of remaining Cauldrons once the exploit was detected.
While the architectural isolation prevented cascading effects, the existence of exploitable legacy deployments underscores why even inactive contracts should be formally deprecated and paused once superseded.