When refunding a user in _handleReturn
we perform burn()
first (which deleted the depositInfo[]
of the user) and then do the refund which reads the depositInfo[depositId].executionFee
, but since depositInfo[]
has been deleted before , depositInfo[depositId].executionFee
would be read as 0 hence no refunds.
Consider the following ->
1.) There's a 1x Long perp vault position open on GMX (positionIsClosed
is false).
2.) A user wants to withdraw hence calls withdraw()
at L253 , and pays the execution fee at L272 _payExecutionFee(depositId, false);
, and _withdraw()
is invoked .
3.) Since position is 1x long , inside _withdraw()
this branch would be executed (L1097 - L1102)->
4.) Since next action is now SWAP_ACTION
, when keeper runs runNextAction()
, this branch would be called (L382 - L387) ->
5.) Therefore , _runSwap
is called and assuming metada.length == 1
(passed in _runNextAction) this branch of runSwap would be invoked ->
6.) We perform the swap through _doDexSwap
and then since flow is WITHDRAW ->
7.) Therefore , _handleReturn
is called with refundFee as true (because we wanna refund since no interaction with GMX took place) ->
[https://github.com/CodeHawks-Contests/2025-02-gamma/blob/main/contracts/PerpetualVault.sol#L1129]
and then amount is calculated to be transferred and then transferred via _transferToken
8.) Then we burn the depositId (L1143) and inside burn we delete the depositInfo of the user ->
9.) Then in _handleReturn since refundFee
was true we do ->
10.) But since depositInfo
is deleted in burn , depositInfo[depositId].executionFee
would always be 0 and therefore no refund would take place in the above refund fee branch (this refund is for excess fee or since this swap was completed by the dex and not on gmx side).
The above refund would never take place since burn is performed before refund .
Manual analysis
Call burn after refunding the fee.
Likelihood: High, every time a user withdraw on 1x vault with paraswap Impact: Medium, fees never claimed to GMX and refund to the owner.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.