Web3Exploit logoWeb3Exploit
← Back to Case Research

Cork $12M Case Research: HIYA Price Skew Meets an Unauthenticated Uniswap v4 Hook

Cork is a good reminder that complex DeFi failures rarely live in one line. The May 2025 exploit combined an economic pricing edge with a raw access-control failure. A late-expiry trade distorted Cork's Historical Implied Yield Average (HIYA), then an unauthenticated Uniswap v4 hook path let the attacker feed crafted state into the protocol's flash-swap machinery. The result was roughly 3,761 wstETH, about $12M, leaving the liquidity vault.

This write-up uses BlockSec's deep dive, CertiK's incident analysis, and CoInspect's reproduction-oriented breakdown. Code snippets are representative, based on the published flow and named functions.

The takeaway: programmable hooks are privileged execution surfaces. If beforeSwap can be called by anything other than the PoolManager or a vetted router path, the hook becomes an attacker-controlled accounting API.

Target architecture: risk tokens and HIYA

Cork markets split a redemption asset (RA) into derivative tokens:

RA = Redemption Asset, e.g. wstETH
PA = Pegged Asset, e.g. weETH
DS = Depeg Swap token
CT = Cover Token

The system prices depeg risk using HIYA, a historical implied-yield average. The dangerous property is time sensitivity. As expiry approaches, the risk-premium formula has a 1 / T style amplification. A small price move close to expiry can inflate the implied risk premium dramatically.

Conceptually:

r_T = (F / p_T)^(1 / T) - 1
HIYA = sum(volume_T * r_T)

When T is tiny, r_T can explode. That means a small, late trade can poison the next market's initialization.

Root cause #1: late-expiry HIYA manipulation

The first phase was economic. The attacker executed a small RA-to-DS swap shortly before expiry of a wstETH:weETH market. CoInspect describes this as occurring about 19 minutes before expiry. Because the HIYA formula is exponentially sensitive as time-to-maturity approaches zero, the trade inflated the risk premium used during rollover.

Representative shape:

// Attacker-chosen guesses produce an extreme near-expiry risk premium.
OffchainGuess memory guess = OffchainGuess({
    initialBorrowAmount: 2e18,
    afterSoldBorrowAmount: 2.55e18
});

flashSwapProxy.swapRaforDs(
    pairId,
    reserveId,
    3.5e15, // small wstETH paid
    0,
    buyParams,
    guess
);

The protocol then uses the inflated HIYA to initialize the next market with Cover Tokens priced far too cheaply. That lets the attacker buy a large CT position for little RA.

Root cause #2: CorkHook.beforeSwap lacked caller authentication

The second phase is the pure access-control failure. Cork integrated with Uniswap v4 hooks. Hook callbacks are powerful because the PoolManager calls them during swaps. That means a hook must know who is calling and whether the supplied hook data belongs to a real swap path.

The vulnerable shape:

function beforeSwap(
    address sender,
    PoolKey calldata key,
    IPoolManager.SwapParams calldata params,
    bytes calldata hookData
) external returns (bytes4, BeforeSwapDelta, uint24) {
    // Missing: require(msg.sender == address(poolManager));
    // Missing: authenticate router/market context in hookData.
    return _beforeSwap(sender, key, params, hookData);
}

The fix is not subtle:

modifier onlyPoolManager() {
    require(msg.sender == address(poolManager), "not PoolManager");
    _;
}

function beforeSwap(...) external onlyPoolManager returns (...) {
    _validateHookData(key, params, hookData);
    return _beforeSwap(...);
}

Without that boundary, the attacker can call into the hook through a malicious callback and supply crafted parameters that make Cork's internal router believe it is handling a legitimate flash-swap/rebalancing path.

Attack chain

The exploit has two connected phases.

Phase 1: make CT cheap

  1. Execute a small near-expiry swapRaforDs.
  2. Exploit the 1 / T HIYA amplification.
  3. Let the next market initialize with distorted risk parameters.
  4. Buy a large amount of CT cheaply.

Phase 2: siphon value through the hook path

  1. Create a fake market where attacker-controlled inputs can act like a valid rate source.
  2. Trigger Uniswap v4 PoolManager.unlock.
  3. In the callback, call CorkHook.beforeSwap with crafted hook data.
  4. Route Cork's flash-swap machinery into the attacker's proxy market.
  5. Cause DS/CT derivative issuance or double counting under the wrong market context.
  6. Redeem accumulated CT and DS through the Peg Stability Module for real wstETH.

Representative call chain:

Attacker contract
  -> PoolManager.unlock()
    -> attacker unlockCallback()
      -> CorkHook.beforeSwap(crafted hookData)
        -> FlashSwapRouter.corkCall(...)
          -> ModuleCore.depositPsm(...)
          -> mint pDS / pCT to attacker-controlled market
  -> redeem pDS + pCT for wstETH

CertiK describes the core as fake market setup plus open CorkHook access causing derivative token double counting. BlockSec frames it as HIYA manipulation plus missing msg.sender authentication. Those are complementary descriptions of the same exploit chain.

Transaction trail

Public reports cite:

  • Preparation tx: https://etherscan.io/tx/0x14cdf1a643fc94a03140b7581239d1b7603122fbb74a80dd4704dfb336c1dec0
  • Exploit tx: https://etherscan.io/tx/0xfd89cdd0be468a564dd525b222b728386d7c6780cf7b2f90d2b54493be09f64d
  • Attack wallet: 0xEA6f30e360192bae715599E15e2F765B49E4da98
  • Attack contract: 0x9Af3dCE0813FD7428c47F57A39da2F6Dd7C9bb09
  • CorkHook: 0x5287e8915445aee78e10190559d8dd21e0e9ea88

What I would change

  1. Authenticate hook callers. A Uniswap v4 hook should reject direct calls unless msg.sender is the expected PoolManager.
  2. Bind hook data to the pool and router context. Treat hookData as untrusted calldata, not as an internal message.
  3. Add rollover manipulation bounds. A single late-expiry trade should not dominate the next market's initialization.
  4. Simulate expiry edges. Property tests should target T -> 0, low volume, and tiny trades with large implied-risk effects.
  5. Separate economic checks from hook authorization. Even if HIYA is manipulated, unauthenticated hook calls should still be impossible.

Confidence notes

  • Firm: the incident happened on May 28, 2025 and drained roughly 3,761 wstETH.
  • Firm: public technical reports identify both HIYA/rollover pricing distortion and missing CorkHook access control as exploit components.
  • Firm: the exploit used fake/crafted market context and redeemed derivatives for wstETH.
  • Representative: the snippets express the relevant logic shape; they are not a complete source dump of Cork's contracts.

Sources

  • BlockSec — Cork Protocol Incident: Two Independent Flaws Combine into One Devastating Exploit Chain: https://blocksec.com/blog/cork-protocol-incident-two-independent-flaws-combine-into-one-devastating-exploit-chain
  • CertiK — Cork Protocol Incident Analysis: https://www.certik.com/blog/cork-protocol-incident-analysis
  • CoInspect — Cork Finance case reproduction: https://www.coinspect.com/learn-evm-attacks/cases/cork-finance/
  • Incrypthos — Cork Protocol suffers $12M exploit via Uniswap v4 hook manipulation: https://incrypthos.com/security/cork-protocol-suffers-12-million-exploit-via-uniswap-v4-hook-manipulation/