From f9bf5e5c493aea7a3873f6e13c93295e7c84af90 Mon Sep 17 00:00:00 2001 From: Alastair Holmes <42404303+AlastairHolmes@users.noreply.github.com> Date: Mon, 23 Oct 2023 18:03:01 +0200 Subject: [PATCH] feat: auto sweep earnings and accurate free balance rpc (PRO-856) (#4145) feat: auto sweep earnings and accurate free balance rpc --- api/lib/src/lp.rs | 16 +- state-chain/pallets/cf-lp/src/lib.rs | 5 +- state-chain/pallets/cf-lp/src/mock.rs | 1 + state-chain/pallets/cf-lp/src/weights.rs | 248 +++++++++++--------- state-chain/pallets/cf-pools/src/lib.rs | 70 +++++- state-chain/pallets/cf-pools/src/weights.rs | 156 +++++++----- state-chain/runtime/src/lib.rs | 7 +- state-chain/traits/src/liquidity.rs | 16 ++ 8 files changed, 337 insertions(+), 182 deletions(-) diff --git a/api/lib/src/lp.rs b/api/lib/src/lp.rs index b90444d9e5..2fbb0be29b 100644 --- a/api/lib/src/lp.rs +++ b/api/lib/src/lp.rs @@ -29,6 +29,7 @@ pub struct RangeOrderReturn { fn collect_range_order_returns( events: impl IntoIterator, + order_id: OrderId, ) -> Vec { events .into_iter() @@ -40,9 +41,10 @@ fn collect_range_order_returns( assets_delta, collected_fees, tick_range, + id, .. }, - ) => Some(RangeOrderReturn { + ) if order_id == id => Some(RangeOrderReturn { liquidity_delta, liquidity_total, increase_or_decrease, @@ -66,6 +68,7 @@ pub struct LimitOrderReturn { fn collect_limit_order_returns( events: impl IntoIterator, + order_id: OrderId, ) -> Vec { events .into_iter() @@ -77,9 +80,10 @@ fn collect_limit_order_returns( collected_fees, bought_amount, tick, + id, .. }, - ) => Some(LimitOrderReturn { + ) if order_id == id => Some(LimitOrderReturn { tick, amount_total, collected_fees, @@ -177,7 +181,7 @@ pub trait LpApi: SignedExtrinsicApi { .until_in_block() .await?; - Ok(collect_range_order_returns(events)) + Ok(collect_range_order_returns(events, id)) } async fn set_range_order( @@ -201,7 +205,7 @@ pub trait LpApi: SignedExtrinsicApi { .until_in_block() .await?; - Ok(collect_range_order_returns(events)) + Ok(collect_range_order_returns(events, id)) } async fn update_limit_order( @@ -227,7 +231,7 @@ pub trait LpApi: SignedExtrinsicApi { .until_in_block() .await?; - Ok(collect_limit_order_returns(events)) + Ok(collect_limit_order_returns(events, id)) } async fn set_limit_order( @@ -251,6 +255,6 @@ pub trait LpApi: SignedExtrinsicApi { .until_in_block() .await?; - Ok(collect_limit_order_returns(events)) + Ok(collect_limit_order_returns(events, id)) } } diff --git a/state-chain/pallets/cf-lp/src/lib.rs b/state-chain/pallets/cf-lp/src/lib.rs index a805bdf594..dc59e7cf97 100644 --- a/state-chain/pallets/cf-lp/src/lib.rs +++ b/state-chain/pallets/cf-lp/src/lib.rs @@ -5,7 +5,7 @@ use cf_chains::{address::AddressConverter, AnyChain, ForeignChainAddress}; use cf_primitives::{Asset, AssetAmount, ForeignChain}; use cf_traits::{ impl_pallet_safe_mode, liquidity::LpBalanceApi, AccountRoleRegistry, Chainflip, DepositApi, - EgressApi, + EgressApi, PoolApi, }; #[cfg(feature = "try-runtime")] @@ -59,6 +59,9 @@ pub mod pallet { /// Safe Mode access. type SafeMode: Get; + /// The interface for sweeping funds from pools into free balance + type PoolApi: PoolApi; + /// Benchmark weights type WeightInfo: WeightInfo; } diff --git a/state-chain/pallets/cf-lp/src/mock.rs b/state-chain/pallets/cf-lp/src/mock.rs index 1216b1da6c..3f19bad122 100644 --- a/state-chain/pallets/cf-lp/src/mock.rs +++ b/state-chain/pallets/cf-lp/src/mock.rs @@ -95,6 +95,7 @@ impl crate::Config for Test { type AddressConverter = MockAddressConverter; type SafeMode = MockRuntimeSafeMode; type WeightInfo = (); + type PoolApi = Self; } pub const LP_ACCOUNT: [u8; 32] = [1u8; 32]; diff --git a/state-chain/pallets/cf-lp/src/weights.rs b/state-chain/pallets/cf-lp/src/weights.rs index f56ba0d79f..80740ac0d8 100644 --- a/state-chain/pallets/cf-lp/src/weights.rs +++ b/state-chain/pallets/cf-lp/src/weights.rs @@ -2,9 +2,10 @@ //! Autogenerated weights for pallet_cf_lp //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-04-21, STEPS: `20`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! HOSTNAME: `Roys-MacBook-Pro.local`, CPU: `` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024 +//! DATE: 2023-10-17, STEPS: `20`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `MacBook-Pro.localdomain`, CPU: `` +//! EXECUTION: , WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024 // Executed Command: // ./target/release/chainflip-node @@ -24,145 +25,172 @@ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] #![allow(unused_imports)] +#![allow(missing_docs)] use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; -use sp_std::marker::PhantomData; +use core::marker::PhantomData; /// Weight functions needed for pallet_cf_lp. pub trait WeightInfo { fn request_liquidity_deposit_address() -> Weight; fn withdraw_asset() -> Weight; fn register_lp_account() -> Weight; - fn on_initialize(a: u32, ) -> Weight; - fn set_lp_ttl() -> Weight; fn register_liquidity_refund_address() -> Weight; } /// Weights for pallet_cf_lp using the Substrate node and recommended hardware. pub struct PalletWeight(PhantomData); impl WeightInfo for PalletWeight { - // Storage: Environment CurrentSystemState (r:1 w:0) - // Storage: AccountRoles AccountRoles (r:1 w:0) - // Storage: EthereumIngressEgress AddressPool (r:1 w:0) - // Storage: EthereumIngressEgress ChannelIdCounter (r:1 w:1) - // Storage: Environment EthereumVaultAddress (r:1 w:0) - // Storage: LiquidityProvider LpTTL (r:1 w:0) - // Storage: LiquidityProvider LiquidityChannelExpiries (r:1 w:1) - // Storage: EthereumIngressEgress ChannelActions (r:0 w:1) - // Storage: EthereumIngressEgress FetchParamDetails (r:0 w:1) - // Storage: EthereumIngressEgress AddressStatus (r:0 w:1) - // Storage: EthereumIngressEgress DepositAddressDetailsLookup (r:0 w:1) + /// Storage: `Environment::RuntimeSafeMode` (r:1 w:0) + /// Proof: `Environment::RuntimeSafeMode` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `AccountRoles::AccountRoles` (r:1 w:0) + /// Proof: `AccountRoles::AccountRoles` (`max_values`: None, `max_size`: Some(33), added: 2508, mode: `MaxEncodedLen`) + /// Storage: `LiquidityProvider::LiquidityRefundAddress` (r:1 w:0) + /// Proof: `LiquidityProvider::LiquidityRefundAddress` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `EthereumIngressEgress::DepositChannelPool` (r:1 w:0) + /// Proof: `EthereumIngressEgress::DepositChannelPool` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `EthereumIngressEgress::ChannelIdCounter` (r:1 w:1) + /// Proof: `EthereumIngressEgress::ChannelIdCounter` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Environment::EthereumVaultAddress` (r:1 w:0) + /// Proof: `Environment::EthereumVaultAddress` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `EthereumChainTracking::CurrentChainState` (r:1 w:0) + /// Proof: `EthereumChainTracking::CurrentChainState` (`max_values`: Some(1), `max_size`: Some(40), added: 535, mode: `MaxEncodedLen`) + /// Storage: `EthereumIngressEgress::DepositChannelLifetime` (r:1 w:0) + /// Proof: `EthereumIngressEgress::DepositChannelLifetime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `EthereumIngressEgress::DepositChannelRecycleBlocks` (r:1 w:1) + /// Proof: `EthereumIngressEgress::DepositChannelRecycleBlocks` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `EthereumIngressEgress::DepositChannelLookup` (r:0 w:1) + /// Proof: `EthereumIngressEgress::DepositChannelLookup` (`max_values`: None, `max_size`: None, mode: `Measured`) fn request_liquidity_deposit_address() -> Weight { - // Minimum execution time: 55_000 nanoseconds. - Weight::from_parts(56_000_000, 0) - .saturating_add(T::DbWeight::get().reads(7)) - .saturating_add(T::DbWeight::get().writes(6)) + // Proof Size summary in bytes: + // Measured: `1044` + // Estimated: `4509` + // Minimum execution time: 46_000_000 picoseconds. + Weight::from_parts(47_000_000, 4509) + .saturating_add(T::DbWeight::get().reads(9_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) } - // Storage: Environment CurrentSystemState (r:1 w:0) - // Storage: AccountRoles AccountRoles (r:1 w:0) - // Storage: LiquidityProvider FreeBalances (r:1 w:1) - // Storage: EthereumIngressEgress EgressIdCounter (r:1 w:1) - // Storage: EthereumIngressEgress ScheduledEgressFetchOrTransfer (r:1 w:1) + /// Storage: `Environment::RuntimeSafeMode` (r:1 w:0) + /// Proof: `Environment::RuntimeSafeMode` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `AccountRoles::AccountRoles` (r:1 w:0) + /// Proof: `AccountRoles::AccountRoles` (`max_values`: None, `max_size`: Some(33), added: 2508, mode: `MaxEncodedLen`) + /// Storage: `LiquidityProvider::FreeBalances` (r:1 w:1) + /// Proof: `LiquidityProvider::FreeBalances` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `EthereumIngressEgress::EgressIdCounter` (r:1 w:1) + /// Proof: `EthereumIngressEgress::EgressIdCounter` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `EthereumIngressEgress::ScheduledEgressFetchOrTransfer` (r:1 w:1) + /// Proof: `EthereumIngressEgress::ScheduledEgressFetchOrTransfer` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn withdraw_asset() -> Weight { - // Minimum execution time: 44_000 nanoseconds. - Weight::from_parts(45_000_000, 0) - .saturating_add(T::DbWeight::get().reads(5)) - .saturating_add(T::DbWeight::get().writes(3)) + // Proof Size summary in bytes: + // Measured: `913` + // Estimated: `4378` + // Minimum execution time: 39_000_000 picoseconds. + Weight::from_parts(40_000_000, 4378) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) } - // Storage: AccountRoles SwappingEnabled (r:1 w:0) - // Storage: AccountRoles AccountRoles (r:1 w:1) + /// Storage: `AccountRoles::SwappingEnabled` (r:1 w:0) + /// Proof: `AccountRoles::SwappingEnabled` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) + /// Storage: `AccountRoles::AccountRoles` (r:1 w:1) + /// Proof: `AccountRoles::AccountRoles` (`max_values`: None, `max_size`: Some(33), added: 2508, mode: `MaxEncodedLen`) fn register_lp_account() -> Weight { - // Minimum execution time: 20_000 nanoseconds. - Weight::from_parts(21_000_000, 0) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(1)) - } - // Storage: LiquidityProvider LiquidityChannelExpiries (r:1 w:1) - // Storage: EthereumIngressEgress AddressStatus (r:1 w:0) - // Storage: EthereumIngressEgress DepositAddressDetailsLookup (r:1 w:1) - // Storage: EthereumIngressEgress ChannelActions (r:0 w:1) - /// The range of component `a` is `[1, 100]`. - fn on_initialize(a: u32, ) -> Weight { - // Minimum execution time: 29_000 nanoseconds. - Weight::from_parts(34_520_228, 0) - // Standard Error: 40_282 - .saturating_add(Weight::from_parts(14_834_261, 0).saturating_mul(a.into())) - .saturating_add(T::DbWeight::get().reads(1)) - .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(a.into()))) - .saturating_add(T::DbWeight::get().writes(1)) - .saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(a.into()))) - } - // Storage: LiquidityProvider LpTTL (r:0 w:1) - fn set_lp_ttl() -> Weight { - // Minimum execution time: 13_000 nanoseconds. - Weight::from_parts(14_000_000, 0) - .saturating_add(T::DbWeight::get().writes(1)) + // Proof Size summary in bytes: + // Measured: `358` + // Estimated: `3498` + // Minimum execution time: 14_000_000 picoseconds. + Weight::from_parts(15_000_000, 3498) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) } + /// Storage: `AccountRoles::AccountRoles` (r:1 w:0) + /// Proof: `AccountRoles::AccountRoles` (`max_values`: None, `max_size`: Some(33), added: 2508, mode: `MaxEncodedLen`) + /// Storage: `LiquidityProvider::LiquidityRefundAddress` (r:0 w:1) + /// Proof: `LiquidityProvider::LiquidityRefundAddress` (`max_values`: None, `max_size`: None, mode: `Measured`) fn register_liquidity_refund_address() -> Weight { - Weight::from_parts(1_000_000, 0) + // Proof Size summary in bytes: + // Measured: `358` + // Estimated: `3498` + // Minimum execution time: 15_000_000 picoseconds. + Weight::from_parts(16_000_000, 3498) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) } } // For backwards compatibility and tests impl WeightInfo for () { - // Storage: Environment CurrentSystemState (r:1 w:0) - // Storage: AccountRoles AccountRoles (r:1 w:0) - // Storage: EthereumIngressEgress AddressPool (r:1 w:0) - // Storage: EthereumIngressEgress ChannelIdCounter (r:1 w:1) - // Storage: Environment EthereumVaultAddress (r:1 w:0) - // Storage: LiquidityProvider LpTTL (r:1 w:0) - // Storage: LiquidityProvider LiquidityChannelExpiries (r:1 w:1) - // Storage: EthereumIngressEgress ChannelActions (r:0 w:1) - // Storage: EthereumIngressEgress FetchParamDetails (r:0 w:1) - // Storage: EthereumIngressEgress AddressStatus (r:0 w:1) - // Storage: EthereumIngressEgress DepositAddressDetailsLookup (r:0 w:1) + /// Storage: `Environment::RuntimeSafeMode` (r:1 w:0) + /// Proof: `Environment::RuntimeSafeMode` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `AccountRoles::AccountRoles` (r:1 w:0) + /// Proof: `AccountRoles::AccountRoles` (`max_values`: None, `max_size`: Some(33), added: 2508, mode: `MaxEncodedLen`) + /// Storage: `LiquidityProvider::LiquidityRefundAddress` (r:1 w:0) + /// Proof: `LiquidityProvider::LiquidityRefundAddress` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `EthereumIngressEgress::DepositChannelPool` (r:1 w:0) + /// Proof: `EthereumIngressEgress::DepositChannelPool` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `EthereumIngressEgress::ChannelIdCounter` (r:1 w:1) + /// Proof: `EthereumIngressEgress::ChannelIdCounter` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `Environment::EthereumVaultAddress` (r:1 w:0) + /// Proof: `Environment::EthereumVaultAddress` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `EthereumChainTracking::CurrentChainState` (r:1 w:0) + /// Proof: `EthereumChainTracking::CurrentChainState` (`max_values`: Some(1), `max_size`: Some(40), added: 535, mode: `MaxEncodedLen`) + /// Storage: `EthereumIngressEgress::DepositChannelLifetime` (r:1 w:0) + /// Proof: `EthereumIngressEgress::DepositChannelLifetime` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `EthereumIngressEgress::DepositChannelRecycleBlocks` (r:1 w:1) + /// Proof: `EthereumIngressEgress::DepositChannelRecycleBlocks` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `EthereumIngressEgress::DepositChannelLookup` (r:0 w:1) + /// Proof: `EthereumIngressEgress::DepositChannelLookup` (`max_values`: None, `max_size`: None, mode: `Measured`) fn request_liquidity_deposit_address() -> Weight { - // Minimum execution time: 55_000 nanoseconds. - Weight::from_parts(56_000_000, 0) - .saturating_add(RocksDbWeight::get().reads(7)) - .saturating_add(RocksDbWeight::get().writes(6)) + // Proof Size summary in bytes: + // Measured: `1044` + // Estimated: `4509` + // Minimum execution time: 46_000_000 picoseconds. + Weight::from_parts(47_000_000, 4509) + .saturating_add(RocksDbWeight::get().reads(9_u64)) + .saturating_add(RocksDbWeight::get().writes(3_u64)) } - // Storage: Environment CurrentSystemState (r:1 w:0) - // Storage: AccountRoles AccountRoles (r:1 w:0) - // Storage: LiquidityProvider FreeBalances (r:1 w:1) - // Storage: EthereumIngressEgress EgressIdCounter (r:1 w:1) - // Storage: EthereumIngressEgress ScheduledEgressFetchOrTransfer (r:1 w:1) + /// Storage: `Environment::RuntimeSafeMode` (r:1 w:0) + /// Proof: `Environment::RuntimeSafeMode` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `AccountRoles::AccountRoles` (r:1 w:0) + /// Proof: `AccountRoles::AccountRoles` (`max_values`: None, `max_size`: Some(33), added: 2508, mode: `MaxEncodedLen`) + /// Storage: `LiquidityProvider::FreeBalances` (r:1 w:1) + /// Proof: `LiquidityProvider::FreeBalances` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `EthereumIngressEgress::EgressIdCounter` (r:1 w:1) + /// Proof: `EthereumIngressEgress::EgressIdCounter` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `EthereumIngressEgress::ScheduledEgressFetchOrTransfer` (r:1 w:1) + /// Proof: `EthereumIngressEgress::ScheduledEgressFetchOrTransfer` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn withdraw_asset() -> Weight { - // Minimum execution time: 44_000 nanoseconds. - Weight::from_parts(45_000_000, 0) - .saturating_add(RocksDbWeight::get().reads(5)) - .saturating_add(RocksDbWeight::get().writes(3)) + // Proof Size summary in bytes: + // Measured: `913` + // Estimated: `4378` + // Minimum execution time: 39_000_000 picoseconds. + Weight::from_parts(40_000_000, 4378) + .saturating_add(RocksDbWeight::get().reads(5_u64)) + .saturating_add(RocksDbWeight::get().writes(3_u64)) } - // Storage: AccountRoles SwappingEnabled (r:1 w:0) - // Storage: AccountRoles AccountRoles (r:1 w:1) + /// Storage: `AccountRoles::SwappingEnabled` (r:1 w:0) + /// Proof: `AccountRoles::SwappingEnabled` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) + /// Storage: `AccountRoles::AccountRoles` (r:1 w:1) + /// Proof: `AccountRoles::AccountRoles` (`max_values`: None, `max_size`: Some(33), added: 2508, mode: `MaxEncodedLen`) fn register_lp_account() -> Weight { - // Minimum execution time: 20_000 nanoseconds. - Weight::from_parts(21_000_000, 0) - .saturating_add(RocksDbWeight::get().reads(2)) - .saturating_add(RocksDbWeight::get().writes(1)) - } - // Storage: LiquidityProvider LiquidityChannelExpiries (r:1 w:1) - // Storage: EthereumIngressEgress AddressStatus (r:1 w:0) - // Storage: EthereumIngressEgress DepositAddressDetailsLookup (r:1 w:1) - // Storage: EthereumIngressEgress ChannelActions (r:0 w:1) - /// The range of component `a` is `[1, 100]`. - fn on_initialize(a: u32, ) -> Weight { - // Minimum execution time: 29_000 nanoseconds. - Weight::from_parts(34_520_228, 0) - // Standard Error: 40_282 - .saturating_add(Weight::from_parts(14_834_261, 0).saturating_mul(a.into())) - .saturating_add(RocksDbWeight::get().reads(1)) - .saturating_add(RocksDbWeight::get().reads((2_u64).saturating_mul(a.into()))) - .saturating_add(RocksDbWeight::get().writes(1)) - .saturating_add(RocksDbWeight::get().writes((2_u64).saturating_mul(a.into()))) - } - // Storage: LiquidityProvider LpTTL (r:0 w:1) - fn set_lp_ttl() -> Weight { - // Minimum execution time: 13_000 nanoseconds. - Weight::from_parts(14_000_000, 0) - .saturating_add(RocksDbWeight::get().writes(1)) + // Proof Size summary in bytes: + // Measured: `358` + // Estimated: `3498` + // Minimum execution time: 14_000_000 picoseconds. + Weight::from_parts(15_000_000, 3498) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) } + /// Storage: `AccountRoles::AccountRoles` (r:1 w:0) + /// Proof: `AccountRoles::AccountRoles` (`max_values`: None, `max_size`: Some(33), added: 2508, mode: `MaxEncodedLen`) + /// Storage: `LiquidityProvider::LiquidityRefundAddress` (r:0 w:1) + /// Proof: `LiquidityProvider::LiquidityRefundAddress` (`max_values`: None, `max_size`: None, mode: `Measured`) fn register_liquidity_refund_address() -> Weight { - Weight::from_parts(1_000_000, 0) + // Proof Size summary in bytes: + // Measured: `358` + // Estimated: `3498` + // Minimum execution time: 15_000_000 picoseconds. + Weight::from_parts(16_000_000, 3498) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) } } diff --git a/state-chain/pallets/cf-pools/src/lib.rs b/state-chain/pallets/cf-pools/src/lib.rs index 6e833749b5..7c21f09aec 100644 --- a/state-chain/pallets/cf-pools/src/lib.rs +++ b/state-chain/pallets/cf-pools/src/lib.rs @@ -10,7 +10,7 @@ use cf_amm::{ PoolState, }; use cf_primitives::{chains::assets::any, Asset, AssetAmount, SwapOutput, STABLE_ASSET}; -use cf_traits::{impl_pallet_safe_mode, Chainflip, LpBalanceApi, SwappingApi}; +use cf_traits::{impl_pallet_safe_mode, Chainflip, LpBalanceApi, PoolApi, SwappingApi}; use frame_support::{ pallet_prelude::*, sp_runtime::{Permill, Saturating}, @@ -669,6 +669,7 @@ pub mod pallet { ); let lp = T::AccountRoleRegistry::ensure_liquidity_provider(origin)?; T::LpBalance::ensure_has_refund_address_for_pair(&lp, base_asset, pair_asset)?; + Self::inner_sweep(&lp)?; Self::try_mutate_enabled_pool(base_asset, pair_asset, |asset_pair, pool| { let tick_range = match ( pool.range_orders_cache @@ -753,6 +754,7 @@ pub mod pallet { ); let lp = T::AccountRoleRegistry::ensure_liquidity_provider(origin)?; T::LpBalance::ensure_has_refund_address_for_pair(&lp, base_asset, pair_asset)?; + Self::inner_sweep(&lp)?; Self::try_mutate_enabled_pool(base_asset, pair_asset, |asset_pair, pool| { let tick_range = match ( pool.range_orders_cache @@ -826,6 +828,7 @@ pub mod pallet { ); let lp = T::AccountRoleRegistry::ensure_liquidity_provider(origin)?; T::LpBalance::ensure_has_refund_address_for_pair(&lp, sell_asset, buy_asset)?; + Self::inner_sweep(&lp)?; Self::try_mutate_enabled_pool(sell_asset, buy_asset, |asset_pair, pool| { let tick = match ( pool.limit_orders_cache[asset_pair.base_side] @@ -902,6 +905,7 @@ pub mod pallet { ); let lp = T::AccountRoleRegistry::ensure_liquidity_provider(origin)?; T::LpBalance::ensure_has_refund_address_for_pair(&lp, sell_asset, buy_asset)?; + Self::inner_sweep(&lp)?; Self::try_mutate_enabled_pool(sell_asset, buy_asset, |asset_pair, pool| { let tick = match ( pool.limit_orders_cache[asset_pair.base_side] @@ -1039,6 +1043,14 @@ impl SwappingApi for Pallet { } } +impl PoolApi for Pallet { + type AccountId = T::AccountId; + + fn sweep(who: &T::AccountId) -> DispatchResult { + Self::inner_sweep(who) + } +} + impl cf_traits::FlipBurnInfo for Pallet { fn take_flip_to_burn() -> AssetAmount { FlipToBurn::::take() @@ -1106,6 +1118,62 @@ pub struct UnidirectionalPoolDepth { } impl Pallet { + fn inner_sweep(lp: &T::AccountId) -> DispatchResult { + // Collect to avoid undefined behaviour (See StorsgeMap::iter_keys documentation) + for canonical_asset_pair in Pools::::iter_keys().collect::>() { + let mut pool = Pools::::get(canonical_asset_pair).unwrap(); + + if let Some(range_orders_cache) = pool.range_orders_cache.get(lp).cloned() { + let asset_pair = AssetPair { canonical_asset_pair, base_side: Side::Zero }; + + for (id, range) in range_orders_cache.iter() { + Self::inner_update_range_order( + &mut pool, + lp, + &asset_pair, + *id, + range.clone(), + IncreaseOrDecrease::Decrease, + range_orders::Size::Liquidity { liquidity: 0 }, + false, + )?; + } + } + + for (side, limit_orders_cache) in pool + .limit_orders_cache + .as_ref() + .into_iter() + .filter_map(|(side, limit_orders_cache)| { + limit_orders_cache + .get(lp) + .cloned() + .map(|limit_orders_cache| (side, limit_orders_cache)) + }) + .collect::>() + { + let asset_pair = AssetPair { canonical_asset_pair, base_side: side }; + + for (id, tick) in limit_orders_cache { + Self::inner_update_limit_order( + &mut pool, + lp, + &asset_pair, + id, + tick, + IncreaseOrDecrease::Decrease, + Default::default(), + false, + )?; + } + } + + Pools::::insert(canonical_asset_pair, pool); + } + + Ok(()) + } + #[allow(clippy::too_many_arguments)] fn inner_update_limit_order( pool: &mut Pool, diff --git a/state-chain/pallets/cf-pools/src/weights.rs b/state-chain/pallets/cf-pools/src/weights.rs index 60d1fbadb1..517f80162f 100644 --- a/state-chain/pallets/cf-pools/src/weights.rs +++ b/state-chain/pallets/cf-pools/src/weights.rs @@ -2,7 +2,7 @@ //! Autogenerated weights for pallet_cf_pools //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-09-04, STEPS: `20`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-10-17, STEPS: `20`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `MacBook-Pro.localdomain`, CPU: `` //! EXECUTION: , WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024 @@ -51,7 +51,7 @@ impl WeightInfo for PalletWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 8_000_000 picoseconds. + // Minimum execution time: 7_000_000 picoseconds. Weight::from_parts(8_000_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -61,8 +61,8 @@ impl WeightInfo for PalletWeight { // Proof Size summary in bytes: // Measured: `418` // Estimated: `3883` - // Minimum execution time: 16_000_000 picoseconds. - Weight::from_parts(17_000_000, 3883) + // Minimum execution time: 15_000_000 picoseconds. + Weight::from_parts(16_000_000, 3883) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -81,75 +81,90 @@ impl WeightInfo for PalletWeight { /// Proof: `Environment::RuntimeSafeMode` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `AccountRoles::AccountRoles` (r:1 w:0) /// Proof: `AccountRoles::AccountRoles` (`max_values`: None, `max_size`: Some(33), added: 2508, mode: `MaxEncodedLen`) - /// Storage: `LiquidityPools::Pools` (r:1 w:1) + /// Storage: `LiquidityProvider::LiquidityRefundAddress` (r:1 w:0) + /// Proof: `LiquidityProvider::LiquidityRefundAddress` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `LiquidityPools::Pools` (r:2 w:1) /// Proof: `LiquidityPools::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `LiquidityProvider::FreeBalances` (r:2 w:2) /// Proof: `LiquidityProvider::FreeBalances` (`max_values`: None, `max_size`: None, mode: `Measured`) fn update_range_order() -> Weight { // Proof Size summary in bytes: - // Measured: `1302` - // Estimated: `7242` - // Minimum execution time: 54_000_000 picoseconds. - Weight::from_parts(55_000_000, 7242) - .saturating_add(T::DbWeight::get().reads(5_u64)) + // Measured: `1438` + // Estimated: `7378` + // Minimum execution time: 71_000_000 picoseconds. + Weight::from_parts(72_000_000, 7378) + .saturating_add(T::DbWeight::get().reads(7_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } /// Storage: `Environment::RuntimeSafeMode` (r:1 w:0) /// Proof: `Environment::RuntimeSafeMode` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `AccountRoles::AccountRoles` (r:1 w:0) /// Proof: `AccountRoles::AccountRoles` (`max_values`: None, `max_size`: Some(33), added: 2508, mode: `MaxEncodedLen`) - /// Storage: `LiquidityPools::Pools` (r:1 w:1) + /// Storage: `LiquidityProvider::LiquidityRefundAddress` (r:1 w:0) + /// Proof: `LiquidityProvider::LiquidityRefundAddress` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `LiquidityPools::Pools` (r:2 w:1) /// Proof: `LiquidityPools::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `LiquidityProvider::FreeBalances` (r:2 w:2) /// Proof: `LiquidityProvider::FreeBalances` (`max_values`: None, `max_size`: None, mode: `Measured`) fn set_range_order() -> Weight { // Proof Size summary in bytes: - // Measured: `1302` - // Estimated: `7242` - // Minimum execution time: 54_000_000 picoseconds. - Weight::from_parts(55_000_000, 7242) - .saturating_add(T::DbWeight::get().reads(5_u64)) + // Measured: `1438` + // Estimated: `7378` + // Minimum execution time: 74_000_000 picoseconds. + Weight::from_parts(75_000_000, 7378) + .saturating_add(T::DbWeight::get().reads(7_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } /// Storage: `Environment::RuntimeSafeMode` (r:1 w:0) /// Proof: `Environment::RuntimeSafeMode` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `AccountRoles::AccountRoles` (r:1 w:0) /// Proof: `AccountRoles::AccountRoles` (`max_values`: None, `max_size`: Some(33), added: 2508, mode: `MaxEncodedLen`) - /// Storage: `LiquidityPools::Pools` (r:1 w:1) + /// Storage: `LiquidityProvider::LiquidityRefundAddress` (r:1 w:0) + /// Proof: `LiquidityProvider::LiquidityRefundAddress` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `LiquidityPools::Pools` (r:2 w:1) /// Proof: `LiquidityPools::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `LiquidityProvider::FreeBalances` (r:1 w:1) /// Proof: `LiquidityProvider::FreeBalances` (`max_values`: None, `max_size`: None, mode: `Measured`) fn update_limit_order() -> Weight { // Proof Size summary in bytes: - // Measured: `1302` - // Estimated: `4767` - // Minimum execution time: 43_000_000 picoseconds. - Weight::from_parts(44_000_000, 4767) - .saturating_add(T::DbWeight::get().reads(4_u64)) + // Measured: `1438` + // Estimated: `7378` + // Minimum execution time: 59_000_000 picoseconds. + Weight::from_parts(60_000_000, 7378) + .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `Environment::RuntimeSafeMode` (r:1 w:0) /// Proof: `Environment::RuntimeSafeMode` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `AccountRoles::AccountRoles` (r:1 w:0) /// Proof: `AccountRoles::AccountRoles` (`max_values`: None, `max_size`: Some(33), added: 2508, mode: `MaxEncodedLen`) - /// Storage: `LiquidityPools::Pools` (r:1 w:1) + /// Storage: `LiquidityProvider::LiquidityRefundAddress` (r:1 w:0) + /// Proof: `LiquidityProvider::LiquidityRefundAddress` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `LiquidityPools::Pools` (r:2 w:1) /// Proof: `LiquidityPools::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `LiquidityProvider::FreeBalances` (r:1 w:1) /// Proof: `LiquidityProvider::FreeBalances` (`max_values`: None, `max_size`: None, mode: `Measured`) fn set_limit_order() -> Weight { // Proof Size summary in bytes: - // Measured: `1302` - // Estimated: `4767` - // Minimum execution time: 43_000_000 picoseconds. - Weight::from_parts(45_000_000, 4767) - .saturating_add(T::DbWeight::get().reads(4_u64)) + // Measured: `1438` + // Estimated: `7378` + // Minimum execution time: 57_000_000 picoseconds. + Weight::from_parts(60_000_000, 7378) + .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - + /// Storage: `LiquidityPools::Pools` (r:1 w:1) + /// Proof: `LiquidityPools::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `LiquidityProvider::FreeBalances` (r:1 w:1) + /// Proof: `LiquidityProvider::FreeBalances` (`max_values`: None, `max_size`: None, mode: `Measured`) fn set_pool_fees() -> Weight { - Weight::from_parts(17_000_000, 3883) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) + // Proof Size summary in bytes: + // Measured: `1417` + // Estimated: `4882` + // Minimum execution time: 50_000_000 picoseconds. + Weight::from_parts(51_000_000, 4882) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) } } @@ -161,7 +176,7 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 8_000_000 picoseconds. + // Minimum execution time: 7_000_000 picoseconds. Weight::from_parts(8_000_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -171,8 +186,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `418` // Estimated: `3883` - // Minimum execution time: 16_000_000 picoseconds. - Weight::from_parts(17_000_000, 3883) + // Minimum execution time: 15_000_000 picoseconds. + Weight::from_parts(16_000_000, 3883) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -191,74 +206,89 @@ impl WeightInfo for () { /// Proof: `Environment::RuntimeSafeMode` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `AccountRoles::AccountRoles` (r:1 w:0) /// Proof: `AccountRoles::AccountRoles` (`max_values`: None, `max_size`: Some(33), added: 2508, mode: `MaxEncodedLen`) - /// Storage: `LiquidityPools::Pools` (r:1 w:1) + /// Storage: `LiquidityProvider::LiquidityRefundAddress` (r:1 w:0) + /// Proof: `LiquidityProvider::LiquidityRefundAddress` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `LiquidityPools::Pools` (r:2 w:1) /// Proof: `LiquidityPools::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `LiquidityProvider::FreeBalances` (r:2 w:2) /// Proof: `LiquidityProvider::FreeBalances` (`max_values`: None, `max_size`: None, mode: `Measured`) fn update_range_order() -> Weight { // Proof Size summary in bytes: - // Measured: `1302` - // Estimated: `7242` - // Minimum execution time: 54_000_000 picoseconds. - Weight::from_parts(55_000_000, 7242) - .saturating_add(RocksDbWeight::get().reads(5_u64)) + // Measured: `1438` + // Estimated: `7378` + // Minimum execution time: 71_000_000 picoseconds. + Weight::from_parts(72_000_000, 7378) + .saturating_add(RocksDbWeight::get().reads(7_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } /// Storage: `Environment::RuntimeSafeMode` (r:1 w:0) /// Proof: `Environment::RuntimeSafeMode` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `AccountRoles::AccountRoles` (r:1 w:0) /// Proof: `AccountRoles::AccountRoles` (`max_values`: None, `max_size`: Some(33), added: 2508, mode: `MaxEncodedLen`) - /// Storage: `LiquidityPools::Pools` (r:1 w:1) + /// Storage: `LiquidityProvider::LiquidityRefundAddress` (r:1 w:0) + /// Proof: `LiquidityProvider::LiquidityRefundAddress` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `LiquidityPools::Pools` (r:2 w:1) /// Proof: `LiquidityPools::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `LiquidityProvider::FreeBalances` (r:2 w:2) /// Proof: `LiquidityProvider::FreeBalances` (`max_values`: None, `max_size`: None, mode: `Measured`) fn set_range_order() -> Weight { // Proof Size summary in bytes: - // Measured: `1302` - // Estimated: `7242` - // Minimum execution time: 54_000_000 picoseconds. - Weight::from_parts(55_000_000, 7242) - .saturating_add(RocksDbWeight::get().reads(5_u64)) + // Measured: `1438` + // Estimated: `7378` + // Minimum execution time: 74_000_000 picoseconds. + Weight::from_parts(75_000_000, 7378) + .saturating_add(RocksDbWeight::get().reads(7_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } /// Storage: `Environment::RuntimeSafeMode` (r:1 w:0) /// Proof: `Environment::RuntimeSafeMode` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `AccountRoles::AccountRoles` (r:1 w:0) /// Proof: `AccountRoles::AccountRoles` (`max_values`: None, `max_size`: Some(33), added: 2508, mode: `MaxEncodedLen`) - /// Storage: `LiquidityPools::Pools` (r:1 w:1) + /// Storage: `LiquidityProvider::LiquidityRefundAddress` (r:1 w:0) + /// Proof: `LiquidityProvider::LiquidityRefundAddress` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `LiquidityPools::Pools` (r:2 w:1) /// Proof: `LiquidityPools::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `LiquidityProvider::FreeBalances` (r:1 w:1) /// Proof: `LiquidityProvider::FreeBalances` (`max_values`: None, `max_size`: None, mode: `Measured`) fn update_limit_order() -> Weight { // Proof Size summary in bytes: - // Measured: `1302` - // Estimated: `4767` - // Minimum execution time: 43_000_000 picoseconds. - Weight::from_parts(44_000_000, 4767) - .saturating_add(RocksDbWeight::get().reads(4_u64)) + // Measured: `1438` + // Estimated: `7378` + // Minimum execution time: 59_000_000 picoseconds. + Weight::from_parts(60_000_000, 7378) + .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `Environment::RuntimeSafeMode` (r:1 w:0) /// Proof: `Environment::RuntimeSafeMode` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `AccountRoles::AccountRoles` (r:1 w:0) /// Proof: `AccountRoles::AccountRoles` (`max_values`: None, `max_size`: Some(33), added: 2508, mode: `MaxEncodedLen`) - /// Storage: `LiquidityPools::Pools` (r:1 w:1) + /// Storage: `LiquidityProvider::LiquidityRefundAddress` (r:1 w:0) + /// Proof: `LiquidityProvider::LiquidityRefundAddress` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `LiquidityPools::Pools` (r:2 w:1) /// Proof: `LiquidityPools::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `LiquidityProvider::FreeBalances` (r:1 w:1) /// Proof: `LiquidityProvider::FreeBalances` (`max_values`: None, `max_size`: None, mode: `Measured`) fn set_limit_order() -> Weight { // Proof Size summary in bytes: - // Measured: `1302` - // Estimated: `4767` - // Minimum execution time: 43_000_000 picoseconds. - Weight::from_parts(45_000_000, 4767) - .saturating_add(RocksDbWeight::get().reads(4_u64)) + // Measured: `1438` + // Estimated: `7378` + // Minimum execution time: 57_000_000 picoseconds. + Weight::from_parts(60_000_000, 7378) + .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - + /// Storage: `LiquidityPools::Pools` (r:1 w:1) + /// Proof: `LiquidityPools::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `LiquidityProvider::FreeBalances` (r:1 w:1) + /// Proof: `LiquidityProvider::FreeBalances` (`max_values`: None, `max_size`: None, mode: `Measured`) fn set_pool_fees() -> Weight { - Weight::from_parts(17_000_000, 3883) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) + // Proof Size summary in bytes: + // Measured: `1417` + // Estimated: `4882` + // Minimum execution time: 50_000_000 picoseconds. + Weight::from_parts(51_000_000, 4882) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) } } diff --git a/state-chain/runtime/src/lib.rs b/state-chain/runtime/src/lib.rs index 117767653b..8143e75dad 100644 --- a/state-chain/runtime/src/lib.rs +++ b/state-chain/runtime/src/lib.rs @@ -82,7 +82,9 @@ use sp_version::RuntimeVersion; pub use cf_primitives::{ AccountRole, Asset, AssetAmount, BlockNumber, FlipBalance, SemVer, SwapOutput, }; -pub use cf_traits::{AccountInfo, EpochInfo, QualifyNode, SessionKeysRegistered, SwappingApi}; +pub use cf_traits::{ + AccountInfo, EpochInfo, PoolApi, QualifyNode, SessionKeysRegistered, SwappingApi, +}; pub use chainflip::chain_instances::*; use chainflip::{ @@ -337,6 +339,7 @@ impl pallet_cf_lp::Config for Runtime { type EgressHandler = chainflip::AnyChainIngressEgressHandler; type AddressConverter = ChainAddressConverter; type SafeMode = RuntimeSafeMode; + type PoolApi = LiquidityPools; type WeightInfo = pallet_cf_lp::weights::PalletWeight; } @@ -1061,6 +1064,8 @@ impl_runtime_apis! { (chain, pallet_cf_lp::LiquidityRefundAddress::::get(&account_id, chain)) }).collect(); + LiquidityPools::sweep(&account_id).unwrap(); + let balances = Asset::all().iter().map(|&asset| (asset, pallet_cf_lp::FreeBalances::::get(&account_id, asset).unwrap_or(0)) ).collect(); diff --git a/state-chain/traits/src/liquidity.rs b/state-chain/traits/src/liquidity.rs index e9f1a16fbd..f12b7155d2 100644 --- a/state-chain/traits/src/liquidity.rs +++ b/state-chain/traits/src/liquidity.rs @@ -46,6 +46,22 @@ pub trait LpBalanceApi { ) -> DispatchResult; } +pub trait PoolApi { + type AccountId; + + /// Sweep all earnings of an LP into their free balance (Should be called before any assets are + /// debited from their free balance) + fn sweep(who: &Self::AccountId) -> Result<(), DispatchError>; +} + +impl PoolApi for T { + type AccountId = T::AccountId; + + fn sweep(_who: &Self::AccountId) -> Result<(), DispatchError> { + Ok(()) + } +} + pub trait SwappingApi { /// Takes the swap amount in STABLE_ASSET, collect network fee from it /// and return the remaining value