An unguarded OrderBook function let a trader poison their own cached funding growth on Perpetual Protocol v2, then withdraw the inflated balance from two vaults.
Logged as “2026-07-16: V2 Curie Unguarded Orderbook Funding Growth Update Lets Anyone Poison Cached Funding Draining The Vault on PerpetualProtocol”.
Perpetual Protocol v2 (Curie) used a shared OrderBook contract whose state-changing entrypoints each open with _requireOnlyClearingHouse(). Every one of them does, except updateFundingGrowthAndLiquidityCoefficientInFundingPayment, whose body runs straight into reading the trader's open orders and applying a caller-supplied twPremiumX96 to their cached funding growth, with no caller check. The function is external, so anyone can call it for their own account.
The attacker's contract took the public user path. It called ClearingHouse.addLiquidity with a dust order (2 base, 1 quote) to obtain a cached open order, then called the unguarded OrderBook.updateFundingGrowthAndLiquidityCoefficientInFundingPayment(self, baseToken, Funding.Growth(twPremiumX96 = 1e70, 0)) directly, poisoning its own order's cached funding growth with a fabricated roughly 1e70 premium. A subsequent Vault.withdraw(USDC) triggered settleAllFunding, which converted the poisoned cache into a large bogus funding payment and realised PnL, inflating free collateral until the full vault balance was withdrawable.
The transaction hit two perp deployments in a single block. Vault 0x28bB.. lost 71.777612 USDC.e; vault 0xf127.. lost 2,990.435495 USDC.e. DeFiHackLabs records the total at 3,062.21 USDC.e. The loss is the other LPs' principal, not a protocol-level reserve: the attacker redeemed against standing LP positions and walked out with the depositors' funds.
The bug is a single missing line. addLiquidity (line 99 of the verified OrderBook implementation 0xa0D9966d), removeLiquidity (line 178), replaySwapInternal (line 200), and updateOrderDebt (line 275) all carry the clearing-house guard. updateFundingGrowthAndLiquidityCoefficientInFundingPayment (line 232) does not. Sourcify's full source shows the function body running from line 232 to 268 with no caller check before reading trader storage and writing the funding growth. Adding _requireOnlyClearingHouse() at the top of that function would have closed the gap.
Perpetual Protocol v2 (Curie) runs on Optimism. The exploit transaction is at block 154,311,432, from 0x957c6cF5E0F69597dB7A8065c94af1A48aBCA47d, contract creation (one-shot attacker). The DeFiHackLabs entry for the perpetual-protocol anchor is dated 16 July 2026 but has been renamed: the original feed record's headline described a generic access-control missing-permission-check, while the current README entry names the specific OrderBook function. This post is written against the current entry.
Query every incident yourself — free, no signup
Updated 14 Oct 2026. Figures are as reported by the sources listed above and are not independently verified.