Skip to content

Conversation

@yogurtandjam
Copy link
Contributor

  • emit currentStreak on spin complete
  • restoreSTreak also sets last spin timestamp

Copilot AI review requested due to automatic review settings October 17, 2025 16:12
@octane-security-app
Copy link

Summary by Octane

New Contracts

No new contracts were added in this PR.

Updated Contracts

  • Spin.sol: The SpinCompleted event now includes currentStreak, and restoreStreak updates lastSpinTimestamp.

🔗 Commit Hash: 70962a7

@yogurtandjam yogurtandjam merged commit 358eefe into main Oct 17, 2025
2 checks passed
@yogurtandjam yogurtandjam deleted the jerms/fix-restore-streak branch October 17, 2025 16:12
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Adds current streak information to the SpinCompleted event and ensures admin streak restoration updates last spin timestamp.

  • Extend SpinCompleted event with currentStreak parameter and emit it.
  • Update restoreStreak and restoreStreaks to also set lastSpinTimestamp.
  • No input validation added for new/changed behaviors.

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment on lines +73 to +75
event SpinCompleted(
address indexed walletAddress, string rewardCategory, uint256 rewardAmount, uint256 currentStreak
);
Copy link

Copilot AI Oct 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changing the SpinCompleted event signature (adding currentStreak) is a breaking change for off-chain consumers relying on the previous ABI. Consider adding a new event (e.g., SpinCompletedV2) and emitting both during a transition period, or clearly documenting the migration requirement.

Copilot uses AI. Check for mistakes.
Comment on lines 328 to 333

function restoreStreak(address user, uint256 streak) external onlyRole(ADMIN_ROLE) {
userData[user].streakCount = streak;
userData[user].lastSpinTimestamp = block.timestamp;
}

Copy link

Copilot AI Oct 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] restoreStreak now also updates lastSpinTimestamp but the function name and (presumed) existing documentation suggest only streak restoration. Add a comment clarifying this side-effect or rename if broader state restoration is intended.

Suggested change
function restoreStreak(address user, uint256 streak) external onlyRole(ADMIN_ROLE) {
userData[user].streakCount = streak;
userData[user].lastSpinTimestamp = block.timestamp;
}
/**
* @notice Restores a user's streak count and also updates their lastSpinTimestamp to the current block timestamp.
* This function has the side-effect of resetting the user's last spin time.
*/
function restoreStreak(address user, uint256 streak) external onlyRole(ADMIN_ROLE) {
userData[user].streakCount = streak;
userData[user].lastSpinTimestamp = block.timestamp;
}
/**
* @notice Restores multiple users' streak counts and also updates their lastSpinTimestamp to the current block timestamp.
* This function has the side-effect of resetting each user's last spin time.
*/

Copilot uses AI. Check for mistakes.
Comment on lines 334 to 339
function restoreStreaks(address[] memory users, uint256[] memory streaks) external onlyRole(ADMIN_ROLE) {
for (uint256 i = 0; i < users.length; i++) {
userData[users[i]].streakCount = streaks[i];
userData[users[i]].lastSpinTimestamp = block.timestamp;
}
}
Copy link

Copilot AI Oct 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing validation that users and streaks arrays have equal length; a mismatch will either revert (out-of-bounds) or silently ignore extra streak entries. Add a require(users.length == streaks.length, 'Length mismatch') before the loop for clearer input validation.

Copilot uses AI. Check for mistakes.
Comment on lines 334 to 339
function restoreStreaks(address[] memory users, uint256[] memory streaks) external onlyRole(ADMIN_ROLE) {
for (uint256 i = 0; i < users.length; i++) {
userData[users[i]].streakCount = streaks[i];
userData[users[i]].lastSpinTimestamp = block.timestamp;
}
}
Copy link

Copilot AI Oct 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Similar to restoreStreak, this batch function now alters both streakCount and lastSpinTimestamp; add a comment explaining why timestamp is reset during restoration to avoid confusion for maintainers.

Copilot uses AI. Check for mistakes.
@octane-security-app
Copy link

Overview

Vulnerabilities found: 2                                                                                
Severity breakdown: 1 Medium, 1 Low
Warnings found: 5                                                                                

Detailed findings

plume/src/spin/Spin.sol

  • Timestamp-dependent reward evaluation in Spin.determineReward/handleRandomness allows timing control to bias jackpot odds and payouts. See more
  • Stale streakCount read before update in Spin.handleRandomness jackpot eligibility causes mis-awarded jackpot and protocol fund loss. See more

Warnings

plume/src/spin/Spin.sol

  • Payout transfer revert in Spin.handleRandomness causes per-user startSpin lock due to pending flag rollback. See more
  • Missing nonce validation/binding in Spin oracle integration causes user fee loss and reward misbinding. See more
  • Missing address validation in Spin.initialize causes core spin DoS. See more
  • uint8 week-number truncation in Spin.determineReward causes zero or unintended jackpot payouts. See more
  • Missing array length check in Spin.handleRandomness causes pending spin DoS. See more

🔗 Commit Hash: 70962a7
🛡️ Octane Dashboard: All vulnerabilities

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants