diff --git a/plume/SPIN.md b/plume/SPIN.md index e02b25b5..6e442b9b 100644 --- a/plume/SPIN.md +++ b/plume/SPIN.md @@ -132,6 +132,7 @@ The contract calculates a user's streak of consecutive daily spins to reward con | `startSpin()` | User-callable function to initiate a spin by sending the required `spinPrice`. | Public | | `handleRandomness(...)` | The callback function for the Supra oracle. Processes the spin result and updates user state. | `SUPRA_ROLE` | | `spendRaffleTickets(...)` | Allows the `Raffle` contract to deduct tickets from a user's balance. | `raffleContract` only | +| `addRaffleTickets(...)` | Allows the admin to add tickets to a user's balance. | `ADMIN_ROLE` | | `pause()` / `unpause()` | Pauses or unpauses the `startSpin` functionality. | `ADMIN_ROLE` | | `adminWithdraw(...)` | Allows admin to withdraw PLUME tokens from the contract balance. | `ADMIN_ROLE` | | `cancelPendingSpin(address user)` | Escape hatch to cancel a user's spin request that is stuck pending an oracle callback. | `ADMIN_ROLE` | @@ -145,6 +146,7 @@ The contract calculates a user's streak of consecutive daily spins to reward con - `SpinRequested(uint256 indexed nonce, address indexed user)`: Emitted when a user successfully initiates a spin. - `SpinCompleted(address indexed walletAddress, string rewardCategory, uint256 rewardAmount)`: Emitted after the oracle callback is processed, detailing the reward. - `RaffleTicketsSpent(address indexed walletAddress, uint256 ticketsUsed, uint256 remainingTickets)`: Emitted when the `Raffle` contract spends a user's tickets. +- `RaffleTicketsAdded(address indexed walletAddress, uint256 ticketsAdded, uint256 newBalance)`: Emitted when an admin adds tickets to a user's balance. - `NotEnoughStreak(string message)`: Emitted if a user meets the odds for a jackpot but does not have the required streak count. - `JackpotAlreadyClaimed(string message)`: Emitted if a user meets the odds for a jackpot but it has already been won that week. diff --git a/plume/src/spin/Spin.sol b/plume/src/spin/Spin.sol index 63c5f53c..26dff38a 100644 --- a/plume/src/spin/Spin.sol +++ b/plume/src/spin/Spin.sol @@ -36,8 +36,8 @@ contract Spin is uint256 plumeTokenThreshold; // Range start depends on daily jackpot threshold, ends here. uint256 raffleTicketThreshold; // Starts after plumeTokenThreshold, ends here. uint256 ppThreshold; // Starts after raffleTicketThreshold, ends here. - // anything above ppThreshold is "Nothing" } + // anything above ppThreshold is "Nothing" // Roles bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE"); @@ -74,6 +74,7 @@ contract Spin is address indexed walletAddress, string rewardCategory, uint256 rewardAmount, uint256 currentStreak ); event RaffleTicketsSpent(address indexed walletAddress, uint256 ticketsUsed, uint256 remainingTickets); + event RaffleTicketsAdded(address indexed walletAddress, uint256 ticketsAdded, uint256 newBalance); event NotEnoughStreak(string message); event JackpotAlreadyClaimed(string message); @@ -132,8 +133,8 @@ contract Spin is plumeTokenThreshold: 200_000, // Up to 200,000 (Approx 20%) raffleTicketThreshold: 600_000, // Up to 600,000 (Approx 40%) ppThreshold: 900_000 // Up to 900,000 (Approx 30%) - // Above 900,000 is "Nothing" (Approx 10%) }); + // Above 900,000 is "Nothing" (Approx 10%) } /// @notice Ensures that the user can only spin once per day by checking their last spin date. @@ -353,6 +354,15 @@ contract Spin is emit RaffleTicketsSpent(user, amount, userDataStorage.raffleTicketsBalance); } + /// @notice Allows the admin to add tickets to a user\'s balance. + function addRaffleTickets(address user, uint256 amount) external onlyRole(ADMIN_ROLE) { + require(user != address(0), "Invalid user address"); + UserData storage userDataStorage = userData[user]; + userDataStorage.raffleTicketsBalance += amount; + userDataStorage.raffleTicketsGained += amount; + emit RaffleTicketsAdded(user, amount, userDataStorage.raffleTicketsBalance); + } + /// @notice Allows the admin to withdraw PLUME tokens from the contract. function adminWithdraw(address payable recipient, uint256 amount) external onlyRole(ADMIN_ROLE) { require(recipient != address(0), "Invalid recipient address");