Inactive variable depositor locks protocol fees
Description
The variable appliedProtocolFee
is increased whenever protocol fees are charged, and the protocolFeeReceiver
can withdraw them using various withdraw procedures throughout the vault life cycle.
However, if a variable-side depositor requests a withdraw during the vault's lifetime, the protocol fee is only applied when the request is finalized and they call finalizeVaultOngoingVariableWithdrawals
:
function finalizeVaultOngoingVariableWithdrawals() external {
// [...]
uint256 protocolFee = applyProtocolFee(amountWithdrawn);
// [...]
}
function applyProtocolFee(uint256 stakingEarnings) internal returns (uint256) {
uint256 protocolFee = stakingEarnings.mulDiv(protocolFeeBps, 10000);
appliedProtocolFee += protocolFee;
return protocolFee;
}
This means that if a variable-side depositor disappears and never finalizes their withdrawal, the protocol fee is never claimable by the protocol-fee receiver even if the vault completely ends.
Impact
Protocol fees that should have been claimable can become lost if a variable-side depositor goes missing or loses their private key. For vaults with many depositors, it is likely that the vault must be monitored by the protocol-fee receiver for a long time to withdraw the protocol fee if a depositor ever comes back and claims their funds. Over time, this unboundedly builds up the number of contracts the protocol-fee receiver must watch for events.
Recommendations
Allow the protocol-fee receiver to finalize ongoing variable withdrawals on behalf of the withdrawer. Similar to fixedToPendingWithdrawalAmount
, the value should be kept in ETH and the withdrawer should be able to withdraw their share later.
Remediation
This issue has been acknowledged by Saffron, and fixes were implemented in the following commits: