# Uniswap V3: Increasing/decreasing a tick by a percentage

This is my approach to increase a tick by a certain percentage:

``````// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.4;

import {TickMath} from "./TickMath.sol";
import {FullMath} from "./FullMath.sol";
import {PRBMathUD60x18} from "@prb/math/contracts/PRBMathUD60x18.sol";

contract TickPercentage {
using TickMath for int24;

function increaseTickByPercentage(int24 _tick, uint24 _tickSpacing, uint16 _percentage)
external
pure
returns (int24)
{
// Convert Tick to sqrtPriceX96
uint160 currentPriceX96 = _tick.getSqrtRatioAtTick();

// Convert SqrtPriceX96 to Wei price
uint256 currentPriceX96ToUint = sqrtPriceX96ToUint(currentPriceX96, 18);

// New Wei price increased by percentage amount
uint256 newWeiPrice = currentPriceX96ToUint + (currentPriceX96ToUint * _percentage) / 10000;

// Convert Wei price to SqrtPriceX96
uint160 newPriceX96 = uint160(PRBMathUD60x18.sqrt(newWeiPrice) * 2 ** 96) / 1e18;

// Convert SqrtPriceX96 to the nearest Tick and return
return TickMath.nearestUsableTick(TickMath.getTickAtSqrtRatio(newPriceX96), _tickSpacing);
}

function sqrtPriceX96ToUint(uint160 sqrtPriceX96, uint8 decimalsToken0)
public
pure
returns (uint256)
{
uint256 numerator1 = uint256(sqrtPriceX96) * uint256(sqrtPriceX96);
uint256 numerator2 = 10**decimalsToken0;
return FullMath.mulDiv(numerator1, numerator2, 1 << 192);
}
``````

For precision, I'm converting the Tick to its sqrtPriceX96 value, then converting that to a Wei value. Then I perform the percentage operation on the Wei value, and convert it back to sqrtPriceX96 then Tick.

It works, but it would be much more efficient to perform the percent operation directly on the Tick value, without having to do the conversions, I just don't know how to do it.

Is there a more efficient way to do this?

The good thing about the tick math is that a price increase (or decrease) by some ratio is equal to adding (or subtracting) a fixed number of ticks. For example, price increase by 5% is increase by `delta_t` ticks:

``````delta_t = log(1.05, 1.0001) = 487.9260363698946
``````

which is approximately equal to 488 ticks.

The steps to compute a price increase from tick `t` by `x`%:

1. Transform the percentage `x` to a ratio `r`;
2. Transform the ratio `r` to a number of ticks `delta_t`;
3. Add the number of ticks: `t_new = t + t_delta`.

The bad thing is that in order to translate between percentages and ticks you'd still need to compute logarithm at some point, which could be complex and expensive in Solidity. In the general case, you can use Uniswap's `getTickAtSqrtRatio` function for this. But if you have some fixed range of percentages, then a better option might be an `immutable` lookup table, which is precomputed using Python or another language, and maps between the percentages and the number of ticks:

``````...
delta_t[4] = 392;
delta_t[5] = 488;
delta_t[6] = 582;
...
``````

Edit: to stress the point about gas optimizations more clearly, the precomputed table should be `immutable` (or `constant`, when possible). Using a table in the storage actually gives no cost savings over calling the simply calling the `getTickAtSqrtRatio` method. It's amazing, but all this complex math really does cost less gas than a single SLOAD instruction.