The owner of the contract has the ability to add new rewards via the MysteryBox::addReward function. However, any rewards added will not be obtainable by players of Mystery Box. This is due to the rewards distribution mechanism in the MysteryBox::openBox function being hard-coded specifically to the rewards set in the constuctor.
Examining the MysteryBox::openBox function below, it can be seen that rewards are allocated according to the if statements predicated on the randomly generated number value.
However, only the four original rewards that were set in the constructor are present and there is no mechanism to include the rewards added later by the owner using the MysteryBox::addReward function.
Any new rewards added by the owner are unobtainable by the players of Mystery Box. Therefore the extensibility of the game is impacted, as the original rewards will be the only rewards that can every be claimed by the players.
Manual review
Rather than hardcoding the probabilities in the Mysterbox::openBox function, weight based probabilities can be used, whereby each MysteryBox::Reward will have a probability weight value. The probability of a reward being received will be the item's probability weight divided by the total probability weight of all rewards.
The update to the MysteryBox::Reward stuct will look as follows:
This tracks the weight of individual rewards, but as aforementioned, the total weight is also required for this selection method to work. It will be used as the new modulus value instead of the magic number value used currently in the MysteryBox::openBox function of 100.
This can be added as a state variable and this variable should be updated in both the MysteryBox::constructor and MysteryBox::addReward as these are the two functions in the contract that add new rewards.
This can be seen below:
MysteryBox::openBox now can be refactored to use probability weights to determine the distribution of rewards. This ensures it is dynamic and can accommodate future reward types that will be added.
As can be seen above, when new rewards are added to the reward pool, e.g. diamond coin as in TestMysteryBox.t.sol::testAddReward. MysteryBox::addReward("Diamond Coin", 2 ether, 1) now the totalProbabilityWeight is 101 and the chance of getting a diamond coin is 1/101, gold 1/101, silver 4/101, bronze 20/101 and coal 75/101. So the probabilities are updated accordingly and all rewards can now be earned by the players.
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.