Within the GMXOracle#getLpTokenValue()
, the decimals precision of each GMX MarketToken-returned via the GMXOracle#getMarketTokenInfo()
would be assumed as 1e3## Summary Within the GMXOracle#
getLpTokenValue(), the decimals precision of each GMX MarketToken-returned via the GMXOracle#
getMarketTokenInfo()would be assumed as
1e30. And therefore, it would be normalized by dividing it by
1e12. However, the actual decimals precision of each GMX MarketToken-returned via the GMXOracle#
getMarketTokenInfo()would be in
1e18`.
This lead to a deflated-price of GM token (LpTokenValue
) due to unnecessary precision downscaling.
When retrieving a price of a GM token (LpTokenValue
), the GMXOracle#getLpTokenValue()
would be called.
Within the GMXOracle#getLpTokenValue()
, the GMXOracle#getMarketTokenInfo()
would be called to retrieve the _marketTokenPrice
. And then, it would be normalized by dividing by 1e12
. Finally the result would be returned like this:
https://github.com/Cyfrin/2023-10-SteadeFi/blob/main/contracts/oracles/GMXOracle.sol#L250-L257
https://github.com/Cyfrin/2023-10-SteadeFi/blob/main/contracts/oracles/GMXOracle.sol#L263-L264
Within the GMXOracle#getMarketTokenInfo()
, the result of the ISyntheticReader#getMarketTokenPrice()
(Reader#getMarketTokenPrice()
) would be returned like this:
Note
The original contract of the ISyntheticReader would be named the Reader contract:https://github.com/gmx-io/gmx-synthetics/blob/main/contracts/reader/Reader.sol#L187-L206
(Doc:https://gmx-docs.io/docs/api/contracts-v2#reading-values )
https://github.com/Cyfrin/2023-10-SteadeFi/blob/main/contracts/oracles/GMXOracle.sol#L178-L186
Within the Reader#getMarketTokenPrice()
(ISyntheticReader#getMarketTokenPrice()
), the result of the MarketUtils#getMarketTokenPrice()
would be returned like this:
https://github.com/gmx-io/gmx-synthetics/blob/main/contracts/reader/Reader.sol#L197-L205
Within the MarketUtils#getMarketTokenPrice()
, the marketTokenPrice
would be calculated based on the formula (Precision.mulDiv(Precision.WEI_PRECISION, poolValueInfo.poolValue, supply)
). And then, the result of the calculation would be returned like this:
https://github.com/gmx-io/gmx-synthetics/blob/main/contracts/market/MarketUtils.sol#L164-L165
Let's zooming into the calculation of the marketTokenPrice
above.
Here is the calculation process of the marketTokenPrice
above to observe only decimals precision transition in the calculation process of above:
https://github.com/gmx-io/gmx-synthetics/blob/main/contracts/market/MarketUtils.sol#L164
As we can see above, the decimals precision of the marketTokenPrice
would result in 1e18
.
Also, according to the "Market" part in the GMX's README, the price of MarketToken, which is retrieved via the MarketUtils#getMarketTokenPrice()
, would be in 1e18
decimals precision like this:
https://github.com/gmx-io/gmx-synthetics/tree/main#markets-1 \
At any point in time, the price of a MarketToken is
(worth of market pool) / MarketToken.totalSupply()
, the functionMarketUtils.getMarketTokenPrice
can be used to retrieve this value.
The worth of the market pool is the sum of
worth of all tokens deposited into the pool
total pending PnL of all open positions
total pending borrow fees of all open positions
In addition to that, according to the arbiscan (Etherscan for Arbitrum), the decimals precision of each GM token on Arbitrum-used in the SteadeFi protocol would be the 1e18
like this: \
ETH-USDC GM token:0x70d95587d40a2caf56bd97485ab3eec10bee6336
https://arbiscan.io/token/0x70d95587d40a2caf56bd97485ab3eec10bee6336
WBTC-USDC GM token:0x47c031236e19d024b42f8AE6780E44A573170703
https://arbiscan.io/token/0x47c031236e19d024b42f8AE6780E44A573170703
ARB-USDC GM token: 0xC25cEf6061Cf5dE5eb761b50E4743c1F5D7E5407
https://arbiscan.io/token/0xC25cEf6061Cf5dE5eb761b50E4743c1F5D7E5407
LINK-USDC GM token: 0x7f1fa204bb700853D36994DA19F830b6Ad18455C
https://arbiscan.io/token/0x7f1fa204bb700853D36994DA19F830b6Ad18455C
SOL-USDC GM token: 0x09400D9DB990D5ed3f35D7be61DfAEB900Af03C9
https://arbiscan.io/token/0x09400D9DB990D5ed3f35D7be61DfAEB900Af03C9
UNI-USDC GM token: 0xc7Abb2C5f3BF3CEB389dF0Eecd6120D451170B50
https://arbiscan.io/token/0xc7Abb2C5f3BF3CEB389dF0Eecd6120D451170B50
However, within the GMXOracle#getLpTokenValue()
, the decimals precision of each GMX MarketToken-returned via the GMXOracle#getMarketTokenInfo()
would be assumed as a 1e30
.
This is problematic. Because, within the GMXOracle#getLpTokenValue()
, the decimals precision of each GMX MarketToken-returned would be 1e12
times smaller than the actual decimals precision of it if the decimals precision of each GMX MarketToken-returned via the GMXOracle#getMarketTokenInfo()
would be in 1e18
before normalized like this:
(NOTE:Below would track only decimals precision transition)
https://github.com/Cyfrin/2023-10-SteadeFi/blob/main/contracts/oracles/GMXOracle.sol#L263-L264
This lead to a deflated-price of GM token (LpTokenValue
) due to unnecessary precision downscaling.
This lead to a deflated-price of GM token (LpTokenValue
) due to unnecessary precision downscaling.
Foundry
Within the GMXOracle#getLpTokenValue()
, consider removing the unnecessary division (/ 1e12
) like this:
0. And therefore, it would be normalized by dividing it by
1e12. However, the actual decimals precision of each GMX MarketToken-returned via the GMXOracle#
getMarketTokenInfo()would be in
1e18`.
This lead to a deflated-price of GM token (LpTokenValue
) due to unnecessary precision downscaling.
When retrieving a price of a GM token (LpTokenValue
), the GMXOracle#getLpTokenValue()
would be called.
Within the GMXOracle#getLpTokenValue()
, the GMXOracle#getMarketTokenInfo()
would be called to retrieve the _marketTokenPrice
. And then, it would be normalized by dividing by 1e12
. Finally the result would be returned like this:
https://github.com/Cyfrin/2023-10-SteadeFi/blob/main/contracts/oracles/GMXOracle.sol#L250-L257
https://github.com/Cyfrin/2023-10-SteadeFi/blob/main/contracts/oracles/GMXOracle.sol#L263-L264
Within the GMXOracle#getMarketTokenInfo()
, the result of the ISyntheticReader#getMarketTokenPrice()
(Reader#getMarketTokenPrice()
) would be returned like this:
Note
The original contract of the ISyntheticReader would be named the Reader contract:https://github.com/gmx-io/gmx-synthetics/blob/main/contracts/reader/Reader.sol#L187-L206
(Doc:https://gmx-docs.io/docs/api/contracts-v2#reading-values )
https://github.com/Cyfrin/2023-10-SteadeFi/blob/main/contracts/oracles/GMXOracle.sol#L178-L186
Within the Reader#getMarketTokenPrice()
(ISyntheticReader#getMarketTokenPrice()
), the result of the MarketUtils#getMarketTokenPrice()
would be returned like this:
https://github.com/gmx-io/gmx-synthetics/blob/main/contracts/reader/Reader.sol#L197-L205
Within the MarketUtils#getMarketTokenPrice()
, the marketTokenPrice
would be calculated based on the formula (Precision.mulDiv(Precision.WEI_PRECISION, poolValueInfo.poolValue, supply)
). And then, the result of the calculation would be returned like this:
https://github.com/gmx-io/gmx-synthetics/blob/main/contracts/market/MarketUtils.sol#L164-L165
Let's zooming into the calculation of the marketTokenPrice
above.
Here is the calculation process of the marketTokenPrice
above to observe only decimals precision transition in the calculation process of above:
https://github.com/gmx-io/gmx-synthetics/blob/main/contracts/market/MarketUtils.sol#L164
As we can see above, the decimals precision of the marketTokenPrice
would result in 1e18
.
Also, according to the "Market" part in the GMX's README, the price of MarketToken, which is retrieved via the MarketUtils#getMarketTokenPrice()
, would be in 1e18
decimals precision like this:
https://github.com/gmx-io/gmx-synthetics/tree/main#markets-1
At any point in time, the price of a MarketToken is
(worth of market pool) / MarketToken.totalSupply()
, the functionMarketUtils.getMarketTokenPrice
can be used to retrieve this value.
The worth of the market pool is the sum of
worth of all tokens deposited into the pool
total pending PnL of all open positions
total pending borrow fees of all open positions
In addition to that, according to the arbiscan (Etherscan for Arbitrum), the decimals precision of each GM token on Arbitrum-used in the SteadeFi protocol would be the 1e18
like this:
ETH-USDC GM token:0x70d95587d40a2caf56bd97485ab3eec10bee6336
https://arbiscan.io/token/0x70d95587d40a2caf56bd97485ab3eec10bee6336
WBTC-USDC GM token:0x47c031236e19d024b42f8AE6780E44A573170703
https://arbiscan.io/token/0x47c031236e19d024b42f8AE6780E44A573170703
ARB-USDC GM token: 0xC25cEf6061Cf5dE5eb761b50E4743c1F5D7E5407
https://arbiscan.io/token/0xC25cEf6061Cf5dE5eb761b50E4743c1F5D7E5407
LINK-USDC GM token: 0x7f1fa204bb700853D36994DA19F830b6Ad18455C
https://arbiscan.io/token/0x7f1fa204bb700853D36994DA19F830b6Ad18455C
SOL-USDC GM token: 0x09400D9DB990D5ed3f35D7be61DfAEB900Af03C9
https://arbiscan.io/token/0x09400D9DB990D5ed3f35D7be61DfAEB900Af03C9
UNI-USDC GM token: 0xc7Abb2C5f3BF3CEB389dF0Eecd6120D451170B50
https://arbiscan.io/token/0xc7Abb2C5f3BF3CEB389dF0Eecd6120D451170B50
However, within the GMXOracle#getLpTokenValue()
, the decimals precision of each GMX MarketToken-returned via the GMXOracle#getMarketTokenInfo()
would be assumed as a 1e30
.
This is problematic. Because, within the GMXOracle#getLpTokenValue()
, the decimals precision of each GMX MarketToken-returned would be 1e12
times smaller than the actual decimals precision of it if the decimals precision of each GMX MarketToken-returned via the GMXOracle#getMarketTokenInfo()
would be in 1e18
before normalized like this:
(NOTE:Below would track only decimals precision transition)
https://github.com/Cyfrin/2023-10-SteadeFi/blob/main/contracts/oracles/GMXOracle.sol#L263-L264
This lead to a deflated-price of GM token (LpTokenValue
) due to unnecessary precision downscaling.
This lead to a deflated-price of GM token (LpTokenValue
) due to unnecessary precision downscaling.
Foundry
Within the GMXOracle#getLpTokenValue()
, consider removing the unnecessary division (/ 1e12
) like this:
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.