All incidents

Ploutos Market Oracle Feed Misconfiguration Enabled Undercollateralized WETH Borrow

Share
Feb 26, 2026 05:07 UTCAttackLoss: 187.36 WETHManually checked1 exploit txWindow: Atomic
Estimated Impact
187.36 WETH
Label
Attack
Exploit Tx
1
Addresses
3
Attack Window
Atomic
Feb 26, 2026 05:07 UTC → Feb 26, 2026 05:07 UTC

Exploit Transactions

TX 1Ethereum
0xa17dc37e1b65c65d20042212fb834974f7faaa961442e3fc05393778705f8474
Feb 26, 2026 05:07 UTCExplorer

Victim Addresses

0x7398e7e3603119d9241e45f688734436fd7b1540Ethereum
0x9dce7a180c34203fee8ce8ca62f244feeb67bd30Ethereum
0xd060ebd4f56be8866376a3616b6e5aef87f945d2Ethereum

Loss Breakdown

187.36WETH

Similar Incidents

Root Cause Analysis

Ploutos Market Oracle Feed Misconfiguration Enabled Undercollateralized WETH Borrow

1. Incident Overview TL;DR

In Ethereum block 24538897, an unprivileged adversary executed transaction 0xa17dc37e1b65c65d20042212fb834974f7faaa961442e3fc05393778705f8474 against Ploutos Market (0x7398e7e3603119d9241e45f688734436fd7b1540) and drained most borrowable WETH by posting only 8.879192 USDC collateral.

The borrow passed because the protocol oracle (0x9dce7a180c34203fee8ce8ca62f244feeb67bd30) priced USDC using the BTC/USD feed (0xF4030086522a5bEEa4988F8cA5B36dbC97BeE88c). This mapping was set in the prior block by transaction 0xcfedf63b37a6cd45b21bc94e3de5412fee0765e7dad6b7c8561a01cebd193ab6.

Root cause: AaveOracle accepted an incompatible source assignment (USDC -> BTC/USD) and getAssetPrice returned raw latestAnswer() without semantic validation/sanity bounds, so collateral valuation became deterministically incorrect.

This is an ACT case: one public transaction by an unprivileged EOA realized the exploit predicate and netted 181.745096492453810260 ETH.

2. Key Background

Ploutos uses an Aave v3-style valuation path where collateral and debt checks call AaveOracle.getAssetPrice(asset) and compare normalized values in a common base currency (BASE_CURRENCY_UNIT = 1e8).

Relevant components:

  • Pool proxy (victim path): 0x7398e7e3603119d9241e45f688734436fd7b1540
  • Oracle: 0x9dce7a180c34203fee8ce8ca62f244feeb67bd30
  • Collateral token: USDC 0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48
  • Borrowed token: WETH 0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
  • Misconfigured feed: BTC/USD 0xF4030086522a5bEEa4988F8cA5B36dbC97BeE88c

Exploit pre-state (just before block 24538897) is publicly reconstructible and already contains the wrong USDC source from tx 0xcfedf63b... in block 24538896.

3. Vulnerability Analysis & Root Cause Summary

Root cause category: ATTACK.

The protocol safety invariant is: each listed asset must map to a semantically correct oracle feed for that asset at the expected base-currency scale. Borrow safety inherits this assumption.

The concrete code-level breakpoint is in AaveOracle:

  • _setAssetsSources writes assetsSources[asset] = AggregatorInterface(source) with no asset/feed compatibility checks.
  • getAssetPrice returns uint256(source.latestAnswer()) when positive, with no semantic sanity guard that USDC is actually mapped to a USD-stable feed.

As a result, when USDC was mapped to BTC/USD, borrow logic treated 8.879192 USDC as extremely valuable collateral and allowed borrowing 187.366746326704993556 WETH.

4. Detailed Root Cause Analysis

4.1 Victim code mechanism

Oracle implementation confirms the vulnerable behavior:

function _setAssetsSources(address[] memory assets, address[] memory sources) internal {
  require(assets.length == sources.length, Errors.INCONSISTENT_PARAMS_LENGTH);
  for (uint256 i = 0; i < assets.length; i++) {
    assetsSources[assets[i]] = AggregatorInterface(sources[i]);
    emit AssetSourceUpdated(assets[i], sources[i]);
  }
}

function getAssetPrice(address asset) public view override returns (uint256) {
  AggregatorInterface source = assetsSources[asset];
  ...
  int256 price = source.latestAnswer();
  if (price > 0) {
    return uint256(price);
  } else {
    return _fallbackOracle.getAssetPrice(asset);
  }
}

