nautilus_model/defi/tick_map/
liquidity_math.rs1use crate::defi::tick_map::tick::PoolTick;
17
18#[must_use]
30pub fn liquidity_math_add(x: u128, y: i128) -> u128 {
31 if y < 0 {
32 let delta = y.unsigned_abs();
33 let z = x.wrapping_sub(delta);
34 assert!(
35 z < x,
36 "Liquidity subtraction underflow: x={x}, y={y}, delta={delta}, result={z}"
37 );
38 z
39 } else {
40 let delta = y as u128;
41 let z = x.wrapping_add(delta);
42 assert!(
43 z >= x,
44 "Liquidity addition overflow: x={x}, y={y}, delta={delta}, result={z}"
45 );
46 z
47 }
48}
49
50#[must_use]
56pub fn tick_spacing_to_max_liquidity_per_tick(tick_spacing: i32) -> u128 {
57 assert!(tick_spacing != 0, "Tick spacing must be non-zero");
58
59 let min_tick = (PoolTick::MIN_TICK / tick_spacing) * tick_spacing;
61 let max_tick = (PoolTick::MAX_TICK / tick_spacing) * tick_spacing;
62
63 let num_ticks = ((i64::from(max_tick) - i64::from(min_tick)) / i64::from(tick_spacing)) + 1;
65
66 u128::MAX / num_ticks as u128
67}
68
69#[cfg(test)]
70mod tests {
71 use rstest::rstest;
72
73 use super::*;
74
75 #[rstest]
76 fn test_add() {
77 assert_eq!(liquidity_math_add(1, 0), 1);
78 assert_eq!(liquidity_math_add(1, 1), 2);
79 }
80
81 #[rstest]
82 fn test_subtract_one() {
83 assert_eq!(liquidity_math_add(1, -1), 0);
84 assert_eq!(liquidity_math_add(3, -2), 1);
85 }
86
87 #[rstest]
88 #[should_panic(expected = "Liquidity addition overflow")]
89 fn test_addition_overflow() {
90 let x = u128::MAX - 14; let _ = liquidity_math_add(x, 15);
92 }
93
94 #[rstest]
95 #[should_panic(expected = "Liquidity subtraction underflow")]
96 fn test_subtraction_underflow_zero() {
97 let _ = liquidity_math_add(0, -1);
98 }
99
100 #[rstest]
101 #[should_panic(expected = "Liquidity subtraction underflow")]
102 fn test_subtraction_underflow() {
103 let _ = liquidity_math_add(3, -4);
104 }
105
106 #[rstest]
107 fn test_tick_spacing_to_max_liquidity() {
108 assert_eq!(
110 tick_spacing_to_max_liquidity_per_tick(1),
111 191_757_530_477_355_301_479_181_766_273_477
112 );
113 assert_eq!(
115 tick_spacing_to_max_liquidity_per_tick(10),
116 1_917_569_901_783_203_986_719_870_431_555_990
117 );
118 assert_eq!(
120 tick_spacing_to_max_liquidity_per_tick(60),
121 11_505_743_598_341_114_571_880_798_222_544_994
122 );
123 assert_eq!(
125 tick_spacing_to_max_liquidity_per_tick(200),
126 38_350_317_471_085_141_830_651_933_667_504_588
127 );
128 }
129}