Skip to content

Commit 154ac57

Browse files
authored
Merge pull request #1468 from opentensor/sasha/feat/uniswapv3-lp
Sasha/feat/uniswapv3 lp
2 parents f5a4478 + 6b0f6e6 commit 154ac57

File tree

2 files changed

+242
-144
lines changed

2 files changed

+242
-144
lines changed

pallets/swap/src/lib.rs

+75-99
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use safe_math::*;
99
use sp_arithmetic::helpers_128bit::sqrt;
1010
use substrate_fixed::types::U64F64;
1111

12-
use self::tick::{Tick, TickIndex};
12+
use self::tick::{Layer, Tick, TickIndex, TickIndexBitmap};
1313

1414
pub mod pallet;
1515
mod tick;
@@ -1040,7 +1040,7 @@ where
10401040
/// Get fees above a tick
10411041
///
10421042
fn get_fees_above(&mut self, tick_index: TickIndex, quote: bool) -> U64F64 {
1043-
let maybe_tick_index = tick_index.find_closest_lower_active(&self.state_ops);
1043+
let maybe_tick_index = self.find_closest_lower_active_tick_index(tick_index);
10441044
let current_tick = self.get_current_tick_index();
10451045

10461046
if let Some(tick_index) = maybe_tick_index {
@@ -1072,7 +1072,7 @@ where
10721072

10731073
/// Get fees below a tick
10741074
fn get_fees_below(&mut self, tick_index: TickIndex, quote: bool) -> U64F64 {
1075-
let maybe_tick_index = tick_index.find_closest_lower_active(&self.state_ops);
1075+
let maybe_tick_index = self.find_closest_lower_active_tick_index(tick_index);
10761076
let current_tick = self.get_current_tick_index();
10771077

10781078
if let Some(tick_index) = maybe_tick_index {
@@ -1115,46 +1115,38 @@ where
11151115
/// Deletion: 2 reads, 1-3 writes
11161116
///
11171117
1118-
// Addresses an index as (word, bit)
1119-
fn index_to_address(index: u32) -> (u32, u32) {
1120-
let word: u32 = index.safe_div(128);
1121-
let bit: u32 = index.checked_rem(128).unwrap_or_default();
1122-
(word, bit)
1123-
}
1124-
1125-
// Reconstructs an index from address in lower level
1126-
fn address_to_index(word: u32, bit: u32) -> u32 {
1127-
word.saturating_mul(128).saturating_add(bit)
1128-
}
1118+
// Use TickIndexBitmap::layer_to_index instead
11291119

11301120
pub fn insert_active_tick(&mut self, index: TickIndex) {
11311121
// Check the range
11321122
if (index < TickIndex::MIN) || (index > TickIndex::MAX) {
11331123
return;
11341124
}
11351125

1136-
// Convert the tick index value to an offset_index for the tree representation
1137-
// to avoid working with the sign bit.
1138-
let offset_index = (index.get() + TickIndex::OFFSET.get()) as u32;
1139-
1140-
// Calculate index in each layer
1141-
let (layer2_word, layer2_bit) = Self::index_to_address(offset_index);
1142-
let (layer1_word, layer1_bit) = Self::index_to_address(layer2_word);
1143-
let (layer0_word, layer0_bit) = Self::index_to_address(layer1_word);
1126+
// Convert to bitmap representation
1127+
let bitmap = TickIndexBitmap::from(index);
11441128

11451129
// Update layer words
1146-
let mut word0_value = self.state_ops.get_layer0_word(layer0_word);
1147-
let mut word1_value = self.state_ops.get_layer1_word(layer1_word);
1148-
let mut word2_value = self.state_ops.get_layer2_word(layer2_word);
1149-
1150-
let bit: u128 = 1;
1151-
word0_value = word0_value | bit.wrapping_shl(layer0_bit);
1152-
word1_value = word1_value | bit.wrapping_shl(layer1_bit);
1153-
word2_value = word2_value | bit.wrapping_shl(layer2_bit);
1154-
1155-
self.state_ops.set_layer0_word(layer0_word, word0_value);
1156-
self.state_ops.set_layer1_word(layer1_word, word1_value);
1157-
self.state_ops.set_layer2_word(layer2_word, word2_value);
1130+
let mut word0_value = self.state_ops.get_layer0_word(bitmap.word_at(Layer::Top));
1131+
let mut word1_value = self
1132+
.state_ops
1133+
.get_layer1_word(bitmap.word_at(Layer::Middle));
1134+
let mut word2_value = self
1135+
.state_ops
1136+
.get_layer2_word(bitmap.word_at(Layer::Bottom));
1137+
1138+
// Set bits in each layer
1139+
word0_value |= bitmap.bit_mask(Layer::Top);
1140+
word1_value |= bitmap.bit_mask(Layer::Middle);
1141+
word2_value |= bitmap.bit_mask(Layer::Bottom);
1142+
1143+
// Update the storage
1144+
self.state_ops
1145+
.set_layer0_word(bitmap.word_at(Layer::Top), word0_value);
1146+
self.state_ops
1147+
.set_layer1_word(bitmap.word_at(Layer::Middle), word1_value);
1148+
self.state_ops
1149+
.set_layer2_word(bitmap.word_at(Layer::Bottom), word2_value);
11581150
}
11591151

11601152
pub fn remove_active_tick(&mut self, index: TickIndex) {
@@ -1163,58 +1155,34 @@ where
11631155
return;
11641156
}
11651157

1166-
// Convert the tick index value to an offset_index for the tree representation
1167-
// to avoid working with the sign bit.
1168-
let offset_index = (index.get() + TickIndex::OFFSET.get()) as u32;
1169-
1170-
// Calculate index in each layer
1171-
let (layer2_word, layer2_bit) = Self::index_to_address(offset_index);
1172-
let (layer1_word, layer1_bit) = Self::index_to_address(layer2_word);
1173-
let (layer0_word, layer0_bit) = Self::index_to_address(layer1_word);
1158+
// Convert to bitmap representation
1159+
let bitmap = TickIndexBitmap::from(index);
11741160

11751161
// Update layer words
1176-
let mut word0_value = self.state_ops.get_layer0_word(layer0_word);
1177-
let mut word1_value = self.state_ops.get_layer1_word(layer1_word);
1178-
let mut word2_value = self.state_ops.get_layer2_word(layer2_word);
1162+
let mut word0_value = self.state_ops.get_layer0_word(bitmap.word_at(Layer::Top));
1163+
let mut word1_value = self
1164+
.state_ops
1165+
.get_layer1_word(bitmap.word_at(Layer::Middle));
1166+
let mut word2_value = self
1167+
.state_ops
1168+
.get_layer2_word(bitmap.word_at(Layer::Bottom));
11791169

11801170
// Turn the bit off (& !bit) and save as needed
1181-
let bit: u128 = 1;
1182-
word2_value = word2_value & !bit.wrapping_shl(layer2_bit);
1183-
self.state_ops.set_layer2_word(layer2_word, word2_value);
1171+
word2_value &= !bitmap.bit_mask(Layer::Bottom);
1172+
self.state_ops
1173+
.set_layer2_word(bitmap.word_at(Layer::Bottom), word2_value);
1174+
11841175
if word2_value == 0 {
1185-
word1_value = word1_value & !bit.wrapping_shl(layer1_bit);
1186-
self.state_ops.set_layer1_word(layer1_word, word1_value);
1187-
}
1188-
if word1_value == 0 {
1189-
word0_value = word0_value & !bit.wrapping_shl(layer0_bit);
1190-
self.state_ops.set_layer0_word(layer0_word, word0_value);
1176+
word1_value &= !bitmap.bit_mask(Layer::Middle);
1177+
self.state_ops
1178+
.set_layer1_word(bitmap.word_at(Layer::Middle), word1_value);
11911179
}
1192-
}
11931180

1194-
// Finds the closest active bit and, if active bit exactly matches bit, then the next one
1195-
// Exact match: return Some([next, bit])
1196-
// Non-exact match: return Some([next])
1197-
// No match: return None
1198-
fn find_closest_active_bit_candidates(&self, word: u128, bit: u32, lower: bool) -> Vec<u32> {
1199-
let mut result = vec![];
1200-
let mut mask: u128 = 1_u128.wrapping_shl(bit);
1201-
let mut layer0_active_bit: u32 = bit;
1202-
while mask > 0 {
1203-
if mask & word != 0 {
1204-
result.push(layer0_active_bit);
1205-
if layer0_active_bit != bit {
1206-
break;
1207-
}
1208-
}
1209-
mask = if lower {
1210-
layer0_active_bit = layer0_active_bit.saturating_sub(1);
1211-
mask.wrapping_shr(1)
1212-
} else {
1213-
layer0_active_bit = layer0_active_bit.saturating_add(1);
1214-
mask.wrapping_shl(1)
1215-
};
1181+
if word1_value == 0 {
1182+
word0_value &= !bitmap.bit_mask(Layer::Top);
1183+
self.state_ops
1184+
.set_layer0_word(bitmap.word_at(Layer::Top), word0_value);
12161185
}
1217-
result
12181186
}
12191187

12201188
pub fn find_closest_active_tick_index(
@@ -1227,28 +1195,31 @@ where
12271195
return None;
12281196
}
12291197

1230-
// Convert the tick index value to an offset_index for the tree representation
1231-
// to avoid working with the sign bit.
1232-
let offset_index = (index.get() + TickIndex::OFFSET.get()) as u32;
1198+
// Convert to bitmap representation
1199+
let bitmap = TickIndexBitmap::from(index);
12331200
let mut found = false;
12341201
let mut result: u32 = 0;
12351202

1236-
// Calculate index in each layer
1237-
let (layer2_word, layer2_bit) = Self::index_to_address(offset_index);
1238-
let (layer1_word, layer1_bit) = Self::index_to_address(layer2_word);
1239-
let (layer0_word, layer0_bit) = Self::index_to_address(layer1_word);
1203+
// Layer positions from bitmap
1204+
let layer0_word = bitmap.word_at(Layer::Top);
1205+
let layer0_bit = bitmap.bit_at(Layer::Top);
1206+
let layer1_word = bitmap.word_at(Layer::Middle);
1207+
let layer1_bit = bitmap.bit_at(Layer::Middle);
1208+
let layer2_word = bitmap.word_at(Layer::Bottom);
1209+
let layer2_bit = bitmap.bit_at(Layer::Bottom);
12401210

12411211
// Find the closest active bits in layer 0, then 1, then 2
12421212

12431213
///////////////
12441214
// Level 0
12451215
let word0 = self.state_ops.get_layer0_word(layer0_word);
1246-
let closest_bits_l0 = self.find_closest_active_bit_candidates(word0, layer0_bit, lower);
1216+
let closest_bits_l0 =
1217+
TickIndexBitmap::find_closest_active_bit_candidates(word0, layer0_bit, lower);
12471218

12481219
closest_bits_l0.iter().for_each(|&closest_bit_l0| {
12491220
///////////////
12501221
// Level 1
1251-
let word1_index = Self::address_to_index(0, closest_bit_l0);
1222+
let word1_index = TickIndexBitmap::layer_to_index(0, closest_bit_l0);
12521223

12531224
// Layer 1 words are different, shift the bit to the word edge
12541225
let start_from_l1_bit = if word1_index < layer1_word {
@@ -1260,12 +1231,15 @@ where
12601231
};
12611232
let word1_value = self.state_ops.get_layer1_word(word1_index);
12621233

1263-
let closest_bits_l1 =
1264-
self.find_closest_active_bit_candidates(word1_value, start_from_l1_bit, lower);
1234+
let closest_bits_l1 = TickIndexBitmap::find_closest_active_bit_candidates(
1235+
word1_value,
1236+
start_from_l1_bit,
1237+
lower,
1238+
);
12651239
closest_bits_l1.iter().for_each(|&closest_bit_l1| {
12661240
///////////////
12671241
// Level 2
1268-
let word2_index = Self::address_to_index(word1_index, closest_bit_l1);
1242+
let word2_index = TickIndexBitmap::layer_to_index(word1_index, closest_bit_l1);
12691243

12701244
// Layer 2 words are different, shift the bit to the word edge
12711245
let start_from_l2_bit = if word2_index < layer2_word {
@@ -1277,13 +1251,16 @@ where
12771251
};
12781252

12791253
let word2_value = self.state_ops.get_layer2_word(word2_index);
1280-
let closest_bits_l2 =
1281-
self.find_closest_active_bit_candidates(word2_value, start_from_l2_bit, lower);
1254+
let closest_bits_l2 = TickIndexBitmap::find_closest_active_bit_candidates(
1255+
word2_value,
1256+
start_from_l2_bit,
1257+
lower,
1258+
);
12821259

12831260
if closest_bits_l2.len() > 0 {
12841261
// The active tick is found, restore its full index and return
12851262
let offset_found_index =
1286-
Self::address_to_index(word2_index, closest_bits_l2[0]);
1263+
TickIndexBitmap::layer_to_index(word2_index, closest_bits_l2[0]);
12871264

12881265
if lower {
12891266
if (offset_found_index > result) || (!found) {
@@ -1300,13 +1277,12 @@ where
13001277
});
13011278
});
13021279

1303-
if found {
1304-
// Convert the tree offset_index back to a tick index value
1305-
let tick_value = (result as i32).saturating_sub(TickIndex::OFFSET.get());
1306-
Some(TickIndex::new_unchecked(tick_value))
1307-
} else {
1308-
None
1280+
if !found {
1281+
return None;
13091282
}
1283+
1284+
// Convert the result offset_index back to a tick index
1285+
TickIndex::from_offset_index(result).ok()
13101286
}
13111287

13121288
pub fn find_closest_lower_active_tick_index(&self, index: TickIndex) -> Option<TickIndex> {

0 commit comments

Comments
 (0)