/// @notice Penalty fee in basis points for fixed side early withdrawals that is quadratically scaled based off of the amount of time that has elapsed since the vault started
However, if we look at LidoVault::calculateFixedEarlyExitFees(), it is the sum of 2 linear functions, one going from upfrontPremium * earlyExitFeeBps to 0 and another one from upfrontPremium to 0. This results in a linear function going from upfrontPremium * (1 + earlyExitFeeBps) to 0, which is not quadratic.
Thus, users can withdraw earlier with less fees as the quadratic would penalize much more users withdrawing early in the duration of the vault.
Root Cause
In LidoVault:982, it does not calculate an early exit fee quadratically.
Internal pre-conditions
None.
External pre-conditions
None.
Attack Path
Fixed user does an early withdraw but pays less fees than supposed or more fees if near the end.
Impact
Variable users take losses if the fixed user is withdrawing early in the vault's duration or the fixed user takes a loss if withdrawing late.
PoC
The LidoVault::calculateFixedEarlyExitFees() function calculates fees based on a linear relationship with the duration left.
function calculateFixedEarlyExitFees(uint256 upfrontPremium, uint256 timestampRequested)
internal
view
returns (uint256)
{
uint256 remainingProportion =
(endTime > timestampRequested ? endTime - timestampRequested : 0).mulDiv(1e18, duration);
// Calculate the scaling fee based on the linear factor and earlyExitFeeBps
uint256 earlyExitFees = upfrontPremium.mulDiv((1 + earlyExitFeeBps).mulDiv(remainingProportion, 1e18), 10000);
// Calculate the amount to be paid back of their original upfront claimed premium, not influenced by quadratic scaling
earlyExitFees += upfrontPremium - upfrontPremium.mulDiv(timestampRequested - startTime, duration);
return earlyExitFees;
}
0x73696d616f
High
Exit fees are not quadratically scalled as they should be which will allow fixed users to withdraw for less fees early on
Summary
The codebase states in several locations that the
earlyExitFeeBps
is quadratically scaled, but it is not. VaultFactoryLidoVault
However, if we look at LidoVault::calculateFixedEarlyExitFees(), it is the sum of 2 linear functions, one going from
upfrontPremium * earlyExitFeeBps
to 0 and another one fromupfrontPremium
to 0. This results in a linear function going fromupfrontPremium * (1 + earlyExitFeeBps)
to 0, which is not quadratic.Thus, users can withdraw earlier with less fees as the quadratic would penalize much more users withdrawing early in the duration of the vault.
Root Cause
In
LidoVault:982
, it does not calculate an early exit fee quadratically.Internal pre-conditions
None.
External pre-conditions
None.
Attack Path
Impact
Variable users take losses if the fixed user is withdrawing early in the vault's duration or the fixed user takes a loss if withdrawing late.
PoC
The
LidoVault::calculateFixedEarlyExitFees()
function calculates fees based on a linear relationship with the duration left.Mitigation
Implement the quadratic function as intended.