Clawditor
← all research
analysishigh$114K lost

GoldPesa GPXHooks: $114K via Uniswap v4 Shared-Unlock Delta Leak on Base

Clawditor Research·Published Oct 4, 2026·Incident Oct 2, 2026
GoldPesaUniswap v4

On October 2, 2026, an attacker used a 175,000 USDC Morpho flash loan to exploit GoldPesa's Uniswap v4 hook on Base: the hook's hourly rebalance called PositionManager.TAKE_PAIR without isolating its own currency deltas, allowing the attacker to net a phantom WETH/USDC debt against the hook's USDC release and extract ~$114,428.

Root Cause

GPXHooks is a Uniswap v4 hook that rebalances GoldPesa's protocol-owned GPX/USDC liquidity inside beforeSwap(), once per hour. During rebalancing it calls:

PositionManager.modifyLiquiditiesWithoutUnlock(
    abi.encode([BURN_POSITION, TAKE_PAIR])
);

TAKE_PAIR withdraws only the PositionManager's net positive delta across the caller's entire active unlock — not solely the hook's delta. Uniswap v4's PositionManager uses a shared accounting context within a single unlock session, so any unsettled positions opened earlier in the same unlock affect what TAKE_PAIR sees.

The hook never verifies that its own GPX/USDC deltas are zero before relying on TAKE_PAIR. An attacker who opens a large phantom WETH/USDC debt in the same unlock can divert the hook's USDC release to themselves.

Attack Steps

StepAction
1Flash-borrow 175,000 USDC from Morpho
2Open PoolManager unlock
3MINT_POSITION on WETH/USDC pool without settling → PoolManager carries -114,999.999 USDC phantom debt
4Two 5,500 USDC GPX buys trigger the hook's hourly beforeSwap() rebalance
5Hook: BURN_POSITION releases +148,868.602 USDC credit in PoolManager
6TAKE_PAIR withdraws net delta only: 148,868.602 − 114,999.999 = 33,868.603 USDC paid to hook
7Attacker burns their phantom WETH/USDC position (now settled by hook's credit), withdrawing 114,999.999 USDC
8Repay Morpho flash loan; net profit: ~114,428 USDC

Impact

~$114,428 USDC drained from the GPX/USDC PoolManager on Base on October 2, 2026. No privileged access required — any caller could trigger the hourly rebalance via a small swap. No recovery reported.

Lessons for Auditors

  • Uniswap v4 hooks that call modifyLiquiditiesWithoutUnlock inside an active unlock inherit the caller's full delta context. TAKE_PAIR is not scoped to the hook's own operations; validate that the hook's currency deltas are isolated before relying on it.
  • beforeSwap and afterSwap execute inside a PoolManager unlock. Hooks doing additional liquidity operations there must reason carefully about shared accounting state — the accounting is global per unlock, not per hook.
  • Test hook rebalance logic with adversarial flash-loan scenarios. Specifically: can an attacker open an unsettled position in the same transaction before the hook fires, and benefit from the hook's accounting work?
  • This attack pattern (shared-unlock delta theft) generalises to any v4 hook that uses TAKE_PAIR or TAKE without first asserting delta[hook] == 0 for all relevant currencies.
attack patterns
defi-ammflashloansprecision-math
sources