Chain attributes, such as block.timestamp and block.timestamp can be predicted or manipulated, and should thus never be used for random number generation. The block.timestamp is used twice in the PuppyRaffle::selectWinner() function, first to select the winner and again to select the winner's NFT.
The PuppyRaffle::selectWinner() function decides the winnerIndex and NFT rarity based on pseudorandom numbers generated from deterministic information that can be either manipulated or predicted.
PuppyRaffle::L128: uint256 winnerIndex = uint256(keccak256(abi.encodePacked(msg.sender, block.timestamp, block.difficulty))) % players.length;
PuppyRaffle::L139: uint256 rarity = uint256(keccak256(abi.encodePacked(msg.sender, block.difficulty))) % 100;
The Chainlink team have researched and discussed the problems associated with using data form a deterministic blockchain at: https://chain.link/vrf
The two key points are:
Onchain solutions that rely on biasable inputs like blockhashes are at severe risk of being exploited.
You and your users take severe risks of being financially impacted by insecure and biasable RNG techniques.
This will allow a malicious actor to potentially steal the winnings and the rarity of the NFT when the PuppyRaffle::selectWinner() is invoked.
Manual Review and Foundry
The contract should be updated to use an oracle solution such as Chainlink VRF.
Root cause: bad RNG Impact: manipulate winner
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.