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

Unchecked Position Size Validation Compromises Vault Risk Management

Summary

The VaultReader contract's position size validation fails to properly handle non-zero keys, allowing potential misreporting of position sizes. This could lead to incorrect position calculations and risk management in the perpetual trading system. When a non-zero key is passed, the contract returns potentially invalid position sizes without proper validation. Just like a bank checking account balances, while it correctly shows zero balance for new accounts (key = 0), it fails to properly validate existing account balances (non-zero keys). This creates a disconnect between what the system thinks exists and what actually exists in GMX's storage.

In VaultReader.sol#getPositionSizeInUsd

/**
* @notice Retrieves the position size in USD for a given key.
* @param key The key representing the position.
* @return sizeInUsd The size of the position in USD.
*/
function getPositionSizeInUsd(bytes32 key) public view returns (uint256 sizeInUsd) {
sizeInUsd = dataStore.getUint(keccak256(abi.encode(key, SIZE_IN_USD)));
}

The flow: arbitrary keykeccak256 hashdataStore lookupunchecked return value

The VaultReader contract serves as the eyes of the Perpetual Vault system, responsible for accurately reporting position sizes from GMX. When users deposit USDC to open leveraged positions, the system needs to track these positions reliably. However, there's a critical oversight in how position sizes are validated.

Vulnerability Details

When users deposit USDC to open leveraged positions up to 3x, the system must maintain precise position tracking to protect user funds and manage risk effectively.

The vulnerability emerges in how position sizes are validated. The VaultReader directly passes through GMX storage values without proper bounds checking or validation. This creates a dangerous scenario where the vault could operate with incorrect position sizes, similar to a trading system accepting unverified account balances.

In the real world, this manifests when users interact with leveraged positions. The VaultReader's getPositionSizeInUsd() function blindly trusts GMX storage values

// 🎯 VaultReader.sol - Core vulnerability location
function getPositionSizeInUsd(bytes32 key) public view returns (uint256 sizeInUsd) {
// 🚨 Direct pass-through to GMX storage without validation
sizeInUsd = dataStore.getUint(keccak256(abi.encode(key, SIZE_IN_USD)));
}

When position sizes exceed expected bounds, the entire risk management system becomes compromised. The vault could:

  • Allow leverage beyond the protocol's 3x maximum

  • Miscalculate user share allocations

  • Incorrectly distribute funding fees

  • Make flawed position management decisions

Impact

The code assumed GMX's dataStore would handle position size validation, but overlooked:

  1. The protocol's position key format requirements (Section 4.2 of GMX docs)

  2. The need for bounds checking on returned values

  3. The potential for malicious position key crafting

Recommendations

Validation should be implemented at multiple levels

// 🔍 VaultReader.sol
function getPositionSizeInUsd(bytes32 key) public view returns (uint256 sizeInUsd) {
// ✅ Validate against GMX position key format
bytes32 positionKey = keccak256(abi.encode(key, SIZE_IN_USD));
sizeInUsd = dataStore.getUint(positionKey);
// ✅ Check against vault's leverage limits (max 3x per README)
require(sizeInUsd <= maxDepositAmount * 3, "Exceeds max leverage");
}
Updates

Lead Judging Commences

n0kto Lead Judge 9 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.

Give us feedback!