@paraswap/dex-lib 4.8.36 → 4.8.37-native-dex-math.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/build/dex/aave-gsm/config.js +2 -2
  2. package/build/dex/idex.d.ts +1 -1
  3. package/build/dex/pancakeswap-v3/pancakeswap-v3-pool.d.ts +2 -0
  4. package/build/dex/pancakeswap-v3/pancakeswap-v3-pool.js +5 -0
  5. package/build/dex/pancakeswap-v3/pancakeswap-v3-pool.js.map +1 -1
  6. package/build/dex/pancakeswap-v3/pancakeswap-v3.d.ts +6 -3
  7. package/build/dex/pancakeswap-v3/pancakeswap-v3.js +85 -9
  8. package/build/dex/pancakeswap-v3/pancakeswap-v3.js.map +1 -1
  9. package/build/dex/solidly-v3/solidly-v3-pool.d.ts +3 -0
  10. package/build/dex/solidly-v3/solidly-v3-pool.js +8 -0
  11. package/build/dex/solidly-v3/solidly-v3-pool.js.map +1 -1
  12. package/build/dex/solidly-v3/solidly-v3.d.ts +5 -2
  13. package/build/dex/solidly-v3/solidly-v3.js +84 -8
  14. package/build/dex/solidly-v3/solidly-v3.js.map +1 -1
  15. package/build/dex/uniswap-v3/scripts/measure-calc-time.js +222 -110
  16. package/build/dex/uniswap-v3/scripts/measure-calc-time.js.map +1 -1
  17. package/build/dex/uniswap-v3/types.d.ts +1 -0
  18. package/build/dex/uniswap-v3/types.js.map +1 -1
  19. package/build/dex/uniswap-v3/uniswap-v3-pool.d.ts +2 -0
  20. package/build/dex/uniswap-v3/uniswap-v3-pool.js +5 -0
  21. package/build/dex/uniswap-v3/uniswap-v3-pool.js.map +1 -1
  22. package/build/dex/uniswap-v3/uniswap-v3.d.ts +11 -3
  23. package/build/dex/uniswap-v3/uniswap-v3.js +86 -9
  24. package/build/dex/uniswap-v3/uniswap-v3.js.map +1 -1
  25. package/build/dex/uniswap-v4/types.d.ts +1 -0
  26. package/build/dex/uniswap-v4/uniswap-v4-pool-manager.d.ts +2 -0
  27. package/build/dex/uniswap-v4/uniswap-v4-pool-manager.js +3 -0
  28. package/build/dex/uniswap-v4/uniswap-v4-pool-manager.js.map +1 -1
  29. package/build/dex/uniswap-v4/uniswap-v4-pool.d.ts +3 -0
  30. package/build/dex/uniswap-v4/uniswap-v4-pool.js +18 -0
  31. package/build/dex/uniswap-v4/uniswap-v4-pool.js.map +1 -1
  32. package/build/dex/uniswap-v4/uniswap-v4.d.ts +3 -1
  33. package/build/dex/uniswap-v4/uniswap-v4.js +74 -14
  34. package/build/dex/uniswap-v4/uniswap-v4.js.map +1 -1
  35. package/build/pricing-helper.d.ts +1 -1
  36. package/build/pricing-helper.js +2 -2
  37. package/build/pricing-helper.js.map +1 -1
  38. package/native/Cargo.lock +331 -0
  39. package/native/Cargo.toml +22 -0
  40. package/native/build.rs +5 -0
  41. package/native/package-lock.json +32 -0
  42. package/native/package.json +20 -0
  43. package/native/src/config.rs +73 -0
  44. package/native/src/lib.rs +528 -0
  45. package/native/src/math/bit_math.rs +177 -0
  46. package/native/src/math/full_math.rs +217 -0
  47. package/native/src/math/liquidity_math.rs +72 -0
  48. package/native/src/math/mod.rs +10 -0
  49. package/native/src/math/oracle.rs +493 -0
  50. package/native/src/math/sqrt_price_math.rs +272 -0
  51. package/native/src/math/swap_math.rs +306 -0
  52. package/native/src/math/tick.rs +239 -0
  53. package/native/src/math/tick_bitmap.rs +312 -0
  54. package/native/src/math/tick_math.rs +321 -0
  55. package/native/src/math/unsafe_math.rs +67 -0
  56. package/native/src/pool_state.rs +41 -0
  57. package/native/src/query_outputs.rs +379 -0
  58. package/native/src/v4_query_outputs.rs +255 -0
  59. package/package.json +2 -1
