Closed c4-bot-4 closed 4 months ago
That comment could be a bit confusing, but the asset
is supposed to represent the unit of position sizing. The suggested "correct" sizing path makes no sense (asset=1 does not mean 1 of token0).
Picodes marked the issue as unsatisfactory: Invalid
Lines of code
https://github.com/code-423n4/2024-04-panoptic/blob/833312ebd600665b577fbd9c03ffa0daf250ed24/contracts/libraries/PanopticMath.sol#L289-L330 https://github.com/code-423n4/2024-04-panoptic/blob/833312ebd600665b577fbd9c03ffa0daf250ed24/contracts/libraries/PanopticMath.sol#L324-L330 https://github.com/code-423n4/2024-04-panoptic/blob/833312ebd600665b577fbd9c03ffa0daf250ed24/contracts/libraries/PanopticMath.sol#L328
Vulnerability details
Vulnerability Description
In the getLiquidityChunk function of the PanopticMath, the liquidity calculation for a position leg does not properly handle the case when the asset parameter is set to 1. This can lead to incorrect liquidity amounts being minted or burned in the SFPM contract.
Impact
The function retrieves the tick range (
tickLower
andtickUpper
) for the leg usingtokenId.asTicks(legIndex)
. It then calculates the liquidity based on the asset parameter encoded in thetokenId
.PanopticMath.sol#L324-L328
When the
asset
parameter of thetokenId
is set to 1. In this case, the function incorrectly assumes that the liquidity should be calculated usingMath.getLiquidityForAmount1
.According to the comments in the code, when asset is 1, the amount of token1 moved at strike K is K, and the amount of token0 moved is 1. This means that the liquidity calculation should be based on
token0
, nottoken1
.This #Line328 Is responsible
Proof of Concept
The
getLiquidityChunk
function can lead to incorrect liquidity calculations and potentially impact the protocol and its users.User calls the mintOptions function passing the necessary parameters, including the
tokenId
withasset
set to 1.Inside the mintOptions function, the _mintInSFPMAndUpdateCollateral function is called, which eventually invokes the mintTokenizedPosition function in the SFPM contract.
The SFPM contract calls the _validateAndForwardToAMM function, which in turn calls the _createPositionInAMM function.
The _createPositionInAMM function loops through each leg of the
tokenId
and calls the _createLegInAMM function for each leg.Inside the _createLegInAMM function, the getLiquidityChunk function from the PanopticMath library is called to calculate the liquidity chunk for the leg.
The getLiquidityChunk function receives the following inputs:
tokenId
: The option position ID withasset
set to 1.legIndex
: 0positionSize
: 10The function retrieves the tick range:
tickLower
= 50000 andtickUpper
= 50200.Calculates the
amount
:Since
tokenId.asset(legIndex)
is 1, the function incorrectly usesMath.getLiquidityForAmount1
to calculate the liquidity:The
Math.getLiquidityForAmount1
function is called withtickLower
= 50000,tickUpper
= 50200, andamount
= 10.The function calculates the liquidity based on the formula:
The calculated liquidity is returned to the
_createLegInAMM
function and subsequently used to mint the liquidity in the Uniswap V3 pool.Tools Used
Manual audit, VS Code
Recommended Mitigation
Update the liquidity calculation logic to handle the case
when tokenId.asset(legIndex) == 1
correctly. Ensure that the correct function (getLiquidityForAmount1
) is called and the appropriate parameters are passed.When
asset
is 1, the liquidity is calculated usingMath.getLiquidityForAmount0
with an amount of 1, as per the expected behavior described in the comments.Assessed type
Math