Immunefi Audit Competitions
Plume | Attackathon

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

High severity: Jackpot eligibility check uses stored streakCount (previous value) instead of the freshly computed streak that includes today's spin.

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

Scenario setup

Assume requiredStreak = currentWeek + 2 = 5.

Yesterday's stored streak

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

Today's computed streak

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

Jackpot check uses stored value

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

streakCount updated after check

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

Net result

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

References