Reproduced Exploit

BOB Staking — instantWithdraw does not transfer amountForContract

1. Delegated stake lives in a DelegationSurrogate. 2. instantWithdraw pulls only _amountForUser from the surrogate. 3. _amountForContract (penalty) is never transferred back to BobStaking. 4. Penalty tokens freeze in the surrogate while rewardTokenBalance is increased on paper.

Oct 2025Otherlogic3 min read

Chain

Other

Category

logic

Date

Oct 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: 63717-c-01-instantwithdraw-does-not-transfer-amountforcontract-lo. Standalone Foundry PoC and full write-up: 63717-c-01-instantwithdraw-does-not-transfer-amountforcontract-lo_exp in the evm-hack-registry mirror.


Vulnerability classes: vuln/logic/frozen-funds · reward-accounting · temporary

Reproduction: a self-contained Foundry PoC that compiles & runs in an isolated project with only forge-std — no fork, no RPC, no anvil_state. Full trace: output.txt. PoC: test/63717-c-01-instantwithdraw-does-not-transfer-amountforcontract-lo_exp.sol.

AuditVault taxonomy: severity/high · sector/staking · sector/governance · platform/pashov · frozen-funds · reward-accounting · reentrancy-guard · vote-delegation-loop


Key info#

ImpactHIGH — early-withdraw penalty permanently stuck in surrogate; paper rewards inflated
ProtocolBOB Staking
Vulnerable codeBobStaking.instantWithdraw — missing transfer of _amountForContract from surrogate
Bug classIncomplete token path when stake is delegated
FindingPashov BOB-Staking security review 2025-10-18 · #63717
ReportPashov BOB-Staking review
SourceAuditVault
StatusAudit finding — resolved per report. Reproduced as a reduced local synthetic.
Compiler^0.8.24 (PoC)

TL;DR#

  1. Delegated stake lives in a DelegationSurrogate.
  2. instantWithdraw pulls only _amountForUser from the surrogate.
  3. _amountForContract (penalty) is never transferred back to BobStaking.
  4. Penalty tokens freeze in the surrogate while rewardTokenBalance is increased on paper.

The vulnerable code#

SOLIDITY
if (stakers[_stakeMsgSender()].governanceDelegatee != address(0)) {
    DelegationSurrogate surrogate = storedSurrogates[...];
    IERC20(stakingToken).safeTransferFrom(address(surrogate), _receiver, _amountForUser);
    // @> VULN: missing safeTransferFrom(surrogate, address(this), _amountForContract)
} else {
    IERC20(stakingToken).safeTransfer(_receiver, _amountForUser);
}

Root cause#

The delegated and non-delegated withdraw paths are asymmetric: only the non-delegated path leaves the penalty in the staking contract naturally. The delegated path never repatriates it.

Preconditions#

  • Staker has non-zero stake and a non-zero governance delegatee (tokens in surrogate).
  • Instant withdraw allowed (not locked / no unbond started).
  • instantWithdrawalRate < 100 so a non-zero penalty exists.

Attack walkthrough#

  1. Stake 1 BOB; whitelist and set a governance delegatee (tokens → surrogate).
  2. Call instantWithdraw (50% rate).
  3. User receives 0.5 BOB; 0.5 BOB remains in the surrogate forever.
  4. Staking contract balance unchanged; rewardTokenBalance claims +0.5 on paper.

Diagrams#

flowchart TD A["Stake then delegate"] --> B["Tokens in surrogate"] B --> C["instantWithdraw"] C --> D["Pull amountForUser only"] D --> E["VULN: amountForContract never moved"] E --> F["Penalty stuck in surrogate"] F --> G["Paper rewardTokenBalance inflated"]

Impact#

Penalty value that should fund rewards is permanently unrecoverable. Accounting overstates reward inventory, risking insolvency for later claimers.

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.