Beginner FriendlyFoundryNFT
100 EXP
View results
Submission Details
Severity: high
Valid

enterRaffle accepts Zero Address

Summary

The PuppyRaffle::enterRaffle function doesn't check if an entered address is equal to Zero Address. If the PuppyRaffle::selectWinner function chooses the Zero Address as winner, the transaction will revert.

Vulnerability Details

The function PuppyRaffle::enterRaffle accepts as input an array of addresses, but it doesn't check if inside the array there is the Zero Address.

Code
function enterRaffle(address[] memory newPlayers) public payable {
require(msg.value == entranceFee * newPlayers.length, "PuppyRaffle: Must send enough to enter raffle");
for (uint256 i = 0; i < newPlayers.length; i++) {
@> players.push(newPlayers[i]);
}
// Check for duplicates
for (uint256 i = 0; i < players.length - 1; i++) {
for (uint256 j = i + 1; j < players.length; j++) {
require(players[i] != players[j], "PuppyRaffle: Duplicate player");
}
}
emit RaffleEnter(newPlayers);
}

If in the PuppyRaffle::selectWinner function, address Zero is chosen as the winner, _safeMint(winner, tokenId); will revert with the error ERC721: mint to the zero address.

It is possibile to check with this test, before run the test it is necessary to edit manually the smart contract to select the Zero Address as Winner, editing the row 157 inside selectWinner function.

- address winner = players[winnerIndex];
+ address winner = players[0];

and run this test

Code
function testCanAddZeroAddressToPlayersAndRevertSelectWinnerFunction() public {
address[] memory players = new address[](4);
players[0] = address(0);
players[1] = playerOne;
players[2] = playerTwo;
players[3] = playerThree;
puppyRaffle.enterRaffle{value: entranceFee * 4}(players);
assertEq(puppyRaffle.players(0), address(0));
assertEq(puppyRaffle.players(1), playerOne);
assertEq(puppyRaffle.players(2), playerTwo);
assertEq(puppyRaffle.players(3), playerThree);
uint256 expectedPrizeAmount = ((entranceFee * 4) * 20) / 100;
vm.warp(block.timestamp + duration + 1);
vm.roll(block.number + 1);
vm.expectRevert("ERC721: mint to the zero address");
puppyRaffle.selectWinner();
}

Impact

The problem is not of a high level because it only occurs if the Zero address comes out as the winner. If this happens the transaction will fail and it will be enough to relaunch it (or it will be launched automatically n seconds later) and if a valid address is chosen the transaction will go to successful.

Tools Used

  • Foundry

  • Manual check

Recommendations

To fix the problem, just check that no address in the array is equal to Zero Address, and if not, do revert.

Code
function enterRaffle(address[] memory newPlayers) public payable {
require(
msg.value == entranceFee * newPlayers.length,
"PuppyRaffle: Must send enough to enter raffle"
);
for (uint256 i = 0; i < newPlayers.length; i++) {
+ require(
+ newPlayers[i] != address(0),
+ "PuppyRaffle: Zero address cannot participate"
+ );
players.push(newPlayers[i]);
}
// Check for duplicates
for (uint256 i = 0; i < players.length - 1; i++) {
for (uint256 j = i + 1; j < players.length; j++) {
require(
players[i] != players[j],
"PuppyRaffle: Duplicate player"
);
}
}
emit RaffleEnter(newPlayers);
}
Updates

Lead Judging Commences

Hamiltonite Lead Judge about 2 years ago
Submission Judgement Published
Validated
Assigned finding tags:

zero address can win the raffle

Funds are locked to no one. If someone gets the refund issue, they also got this issue. IMPACT: High Likelihood: High

Support

FAQs

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

Give us feedback!