Puppy Raffle

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

Refunded players set to `address(0)` instead of removed → sparse array wastes gas and `selectWinner()` can pick zero address

Description

  • Normal: Refunding a player should remove them from the players[] array to keep it compact.

  • Bug: refund() sets players[playerIndex] = address(0) — a hole in the array. Operations iterating players[] waste gas on zero-address entries, and selectWinner() can randomly land on address(0).

// src/PuppyRaffle.sol:103
players[playerIndex] = address(0); //@> Leaves a hole — array never compacts

Risk

Likelihood:

  • Every refund creates a hole — the more refunds, the sparser the array

  • With a typical refund rate, the array becomes majority address(0) entries

  • selectWinner() selects a random index — probability of hitting address(0) increases with each refund

Impact:

  • Gas waste: every enterRaffle() scans all zero entries during duplicate check

  • selectWinner() may pick address(0) — prize distribution bricks, no winner gets the NFT

  • Array only grows, never shrinks — gas cost compounds over the raffle's lifetime

Proof of Concept

After 5 players enter and 3 refund:

  • players = [0x0, 0x0, player3, 0x0, player5]

  • selectWinner() has a 3/5 chance of picking address(0)

  • Every enterRaffle() scans all 5 entries (including 3 zeroes) in O(n²)

Recommended Mitigation

function refund(uint256 playerIndex) public {
address playerAddress = players[playerIndex];
require(playerAddress == msg.sender);
require(playerAddress != address(0));
- players[playerIndex] = address(0);
+ players[playerIndex] = players[players.length - 1];
+ players.pop();
payable(msg.sender).sendValue(entranceFee);
emit RaffleRefunded(playerAddress);
}
Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge about 2 hours 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!