@@ -0,0 +1,177 @@
1
+ use ethnum::U256;
2
+
3
+ /// Returns the index of the most significant bit of the number,
4
+ /// where the least significant bit is at index 0 and the most significant bit is at index 255.
5
+ ///
6
+ /// Panics if x is zero.
7
+ pub fn most_significant_bit(x: U256) -> u8 {
8
+ assert!(x > U256::ZERO, "x must be > 0");
9
+ let mut x = x;
10
+ let mut r: u8 = 0;
11
+
12
+ if x >= U256::from_words(1, 0) {
13
+ x >>= 128;
14
+ r += 128;
15
+ }
16
+ if x >= U256::from(0x10000000000000000u128) {
17
+ x >>= 64;
18
+ r += 64;
19
+ }
20
+ if x >= U256::from(0x100000000u128) {
21
+ x >>= 32;
22
+ r += 32;
23
+ }
24
+ if x >= U256::from(0x10000u64) {
25
+ x >>= 16;
26
+ r += 16;
27
+ }
28
+ if x >= U256::from(0x100u64) {
29
+ x >>= 8;
30
+ r += 8;
31
+ }
32
+ if x >= U256::from(0x10u64) {
33
+ x >>= 4;
34
+ r += 4;
35
+ }
36
+ if x >= U256::from(0x4u64) {
37
+ x >>= 2;
38
+ r += 2;
39
+ }
40
+ if x >= U256::from(0x2u64) {
41
+ r += 1;
42
+ }
43
+
44
+ r
45
+ }
46
+
47
+ /// Returns the index of the least significant bit of the number,
48
+ /// where the least significant bit is at index 0 and the most significant bit is at index 255.
49
+ ///
50
+ /// Panics if x is zero.
51
+ pub fn least_significant_bit(x: U256) -> u8 {
52
+ assert!(x > U256::ZERO, "x must be > 0");
53
+ let mut x = x;
54
+ let mut r: u8 = 255;
55
+
56
+ let max_uint128: U256 = U256::new(u128::MAX);
57
+ let max_uint64: U256 = U256::from(u64::MAX);
58
+ let max_uint32: U256 = U256::from(u32::MAX as u64);
59
+ let max_uint16: U256 = U256::from(u16::MAX as u64);
60
+ let max_uint8: U256 = U256::from(u8::MAX as u64);
61
+
62
+ if (x & max_uint128) > U256::ZERO {
63
+ r -= 128;
64
+ } else {
65
+ x >>= 128;
66
+ }
67
+ if (x & max_uint64) > U256::ZERO {
68
+ r -= 64;
69
+ } else {
70
+ x >>= 64;
71
+ }
72
+ if (x & max_uint32) > U256::ZERO {
73
+ r -= 32;
74
+ } else {
75
+ x >>= 32;
76
+ }
77
+ if (x & max_uint16) > U256::ZERO {
78
+ r -= 16;
79
+ } else {
80
+ x >>= 16;
81
+ }
82
+ if (x & max_uint8) > U256::ZERO {
83
+ r -= 8;
84
+ } else {
85
+ x >>= 8;
86
+ }
87
+ if (x & U256::from(0xFu64)) > U256::ZERO {
88
+ r -= 4;
89
+ } else {
90
+ x >>= 4;
91
+ }
92
+ if (x & U256::from(0x3u64)) > U256::ZERO {
93
+ r -= 2;
94
+ } else {
95
+ x >>= 2;
96
+ }
97
+ if (x & U256::ONE) > U256::ZERO {
98
+ r -= 1;
99
+ }
100
+
101
+ r
102
+ }
103
+
104
+ #[cfg(test)]
105
+ mod tests {
106
+ use super::*;
107
+
108
+ #[test]
109
+ fn test_msb_one() {
110
+ assert_eq!(most_significant_bit(U256::ONE), 0);
111
+ }
112
+
113
+ #[test]
114
+ fn test_msb_two() {
115
+ assert_eq!(most_significant_bit(U256::from(2u64)), 1);
116
+ }
117
+
118
+ #[test]
119
+ fn test_msb_powers_of_two() {
120
+ for i in 0..=255u8 {
121
+ let x = U256::ONE << i;
122
+ assert_eq!(most_significant_bit(x), i);
123
+ }
124
+ }
125
+
126
+ #[test]
127
+ fn test_msb_max() {
128
+ assert_eq!(most_significant_bit(U256::MAX), 255);
129
+ }
130
+
131
+ #[test]
132
+ #[should_panic]
133
+ fn test_msb_zero_panics() {
134
+ most_significant_bit(U256::ZERO);
135
+ }
136
+
137
+ #[test]
138
+ fn test_lsb_one() {
139
+ assert_eq!(least_significant_bit(U256::ONE), 0);
140
+ }
141
+
142
+ #[test]
143
+ fn test_lsb_two() {
144
+ assert_eq!(least_significant_bit(U256::from(2u64)), 1);
145
+ }
146
+
147
+ #[test]
148
+ fn test_lsb_powers_of_two() {
149
+ for i in 0..=255u8 {
150
+ let x = U256::ONE << i;
151
+ assert_eq!(least_significant_bit(x), i);
152
+ }
153
+ }
154
+
155
+ #[test]
156
+ fn test_lsb_max() {
157
+ assert_eq!(least_significant_bit(U256::MAX), 0);
158
+ }
159
+
160
+ #[test]
161
+ #[should_panic]
162
+ fn test_lsb_zero_panics() {
163
+ least_significant_bit(U256::ZERO);
164
+ }
165
+
166
+ #[test]
167
+ fn test_msb_mixed() {
168
+ assert_eq!(most_significant_bit(U256::from(10u64)), 3);
169
+ assert_eq!(most_significant_bit(U256::from(24u64)), 4);
170
+ }
171
+
172
+ #[test]
173
+ fn test_lsb_mixed() {
174
+ assert_eq!(least_significant_bit(U256::from(10u64)), 1);
175
+ assert_eq!(least_significant_bit(U256::from(24u64)), 3);
176
+ }
177
+ }
@@ -0,0 +1,217 @@
1
+ use ethnum::U256;
2
+
3
+ /// Calculates floor(a * b / denominator).
4
+ ///
5
+ /// The TS version uses BigInt which has arbitrary precision, so `a * b` never
6
+ /// overflows. We replicate this by widening to 512-bit via two U256 halves.
7
+ ///
8
+ /// Panics if the result exceeds U256::MAX or denominator is zero.
9
+ pub fn mul_div(a: U256, b: U256, denominator: U256) -> U256 {
10
+ assert!(denominator > U256::ZERO, "denominator must be > 0");
11
+ let (lo, hi) = widening_mul(a, b);
12
+ let (quot, _) = div_512_by_256(lo, hi, denominator);
13
+ quot
14
+ }
15
+
16
+ /// Calculates ceil(a * b / denominator).
17
+ ///
18
+ /// Panics if the result exceeds U256::MAX or denominator is zero.
19
+ pub fn mul_div_rounding_up(a: U256, b: U256, denominator: U256) -> U256 {
20
+ assert!(denominator > U256::ZERO, "denominator must be > 0");
21
+ // result = (a * b + denominator - 1) / denominator
22
+ let (lo, hi) = widening_mul(a, b);
23
+ // add (denominator - 1) to the 512-bit product
24
+ let addend = denominator - U256::ONE;
25
+ let (lo2, carry) = lo.overflowing_add(addend);
26
+ let hi2 = if carry { hi + U256::ONE } else { hi };
27
+ let (quot, _) = div_512_by_256(lo2, hi2, denominator);
28
+ quot
29
+ }
30
+
31
+ /// Returns (lo, hi) such that a * b = hi * 2^256 + lo.
32
+ fn widening_mul(a: U256, b: U256) -> (U256, U256) {
33
+ let mask128 = (U256::ONE << 128) - U256::ONE;
34
+
35
+ let a_lo = a & mask128;
36
+ let a_hi = a >> 128;
37
+ let b_lo = b & mask128;
38
+ let b_hi = b >> 128;
39
+
40
+ let p0: U256 = a_lo * b_lo;
41
+ let p1: U256 = a_lo * b_hi;
42
+ let p2: U256 = a_hi * b_lo;
43
+ let p3: U256 = a_hi * b_hi;
44
+
45
+ let lo: U256 = p0;
46
+ let hi: U256 = p3;
47
+
48
+ // Add p1 << 128
49
+ let p1_lo = p1 << 128;
50
+ let p1_hi = p1 >> 128;
51
+ let (lo, c1) = lo.overflowing_add(p1_lo);
52
+ let hi = hi + p1_hi + if c1 { U256::ONE } else { U256::ZERO };
53
+
54
+ // Add p2 << 128
55
+ let p2_lo = p2 << 128;
56
+ let p2_hi = p2 >> 128;
57
+ let (lo, c2) = lo.overflowing_add(p2_lo);
58
+ let hi = hi + p2_hi + if c2 { U256::ONE } else { U256::ZERO };
59
+
60
+ (lo, hi)
61
+ }
62
+
63
+ /// Divides a 512-bit number (lo + hi * 2^256) by a 256-bit denominator.
64
+ /// Returns (quotient, remainder). Panics if quotient overflows U256.
65
+ fn div_512_by_256(lo: U256, hi: U256, d: U256) -> (U256, U256) {
66
+ assert!(d > U256::ZERO, "division by zero");
67
+
68
+ if hi == U256::ZERO {
69
+ return (lo / d, lo % d);
70
+ }
71
+
72
+ assert!(hi < d, "mul_div result overflows U256");
73
+
74
+ // Split lo into two 128-bit halves and do two rounds of division.
75
+ let mask128 = (U256::ONE << 128) - U256::ONE;
76
+ let lo_hi = (lo >> 128) & mask128;
77
+ let lo_lo = lo & mask128;
78
+
79
+ // First round: divide (hi * 2^128 + lo_hi) by d
80
+ let (q_hi, r1) = div_384_by_256(lo_hi, hi, d);
81
+
82
+ // Second round: divide (r1 * 2^128 + lo_lo) by d
83
+ let (q_lo, rem) = div_384_by_256(lo_lo, r1, d);
84
+
85
+ let quotient = (q_hi << 128) + q_lo;
86
+ (quotient, rem)
87
+ }
88
+
89
+ /// Divides (hi * 2^128 + lo_128) by d, where hi < d and lo_128 < 2^128.
90
+ /// Returns (quotient, remainder).
91
+ fn div_384_by_256(lo_128: U256, hi: U256, d: U256) -> (U256, U256) {
92
+ let mask128 = (U256::ONE << 128) - U256::ONE;
93
+ let hi_upper = hi >> 128;
94
+
95
+ if hi_upper == U256::ZERO {
96
+ // hi fits in 128 bits, so hi * 2^128 + lo_128 fits in 256 bits
97
+ let numerator = (hi << 128) | lo_128;
98
+ return (numerator / d, numerator % d);
99
+ }
100
+
101
+ // hi doesn't fit in 128 bits. Use bit-by-bit long division.
102
+ // The quotient fits in at most ~129 bits (since hi < d).
103
+ let _ = mask128;
104
+ let mut remainder = hi;
105
+ let mut quotient = U256::ZERO;
106
+
107
+ for i in (0..128).rev() {
108
+ let bit = (lo_128 >> i) & U256::ONE;
109
+
110
+ // Check if shifting left would overflow
111
+ let overflow = remainder >> 255 != U256::ZERO;
112
+ remainder = (remainder << 1) | bit;
113
+
114
+ if overflow || remainder >= d {
115
+ remainder = remainder.wrapping_sub(d);
116
+ quotient = quotient | (U256::ONE << i);
117
+ }
118
+ }
119
+
120
+ (quotient, remainder)
121
+ }
122
+
123
+ #[cfg(test)]
124
+ mod tests {
125
+ use super::*;
126
+
127
+ #[test]
128
+ fn test_mul_div_simple() {
129
+ assert_eq!(
130
+ mul_div(U256::from(6u64), U256::from(7u64), U256::from(3u64)),
131
+ U256::from(14u64)
132
+ );
133
+ }
134
+
135
+ #[test]
136
+ fn test_mul_div_large() {
137
+ assert_eq!(
138
+ mul_div(U256::MAX, U256::ONE, U256::ONE),
139
+ U256::MAX
140
+ );
141
+ }
142
+
143
+ #[test]
144
+ fn test_mul_div_rounding_up_exact() {
145
+ assert_eq!(
146
+ mul_div_rounding_up(U256::from(6u64), U256::from(7u64), U256::from(3u64)),
147
+ U256::from(14u64)
148
+ );
149
+ }
150
+
151
+ #[test]
152
+ fn test_mul_div_rounding_up_rounds() {
153
+ // 5 * 7 / 3 = 35/3 = 11.666... -> ceil = 12
154
+ assert_eq!(
155
+ mul_div_rounding_up(U256::from(5u64), U256::from(7u64), U256::from(3u64)),
156
+ U256::from(12u64)
157
+ );
158
+ }
159
+
160
+ #[test]
161
+ fn test_mul_div_floor() {
162
+ // 5 * 7 / 3 = 35/3 = 11.666... -> floor = 11
163
+ assert_eq!(
164
+ mul_div(U256::from(5u64), U256::from(7u64), U256::from(3u64)),
165
+ U256::from(11u64)
166
+ );
167
+ }
168
+
169
+ #[test]
170
+ fn test_mul_div_large_product() {
171
+ let a = U256::ONE << 200;
172
+ let b = U256::ONE << 200;
173
+ let d = U256::ONE << 200;
174
+ assert_eq!(mul_div(a, b, d), U256::ONE << 200);
175
+ }
176
+
177
+ #[test]
178
+ fn test_mul_div_max_times_max() {
179
+ assert_eq!(mul_div(U256::MAX, U256::MAX, U256::MAX), U256::MAX);
180
+ }
181
+
182
+ #[test]
183
+ #[should_panic]
184
+ fn test_mul_div_overflow() {
185
+ mul_div(U256::MAX, U256::MAX, U256::ONE);
186
+ }
187
+
188
+ #[test]
189
+ fn test_mul_div_rounding_up_large() {
190
+ let a = U256::ONE << 128;
191
+ let b = U256::ONE << 128;
192
+ let d = (U256::ONE << 128) + U256::ONE;
193
+ let result = mul_div_rounding_up(a, b, d);
194
+ assert!(result > U256::ZERO);
195
+ }
196
+
197
+ #[test]
198
+ fn test_widening_mul_simple() {
199
+ let (lo, hi) = widening_mul(U256::from(3u64), U256::from(7u64));
200
+ assert_eq!(lo, U256::from(21u64));
201
+ assert_eq!(hi, U256::ZERO);
202
+ }
203
+
204
+ #[test]
205
+ fn test_widening_mul_large() {
206
+ let (lo, hi) = widening_mul(U256::MAX, U256::from(2u64));
207
+ assert_eq!(hi, U256::ONE);
208
+ assert_eq!(lo, U256::MAX - U256::ONE);
209
+ }
210
+
211
+ #[test]
212
+ fn test_mul_div_uniswap_style() {
213
+ // Test case from Uniswap V3: mulDiv(Q128, Q128, Q128) = Q128
214
+ let q128 = U256::ONE << 128;
215
+ assert_eq!(mul_div(q128, q128, q128), q128);
216
+ }
217
+ }
@@ -0,0 +1,72 @@
1
+ use ethnum::{I256, U256};
2
+
3
+ /// Adds a signed liquidity delta to an unsigned liquidity value.
4
+ ///
5
+ /// In Solidity, when y < 0:
6
+ /// z = x - uint128(-y); require(z < x)
7
+ /// When y >= 0:
8
+ /// z = x + uint128(y); require(z >= x)
9
+ ///
10
+ /// Panics with "LS" if y < 0 and the subtraction underflows.
11
+ /// Panics with "LA" if y >= 0 and the addition overflows.
12
+ pub fn add_delta(x: U256, y: I256) -> U256 {
13
+ let mask_128: U256 = (U256::ONE << 128) - U256::ONE;
14
+
15
+ if y < I256::ZERO {
16
+ // _y = BigInt.asUintN(128, -y)
17
+ // (-y) is positive I256; reinterpret as U256 and mask to 128 bits
18
+ let neg_y_u256 = (-y).as_u256();
19
+ let _y = neg_y_u256 & mask_128;
20
+ let z = x.checked_sub(_y).expect("LS");
21
+ assert!(z < x, "LS");
22
+ z
23
+ } else {
24
+ // _y = BigInt.asUintN(128, y)
25
+ let _y = y.as_u256() & mask_128;
26
+ let z = x.checked_add(_y).expect("LA");
27
+ assert!(z >= x, "LA");
28
+ z
29
+ }
30
+ }
31
+
32
+ #[cfg(test)]
33
+ mod tests {
34
+ use super::*;
35
+
36
+ #[test]
37
+ fn test_add_positive_delta() {
38
+ let x = U256::from(100u64);
39
+ let y = I256::new(50);
40
+ assert_eq!(add_delta(x, y), U256::from(150u64));
41
+ }
42
+
43
+ #[test]
44
+ fn test_add_negative_delta() {
45
+ let x = U256::from(100u64);
46
+ let y = I256::new(-50);
47
+ assert_eq!(add_delta(x, y), U256::from(50u64));
48
+ }
49
+
50
+ #[test]
51
+ fn test_add_zero_delta() {
52
+ let x = U256::from(100u64);
53
+ let y = I256::ZERO;
54
+ assert_eq!(add_delta(x, y), U256::from(100u64));
55
+ }
56
+
57
+ #[test]
58
+ #[should_panic(expected = "LS")]
59
+ fn test_subtract_too_much() {
60
+ let x = U256::from(50u64);
61
+ let y = I256::new(-100);
62
+ add_delta(x, y);
63
+ }
64
+
65
+ #[test]
66
+ #[should_panic(expected = "LA")]
67
+ fn test_add_overflow() {
68
+ let x = U256::MAX;
69
+ let y = I256::new(1);
70
+ add_delta(x, y);
71
+ }
72
+ }
@@ -0,0 +1,10 @@
1
+ pub mod bit_math;
2
+ pub mod full_math;
3
+ pub mod liquidity_math;
4
+ pub mod sqrt_price_math;
5
+ pub mod swap_math;
6
+ pub mod tick;
7
+ pub mod tick_bitmap;
8
+ pub mod tick_math;
9
+ pub mod unsafe_math;
10
+ pub mod oracle;