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

`PuppyRaffle::winnerIndex` randomizing issue

Summary

The PuppyRaffle::winnerIndex variable does not select a truly random winner. Off-chain solutions are recommended.

Vulnerability Details

uint256 winnerIndex = uint256(
keccak256(
abi.encodePacked(msg.sender, block.timestamp, block.difficulty)
)
) % players.length;

The PuppyRaffle::winnerIndex variable selects a random winner index by using an onchain randomizing method. This method can be used by an attacker to theoretically select a specific winner by manipulating msg.sender, block.timestamp, block.difficulty parameters. On top of that, this function does not have an access controller which allows an attacker to attack.

Impact

Here is my PoC that shows an attacker can call the selectWinner function

address attackerAddress = address(7);
modifier playersEntered() {
address[] memory players = new address[](4);
players[0] = playerOne;
players[1] = playerTwo;
players[2] = playerThree;
players[3] = playerFour;
puppyRaffle.enterRaffle{value: entranceFee * 4}(players);
_;
}
function testSelectWinner() public playersEntered {
vm.warp(block.timestamp + duration + 1);
vm.roll(block.number + 1);
vm.prank(attackerAddress);
puppyRaffle.selectWinner();
assertEq(puppyRaffle.previousWinner(), playerFour);
}

Tools Used

  • Manual Analysis

Recommendations

1 - Use an acess controller on selectWinner function.

2 - Use off-chain solutions to achieve true random values.(Ex. Chainlink VRF)

Updates

Lead Judging Commences

Hamiltonite Lead Judge over 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

weak-randomness

Root cause: bad RNG Impact: manipulate winner

Support

FAQs

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