# Tick spacing misalignment in position bounds

Tick rounding or spacing math where lower and upper bounds cross or collapse to equal

_Area: DeFi accounting and math bugs. Seen in 3 disclosed reports; latest 2025-02-21. Updated 2026-10-25._

## How it works
Position ranges are assumed to be ordered and aligned to tick spacing. Downstream math (token deltas, fee growth, active-range checks) silently assumes `lower < upper` and that both ticks sit on valid spacing boundaries. When an entry point skips the ordering check, or spacing math rounds a negative tick the wrong way, the bounds can become equal or inverted. The delta formulas then collapse to zero or produce wrong fee attribution, so a position that should cost tokens costs nothing, or a range that should be out-of-range reads as active.

## Where it shows up
- A mint/open-position entry point that never asserts `lower < upper` while sibling functions do.
- Tick math using `%` on signed values without normalizing negatives (Solidity truncates toward zero).
- One function correcting negative modulo and a sibling copying the math without the correction.
- Comparisons like `modulo < tickSpacing/2` that collapse to one branch when `tickSpacing == 1`.
- Range width derived as a multiple of spacing where a side flag can make lower equal upper.

## How to review
Check the invariant `lower < upper` and `lower % spacing == 0 && upper % spacing == 0` at every entry point that accepts or derives ticks, not just where it is convenient. For each derived tick, trace the negative-tick path and the `tickSpacing == 1` boundary explicitly. Confirm the same normalization is applied in every function that computes ticks. Verify that when bounds are equal or inverted, the code reverts rather than falling through to zero-delta or wrong-fee branches.

## Variants seen
- Missing `lower < upper` check lets equal ticks mint arbitrary liquidity for zero tokens and farm fees [E1](https://bugbountylibrary.com/r/c4%3A2024-08-superposition%3AH-03.md).
- Negative-tick modulo not corrected in secondary position ticks makes an out-of-range position active and can divide by zero [E2](https://bugbountylibrary.com/r/sherlock%3A2025-02-yieldoor%3AM-6.md).
- `isLowerSided` inequality always true at spacing 1, producing asymmetric ranges and lost fees [E3](https://bugbountylibrary.com/r/sherlock%3A2025-02-yieldoor%3AM-3.md).

## Impact and severity
Consequences ranged from free liquidity and inflated fee farming [E1](https://bugbountylibrary.com/r/c4%3A2024-08-superposition%3AH-03.md), to broken rebalancing and division-by-zero reverts [E2](https://bugbountylibrary.com/r/sherlock%3A2025-02-yieldoor%3AM-6.md), to silent fee loss from asymmetric ranges [E3](https://bugbountylibrary.com/r/sherlock%3A2025-02-yieldoor%3AM-3.md). Severity rises when the bad range is reachable by any caller and when fee accounting is directly monetizable; it is worse where the same math is reused across multiple position-setting functions.

## Evidence
- E1: https://bugbountylibrary.com/r/c4%3A2024-08-superposition%3AH-03.md
- E2: https://bugbountylibrary.com/r/sherlock%3A2025-02-yieldoor%3AM-6.md
- E3: https://bugbountylibrary.com/r/sherlock%3A2025-02-yieldoor%3AM-3.md
