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: 4/55
Findings: 2
Award: $8,159.28
🌟 Selected for report: 1
🚀 Solo Findings: 1
🌟 Selected for report: KupiaSec
8126.3155 USDC - $8,126.32
Because of incorrect validation, it allows option buyers not to pay premium.
When long leg is minted or short leg is burnt, the protocol checks liquidity spread by calculating TotalLiquidity / NetLiquidity
and allows it not exceed 9
.
However in the check function, the validation is ignored when NetLiquidity
is zero.
This means when a user mints long leg that buys whole selling amount, the liquidity spread is not checked. This issue allows the option buyer not to pay premium, and here is why:
s_grossPremiumLast
. Refer to _updateSettlementPostMint
function of PanopticPool
contract._updateSettlementPostBurn
function of PanopticPool
contract.Since there is no difference in owed premium value, the option buyer will not pay the premium when burning the option.
Manual Review
When checking liquidity spread, it should revert when N is zero and T is positive:
+ if(netLiquidity == 0 && totalLiquidity > 0) revert; if(netLiquidity == 0) return;
Context
#0 - c4-judge
2024-05-06T14:53:07Z
Picodes marked the issue as satisfactory
#1 - c4-judge
2024-05-06T14:53:10Z
Picodes marked the issue as selected for report
🌟 Selected for report: DadeKuma
Also found by: 0xStalin, 0xhacksmithh, 99Crits, Aymen0909, Bauchibred, CodeWasp, Dup1337, IllIllI, John_Femi, K42, KupiaSec, Naresh, Rhaydden, Rolezn, Sathish9098, Topmark, ZanyBonzy, albahaca, bareli, blockchainbuttonmasher, cheatc0d3, codeslide, crc32, d3e4, favelanky, grearlake, hihen, jasonxiale, jesjupyter, lanrebayode77, lirezArAzAvi, lsaudit, mining_mario, oualidpro, pfapostol, radin100, rbserver, sammy, satoshispeedrunner, slvDev, twcctop, zabihullahazadzoi
32.9585 USDC - $32.96
https://github.com/code-423n4/2024-04-panoptic/blob/833312ebd600665b577fbd9c03ffa0daf250ed24/contracts/SemiFungiblePositionManager.sol#L999-L1035 https://github.com/code-423n4/2024-04-panoptic/blob/833312ebd600665b577fbd9c03ffa0daf250ed24/contracts/PanopticPool.sol#L836-L847
Option sellers won't be able to close short positions because of existing dust amount of buy, thus might cause a few issues:
PanopticPool
contract only allows option sellers to burn entire position size of an option.
By using feature/vulnerability, malicious users can buy dust amount of options to prevent option sellers from closing their positions.
Here's a PoC written in Foundry that shows an option seller not being able to close position:
function test_Audit_dosBurn( uint256 x, uint256 widthSeed, int256 strikeSeed, uint256 positionSizeSeed ) public { // Prepare pool _initPool(x); (int24 width, int24 strike) = PositionUtils.getOTMSW( widthSeed, strikeSeed, uint24(tickSpacing), currentTick, 0 ); populatePositionData(width, strike, positionSizeSeed); // Create a short position TokenId shortTokenId = TokenId.wrap(0).addPoolId(poolId).addLeg(0, 1, isWETH, 0, 0, 0, strike, width); TokenId[] memory posIdList = new TokenId[](1); posIdList[0] = shortTokenId; // Bob sells positionSize amount of options vm.startPrank(Bob); pp.mintOptions(posIdList, positionSize, 0, 0, 0); // Create a buy position TokenId longTokenId = TokenId.wrap(0).addPoolId(poolId).addLeg(0, 1, isWETH, 1, 0, 0, strike, width); posIdList[0] = longTokenId; // Malicious Alice buys dust amount of options, e.g 1e4 vm.startPrank(Alice); pp.mintOptions(posIdList, 1e4, type(uint64).max - 1, 0, 0); // Later, Bob tries to burn the position, but not able to burn it vm.startPrank(Bob); vm.expectRevert(); pp.burnOptions(shortTokenId, new TokenId[](0), 0, 0); }
Manual Review, Foundry
Option sellers should be able to close partial amount of their positions. Or, only allow to buy meaningful minimum amount of options.
DoS
#0 - c4-judge
2024-04-26T18:36:11Z
Picodes marked the issue as primary issue
#1 - dyedm1
2024-04-26T20:54:33Z
Options sellers can force exercise buyers if they are out-of-range, and they can also sell a smaller position in the same chunk if they want to close their position and it is truly a "dust" amount purchased.
#2 - c4-judge
2024-05-06T15:36:33Z
Picodes changed the severity to QA (Quality Assurance)
#3 - Picodes
2024-05-06T15:36:50Z
Downgrading to Low following the sponsor's answer
#4 - c4-judge
2024-05-06T16:07:25Z
Picodes marked the issue as grade-c
#5 - c4-judge
2024-05-06T16:07:28Z
Picodes marked the issue as grade-b