# Tick

### Core Data Structures

**TickManager**

The main controller that organizes all ticks for a pool:

```rust
struct TickManager {
    tick_spacing: u32,           // Spacing between valid ticks
    ticks: SkipList<Tick>       // Ordered collection of ticks
}
```

**Tick**

Individual tick containing all relevant price point data:

```rust
struct Tick {
    index: I32,                          // Tick index (price level)
    sqrt_price: u128,                    // Square root price at this tick
    liquidity_net: I128,                 // Net liquidity change when crossing
    liquidity_gross: u128,               // Total liquidity at this tick
    fee_growth_outside_a: u128,          // Fee growth outside for token A
    fee_growth_outside_b: u128,          // Fee growth outside for token B
    points_growth_outside: u128,         // Points growth outside
    rewards_growth_outside: vector<u128> // Reward growth outside (per token)
}
```

#### Key Properties

**Liquidity Net vs Gross**

* **`liquidity_net`**: Signed change in active liquidity when crossing this tick
  * Positive when tick is the lower bound of positions
  * Negative when tick is the upper bound of positions
* **`liquidity_gross`**: Total amount of liquidity referencing this tick
  * Always positive
  * Used to determine if tick can be removed

**Growth Outside Pattern**

The "growth outside" pattern enables efficient fee and reward calculations:

* Tracks accumulated growth outside the current active range
* Allows O(1) calculation of growth within any range
* Automatically updated when ticks are crossed during swaps

### Core Functionality

#### Initialization

```rust
public(friend) fun new(tick_spacing: u32, seed: u64, ctx: &mut TxContext) : TickManager
```

Creates a new tick manager with:

* Specified tick spacing
* Empty SkipList with randomized structure
* 16 levels maximum for optimal performance

#### Liquidity Management

**Adding Liquidity**

```rust
public(friend) fun increase_liquidity(
    tick_manager: &mut TickManager,
    current_tick: I32,
    tick_lower: I32,
    tick_upper: I32,
    amount: u128,
    fee_growth_global_a: u128,
    fee_growth_global_b: u128,
    points_growth_global: u128,
    rewards_growth_global: vector<u128>
)
```

Process:

1. **Tick Creation**: Creates ticks if they don't exist
2. **Lower Tick Update**: Increases `liquidity_net` (positive delta)
3. **Upper Tick Update**: Decreases `liquidity_net` (negative delta)
4. **Growth Initialization**: Sets appropriate "outside" growth values

**Removing Liquidity**

```rust
public(friend) fun decrease_liquidity(
    tick_manager: &mut TickManager,
    current_tick: I32,
    tick_lower: I32,
    tick_upper: I32,
    amount: u128,
    fee_growth_global_a: u128,
    fee_growth_global_b: u128,
    points_growth_global: u128,
    rewards_growth_global: vector<u128>
)
```

Process:

1. **Validation**: Ensures ticks exist and have sufficient liquidity
2. **Liquidity Reduction**: Decreases gross liquidity at both ticks
3. **Net Adjustment**: Adjusts net liquidity appropriately
4. **Cleanup**: Removes ticks if no liquidity remains

#### Swap Operations

**Tick Crossing**

```rust
public(friend) fun cross_by_swap(
    tick_manager: &mut TickManager,
    tick_idx: I32,
    a2b: bool,
    liquidity: u128,
    fee_growth_global_a: u128,
    fee_growth_global_b: u128,
    points_growth_global: u128,
    rewards_growth_global: vector<u128>
) : u128
```

When a swap crosses a tick:

1. **Liquidity Update**: Applies `liquidity_net` to active liquidity
2. **Direction Handling**: Negates delta for reverse direction (a2b)
3. **Growth Flipping**: Updates "outside" growth values using wrapping subtraction
4. **Safety Checks**: Validates liquidity doesn't overflow or underflow

**Swap Navigation**

```rust
public fun first_score_for_swap(
    tick_manager: &TickManager,
    tick_idx: I32,
    a2b: bool
) : OptionU64
```

Finds the next tick to process during swaps:

* **a2b (true)**: Finds previous tick (lower price)
* **b2a (false)**: Finds next tick (higher price)
* Handles edge cases at minimum and maximum ticks

```rust
public fun borrow_tick_for_swap(
    tick_manager: &TickManager,
    node_id: u64,
    a2b: bool
) : (&Tick, OptionU64)
```

Returns current tick data and next tick ID for efficient swap iteration.

#### Range Calculations

**Fee Growth in Range**

```rust
public fun get_fee_in_range(
    current_tick: I32,
    fee_growth_global_a: u128,
    fee_growth_global_b: u128,
    tick_lower_opt: Option<Tick>,
    tick_upper_opt: Option<Tick>
) : (u128, u128)
```

Calculates accumulated fees within a position's range using the formula:

```rust
fee_inside = fee_global - fee_below - fee_above
```

Where:

* `fee_below`: Fee growth below the lower tick
* `fee_above`: Fee growth above the upper tick

**Points Growth in Range**

```rust
public fun get_points_in_range(
    current_tick: I32,
    points_growth_global: u128,
    tick_lower_opt: Option<Tick>,
    tick_upper_opt: Option<Tick>
) : u128
```

Similar calculation for points (used in reward calculations).

**Rewards Growth in Range**

```rust
public fun get_rewards_in_range(
    current_tick: I32,
    rewards_growth_global: vector<u128>,
    tick_lower_opt: Option<Tick>,
    tick_upper_opt: Option<Tick>
) : vector<u128>
```

Calculates reward growth for multiple reward tokens within a range.

### Advanced Features

