enterRaffle() (line 79) pushes every submitted address into players with no validation against address(0):
A zero-address entry is uniquely toxic because it can never be removed: refund() requires playerAddress == msg.sender, and msg.sender can never be address(0). The slot persists for the whole round.
In selectWinner(), if winnerIndex lands on the zero slot, winner is address(0). The prize transfer winner.call{value: prizePool} to address(0) succeeds (burning the ETH), but _safeMint(address(0), tokenId) (line 153) reverts with ERC721: mint to the zero address — rolling back the entire selectWinner() call. Every draw attempt that picks the zero slot fails, delaying the raffle and wasting callers' gas. Combined with the predictable randomness (H-3), the griefing can even be targeted at specific rounds.
Likelihood: Medium — anyone can plant the zero address for the cost of one entrance fee; no privileged access needed.
Impact: Medium — raffle draws that pick the zero slot revert, griefing the round and burning gas; the entry itself can never be refunded or removed.
The Foundry test below demonstrates the griefing:
Four players enter, including address(0) at index 2, paying 4 ETH.
Time warps past the raffle duration.
Timestamps are scanned to find one where the public winner formula (keccak256(caller, timestamp, difficulty) % 4) lands on index 2.
A caller invokes selectWinner() at that timestamp — it reverts on the _safeMint(address(0)) path.
Test assertions and measured result (forge test --match-test test_PoC_R3_AddressZeroPlayerBricksRaffle):
address(0) is accepted as a player at index 2,
selectWinner() reverts when the zero slot is picked as winner.
Reject the zero address at entry. With no address(0) ever in the array, every player is a real account that can receive the NFT, so the _safeMint zero-address revert path becomes unreachable and the unrefundable-slot problem disappears.
The contest is live. Earn rewards by submitting a finding.
Submissions are being reviewed by our AI judge. Results will be available in a few minutes.
View all submissionsThe contest is complete and the rewards are being distributed.