The VaultReader::getPriceImpactInCollateral
function fails to account for varying token decimals when converting price impact between tokens, potentially leading to incorrect share calculations. This issue affects the vault's core accounting and could result in significant share misallocations regardless of the decimal combinations of the token pairs used.
The current price impact calculation doesn't account for decimal differences between tokens:
The calculation involves:
Index token (variable decimals, e.g., ETH: 18, BTC: 8)
Collateral token (variable decimals, e.g., USDC: 6)
Price feeds: 30 decimals
For example, with ETH/USDC:
The result maintains the index token's decimals instead of converting to collateral token decimals, leading to incorrect share calculations in PerpetualVault::afterOrderExecution
, particularly where increased = amount - feeAmount - uint256(priceImpact) - 1;
is calculated and the subsequent _mint()
call is made.
Example scenarios showing the decimal mismatch:
Incorrect share minting: Users receive wrong number of shares based on their deposits
Impact varies based on decimal differences between token pairs
Breaks vault's share-to-asset ratio
Unfair profit/loss distribution among users
Issue becomes more severe with larger decimal differences between tokens
Manual
Track token decimals at contract initialization:
Modify price impact calculation to account for decimal differences:
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.