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

Break invariant: Users cannot claim rewards after three epochs

Summary

It is stated in documentation by the Fjord team, that user should be able to complete their claim request three epochs after the request is created. However, there's an edge case that it requires a minimum of four epochs.

Vulnerability Details

When finalizing a claim request using completeClaimRequest, the contract verifies whether at least four epochs have passed since the request was initiated. However, the intended behavior is to allow completion after three epochs.
For example, if a user initiates a claim request in epoch 3, they should be eligible to complete the claim in epoch 6 or later. For now, the staking contract reverts the request if the difference between the current epoch and the request epoch is less than or equal to claimCycle (3 epochs).

function completeClaimRequest()
external
checkEpochRollover
redeemPendingRewards
returns (uint256 rewardAmount)
{
ClaimReceipt memory cr = claimReceipts[msg.sender];
//CHECK
if (cr.requestEpoch < 1) revert ClaimReceiptNotFound();
// to complete claim receipt, user must wait for at least 3 epochs
if (currentEpoch - cr.requestEpoch <= claimCycle) revert CompleteRequestTooEarly();
...

That means:

if (6 - 3 <= claimCycle) revert CompleteRequestTooEarly();

Below is a POC by foundry:

function test_CompleteRequestFailure() public {
vm.prank(bob);
fjordStaking.stake(1 ether);
_addRewardAndEpochRollover(3 ether, 2);
vm.prank(bob);
fjordStaking.claimReward(false);
skip(3 weeks);
skip(3 days);
vm.prank(bob);
vm.expectRevert(FjordStaking.CompleteRequestTooEarly.selector);
fjordStaking.completeClaimRequest();
}

Impact

This breaks one of the system invariants. Users must wait four weeks to complete a claim request, rather than the intended three weeks.

Tools Used

Manual Review

Recommendations

Update the conditional to make sure users can claim at right moment.

- if (currentEpoch - cr.requestEpoch <= claimCycle) revert CompleteRequestTooEarly();
+ if (currentEpoch - cr.requestEpoch < claimCycle) revert CompleteRequestTooEarly();
Updates

Lead Judging Commences

inallhonesty Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

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