Mystery Box

First Flight #25
Beginner FriendlyFoundry
100 EXP
View results
Submission Details
Severity: medium
Valid

[M-1] Weak Randomness in `MysteryBox::openBox`

Summary

The openBox function is in charge of determining the reward that the user receives upon opening the box they bought. It does that but calculating a random number and depending on that number is the reward that the user gets. However, determining the random number on chain is not possible like such. Hashing the `block.timestamp` and the address of (msg.sender) will create a predictable number on-chain.

Vulnerability Details

function openBox() public {
require(boxesOwned[msg.sender] > 0, "No boxes to open");
// Generate a random number between 0 and 99
@> uint256 randomValue = uint256(keccak256(abi.encodePacked(block.timestamp, msg.sender))) % 100; <@
// Determine the reward based on probability
if (randomValue < 75) {
// 75% chance to get Coal (0-74)
rewardsOwned[msg.sender].push(Reward("Coal", 0 ether));
} else if (randomValue < 95) {
// 20% chance to get Bronze Coin (75-94)
rewardsOwned[msg.sender].push(Reward("Bronze Coin", 0.1 ether));
} else if (randomValue < 99) {
// 4% chance to get Silver Coin (95-98)
rewardsOwned[msg.sender].push(Reward("Silver Coin", 0.5 ether));
} else {
// 1% chance to get Gold Coin (99)
rewardsOwned[msg.sender].push(Reward("Gold Coin", 1 ether));
}
boxesOwned[msg.sender] -= 1;
}

Impact

- Malicious users can manipulate those values, or know what they will be, helping them choose a user the win.
- This also lets users front-run and requesting a refund if they are not the winner.

Tools Used

Manual Review

Recommendations

Consider using a cryptographically provable random number generator such as Chainlink VRF.

Updates

Appeal created

inallhonesty Lead Judge 9 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Weak Randomness

Support

FAQs

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