Prehistoric Cobalt Aphid
High
Strategy main ticks are not symmetric when the tick spacing is one due to incorrect isLowerSided inequality
Strategy main position ticks are set according to:
function _setMainTicks(int24 tick) internal {
int24 halfWidth = int24(positionWidth / 2);
int24 modulo = tick % tickSpacing;
if (modulo < 0) modulo += tickSpacing; // if tick is negative, modulo is also negative
bool isLowerSided = modulo < (tickSpacing / 2);
int24 tickBorder = tick - modulo;
if (!isLowerSided) tickBorder += tickSpacing;
mainPosition.tickLower = tickBorder - halfWidth;
mainPosition.tickUpper = tickBorder + halfWidth;
emit NewMainTicks(tickBorder - halfWidth, tickBorder + halfWidth);
}
As can be seen, when the tick spacing is 1, the tick will be deemed lower sided, which adds a tick spacing (1) to the tick border. So, if the current tick is -1769, the ticks will be -1770 to -1766, which is not symmetric and will miss out on fees.
In Strategy:236
, is lower sided check is incorrect.
None.
None.
- Protocol rebalances but main ticks are not symmetric and will miss out on fees when the price moves to the side that has less liquidity allocated.
Loss of fees.
// in setup
IUniswapV3Pool pool = IUniswapV3Pool(0x20E068D76f9E90b90604500B84c7e19dCB923e7e);
IERC20 wbtc = IERC20(0x4200000000000000000000000000000000000006); // token0
IERC20 usdc = IERC20(0xc1CBa3fCea344f92D9239c08C0568f6F2F0ee452); // token1
address uniRouter = address(0x2626664c2603336E57B271c5C0b26F421741e481);
vm.createSelectFork(vm.envString("RPC_URL_BASE"), 26874136);
function test_POC_WrongTicks_DueToIsLowerSide() public {
skip(10 minutes);
vm.startPrank(rebalancer);
IStrategy(strategy).rebalance();
IStrategy.Position memory mainPos = IStrategy(strategy).getMainPosition();
(, int24 tick,,,,,) = pool.slot0();
//@audit position is not symmetric, harming long term fees
assertEq(tick, -1769);
assertEq(mainPos.tickLower, -1770);
assertEq(mainPos.tickUpper, -1766);
}
bool isLowerSided = modulo <= (tickSpacing / 2);