FluidLocker::_getUnlockingPercentage() uses 540 instead of 540 days leading to stuck funds as the unlocking percentage will be bigger than 100% and underflow
Summary
FluidLocker::_getUnlockingPercentage() calculates the amount to unlock when unvesting via the FluidLocker. It incorrectly uses 540 instead of 540 days, yielding a massive error such that the unlocking percentage will be much bigger than 10_000 and underflow.
function _getUnlockingPercentage(uint128 unlockPeriod) internal pure returns (uint256 unlockingPercentageBP) {
unlockingPercentageBP = (
_PERCENT_TO_BP
* (
((80 * _SCALER) / Math.sqrt(540 * _SCALER)) * (Math.sqrt(unlockPeriod * _SCALER) / _SCALER)
+ 20 * _SCALER
)
) / _SCALER;
}Note: due to other bugs in the calculation it will not revert.
Root Cause
In FluidLocker:388 it uses 540 instead of 540 days.
Internal pre-conditions
None.
External pre-conditions
None.
Attack Path
- User unlocks their Fluid from the
FluidLocker, but it reverts because of the mentioned underflow. The funds within the locker will be stuck unless the user instantly unlocks and takes a80%penalty.
Impact
User is forced to take a 80% penalty or have the funds stuck.
PoC
The calculation is presented in the summary. Essentially, as 540 is used in the denominator, much smaller than the correct 540 days (which is the maximum unlock period, when the percentage becomes 100%), the value will be much bigger than 10_000.
As the unlocking percentage is bigger than 10_000, the unlock flow rate
unlockFlowRate = (globalFlowRate * int256(_getUnlockingPercentage(unlockPeriod))).toInt96()
/ int256(_BP_DENOMINATOR).toInt96();will be bigger than the global flow rate, so it reverts when calculating the tax flow rate taxFlowRate = globalFlowRate - unlockFlowRate;.
Mitigation
Use 540 days instead of 540.