DeFiFoundry
50,000 USDC
View results
Submission Details
Severity: low
Invalid

Protocol can never execute cancelFlow as intended because of gmxLock modifier

Summary

In PerpetualVault::cancelFlow-> the protocol intends to use this function to cancel an ongoing user flow due to some accidents.

But the function uses the gmxLockmodifier which disallows the function from running until the entire gmxorder creation process is complete -> which will never allow the protocol to cancel an ongoing flow invloving gmx when there is an accident and the flow needs to be canceled.

Vulnerability Details

Having a look at the documentation, the protocol intends to use this function to cancel flows that involve gmx (order creation) when an error is made.

Notice how the function uses the gmxLockmodifier -> which disallows the function from running until it is set to False

/**
* @notice
* Cancel the current ongoing flow.
* @dev
* In the case of 1x long leverage, we never cancel the ongoing flow.
-> * In the case of gmx position, we could cancel current ongoing
* flow due to some accidents from our side or gmx side.
*/
-> function cancelFlow() external nonReentrant gmxLock {
_onlyKeeper();
_cancelFlow();
}

** First lets understand where the gmxLockgets set to true

> _createDecreasePosition

> _createIncreasePosition

> _settle

> _doGmxSwap

It is important to note, that each of these functions is the last function executed in the transaction, before passing functionality to gmxProxy-> which will create the order on GMX and wait for a callback from GMX after order creation.

** At this point, no functions with the modifier gmxLockcan be executed, as it is now set to true. In the scope of the flow, this is the middle point.

** gmxLockis ONLY reset to falsein 2 functions:

> afterOrderExecution: Which is ONLY called by the gmxProxy AFTER the order has already been successfully created on GMX.

function afterOrderExecution(
bytes32 requestKey,
bytes32 positionKey,
IGmxProxy.OrderResultData memory orderResultData,
MarketPrices memory prices
) external nonReentrant {
if (msg.sender != address(gmxProxy)) {
revert Error.InvalidCall();
}
// MarketPrices memory marketPrices = gmxProxy.getMarketPrices(market);
_gmxLock = false;

> afterOrderCancellation: Which is ONLY called by the gmxProxy AFTER an order creation has been unsuccessfully created on GMX, but attempted and not unsuccessful because of the protocol wanting to cancel it , it then attempts to retry the order creation.

It is important to note that this has no role in the cancelFlowfunction -> this is functionality to handle situations where an order flow that the protocol wants to succeed runs into a problem on GMX and this will retry to create the order, becasue it is wanted that this users order is successful.

/**
* @notice Callback function triggered when an order execution on GMX is canceled due to an error.
* @param requestKey The request key of the executed order.
* @param orderType The type of order.
* @param orderResultData The result data of the order execution.
*/
function afterOrderCancellation(
bytes32 requestKey,
Order.OrderType orderType,
IGmxProxy.OrderResultData memory orderResultData
) external {
if (msg.sender != address(gmxProxy)) {
revert Error.InvalidCall();
}
_gmxLock = false;

** Also, both of those functions ARE ONLY CALLED AFTER the protocol attempts to create the order on GMX.

Impact

So for the situation where the protocol wants to manually cancel a users order flow, It will be unable to do so because they can only invoke the cancelFlowfunction after the initial transaction of the user depositingor withdrawingis completed.

Which, at that point, the gmxLockis already set to trueand functionality is passed to GMX and can only have gmxLockset to falseAFTER the order is attempted to be created.

The protocol can never stop an order flow involving gmxbecause of the order of transactions and the gmxLockbeing set to truein the initial transaction by the user.

Tools Used

Manual Review

Recommendations

Remove the gmxLockmodifier from cancelFlow

Updates

Lead Judging Commences

n0kto Lead Judge 9 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!