Refund execution fee logic within the _handleReturn function use the wrong argument which causes the execution fee being refunded to the wrong recipient.
Below is a snippet of the _handleReturnfunction from PerpetualVault.sol:
In the if refundFee block, it performs a check on depositInfo[depositId].executionFee but then uses depositInfo[counter] when calling refundExecutionFee. counter is a state variable that only increment by 1 when there is a new deposit, while depositId comes from the flowData which is updated with the value of the intended deposit id of the user that requested withdrawal.
Consider this scenario:
User A deposits funds, the contract increments the counter to 1 and the contract assigns a deposit ID of 1. In the deposit record depositInfo[1], User A has an executionFee of 1 ETH.
Shortly after, User B deposits funds, and the contract increments the counter to 2, creating depositInfo[2] with an executionFee of 1.2 ETH.
User A initiates a withdrawal that triggers the _handleReturn function with depositId 1.
Inside _handleReturn, the function calculates usedFee (for example, 0.1 ETH) and checks that depositInfo[1].executionFee (1 ETH) is greater than usedFee.
Intended Behavior: The refund should be calculated as 1 ETH - 0.1 ETH = 0.9 ETH and be sent to User A.
Actual Behavior: Due to the bug, the refund call uses depositInfo[2] instead of depositInfo[1]. As a result, the function refunds 1.2 ETH - 0.1 ETH = 1.1 ETH to User B instead of refunding User A.
It is noteworthy that this function will only hit the refund logic if the owner need to change the flow state to WITHDRAW through the setVaultStatefunction, because the only instance where _handleReturn is called with the refundFee parameter set to true is in the _runSwapfunction which can be called manually through the runNextActionfunction by the keeper.
Execution fee is refunded to the wrong user with the wrong amount.
Manual review
Replace depositInfo[counter] with depositInfo[depositId] in the refund fee block to ensure that the refund logic correctly references the intended deposit.
Likelihood: Medium/High, when withdraw on a 1x vault. Impact: High, the fees will be distributed to the last depositor and not the withdrawer.
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.