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

Gas Price Manipulation Leading to Forced Deposit Failure

Summary

The _payExecutionFee() function calculates the required execution fee using gas price at execution time (tx.gasprice). Since tx.gasprice can be manipulated by front-running attacks, an attacker can artificially increases gas prices right before a user's transaction executes. This results in a higher required execution fee than the user originally sent, causing _payExecutionFee() to revert the deposit transaction.

This attack does not require direct contract interaction an attacker can simply manipulate gas fees at the mempool level, making it hard to trace and difficult for regular users to prevent

Vulnerability Details

HOW THE ATTACK WORKS

Normal Execution:

Assume getExecutionGasLimit(isDeposit) = 50,000 gas
Current gas price: tx.gasprice = 2 gwei
Required execution fee calculation:

minExecutionFee = 50,000 * 2 gwei = 100,000 gwei (0.0001 ETH)
  • User submits a deposit transaction with msg.value = 0.0001 ETH
    Deposit executes succesfully.

Attack Process:

  • Victim submits a deposit transaction with msg.value = minExecutionFee, based on the current gas price (2 gwei).

  • Attacker monitors the pending transaction in the mempool and submits a transaction with an artificially high gas price (10 gwei).

  • Ethereum's fee mechanism adjusts to the new higher gas price.

  • When the victim's transaction executes, tx.gasprice is now 10 gwei instead of 2 gwei.

  • The new required execution fee is now:

minExecutionFee = 50,000 * 10 gwei = 500,000 gwei (0.0005 ETH)
  • Since the user only sent 0.0001 ETH, _payExecutionFee() reverts, causing the deposits to fail.

  • Attacker's gas-spike transaction gets mined first, but they do not lose any ETH because they never interact with the contract.

Attacker successful >>
Deposit fails without direct contract interaction.

ROOT CAUSE

  • The contract relies on tx.gasprice, which is variable and attackable.

Impact

Users are locked out of depositing
Attackers can target specific users and prevent their deposits from going through (DoS)

Tools Used

Manual Review

Recommendations

Use block.basefee instead of tx.gasprice
Ethereum introduced EIP-1559, which seperate base fee (block.basefee) from priority fees (tx.gasprice).

why it works it is constant for an entire block, so it cannot be manipulated per transaction.

  • Unlike tx.gasprice, it remains stable even if atackers front-run.

  • Prevents deposit failures due to gas spikes.

uint256 minExecutionFee = getExecutionGasLimit(isDeposit) * block.basefee;

The same issue in other function that users tx.gasprice

Updates

Lead Judging Commences

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

invalid_tx-gasprice_instable

The frontrunner won’t trigger "congestion" without a huge amount of transactions, and it will cost a lot. Moreover, the execution gas limit is overestimated to prevent such cases: ``` executionGasLimit = baseGasLimit + ((estimatedGasLimit + _callbackGasLimit) * multiplierFactor) / PRECISION; ``` The keeper won’t wait long to execute the order; otherwise, GMX would not be competitive.

Support

FAQs

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