Skip to content

Commit b6b7216

Browse files
authored
MEV Resist Pool Implementation (#17)
1 parent 147b621 commit b6b7216

File tree

10 files changed

+501
-51
lines changed

10 files changed

+501
-51
lines changed

src/math/tick.rs

Lines changed: 93 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::math::uint::U256;
1+
use crate::{math::uint::u256_to_float_base_x128, math::uint::U256};
22

33
const ONE_X128: U256 = U256([0, 0, 1, 0]);
44

@@ -76,50 +76,104 @@ pub fn to_sqrt_ratio(tick: i32) -> Option<U256> {
7676
Some(ratio)
7777
}
7878

79+
const SQRT_TICK_SIZE: f64 =
80+
1.00000049999987500006249996093752734372949220361326815796989439990616646_f64;
81+
82+
pub fn approximate_sqrt_ratio_to_tick(sqrt_ratio: U256) -> i32 {
83+
u256_to_float_base_x128(sqrt_ratio)
84+
.log(SQRT_TICK_SIZE)
85+
.round() as i32
86+
}
87+
7988
#[cfg(test)]
8089
mod tests {
81-
use super::{to_sqrt_ratio, MAX_SQRT_RATIO, MAX_TICK, MIN_SQRT_RATIO, MIN_TICK};
82-
use crate::math::uint::U256;
83-
84-
#[test]
85-
fn test_tick_examples() {
86-
assert_eq!(
87-
to_sqrt_ratio(1000000).unwrap(),
88-
U256::from_str_radix("561030636129153856579134353873645338624", 10).unwrap(),
89-
);
90-
assert_eq!(
91-
to_sqrt_ratio(10000000).unwrap(),
92-
U256::from_str_radix("50502254805927926084423855178401471004672", 10).unwrap(),
93-
);
94-
assert_eq!(
95-
to_sqrt_ratio(-1000000).unwrap(),
96-
U256::from_str_radix("206391740095027370700312310528859963392", 10).unwrap(),
97-
);
98-
assert_eq!(
99-
to_sqrt_ratio(-10000000).unwrap(),
100-
U256::from_str_radix("2292810285051363400276741630355046400", 10).unwrap(),
101-
);
102-
}
90+
mod to_sqrt_ratio {
91+
use super::super::{to_sqrt_ratio, MAX_SQRT_RATIO, MAX_TICK, MIN_SQRT_RATIO, MIN_TICK};
92+
use crate::math::uint::U256;
93+
94+
#[test]
95+
fn test_tick_examples() {
96+
assert_eq!(
97+
to_sqrt_ratio(1000000).unwrap(),
98+
U256::from_str_radix("561030636129153856579134353873645338624", 10).unwrap(),
99+
);
100+
assert_eq!(
101+
to_sqrt_ratio(10000000).unwrap(),
102+
U256::from_str_radix("50502254805927926084423855178401471004672", 10).unwrap(),
103+
);
104+
assert_eq!(
105+
to_sqrt_ratio(-1000000).unwrap(),
106+
U256::from_str_radix("206391740095027370700312310528859963392", 10).unwrap(),
107+
);
108+
assert_eq!(
109+
to_sqrt_ratio(-10000000).unwrap(),
110+
U256::from_str_radix("2292810285051363400276741630355046400", 10).unwrap(),
111+
);
112+
}
103113

104-
#[test]
105-
fn test_tick_too_small() {
106-
assert!(to_sqrt_ratio(MIN_TICK - 1).is_none());
107-
assert!(to_sqrt_ratio(i32::MIN).is_none());
108-
}
114+
#[test]
115+
fn test_tick_too_small() {
116+
assert!(to_sqrt_ratio(MIN_TICK - 1).is_none());
117+
assert!(to_sqrt_ratio(i32::MIN).is_none());
118+
}
109119

110-
#[test]
111-
fn test_min_tick() {
112-
assert_eq!(to_sqrt_ratio(MIN_TICK).unwrap(), MIN_SQRT_RATIO,);
113-
}
120+
#[test]
121+
fn test_min_tick() {
122+
assert_eq!(to_sqrt_ratio(MIN_TICK).unwrap(), MIN_SQRT_RATIO,);
123+
}
114124

115-
#[test]
116-
fn test_max_tick() {
117-
assert_eq!(to_sqrt_ratio(MAX_TICK).unwrap(), MAX_SQRT_RATIO,);
125+
#[test]
126+
fn test_max_tick() {
127+
assert_eq!(to_sqrt_ratio(MAX_TICK).unwrap(), MAX_SQRT_RATIO,);
128+
}
129+
130+
#[test]
131+
fn test_tick_too_large() {
132+
assert!(to_sqrt_ratio(MAX_TICK + 1).is_none());
133+
assert!(to_sqrt_ratio(i32::MAX).is_none());
134+
}
118135
}
119136

120-
#[test]
121-
fn test_tick_too_large() {
122-
assert!(to_sqrt_ratio(MAX_TICK + 1).is_none());
123-
assert!(to_sqrt_ratio(i32::MAX).is_none());
137+
mod approximate_sqrt_ratio_to_tick {
138+
use crate::math::tick::{MAX_TICK, MIN_TICK};
139+
140+
use super::super::{approximate_sqrt_ratio_to_tick, to_sqrt_ratio};
141+
142+
#[test]
143+
fn test_tick_examples() {
144+
assert_eq!(approximate_sqrt_ratio_to_tick(to_sqrt_ratio(0).unwrap()), 0,);
145+
assert_eq!(
146+
approximate_sqrt_ratio_to_tick(to_sqrt_ratio(1000000).unwrap()),
147+
1000000,
148+
);
149+
assert_eq!(
150+
approximate_sqrt_ratio_to_tick(to_sqrt_ratio(10000000).unwrap()),
151+
10000000
152+
);
153+
assert_eq!(
154+
approximate_sqrt_ratio_to_tick(to_sqrt_ratio(-1000000).unwrap()),
155+
-1000000,
156+
);
157+
assert_eq!(
158+
approximate_sqrt_ratio_to_tick(to_sqrt_ratio(-10000000).unwrap()),
159+
-10000000,
160+
);
161+
}
162+
163+
#[test]
164+
fn test_min_tick() {
165+
assert_eq!(
166+
approximate_sqrt_ratio_to_tick(to_sqrt_ratio(MIN_TICK).unwrap()),
167+
MIN_TICK,
168+
);
169+
}
170+
171+
#[test]
172+
fn test_max_tick() {
173+
assert_eq!(
174+
approximate_sqrt_ratio_to_tick(to_sqrt_ratio(MAX_TICK).unwrap()),
175+
MAX_TICK,
176+
);
177+
}
124178
}
125179
}

src/math/uint.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
11
uint::construct_uint! {
22
pub struct U256(4);
33
}
4+
5+
pub fn u256_to_float_base_x128(x128: U256) -> f64 {
6+
x128.0[0] as f64 / 340282366920938463463374607431768211456f64
7+
+ (x128.0[1] as f64 / 18446744073709551616f64)
8+
+ x128.0[2] as f64
9+
+ (x128.0[3] as f64 * 18446744073709551616f64)
10+
}

src/quoting/base_pool.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,10 @@ impl Pool for BasePool {
651651
fn min_tick_with_liquidity(&self) -> Option<i32> {
652652
self.sorted_ticks.first().map(|t| t.index)
653653
}
654+
655+
fn is_path_dependent(&self) -> bool {
656+
false
657+
}
654658
}
655659

656660
#[cfg(test)]

src/quoting/full_range_pool.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ pub struct FullRangePool {
5353
pub enum FullRangePoolError {
5454
/// Token0 must be less than token1.
5555
TokenOrderInvalid,
56+
SqrtRatioInvalid,
5657
}
5758

5859
impl FullRangePool {
@@ -61,13 +62,14 @@ impl FullRangePool {
6162
return Err(FullRangePoolError::TokenOrderInvalid);
6263
}
6364

64-
// Ensure sqrt_ratio is within valid bounds
65-
let sqrt_ratio = state.sqrt_ratio.clamp(MIN_SQRT_RATIO, MAX_SQRT_RATIO);
65+
if state.sqrt_ratio < MIN_SQRT_RATIO || state.sqrt_ratio > MAX_SQRT_RATIO {
66+
return Err(FullRangePoolError::SqrtRatioInvalid);
67+
}
6668

6769
Ok(Self {
6870
key,
6971
state: FullRangePoolState {
70-
sqrt_ratio,
72+
sqrt_ratio: state.sqrt_ratio,
7173
liquidity: state.liquidity,
7274
},
7375
})
@@ -220,6 +222,10 @@ impl Pool for FullRangePool {
220222
None
221223
}
222224
}
225+
226+
fn is_path_dependent(&self) -> bool {
227+
false
228+
}
223229
}
224230

225231
#[cfg(test)]

0 commit comments

Comments
 (0)