DeFiFoundry
20,000 USDC
View results
Submission Details
Severity: medium
Invalid

Rewards could still be claimed early before full epoch settlement in `claimReward`

Impact

If a user calls claimReward with _isClaimEarly = true immediately after an epoch transition (but before new rewards have been added for that epoch), they could claim rewards that don't include the most recent epoch's distributions

Proof of Concept

Take a look, the claimReward function allows users to claim rewards, including an option for early claiming:

function claimReward(bool _isClaimEarly)
external
checkEpochRollover
redeemPendingRewards
returns (uint256 rewardAmount, uint256 penaltyAmount)
{
UserData storage ud = userData[msg.sender];
if (
claimReceipts[msg.sender].requestEpoch > 0
|| claimReceipts[msg.sender].requestEpoch >= currentEpoch - 1
) revert ClaimTooEarly();
if (ud.unclaimedRewards == 0) revert NothingToClaim();
if (!_isClaimEarly) {
claimReceipts[msg.sender] =
ClaimReceipt({ requestEpoch: currentEpoch, amount: ud.unclaimedRewards });
emit ClaimReceiptCreated(msg.sender, currentEpoch);
return (0, 0);
}
rewardAmount = ud.unclaimedRewards;
penaltyAmount = rewardAmount / 2;
rewardAmount -= penaltyAmount;
// ... rest of thee function
}

Although the claimReward function includes checks to prevent multiple claims and ensures the epoch is up-to-date using the checkEpochRollover modifier, it doesn't completely or should I say explicitly verify that the current epoch has been fully settled before allowing an early claim. This could potentially allow users to claim rewards that don't include the most recent epoch's distributions if they call the function immediately after an epoch transition.

Tools used

Manual

Recommended Mitigation Steps

Consider adding an explicit check to ensure that rewards are only claimable for fully settled epochs:

function claimReward(bool _isClaimEarly)
external
checkEpochRollover
redeemPendingRewards
returns (uint256 rewardAmount, uint256 penaltyAmount)
{
+ if (currentEpoch == getEpoch(block.timestamp)) revert ClaimTooEarly();
UserData storage ud = userData[msg.sender];
if (
claimReceipts[msg.sender].requestEpoch > 0
|| claimReceipts[msg.sender].requestEpoch >= currentEpoch - 1
) revert ClaimTooEarly();
// ... rest of the function
}
Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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