QuantAMM

QuantAMM
49,600 OP
View results
Submission Details
Severity: low
Invalid

Double Price Scaling in Pool LP Token Value Calculation

Summary

The UpliftOnlyExample::getPoolLPTokenValue function's double price scaling leads to inflated LP token deposit values being stored in poolsFeeData, even though this doesn't affect fee calculations. This creates inconsistency in stored historical data and could cause issues if these values are used for other purposes.

Vulnerability Details

Taking a look at OracleWrapper contract, it suggests that oracle data is normalized to 18 decimals as seen in the comment below

/// @notice Get data from oracle, to be implemented by child contracts. Needs to return data with 18 decimals
function _getData() internal view virtual returns (int216 data, uint40 timestamp) {}

These 18 decimal places normalization is even evident in the ChainlinkOracle as seen below

function _getData() internal view override returns (int216, uint40) { // ...snip
// @audit data is made into 18 decimals here
@> data = data * int(10 ** normalizationFactor);

But on the contrary, in the function getPoolLPTokenValue in the UpliftOnlyExample contract the prices are being scaled again.

function getPoolLPTokenValue(int256[] memory _prices, address pool, MULDIRECTION _direction)
// ... snip ...
for (uint256 i; i < poolData.tokens.length;) {
@> int256 priceScaled18 = _prices[i] * 1e18; // @audit double scaling
if (_direction == MULDIRECTION.MULUP) {
@> poolValueInUSD += FixedPoint.mulUp(uint256(priceScaled18), poolData.balancesLiveScaled18[i]);
} else {
@> poolValueInUSD += FixedPoint.mulDown(uint256(priceScaled18), poolData.balancesLiveScaled18[i]);
}
// ...

Note hat the FixedPoint mulUp and mulDown are both processing FixedPoint numbers which are 18 decimals but the priceScaled18 will have 36 decimals.
As a result the value for depositValue when an LP adds Liquidity will be stored in the poolsFeeData mapping as a largely inflated value.

Impact

Historical deposit values stored in poolsFeeData are inflated by a factor of 1e18, creating inconsistency in stored data

Tools Used

Manual Review

Recommendations

Remove the redundant scaling to store correct historical values:

- int256 priceScaled18 = _prices[i] * 1e18;
+ int256 priceScaled18 = _prices[i];
Updates

Lead Judging Commences

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

invalid_getPoolLPTokkenValue_price_too_scaled

Order of magnitude: Price = 1e18 (already scaled and normalized by ChainlinkOracle). PriceScaled = 1e36 PoolValueInUSD = 1e36 (mulDown) PoolTotalSupply = 1e18 PoolValueInUSD / PoolTotalSupply = 1e18. Everything seems fine here.

Support

FAQs

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

Give us feedback!