The transferReward function can be exploited by a malicious user to inflate a victim's rewardsOwned array with zero-value rewards. This can lead to a DoS, making it difficult for the victim to interact with the contract due to the increased gas cost for operations involving the inflated array.
A malicious user can repeatedly transfer zero-value rewards to a victim's account. Each transfer adds a new entry to the victim's rewardsOwned array since deleting the reward from the destination resets the value to 0. Therefore, the transaction goes through because there is no limit or check to prevent this action, allowing the attacker to inflate the array size indefinitely.
If the reward being transferred has zero value, the victim’s rewardsOwned array can be filled with thousands of zero-value rewards, making any operation on the array (such as viewing or claiming rewards) extremely gas-intensive.
This vulnerability can lead to the following issues:
DoS: The victim will face increased gas costs when interacting with their rewards array. If the array is sufficiently large, certain functions like getRewards() will run out of gas and fail.
User Frustration: The victim may become unable to claim legitimate rewards due to high gas costs, leading to a poor user experience and potential financial loss. Additionally, the victim may get confused about their rewards indexes since the array is so large.
System Disruption: In severe cases, the contract itself may become unusable for affected accounts due to the excessive gas required for operations involving the inflated arrays.
Attacker can create an exploit contract with a modified transferReward that transfers the reward N times enough to make the victim’s array large.
Attacker calls the transferRewardModified with a high count value (e.g., 1000) to transfer this zero-value reward to victim. While testing it on Remix IDE, repeating the attack allows the attacker to inflate the victim's array, making it increasingly expensive for the victim to call functions like getRewards() or claimAllRewards() or claimSingleReward
Manual review
Remix IDE
Before transferring a reward, check if its value is greater than zero. This will prevent zero-value rewards from being transferred and inflating the recipient’s array.
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.