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

msg.value for fee of one user will pay for the deposit process of another user who will not have enough funds

Summary

msg.value for fee of one user will pay for the deposit process of another user who will not have enough funds for pay fee

The PerpetualVault contract uses msg.value to pay for GMX Keeper execution fees, transferring the value to the gmxProxy. The contract does not check if the msg.value is sent by the user making the deposit or withdrawal.

Vulnerability Details

Example: Alice calls the function deposit and enters the amount she wants to invest and sends msg.value in parallel, Bob also calls deposit with msg.value separately at the same time, but Bob cannot call the function anymore because he will encounter an error because deposit == true after Alice. However, Bob's msg.value will still lie on the contract. Thus Alice will eventually if her msg.value is not enough then Bob's msg.value is used too because there is no binding of msg.value to the user.

In the PerpetualVault contract code, there is no explicit binding of msg.value to a specific user in the deposit and follow-up processing functions. The _payExecutionFee function verifies that msg.value is sufficient to cover the execution fee, but does not identify the sender of the funds. If the msg.value passed by Alice is not sufficient to cover the fee, and the funds from Bob's msg.value remain on the contract, they can be used to pay Alice's fee. A subsequent call to deposit from Bob will fail due to the FLOW lock, but his msg.value remains on the contract and can be used to cover other users' commissions.

function _payExecutionFee(uint256 depositId, bool isDeposit) internal {
uint256 minExecutionFee = getExecutionGasLimit(isDeposit) * tx.gasprice;
if (msg.value < minExecutionFee) {
revert Error.InsufficientAmount();
}
if (msg.value > 0) {
payable(address(gmxProxy)).transfer(msg.value);
depositInfo[depositId].executionFee = msg.value;
}
}

Impact

This creates an opportunity for DoS attacks where any user can intercept (front run) a deposit or withdrawal and execute the transaction for another. The original user will still receive tokens or collateral, but the attacker can make the transaction more expensive by using their msg.value or "stolen" msg.value from other users.

Tools Used

Manual

Recommendations

To mitigate this issue, the contract should validate that msg.sender is the same as the depositor or withdrawer.

Updates

Lead Judging Commences

n0kto Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Appeal created

hajime Submitter
7 months ago
n0kto Lead Judge
6 months ago
n0kto Lead Judge 6 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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