#### Tick Discovery and Querying

**Pagination Support**

```rust
public fun fetch_ticks(
    tick_manager: &TickManager,
    start: vector<u32>,
    limit: u64
) : vector<Tick>
```

Efficiently retrieves ticks with pagination:

* **start**: Optional starting tick index
* **limit**: Maximum number of ticks to return
* Returns ordered list for UI display

**Tick Lookup**

```rust
public fun borrow_tick(tick_manager: &TickManager, tick_idx: I32) : &Tick
public fun try_borrow_tick(tick_manager: &TickManager, tick_idx: I32) : Option<Tick>
```

* `borrow_tick`: Direct access (aborts if not found)
* `try_borrow_tick`: Safe access returning Option

#### Data Access Functions

**Tick Properties**

```rust
public fun index(tick: &Tick) : I32
public fun sqrt_price(tick: &Tick) : u128
public fun liquidity_gross(tick: &Tick) : u128
public fun liquidity_net(tick: &Tick) : I128
public fun fee_growth_outside(tick: &Tick) : (u128, u128)
public fun points_growth_outside(tick: &Tick) : u128
public fun rewards_growth_outside(tick: &Tick) : &vector<u128>
```

**Manager Properties**

```rust
public fun tick_spacing(tick_manager: &TickManager) : u32
public fun tick_count(tick_manager: &TickManager) : u64
```

**Reward Helpers**

```rust
public fun get_reward_growth_outside(tick: &Tick, index: u64) : u128
```

Safely accesses reward growth for a specific reward token index.

### Internal Implementation

#### Tick Scoring System

```rust
fun tick_score(tick_idx: I32) : u64
```

Converts tick indices to SkipList scores:

* Handles negative tick indices
* Ensures proper ordering in SkipList
* Maps to range \[0, tick\_bound \* 2]

#### Default Tick Creation

```rust
fun default(tick_idx: I32) : Tick
```

Creates new tick with:

* Calculated sqrt\_price from tick\_math
* Zero liquidity values
* Zero growth tracking values
* Empty rewards vector

#### Liquidity Update Logic

```rust
fun update_by_liquidity(
    tick: &mut Tick,
    current_tick: I32,
    amount: u128,
    is_new: bool,
    is_increase: bool,
    is_upper: bool,
    fee_growth_global_a: u128,
    fee_growth_global_b: u128,
    points_growth_global: u128,
    rewards_growth_global: vector<u128>
) : u128
```

Core logic for updating tick state:

1. **Gross Liquidity**: Add/subtract amount based on `is_increase`
2. **Net Liquidity**: Adjust based on `is_upper` flag
3. **Growth Initialization**: Set "outside" values for new ticks based on current position
4. **Overflow Protection**: Check for arithmetic overflows
5. **Return Remaining**: Return remaining gross liquidity

**Growth Initialization Logic**

For new ticks:

* **Below current tick**: Initialize outside growth to 0 (all growth is "above")
* **Above current tick**: Initialize outside growth to global values (all growth is "below")

This ensures proper fee/reward calculations when the tick becomes active.

### Error Codes

* **Error 0**: Arithmetic overflow in liquidity calculations
* **Error 1**: Insufficient liquidity for operation
* **Error 2**: Invalid tick score (outside valid range)
* **Error 3**: Tick not found when expected to exist

### Mathematical Concepts

#### Price Calculation

Each tick represents a specific price:

```rust
price = 1.0001^tick_index
sqrt_price = sqrt(price) = 1.0001^(tick_index/2)
```

#### Liquidity Net Calculation

When crossing tick from left to right:

```rust
new_liquidity = current_liquidity + tick.liquidity_net
```

For reverse direction (right to left):

```
new_liquidity = current_liquidity - tick.liquidity_net
```

#### Growth Outside Pattern

Fee growth inside a range \[tickLower, tickUpper]:

```rust
fee_inside = fee_global - fee_below - fee_above

where:
fee_below = (current_tick >= tickLower) ? tickLower.fee_outside : (fee_global - tickLower.fee_outside)
fee_above = (current_tick < tickUpper) ? tickUpper.fee_outside : (fee_global - tickUpper.fee_outside)
```

### Performance Characteristics

#### Time Complexity

* **Tick lookup**: O(log n)
* **Tick insertion/deletion**: O(log n)
* **Range queries**: O(log n + k) where k is result size
* **Crossing tick**: O(1)
* **Fee/reward calculation**: O(1)

#### Space Complexity

* **Memory per tick**: \~200 bytes + rewards vector
* **SkipList overhead**: \~16 pointers per tick
* **Total for n ticks**: O(n)

#### Gas Efficiency

* Efficient sparse storage (only initialized ticks consume gas)
* O(1) tick crossing operations
* Batch operations for multiple tick updates
* Optimized wrapping arithmetic for growth calculations

#### Best Practices

1. **Tick Spacing**: Choose spacing based on gas costs vs. precision needs
2. **Batch Operations**: Group multiple liquidity operations when possible
3. **Error Handling**: Always check for tick existence before operations
4. **Memory Management**: Clean up empty ticks to reduce storage costs
5. **Precision**: Use appropriate decimal precision for price calculations

### Security Considerations

1. **Overflow Protection**: All arithmetic operations include overflow checks
2. **Tick Bounds**: Validate tick indices are within valid range
3. **Liquidity Validation**: Ensure sufficient liquidity before decreasing
4. **Growth Calculation**: Use wrapping arithmetic to handle edge cases
5. **Access Control**: Restrict dangerous operations to friend modules only


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.ferra.ag/integration/clmm/smart-contract/tick.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
