The "claimAllRewards" functions in the MysteryBox contract have a problem that could make them very expensive to use. Eventually, if a user has collected many rewards, the function will stop working. The core issue is the inefficient handling of dynamic arrays and the use of the delete keyword to remove rewards.
When the 'delete' keyword is used to remove an element from the array, it only removes the element of a particular index, and the size of the array remains the same; this leads to a problem where the dynamic array keeps growing larger and larger
In the claimAllRewards function, the contract loops through all the rewards a user has collected, which can become expensive if the list is long. The delete operation used to clear all rewards is also costly, further increasing the gas required. If the list of rewards grows large, this function could fail due to running out of gas.
If a user collects many rewards, both functions could stop working because they require too much gas, leading to a Denial of Service (DoS) situation. This means users would not be able to claim their rewards.
Let a user collect a large number of rewards.
Try to call either the claimSingleReward or claimAllRewards function.
You will Notice the gas costs become very high, and eventually, the transaction fails because it runs out of gas.
1. Claiming Rewards in Smaller Steps: In claimAllRewards, instead of claiming all rewards in one transaction, allow users to claim their rewards over multiple transactions. This will spread out the gas costs.
2. Better Way to Remove Rewards: Instead of using delete in both functions, use a more efficient method. One way is to replace the reward you want to remove with the last reward in the list, and then remove the last reward using pop(). This is much cheaper.
Example:
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.