Uniswap V3 – Understanding Tick Range in Negative Ticks with Solidity 0.8.x

soliditysolidity-0.8.xuniswapuniswapv3

I am looking for a formula to calculate the tick range for a negative tick.

Ex1: 
  tick: -15
  tickSpacing: 10
  range: [-20, -10)

Ex2:
  tick: -20
  tickSpacing: 10
  range: [-20, -10)

I was trying this formula

tickLower = tick / tickSpacing * tickSpacing
tickUpper = tickLower + tickSpacing

But this not working in the case of -15, it gives [-10, 0), which is not including -20

tickUpper = tick / tickSpacing * tickSpacing
tickLower = tickLower - tickSpacing

But this is not giving the right answer for -20, it give [-30, -20), which is not including -20

Someone knows a formula which works in both cases?

Best Answer

In Solidity, you need to add a conditional statement to implement this correctly:

tickLower = tick / tickSpacing * tickSpacing;
if (tick < 0 && tick % tickSpacing != 0) tickLower -= tickSpacing;
tickUpper = tickLower + tickSpacing;

The Uniswap source code itself uses this pattern.

Explanation: when dividing a negative number, some programming languages round the result up, some round it down. This is related to whether the % operator computes the modulo or the remainder. In all sensible languages, the following invariant holds x == x / k * k + x % k.

  • In languages like Python where % computes the modulo of the arguments, integer division must always round down for the invariant to hold.
  • In languages like C and Solidity the remainder of % always has the same sign as the dividend x, so the division / must round up for the invariant to hold.

As a result, this code correctly works in Python, but not in other languages:

tickLower = tick // tickSpacing * tickSpacing
tickUpper = tickLower + tickSpacing
Related Topic