removedLiquidity can be underflowed to lock other user's deposits #516
Labels
2 (Med Risk)
Assets not at direct risk, but function/availability of the protocol could be impacted or leak value
bug
Something isn't working
downgraded by judge
Judge downgraded the risk level of this issue
M-02
primary issue
Highest quality submission among a set of duplicates
satisfactory
satisfies C4 submission criteria; eligible for awards
selected for report
This submission will be included/highlighted in the audit report
Lines of code
https://github.com/code-423n4/2023-11-panoptic/blob/main/contracts/SemiFungiblePositionManager.sol#L979
Vulnerability details
Impact
premia
calculated to extremely high levelsProof of Concept
When burning a long token, the
removedLiquidity
is subtracted in an unchecked blockhttps://github.com/code-423n4/2023-11-panoptic/blob/main/contracts/SemiFungiblePositionManager.sol#L936-L980
An underflow can be produced here by the following (burning is done after transferring the current position):
removedAmount
safeTransferFrom
to clear the current position. By passing in 0 as the token amount, we can move the position to some other address while still retaining the token amounts. This will set the netLiquidity and removedLiquidity to 0.2 ** 128 - prevNetLiquidity
and increase the netLiquidityThe ability to obtain such a position allows an attacker to perform a variety of attacks.
Lock other user's first time (have liquidity and feesBase 0) deposits by front-running
If the
totalLiquidity
of a position is equal to2 ** 128
, the premia calculation will revert due to division by zerohttps://github.com/code-423n4/2023-11-panoptic/blob/main/contracts/SemiFungiblePositionManager.sol#L1313-L1322
An attacker can exploit this by creating a position with
removedLiquidity == 2 ** 128 - depositorLiquidity
andnetLiquidity == 0
. The attacker can then front run and transfer this position to the depositor following which the funds will be lost/locked if burn is attempted without adding more liquidity or fees has been accrued on the position (causable by the attacker)Instead of matching exactly with
2 ** 128 - depositorLiquidity
an attacker can also keepremovedLiquidity
extremely close totype(uint128).max
in which case depending on the depositor's amount, a similar effect will take place due to casting errorsAnother less severe possibility for the attacker is to keep
netLiquidity
slightly above 0 (some other amount which will cause fees collected to be non-zero and hence invoke the_getPremiaDeltas
) and transfer to target address causing DOS since any attempt tomint
will result in revert due to premia calculationManipulate the premia calculation
Instead of making
totalLiquidity == 2 ** 128
, an attacker can choose values fornetLiquidity
andremovedLiquidity
such thattotalLiquidity > 2 ** 128
. This will disrupt the premia calculationExample values:
POC Code
Set fork_block_number = 18706858
For the division by 0 revert lock run :
forge test --mt testHash_DepositAmountLockDueToUnderflowDenomZero
For the casting error revert lock run :
forge test --mt testHash_DepositAmountLockDueToUnderflowCastingError
Tools Used
Manual review
Recommended Mitigation Steps
Check if
removedLiquidity
is greater thanchunkLiquidity
before subtractingAssessed type
Under/Overflow
The text was updated successfully, but these errors were encountered: