Reproduced Exploit

Superfluid Locker — Staked tokens inside FluidLocker can be withdrawn without Unstake

1. Owner stakes all FLUID in the locker (_stakedBalance = balance). 2. provideLiquidity(supAmount) does not check available balance — staked tokens leave to Uniswap. 3. After tax-free withdrawLiquidity, FLUID is at the owner; _stakedBalance still full. 4. Staking reward units keep accruing on phant…

Jun 2025Otheruntagged2 min read

Chain

Other

Category

untagged

Date

Jun 2025

Source

AuditVault

EVM Playground

Source-level debugger — step opcodes and Solidity in sync

evm-hack-analyzer

The attack is replayed in an in-browser EVM preloaded with the exact dumped fork state. The execution tree shows every call; step by Solidity line or by opcode across all depths — source, Stack, Memory, Storage, Balances (native / ERC-20 / NFT), Transient storage and Return value stay in sync. Click a tree node, opcode, or source line to jump. No backend, no live RPC.

Loading fork state…

Source & credit. Reproduction of a public audit finding curated by AuditVault — the original finding: 58281-h-1-staked-tokens-inside-fluidlocker-can-be-withdrawn-withou. Standalone Foundry PoC and full write-up: 58281-h-1-staked-tokens-inside-fluidlocker-can-be-withdrawn-withou_exp in the evm-hack-registry mirror.


Vulnerability classes: cross-contract-state-consistency · variant · staking integrity

Reproduction: self-contained Foundry PoC with only forge-std — no fork. output.txt · test/58281-…sol.

AuditVault taxonomy: lang/solidity · sector/dex · sector/staking · platform/sherlock · severity/high · genome: cross-contract-state-consistency · variant


Key info#

ImpactHIGH — phantom stake accrues reward units after tokens left the locker
ProtocolSuperfluid Locker System — FluidLocker.provideLiquidity
Vulnerable codeprovideLiquidity never checks supAmount <= getAvailableBalance()
Bug classMissing available-balance validation / double-use of staked funds
FindingSherlock 2025-06-superfluid-locker-system · H-1 · #58281 · newspacexyz et al.
Reportjudging issue #177
SourceAuditVault
Fixsuperfluid-finance/fluid#26 — require available balance
Compiler^0.8.24 (PoC)
Reposherlock-audit/2025-06-superfluid-locker-system@d8beaeed

TL;DR#

  1. Owner stakes all FLUID in the locker (_stakedBalance = balance).
  2. provideLiquidity(supAmount) does not check available balance — staked tokens leave to Uniswap.
  3. After tax-free withdrawLiquidity, FLUID is at the owner; _stakedBalance still full.
  4. Staking reward units keep accruing on phantom stake; getAvailableBalance underflows.

Vulnerable code#

SOLIDITY
function provideLiquidity(uint256 supAmount) external payable {
    // missing: require(supAmount <= getAvailableBalance());
    // ...
    NONFUNGIBLE_POSITION_MANAGER.mint(..., supAmount, ...); // @> VULN
}

Root cause#

Stake accounting (_stakedBalance) is independent of the FLUID path used by provideLiquidity. Only stake/unstake touch the stake counter; LP paths move the actual tokens.

Preconditions#

  • Locker holds FLUID and has a locker owner.
  • Owner can stake and call provideLiquidity / withdrawLiquidity.

Attack walkthrough#

  1. Fund locker with 100 FLUID; stake all 100.
  2. provideLiquidity(100) — tokens leave despite being staked.
  3. Tax-free withdraw (delay reduced to 0 in synthetic) returns FLUID to owner.
  4. getStakedBalance() == 100 while locker balance is 0.

Diagrams#

sequenceDiagram participant Owner participant Locker as FluidLocker participant NPM as PositionManager Owner->>Locker: stake 100 Note over Locker: staked=100 available=0 Owner->>Locker: provideLiquidity 100 Locker->>NPM: mint pulls 100 FLUID Note over Locker: staked still 100 balance 0 Owner->>Locker: withdrawLiquidity Locker->>Owner: transfer 100 FLUID Note over Locker: phantom stake 100 remains

Impact#

Unbounded phantom stake corrupts the staker reward distribution; free points dominate future reward shares.

Sources#


Sources & further analysis#

Reproductions & code

Alerts & third-party analyses

  • Web3Sec X hacked database: search.
  • Rekt leaderboard: search.
  • Solodit incident search: search.

These dashboards index community alerts tweets, post-mortems, and independent write-ups. Reach them through the protocol name above to cross-check this reproduction against other analyses.