@@ -77,7 +77,7 @@ use frame_support::{
7777 ensure,
7878 storage:: { with_storage_layer, with_transaction} ,
7979 traits:: {
80- fungibles:: { Balanced , Create , Credit , Inspect , Mutate , MutateFreeze , metadata :: Inspect as InspectMetadata } ,
80+ fungibles:: { Balanced , Create , Credit , Inspect , Mutate , MutateFreeze } ,
8181 tokens:: {
8282 AssetId , Balance ,
8383 Fortitude :: Polite ,
@@ -150,8 +150,7 @@ pub mod pallet {
150150 type Assets : Inspect < Self :: AccountId , AssetId = Self :: AssetKind , Balance = Self :: Unit >
151151 + Mutate < Self :: AccountId >
152152 + AccountTouch < Self :: AssetKind , Self :: AccountId , Balance = Self :: Unit >
153- + Balanced < Self :: AccountId >
154- + InspectMetadata < Self :: AccountId > ;
153+ + Balanced < Self :: AccountId > ;
155154
156155 type AssetsFreezer : MutateFreeze <
157156 Self :: AccountId ,
@@ -216,7 +215,7 @@ pub mod pallet {
216215 type MaxSwapPathLength : Get < u32 > ;
217216
218217 #[ pallet:: constant]
219- type StandardDecimals : Get < u8 > ;
218+ type StandardDecimals : Get < u8 > ;
220219
221220 /// The pallet's id, used for deriving its sovereign account ID.
222221 #[ pallet:: constant]
@@ -454,6 +453,10 @@ pub mod pallet {
454453 ConversionError ,
455454 /// Operation can't be done
456455 NoOps ,
456+ /// Invalid tick size
457+ InvalidTickSize ,
458+ /// Invalid lot size
459+ InvalidLotSize ,
457460 }
458461
459462 #[ pallet:: hooks]
@@ -478,14 +481,18 @@ pub mod pallet {
478481 pub fn create_pool (
479482 origin : OriginFor < T > ,
480483 base_asset : Box < T :: AssetKind > ,
484+ base_decimals : u8 ,
481485 quote_asset : Box < T :: AssetKind > ,
486+ quote_decimals : u8 ,
482487 taker_fee_rate : Permill ,
483488 tick_size : T :: Unit ,
484489 lot_size : T :: Unit ,
490+ pool_decimals : u8 ,
485491 ) -> DispatchResult {
486492 let sender = ensure_signed ( origin) ?;
487493 ensure ! ( base_asset != quote_asset, Error :: <T >:: InvalidAssetPair ) ;
488-
494+ ensure ! ( tick_size > Zero :: zero( ) , Error :: <T >:: InvalidTickSize ) ;
495+ ensure ! ( lot_size > Zero :: zero( ) , Error :: <T >:: InvalidLotSize ) ;
489496 // prepare pool_id
490497 let pool_id = T :: PoolLocator :: pool_id ( & base_asset, & quote_asset)
491498 . map_err ( |_| Error :: < T > :: InvalidAssetPair ) ?;
@@ -503,9 +510,13 @@ pub mod pallet {
503510 ) ?;
504511 T :: PoolSetupFeeTarget :: on_unbalanced ( fee) ;
505512
506-
507- let b_decimals_adjustment = Self :: get_decimals ( & base_asset) ;
508- let q_decimals_adjustment = Self :: get_decimals ( & quote_asset) ;
513+ let mut base_decimals_adjustment = None ;
514+ let mut quote_decimals_adjustment = None ;
515+ if base_decimals > quote_decimals {
516+ base_decimals_adjustment = Some ( base_decimals - quote_decimals) ;
517+ } else if base_decimals < quote_decimals {
518+ quote_decimals_adjustment = Some ( quote_decimals - base_decimals) ;
519+ }
509520
510521 if T :: Assets :: should_touch ( * base_asset. clone ( ) , & pool_account) {
511522 T :: Assets :: touch ( * base_asset, & pool_account, & sender) ?
@@ -535,8 +546,9 @@ pub mod pallet {
535546 taker_fee_rate,
536547 tick_size,
537548 lot_size,
538- b_decimals_adjustment,
539- q_decimals_adjustment,
549+ pool_decimals,
550+ base_decimals_adjustment,
551+ quote_decimals_adjustment,
540552 ) ,
541553 ) ;
542554 Self :: deposit_event ( Event :: PoolCreated {
@@ -901,27 +913,24 @@ pub mod pallet {
901913 }
902914
903915 impl < T : Config > Pallet < T > {
904- fn account_id ( ) -> T :: AccountId {
916+ fn _account_id ( ) -> T :: AccountId {
905917 T :: PalletId :: get ( ) . into_account_truncating ( )
906918 }
907919
908- fn get_pool (
920+ pub fn get_pool_query (
909921 base_asset : & T :: AssetKind ,
910922 quote_asset : & T :: AssetKind ,
911- ) -> Result < Pool < T > , DispatchError > {
912- let pool_id = T :: PoolLocator :: pool_id ( base_asset, quote_asset)
913- . map_err ( |_| Error :: < T > :: InvalidAssetPair ) ?;
914- Pools :: < T > :: get ( & pool_id) . ok_or ( Error :: < T > :: PoolNotFound . into ( ) )
915- }
916-
917- fn get_decimals ( asset_kind : & T :: AssetKind ) -> u8 {
918- let asset_decimals = T :: Assets :: decimals ( asset_kind. clone ( ) ) ;
919- let n_decimals = if T :: StandardDecimals :: get ( ) > asset_decimals {
920- T :: StandardDecimals :: get ( )
921- } else {
922- asset_decimals - T :: StandardDecimals :: get ( )
923- } ;
924- n_decimals
923+ ) -> Result < PoolQuery < T :: OrderBook , T :: Unit > , DispatchError > {
924+ let pool_id = T :: PoolLocator :: pool_id ( base_asset, quote_asset) . map_err ( |_| Error :: < T > :: PoolNotFound ) ?;
925+ let pool_account = T :: PoolLocator :: pool_address ( & base_asset, & quote_asset) . map_err ( |_| Error :: < T > :: PoolNotFound ) ?;
926+ let pool = Pools :: < T > :: get ( & pool_id) . ok_or ( Error :: < T > :: PoolNotFound ) ?;
927+ let base_asset_reserve = Self :: get_balance ( & pool_account, & base_asset) ;
928+ let quote_asset_reserve = Self :: get_balance ( & pool_account, & quote_asset) ;
929+ let pool_decimals = pool. pool_decimals ;
930+ let base_adjustment = pool. base_adjustment ;
931+ let quote_adjustment = pool. quote_adjustment ;
932+ let pool_price = Self :: pool_price ( base_asset, pool_decimals, base_adjustment, quote_asset, quote_adjustment) ?;
933+ return Ok ( pool. to_pool_query ( base_asset_reserve, quote_asset_reserve, pool_price) ) ;
925934 }
926935
927936 fn freeze_asset (
@@ -981,16 +990,19 @@ pub mod pallet {
981990 quote_asset : & T :: AssetKind ,
982991 quantity : T :: Unit ,
983992 ) -> DispatchResult {
984- // Order quantity should be greater than 0
985993 ensure ! ( quantity > Zero :: zero( ) , Error :: <T >:: WrongDesiredAmount ) ;
986994 let pool_id = T :: PoolLocator :: pool_id ( base_asset, quote_asset)
987995 . map_err ( |_| Error :: < T > :: InvalidAssetPair ) ?;
988- let mut pool = Pools :: < T > :: get ( & pool_id) . ok_or ( Error :: < T > :: PoolNotFound ) ?;
989- Self :: do_match_order ( is_bid, taker, & mut pool, base_asset, quote_asset, quantity) ?;
990- Pools :: < T > :: insert ( pool_id, pool) ;
991- Self :: deposit_event ( Event :: < T > :: MarketOrder {
992- taker : taker. clone ( ) ,
993- } ) ;
996+ Pools :: < T > :: try_mutate_exists ( pool_id, |maybe_pool| -> DispatchResult {
997+ let mut pool = maybe_pool. take ( ) . ok_or ( Error :: < T > :: PoolNotFound ) ?;
998+ ensure ! ( pool. is_valid_order_quantity( quantity) , Error :: <T >:: InvalidOrderQuantity ) ;
999+ Self :: do_match_order ( is_bid, taker, & mut pool, base_asset, quote_asset, quantity) ?;
1000+ * maybe_pool = Some ( pool) ;
1001+ Self :: deposit_event ( Event :: < T > :: MarketOrder {
1002+ taker : taker. clone ( ) ,
1003+ } ) ;
1004+ Ok ( ( ) )
1005+ } ) ?;
9941006 Ok ( ( ) )
9951007 }
9961008
@@ -1011,28 +1023,25 @@ pub mod pallet {
10111023 base_asset : & T :: AssetKind ,
10121024 quote_asset : & T :: AssetKind ,
10131025 ) -> DispatchResult {
1014- // Validity check
10151026 let pool_id = T :: PoolLocator :: pool_id ( base_asset, quote_asset)
10161027 . map_err ( |_| Error :: < T > :: InvalidAssetPair ) ?;
10171028 let mut pool = Pools :: < T > :: get ( & pool_id) . ok_or ( Error :: < T > :: PoolNotFound ) ?;
1018- let pool_price =
1019- Self :: pool_price ( base_asset, pool . base_adjustment , quote_asset , pool . quote_adjustment ) . map_err ( |_| Error :: < T > :: ZeroLiquidity ) ? ;
1020- ensure ! (
1021- order_quantity > Zero :: zero ( ) ,
1022- Error :: < T > :: WrongDesiredAmount
1023- ) ;
1024- ensure ! ( order_price > Zero :: zero ( ) , Error :: < T > :: InvalidOrderPrice ) ;
1025- // Price of order could only be set to the multiple of `tick_size`
1029+ let pool_price = Self :: pool_price (
1030+ base_asset,
1031+ pool . pool_decimals ,
1032+ pool . base_adjustment ,
1033+ quote_asset ,
1034+ pool . quote_adjustment ,
1035+ )
1036+ . map_err ( |_| Error :: < T > :: ZeroLiquidity ) ? ;
10261037 ensure ! (
1027- order_price % pool. tick_size == Zero :: zero ( ) ,
1038+ pool. is_valid_order_price ( order_price ) ,
10281039 Error :: <T >:: InvalidOrderPrice
10291040 ) ;
1030- // Quantity of order could only be set to the multiple of `lot_size`
10311041 ensure ! (
1032- order_quantity >= pool. lot_size && order_quantity % pool . lot_size == Zero :: zero ( ) ,
1042+ pool. is_valid_order_quantity ( order_quantity ) ,
10331043 Error :: <T >:: InvalidOrderQuantity
10341044 ) ;
1035-
10361045 // Check whether order should be matched
10371046 let should_match_order = if is_bid {
10381047 order_price >= pool_price
@@ -1164,6 +1173,7 @@ pub mod pallet {
11641173 let max_swap_quantity = Self :: find_max_swap_quantity (
11651174 is_bid,
11661175 orderbook_price,
1176+ pool. pool_decimals ,
11671177 base_asset,
11681178 pool. base_adjustment ,
11691179 quote_asset,
@@ -1307,15 +1317,19 @@ pub mod pallet {
13071317 /// 1 * quote_reserve / base_reserve
13081318 pub fn pool_price (
13091319 base_asset : & T :: AssetKind ,
1310- base_decimals_adjustment : u8 ,
1320+ pool_decimals : Option < u8 > ,
1321+ base_decimals_adjustment : Option < u8 > ,
13111322 quote_asset : & T :: AssetKind ,
1312- quote_decimals_adjustment : u8 ,
1323+ quote_decimals_adjustment : Option < u8 > ,
13131324 ) -> Result < T :: Unit , Error < T > > {
13141325 let ( base_reserve, quote_reserve) = Self :: get_reserves ( base_asset, quote_asset) ?;
1315- Self :: quote (
1316- & One :: one ( ) ,
1317- & base_reserve. normalize ( base_decimals_adjustment) ,
1318- & quote_reserve. normalize ( quote_decimals_adjustment)
1326+ Ok (
1327+ Self :: quote (
1328+ & One :: one ( ) ,
1329+ & base_reserve. normalize ( base_decimals_adjustment) ,
1330+ & quote_reserve. normalize ( quote_decimals_adjustment) ,
1331+ ) ?
1332+ . normalize ( pool_decimals)
13191333 )
13201334 }
13211335
@@ -1328,10 +1342,11 @@ pub mod pallet {
13281342 pub ( crate ) fn find_max_swap_quantity (
13291343 is_bid : bool ,
13301344 target : T :: Unit ,
1345+ pool_decimals : Option < u8 > ,
13311346 base_asset : & T :: AssetKind ,
1332- base_decimals_adjustment : u8 ,
1347+ base_decimals_adjustment : Option < u8 > ,
13331348 quote_asset : & T :: AssetKind ,
1334- quote_decimals_adjustment : u8 ,
1349+ quote_decimals_adjustment : Option < u8 > ,
13351350 order_quantity : T :: Unit ,
13361351 ) -> Result < T :: Unit , Error < T > > {
13371352 let ( b_r, q_r) = Self :: get_reserves ( base_asset, quote_asset) ?;
@@ -1345,13 +1360,23 @@ pub mod pallet {
13451360 // of `base_asset` quantity of `base_asset`
13461361 let amount_in = Self :: get_amount_in ( & mid, & q_r, & b_r) ?;
13471362 if_std ! { println!( "Bid order: amount_in => {:?}, K = {:?}" , amount_in, ( ( b_r-mid) * ( q_r+amount_in) ) ) ; }
1348- Self :: quote ( & One :: one ( ) , & ( b_r - mid) . normalize ( base_decimals_adjustment) , & ( q_r + amount_in) . normalize ( quote_decimals_adjustment) ) ?
1363+ Self :: quote (
1364+ & One :: one ( ) ,
1365+ & ( b_r - mid) . normalize ( base_decimals_adjustment) ,
1366+ & ( q_r + amount_in) . normalize ( quote_decimals_adjustment) ,
1367+ ) ?
1368+ . normalize ( pool_decimals)
13491369 } else {
13501370 // If it is ask order, get `amount_out` of `quote_asset` with given `amount_in`
13511371 // of `base_asset`
13521372 let amount_out = Self :: get_amount_out ( & mid, & b_r, & q_r) ?;
13531373 if_std ! { println!( "Ask order: amount_out => {:?}" , amount_out) ; }
1354- Self :: quote ( & One :: one ( ) , & ( b_r + mid) . normalize ( base_decimals_adjustment) , & ( q_r - amount_out) . normalize ( quote_decimals_adjustment) ) ?
1374+ Self :: quote (
1375+ & One :: one ( ) ,
1376+ & ( b_r + mid) . normalize ( base_decimals_adjustment) ,
1377+ & ( q_r - amount_out) . normalize ( quote_decimals_adjustment) ,
1378+ ) ?
1379+ . normalize ( pool_decimals)
13551380 } ;
13561381 if_std ! {
13571382 println!( "Pool Price => {:?}, Mid => {:?}" , pool_price, mid) ;
@@ -2021,10 +2046,11 @@ pub mod pallet {
20212046sp_api:: decl_runtime_apis! {
20222047 /// This runtime api allows people to query the size of the liquidity pools
20232048 /// and quote prices for swaps.
2024- pub trait HybridOrderbookApi <Balance , AssetId >
2049+ pub trait HybridOrderbookApi <Balance , AssetId , Orderbook >
20252050 where
20262051 Balance : frame_support:: traits:: tokens:: Balance + MaybeDisplay ,
20272052 AssetId : Codec ,
2053+ Orderbook : Codec ,
20282054 {
20292055 /// Provides a quote for [`Pallet::swap_tokens_for_exact_tokens`].
20302056 ///
@@ -2052,7 +2078,10 @@ sp_api::decl_runtime_apis! {
20522078 fn get_reserves( asset1: AssetId , asset2: AssetId ) -> Option <( Balance , Balance ) >;
20532079
20542080 /// Returns the price of the given asset pair.
2055- fn get_pool_price( base: AssetId , quote: AssetId ) -> Option <Balance >;
2081+ fn get_pool_price( base: AssetId , pool_decimals: Option <u8 >, base_decimal_diff: Option <u8 >, quote: AssetId , quote_decimal_diff: Option <u8 >) -> Option <Balance >;
2082+
2083+ /// Returns query of the `pool`
2084+ fn get_pool_query( base: AssetId , quote: AssetId ) -> Option <PoolQuery <Orderbook , Balance >>;
20562085 }
20572086}
20582087
0 commit comments