For the complete documentation index, see llms.txt. This page is also available as Markdown.

52706 sc low multi quantity prize claims revert until all winners are drawn freezing early winners

Submitted on Aug 12th 2025 at 14:36:49 UTC by @wellbyt3 for Attackathon | Plume Network

  • Report ID: #52706

  • Report Type: Smart Contract

  • Report severity: Low

  • Target: https://github.com/immunefi-team/attackathon-plume-network/blob/main/plume/src/spin/Raffle.sol

  • Impacts: Temporary freezing of funds for at least 1 hour

Description

Brief/Intro

claimPrize() reverts for multi-quantity prizes until all winners are drawn, so early winners (e.g., week 1 of a 4-week raffle) can’t claim until the final draw, temporarily freezing their prize.

Vulnerability Details

When a raffle participant wins a prize, they call claimPrize() to claim the prize they won.

However, this call will revert if the quantity of the prize is > 1 and all the winners haven't been drawn:

function claimPrize(uint256 prizeId, uint256 winnerIndex) external {
     if (prizes[prizeId].isActive && winnersDrawn[prizeId] < prizes[prizeId].quantity) {
            revert WinnerNotDrawn();
        }
...SNIP...
}

This causes an issue if the same prize is intended to be distributed (for example once a week for 4 weeks).

A user who wins the prize in week 1 won't be able to claim until after the week 4 prize has been drawn, temporarily freezing the prize they're entitled to.

Impact Details

Temporary freezing of funds (i.e., raffle prizes).

References

https://github.com/immunefi-team/attackathon-plume-network/blob/580cc6d61b08a728bd98f11b9a2140b84f41c802/plume/src/spin/Raffle.sol#L298-L301

Proof of Concept

Repro test (Forge)

Add a new .t.sol file to /plume/test/, paste the code below, then run:

forge test --mt test_userCannotClaimPrizeIfNotAllWinnersDrawn -vv

Reproduction Steps

1

Step 1 — Setup and spin

  • Fund user with test ETH and have them call spin.startSpin{value: 2 ether}().

  • Simulate randomness callback so the user acquires raffle tickets.

2

Step 2 — Add multi-quantity prize

  • Admin adds a prize with quantity = 2 via raffle.addPrize(...).

3

Step 3 — Spend raffle tickets

  • The user spends raffle tickets on the prize (raffle.spendRaffle(prizeId, amount)).

4

Step 4 — Request and draw first winner

  • Admin requests a winner for the prize (raffle.requestWinner(prizeId)).

  • Simulate the RNG callback and ensure the first winner is the user.

5

Step 5 — Attempt to claim

  • The user calls raffle.claimPrize(prizeId, winnerIndex) and the call reverts with WinnerNotDrawn because winnersDrawn[prizeId] < prizes[prizeId].quantity.

Notes

  • This is a logical bug that causes early winners of multi-quantity prizes to be unable to claim their prize until the final winner has been drawn (temporarily freezing the prize).

  • Severity assessed as Low, impact is temporary freezing of prizes until draws complete.

Was this helpful?