DEV Community

ohmygod
ohmygod

Posted on

The Makina Finance Exploit: How $280M in Flash Loans Turned a Curve Pool Oracle Into a $4M ATM

On January 20, 2026, an attacker drained approximately $4 million from Makina Finance's DUSD/USDC Curve stableswap pool in a single transaction. The weapon: $280 million in flash-loaned USDC that temporarily warped external Curve pool data feeding into Makina's internal accounting. The entire attack—from flash loan to ETH transfer—executed in one block.

This exploit is a masterclass in what happens when DeFi protocols treat external liquidity pool data as ground truth without questioning whether that truth can be rented for 12 seconds.

The Architecture That Got Exploited

Makina Finance is an on-chain yield and asset management engine. At its core, two contracts matter:

  • Machine: Tracks total Assets Under Management (AUM) and computes sharePrice for depositors
  • Caliber: Uses Merkle-verified instructions to call external Curve functions and compute positional AUM

The critical dependency: Caliber called MIM-3LP3CRV-f.calc_withdraw_one_coin() and DAI/USDC/USDT.balance() to determine how much a given position was "worth." These values fed directly into Machine's totalAUM, which determined sharePrice.

No time-weighting. No sanity bounds. No flash loan detection. Just: "ask Curve, trust the answer."

The Attack: Step by Step

Step 1: Borrow Everything

The attacker flash-loaned:

  • 160.6M USDC from Morpho
  • 119.4M USDC from Aave V2

Total: ~$280M in borrowed capital, cost: zero (repaid same transaction).

Step 2: Seed the Target Pool

Added 100M USDC to the DUSD/USDC pool, receiving LP tokens. Then swapped 10M USDC → ~9.215M DUSD. This positioned them on both sides of the pool.

Step 3: Inflate External Curve Pools

This is where it gets clever. The attacker didn't just manipulate the target pool—they manipulated the data sources that Makina used to compute AUM:

  1. Added 170M USDC to Curve's DAI/USDC/USDT 3pool, receiving LP tokens
  2. Added 30M of 3pool LP to the MIM-3LP3CRV-f pool
  3. Partially withdrew MIM tokens, deliberately skewing pool balances

Post-manipulation pool state (DAI/USDC/USDT):

  • DAI: ~34.87M
  • USDC: ~35.99M
  • USDT: ~96.65M

These distorted balances were now the "reality" that Caliber would query.

Step 4: Trigger the Accounting Update

Called accountForPosition() on Caliber. The function:

  1. Called calc_withdraw_one_coin() on MIM-3Crv → got an inflated reward value
  2. Called balance() on the 3pool → got inflated balances
  3. Computed positional AUM: ~19.36M (massively inflated)
  4. Updated Machine's totalAUM to ~67.88M
  5. sharePrice jumped from 1.011 → 1.331 (31.6% inflation in one call)

Step 5: Extract the Difference

With sharePrice artificially inflated:

  • Swapped ~9.215M DUSD → ~12.785M USDC (extracting the inflated value)
  • Removed LP tokens → received ~100.66M USDC
  • Net profit: ~4M USDC

Step 6: Unwind and Exit

Reversed all liquidity additions, repaid the $280M in flash loans, swapped profit to WETH on Uniswap V3, unwrapped to ETH, and transferred 1,299 ETH to a clean address.

Total time: one block. Total cost: gas fees.

The MEV Plot Twist

An MEV bot front-ran the attack transaction, capturing 276 ETH (~$860K) of the profit. The bot detected the manipulation opportunity in the mempool and inserted its own transaction first.

Even the attacker got attacked. The MEV bot sent its 276 ETH to a block validator, while the primary attacker kept 1,023 ETH. DeFi's food chain in action.

Root Cause Analysis

The vulnerability boils down to three compounding failures:

1. Unvalidated External Data

positional_AUM = balance * total_MIM_3Crv_reward / total_3Crv_LP_supply
Enter fullscreen mode Exit fullscreen mode

Every variable in this formula could be temporarily manipulated via flash loans. Makina treated Curve pool state as an oracle, but Curve pools aren't oracles—they're markets that can be moved by anyone with enough capital.

2. No Flash Loan Resistance

Time-Weighted Average Price (TWAP) mechanisms exist specifically to prevent single-block manipulation. Makina used instantaneous values. A simple check—comparing current block values against a moving average—would have detected the 31% sharePrice jump as anomalous.

