L-17. GMXOracle.sol#L280: function `getLpTokenAmount` icorrectly assumes that the returned price is in 18 decimal places. But it is 30 decimal places.

Submitted by ak1.

Relevant GitHub Links

Summary

GMXOracle oracle has a function getLpTokenAmount which is in scope. This is Used in keeper script to calculate how much LP tokens for given USD value.
This function returns the lpTokenAmount with 30 decimal places instead of 18 as the function assumes.

Vulnerability Details

Lets look at the function getLpTokenAmount
plain text
/** * @notice Get token A and token B's LP token amount required for a given value * @param givenValue Given value needed, expressed in 1e30 -------------------------->> refer this * @param marketToken LP token address * @param indexToken Index token address * @param longToken Long token address * @param shortToken Short token address * @param isDeposit Boolean for deposit or withdrawal * @param maximize Boolean for minimum or maximum price * @return lpTokenAmount Amount of LP tokens; expressed in 1e18 -------------->>> refer this */ function getLpTokenAmount( uint256 givenValue, address marketToken, address indexToken, address longToken, address shortToken, bool isDeposit, bool maximize ) public view returns (uint256) { uint256 _lpTokenValue = getLpTokenValue( marketToken, indexToken, longToken, shortToken, isDeposit, maximize ); return givenValue * SAFE_MULTIPLIER / _lpTokenValue; }
SAFE_MULTIPLIER is in 18 decimal places.
The values returned from the function _lpTokenValue is in 18 decimal places. Refer the line
So the final returned value from the function getLpTokenAmount is (1e30 * 1e18) / 1e18 = 1e30

Impact

Overestimating the lpToken amount for the given USD value.

Tools Used

Manual review.

Recommendations

Update the function getLpTokenAmount as shown below.
plain text
function getLpTokenAmount( uint256 givenValue, address marketToken, address indexToken, address longToken, address shortToken, bool isDeposit, bool maximize ) public view returns (uint256) { uint256 _lpTokenValue = getLpTokenValue( marketToken, indexToken, longToken, shortToken, isDeposit, maximize ); return givenValue * SAFE_MULTIPLIER / _lpTokenValue; ------>> remove return (givenValue * SAFE_MULTIPLIER) / (_lpTokenValue * 1e12); ---->> add }