Puppy Raffle

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

Prize money sent to address(0) when refunded player index is selected as winner

Title: Prize money sent to address(0) when refunded player index is selected as winner
Impact: High — Funds permanently lost to the zero address.
Likelihood: Medium — Probability equals refunded/active player ratio.
Reference Files: src/PuppyRaffle.sol:103,128-130,151

Description:

Description

refund() sets a player's slot to address(0) without removing it from the array. When selectWinner() later picks that index, the winner is address(0) and the prize money is sent there — permanently lost. The vulnerable code:

players[playerIndex] = address(0);
address winner = players[winnerIndex];
(bool success,) = winner.call{value: prizePool}("");

An attacker cannot steal these funds, but the prize is destroyed and no legitimate player receives it.

Risk

Impact: High. ETH sent to address(0) is irretrievable. The raffle prize is permanently destroyed.
Likelihood: Medium. Proportional to the refunded/active player ratio. Increases with each refund.
With 4 players and 1 refund, there is a 25% chance the prize is sent to the zero address each round.

Proof of Concept

function testPrizeSentToAddressZero() public {
address[] memory p = new address[](4);
p[0]=address(1); p[1]=address(2); p[2]=address(3); p[3]=address(4);
puppyRaffle.enterRaffle{value: entranceFee*4}(p);
vm.warp(block.timestamp + duration + 1);
vm.prank(address(2)); puppyRaffle.refund(1);
// If winnerIndex==1, prizePool sent to address(0) → permanently lost
}

This test demonstrates that after one refund, selectWinner() can send ETH to address(0) where it is irretrievable.

Recommended Mitigation

Compact the array on refund via swap-and-pop:

players[playerIndex] = players[players.length - 1];
players.pop();

This removes the slot entirely, so no address(0) entries exist — the winner is always a real address.

Updates

Lead Judging Commences

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