Reproduced Exploit
Souls.club — staking during the cooldown flag wins 100 PRIZE the attacker should not
The attacker joins with stake 1. The victim joins with stake 100. Both seats are filled, so cooldown becomes true in this block. The attacker then adds 1,000. Stake is now 1,001.
Chain
Other
Category
logic
Date
Nov 2025
Source
AuditVault
EVM Playground
Source-level debugger — step opcodes and Solidity in sync
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.
Source & credit. Reproduction of a public audit finding curated by AuditVault — the original finding: 64739-h-01-stake-manipulation-during-cooldown-period-allows-probab. Standalone Foundry PoC and full write-up: 64739-h-01-stake-manipulation-during-cooldown-period-allows-probab_exp in the
evm-hack-registrymirror.
Vulnerability classes: vuln/logic/reward-calculation · vuln/logic/wrong-condition
Reproduction: a self-contained Foundry PoC that compiles and runs offline with only
forge-std— no fork and no RPC. Trace: output.txt. PoC: test/64739-h-01-stake-manipulation-during-cooldown-period-allows-probab_exp.sol.
Key info#
| Impact | HIGH — the attacker wins 100 PRIZE on roll 50 after raising stake from 1 to 1,001 during cooldown |
| Protocol | Souls.club Wheel |
| Vulnerable code | joinDuringCooldown adds to stakeA while cooldown is already true |
| Bug class | Stake changes the odds after the round has locked |
| Finding | Shieldify — Souls.club Wheel, November 2025 · id 64739, H-01 |
| Report | Souls.club Wheel review |
| Source | AuditVault finding |
| Status | Reproduced here as a local synthetic. Cooldown is a flag. There is no warp. |
| Compiler | solc 0.8.27, cancun, via IR |
TL;DR#
The attacker joins with stake 1. The victim joins with stake 100. Both seats are filled, so cooldown becomes true in this block. The attacker then adds 1,000. Stake is now 1,001.
The wheel walks the attacker first. Roll 50 is not less than 1, so the frozen stake would lose. It is less than 1,001, so the boosted stake wins. The attacker receives 100 PRIZE.
Control reverts the extra stake. Stake stays 1. The same roll selects the victim. The attacker receives 0 and the prize stays in the wheel.
The vulnerable code#
function joinDuringCooldown(uint256 amount) external {
require(cooldown, "cooldown");
// @> VULN: cooldown is already set and the attacker stake still grows
stakeA += amount;
}
The fix reverts instead of adding the amount.
Root cause#
joinGame keeps adding to stakeByPlayer after the session has activated. The winner is stake-weighted, so a deposit during that window changes who roll 50 hits.
Preconditions#
- Attacker stake starts at 1 and victim stake is 100. The attacker is the first player in the walk.
cooldownis the flag set when both stakes are nonzero. The roll is the constant 50.- The wheel holds 100 PRIZE.
Attack walkthrough#
- Fund 100 PRIZE. Attacker joins with 1. Victim joins with 100.
cooldownbecomes true. joinDuringCooldown(1000)adds tostakeA. It is now 1001.spinuses roll 50.50 < 1001selects the attacker.50 < 1would have selected the victim.- The wheel transfers 100 PRIZE to the attacker.
Control reverts joinDuringCooldown. The spin pays nobody on the attacker path. The winner is the victim. The prize balance of the wheel stays 100.
Diagrams#
Impact#
The attacker wins 100 PRIZE that roll 50 would have given to the victim. The victim's 100 stake is no longer the winning range.
Remediation#
Reject stake increases once cooldown is true. Freeze the stakes that the roll is measured against.
Sources#
Taxonomy#
severity/highsector/gamingplatform/shieldify
Sources & further analysis#
Reproductions & code
- Standalone PoC + full trace: 64739-h-01-stake-manipulation-during-cooldown-period-allows-probab_exp (evm-hack-registry mirror).
- AuditVault finding: 64739-h-01-stake-manipulation-during-cooldown-period-allows-probab.
Alerts & third-party analyses
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.