The assignment and read paths are independent of asset/feed semantic correctness.

4.2 Deterministic precondition creation

In tx 0xcfedf63b37a6cd45b21bc94e3de5412fee0765e7dad6b7c8561a01cebd193ab6, oracle event data shows:

  • AssetSourceUpdated(asset=USDC, source=0xF403...E88c)

Independent state calls at block 24538897 confirm:

  • getSourceOfAsset(USDC) = 0xF4030086522a5bEEa4988F8cA5B36dbC97BeE88c
  • Feed description() = "BTC / USD"
  • Feed latestAnswer() = 6855405329514

4.3 Exploit execution and borrow acceptance

Seed trace shows the atomic flow:

UniswapV2Pair::swap(8879192, ...) -> attackerContract::uniswapV2Call(...)
Pool::deposit(USDC, 8879192, attackerContract, 0)
Pool::borrow(WETH, 187366746326704993556, 2, 0, attackerContract)
AaveOracle::getAssetPrice(USDC) -> BTC/USD latestAnswer -> 6855405329514
AaveOracle::getAssetPrice(WETH) -> ETH/USD latestAnswer -> 208047000000

Because USDC price was massively inflated relative to WETH, the health-factor and borrow checks passed.

4.4 Settlement and realized predicate

The same transaction then:

  • repaid only 0.004289216474598283 WETH to the pair,
  • unwrapped 187.362457110230395273 WETH,
  • transferred 5.612909926920174741 ETH to builder address 0x4838b106fce9647bdf1e7877bf73ce8b0bad5f97,
  • transferred 181.749547183310220532 ETH to attacker EOA 0x3885869b0f4526806b468a0c64a89bb860a18cee.

Balance deltas give the deterministic net result (after gas/transfers):

  • attacker EOA native balance delta: +181.745096492453810260 ETH
  • WETH contract native delta (proxy for protocol-side WETH outflow in this flow): -187.362457110230395273 ETH

4.5 ACT exploit conditions

The opportunity exists when all of the following hold:

  • USDC source is mapped to a high-valued non-USDC feed with positive answer.
  • Pool has material WETH liquidity.
  • Adversary can source small USDC atomically and perform deposit+borrow in one tx.

All conditions were satisfied at block 24538897.

5. Adversary Flow Analysis

Adversary-related accounts:

  • EOA 0x3885869b0f4526806b468a0c64a89bb860a18cee: seed tx sender and final ETH recipient.
  • Contract 0x3e47945cca05439f99029a3d21e3166ce1a84fab: executes flash-swap callback, collateral deposit, borrow, repayment, unwrap, and payout.

End-to-end lifecycle:

  1. Precondition (victim-observed): tx 0xcfedf63b... remaps USDC source to BTC/USD.
  2. Atomic exploit: tx 0xa17dc37e... executes flash swap -> deposit USDC -> borrow WETH while oracle is misconfigured.
  3. Profit realization: attacker repays minimal flash leg, unwraps WETH, pays builder, and exits with net ETH profit.

6. Impact & Losses

Measured impact:

  • Primary reserve depletion: 187.362457110230395273 WETH
  • Net attacker profit: 181.745096492453810260 ETH

Affected parties/components:

  • Ploutos lending pool WETH reserve (aWETH/pool liquidity path)
  • Borrow-risk controls that trusted mutable oracle source mapping without semantic guardrails

Exposure closure:

  • A later corrective transaction (0xee3d7556528d3ceb00681a3c7ed7be3751c83923675bc3774c77f9f4e60d20f0) remapped USDC to the intended feed.

7. References

  • Seed exploit tx: 0xa17dc37e1b65c65d20042212fb834974f7faaa961442e3fc05393778705f8474
  • Misconfiguration tx: 0xcfedf63b37a6cd45b21bc94e3de5412fee0765e7dad6b7c8561a01cebd193ab6
  • Correction tx: 0xee3d7556528d3ceb00681a3c7ed7be3751c83923675bc3774c77f9f4e60d20f0
  • Oracle contract: 0x9dce7a180c34203fee8ce8ca62f244feeb67bd30
  • Pool proxy: 0x7398e7e3603119d9241e45f688734436fd7b1540
  • BTC/USD feed used for USDC: 0xF4030086522a5bEEa4988F8cA5B36dbC97BeE88c
  • Local evidence artifacts:
    • seed trace (trace.cast.log)
    • seed balance deltas (balance_diff.json)
    • seed metadata (metadata.json)
  • Public code source (AaveOracle implementation): Sourcify full-match source for 0x9dce....