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

Manipulation of Transaction Gas Price in Fee Calculations

Summary

PerpetualVault contracts directly use tx.gasprice for calculating execution fees. This allows malicious users to manipulate the gas price when initiating transactions, potentially paying insufficient fees or causing denial-of-service conditions.

Vulnerability Details

The vulnerability exists in several locations where tx.gasprice is used to calculate execution fees:

Line 722 in PerpetualVault.sol
uint256 minExecutionFee = getExecutionGasLimit(isDeposit) * tx.gasprice;

For fee refund calculations in PerpetualVault._mint():

// Line 751 in PerpetualVault.sol
uint256 usedFee = callbackGasLimit * tx.gasprice;

And similarly in PerpetualVault._handleReturn():

// Line 955 in PerpetualVault.sol
uint256 usedFee = callbackGasLimit * tx.gasprice;

The issue is that tx.gasprice is a transaction-level property set by the original transaction sender, and it persists throughout the entire transaction execution regardless of which contracts are calling each other. This means users can manipulate this value to their advantage when interacting with the protocol.

Impact

This vulnerability can lead to several serious issues:

  1. Insufficient Execution Fees: A user could set an abnormally low gas price when calling deposit(), resulting in insufficient fees being collected to cover GMX execution costs.

  2. Economic Loss: The protocol might need to cover the difference between the collected execution fees and the actual cost of executing orders on GMX.

  3. Denial of Service: In extreme cases, if the collected fees are too low, GMX keepers might not execute the orders at all, causing operations to stall.

  4. Fee Miscalculation: In the case of fee refunds, an abnormally high gas price could lead to large refunds that don't reflect the actual execution cost.

The most direct attack vector is through the PerpetualVault.deposit() function, which is directly callable by users:

function deposit(uint256 amount) external payable nonReentrant {
_noneFlow();
if (depositPaused == true) {
revert Error.Paused();
}
// [...]
_payExecutionFee(counter, true);
// [...]
}

A user calling this function with a manipulated gas price would affect the fee calculations in _payExecutionFee().

Tools Used

Manual code review

Recommendations

The most robust mitigation would be to implement a gas price oracle system that provides reliable gas price data for both Arbitrum and Avalanche networks, as the protocol will be deployed on both platforms.

Updates

Lead Judging Commences

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

invalid_tx-gasprice_user_manipulation

If the sender does not provide enough, the transaction to create the order won't be included in the current block: no problem. If the user provides more, they will pay more: user mistake. Moreover, the `refundFee` is set to `true` only when the keeper is the caller, preventing manipulation.

Support

FAQs

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

Give us feedback!