# 51218 sc high oracle callback timing vulnerability causes jackpot prize loss

**Submitted on Aug 1st 2025 at 01:25:02 UTC by @KlosMitSoss for** [**Attackathon | Plume Network**](https://immunefi.com/audit-competition/plume-network-attackathon)

* **Report ID:** #51218
* **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 a callback from the Supra Router is executed, the current week is calculated based on the current timestamp rather than when the spin was initiated. This creates a timing vulnerability where users can start a spin during an active campaign, but the callback executes after the campaign has ended. When such delayed spins win the jackpot, users receive zero rewards despite legitimately winning and paying the spin fee.

### Vulnerability Details

Users who initiate spins in the final weeks of the campaign risk losing legitimately won jackpots due to oracle callback delays beyond their control. The vulnerability occurs in the `handleRandomness()` function:

```solidity
function determineReward(uint256 randomness, uint256 streakForReward) internal view returns (string memory, uint256) {
    ... ...
    uint8 weekNumber = uint8(getCurrentWeek()); // Uses current timestamp, not spin initiation time
    
    if (probability < jackpotThreshold) {
        return ("Jackpot", jackpotPrizes[weekNumber]); // Returns 0 for weeks > 11
    }
    ... ...
}
```

These delays cannot be controlled and will lead to unfair situations for users that didn't do anything wrong and started their spin during the campaign.

To mitigate this, consider using the timestamp of the `startSpin()` call such that the current week only relies on the user and not on the delay between the two calls.

### Impact Details

The won jackpot cannot be claimed even though the user started the spin while the campaign was ongoing. This leads to users losing legitimately won jackpots which are currently worth up to 100,000 PLUME tokens.

### References

Code references are provided throughout the report.

## Proof of Concept

{% stepper %}
{% step %}

### Step

Alice calls `startSpin()` in week 11 of the campaign, which is the last valid week (<https://github.com/immunefi-team/attackathon-plume-network/blob/580cc6d61b08a728bd98f11b9a2140b84f41c802/plume/src/spin/Spin.sol#L174-L195>).
{% endstep %}

{% step %}

### Step

The callback is executed in week 12, meaning the campaign has already ended. Alice wins the jackpot.
{% endstep %}

{% step %}

### Step

In `handleRandomness()`, `determineReward()` is called. Inside this function, the week number is calculated based on the current timestamp, not the timestamp of the `startSpin()` call (<https://github.com/immunefi-team/attackathon-plume-network/blob/580cc6d61b08a728bd98f11b9a2140b84f41c802/plume/src/spin/Spin.sol#L285-L286>).
{% endstep %}

{% step %}

### Step

This week number is used to retrieve the jackpot prize for the week (<https://github.com/immunefi-team/attackathon-plume-network/blob/580cc6d61b08a728bd98f11b9a2140b84f41c802/plume/src/spin/Spin.sol#L293>). However, since the week number is greater than 11 and the campaign only lasts 12 weeks (weeks 0-11), the jackpot prize for week 12 will be 0. The following comment also confirms this: <https://github.com/immunefi-team/attackathon-plume-network/blob/580cc6d61b08a728bd98f11b9a2140b84f41c802/plume/src/spin/Spin.sol#L451>
{% endstep %}

{% step %}

### Step

As a result, Alice wins the jackpot but cannot claim anything, even though she submitted the spin on time while the campaign was ongoing.
{% endstep %}
{% endstepper %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://reports.immunefi.com/plume-or-attackathon/51218-sc-high-oracle-callback-timing-vulnerability-causes-jackpot-prize-loss.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
