Nereus Oracle Overborrow
Exploit Transactions
0x0ab12913f9232b27b0664cd2d50e482ad6aa896aeb811b53081712f42d54c026Victim Addresses
0xC0A7a7F141b6A5Bce3EC1B81823c8AFA456B6930Avalanche0xf955a6694C6F5629f5Ecd514094B3bd450b59000AvalancheLoss Breakdown
Similar Incidents
SuperTokenV2 share inflation
36%Platypus LP Cross-Asset Mispricing
32%MuBank Bond Manipulation
32%Sentiment Balancer Oracle Overborrow
31%Platypus Stale Collateral Withdrawal
30%Platypus PoolSAvax JIT LP Exploit
30%Root Cause Analysis
Nereus Oracle Overborrow
1. Incident Overview TL;DR
An unprivileged adversary exploited Nereus Finance on Avalanche in transaction 0x0ab12913f9232b27b0664cd2d50e482ad6aa896aeb811b53081712f42d54c026 by flash-loaning 51,000,000 USDC.e, manipulating the Trader Joe WAVAX-USDC JLP state, refreshing the Nereus collateral oracle at the manipulated state, borrowing 998,000 NXUSD plus fee against newly created JLP collateral, unwinding into stables, repaying Aave, and retaining 371,406.644911 USDC.e. The root cause was Nereus trusting a same-transaction, reserve-based JLP oracle for borrow limits. Because the oracle priced JLP from live AMM reserves and LP total supply, the attacker could distort those inputs with flash liquidity and make fresh JLP collateral appear materially more valuable than it was.
2. Key Background
Nereus used the Trader Joe WAVAX-USDC LP token at 0xf4003F4efBE8691B60249E6afbD307aBE7758adb as collateral inside the cauldron at 0xC0A7a7F141b6A5Bce3EC1B81823c8AFA456B6930. The collateral oracle was 0xf955a6694C6F5629f5Ecd514094B3bd450b59000, a verified JLPWAVAXUSDCOracle. Its pricing logic was reserve based:
(uint112 wavaxReserve, uint112 usdcReserve, ) = joePair.getReserves();
uint256 price =
(wavaxReserve * avaxPrice + usdcReserve * usdcPrice * 1e12)
/ uint256(joePair.totalSupply());
return 1e26 / price;
This is synchronously manipulable because getReserves() and totalSupply() are public state that any permissionless trader can change via swaps and LP minting in the same transaction. The exploit trace confirms the pre-state oracle rate was 89222628801 at block 19613452, before the attacker refreshed it at the manipulated state.
3. Vulnerability Analysis & Root Cause Summary
The vulnerability class is a borrow-limit oracle manipulation. Nereus accepted spot AMM state as collateral truth, even though that state was controllable within a flash-loaned transaction. The oracle did not use a TWAP, delayed settlement, or a manipulation-resistant redemption-value model. The attacker first shifted the Trader Joe pool with large swaps, then minted fresh JLP while the pool was distorted, and immediately called updateExchangeRate() so the cauldron cached the manipulated value. The exploit trace emitted LogExchangeRate(32701350550), showing the exchange rate dropped from 89222628801 to 32701350550, which made the attacker’s JLP collateral appear about 2.73x more valuable to the cauldron. CauldronV2 then allowed cook([5,21,20,10], ...) to borrow and finalize the collateralized position, and its end-of-cook solvency check used the same manipulated exchange rate.
4. Detailed Root Cause Analysis
The core invariant is that borrowed NXUSD must remain bounded by the realizable liquidation value of posted collateral. Nereus broke that invariant by valuing JLP from attacker-controlled live reserves and current LP supply instead of a manipulation-resistant value.
The exploit transaction shows the full mechanism. Aave V3 supplied the attacker helper contract with 51,000,000 USDC.e through a flash loan. The attacker then executed two large Trader Joe swaps and a liquidity-add sequence against the WAVAX-USDC pool. Those actions changed the pool state and minted 45,330,977,931,305,070 JLP to the attacker helper during the manipulated state.
Immediately after those AMM operations, the attacker called the victim cauldron’s updateExchangeRate(). The trace shows the oracle call and event:
0xC0A7...6930::updateExchangeRate()
0xf955...9000::get(0x0000000000000000000000000000000000000000)
emit LogExchangeRate(: 32701350550)
That refreshed rate was lower than the pre-state rate because the oracle returns the inverse of the reserve-derived LP price. A lower exchange rate in this cauldron design increased how much debt the posted JLP could support.
The attacker then executed:
0xC0A7...6930::cook([5, 21, 20, 10], ...)
Inside that flow, the cauldron borrowed 998000000000000000000000 NXUSD to the attacker path, withdrew the NXUSD from BentoBox, deposited the attacker’s JLP balance into BentoBox, and added that collateral share to the cauldron position. The verified cauldron source performs the borrow and then ends with:
if (status.needsSolvencyCheck) {
require(_isSolvent(msg.sender, exchangeRate), "Cauldron: user insolvent");
}
Because exchangeRate had just been refreshed from the manipulated oracle state, the final solvency check validated an overvalued collateral mark rather than the unmanipulated liquidation value. That is why the cauldron’s debt increased even though the collateral quality was illusory.
5. Adversary Flow Analysis
The attacker cluster consisted of sender EOA 0x69992a2e5d6ec031ab16733975110f0b43a0b1af, helper contract 0x16b94c6358fe622241d055811d829281836e49d6, and profit recipient 0x8ec74e6f9627d445f546cdc606a35a3334378381. The sender only needed standard user privileges.
The on-chain flow was:
1. Flash-loan 51,000,000 USDC.e from Aave V3.
2. Swap USDC.e into WAVAX and add manipulated liquidity on Trader Joe.
3. Mint fresh WAVAX-USDC JLP while the pool is distorted.
4. Refresh the Nereus JLP oracle with updateExchangeRate().
5. Borrow 998,000 NXUSD through cauldron cook().
6. Unwind borrowed NXUSD through the NXUSD metapool and stable swap path.
7. Swap remaining assets back to USDC.e, repay Aave plus 25,500 USDC.e fee, and transfer profit.
The trace and balance deltas are consistent with that sequence. balance_diff.json shows the Aave aToken underlying provider gained 25500000000 USDC.e, confirming the flash-loan fee, and the final profit recipient gained 371406644911 USDC.e. The same artifact shows the NXUSD metapool lost 998000000000000000000000 NXUSD while the metapool received that amount, matching the cauldron overborrow and dump step.
6. Impact & Losses
The measurable protocol loss was over-issuance of NXUSD against manipulated collateral. The analysis records 1,002,990 NXUSD in cauldron debt impact, encoded on-chain as:
{"token_symbol":"NXUSD","amount":"1002990000000000000000000","decimal":18}
The attacker realized 371,406.644911 USDC.e profit after repaying the flash loan path. More importantly, the protocol was left with debt backed by a collateral mark that was only valid during an attacker-induced reserve distortion, which is the precise safety failure for a lending market.
7. References
- Exploit transaction:
0x0ab12913f9232b27b0664cd2d50e482ad6aa896aeb811b53081712f42d54c026on Avalanche block19613453. - Exploit trace showing the flash loan,
updateExchangeRate(),LogExchangeRate(32701350550), andcook([5,21,20,10], ...). - Exploit balance-diff artifact showing
371406644911USDC.e profit and the25500000000USDC.e flash-loan fee. - Verified source for
JLPWAVAXUSDCOracle, whose_get()function prices JLP from livegetReserves()andtotalSupply(). - Verified source for
CauldronV2, whosecook()flow completes with a solvency check against the current cachedexchangeRate.