3. Upgradeable Proxy Without Guards

The Caliber contract was upgradeable, meaning the team could have patched it. But the absence of rate limits, sanity bounds, or circuit breakers on sharePrice changes meant there was nothing to slow the attack while a human could react.

The Recovery: A DeFi Success Story

Unlike most exploits, Makina's story has a relatively happy ending:

  • 920 ETH returned by the MEV builder (under SEAL Whitehat Safe Harbor, minus 10% bounty)
  • 157.1 ETH returned by the Rocket Pool validator
  • 229,963 USDC recovered from post-exploit arbitrage
  • $3.65M+ total recovered within one week
  • 89% of users made fully whole
  • Remaining 11% covered through revenue-share restitution plan
  • Protocol resumed operations on January 26, 2026

The SEAL Safe Harbor framework proved its worth here—the MEV builder had legal cover to return funds with a bounty, rather than keeping them in legal limbo.

Defensive Patterns: How to Not Be Makina

1. Never Use Instantaneous Pool State for Accounting

// BAD: Single-block manipulable
uint256 aum = curvePool.calc_withdraw_one_coin(amount, i);

// BETTER: Time-weighted with bounds
uint256 currentValue = curvePool.calc_withdraw_one_coin(amount, i);
uint256 twapValue = _getTimeWeightedValue(poolId);
require(
    currentValue <= twapValue * 110 / 100,
    "Value deviation too high"
);
Enter fullscreen mode Exit fullscreen mode

2. Implement SharePrice Circuit Breakers

uint256 constant MAX_SHARE_PRICE_CHANGE = 500; // 5% per update

function _updateSharePrice(uint256 newPrice) internal {
    uint256 maxAllowed = lastSharePrice * (10000 + MAX_SHARE_PRICE_CHANGE) / 10000;
    require(newPrice <= maxAllowed, "SharePrice change exceeds bounds");
    lastSharePrice = newPrice;
}
Enter fullscreen mode Exit fullscreen mode

A 31% sharePrice jump in one transaction should never be possible in a stableswap pool context.

3. Flash Loan Detection

modifier noFlashLoan() {
    require(
        block.number > lastInteractionBlock[msg.sender],
        "Same-block interaction detected"
    );
    lastInteractionBlock[msg.sender] = block.number;
    _;
}
Enter fullscreen mode Exit fullscreen mode

4. Multi-Source Price Validation

Don't rely on a single Curve pool for pricing. Cross-reference with Chainlink, Uniswap TWAP, or at minimum multiple Curve pools to detect outliers.

The Bigger Picture: Oracle Trust Is DeFi's Achilles' Heel

The Makina exploit joins a long list of oracle manipulation attacks:

  • Mango Markets (2022): $116M via Pyth oracle manipulation
  • Euler Finance (2023): $197M via donation attack affecting eToken pricing
  • Venus Protocol (2026): $3.7M via THENA token price manipulation
  • YieldBlox (2026): $10.97M via oracle manipulation on Stellar

The pattern is always the same: a protocol reads external state, trusts it implicitly, and an attacker finds a way to temporarily distort that state within a single transaction.

Until DeFi protocols treat every external data source as adversarial by default—validating, bounding, time-weighting, and cross-referencing—these exploits will keep happening. The question isn't whether your oracle can be manipulated. It's whether you've made manipulation unprofitable.

Key Takeaways

  1. Flash loans turn every pool into a manipulable oracle. If your accounting depends on pool state, assume it can change by 100x in one block.
  2. SharePrice changes need bounds. A stableswap pool's sharePrice moving 31% in one transaction is pathological—detect and reject it.
  3. SEAL Safe Harbor works. Makina recovered 91% of funds partly because the MEV builder had a legal framework for returning funds.
  4. Recovery is possible with preparation. Makina's pre-exploit snapshots, quick pause mechanism, and coordinated response saved their users.
  5. The best oracle defense is defense in depth. No single check stops sophisticated attackers—layer TWAPs, bounds, flash loan detection, and multi-source validation.

The Makina exploit transaction: 0x569733b...

Want more DeFi security deep dives? Follow for weekly vulnerability analyses, audit tool comparisons, and security best practices for Solana and EVM developers.

Top comments (0)