Finding Description and Impact
The function _calculatePendingRewards() miscalculates a user's pending rewards due to incorrect tracking of userRewards[user].
userRewards[user] is only updated whenclaimRewards() is called and it is set to totalDistributed.
This means userRewards[user] is either 0 (if the user has never claimed rewards) or totalDistributed (if they have claimed at least once).
However, _calculatePendingRewards() assumes userRewards[user] tracks the user's actual "Accumulated rewards", which is incorrect after a user's first claim, as it is just reset to totalDistributed.
Impact
Users are not able to claim their entitled rewards after their first claim.
If a user's share of the rewards is slightly above their current accumlated rewards, they may be eligible for additional rewards, but the function will return 0 instead of the correct pending amount, as the new calculated share can never be bigger than totalDistributed.
This could lead to permanent loss of rewards for affected users.
Proof of Concept
Issue in _calculatePendingRewards()
The comparison share > userRewards[user] assumes userRewards[user] represents accumulated rewards received, but in reality:
userRewards[user] is only updated in claimRewards() as totalDistributed after a user's first claim.
After a user's first claim this will cause all future pending rewards to be lost.
Code Reference in claimRewards()
This overwrites userRewards[user] instead of incrementally tracking rewards.
Expected Behavior
userRewards[user] should properly track the total claimed rewards, not just reset to totalDistributed.
Recommended Mitigation Steps
To ensure accurate tracking of claimed rewards and prevent loss of pending rewards:
Fix the reward update logic in claimRewards()
Instead of setting userRewards[user] = totalDistributed, increment it correctly:
This ensures userRewards[user] correctly reflects cumulative rewards received.
By implementing these fixes, the contract will ensure that users can claim all their rightful rewards without unintended losses.
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.