Reproduced Exploit

Statusl — bypass stake lock via leave + migrateToVault

1. Stake with a multi-year lock for max multiplier. 2. leave() zeros stakedBalance but does not permanently ban the vault as a migrate target. 3. An empty vault migrates onto the left vault and overwrites lockUntil with 0. 4. Withdraw the full stake immediately.

Jan 2026Otheruntagged3 min read

Chain

Other

Category

untagged

Date

Jan 2026

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: 65328-user-can-bypass-lock-and-withdraw-stake-anytime-cyfrin-none. Standalone Foundry PoC and full write-up: 65328-user-can-bypass-lock-and-withdraw-stake-anytime-cyfrin-none_exp in the evm-hack-registry mirror.


Vulnerability classes: wrong-condition · indirect-loss · reward-accounting

Reproduction: self-contained Foundry PoC with only forge-std. Full trace: output.txt. PoC: test/65328-user-can-bypass-lock-and-withdraw-stake-anytime-cyfrin-none_exp.sol.

AuditVault taxonomy: lang/solidity · platform/cyfrin · has/github · has/poc · severity/high · sector/staking · genome: wrong-condition · indirect-loss · reward-accounting


Key info#

ImpactHIGH — max-lock stake withdrawable immediately; up to 3x unfair reward share
ProtocolStatus Network / Statusl
Vulnerable codeStakeManager.leave + migrateToVault / StakeVault.migrateFromVault
Bug classMissing hasLeft guard on migration target
FindingCyfrin Statusl2 v2.0, 2026-01-05 · #65328 · Samuraii77
ReportCyfrin report
SourceAuditVault
StatusFixed in fb6c8ef
Compiler^0.8.24 (PoC)

TL;DR#

  1. Stake with a multi-year lock for max multiplier.
  2. leave() zeros stakedBalance but does not permanently ban the vault as a migrate target.
  3. An empty vault migrates onto the left vault and overwrites lockUntil with 0.
  4. Withdraw the full stake immediately.
  5. HARM: lock bypass — max rewards with no lock downside.

The vulnerable code#

SOLIDITY
_unstake(vault.stakedBalance, vault); // @> VULN: leave without blocking migrate-to
// ...
if (vaultOwners[migrateTo] == address(0)) revert; // @> VULN: no hasLeft check
if (vaultData[migrateTo].stakedBalance > 0) revert;
// ...
lockUntil = data.lockUntil; // @> VULN: empty source clears lock

Fix: disallow migrating to (or from) a vault with hasLeft == true.


Root cause#

Migration only checks registration and zero staked balance. A vault that has left is empty and still registered, so it accepts a migrate that writes lockUntil = 0.


Preconditions#

  • User can create multiple vaults and call leave/migrate.
  • Stake locked for a long period.

Attack walkthrough#

  1. Stake 1000 tokens with a 4-year lock on vault A.
  2. Create empty vault B.
  3. leave on A — stake accounting cleared, tokens return to vault, hasLeft set but unused by migrate.
  4. B migrates to A with zero lock metadata → A.lockUntil = 0.
  5. Withdraw full stake from A immediately.

Diagrams#

sequenceDiagram participant U as User participant A as LockedVault participant B as EmptyVault participant M as StakeManager U->>A: stake 1000, lock 4y U->>A: leave A->>M: leave zeros stakedBalance U->>B: migrateToVault(A) B->>M: migrateToVault M->>A: migrateFromVault lockUntil=0 U->>A: withdraw 1000

Impact#

Users take max lock multiplier (6x vs 2x unlocked) then exit instantly, diluting honest locked stakers' rewards.


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.