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

The Incorrect Decimal Adjustment in Price Validation

Summary

Prices from the vault and Chainlink must be normalized to the same scale for accurate comparison. The decimal adjustment logic in _check miscalculates the scaling factor between the vault's price (1e30 precision) and Chainlink's 8 decimals.

Vulnerability Details

The decimal adjustment logic in _check miscalculates the scaling factor between the vault's price (1e30 precision) and Chainlink's 8 decimals. For a token with x decimals

uint256 decimals = 30 - IERC20Meta(token).deccs();
price = price / 10 ** (decimals - 8); // Incorrect scaling

A token with 18 decimals would incorrectly scale 1e30 to 1e26 instead of the correct 1e20 (to match Chainlink's 8 decimals). This leads to invalid price comparisons.

Example:

Token: USDC (18 decimals)

Vault Price: 1e30 (represents $1 per USDC)

Chainlink Price: 1e8 (represents $1 in 8 decimals)

decimals = 30 - 18 = 12

price = 1e30 / 10^(12 - 8) = 1e30 / 1e4 = 1e26

  • Result: Scaled price = 1e26

The divisor 10^(decimals - 8) uses 30 - tokenDecimals (12 for USDC) instead of tokenDecimals + 8 (26 for USDC).

  • The code scales the price to 1e26 instead of the correct 1e20.

Impact

Price validation fails even for valid prices, or passes for incorrect ones

Tools Used

Foundry

Recommendations

// Adjust for token decimals and Chainlink's 8 decimals:
price = price / 10 ** (tokenDecimals - 8); // 18 -8 =10 → 1e30 /1e10=1e20
Updates

Lead Judging Commences

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

invalid_prices_decimals

GMX github documentation: “Prices stored within the Oracle contract represent the price of one unit of the token using a value with 30 decimals of precision. Representing the prices in this way allows for conversions between token amounts and fiat values to be simplified, e.g. to calculate the fiat value of a given number of tokens the calculation would just be: token amount * oracle price, to calculate the token amount for a fiat value it would be: fiat value / oracle price.” Sponsor confirmed the keeper does the same, so price decimals change in function of the token, to be sure the above rule is true. Example for USDC (6 decimals): Prices will have 24 decimals → 1e6 * 1e24 = 1e30. Just a reminder for some submissions: shortToken == collateralTokens, so the decimals is 1e24 for shortToken prices.

Support

FAQs

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