Closed c4-bot-3 closed 4 months ago
Picodes marked the issue as unsatisfactory: Invalid
Case 1: see https://github.com/code-423n4/2024-04-panoptic/blob/833312ebd600665b577fbd9c03ffa0daf250ed24/contracts/SemiFungiblePositionManager.sol#L727 Case 2: the check is done on the tick Case 3: on pool creation so no risk of frontrunning
Dear @Picodes ,
Thanks for judging the contest, I appreciate the hard work.
Could you please take a look at this issue again, more specifically case number 3. Issue #537, which was accepted as valid MED talks specifically about the case 3 I described in my finding.
In my submission, I stated:
When deploying new pool, user is obligated to mint full range liquidity. It also uses slot0 and no slippage protection.
Issue #537 talks about the same:
The spot price is used to calculate the range liquidity for each token
I also provided the same vulnerable code part. Hence, I believe that my finding should be grouped with #537
Indeed, thanks for flagging
Picodes marked the issue as duplicate of #537
Picodes marked the issue as satisfactory
Picodes changed the severity to 2 (Med Risk)
Lines of code
https://github.com/code-423n4/2024-04-panoptic/blob/833312ebd600665b577fbd9c03ffa0daf250ed24/contracts/SemiFungiblePositionManager.sol#L1203-L1209 https://github.com/code-423n4/2024-04-panoptic/blob/833312ebd600665b577fbd9c03ffa0daf250ed24/contracts/SemiFungiblePositionManager.sol#L788-L850 https://github.com/code-423n4/2024-04-panoptic/blob/833312ebd600665b577fbd9c03ffa0daf250ed24/contracts/PanopticFactory.sol#L341-L410
Vulnerability details
There are multiple places where Panoptic does not protect against slippage and uses spot price (e.g. reading price from
slot0
). We identified 3 most severe cases that impact users and allow for huge losses for the protocol users:Case 1
When position is created, either via PanopticPool or via SFPM,
UniswapPool.mint()
is called. It is a lo level function, that usually should be called via periphery contracts and verify if user liquidity was added with the amount expected. However in case of Panoptic there is no protection against that, because user passes only "liquidity" that will be minted and then UniswapPool calculated how much erc20 to get from user, but this amount is highly manipulable. The code in Panoptic:In case of Uniswap, mint funciton looks like this:
function
_modifyPosition()
is a bit complex, but you can see there that the amount that will be taken from user is dependent on current asset price and square root at given tick:According to Uniswap docs
Case 2
When creating a position, it's possible to have optional swap, in case that the position is created in the money, meaning that the position consists partly of token0 and partly of token1. Then, if user passes min tick above max tick, swap is performed. However, the swap doesn't have any slippage protection, even though it's possible to manipulate the pool before hand. Slippage in this case is hardcoded either to
MIN_V3POOL_SQRT_RATIO
orMAX_V3POOL_SQRT_RATIO
, depending on swap direction:Case 3
When deploying new pool, user is obligated to mint full range liquidity. It also uses
slot0
and no slippage protection:Impact
Stealing from users due to lack of slippage protection
Proof of Concept
The following test shows how the same mint behaves for situation where there is no frontrunning, then state is reverted and second case is shown - this time with frontrunning. This shows
Case 1
described above, however other cases work similarly. Add following toSemiFungiblePositionManager.t.sol
:Additionally, adding
import "forge-std/Test.sol";
at the beggining might be required.Test results will differ based on the current block of test simulation, at the time of running this tests, the results where following:
The results show that in one case user paid 16 WETH, in the other 10025, meaning that we were able to seriously manipulate the price of the asset, leading to serious user loss.
Tools Used
Manual Review
Recommended Mitigation Steps
Please introduce proper slippage protection. Generalized MEV bots are very sophisticated, and without any adjustments will be able to exploit unprotected swap sin UniswapV3 pools.
Assessed type
MEV