Summary
We withdraw from the vaults using the VaultDepositController::withdraw. A vault cannot be left iwth an amount of assets lower than the minimum deposits. However, the eeror 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.
Recommendation
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;
}
}