Tick
Manages the discrete price points and liquidity distribution across the price curve.
Core Data Structures
TickManager
The main controller that organizes all ticks for a pool:
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:
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 tickPositive 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 tickAlways 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
Creates a new tick manager with:
Specified tick spacing
Empty SkipList with randomized structure
16 levels maximum for optimal performance
Liquidity Management
Adding Liquidity
Process:
Tick Creation: Creates ticks if they don't exist
Lower Tick Update: Increases
liquidity_net(positive delta)Upper Tick Update: Decreases
liquidity_net(negative delta)Growth Initialization: Sets appropriate "outside" growth values
Removing Liquidity
Process:
Validation: Ensures ticks exist and have sufficient liquidity
Liquidity Reduction: Decreases gross liquidity at both ticks
Net Adjustment: Adjusts net liquidity appropriately
Cleanup: Removes ticks if no liquidity remains
Swap Operations
Tick Crossing
When a swap crosses a tick:
Liquidity Update: Applies
liquidity_netto active liquidityDirection Handling: Negates delta for reverse direction (a2b)
Growth Flipping: Updates "outside" growth values using wrapping subtraction
Safety Checks: Validates liquidity doesn't overflow or underflow
Swap Navigation
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
Returns current tick data and next tick ID for efficient swap iteration.
Range Calculations
Fee Growth in Range
Calculates accumulated fees within a position's range using the formula:
Where:
fee_below: Fee growth below the lower tickfee_above: Fee growth above the upper tick
Points Growth in Range
Similar calculation for points (used in reward calculations).
Rewards Growth in Range
Calculates reward growth for multiple reward tokens within a range.
Advanced Features
Tick Discovery and Querying
Pagination Support
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
borrow_tick: Direct access (aborts if not found)try_borrow_tick: Safe access returning Option
Data Access Functions
Tick Properties
Manager Properties
Reward Helpers
Safely accesses reward growth for a specific reward token index.
Internal Implementation
Tick Scoring System
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
Creates new tick with:
Calculated sqrt_price from tick_math
Zero liquidity values
Zero growth tracking values
Empty rewards vector
Liquidity Update Logic
Core logic for updating tick state:
Gross Liquidity: Add/subtract amount based on
is_increaseNet Liquidity: Adjust based on
is_upperflagGrowth Initialization: Set "outside" values for new ticks based on current position
Overflow Protection: Check for arithmetic overflows
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:
Liquidity Net Calculation
When crossing tick from left to right:
For reverse direction (right to left):
Growth Outside Pattern
Fee growth inside a range [tickLower, tickUpper]:
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
Tick Spacing: Choose spacing based on gas costs vs. precision needs
Batch Operations: Group multiple liquidity operations when possible
Error Handling: Always check for tick existence before operations
Memory Management: Clean up empty ticks to reduce storage costs
Precision: Use appropriate decimal precision for price calculations
Security Considerations
Overflow Protection: All arithmetic operations include overflow checks
Tick Bounds: Validate tick indices are within valid range
Liquidity Validation: Ensure sufficient liquidity before decreasing
Growth Calculation: Use wrapping arithmetic to handle edge cases
Access Control: Restrict dangerous operations to friend modules only
Last updated