-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Slippage checks are disabled in an edge case when minting/burning options; may lead to loss of funds #424
Comments
Picodes marked the issue as duplicate of #302 |
Picodes marked the issue as unsatisfactory: |
Dear @Picodes, dear @dyedm1, I kindly ask you to: 1. Deduplicate this finding from 302: they are not dups, but completely opposite. Here is why:
2. Evaluate this finding based on its own merits How likely is such input to happen? Very likely, essentially guaranteed, because this is the way it is described e.g. in Minting a Panoption documentation: pp.mintOptions({
positionIdList: positionIdList,
positionSize: 10 * 10 ** 18,
effectiveLiquidityLimitX32: 0,
tickLimitLow: 0,
tickLimitHigh: 0
}); We all know that such code fragments from documentation are frequently copy-pasted by developers. Why is this a problem? This code fragment is intended for trading OTM, not ITM! Yes, this is exactly right! And this is the core of the problem: Needless to say that a transaction with disabled slippage checks in a mempool is an open invitation to attacks, such as sandwich attacks or in general pool manipulation. Nothing prevents an attacker to shift the pool state in such a way that a transaction submitted with the intention of minting/burning options OTM, will result in being executed ITM, resulting in the unbounded losses for the user. With kind regards, |
For clarity, let me also elaborate as to why, in my understanding, this bug happened (in the audited version of the code):
|
I was mistaken about this point, so I edited it away from the original PJQA reply... The docs I thought are new, are actually 2 years old, i.e. previously there were 2 functions ( |
Picodes marked the issue as not a duplicate |
Tagging @dyedm1 for review. @andrey-kuprianov thanks for your comment. My understanding is that this is by-design so isn't a Medium severity issue but falls within QA. |
Picodes changed the severity to QA (Quality Assurance) |
Picodes marked the issue as grade-b |
Yes, the TLH=TLL is a flag the users can set to disable slippage checks. The tick limits define an open interval anyway, so equal tick limits would be meaningless otherwise. |
@Picodes , @dyedm1, I still don't understand how "mint/burn in-the-money" and "disable slippage checks" can possibly be together? Isn't it that the user has to pay whatever extra amount the option minted/burned is in the money? Then, as this finding outlines, the losses are unbounded without slippage checks, and such transaction is a honey-pot. I would appreciate an explanation. |
That's what I am trying to explain here. Every bug is someone's design initially, until it's either fixed or exploited. I am showing that the design which disables slippage checks for a transaction which may be traded in-the-money, with unbounded losses for the user, is a bug, and not just a design choice. |
Please note that this is not a debate, as stated in multiple places in the code of conduct. For example: "At the point that a judge provides a response, the conversation is over, unless you wish to provide additional facts which demonstrate inaccurate assumptions in the judge's response. Further pursuit of the conversation will result in having SR access suspended." "Avoid engaging in any discussion and evaluation of issues submitted by yourself except to answer a question or provide additional context or clarification when requested by a judge or sponsor." Of course, as I assume this is your issue, you're considering that it's worth Medium severity and would like to be awarded, but I don't see what additional facts your last 2 comments are bringing. |
Now, to answer your comments, I don't see what's unclear in the sponsor's design: Due to this line setting |
Dear @Picodes, I know all that, and I am trying to "avoid engaging in any discussion", please believe me. I only feel that the information that I have already provided has not been read carefully enough. I will provide this last bit of info for you to consider, as a response to your last comment, and then will let it for you to decide.
Specifically about "that would be a user mistake". I have written it already before: Nowhere in the user-facing documentation it is written such input is used to disable slippage. On the contrary:
I hope this demonstrates enough that the docs recommend triggering this bug. If the sponsor points me to the docs where it is explicitly written that setting As I said, this is the last comment from me; please excuse me if I violated any boundaries. I am now leaving it to you to decide. With best regards |
@andrey-kuprianov note that I do agree with you that the docs do not state this clearly and may even be misleading. But this isn't worth Medium severity under C4's rules: "function incorrect as to spec, issues with comments" are Low, and that's why I downgraded this report to Low instead of giving an "unsatisfactory" label. |
I understand, and though disagree, I respect judge's decision. For sponsor's benefit, as well as for future reference (in case of security incidents), I would like the following to be added to the protocol: I maintain my stance that a transaction with disabled slippage checks has no place in the mempool; no matter intentional or unintentional. I recommend to fix that as suggested in the finding. |
Lines of code
https://github.com/code-423n4/2024-04-panoptic/blob/833312ebd600665b577fbd9c03ffa0daf250ed24/contracts/PanopticPool.sol#L630-L630
https://github.com/code-423n4/2024-04-panoptic/blob/833312ebd600665b577fbd9c03ffa0daf250ed24/contracts/PanopticPool.sol#L834-L834
Vulnerability details
Description
Both externally callable functions mintOptions() and burnOptions() include parameters
tickLimitLow
,tickLimitHigh
which are intended for slippage protection. These functions further continue as internal functions _mintOptions(), and _burnOptions(), both having this fragmentFunction _getSlippageLimits() though, whenever
tickLimitLow <= tickLimitHigh
reverses their order, and, moreover, iftickLimitLow == tickLimitHigh
assigns(tickLimitLow, tickLimitHigh) = (MAX_SWAP_TICK, MIN_SWAP_TICK)
:As a result, when the swap is executed in _validateAndForwardToAMM(), the following happens:
With
tickLimitLow == MAX_SWAP_TICK
, andtickLimitHigh == MIN_SWAP_TICK
, they get swapped, and the slippage check passes trivially. Thus, although the user requested the swap at a precise tick (tickLimitLow == tickLimitHigh
), the swap will be executed regardless, at any price tick.From the comment "disable slippage checks if tickLimitLow == tickLimitHigh" it looks like a deliberate design decision, but the rationale behind it is unclear, and it is clearly against user expectations.
Severity Rationalization
Impact
Arbitrary slippage when the user expects no slippage at all; loss of funds.
Proof of Concept
mintOptions
/burnOptions
ofPanopticPool
withtickLimitLow == tickLimitHigh
In particular, apply the following diff to function test_Fail_mintOptions_LowerPriceBoundFail()
and run with
forge test -vvvv --match-test test_Fail_mintOptions_LowerPriceBoundFail
. The change makes the test failing, in which the callmintOptions()
, which was expected to revert, succeeded:Tools Used
Manual audit
Recommended Mitigation Steps
Remove the aforementioned special case from function
_getSlippageLimits
.Assessed type
Math
The text was updated successfully, but these errors were encountered: