Closed c4-bot-9 closed 4 months ago
Picodes marked the issue as primary issue
Actually, Uniswap defines the tickLower as in-range but the tickUpper as out-of-range by convention. You also misunderstood that comment -- one leg (out of four legs each with their own Uniswap chunk) must be out of range, not 1 tick out of range.
This is indeed the convention. See for example https://github.com/Uniswap/v3-core/blob/d8b1c635c275d2a9450bd6a78f3fa2484fef73eb/contracts/UniswapV3Pool.sol#L328C17-L328C28.
Picodes marked the issue as unsatisfactory: Invalid
Lines of code
https://github.com/code-423n4/2024-04-panoptic/blob/833312ebd600665b577fbd9c03ffa0daf250ed24/contracts/types/TokenId.sol#L578
Vulnerability details
Impact
Nonexercisable positions can be exercisable
Proof of Concept
The protocol checks if a position is exercisable, i.e. at least one of its legs is outside of predefined width, by
currentTick >= _strike + rangeUp) || (currentTick < _strike - rangeDown
condition.However, it also includes the case when the tick is right at the width, which should be nonexercisable.
As per the validation of exercisable position logic, the position should be 1 tick out of the range of the current tick:
And
validateIsExercisable
checks the issue as :Looking at L:589, it also checks the equivalency - not 1 tick difference only which means that the positions that don´t have this difference can also be exercisable.
In addition,
rangeup
calculation is based on rounding up - which we can say that it´s really being forced to be inside the ticks even if it might not be:Tools Used
Manual Review
Recommended Mitigation Steps
We recommend refactoring the logic to below:
Assessed type
Invalid Validation