Reproduced Exploit
RipIt: A spin with prizeCount=2 makes SpinLottery's min-guarantee reserve the lone scarce high-ra
Chain
Other
Category
untagged
Date
Jan 1970
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: 62541-h-04-dos-risk-from-pending-prize-locking-mechanism-pashov-au. The historical source/toolchain is unavailable; this entry is documentation only and claims no executable Forge PoC.
Vulnerability classes: vuln/locked-funds
Reproduction: a faithful minimal reproduction of the vulnerable finding — the vulnerable function is reproduced verbatim (marked
@>) with faithful minimal doubles; local deploy, no fork.
Root cause#
A spin with prizeCount=2 makes SpinLottery's min-guarantee reserve the lone scarce high-rarity prize (whose weighted allocation is 0), locking the whole supply as pending so every subsequent user's spin reverts InsufficientPrizes — a temporary DoS; 1 scarce prize is marked locked to the SINK and UserB's spin actually reverts, while deleting the min-guarantee line lets UserB spin succeed.
uint256 pendingCount = (_prizeCount * weight) / totalWeight;
// Ensure at least some prizes are allocated if weights allow it
if (_prizeCount > 1 && pendingCount == 0 && weight > 0) { // @> min-guarantee reserves a scarce prize even when the weighted allocation is 0 -> locks the whole scarce supply
pendingCount = 1;
}
Why it's exploitable here#
A spin with prizeCount=2 makes SpinLottery's min-guarantee reserve the lone scarce high-rarity prize (whose weighted allocation is 0), locking the whole supply as pending so every subsequent user's spin reverts InsufficientPrizes — a temporary DoS; 1 scarce prize is marked locked to the SINK and UserB's spin actually reverts, while deleting the min-guarantee line lets UserB spin succeed.
Attack path#
Marked-line walkthrough (Playground)#
The EVM Playground pins each step to the exact executed source line in 0x8ea53755a6…:
- L78 — Configure a rarity tier: Setup: admin sets a rarity's weight, price, and prize supply — the scarce high-rarity tier gets very few prizes.
- L94 — Sum active rarity weights: Setup: helper that totals the weights of all active rarities, used to size each spin's allocation.
- L111 — Read total active weight: Caches the summed active weight before computing how many prizes each rarity should reserve for this spin.
- L115 — Min-guarantee reserves a scarce prize: Root-cause: this min-guarantee force-reserves 1 prize whenever a weighted allocation rounds to 0, locking the lone scarce prize's whole supply as pending.
- L126 — Loop over rarity tiers: Iterates every rarity tier to accumulate the reservations computed above.
- L135 — Check tier has reservations: Gates the commit on tiers that actually reserved prizes this spin.
- L149 — Commit reserved pending counts: Adds the reserved amounts into each pool's
pendingCount; the force-reserved scarce prize now sits locked, so later spins revert InsufficientPrizes.
PoC#
Registry (Foundry, local deploy — verbatim vulnerable source + harm-asserting test + negative control):
cd 62541-h-04-dos-risk-from-pending-prize-locking-mechanism-pashov-au_exp
forge test -vvv
The browser Playground replays the same synthetic opcode-for-opcode and measures the harm: A spin with prizeCount=2 makes SpinLottery's min-guarantee reserve the lone scarce high-rarity prize (whose weighted allocation is 0), locki. Both gates are green (registry forge test PASS + Playground _verify-poc VERDICT: PASS).
Sources & further analysis#
Reproductions & code
- No executable Forge reproduction is claimed; the historical source/toolchain was unavailable for this finding.
- AuditVault finding: 62541-h-04-dos-risk-from-pending-prize-locking-mechanism-pashov-au.
- Upstream DeFiHackLabs PoC directory: src/test.
Alerts & third-party analyses
- DeFiHackLabs incident explorer: search "RipIt: A spin with prizeCount=2 makes SpinLottery's min-guarantee reserve the lone scarce high-ra".
- 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.