52560 sc high incorrect current streak used when calculating whether the jackpot should be awarded or not
Submitted on Aug 11th 2025 at 15:47:59 UTC by @swarun for Attackathon | Plume Network
Report ID: #52560
Report Type: Smart Contract
Report severity: High
Target: https://github.com/immunefi-team/attackathon-plume-network/blob/main/plume/src/spin/Spin.sol
Impacts: Theft of unclaimed yield
Description
Brief / Intro
When deciding whether the jackpot should be awarded, the function does not take into account the user's current spin count correctly. This can lead to denial of the jackpot prize to an otherwise eligible user.
Vulnerability Details
When the determineReward function indicates a user is eligible for the jackpot, the contract checks the user's streak against the required threshold. However, that check compares the stored (old) streakCount instead of the computed currentSpinStreak (which already includes the current spin). Because the stored streakCount is updated only after the jackpot eligibility check, the check can use a stale value (one less than the current streak), causing an eligible user to be denied the jackpot.
Impact Details
A user who has satisfied the streak requirement (including the current spin) can be incorrectly prevented from receiving the jackpot prize. Since jackpot wins are rare and valuable, this results in a significant loss for affected users.
Reference
https://github.com/immunefi-team/attackathon-plume-network/blob/580cc6d61b08a728bd98f11b9a2140b84f41c802/plume/src/spin/Spin.sol#L232
Proof of Concept
Step — where the incorrect check happens
determineReward may return ("Jackpot", amount) based on currentSpinStreak. However, the jackpot eligibility guard uses the stored userDataStorage.streakCount (old value) instead of currentSpinStreak:
Since userDataStorage.streakCount is only updated after this check:
the contract may treat a legitimately eligible user as ineligible (stale value), denying the jackpot.
Summary of the bug
determineReward is called with currentSpinStreak (which correctly accounts for the current spin).
The subsequent jackpot eligibility check uses userData.storage.streakCount (old/stale value).
The stored streak is updated only after the check, so users can be incorrectly denied the jackpot even when currentSpinStreak meets the requirement.
Suggested remediation (high level)
Use the computed currentSpinStreak when checking jackpot eligibility (i.e., compare currentSpinStreak to the threshold), or update userDataStorage.streakCount before performing the jackpot eligibility check.
Ensure effect-ordering follows checks that depend on computed ephemeral state.
(End of report)
Was this helpful?