Mystery Box

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

Weak Randomness Leading to Predictable Rewards

Summary

The openBox function uses block timestamp and msg.sender in keccak256 to generate randomness, which can be manipulated by miners or users to predict or influence the outcome of reward selection, compromising the fairness and unpredictability of rewards.

Vulnerability Details

In the MysteryBox.sol contract, the openBox function generates a pseudo-random number as follows:

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;
}

The randomness relies on block.timestamp and msg.sender, both of which are predictable or manipulable:

  • Block Timestamp: Miners have the ability to influence the timestamp within a certain range, allowing them to potentially manipulate the outcome.

  • msg.sender: Users can predict or control their own address, aiding in crafting specific outcomes.

This predictability can be exploited to increase the chances of obtaining rare rewards or manipulating the distribution of rewards.

Impact

An attacker can manipulate the outcome of the openBox function to consistently receive higher-value rewards, such as "Gold Coin" or "Silver Coin." This undermines the fairness of the reward system, leading to potential financial losses for the contract and eroding user trust in the protocol.

PoC

An attacker can repeatedly call the openBox function within the same block or manipulate the block timestamp to influence the randomValue. For example:

// Pseudo-code illustrating the attack
while (!receivedGoldCoin) {
// Manipulate block timestamp if possible
openBox();
if (lastReceivedReward === "Gold Coin") {
break;
}
}

Tools Used

Manual code review

Solidity static analysis tools

Recommendations

Implement a more secure and unpredictable source of randomness. Consider integrating Chainlink VRF (Verifiable Random Function) or a similar decentralized randomness oracle to ensure that the random values cannot be manipulated by any single party.

Updates

Appeal created

inallhonesty Lead Judge about 1 year 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.

Give us feedback!