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

Incorrect check in unstakeVested

Summary

In unstakeVested, the check that makes sure that the correct epochs are maintained has been implemented incorrectly.

Vulnerability Details

In the unstakeVested() the conditional check ensures that if the current and NFT-data epochs aren't the same then the funds are locked for 21 days but here lies one extreme case.

function unstakeVested(uint256 _streamID) external checkEpochRollover redeemPendingRewards {
//CHECK
NFTData memory data = _streamIDs[msg.sender][_streamID];
DepositReceipt memory dr = deposits[msg.sender][data.epoch];
if (data.epoch == 0 || data.amount == 0 || dr.vestedStaked == 0 || dr.epoch == 0) {
revert DepositNotFound();
}
// If epoch is same as current epoch then user can unstake immediately
if (currentEpoch != data.epoch) {
// If epoch less than current epoch then user can unstake after at complete lockCycle
if (currentEpoch - data.epoch <= lockCycle) revert UnstakeEarly();//----------ISSUE---------//
}
_unstakeVested(msg.sender, _streamID, data.amount);
}

Here's how this scenario will work out:

  • USER A vested staked on 1 September 2024 at 2:01 PM

  • USER A tried to unstake on 22 September 2024 at 2:01 PM(after 21 days)

  • Result: Txn reverts due to the incorrectly implemented check

Impact

The user won't be able to unstake his funds leading to the bad reputation of the protocol.

Tools Used

Manual Review

Recommendations

function unstakeVested(uint256 _streamID) external checkEpochRollover redeemPendingRewards {
//CHECK
NFTData memory data = _streamIDs[msg.sender][_streamID];
DepositReceipt memory dr = deposits[msg.sender][data.epoch];
if (data.epoch == 0 || data.amount == 0 || dr.vestedStaked == 0 || dr.epoch == 0) {
revert DepositNotFound();
}
// If epoch is same as current epoch then user can unstake immediately
if (currentEpoch != data.epoch) {
// If epoch less than current epoch then user can unstake after at complete lockCycle
- if (currentEpoch - data.epoch <= lockCycle) revert UnstakeEarly();
+ if (currentEpoch - data.epoch < lockCycle) revert UnstakeEarly();
}
_unstakeVested(msg.sender, _streamID, data.amount);
}
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.