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

User can't unstake from current epoch in `unstakeAll`

Vulnerability details

Protocol allows users to stake and immediately unstake if it is done in the same epoch.

Unstake function:

// _epoch is same as current epoch then user can unstake immediately
if (currentEpoch != _epoch) {
// _epoch less than current epoch then user can unstake after at complete lockCycle
if (currentEpoch - _epoch <= lockCycle) revert UnstakeEarly();
}

However this functionality is not implemented in unstakeAll function which is expected to do the same thing as unstake function but for every epoch.

function unstakeAll()
external
checkEpochRollover
redeemPendingRewards
returns (uint256 totalStakedAmount)
{
uint256[] memory activeDeposits = getActiveDeposits(msg.sender);
if (activeDeposits.length == 0) revert NoActiveDeposit();
for (uint16 i = 0; i < activeDeposits.length; i++) {
uint16 epoch = uint16(activeDeposits[i]);
DepositReceipt storage dr = deposits[msg.sender][epoch];
if (dr.epoch == 0 || currentEpoch - epoch <= lockCycle) continue;
totalStakedAmount += dr.staked;
// no vested staked and stake is 0 then delete the deposit
if (dr.vestedStaked == 0) {
delete deposits[msg.sender][epoch];
_activeDeposits[msg.sender].remove(epoch);
} else {
// still have vested staked, then only delete the staked
dr.staked = 0;
}
}
totalStaked -= totalStakedAmount;
userData[msg.sender].totalStaked -= totalStakedAmount;
fjordToken.transfer(msg.sender, totalStakedAmount);
points.onUnstaked(msg.sender, totalStakedAmount);
// emit event
emit UnstakedAll(
msg.sender, totalStakedAmount, activeDeposits, getActiveDeposits(msg.sender)
);
}

if (dr.epoch == 0 || currentEpoch - epoch <= lockCycle) continue;

It does not check if user's stake and unstake is in the same epoch.

Impact

unstakeAll does not work as intended. Due to this missing functionality user will be required to stake for lockCycle locking his funds for this period.

Recommended Mitigation Steps

In unstakeAll check if user's unstake is being made in the same epoch, the same way as it is implemented in unstake function.

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.