Mystery Box

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

Users are unable to claim rewards due to insufficient contract balance caused by the owner's withdrawal of funds.

Summary

Users are unable to claim rewards due to insufficient contract balance caused by the owner's withdrawal of funds.

Vulnerability Details

The issue arises when users, after winning rewards, attempt to claim them but are unable to due to insufficient contract balance. This occurs because the contract owner has withdrawn the majority or all of the funds, leaving the contract without enough balance to fulfill users' reward claims.
This becomes critical when users have won valuable rewards such as Gold Coins (1 ether), but the contract no longer holds enough ether to cover these claims.

Impact

Users who have won rewards may be permanently unable to claim them due to low or zero contract balance, which has already been withdrawn by the contract owner. This can result in users losing their prizes and undermines the trust in the system.

POC

function testClaimAllRewards_NotEnoughContractBalance_OwnerClaims() public {
address randomUser = makeAddr("randomUser");
vm.deal(randomUser, 2 ether);
for (uint256 i = 0; i < 20; i++) {
vm.prank(randomUser);
mysteryBox.buyBox{value: 0.1 ether}();
}
vm.deal(user1, 1 ether);
vm.startPrank(user1);
mysteryBox.buyBox{value: 0.1 ether}();
vm.warp(26);
// Open the box to win a reward
mysteryBox.openBox();
// Ensure the user has at least one reward
uint256 rewardCount = mysteryBox.getRewards().length;
assertGt(rewardCount, 0, "User should have at least one reward after opening a box");
uint256 totalValue = 0;
///////// calculate all reward value
for (uint256 i = 0; i < mysteryBox.getRewards().length; i++) {
totalValue += mysteryBox.getRewards()[i].value;
}
vm.stopPrank();
// contract owner withdraws all funds before reward owner could withraw their funds
vm.prank(owner);
mysteryBox.withdrawFunds();
/// call revert due to contract being out of balance
vm.expectRevert();
vm.startPrank(user1);
mysteryBox.claimAllRewards();
vm.stopPrank();
}

Tools Used

Manual review

Recommendations

The protocol should ensure that the contract maintains a sufficient balance to cover all outstanding rewards. This can be done by:

  1. Implementing checks that prevent the contract owner from withdrawing funds if there are pending reward claims.

  2. Allocating a specific portion of funds that can only be used for user reward claims.

  3. Improving fund management practices within the contract to ensure user rewards are always claimable.

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!