Puppy Raffle

AI First Flight #1
Beginner FriendlyFoundrySolidityNFT
EXP
View results
Submission Details
Severity: high
Valid

Refunded Player Addresses Set to Zero Allow Prize Pool to Be Burned

Description

The selectWinner() function is designed to randomly select a winner from the players array and send them the prize pool. The function should only select valid participant addresses.

When a player calls refund(), their address in the array is replaced with address(0) rather than being removed. The selectWinner() function does not validate that the selected winner is a non-zero address, allowing the prize pool to be sent to address(0) and permanently burned.

function refund(uint256 playerIndex) public {
address playerAddress = players[playerIndex];
require(playerAddress == msg.sender, "PuppyRaffle: Only the player can refund");
require(playerAddress != address(0), "PuppyRaffle: Player already refunded, or is not active");
payable(msg.sender).sendValue(entranceFee);
@> players[playerIndex] = address(0); // Sets to zero address instead of removing
emit RaffleRefunded(playerAddress);
}
function selectWinner() external {
// ... winner selection logic ...
@> address winner = players[winnerIndex]; // No check for address(0)
// ...
@> (bool success,) = winner.call{value: prizePool}(""); // Sends to address(0)
}

Risk

Likelihood: Medium

  • Any player can refund at any time during the raffle, creating zero-address slots in the array

  • The random winner selection has no exclusion logic for zero addresses

Impact: High

  • Complete and permanent loss of the entire prize pool

  • All participants lose their potential winnings

Proof of Concept

  1. Alice enters the raffle and is assigned index 7 in the players array

  2. Alice decides to refund her entry by calling refund(7)

  3. Her address at index 7 is replaced with address(0)

  4. The raffle ends and selectWinner() is called

  5. The random winner index calculation returns 7

  6. The prize pool is sent to address(0), permanently burning all funds

Recommended Mitigation

function selectWinner() external {
// ... winner selection logic ...
address winner = players[winnerIndex];
+ require(winner != address(0), "PuppyRaffle: Invalid winner, please retry");
// ...
}

Alternatively, properly remove players from the array in refund():

function refund(uint256 playerIndex) public {
// ... existing checks ...
- players[playerIndex] = address(0);
+ players[playerIndex] = players[players.length - 1];
+ players.pop();
emit RaffleRefunded(playerAddress);
}
Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge about 1 hour ago
Submission Judgement Published
Validated
Assigned finding tags:

[H-01] Potential Loss of Funds During Prize Pool Distribution

## Description In the `selectWinner` function, when a player has refunded and their address is replaced with address(0), the prize money may be sent to address(0), resulting in fund loss. ## Vulnerability Details In the `refund` function if a user wants to refund his money then he will be given his money back and his address in the array will be replaced with `address(0)`. So lets say `Alice` entered in the raffle and later decided to refund her money then her address in the `player` array will be replaced with `address(0)`. And lets consider that her index in the array is `7th` so currently there is `address(0)` at `7th index`, so when `selectWinner` function will be called there isn't any kind of check that this 7th index can't be the winner so if this `7th` index will be declared as winner then all the prize will be sent to him which will actually lost as it will be sent to `address(0)` ## Impact Loss of funds if they are sent to address(0), posing a financial risk. ## Recommendations Implement additional checks in the `selectWinner` function to ensure that prize money is not sent to `address(0)`

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!