Mystery Box

First Flight #25
Beginner FriendlyFoundry
100 EXP
View results
Submission Details
Severity: low
Invalid

Incorrect Index Validation in claimSingleReward Function

Summary

The claimSingleReward function incorrectly validates the reward index, allowing out-of-bounds access and potential unintended behavior. Specifically, the comparison should use < instead of <=, leading to acceptance of an index equal to the array length, which is invalid.

Vulnerability Details

In the MysteryBox.sol contract, the claimSingleReward function performs index validation as follows:

function claimSingleReward(uint256 _index) public {
require(_index <= rewardsOwned[msg.sender].length, "Invalid index");
uint256 value = rewardsOwned[msg.sender][_index].value;
require(value > 0, "No reward to claim");
(bool success, ) = payable(msg.sender).call{value: value}("");
require(success, "Transfer failed");
delete rewardsOwned[msg.sender][_index];
}

The condition require(_index <= rewardsOwned[msg.sender].length, "Invalid index"); allows _index to be equal to rewardsOwned[msg.sender].length, which is out of bounds. Accessing rewardsOwned[msg.sender][_index] with an index equal to the array length will cause a runtime error and revert the transaction.

Impact

This prevents users from correctly claiming specific rewards and can result in failed transactions. Users attempting to claim the last reward in the array will encounter an error due to incorrect index validation, leading to a poor user experience.

PoC

Attempting to claim a reward with an index equal to the array length will fail:

// Assume rewardsOwned[msg.sender].length == 2
await mysteryBox.claimSingleReward(2, { from: userAddress });
// Transaction reverts with "Invalid index"

Tools Used

Manual code review

Recommendations

Correct the index validation to ensure that _index is strictly less than the array length, preventing out-of-bounds access.

Revised claimSingleReward function:

function claimSingleReward(uint256 _index) public {
require(_index < rewardsOwned[msg.sender].length, "Invalid index");
uint256 value = rewardsOwned[msg.sender][_index].value;
require(value > 0, "No reward to claim");
// Effects
rewardsOwned[msg.sender][_index].value = 0;
// Interaction
(bool success, ) = payable(msg.sender).call{value: value}("");
require(success, "Transfer failed");
}
Updates

Appeal created

inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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

Give us feedback!