It is possible to prevent users from entering the raffle under various conditions. These can arise due to the intended use of the protocol or via an attacker.
The severity was selected as high since an attacker could easily prevent this contract from minting NFT tokens in the future, potentially affecting the value of previous winner's tokens.
Under all scenarios, the reason why this occurs is because there will be at least two 'holes', or two zero address entries, in the players storage array. This will fail the duplicates check in enterRaffle -- shown below:
Some scenarios that produce this state include:
At least two users successfully refund.
A user enters the raffle with a zero address & at least one user requests a refund.
Test scenarios below:
Two scenarios before users are prevented from entering the raffle:
Less than 4 players have entered:
The raffle can never end/restart since selectWinner cannot be called (requires more than 4 players). While users that have entered, are able to refund their ETH, the PuppyRaffle contract will not be able to mint any tokens in the future. Would have to consider redeploying the contract.
More than 4 players have entered:
selectWinner can be called and the raffle can be restarted.
Foundry.
Alter storage layout of contract.
Use a mapping instead of an array of addresses to track the players that have entered the raffle (or refunded). Example: mapping(address => bool) playerEntered;.
Use a variable to track the number of players entered (this can be slot packed to save gas) for determining the winnerIndex in selectWinner instead of players.length: Example: uint16 totalPlayers;
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.