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

Critical Position Validation

Summary

There is an issue in the VaultReader contract position validation logic that incorrectly blocks the opening of valid positions and can cause significant trading disruption. The issue stems from incorrect validation in the willPositionCollateralBeInsufficient function.

Vulnerability Details

function willPositionCollateralBeInsufficient(
MarketPrices memory prices,
bytes32 positionKey,
address market,
bool isLong,
uint256 sizeDeltaUsd,
uint256 collateralDeltaAmount
) external view returns (bool) {
if (getPositionSizeInUsd(positionKey) == 0) return true; // Issue line
...
}

In the willPositionCollateralBeInsufficient function, the function always assumes insufficient collateral if position = 0 without validating the actual collateral amount provided, does not check market-specific minimum collateral requirements, and does not consider the proposed position size and leverage. This may prevent new positions from being opened that are actually valid.

Impact

  • All new position openings are blocked

  • Valid trades with sufficient collateral are rejected

  • Users cannot enter positions even with excess collateral

Scenario

1.User attempts to open a new position with valid collateral:

// Example: User wants to open a position
collateral = 1000 USDC
leverage = 2x
position size = 2000 USD

2.System calls willPositionCollateralBeInsufficient to validate

3.Function sees position size is 0 (new position)

4.Returns true automatically, rejecting the valid trade

5.Position is blocked despite having sufficient collateral

Tools Used

  • Manual review

Recommendations

Remove immediate true return when position = 0, add minimum collateral required based on position size, and add safety buffer to avoid too close liquidation.

function willPositionCollateralBeInsufficient(
MarketPrices memory prices,
bytes32 positionKey,
address market,
bool isLong,
uint256 sizeDeltaUsd,
uint256 collateralDeltaAmount
) external view returns (bool) {
uint256 currentPositionSize = getPositionSizeInUsd(positionKey);
// For new positions (current Position Size == 0)
if (currentPositionSize == 0) {
// Get market parameters
MarketProps memory marketProps = getMarket(market);
// Calculate the minimum collateral required based on position size
uint256 minRequiredCollateral = (sizeDeltaUsd * marketProps.minCollateralFactor) / PRECISION;
// Add 2% safety margin
uint256 requiredCollateralWithBuffer = (minRequiredCollateral * 102) / 100;
// Return true if collateral is less than required
return collateralDeltaAmount < requiredCollateralWithBuffer;
}
// For existing positions
PositionInfo memory positionInfo = gmxReader.getPositionInfo(
address(dataStore),
referralStorage,
positionKey,
prices,
uint256(0),
address(0),
true
);
uint256 remainingCollateral = positionInfo.position.numbers.collateralAmount - collateralDeltaAmount;
uint256 requiredCollateral = (sizeDeltaUsd * marketProps.minCollateralFactor) / PRECISION;
return remainingCollateral < requiredCollateral;
}
Updates

Lead Judging Commences

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

Suppositions

There is no real proof, concrete root cause, specific impact, or enough details in those submissions. Examples include: "It could happen" without specifying when, "If this impossible case happens," "Unexpected behavior," etc. Make a Proof of Concept (PoC) using external functions and realistic parameters. Do not test only the internal function where you think you found something.

Support

FAQs

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