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

Bad source of randomness for 'rarity'

Summary

The source of randomness for rarity can be gamed/brute forced to achieve a desired outcome.

Vulnerability Details

Using msg.sender, block.difficulty as a source of randomness is not advised since the outcome can be manipulated. An attacker can use this bad source of randomness to ensure that once they're selected as a winner, they can obtain the highest rarity nft.

The rarity is currently generated as below:

uint256 rarity = uint256(keccak256(abi.encodePacked(msg.sender, block.difficulty))) % 100;

These values are readily available to miners and attackers may retry and brute force until they achieve a desirable result.

An attack path for an attacker to retry the result of bad randomness can look something similar to this:

function attack(uint256 _desiredIndex) external {
address[] memory players = IPuppyRaffle(target).players();
uint256 winnerIndex = uint256(
keccak256(
abi.encodePacked(msg.sender, block.timestamp, block.difficulty)
)
) % players.length;
require(winnerIndex == _desiredIndex, "Not the desired index");
uint256 rarity = uint256(
keccak256(abi.encodePacked(msg.sender, block.difficulty))
) % 100;
require(rarity > 95, "Not rare enough");
IPuppyRaffle(target).selectWinner();
}

The attack requires the attacker to repeatedly call the attack function with data that is known, and the output that is wised for until the results match, and only then continue call the Raffle Contract.

Impact

An attacker can ensure that they are the ones selected as the winner for the raffle and obtain the highest rarity nft, by consecutively attacking the contract to reach a desired outcome. And finally, obtaining the nft and also the prize pool.

Tools Used

Manual review

Recommendations

  • Consider using a decentralized oracle for the generation of random numbers, such as Chainlinks VRF

  • Consider using commit-reveal schemes such as blockhash of a future block, it is less gameable but not foolproof.

Updates

Lead Judging Commences

Hamiltonite Lead Judge about 2 years 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.

Give us feedback!