Skip to content

Commit bf3ba76

Browse files
committed
feat: add 'decimals' for pool
- edit 'max_swap_quantity' based on base asset decimals - refactor
1 parent cef4f93 commit bf3ba76

File tree

4 files changed

+133
-159
lines changed

4 files changed

+133
-159
lines changed

pallets/hybrid-orderbook/src/lib.rs

Lines changed: 96 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -510,14 +510,6 @@ pub mod pallet {
510510
)?;
511511
T::PoolSetupFeeTarget::on_unbalanced(fee);
512512

513-
let mut base_decimals_adjustment = None;
514-
let mut quote_decimals_adjustment = None;
515-
if base_decimals > quote_decimals {
516-
quote_decimals_adjustment = Some(base_decimals - quote_decimals);
517-
} else if base_decimals < quote_decimals {
518-
base_decimals_adjustment = Some(quote_decimals - base_decimals);
519-
}
520-
521513
if T::Assets::should_touch(*base_asset.clone(), &pool_account) {
522514
T::Assets::touch(*base_asset, &pool_account, &sender)?
523515
};
@@ -547,8 +539,8 @@ pub mod pallet {
547539
tick_size,
548540
lot_size,
549541
pool_decimals,
550-
base_decimals_adjustment,
551-
quote_decimals_adjustment,
542+
base_decimals,
543+
quote_decimals,
552544
),
553545
);
554546
Self::deposit_event(Event::PoolCreated {
@@ -923,15 +915,10 @@ pub mod pallet {
923915
quote_asset: &T::AssetKind,
924916
) -> Result<PoolQuery<T::OrderBook, T::Unit>, DispatchError> {
925917
let pool_id = T::PoolLocator::pool_id(base_asset, quote_asset).map_err(|_| Error::<T>::PoolNotFound)?;
926-
let pool_account = T::PoolLocator::pool_address(&base_asset, &quote_asset).map_err(|_| Error::<T>::PoolNotFound)?;
927918
let pool = Pools::<T>::get(&pool_id).ok_or(Error::<T>::PoolNotFound)?;
928-
let base_asset_reserve = Self::get_balance(&pool_account, &base_asset);
929-
let quote_asset_reserve = Self::get_balance(&pool_account, &quote_asset);
930-
let pool_decimals = pool.pool_decimals;
931-
let base_adjustment = pool.base_adjustment;
932-
let quote_adjustment = pool.quote_adjustment;
933-
let pool_price = Self::pool_price(base_asset, pool_decimals, base_adjustment, quote_asset, quote_adjustment)?;
934-
return Ok(pool.to_pool_query(base_asset_reserve, quote_asset_reserve, pool_price));
919+
let (b_r, q_r) = Self::get_reserves(base_asset, quote_asset)?;
920+
let pool_price = Self::pool_price(&pool, &b_r, &q_r)?;
921+
return Ok(pool.to_pool_query(b_r, q_r, pool_price));
935922
}
936923

937924
fn freeze_asset(
@@ -1026,62 +1013,61 @@ pub mod pallet {
10261013
) -> DispatchResult {
10271014
let pool_id = T::PoolLocator::pool_id(base_asset, quote_asset)
10281015
.map_err(|_| Error::<T>::InvalidAssetPair)?;
1029-
let mut pool = Pools::<T>::get(&pool_id).ok_or(Error::<T>::PoolNotFound)?;
1030-
let pool_price = Self::pool_price(
1031-
base_asset,
1032-
pool.pool_decimals,
1033-
pool.base_adjustment,
1034-
quote_asset,
1035-
pool.quote_adjustment,
1036-
)
1037-
.map_err(|_| Error::<T>::ZeroLiquidity)?;
1038-
ensure!(
1039-
pool.is_valid_order_price(order_price),
1040-
Error::<T>::InvalidOrderPrice
1041-
);
1042-
ensure!(
1043-
pool.is_valid_order_quantity(order_quantity),
1044-
Error::<T>::InvalidOrderQuantity
1045-
);
1046-
// Check whether order should be matched
1047-
let should_match_order = if is_bid {
1048-
order_price >= pool_price
1049-
} else {
1050-
order_price <= pool_price
1051-
};
1016+
Pools::<T>::try_mutate(pool_id.clone(), |maybe_pool| -> DispatchResult {
1017+
let mut pool = maybe_pool.take().ok_or(Error::<T>::PoolNotFound)?;
1018+
let (b_r, q_r) = Self::get_reserves(base_asset, quote_asset)?;
1019+
let pool_price = Self::pool_price(
1020+
&pool,
1021+
&b_r,
1022+
&q_r,
1023+
)
1024+
.map_err(|_| Error::<T>::ZeroLiquidity)?;
1025+
ensure!(
1026+
pool.is_valid_order_price(order_price),
1027+
Error::<T>::InvalidOrderPrice
1028+
);
1029+
ensure!(
1030+
pool.is_valid_order_quantity(order_quantity),
1031+
Error::<T>::InvalidOrderQuantity
1032+
);
1033+
// Check whether order should be matched
1034+
let should_match_order = if is_bid {
1035+
order_price >= pool_price
1036+
} else {
1037+
order_price <= pool_price
1038+
};
10521039

1053-
if should_match_order {
1054-
Self::do_match_order(
1055-
is_bid,
1056-
&maker,
1057-
&mut pool,
1058-
&base_asset,
1059-
&quote_asset,
1060-
order_quantity,
1061-
)?;
1062-
} else {
1063-
// place order on orderbook
1064-
Self::do_place_order(
1065-
is_bid,
1066-
&pool_id,
1067-
&mut pool,
1068-
&maker,
1069-
&base_asset,
1070-
&quote_asset,
1040+
if should_match_order {
1041+
Self::do_match_order(
1042+
is_bid,
1043+
&maker,
1044+
&mut pool,
1045+
&base_asset,
1046+
&quote_asset,
1047+
order_quantity,
1048+
)?;
1049+
} else {
1050+
Self::do_place_order(
1051+
is_bid,
1052+
&pool_id,
1053+
&mut pool,
1054+
&maker,
1055+
&base_asset,
1056+
&quote_asset,
1057+
order_price,
1058+
order_quantity,
1059+
)?;
1060+
}
1061+
*maybe_pool = Some(pool);
1062+
Self::deposit_event(Event::<T>::LimitOrder {
1063+
pool_id,
1064+
maker: maker.clone(),
10711065
order_price,
10721066
order_quantity,
1073-
)?;
1074-
}
1075-
// Update pool
1076-
Pools::<T>::insert(&pool_id, pool);
1077-
Self::deposit_event(Event::<T>::LimitOrder {
1078-
pool_id,
1079-
maker: maker.clone(),
1080-
order_price,
1081-
order_quantity,
1082-
is_bid,
1083-
});
1084-
Ok(())
1067+
is_bid,
1068+
});
1069+
Ok(())
1070+
})
10851071
}
10861072

10871073
pub(crate) fn do_place_order(
@@ -1094,12 +1080,16 @@ pub mod pallet {
10941080
price: T::Unit,
10951081
quantity: T::Unit,
10961082
) -> DispatchResult {
1083+
let (p_adj, _, q_adj) = pool.decimal_adjustment();
10971084
if is_bid {
1098-
Self::freeze_asset(maker, quote_asset, (price*quantity).denom(
1099-
pool.pool_decimals.unwrap_or(0) + pool.quote_adjustment.unwrap_or(0)
1100-
))?;
1085+
let freeze_amount = (price*quantity).denom(
1086+
p_adj.unwrap_or(0) + q_adj.unwrap_or(0)
1087+
);
1088+
Self::freeze_asset(maker, quote_asset, freeze_amount)?;
1089+
log::debug!(target: LOG_TARGET, "Freeze {:?} {:?} for bid order", quote_asset, freeze_amount);
11011090
} else {
11021091
Self::freeze_asset(maker, base_asset, quantity)?;
1092+
log::debug!(target: LOG_TARGET, "Freeze {:?} {:?} for ask order", base_asset, quantity);
11031093
}
11041094
let (price, order_id) = pool
11051095
.place_order(is_bid, maker, price, quantity)
@@ -1170,24 +1160,23 @@ pub mod pallet {
11701160
pool.next_bid_order()
11711161
};
11721162
match maybe_next_order {
1173-
Some((orderbook_price, _)) => {
1163+
Some((target_price, _)) => {
11741164
let max_swap_quantity = Self::find_max_swap_quantity(
11751165
is_bid,
1176-
orderbook_price,
1177-
pool.pool_decimals,
1166+
target_price,
1167+
&pool,
11781168
base_asset,
1179-
pool.base_adjustment,
11801169
quote_asset,
1181-
pool.quote_adjustment,
11821170
remain_orders,
11831171
)?;
1184-
log::info!(
1172+
log::debug!(
1173+
target: LOG_TARGET,
11851174
"
11861175
📕 Book Price => {:?},
11871176
🎯 Remain Orders => {:?},
11881177
✅ Max Swap Quantity => {:?}
11891178
",
1190-
orderbook_price, remain_orders, max_swap_quantity
1179+
target_price, remain_orders, max_swap_quantity
11911180
);
11921181
if remain_orders <= max_swap_quantity {
11931182
// All orders filled from pool
@@ -1219,7 +1208,7 @@ pub mod pallet {
12191208
Self::do_fill_book(
12201209
is_bid,
12211210
pool,
1222-
orderbook_price,
1211+
target_price,
12231212
&mut remain_orders,
12241213
&mut filled_orders,
12251214
)?;
@@ -1297,9 +1286,7 @@ pub mod pallet {
12971286
})
12981287
});
12991288
*order_quantity -= filled;
1300-
if_std! {
1301-
println!("🤑 {:?} of orders filled from book for {:?}. {:?} orders left", filled, price, order_quantity);
1302-
}
1289+
log::debug!(target: LOG_TARGET, "🤑 {:?} of orders filled from book for {:?}. {:?} orders left", filled, price, order_quantity);
13031290
Ok(())
13041291
}
13051292

@@ -1309,18 +1296,16 @@ pub mod pallet {
13091296
///
13101297
/// 1 * quote_reserve / base_reserve
13111298
pub fn pool_price(
1312-
base_asset: &T::AssetKind,
1313-
pool_decimals: Option<u8>,
1314-
base_decimals_adjustment: Option<u8>,
1315-
quote_asset: &T::AssetKind,
1316-
quote_decimals_adjustment: Option<u8>,
1299+
pool: &Pool<T>,
1300+
base_reserve: &T::Unit,
1301+
quote_reserve: &T::Unit,
13171302
) -> Result<T::Unit, Error<T>> {
1318-
let (base_reserve, quote_reserve) = Self::get_reserves(base_asset, quote_asset)?;
1319-
let base_norm = base_reserve.normalize(base_decimals_adjustment);
1320-
let quote_norm = quote_reserve.normalize(quote_decimals_adjustment);
1303+
let (p_adj, b_adj, q_adj) = pool.decimal_adjustment();
1304+
let base_norm = base_reserve.normalize(b_adj);
1305+
let quote_norm = quote_reserve.normalize(q_adj);
13211306
let amount: T::Unit = One::one();
13221307
let pool_price = Self::quote(
1323-
&amount.normalize(pool_decimals),
1308+
&amount.normalize(p_adj),
13241309
&base_norm,
13251310
&quote_norm,
13261311
)?;
@@ -1336,16 +1321,15 @@ pub mod pallet {
13361321
pub(crate) fn find_max_swap_quantity(
13371322
is_bid: bool,
13381323
target: T::Unit,
1339-
pool_decimals: Option<u8>,
1324+
pool: &Pool<T>,
13401325
base_asset: &T::AssetKind,
1341-
base_decimals_adjustment: Option<u8>,
13421326
quote_asset: &T::AssetKind,
1343-
quote_decimals_adjustment: Option<u8>,
1344-
order_quantity: T::Unit,
1327+
remain_orders: T::Unit,
13451328
) -> Result<T::Unit, Error<T>> {
13461329
let (b_r, q_r) = Self::get_reserves(base_asset, quote_asset)?;
1330+
let (p_adj, b_adj, q_adj) = pool.decimal_adjustment();
13471331
let mut min: T::Unit = Zero::zero();
1348-
let mut max: T::Unit = order_quantity;
1332+
let mut max: T::Unit = remain_orders;
13491333
let mut swap_quantity: T::Unit = Zero::zero();
13501334
while min < max {
13511335
let mid = (min + max + One::one()) / 2u32.into();
@@ -1354,37 +1338,38 @@ pub mod pallet {
13541338
// If it is bid order, get `amount_in` of `quote_asset` with given `amount_out`
13551339
// of `base_asset` quantity of `base_asset`
13561340
let amount_in = Self::get_amount_in(&mid, &q_r, &b_r)?;
1357-
log::info!("Bid order: amount_in => {:?}, K = {:?}", amount_in, ((b_r-mid)*(q_r+amount_in)));
1341+
log::debug!(target: LOG_TARGET, "Bid order: amount_in => {:?}", amount_in);
13581342
Self::quote(
1359-
&unit.normalize(pool_decimals),
1360-
&(b_r - mid).normalize(base_decimals_adjustment),
1361-
&(q_r + amount_in).normalize(quote_decimals_adjustment),
1343+
&unit.normalize(p_adj),
1344+
&(b_r - mid).normalize(b_adj),
1345+
&(q_r + amount_in).normalize(q_adj),
13621346
)?
13631347
} else {
13641348
// If it is ask order, get `amount_out` of `quote_asset` with given `amount_in`
13651349
// of `base_asset`
13661350
let amount_out = Self::get_amount_out(&mid, &b_r, &q_r)?;
1367-
log::info!("Ask order: amount_out => {:?}", amount_out);
1351+
log::debug!(target: LOG_TARGET, "Ask order: amount_out => {:?}", amount_out);
13681352
Self::quote(
1369-
&unit.normalize(pool_decimals),
1370-
&(b_r + mid).normalize(base_decimals_adjustment),
1371-
&(q_r - amount_out).normalize(quote_decimals_adjustment),
1353+
&unit.normalize(p_adj),
1354+
&(b_r + mid).normalize(b_adj),
1355+
&(q_r - amount_out).normalize(q_adj),
13721356
)?
13731357
};
1374-
log::info!("Pool Price => {:?}, Mid => {:?}", pool_price, mid);
1358+
log::debug!(target: LOG_TARGET, "Pool Price => {:?}, Mid => {:?}", pool_price, mid);
13751359
// Return immediately when pool price after swap is equal to orderbook price
13761360
if pool_price == target {
13771361
return Ok(mid);
13781362
}
1379-
// Narrow it down if it is not
1363+
// Narrow it down if it is not equal to target price
1364+
let one: T::Unit = One::one();
13801365
if pool_price < target {
13811366
// 'pool_price' should become bigger
13821367
if is_bid {
13831368
// If it is bid order, more base assets should be swapped out
1384-
min = mid + One::one();
1369+
min = mid + one.normalize(Some(pool.base_decimals));
13851370
} else {
13861371
// If it is ask order, less base assets should be swapped in
1387-
max = mid - One::one();
1372+
max = mid - one.normalize(Some(pool.base_decimals));
13881373
}
13891374
swap_quantity = mid;
13901375
} else {
@@ -2068,9 +2053,6 @@ sp_api::decl_runtime_apis! {
20682053
/// Returns the size of the liquidity pool for the given asset pair.
20692054
fn get_reserves(asset1: AssetId, asset2: AssetId) -> Option<(Balance, Balance)>;
20702055

2071-
/// Returns the price of the given asset pair.
2072-
fn get_pool_price(base: AssetId, pool_decimals: Option<u8>, base_decimal_diff: Option<u8>, quote: AssetId, quote_decimal_diff: Option<u8>) -> Option<Balance>;
2073-
20742056
/// Returns query of the `pool`
20752057
fn get_pool_query(base: AssetId, quote: AssetId) -> Option<PoolQuery<Orderbook, Balance>>;
20762058
}

0 commit comments

Comments
 (0)