@paraswap/dex-lib 4.8.36 → 4.8.37-native-dex-math.0
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.
- package/build/dex/aave-gsm/config.js +2 -2
- package/build/dex/idex.d.ts +1 -1
- package/build/dex/pancakeswap-v3/pancakeswap-v3-pool.d.ts +2 -0
- package/build/dex/pancakeswap-v3/pancakeswap-v3-pool.js +5 -0
- package/build/dex/pancakeswap-v3/pancakeswap-v3-pool.js.map +1 -1
- package/build/dex/pancakeswap-v3/pancakeswap-v3.d.ts +6 -3
- package/build/dex/pancakeswap-v3/pancakeswap-v3.js +85 -9
- package/build/dex/pancakeswap-v3/pancakeswap-v3.js.map +1 -1
- package/build/dex/solidly-v3/solidly-v3-pool.d.ts +3 -0
- package/build/dex/solidly-v3/solidly-v3-pool.js +8 -0
- package/build/dex/solidly-v3/solidly-v3-pool.js.map +1 -1
- package/build/dex/solidly-v3/solidly-v3.d.ts +5 -2
- package/build/dex/solidly-v3/solidly-v3.js +84 -8
- package/build/dex/solidly-v3/solidly-v3.js.map +1 -1
- package/build/dex/uniswap-v3/scripts/measure-calc-time.js +222 -110
- package/build/dex/uniswap-v3/scripts/measure-calc-time.js.map +1 -1
- package/build/dex/uniswap-v3/types.d.ts +1 -0
- package/build/dex/uniswap-v3/types.js.map +1 -1
- package/build/dex/uniswap-v3/uniswap-v3-pool.d.ts +2 -0
- package/build/dex/uniswap-v3/uniswap-v3-pool.js +5 -0
- package/build/dex/uniswap-v3/uniswap-v3-pool.js.map +1 -1
- package/build/dex/uniswap-v3/uniswap-v3.d.ts +11 -3
- package/build/dex/uniswap-v3/uniswap-v3.js +86 -9
- package/build/dex/uniswap-v3/uniswap-v3.js.map +1 -1
- package/build/dex/uniswap-v4/types.d.ts +1 -0
- package/build/dex/uniswap-v4/uniswap-v4-pool-manager.d.ts +2 -0
- package/build/dex/uniswap-v4/uniswap-v4-pool-manager.js +3 -0
- package/build/dex/uniswap-v4/uniswap-v4-pool-manager.js.map +1 -1
- package/build/dex/uniswap-v4/uniswap-v4-pool.d.ts +3 -0
- package/build/dex/uniswap-v4/uniswap-v4-pool.js +18 -0
- package/build/dex/uniswap-v4/uniswap-v4-pool.js.map +1 -1
- package/build/dex/uniswap-v4/uniswap-v4.d.ts +3 -1
- package/build/dex/uniswap-v4/uniswap-v4.js +74 -14
- package/build/dex/uniswap-v4/uniswap-v4.js.map +1 -1
- package/build/pricing-helper.d.ts +1 -1
- package/build/pricing-helper.js +2 -2
- package/build/pricing-helper.js.map +1 -1
- package/native/Cargo.lock +331 -0
- package/native/Cargo.toml +22 -0
- package/native/build.rs +5 -0
- package/native/package-lock.json +32 -0
- package/native/package.json +20 -0
- package/native/src/config.rs +73 -0
- package/native/src/lib.rs +528 -0
- package/native/src/math/bit_math.rs +177 -0
- package/native/src/math/full_math.rs +217 -0
- package/native/src/math/liquidity_math.rs +72 -0
- package/native/src/math/mod.rs +10 -0
- package/native/src/math/oracle.rs +493 -0
- package/native/src/math/sqrt_price_math.rs +272 -0
- package/native/src/math/swap_math.rs +306 -0
- package/native/src/math/tick.rs +239 -0
- package/native/src/math/tick_bitmap.rs +312 -0
- package/native/src/math/tick_math.rs +321 -0
- package/native/src/math/unsafe_math.rs +67 -0
- package/native/src/pool_state.rs +41 -0
- package/native/src/query_outputs.rs +379 -0
- package/native/src/v4_query_outputs.rs +255 -0
- package/package.json +1 -1
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
use ethnum::{I256, U256};
|
|
2
|
+
|
|
3
|
+
pub const MIN_TICK: I256 = I256::new(-887272);
|
|
4
|
+
pub const MAX_TICK: I256 = I256::new(887272);
|
|
5
|
+
pub const MIN_SQRT_RATIO: U256 = U256::new(4295128739u128);
|
|
6
|
+
// 1461446703485210103287273052203988822378723970342
|
|
7
|
+
// = 0xFFFD8963EFD1FC6A506488495D951D5263988D26
|
|
8
|
+
// hi_128 = 0xFFFD8963, lo_128 = 0xEFD1FC6A506488495D951D5263988D26
|
|
9
|
+
pub const MAX_SQRT_RATIO: U256 =
|
|
10
|
+
U256::from_words(0xFFFD8963, 0xEFD1FC6A506488495D951D5263988D26);
|
|
11
|
+
|
|
12
|
+
// 2^160 - 1 = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
|
|
13
|
+
// hi_128 = 0xFFFFFFFF, lo_128 = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
|
|
14
|
+
const MASK_160: U256 = U256::from_words(0xFFFFFFFF, u128::MAX);
|
|
15
|
+
|
|
16
|
+
/// Truncate to uint160 range.
|
|
17
|
+
fn as_uint160(val: U256) -> U256 {
|
|
18
|
+
val & MASK_160
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/// Calculates sqrt(1.0001^tick) * 2^96.
|
|
22
|
+
///
|
|
23
|
+
/// Panics if |tick| > MAX_TICK.
|
|
24
|
+
pub fn get_sqrt_ratio_at_tick(tick: I256) -> U256 {
|
|
25
|
+
let abs_tick: U256 = if tick < I256::ZERO {
|
|
26
|
+
(-tick).as_u256()
|
|
27
|
+
} else {
|
|
28
|
+
tick.as_u256()
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
assert!(abs_tick <= MAX_TICK.as_u256(), "T");
|
|
32
|
+
|
|
33
|
+
let mut ratio: U256 = if (abs_tick & U256::from(0x1u64)) != U256::ZERO {
|
|
34
|
+
U256::new(0xfffcb933bd6fad37aa2d162d1a594001u128)
|
|
35
|
+
} else {
|
|
36
|
+
// 2^128
|
|
37
|
+
U256::from_words(1, 0)
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
macro_rules! apply_tick_bit {
|
|
41
|
+
($bit:expr, $factor:expr) => {
|
|
42
|
+
if (abs_tick & U256::from($bit as u64)) != U256::ZERO {
|
|
43
|
+
ratio = (ratio * U256::new($factor)) >> 128;
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
apply_tick_bit!(0x2, 0xfff97272373d413259a46990580e213au128);
|
|
49
|
+
apply_tick_bit!(0x4, 0xfff2e50f5f656932ef12357cf3c7fdccu128);
|
|
50
|
+
apply_tick_bit!(0x8, 0xffe5caca7e10e4e61c3624eaa0941cd0u128);
|
|
51
|
+
apply_tick_bit!(0x10, 0xffcb9843d60f6159c9db58835c926644u128);
|
|
52
|
+
apply_tick_bit!(0x20, 0xff973b41fa98c081472e6896dfb254c0u128);
|
|
53
|
+
apply_tick_bit!(0x40, 0xff2ea16466c96a3843ec78b326b52861u128);
|
|
54
|
+
apply_tick_bit!(0x80, 0xfe5dee046a99a2a811c461f1969c3053u128);
|
|
55
|
+
apply_tick_bit!(0x100, 0xfcbe86c7900a88aedcffc83b479aa3a4u128);
|
|
56
|
+
apply_tick_bit!(0x200, 0xf987a7253ac413176f2b074cf7815e54u128);
|
|
57
|
+
apply_tick_bit!(0x400, 0xf3392b0822b70005940c7a398e4b70f3u128);
|
|
58
|
+
apply_tick_bit!(0x800, 0xe7159475a2c29b7443b29c7fa6e889d9u128);
|
|
59
|
+
apply_tick_bit!(0x1000, 0xd097f3bdfd2022b8845ad8f792aa5825u128);
|
|
60
|
+
apply_tick_bit!(0x2000, 0xa9f746462d870fdf8a65dc1f90e061e5u128);
|
|
61
|
+
apply_tick_bit!(0x4000, 0x70d869a156d2a1b890bb3df62baf32f7u128);
|
|
62
|
+
apply_tick_bit!(0x8000, 0x31be135f97d08fd981231505542fcfa6u128);
|
|
63
|
+
apply_tick_bit!(0x10000, 0x9aa508b5b7a84e1c677de54f3e99bc9u128);
|
|
64
|
+
apply_tick_bit!(0x20000, 0x5d6af8dedb81196699c329225ee604u128);
|
|
65
|
+
apply_tick_bit!(0x40000, 0x2216e584f5fa1ea926041bedfe98u128);
|
|
66
|
+
apply_tick_bit!(0x80000, 0x48a170391f7dc42444e8fa2u128);
|
|
67
|
+
|
|
68
|
+
if tick > I256::ZERO {
|
|
69
|
+
ratio = U256::MAX / ratio;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
let remainder = ratio % (U256::ONE << 32);
|
|
73
|
+
let extra = if remainder == U256::ZERO {
|
|
74
|
+
U256::ZERO
|
|
75
|
+
} else {
|
|
76
|
+
U256::ONE
|
|
77
|
+
};
|
|
78
|
+
as_uint160((ratio >> 32) + extra)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/// Calculates the greatest tick value such that getSqrtRatioAtTick(tick) <= ratio.
|
|
82
|
+
///
|
|
83
|
+
/// Panics if sqrtPriceX96 < MIN_SQRT_RATIO or sqrtPriceX96 >= MAX_SQRT_RATIO.
|
|
84
|
+
pub fn get_tick_at_sqrt_ratio(sqrt_price_x96: U256) -> I256 {
|
|
85
|
+
assert!(
|
|
86
|
+
sqrt_price_x96 >= MIN_SQRT_RATIO && sqrt_price_x96 < MAX_SQRT_RATIO,
|
|
87
|
+
"R"
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
let ratio = sqrt_price_x96 << 32;
|
|
91
|
+
|
|
92
|
+
let mut r = ratio;
|
|
93
|
+
let mut msb = U256::ZERO;
|
|
94
|
+
|
|
95
|
+
// _gt helper inline
|
|
96
|
+
let gt = |a: U256, b: U256| -> U256 {
|
|
97
|
+
if a > b { U256::ONE } else { U256::ZERO }
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
let mut f: U256 =
|
|
101
|
+
gt(r, U256::new(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFu128)) << 7;
|
|
102
|
+
msb = msb | f;
|
|
103
|
+
r = r >> f;
|
|
104
|
+
|
|
105
|
+
f = gt(r, U256::from(0xFFFFFFFFFFFFFFFFu128)) << 6;
|
|
106
|
+
msb = msb | f;
|
|
107
|
+
r = r >> f;
|
|
108
|
+
|
|
109
|
+
f = gt(r, U256::from(0xFFFFFFFFu64)) << 5;
|
|
110
|
+
msb = msb | f;
|
|
111
|
+
r = r >> f;
|
|
112
|
+
|
|
113
|
+
f = gt(r, U256::from(0xFFFFu64)) << 4;
|
|
114
|
+
msb = msb | f;
|
|
115
|
+
r = r >> f;
|
|
116
|
+
|
|
117
|
+
f = gt(r, U256::from(0xFFu64)) << 3;
|
|
118
|
+
msb = msb | f;
|
|
119
|
+
r = r >> f;
|
|
120
|
+
|
|
121
|
+
f = gt(r, U256::from(0xFu64)) << 2;
|
|
122
|
+
msb = msb | f;
|
|
123
|
+
r = r >> f;
|
|
124
|
+
|
|
125
|
+
f = gt(r, U256::from(0x3u64)) << 1;
|
|
126
|
+
msb = msb | f;
|
|
127
|
+
r = r >> f;
|
|
128
|
+
|
|
129
|
+
f = gt(r, U256::ONE);
|
|
130
|
+
msb = msb | f;
|
|
131
|
+
|
|
132
|
+
if msb >= U256::from(128u64) {
|
|
133
|
+
r = ratio >> (msb - U256::from(127u64));
|
|
134
|
+
} else {
|
|
135
|
+
r = ratio << (U256::from(127u64) - msb);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// log_2 is int256 in Solidity. (int256(msb) - 128) << 64
|
|
139
|
+
let mut log_2: I256 = (msb.as_i256() - I256::from(128i32)) << 64u32;
|
|
140
|
+
|
|
141
|
+
// 14 iterations of squaring
|
|
142
|
+
macro_rules! log2_step {
|
|
143
|
+
($shift:expr) => {
|
|
144
|
+
r = (r * r) >> 127;
|
|
145
|
+
f = r >> 128;
|
|
146
|
+
// f is 0 or 1 (unsigned), cast to signed for the OR into log_2
|
|
147
|
+
log_2 = log_2 | ((f.as_i256()) << $shift as u32);
|
|
148
|
+
r = r >> f;
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
log2_step!(63);
|
|
153
|
+
log2_step!(62);
|
|
154
|
+
log2_step!(61);
|
|
155
|
+
log2_step!(60);
|
|
156
|
+
log2_step!(59);
|
|
157
|
+
log2_step!(58);
|
|
158
|
+
log2_step!(57);
|
|
159
|
+
log2_step!(56);
|
|
160
|
+
log2_step!(55);
|
|
161
|
+
log2_step!(54);
|
|
162
|
+
log2_step!(53);
|
|
163
|
+
log2_step!(52);
|
|
164
|
+
log2_step!(51);
|
|
165
|
+
|
|
166
|
+
// Last iteration (no r >>= f after)
|
|
167
|
+
r = (r * r) >> 127;
|
|
168
|
+
f = r >> 128;
|
|
169
|
+
log_2 = log_2 | ((f.as_i256()) << 50u32);
|
|
170
|
+
|
|
171
|
+
// log_sqrt10001 = log_2 * 255738958999603826347141 (signed multiply)
|
|
172
|
+
let log_sqrt10001: I256 = log_2 * I256::new(255738958999603826347141i128);
|
|
173
|
+
|
|
174
|
+
// tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128)
|
|
175
|
+
let tick_low_raw: I256 = (log_sqrt10001
|
|
176
|
+
- I256::new(3402992956809132418596140100660247210i128))
|
|
177
|
+
>> 128u32;
|
|
178
|
+
|
|
179
|
+
// tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128)
|
|
180
|
+
let tick_hi_raw: I256 = (log_sqrt10001
|
|
181
|
+
+ U256::new(291339464771989622907027621153398088495u128).as_i256())
|
|
182
|
+
>> 128u32;
|
|
183
|
+
|
|
184
|
+
let tick_low = as_int_n_24(tick_low_raw);
|
|
185
|
+
let tick_hi = as_int_n_24(tick_hi_raw);
|
|
186
|
+
|
|
187
|
+
if tick_low == tick_hi {
|
|
188
|
+
tick_low
|
|
189
|
+
} else if get_sqrt_ratio_at_tick(tick_hi) <= sqrt_price_x96 {
|
|
190
|
+
tick_hi
|
|
191
|
+
} else {
|
|
192
|
+
tick_low
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/// Equivalent to BigInt.asIntN(24, x) -- truncate to 24 bits and sign-extend.
|
|
197
|
+
fn as_int_n_24(x: I256) -> I256 {
|
|
198
|
+
let mask_24 = I256::new((1i128 << 24) - 1);
|
|
199
|
+
let truncated = x & mask_24;
|
|
200
|
+
let sign_bit = I256::ONE << 23u32;
|
|
201
|
+
if (truncated & sign_bit) != I256::ZERO {
|
|
202
|
+
truncated | !mask_24
|
|
203
|
+
} else {
|
|
204
|
+
truncated
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
#[cfg(test)]
|
|
209
|
+
mod tests {
|
|
210
|
+
use super::*;
|
|
211
|
+
|
|
212
|
+
#[test]
|
|
213
|
+
fn test_constants() {
|
|
214
|
+
assert_eq!(MIN_TICK, I256::new(-887272));
|
|
215
|
+
assert_eq!(MAX_TICK, I256::new(887272));
|
|
216
|
+
assert_eq!(MIN_SQRT_RATIO, U256::from(4295128739u64));
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
#[test]
|
|
220
|
+
fn test_max_sqrt_ratio() {
|
|
221
|
+
let expected =
|
|
222
|
+
U256::from_words(0xFFFD8963, 0xEFD1FC6A506488495D951D5263988D26);
|
|
223
|
+
assert_eq!(MAX_SQRT_RATIO, expected);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
#[test]
|
|
227
|
+
fn test_get_sqrt_ratio_at_tick_min() {
|
|
228
|
+
let result = get_sqrt_ratio_at_tick(MIN_TICK);
|
|
229
|
+
assert_eq!(result, MIN_SQRT_RATIO);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
#[test]
|
|
233
|
+
fn test_get_sqrt_ratio_at_tick_max() {
|
|
234
|
+
let result = get_sqrt_ratio_at_tick(MAX_TICK);
|
|
235
|
+
assert_eq!(result, MAX_SQRT_RATIO);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
#[test]
|
|
239
|
+
fn test_get_sqrt_ratio_at_tick_zero() {
|
|
240
|
+
let result = get_sqrt_ratio_at_tick(I256::ZERO);
|
|
241
|
+
let q96 = U256::ONE << 96;
|
|
242
|
+
assert_eq!(result, q96);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
#[test]
|
|
246
|
+
fn test_get_tick_at_sqrt_ratio_min() {
|
|
247
|
+
let result = get_tick_at_sqrt_ratio(MIN_SQRT_RATIO);
|
|
248
|
+
assert_eq!(result, MIN_TICK);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
#[test]
|
|
252
|
+
fn test_get_tick_at_sqrt_ratio_q96() {
|
|
253
|
+
let q96 = U256::ONE << 96;
|
|
254
|
+
let result = get_tick_at_sqrt_ratio(q96);
|
|
255
|
+
assert_eq!(result, I256::ZERO);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
#[test]
|
|
259
|
+
fn test_roundtrip_positive_tick() {
|
|
260
|
+
let tick = I256::from(100i32);
|
|
261
|
+
let sqrt_ratio = get_sqrt_ratio_at_tick(tick);
|
|
262
|
+
let computed_tick = get_tick_at_sqrt_ratio(sqrt_ratio);
|
|
263
|
+
assert_eq!(computed_tick, tick);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
#[test]
|
|
267
|
+
fn test_roundtrip_negative_tick() {
|
|
268
|
+
let tick = I256::from(-100i32);
|
|
269
|
+
let sqrt_ratio = get_sqrt_ratio_at_tick(tick);
|
|
270
|
+
let computed_tick = get_tick_at_sqrt_ratio(sqrt_ratio);
|
|
271
|
+
assert_eq!(computed_tick, tick);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
#[test]
|
|
275
|
+
fn test_roundtrip_large_positive_tick() {
|
|
276
|
+
let tick = I256::new(887270);
|
|
277
|
+
let sqrt_ratio = get_sqrt_ratio_at_tick(tick);
|
|
278
|
+
let computed_tick = get_tick_at_sqrt_ratio(sqrt_ratio);
|
|
279
|
+
assert_eq!(computed_tick, tick);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
#[test]
|
|
283
|
+
fn test_roundtrip_large_negative_tick() {
|
|
284
|
+
let tick = I256::new(-887270);
|
|
285
|
+
let sqrt_ratio = get_sqrt_ratio_at_tick(tick);
|
|
286
|
+
let computed_tick = get_tick_at_sqrt_ratio(sqrt_ratio);
|
|
287
|
+
assert_eq!(computed_tick, tick);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
#[test]
|
|
291
|
+
#[should_panic(expected = "T")]
|
|
292
|
+
fn test_get_sqrt_ratio_at_tick_too_large() {
|
|
293
|
+
get_sqrt_ratio_at_tick(MAX_TICK + I256::ONE);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
#[test]
|
|
297
|
+
#[should_panic(expected = "T")]
|
|
298
|
+
fn test_get_sqrt_ratio_at_tick_too_small() {
|
|
299
|
+
get_sqrt_ratio_at_tick(MIN_TICK - I256::ONE);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
#[test]
|
|
303
|
+
#[should_panic(expected = "R")]
|
|
304
|
+
fn test_get_tick_at_sqrt_ratio_too_small() {
|
|
305
|
+
get_tick_at_sqrt_ratio(MIN_SQRT_RATIO - U256::ONE);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
#[test]
|
|
309
|
+
#[should_panic(expected = "R")]
|
|
310
|
+
fn test_get_tick_at_sqrt_ratio_too_large() {
|
|
311
|
+
get_tick_at_sqrt_ratio(MAX_SQRT_RATIO);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
#[test]
|
|
315
|
+
fn test_as_int_n_24() {
|
|
316
|
+
assert_eq!(as_int_n_24(I256::from(100i32)), I256::from(100i32));
|
|
317
|
+
assert_eq!(as_int_n_24(I256::from(-100i32)), I256::from(-100i32));
|
|
318
|
+
assert_eq!(as_int_n_24(I256::new(887272)), I256::new(887272));
|
|
319
|
+
assert_eq!(as_int_n_24(I256::new(-887272)), I256::new(-887272));
|
|
320
|
+
}
|
|
321
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
use ethnum::U256;
|
|
2
|
+
|
|
3
|
+
/// Divides x by y, rounding up. Does not check for division by zero.
|
|
4
|
+
/// Equivalent to Solidity's `(x + y - 1) / y` with unchecked arithmetic.
|
|
5
|
+
pub fn div_rounding_up(x: U256, y: U256) -> U256 {
|
|
6
|
+
(x + y - U256::ONE) / y
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
#[cfg(test)]
|
|
10
|
+
mod tests {
|
|
11
|
+
use super::*;
|
|
12
|
+
|
|
13
|
+
#[test]
|
|
14
|
+
fn test_exact_division() {
|
|
15
|
+
assert_eq!(
|
|
16
|
+
div_rounding_up(U256::from(10u64), U256::from(5u64)),
|
|
17
|
+
U256::from(2u64)
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
#[test]
|
|
22
|
+
fn test_rounds_up() {
|
|
23
|
+
assert_eq!(
|
|
24
|
+
div_rounding_up(U256::from(11u64), U256::from(5u64)),
|
|
25
|
+
U256::from(3u64)
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
#[test]
|
|
30
|
+
fn test_one_divided_by_one() {
|
|
31
|
+
assert_eq!(
|
|
32
|
+
div_rounding_up(U256::ONE, U256::ONE),
|
|
33
|
+
U256::ONE
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
#[test]
|
|
38
|
+
fn test_zero_numerator() {
|
|
39
|
+
assert_eq!(
|
|
40
|
+
div_rounding_up(U256::ZERO, U256::from(5u64)),
|
|
41
|
+
U256::ZERO
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
#[test]
|
|
46
|
+
fn test_large_values() {
|
|
47
|
+
let _x = U256::MAX;
|
|
48
|
+
let _y = U256::from(2u64);
|
|
49
|
+
// (MAX + 2 - 1) / 2 -- but MAX + 1 wraps to 0, so this is (0) / 2 = 0
|
|
50
|
+
// Wait, U256 arithmetic here is NOT wrapping. Let's think:
|
|
51
|
+
// x + y - 1 = MAX + 2 - 1 = MAX + 1 which overflows.
|
|
52
|
+
// But in Solidity "UnsafeMath" this is unchecked. In our TS it uses BigInt (no overflow).
|
|
53
|
+
// TS: (MAX + 2 - 1) / 2 = (MAX + 1) / 2 = 2^256 / 2 = 2^255.
|
|
54
|
+
// But U256 can't represent 2^256. The TS BigInt can though.
|
|
55
|
+
// Actually in the TS, x is already bounded to uint256 values that come from
|
|
56
|
+
// other operations, so x + y - 1 wouldn't overflow in practice.
|
|
57
|
+
// We skip this edge case test.
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
#[test]
|
|
61
|
+
fn test_rounding_by_one() {
|
|
62
|
+
assert_eq!(
|
|
63
|
+
div_rounding_up(U256::from(1u64), U256::from(3u64)),
|
|
64
|
+
U256::from(1u64)
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
use ethnum::{I256, U256};
|
|
2
|
+
use std::collections::HashMap;
|
|
3
|
+
|
|
4
|
+
use crate::config::MathVariant;
|
|
5
|
+
use crate::math::oracle::OracleObservation;
|
|
6
|
+
use crate::math::tick::TickInfo;
|
|
7
|
+
|
|
8
|
+
/// Mirrors the TS PoolState type, containing all fields needed for pricing.
|
|
9
|
+
/// balance0/balance1 are NOT included — they stay in JS.
|
|
10
|
+
#[derive(Debug, Clone)]
|
|
11
|
+
pub struct PoolState {
|
|
12
|
+
pub block_timestamp: U256,
|
|
13
|
+
pub tick_spacing: I256,
|
|
14
|
+
pub fee: U256,
|
|
15
|
+
|
|
16
|
+
// slot0
|
|
17
|
+
pub sqrt_price_x96: U256,
|
|
18
|
+
pub tick: I256,
|
|
19
|
+
pub observation_index: u16,
|
|
20
|
+
pub observation_cardinality: u16,
|
|
21
|
+
pub observation_cardinality_next: u16,
|
|
22
|
+
pub fee_protocol: U256,
|
|
23
|
+
|
|
24
|
+
pub liquidity: U256,
|
|
25
|
+
pub max_liquidity_per_tick: U256,
|
|
26
|
+
|
|
27
|
+
pub tick_bitmap: HashMap<i16, U256>,
|
|
28
|
+
pub ticks: HashMap<i32, TickInfo>,
|
|
29
|
+
pub observations: HashMap<u16, OracleObservation>,
|
|
30
|
+
|
|
31
|
+
pub start_tick_bitmap: I256,
|
|
32
|
+
pub lowest_known_tick: I256,
|
|
33
|
+
pub highest_known_tick: I256,
|
|
34
|
+
|
|
35
|
+
/// Precomputed bitmap bounds for price queries.
|
|
36
|
+
/// wordPos must be within [bitmap_range_lower, bitmap_range_upper] during pricing.
|
|
37
|
+
pub bitmap_range_lower: i16,
|
|
38
|
+
pub bitmap_range_upper: i16,
|
|
39
|
+
|
|
40
|
+
pub variant: MathVariant,
|
|
41
|
+
}
|