Submitted by 0xdice91
https://github.com/code-423n4/2024-04-panoptic/blob/833312ebd600665b577fbd9c03ffa0daf250ed24/contracts/types/TokenId.sol#L535-L571
https://github.com/code-423n4/2024-04-panoptic/blob/833312ebd600665b577fbd9c03ffa0daf250ed24/contracts/SemiFungiblePositionManager.sol#L673-L702
Each leg in a tokenid has a risk partner which is usually its own index but in some cases, it could be another leg (Partner in defined risk position).
In the function validate() if the risk partner of a specific leg is not its own index then some additional checks are done to ensure that they are compatible like:
In burnTokenizedPosition() the internal function _validateAndForwardToAMM() is called, this function calls Tokenid.flipToBurnToken() which simply flips the isLong bits of all active legs of the tokenid. Then validate() is called which validates a position tokenId and its legs.
The issue here is that if a leg in the tokenid has its risk partner as another leg (that is, it is not its own risk partner), then flipping the isLong bits may cause one of the checks
in validate() to fail and revert as the isLong bits of its risk partner are not changed as well.
Remember that flipping changes the value of the bit from what it was to an opposite value (from 0 to 1 or from 1 to 0).
For example;
Lets say a leg with a different risk partner has  isLong() values that are the same but their tokenType() is different, this would easily pass these checks below from validate()
but after a flip is done to its isLong bits using flipToBurnToken() it will fail and revert in the second check below.
This will result in a continuous revert of the function leading to an inability to Burn a Tokenized Position.
This whole issue results from the simple fact the risk partners, if different, are not flipped as well. I recommend validating the tokenid before flipping the isLong bits, to ensure any changes caused by flipping will not affect the execution of the function.
dyedm1 (Panoptic) confirmed
Picodes (judge) commented:
