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

Address(0) can enterRaffle

Summary

Player with address(0) can enterRaffle

Vulnerability Details

When we call function enterRaffle with an array of address newPlayers, one of value in newPlayers can be address(0)

POC:

function testCanEnterRaffleWithAddress0() public {
address[] memory players = new address[](2);
players[1] = playerTwo;
puppyRaffle.enterRaffle{value: entranceFee * 2}(players);
console.log("Player: ", players[0]);
}

Output:

[⠢] Compiling...
[⠢] Compiling 1 files with 0.7.6
[⠆] Solc 0.7.6 finished in 2.00s
Running 1 test for test/PuppyRaffleTest.t.sol:PuppyRaffleTest
[PASS] testCanEnterRaffleWithAddress0() (gas: 71055)
Logs:
Player: 0x0000000000000000000000000000000000000000
Traces:
[71055] PuppyRaffleTest::testCanEnterRaffleWithAddress0()
├─ [51058] PuppyRaffle::enterRaffle{value: 2000000000000000000}([0x0000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000002])
│ ├─ emit RaffleEnter(newPlayers: [0x0000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000002])
│ └─ ← ()
├─ [0] console::log(Player: , 0x0000000000000000000000000000000000000000) [staticcall]
│ └─ ← ()
└─ ← ()
Test result: ok. 1 passed; 0 failed; 0 skipped; finished in 5.83ms
Ran 1 test suites: 1 tests passed, 0 failed, 0 skipped (1 total tests)

Impact

Address(0) can be a player and also be a winner.

Tools Used

Foundry

Recommendations

Check if one of players is address(0) or not

function enterRaffle(address[] memory newPlayers) public payable {
+ for (uint256 i = 0; i <= newPlayers.length - 1; i++) {
+ require(newPlayers[i] != address(0), "PuppyRaffle: Empty players");
+ }
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);
}

TEST:

function testCanEnterRaffleWithAddress0() public {
address[] memory players = new address[](2);
players[1] = playerTwo;
vm.expectRevert("PuppyRaffle: Empty players");
puppyRaffle.enterRaffle{value: entranceFee * 2}(players);
console.log("Player: ", players[0]);
}

RESULT:

[⠆] Compiling...
[⠘] Compiling 3 files with 0.7.6
[⠃] Solc 0.7.6 finished in 2.52s
Running 1 test for test/PuppyRaffleTest.t.sol:PuppyRaffleTest
[PASS] testCanEnterRaffleWithAddress0() (gas: 23737)
Logs:
Player: 0x0000000000000000000000000000000000000000
Traces:
[23737] PuppyRaffleTest::testCanEnterRaffleWithAddress0()
├─ [0] VM::expectRevert(PuppyRaffle: Empty players)
│ └─ ← ()
├─ [790] PuppyRaffle::enterRaffle{value: 2000000000000000000}([0x0000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000002])
│ └─ ← "PuppyRaffle: Empty players"
├─ [0] console::log(Player: , 0x0000000000000000000000000000000000000000) [staticcall]
│ └─ ← ()
└─ ← ()
Test result: ok. 1 passed; 0 failed; 0 skipped; finished in 7.53ms
Ran 1 test suites: 1 tests passed, 0 failed, 0 skipped (1 total tests)
Updates

Lead Judging Commences

Hamiltonite Lead Judge almost 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.