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

52986 sc high jackpot check uses previous streakcount instead of current computed streak denying jackpot on first eligible day

Submitted on Aug 14th 2025 at 15:10:59 UTC by @daxun for Attackathon | Plume Network

  • Report ID: #52986

  • Report Type: Smart Contract

  • Report severity: High

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

  • Impacts: Contract fails to deliver promised returns, but doesn't lose value

Description

Brief / Intro

During a spin, the contract computes:

  • currentSpinStreak = _computeStreak(user, now, true) (which includes today’s spin)

but verifies jackpot eligibility against the stored userData[user].streakCount (yesterday’s value). On the first day a user reaches the required streak, they can be downgraded to “Nothing”.

Vulnerability Details

In handleRandomness() (simplified):

handleRandomness (simplified)
uint256 currentSpinStreak = _computeStreak(user, block.timestamp, true);
...
if (isJackpot) {
    uint256 currentWeek = getCurrentWeek();
    if (currentWeek == lastJackpotClaimWeek) { ... }
    else if (userDataStorage.streakCount < (currentWeek + 2)) {
        // ↓ uses previous stored streak instead of currentSpinStreak
        rewardCategory = "Nothing"; rewardAmount = 0;
    } else {
        // award jackpot
    }
}
...
userDataStorage.streakCount = currentSpinStreak; // updated only after the check

Because userDataStorage.streakCount is updated after the check, a user who just reached the required streak today is unfairly denied.

Impact Details

  • Immunefi Impact: Low — Contract fails to deliver promised returns, but doesn't lose value

  • Users meeting the milestone can miss the jackpot exactly on the day it should be awarded.

Proof of Concept

1

Scenario setup

Assume requiredStreak = currentWeek + 2 = 5.

2

Yesterday's stored streak

Yesterday’s stored userData[user].streakCount == 4 (consecutive).

3

Today's computed streak

Today, _computeStreak(..., true) returns 5.

4

Jackpot check uses stored value

Jackpot path checks userDataStorage.streakCount < 5true, so it sets reward to “Nothing”.

5

streakCount updated after check

Only after the check, it writes userDataStorage.streakCount = 5.

6

Net result

Net: user is denied the jackpot today, despite meeting the requirement.

References

  • handleRandomness() source: https://github.com/immunefi-team/attackathon-plume-network/blob/580cc6d61b08a728bd98f11b9a2140b84f41c802/plume/src/spin/Spin.sol#L207-L265

Was this helpful?