Mystery Box

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

Dynamic Rewards Not Accounted for in openBox Function

Summary

The openBox function does not account for dynamically added rewards by the owner. It only distributes predefined rewards (Gold, Silver, Bronze, and Coal), ignoring any additional rewards added to the rewardPool by the owner.

Vulnerability Details

The function currently uses a hardcoded probability distribution to assign predefined rewards to users when they open a box. This implementation does not consider any rewards that the owner may have added to the rewardPool after the contract deployment.

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

  • Users will not receive any of the dynamically added rewards, which limits the functionality and flexibility of the contract.

  • Users may feel misled if they are not able to receive the newly added rewards, leading to a loss of trust in the contract.

  • The owner's efforts to add new rewards to the rewardPool will be in vain as these rewards will never be distributed.

Proof Of Concept

Using Remix IDE:

  1. Deployed the MysteryBox contract.

  2. Added a new reward to the rewardPool using the addReward function.

  3. Called the openBox function and observed that the new reward is never distributed.

Tools Used

  • Manual Review

  • Remix IDE

Recommendations

This approach allows for dynamic probability adjustment for existing and new rewards:

function openBox() public {
require(boxesOwned[msg.sender] > 0, "No boxes to open");
// uint256 randomValue = consider using Chainlink VRF for true randomness
// Use the rewardPool for distribution
uint256 totalWeight = rewardPool.length;
uint256 rewardIndex = randomValue % totalWeight;
// Add the selected reward to the user's rewards
rewardsOwned[msg.sender].push(rewardPool[rewardIndex]);
boxesOwned[msg.sender] -= 1;
emit BoxOpened(msg.sender, rewardPool[rewardIndex].name, rewardPool[rewardIndex].value);
}
// Add this event at the contract level
event BoxOpened(address indexed user, string rewardName, uint256 rewardValue);
Updates

Appeal created

inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

addReward won't have any effect on openBox

Support

FAQs

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

Give us feedback!