Skip to content

Latest commit

 

History

History
66 lines (38 loc) · 2.4 KB

File metadata and controls

66 lines (38 loc) · 2.4 KB

Fast Khaki Raccoon

High

getConversionFactor will overflow and DOS the voting module

Summary

getConversionFactor will overflow due to faulty math causing a multiplication to exceed uin256.max most of the time.

Root Cause

By following the math in the comments, it would lead us to the following calculations

_pricePeasNumX96 -> 3.2e46 as we get the price from 0xae750560b09ad1f5246f3b279b3767afd1d79160, which is PEAS : DAI v3 pool, and with a factor of 1e18 (1 : 1) it would result in a value with 46 decimals. Later this value would be multiplied by k, which is reserve0 * reserve1, a value which would be in the magnitude of 1e36 - 1e46 as w tokens with 18 decimals make at lest 1e36.

When these 2 values are multiplied in the final equation we would get a new value with at least 82 decimals, which is way higher than the uint256.max - 1e77.

https://github.com/sherlock-audit/2025-01-peapods-finance/blob/main/contracts/contracts/voting/ConversionFactorSPTKN.sol#L40-L48

        uint160 _sqrtPriceX96 = TWAP_UTILS.sqrtPriceX96FromPoolAndInterval(PEAS_STABLE_CL_POOL);
        uint256 _priceX96 = TWAP_UTILS.priceX96FromSqrtPriceX96(_sqrtPriceX96);

        uint256 _pricePeasNumX96 = _token1 == PEAS 
            ? _priceX96 

            // 2^96 * 2^96 / 192500005625 = 3.2e46 (PEAS : DAI) -> 0xae750560b09ad1f5246f3b279b3767afd1d79160
            : FixedPoint96.Q96 ** 2 / _priceX96;

        // 3.2e46 * 1e18 / 1e18 = 3.2e46
        // _pricePeasNumX96 * _pFactor / 1e18
        uint256 _pricePPeasNumX96 = (_pricePeasNumX96 * _pFactor) / _pDenomenator;

        (uint112 _reserve0, uint112 _reserve1) = V2_RESERVES.getReserves(_lpTkn);

        uint256 _k = uint256(_reserve0) * _reserve1;

        //@finding H this would be too big for low value tokens
        // 3.2e46 * 1e36 -> 6.4e77
        uint256 _avgTotalPeasInLpX96 = _sqrt(_pricePPeasNumX96 * _k) * 2 ** (96 / 2);

Internal Pre-conditions

No response

External Pre-conditions

No response

Attack Path

No attack path is needed, the function would just not work.

Impact

getConversionFactor would revert almost every time, DOS the whole voting module, as it's used in _updateUserState.

PoC

No response

Mitigation

Consider using a more fractured method for calculating the price, i.e. spread the divisions along the way.