Panoptic - grearlake's results

Effortless options trading on any token, any strike, any size.

General Information

Platform: Code4rena

Start Date: 27/11/2023

Pot Size: $60,500 USDC

Total HM: 7

Participants: 72

Period: 7 days

Judge: Picodes

Total Solo HM: 2

Id: 309

League: ETH

Panoptic

Findings Distribution

Researcher Performance

Rank: 66/72

Findings: 1

Award: $11.32

🌟 Selected for report: 0

🚀 Solo Findings: 0

Awards

11.3163 USDC - $11.32

Labels

bug
grade-b
QA (Quality Assurance)
edited-by-warden
Q-28

External Links

1, PoolId can be generated infinitely without escape lead to out of gas for user

Lines of code

https://github.com/code-423n4/2023-11-panoptic/blob/main/contracts/SemiFungiblePositionManager.sol#L370-#L372 https://github.com/code-423n4/2023-11-panoptic/blob/main/contracts/libraries/PanopticMath.sol#L48-#L59

Details

In initializeAMMPool, to avoid Id collision, function will check if previous ID was existed before or not:

while (address(s_poolContext[poolId].pool) != address(0)) { poolId = PanopticMath.getFinalPoolId(poolId, token0, token1, fee); }

This is function to generate new poolId:

function getFinalPoolId( uint64 basePoolId, address token0, address token1, uint24 fee ) internal pure returns (uint64) { unchecked { return basePoolId + (uint64(uint256(keccak256(abi.encodePacked(token0, token1, fee)))) >> 32); } }

But problem is if new poolId generated is same as old one, while loop is still true and it will keep generating same poolId till user run out of gas, and the pool will never be initialized

Impact

User will run out of gas because of while condition loop infinity. Submited as low because chance that it can be happened is very low.

poolId should be selected by user in acceptable range.

2, User failed minting/borrowing if the new tick reaches boundary

Lines of code

https://github.com/code-423n4/2023-11-panoptic/blob/main/contracts/SemiFungiblePositionManager.sol#L713

Details

Developer noted in mintTokenizedPosition and burnTokenizedPosition about two slippage parameter:

/// @param slippageTickLimitLow The lower price slippage limit when minting an ITM position (set to larger than slippageTickLimitHigh for swapping when minting) /// @param slippageTickLimitHigh The higher slippage limit when minting an ITM position (set to lower than slippageTickLimitLow for swapping when minting)

And in the code:

if ((newTick >= tickLimitHigh) || (newTick <= tickLimitLow)) revert Errors.PriceBoundFail();

It can see that new tick is not accepted if it reaches boundary, it is not true compare to what developer noted in function. If the new tick equal to lower or higher tick, transaction will be reverted

Impact

User transaction can be unintentionally reverted.

Checking condition should be changed to:

if ((newTick > tickLimitHigh) || (newTick < tickLimitLow)) revert Errors.PriceBoundFail();

#0 - c4-judge

2023-12-14T16:59:33Z

Picodes marked the issue as grade-b

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter