The getPriceImpactInCollateral
function calculates expectedSizeInTokensDelta
using division before multiplication, leading to truncation errors. This results in understated price impact values, causing inaccurate loss calculations during swaps or leverage adjustments.
Division Before Multiplication:
sizeDeltaInUsd / prices.indexTokenPrice.min
truncates fractional values due to integer division.
Example: If sizeDeltaInUsd = 1500e30
(1,500 USD) and prices.indexTokenPrice.min = 2000e30
($2,000 per token), the division yields 0.75
tokens, which truncates to 0
in integer math.
Subsequent multiplication (0 * price
) results in zero price impact, even though the actual impact should be non-zero.
Understated Losses: Traders may incur larger-than-expected losses during swaps or leverage changes.
Protocol Insolvency Risk: Miscalculations could lead to insufficient collateral reserves to cover actual losses.
Input Values:
sizeDeltaInUsd = 1500e30
($1,500)
prices.indexTokenPrice.min = 2000e30
($2,000 per token)
prices.shortTokenPrice.min = 1e30
($1.00)
Faulty Calculation:
expectedSizeInTokensDelta = 1500e30 / 2000e30 = 0
(truncated from 0.75
).
priceImpactInTokens = 0 - realSizeInTokensDelta
(assume realSizeInTokensDelta = 0.5
).
priceImpactInCollateralTokens = (-0.5) * 2000e30 / 1e30 = -1000e30
(-$1,000).
Correct Calculation (Multiplication First):
expectedSizeInTokensDelta = (1500e30 * 1e30) / 2000e30 = 750e27
(0.75 tokens).
priceImpactInTokens = 0.75 - 0.5 = 0.25
.
priceImpactInCollateralTokens = 0.25 * 2000e30 / 1e30 = 500e30
($500).
Result: The protocol understates the price impact by **1,000vs.
+$500`), leading to incorrect loss reporting.
Perform multiplication before division to preserve precision:
Add a scaling factor (e.g., 1e18
) to minimize truncation:
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.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.