Summary
A wrong withdrawal allows vaults to be left with less than the minimu deposits.
Vulnerability Details
VaultDepositController::withdraw is used to withdraw assets from vaults. A vault cannot be left with an amount of assets lower than the minimum deposits. However, an error when calculating the amount of asset tokens to withdraw allows that situation, on certain condition.
File: contracts/linkStaking/base/VaultControllerStrategy.sol#L135-L150
if (deposits != 0 && vault.claimPeriodActive() && !vault.isRemoved()) {
if (toWithdraw > deposits) {
vault.withdraw(deposits);
unbondedRemaining -= deposits;
toWithdraw -= deposits;
} else if (deposits - toWithdraw > 0 && deposits - toWithdraw < minDeposits) {
>> vault.withdraw(deposits);
unbondedRemaining -= deposits;
break;
} else {
vault.withdraw(toWithdraw);
unbondedRemaining -= toWithdraw;
break;
}
}
As we can see in the above snippet, if deposits - toWithdraw > 0 && deposits - toWithdraw < minDeposits, the amount to withdraw is deposits which will leave the vault with zero asset tokens and will break an important protocol invariant.
Impact
Vaults can be left with less than minimum deposits.
Tools Used
Manual review.
Recommendations
Consider the following changes.
if (deposits != 0 && vault.claimPeriodActive() && !vault.isRemoved()) {
if (toWithdraw > deposits) {
vault.withdraw(deposits);
unbondedRemaining -= deposits;
toWithdraw -= deposits;
} else if (deposits - toWithdraw > 0 && deposits - toWithdraw < minDeposits) {
// cannot leave a vault with less than minimum deposits
-- vault.withdraw(deposits);
++ toWithdraw = deposits - minDeposits;
++ vault.withdraw(toWithdraw);
unbondedRemaining -= deposits;
break;
} else {
vault.withdraw(toWithdraw);
unbondedRemaining -= toWithdraw;
break;
}
}