DeFiFoundry
50,000 USDC
View results
Submission Details
Severity: high
Valid

User can never withdraw from a 1x leverage position without using the GMX swap.

Summary

In _handleReturn() the refunding of a depositId is done after the depositInfo[depositId] is deleted. This will always result in revert.

Vulnerability Details

Lets say the position is 1x leverage Open and a user calls withdraw(). (FLOW = FLOW.WITHDRAW)

Now the keeper calls runNextAction() inorder to swap the indexTokens to collatteralTokens by just using paraswaps. Hence no calls to GMX swap iis made.

This code will get executed.

_handleReturn(outputAmount + swapProgressData.swapped, false, true);

refundFees is true here. Since no gmxCalls are been done.

Now lets check inside _handleReturn() .

https://github.com/CodeHawks-Contests/2025-02-gamma/blob/84b9da452fc84762378481fa39b4087b10bab5e0/contracts/PerpetualVault.sol#L1143-L1150

function _handleReturn(uint256 withdrawn, bool positionClosed, bool refundFee) internal {
...
=> _burn(depositId);
if (refundFee) {
uint256 usedFee = callbackGasLimit * tx.gasprice;
=> if (depositInfo[depositId].executionFee > usedFee) {
try IGmxProxy(gmxProxy).refundExecutionFee(depositInfo[counter].owner, depositInfo[counter].executionFee - usedFee) {} catch {}
}
}

in _burn(depositId)code depositInfo[depositId] is deleted and the check depositInfo[depositId].executionFee > usedFee is made after the this deletion.

Hence this txn will revert leading to the dos.

Impact

User can never withdraw from a 1x leverage position without using the GMX swap.

Tools Used

Manual

Recommendations

execute refund fees even before.

Updates

Lead Judging Commences

n0kto Lead Judge 5 months ago
Submission Judgement Published
Validated
Assigned finding tags:

finding_burn_depositId_before_refund

Likelihood: High, every time a user withdraw on 1x vault with paraswap Impact: Medium, fees never claimed to GMX and refund to the owner.

Support

FAQs

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