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

Fixing Integer Overflows and Underflows in VaultReader Contract

Summary

The VaultReader contract previously contained integer overflow and underflow risks in the calculation of netValue in getPositionInfo() function. The vulnerabilities arose from unchecked arithmetic operations on position collateral, fees, and token prices. This report outlines the identified issues, their impact, and the implemented fixes to ensure safe arithmetic operations using OpenZeppelin’s SafeMath library.

Vulnerability Details

The affected code segment involved calculations such as:

Issues Identified:

1. Multiplication Overflows: If collateralAmount or shortTokenPrice.min were too large, the multiplication could exceed the maximum uint256 value (2^256 - 1), leading to an overflow.

2. Subtraction Underflows: If the sum of all subtracted fees exceeded the total collateral, an underflow could occur, potentially causing unintended behavior.

3. Negative PnL Handling: Since PnL can be negative, incorrect conversion from int256 to uint256 could lead to unintended arithmetic results.

uint256 netValue =
positionInfo.position.numbers.collateralAmount * prices.shortTokenPrice.min +
positionInfo.fees.funding.claimableLongTokenAmount * prices.longTokenPrice.min +
positionInfo.fees.funding.claimableShortTokenAmount * prices.shortTokenPrice.min -
positionInfo.fees.borrowing.borrowingFeeUsd -
positionInfo.fees.funding.fundingFeeAmount * prices.shortTokenPrice.min -
positionInfo.fees.positionFeeAmount * prices.shortTokenPrice.min;

Impact

• Overflow or underflow in these calculations could result in incorrect values for netValue, leading to incorrect risk calculations, improper liquidations, or manipulated position sizes.

• If exploited, malicious actors could prevent liquidation of undercollateralized positions or manipulate displayed PnL values, creating an economic attack vector within the system.

Tools Used

Slither (Static analysis) – Detected potential overflow and underflow risks.

Foundry/Hardhat Tests – Confirmed calculations under extreme values.

Recommendations

To mitigate these risks, SafeMath from OpenZeppelin was used for secure arithmetic operations. The updated safe version of the netValue calculation is:

import "@openzeppelin/contracts/utils/math/SafeMath.sol";
contract VaultReader {
using SafeMath for uint256; // Enable SafeMath for uint256 operations
function getPositionInfo(
bytes32 key,
MarketPrices memory prices
) external view returns (PositionData memory) {
uint256 sizeInTokens = getPositionSizeInUsd(key);
if (sizeInTokens == 0) {
return PositionData({
sizeInUsd: 0,
sizeInTokens: 0,
collateralAmount: 0,
netValue: 0,
pnl: 0,
isLong: true
});
}
PositionInfo memory positionInfo = gmxReader.getPositionInfo(
address(dataStore),
referralStorage,
key,
prices,
uint256(0),
address(0),
true
);
uint256 netValue =
positionInfo.position.numbers.collateralAmount.mul(prices.shortTokenPrice.min)
.add(positionInfo.fees.funding.claimableLongTokenAmount.mul(prices.longTokenPrice.min))
.add(positionInfo.fees.funding.claimableShortTokenAmount.mul(prices.shortTokenPrice.min))
.sub(positionInfo.fees.borrowing.borrowingFeeUsd)
.sub(positionInfo.fees.funding.fundingFeeAmount.mul(prices.shortTokenPrice.min))
.sub(positionInfo.fees.positionFeeAmount.mul(prices.shortTokenPrice.min));
// Handle negative PnL correctly
if (positionInfo.basePnlUsd >= 0) {
netValue = netValue.add(uint256(positionInfo.basePnlUsd));
} else {
netValue = netValue.sub(uint256(-positionInfo.basePnlUsd));
}
return PositionData({
sizeInUsd: positionInfo.position.numbers.sizeInUsd,
sizeInTokens: positionInfo.position.numbers.sizeInTokens,
collateralAmount: positionInfo.position.numbers.collateralAmount,
netValue: netValue,
pnl: positionInfo.basePnlUsd,
isLong: positionInfo.position.flags.isLong
});
}
}

Improvements Implemented:

✅ Multiplication safety – Using .mul() from SafeMath to prevent overflows.
✅ Subtraction safety – Using .sub() from SafeMath to avoid underflows.
✅ Proper PnL handling – Explicit conversion of int256 to uint256 with validation.

Updates

Lead Judging Commences

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