<!-- canonical: https://0xsimao.com/findings/superfluid-locker-system-540-stuck-bigger-underflow -->

# `FluidLocker::_getUnlockingPercentage()` uses 540 instead of `540 days` leading to stuck funds as the unlocking percentage will be bigger than `100%` and underflow

Crit/High · Sherlock · Streaming · 20th November 2024

Finding H-2 of the Superfluid Locker System competition.

- Protocol: https://audits.sherlock.xyz/contests/648
- Report: /reports/superfluid-locker-system
- Codebase: https://github.com/0xsimao/2024-11-superfluid-locking-contract/tree/1fa5f86024be5f269e1a0898b1f939f1d4cce149
- Source: https://github.com/sherlock-audit/2024-11-superfluid-locking-contract-judging/issues/21

---

### Summary

[FluidLocker::_getUnlockingPercentage()](https://github.com/sherlock-audit/2024-11-superfluid-locking-contract/blob/main/fluid/packages/contracts/src/FluidLocker.sol#L384) 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.
```solidity
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

1. 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 a `80%` 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
```solidity
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`.

---

Related findings:

- [Pumponomics can be skipped when using FluidLocker::provideLiquidity](https://0xsimao.com/findings/superfluid-locker-system-ii-pumponomics-skipped-fluid-provide): Superfluid Locker Pumponomics
- [Staked tokens inside FluidLocker can be withdrawn without calling Unstake](https://0xsimao.com/findings/superfluid-locker-system-ii-staked-inside-withdrawn-unstake): Superfluid Locker Pumponomics
- [Fluid (SUP) can be withdrawn from the Locker while the unlock flag is false](https://0xsimao.com/findings/superfluid-locker-system-ii-sup-withdrawn-flag-false): Superfluid Locker Pumponomics
- [Locked funds due to underflow in withdrawal](https://0xsimao.com/findings/yieldoor-locked-funds-underflow-withdrawal): Yieldoor
