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

Missing Collateral Sufficiency Validation Causes Failed GMX Orders and Wasted Gas/Execution Fees

Summary

The PerpetualVault contract fails to validate if there will be sufficient collateral when creating increase position orders on GMX. This oversight leads to orders that are destined to fail GMX's internal collateral validation, resulting in wasted gas and execution fees for users and keepers.

Vulnerability Details

The PerpetualVault contract's _createIncreasePosition() function creates increase orders without checking if the position will have sufficient collateral according to GMX's requirements. However, GMX's increasePosition() function performs strict collateral sufficiency validation and reverts if the check fails.

Several dynamic factors affect position collateral requirements:

  • Position leverage fluctuates with market price changes

  • GMX's maximum leverage is dynamic, increasing with market open interest

  • Trading fees and price impact can increase required collateral

  • Funding fees accumulate over time

Here's how GMX validates collateral sufficiency:

// From GMX's IncreasePositionUtils (OrderHandler: 0xe68CAAACdf6439628DFD2fe624847602991A31eB)
function increasePosition(...) external {
// ...
(bool willBeSufficient, int256 remainingCollateralUsd) =
PositionUtils.willPositionCollateralBeSufficient(...);
if (!willBeSufficient) {
revert Errors.InsufficientCollateralUsd(remainingCollateralUsd);
}
// ...
}

The PerpetualVault should perform similar validation before submitting orders to avoid guaranteed failures:

// Current PerpetualVault implementation - missing validation
function _createIncreasePosition(
bool _isLong,
uint256 acceptablePrice,
MarketPrices memory prices
) internal {
uint256 sizeDelta = prices.shortTokenPrice.max * amountIn * leverage / BASIS_POINTS_DIVISOR;
// Creates order without checking if collateral will be sufficient
Order.OrderType orderType = Order.OrderType.MarketIncrease;
collateralToken.safeTransfer(address(gmxProxy), amountIn);
// ...
}

Proof of Concept

  1. User deposits into vault when market conditions make GMX's required collateral higher than normal

  2. Vault creates increase position order without validating collateral sufficiency

  3. Keeper executes order and pays gas

  4. GMX's increasePosition() reverts due to insufficient collateral

  5. Transaction fails, gas and execution fees are wasted

Impact Details

Failed orders due to insufficient collateral validation result in wasted gas fees for users and keepers, along with consumed execution fees for unsuccessful transactions. This issue is particularly impactful during high volatility periods when market conditions frequently change collateral requirements, leading to a higher rate of failed transactions and unnecessary gas consumption.

Tools Used

Manual Review

Recommendations

Add collateral sufficiency validation before creating increase position orders:

function _createIncreasePosition(
bool _isLong,
uint256 acceptablePrice,
MarketPrices memory prices
) internal {
uint256 amountIn;
if (flow == FLOW.DEPOSIT) {
amountIn = depositInfo[counter].amount;
flowData = vaultReader.getPositionSizeInTokens(curPositionKey);
} else {
amountIn = collateralToken.balanceOf(address(this));
}
uint256 sizeDelta = prices.shortTokenPrice.max * amountIn * leverage / BASIS_POINTS_DIVISOR;
// Add validation for sufficient collateral
+ if (vaultReader.willPositionCollateralBeInsufficient(
+ prices,
+ curPositionKey,
+ market,
+ _isLong,
+ sizeDelta,
+ 0 // No collateral being removed
+ )) {
+ revert Error.InsufficientCollateral();
+ }
Order.OrderType orderType = Order.OrderType.MarketIncrease;
collateralToken.safeTransfer(address(gmxProxy), amountIn);
// ... rest of function
}

This ensures orders are only created when they have a reasonable chance of success based on current market conditions.

Updates

Lead Judging Commences

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

Informational or Gas

Please read the CodeHawks documentation to know which submissions are valid. If you disagree, provide a coded PoC and explain the real likelihood and the detailed impact on the mainnet without any supposition (if, it could, etc) to prove your point.

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

Informational or Gas

Please read the CodeHawks documentation to know which submissions are valid. If you disagree, provide a coded PoC and explain the real likelihood and the detailed impact on the mainnet without any supposition (if, it could, etc) to prove your point.

Appeal created

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

Informational or Gas

Please read the CodeHawks documentation to know which submissions are valid. If you disagree, provide a coded PoC and explain the real likelihood and the detailed impact on the mainnet without any supposition (if, it could, etc) to prove your point.

Support

FAQs

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