How to divide different uint/int types after Solidity 0.8.0

I was trying out the Uniswap's Oracle library to interact with the price feed that their token pools expose. I noticed that if I try to use a solidity compiler greater than 0.8.0, I get the compiler error:

TypeError: Operator / not compatible with types int56 and uint32
  --> contracts/OracleTest.sol:31:42:
   |
31 |         timeWeightedAverageTick = int24( tickCumulativesDelta / period );
   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The function I'm trying to compile is straight from the Uniswap npm package:

    function consult(address pool, uint32 period) internal view returns (int24 timeWeightedAverageTick) {
        require(period != 0, 'BP');

        uint32[] memory secondAgos = new uint32[](2);
        secondAgos[0] = period;
        secondAgos[1] = 0;

        (int56[] memory tickCumulatives, ) = IUniswapV3Pool(pool).observe(secondAgos);
        int56 tickCumulativesDelta = tickCumulatives[1] - tickCumulatives[0];

        timeWeightedAverageTick = int24( tickCumulativesDelta / period );

        // Always round to negative infinity
        if (tickCumulativesDelta < 0 && (tickCumulativesDelta % period != 0)) timeWeightedAverageTick--;
    }

I know that solidity 0.8 changed some things regarding implicit type conversion and overflow protection, so probably that is what is causing the compile-time errors. I tried some throwing an unchecked block in but still get implicit type conversion errors.

Has anyone come across this problem already and found a good work around besides just rolling back to 0.7?

The solution is :
timeWeightedAverageTick = int24( tickCumulativesDelta / int56( int32(period) ) );

basically you need to first convert the unsigned to signed integer with the same kind in either same width or same type. e.g.: uint16(uint8(int8)) or uint16(int16(int8)) .

The details can be found in the solidity 0.8.0 breaking change doc. https://docs.soliditylang.org/en/v0.8.10/080-breaking-changes.html

1 Like