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

Unchecked Subtraction in Token Delta Calculation

Summary

The getPriceImpactInCollateral function in VaultReader.sol contains a calculation error that can lead to underflows when calculating position size deltas, potentially causing transaction reverts or incorrect price impact calculations.

Vulnerability Details

function getPriceImpactInCollateral(
bytes32 positionKey,
uint256 sizeDeltaInUsd,
uint256 prevSizeInTokens,
MarketPrices memory prices
) external view returns (int256) {
uint256 expectedSizeInTokensDelta = sizeDeltaInUsd / prices.indexTokenPrice.min;
uint256 curSizeInTokens = getPositionSizeInTokens(positionKey);
uint256 realSizeInTokensDelta = prevSizeInTokens - curSizeInTokens; // Potential underflow
int256 priceImpactInTokens = expectedSizeInTokensDelta.toInt256() - realSizeInTokensDelta.toInt256();
return priceImpactInTokens * prices.indexTokenPrice.min.toInt256() / prices.shortTokenPrice.min.toInt256();
}

Problems:

  1. Unsigned arithmetic for realSizeInTokensDelta calculation

  2. No validation of size parameters

  3. Potential precision loss in division operations

Impact

Severity: Medium

Reasons:

  • No direct fund loss

  • Affects price impact calculations

  • Can cause position operations to fail

  • Recoverable through contract upgrades

Tools Used

  • Manual code review

  • Solidity static analysis

  • Foundry testing framework

Recommendations

  1. Use signed arithmetic for delta calculations:

function getPriceImpactInCollateral(
bytes32 positionKey,
uint256 sizeDeltaInUsd,
uint256 prevSizeInTokens,
MarketPrices memory prices
) external view returns (int256) {
uint256 expectedSizeInTokensDelta = sizeDeltaInUsd / prices.indexTokenPrice.min;
uint256 curSizeInTokens = getPositionSizeInTokens(positionKey);
// Convert to signed integers early
int256 realSizeInTokensDelta = int256(prevSizeInTokens) - int256(curSizeInTokens);
int256 expectedDeltaSigned = int256(expectedSizeInTokensDelta);
// Calculate price impact
int256 priceImpactInTokens = expectedDeltaSigned - realSizeInTokensDelta;
// Validate results
require(
prices.indexTokenPrice.min > 0 && prices.shortTokenPrice.min > 0,
"Invalid prices"
);
return priceImpactInTokens *
int256(prices.indexTokenPrice.min) /
int256(prices.shortTokenPrice.min);
}
  1. Add input validation:

modifier validatePrices(MarketPrices memory prices) {
require(prices.indexTokenPrice.min > 0, "Invalid index price");
require(prices.shortTokenPrice.min > 0, "Invalid short price");
_;
}
function getPriceImpactInCollateral(
bytes32 positionKey,
uint256 sizeDeltaInUsd,
uint256 prevSizeInTokens,
MarketPrices memory prices
) external view validatePrices(prices) returns (int256) {
// ... rest of function
}
  1. Add events for monitoring:

event PriceImpactCalculated(
bytes32 indexed positionKey,
int256 priceImpact,
uint256 prevSize,
uint256 currentSize
);

The recommended changes will:

  1. Prevent arithmetic underflows

  2. Improve calculation accuracy

  3. Add safety checks

  4. Enable better monitoring

Updates

Lead Judging Commences

n0kto Lead Judge 5 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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