Platform: Code4rena
Start Date: 01/04/2024
Pot Size: $120,000 USDC
Total HM: 11
Participants: 55
Period: 21 days
Judge: Picodes
Total Solo HM: 6
Id: 354
League: ETH
Rank: 32/55
Findings: 1
Award: $153.80
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: DadeKuma
Also found by: Bauchibred, Dup1337, Vancelot, jesjupyter, sammy
153.7983 USDC - $153.80
https://github.com/code-423n4/2024-04-panoptic/blob/main/contracts/PanopticPool.sol#L333-L344 https://github.com/code-423n4/2024-04-panoptic/blob/main/contracts/PanopticFactory.sol#L328-L411
The returned parameter currentSqrtPriceX96
from slot0
can be easily manipulated with a flashloan, resulting in a loss of funds.
The first function that calls slot0
and uses the returned price is assertPriceWithinBounds in PanopticPool.sol
:
function assertPriceWithinBounds(uint160 sqrtLowerBound, uint160 sqrtUpperBound) external view { (uint160 currentSqrtPriceX96,,,,,,) = s_univ3pool.slot0(); if (currentSqrtPriceX96 <= sqrtLowerBound || currentSqrtPriceX96 >= sqrtUpperBound) { revert Errors.PriceBoundFail(); } }
One of the comments for this function states that it can be used in a multicall, as a slippage check, for a force exercise or liquidation. If a malicious user were to front-run the call to this function with a flashloan, they could bump up the price so that their options aren't exercised or their account isn't liquidated.
The second function that utilizes slot0 is _mintFullRange in PanopticFactory.sol
:
function _mintFullRange(IUniswapV3Pool v3Pool, address token0, address token1, uint24 fee) internal returns (uint256, uint256) { (uint160 currentSqrtPriceX96,,,,,,) = v3Pool.slot0(); uint128 fullRangeLiquidity; unchecked { // Since we know one of the tokens is WETH, we simply add 0.1 ETH + worth in tokens if (token0 == WETH) { fullRangeLiquidity = uint128(Math.mulDiv96RoundingUp(FULL_RANGE_LIQUIDITY_AMOUNT_WETH, currentSqrtPriceX96)); } else if (token1 == WETH) { fullRangeLiquidity = uint128( Math.mulDivRoundingUp(FULL_RANGE_LIQUIDITY_AMOUNT_WETH, Constants.FP96, currentSqrtPriceX96) .....
A malicious user could manipulate the price so that the newly created SFPM
is deployed with more liquidity than intended.
Manual Review
I suggest refactoring the functions, in order for them to use Uniswap's TWAP, as it's the safer choice.
Oracle
#0 - c4-judge
2024-04-23T11:55:24Z
Picodes marked the issue as duplicate of #537
#1 - Picodes
2024-04-23T11:55:48Z
For assertPriceWithinBounds
as it's a query function and there is no real scenario described here I consider it to be of low severity
#2 - c4-judge
2024-05-01T10:49:13Z
Picodes changed the severity to 2 (Med Risk)
#3 - c4-judge
2024-05-01T10:51:26Z
Picodes marked the issue as satisfactory
#4 - c4-judge
2024-05-01T10:51:42Z
Picodes marked the issue as partial-25
#5 - Picodes
2024-05-01T10:51:56Z
Giving partial credit for the lack of PoC.