Back to all stories
Blogs
Incident Analysis
Magic Internet Money Incident Analysis
3/27/2025
Magic Internet Money Incident Analysis

Incident Summary

On 25 March 2025, MIM Spell was exploited for 6,261.13 ETH (~$12.9M) due to a vulnerability in the integration of the RouterOrder and Cauldron contracts.

MIM1

The attacker was able to borrow funds, liquidate themselves then borrow funds again without repaying them. This was due to the liquidation process not overwriting records in RouterOrder that counted as collateral, allowing exploiter to falsely borrow additional funds after liquidation.

Key Transactions

Exploits Transactions:

There are a number of exploit transactions across two wallets, below is an example of one set of transactions.

Preparation

https://arbiscan.io/tx/0xef64da328604bca1aee4b86504dbd2f81cc0f5d7d1b80bdca7011e470c076e0e

Borrow and Create Order

https://arbiscan.io/tx/0xcdfce7234225e445f764399407f1256c52f8b75db3baf77493bb4c88c8aacfd1

Liquidate and borrow again

https://arbiscan.io/tx/0x5416a5f23af22bd1c6c92dbbdb382da681884ed2be07f5c0903ab2241

Attack Flow

Addresses

Attack wallet:

ARB: 0x51c9d0264d829a4F6d525dF2357Cd20Ea79b5049

ARB/ETH: 0xAF9e33Aa03CAaa613c3Ba4221f7EA3eE2AC38649

Attack contract: 0xf29120acd274a0c60a181a37b1ae9119fe0f1c9c

Step by Step

Preparation:

  1. The attacker set the master contract for address 0x51c9 and deposited 0.5 GM tokens into DegenBox.

Borrow and Create Order:

  1. The attacker called GmxV2CauldronV4.cook() with a sequence of actions [30,5,30,3] which equates to [CALL, BORROW, CALL, else] and functioned as follows:
  • CALL → 280 ETH was swapped for 6.66 WBTC on attack contract 0xf291.
  • BORROW → The attacker borrowed 300K MIM, with a resulting borrowPart of ~294.7 trillion (internal accounting unit).
  • CALL → The 300K MIM was transferred to 0xf291 which:
    • Swapped the MIM to 300k USDC, then to 145.2 WETH, and then to 3.44 WBTC.
    • Deposited 5 WBTC back into DegenBox and swapped 5.1 WBTC for 214.9 WETH.
  1. In the fourth action, an order was created for 0x51c9 using 5 WBTC as collateral and a small ETH fee.

This triggered a solvency check:

  • The collateral value was calculated as: 5 * $WBTC * 0.85 * $GM ≈ 335.5 trillion (internal valuation).
  • This was compared against the debt using the Cauldron formula: borrowPart * $GM * (elastic/base)

The position passed the solvency check at this stage.

MIM2

Liquidate and Borrow Extra:

  1. The attacker initiated a complex sequence by first borrowing 40K MIM and swapping it for 0.25 WBTC, then borrowing an additional 87.8K MIM.

MIM3

These actions raised the total borrowPart to over 420K units, now exceeding the collateral value (5 * $WBTC * 0.85), enabling liquidation. Note that when interacting through Cauldron, a solvency check is conducted at the end of cook() function after a series of actions and in individual action, eg. _borrow(), solvency is not required.

  1. The attacker could then liquidate their own position using the attack contract. The ‘sendValueInCollateral()’ sent all funds, 5+0.25 BTC, to the liquidator, 0xf291. But the public ‘inputAmount’ variable in 'GmxV2CauldronRouterOrder was not updated, Nor was the order effectively nullified in any other way, all other logic beside highlight deals with ‘normal’ collateral not in RouterOrder

MIM4

0xf291 proceeds to manage funds as 'swapper':

  • withdrew both the 87.8K MIM and the 5.25 WBTC, swapped 5.46 WBTC → 228.6 WETH
  • deposited 214.9 WETH then swapped 443.6 WETH → 910K USDC → 910K MIM
  • deposited 431K MIM into the system
  1. In the final phase, the attacker borrowed an extra 362K MIM and swapped it for WETH. However, because the public ‘inputAmount’ variable stored in ‘GmxV2CauldronRouterOrder' has not been updated, Cauldron still considers the Order to be worth 5 WBTC as collateral. The flawed solvency check allowed the borrow to go through, despite considerably over-leveraging.

  2. The tactic was repeated across multiple orders, enabling the attacker to drain approximately $12.9M in total.

Vulnerability

The vulnerability lies in the integration of RouterOrder and CauldronV4. The OrderAgent and RouterOrder are periphery contracts according to Abracadabra doc, Agent handles the creation and management of RouterOrder clones.

The OrderAgent.create() function creates a new order for a specific user with given parameters. It is called by the GmxV2CauldronV4 contract to set up a new order in response to user actions. RouterOrder.init() not only initializes the order but also triggers the order creation on the GMX Router.

MIM5

During the liquidation process, the ‘sendValueInCollateral()’ function sends all funds to the liquidator, in this case attack contract 0xf291, but the public ‘inputAmount’ variable stored in ‘GmxV2CauldronRouterOrder' is not updated. Nor is the order effectively nullified in any other way. All other logic besides the highlighted line deals with ‘normal’ collateral that is not in RouterOrder. As a result, the exploiter remains able to borrow an additional 85% of the value treated as collateral.

MIM6

Fund Flow

The attacker utilized three main wallets for the exploit:

  • 0xe9A4034E89608Df1731835A3Fd997fd3a82F2f39
  • 0x51c9d0264d829a4F6d525dF2357Cd20Ea79b5049
  • 0xAF9e33Aa03CAaa613c3Ba4221f7EA3eE2AC38649

Each was funded on the morning of the attack on 25 March 2025. 0xAF9e and 0xe9A4 received an initial deposit of ETH from Tornado Cash, whilst 0xe9a4 was used to fund 0x51c9.

MIM7

Funds from the exploit were aggregated into 0xAF9e immediately after then bridged from Arbitrum network to Ethereum via Stargate protocol in batches of 500 ETH.

MIM8

Once on ETH, the funds were split into 3 different wallets:

  • 0xa8f822E937C982e65b0437Ac81792a3AdA76A1ff - 1.259K ETH (~$2.6M)
  • 0x047C2a3dd1Ab4105B365685d4804fE5c440B5729 - 2.001K ETH (~$4.1M)
  • 0x018182FD7B856AeE1606D7E0AA8bca10F1Cb0b5d - 3.001K ETH (~$6.1M)

MIM9

As of 26 March the ETH remains in those wallets. The MIM team have reached out to the attacker to offer a 20% bounty, double the standard 10% offered in many exploits, in exchange for the return of the funds. If accepted, the offer would see around $10.4M returned whilst the exploiter would keep around $2.6M.

MIM10

To keep up to date on the latest incident alerts and statistics follow @certikalert on X, or read our latest analysis on certik.com.