From 5fa02307666161099b4fce2afd54291a6befdd3e Mon Sep 17 00:00:00 2001 From: toints Date: Fri, 1 Mar 2024 01:05:05 +0800 Subject: [PATCH 1/4] Feat: Added the functionality to distribute profits from parachain to the treasury account of the relayChain * use xcm to transfer assets from parachain to relaychain --- Cargo.lock | 69 ++++++++++-------- pallets/liquidation/Cargo.toml | 10 +++ pallets/liquidation/src/lib.rs | 82 +++++++++++++++++++-- pallets/liquidation/src/mock.rs | 125 +++++++++++++++++++++++++++++++- runtime/src/lib.rs | 1 + 5 files changed, 248 insertions(+), 39 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 62b6bfd..42890e9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -217,9 +217,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.4" +version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" +checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" dependencies = [ "anstyle", "anstyle-parse", @@ -1426,9 +1426,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.6" +version = "4.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d04704f56c2cde07f43e8e2c154b43f216dc5c92fc98ada720177362f953b956" +checksum = "c918d541ef2913577a0f9566e9ce27cb35b6df072075769e0b26cb5a554520da" dependencies = [ "clap_builder", "clap_derive", @@ -1436,21 +1436,21 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.6" +version = "4.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e231faeaca65ebd1ea3c737966bf858971cd38c3849107aa3ea7de90a804e45" +checksum = "9f3e7391dad68afb0c2ede1bf619f579a3dc9c2ec67f089baa397123a2f3d1eb" dependencies = [ "anstream", "anstyle", "clap_lex", - "strsim", + "strsim 0.11.0", ] [[package]] name = "clap_derive" -version = "4.4.2" +version = "4.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873" +checksum = "307bc0538d5f0f83b8248db3087aa92fe504e4691294d0c96c0eabc33f47ba47" dependencies = [ "heck", "proc-macro2", @@ -1460,9 +1460,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.5.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961" +checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" [[package]] name = "coarsetime" @@ -2604,7 +2604,7 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "strsim", + "strsim 0.10.0", "syn 1.0.109", ] @@ -2618,7 +2618,7 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "strsim", + "strsim 0.10.0", "syn 2.0.48", ] @@ -4672,12 +4672,6 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" -[[package]] -name = "hex-literal" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" - [[package]] name = "hex-literal" version = "0.4.1" @@ -6249,7 +6243,7 @@ dependencies = [ "async-trait", "cumulus-primitives-core", "cumulus-relay-chain-interface", - "hex-literal 0.3.4", + "hex-literal", "log", "parity-scale-codec", "scale-info", @@ -7087,7 +7081,7 @@ dependencies = [ "ethabi", "frame-support", "frame-system", - "hex-literal 0.4.1", + "hex-literal", "pallet-assets", "pallet-balances", "pallet-evm", @@ -7561,7 +7555,7 @@ dependencies = [ "frame-system", "hash-db 0.16.0", "hex", - "hex-literal 0.4.1", + "hex-literal", "impl-trait-for-tuples", "log", "parity-scale-codec", @@ -7763,6 +7757,7 @@ dependencies = [ name = "pallet-liquidation" version = "0.1.0" dependencies = [ + "cumulus-pallet-xcmp-queue", "frame-benchmarking", "frame-support", "frame-system", @@ -7774,6 +7769,7 @@ dependencies = [ "pallet-pot", "pallet-transaction-payment", "pallet-utility", + "pallet-xcm 1.0.0", "parity-scale-codec", "scale-info", "smallvec", @@ -7782,6 +7778,9 @@ dependencies = [ "sp-io 23.0.0", "sp-runtime 24.0.0", "sp-std 8.0.0", + "staging-xcm", + "staging-xcm-builder", + "staging-xcm-executor", ] [[package]] @@ -7971,7 +7970,7 @@ dependencies = [ "frame-support", "frame-system", "hex", - "hex-literal 0.3.4", + "hex-literal", "log", "magnet-primitives-order", "pallet-balances", @@ -8567,7 +8566,7 @@ dependencies = [ "frame-system", "frame-system-rpc-runtime-api", "futures", - "hex-literal 0.4.1", + "hex-literal", "jsonrpsee 0.16.3", "log", "magnet-client-consensus-aura", @@ -8634,7 +8633,7 @@ dependencies = [ [[package]] name = "parachain-magnet-runtime" -version = "0.5.2" +version = "0.5.3" dependencies = [ "cumulus-pallet-aura-ext", "cumulus-pallet-dmp-queue", @@ -8657,7 +8656,7 @@ dependencies = [ "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", - "hex-literal 0.4.1", + "hex-literal", "log", "magnet-primitives-order", "mp-system", @@ -9849,7 +9848,7 @@ version = "1.0.0" source = "git+https://github.com/paritytech/polkadot-sdk?branch=release-polkadot-v1.1.0#c8d2251cafadc108ba2f1f8a3208dc547ff38901" dependencies = [ "bitvec", - "hex-literal 0.4.1", + "hex-literal", "parity-scale-codec", "polkadot-core-primitives", "polkadot-parachain-primitives", @@ -9915,7 +9914,7 @@ dependencies = [ "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", - "hex-literal 0.4.1", + "hex-literal", "log", "pallet-authority-discovery", "pallet-authorship", @@ -10129,7 +10128,7 @@ dependencies = [ "frame-system", "frame-system-rpc-runtime-api", "futures", - "hex-literal 0.4.1", + "hex-literal", "is_executable", "kvdb", "kvdb-rocksdb", @@ -11072,7 +11071,7 @@ dependencies = [ "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", - "hex-literal 0.4.1", + "hex-literal", "log", "pallet-authority-discovery", "pallet-authorship", @@ -14690,7 +14689,7 @@ dependencies = [ "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", - "hex-literal 0.4.1", + "hex-literal", "kusama-runtime-constants", "log", "pallet-authority-discovery", @@ -14880,6 +14879,12 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "strsim" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" + [[package]] name = "strum" version = "0.24.1" @@ -16775,7 +16780,7 @@ dependencies = [ "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", - "hex-literal 0.4.1", + "hex-literal", "log", "pallet-authority-discovery", "pallet-authorship", diff --git a/pallets/liquidation/Cargo.toml b/pallets/liquidation/Cargo.toml index 6040dbf..268821e 100644 --- a/pallets/liquidation/Cargo.toml +++ b/pallets/liquidation/Cargo.toml @@ -22,6 +22,7 @@ smallvec = { workspace = true } pallet-order = {path = "../order", default-features = false} pallet-pot = {path = "../pot", default-features = false} mp-system = { path = "../../primitives/system", default-features = false } +pallet-xcm = {path = "../pallet-xcm", default-features = false} pallet-balances = { workspace = true, default-features = false } pallet-transaction-payment = { workspace = true, default-features = false } @@ -35,6 +36,10 @@ frame-support = { workspace = true, default-features = false } frame-system = { workspace = true, default-features = false } frame-benchmarking = { workspace = true, default-features = false, optional = true} pallet-utility = { workspace = true, default-features = false} +xcm = { workspace = true, default-features = false} +xcm-builder = { workspace = true, default-features = false} +cumulus-pallet-xcmp-queue = { workspace = true, default-features = false} +xcm-executor = { workspace = true, default-features = false} [features] default = ['std'] @@ -58,6 +63,11 @@ std = [ "mp-system/std", "pallet-utility/std", "frame-benchmarking/std", + "pallet-xcm/std", + "xcm/std", + "xcm-builder/std", + "cumulus-pallet-xcmp-queue/std", + "xcm-executor/std", ] try-runtime = [ "frame-support/try-runtime", diff --git a/pallets/liquidation/src/lib.rs b/pallets/liquidation/src/lib.rs index dbfc77d..2bab813 100644 --- a/pallets/liquidation/src/lib.rs +++ b/pallets/liquidation/src/lib.rs @@ -7,12 +7,13 @@ mod mock; mod tests; use frame_support::{ + dispatch::DispatchResult, storage::types::StorageMap, traits::{Currency, ExistenceRequirement, Get}, weights::WeightToFeePolynomial, Twox64Concat, }; -use frame_system::pallet_prelude::BlockNumberFor; +use frame_system::pallet_prelude::{BlockNumberFor, OriginFor}; use mp_system::BASE_ACCOUNT; pub use pallet::*; use sp_runtime::{ @@ -21,11 +22,18 @@ use sp_runtime::{ }; use sp_std::{prelude::*, vec}; +use xcm::{ + prelude::*, + v3::{Junction, MultiAsset, MultiLocation, NetworkId}, +}; + type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; pub type Balance = u128; +pub const PARACHAIN_TO_RELAYCHAIN_UNIT: u128 = 1_0000_0000; + #[frame_support::pallet] pub mod pallet { use super::*; @@ -54,6 +62,13 @@ pub mod pallet { type Currency: frame_support::traits::Currency + frame_support::traits::ReservableCurrency; + /// The XCM sender + type XcmSender: SendXcm; + + //Treasury account on the Relay Chain + //#[pallet::constant] + //type RelayChainTreasuryAccountId: Get; + ///Handles converting weight to fee value type WeightToFee: WeightToFeePolynomial; @@ -154,14 +169,18 @@ pub mod pallet { ///failed to process liquidation ProcessLiquidationError, + + ///xcm error + XcmError, } #[pallet::hooks] impl Hooks> for Pallet where - T::AccountId: From, + T::AccountId: From + Into, ::RuntimeCall: From>, ::Balance: From>, + T: pallet_xcm::Config, { fn on_finalize(n: BlockNumberFor) { let base_account = ::from(BASE_ACCOUNT); @@ -252,9 +271,11 @@ pub mod pallet { impl Pallet where - T::AccountId: From, + T::AccountId: From + Into, ::RuntimeCall: From>, ::Balance: From>, + T::XcmSender: SendXcm, + T: pallet_xcm::Config, { fn execute_batch_transfers( transfers: Vec<(T::AccountId, BalanceOf)>, @@ -351,17 +372,27 @@ pub mod pallet { let treasury_ratio = T::TreasuryRatio::get(); let operation_ratio = T::OperationRatio::get(); - let treasury_amount = treasury_ratio * total_profit; + let treasury_amount = treasury_ratio * total_profit / PARACHAIN_TO_RELAYCHAIN_UNIT; let operation_amount = operation_ratio * total_profit; let system_amount = system_ratio * total_profit; let total_collators_profit = total_profit.saturating_sub(treasury_amount + operation_amount + system_amount); - let mut transfers = Vec::new(); + let origin: OriginFor = + frame_system::RawOrigin::Signed(treasury_account.clone()).into(); + + let _send_treasury_profit = Self::send_assets_to_relaychain_treasury( + origin, + treasury_account.into(), + treasury_amount, + ); + let mut transfers = Vec::new(); + /* let treasury_account_profit = treasury_amount.try_into().unwrap_or_else(|_| Zero::zero()); transfers.push((treasury_account, treasury_account_profit)); + */ let operation_account_profit = operation_amount.try_into().unwrap_or_else(|_| Zero::zero()); @@ -392,5 +423,46 @@ pub mod pallet { } Self::execute_batch_transfers(transfers) } + + fn send_assets_to_relaychain_treasury( + origin: OriginFor, + recipient: AccountId32, + amount: u128, + ) -> DispatchResult { + let recipient_account_id = recipient.into(); + + let beneficiary = MultiLocation::new( + 0, + X1(Junction::AccountId32 { + id: recipient_account_id, + network: Some(NetworkId::Rococo), //TODO: Any other networks + }), + ); + + let asset = MultiAsset { + id: Concrete(MultiLocation::new(1, Here)), + fun: Fungibility::Fungible(amount), + }; + + let assets = MultiAssets::from(vec![asset]); + let versioned_assets = VersionedMultiAssets::from(assets); + + match pallet_xcm::Pallet::::reserve_transfer_assets( + origin, + Box::new(VersionedMultiLocation::from(MultiLocation::parent())), + Box::new(VersionedMultiLocation::from(beneficiary)), + Box::new(versioned_assets), + 0, + ) { + Ok(_) => { + frame_support::runtime_print!("reserve_transfer_assets executed successfully."); + }, + Err(e) => { + log::error!("Error occurred while executing reserve_transfer_assets: {:?}", e); + return Err(Error::::XcmError.into()); + }, + } + Ok(()) + } } } diff --git a/pallets/liquidation/src/mock.rs b/pallets/liquidation/src/mock.rs index f9c22d2..c072240 100644 --- a/pallets/liquidation/src/mock.rs +++ b/pallets/liquidation/src/mock.rs @@ -1,14 +1,17 @@ pub(crate) use crate as pallet_liquidation; pub(crate) use crate::Event as LiquidationEvent; +use codec::Encode; +use frame_support::traits::{Everything, Nothing}; use frame_support::{ parameter_types, traits::{ConstU32, ConstU64}, weights::{ - constants::ExtrinsicBaseWeight, WeightToFeeCoefficient, WeightToFeeCoefficients, + constants::ExtrinsicBaseWeight, Weight, WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial, }, }; use frame_system as system; +use frame_system::EnsureRoot; use smallvec::smallvec; use sp_core::H256; use sp_runtime::{ @@ -19,7 +22,15 @@ use sp_runtime::{ use frame_system::pallet_prelude::BlockNumberFor; use pallet_order::OrderGasCost; use sp_consensus_aura::sr25519::AuthorityId as AuraId; -use sp_std::collections::btree_map::BTreeMap; +use sp_std::{cell::RefCell, collections::btree_map::BTreeMap}; +use xcm::latest::{MultiAssets, MultiLocation, SendError, SendResult, SendXcm, Xcm, XcmHash}; +use xcm::prelude::*; +use xcm_builder::{ + AccountId32Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom, + AllowTopLevelPaidExecutionFrom, FixedRateOfFungible, FixedWeightBounds, IsConcrete, + SignedToAccountId32, TakeWeightCredit, +}; +use xcm_executor::XcmExecutor; type Balance = u128; type BlockNumber = u32; @@ -37,6 +48,7 @@ frame_support::construct_runtime!( Pot: pallet_pot::{Pallet, Call, Storage, Event}, Utility: pallet_utility::{Pallet, Call, Storage, Event}, Liquidation: pallet_liquidation::{Pallet, Storage, Event}, + XcmPallet: pallet_xcm::{Pallet, Call, Storage, Event, Origin, Config}, } ); @@ -138,6 +150,8 @@ impl pallet_order::Config for Test { } use pallet_pot::PotNameBtreemap; +use pallet_xcm::TestWeightInfo; + pub type AccountId = AccountId32; parameter_types! { pub const PotNames: [&'static str;3] = ["system", "treasury", "maintenance"]; @@ -153,9 +167,116 @@ impl pallet_pot::Config for Test { type Pots = Pots; } +thread_local! { + pub static SENT_XCM: RefCell)>> = RefCell::new(Vec::new()); +} + +pub(crate) fn fake_message_hash(message: &Xcm) -> XcmHash { + message.using_encoded(sp_io::hashing::blake2_256) +} + +pub struct TestSendXcm; +impl SendXcm for TestSendXcm { + type Ticket = (MultiLocation, Xcm<()>); + fn validate( + dest: &mut Option, + msg: &mut Option>, + ) -> SendResult<(MultiLocation, Xcm<()>)> { + let pair = (dest.take().unwrap(), msg.take().unwrap()); + Ok((pair, MultiAssets::new())) + } + fn deliver(pair: (MultiLocation, Xcm<()>)) -> Result { + let hash = fake_message_hash(&pair.1); + SENT_XCM.with(|q| q.borrow_mut().push(pair)); + Ok(hash) + } +} + +parameter_types! { + pub const BaseXcmWeight: Weight = Weight::from_parts(1_000, 1_000); + pub const MaxInstructions: u32 = 100; + pub const MaxAssetsIntoHolding: u32 = 64; + pub XcmFeesTargetAccount: AccountId = AccountId::new([167u8; 32]); + pub UniversalLocation: InteriorMultiLocation = Here; + pub const AnyNetwork: Option = None; + pub const RelayLocation: MultiLocation = Here.into_location(); + pub CurrencyPerSecondPerByte: (AssetId, u128, u128) = (Concrete(RelayLocation::get()), 1, 1); +} + +pub struct XcmConfig; +pub type Barrier = ( + TakeWeightCredit, + AllowTopLevelPaidExecutionFrom, + AllowKnownQueryResponses, + AllowSubscriptionsFrom, +); + +impl xcm_executor::Config for XcmConfig { + type RuntimeCall = RuntimeCall; + type XcmSender = XcmRouter; + type AssetTransactor = (); + type OriginConverter = (); + type IsReserve = (); + type IsTeleporter = (); + type UniversalLocation = UniversalLocation; + type Barrier = Barrier; + type Weigher = FixedWeightBounds; + type Trader = FixedRateOfFungible; + type ResponseHandler = XcmPallet; + type AssetTrap = XcmPallet; + type AssetLocker = (); + type AssetExchanger = (); + type AssetClaims = XcmPallet; + type SubscriptionService = XcmPallet; + type PalletInstancesInfo = AllPalletsWithSystem; + type MaxAssetsIntoHolding = MaxAssetsIntoHolding; + type FeeManager = (); + //type FeeManager = XcmFeeManagerFromComponents< + // EverythingBut, + // XcmFeeToAccount, + //>; + type MessageExporter = (); + type UniversalAliases = Nothing; + type CallDispatcher = RuntimeCall; + type SafeCallFilter = Everything; + type Aliasers = Nothing; +} + +pub type LocalOriginToLocation = SignedToAccountId32; + +impl pallet_xcm::Config for Test { + type RuntimeEvent = RuntimeEvent; + type SendXcmOrigin = xcm_builder::EnsureXcmOrigin; + type XcmRouter = XcmRouter; + type ExecuteXcmOrigin = xcm_builder::EnsureXcmOrigin; + type XcmExecuteFilter = Everything; + type XcmExecutorConfig = XcmConfig; + type XcmExecutor = XcmExecutor; + type XcmTeleportFilter = (); + type XcmReserveTransferFilter = Everything; + type Weigher = FixedWeightBounds; + type UniversalLocation = UniversalLocation; + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100; + type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; + type AdminOrigin = EnsureRoot; + type TrustedLockers = (); + type SovereignAccountOf = AccountId32Aliases<(), AccountId32>; + type Currency = Balances; + type CurrencyMatcher = IsConcrete; + type MaxLockers = frame_support::traits::ConstU32<8>; + type MaxRemoteLockConsumers = frame_support::traits::ConstU32<0>; + type RemoteLockConsumerIdentifier = (); + type WeightInfo = TestWeightInfo; +} + +pub type XcmRouter = TestSendXcm; + impl pallet_liquidation::Config for Test { type RuntimeEvent = RuntimeEvent; type Currency = Balances; + type XcmSender = XcmRouter; type WeightToFee = WeightToFee; type OrderGasCost = MockOrderGasCostHandler; type SystemRatio = SystemRatio; diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 2ddebbf..cfdc5ed 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -918,6 +918,7 @@ parameter_types! { impl pallet_liquidation::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Currency = Balances; + type XcmSender = xcm_config::XcmRouter; type WeightToFee = WeightToFee; type OrderGasCost = OrderGasCostHandler; type SystemRatio = SystemRatio; From eff9c5013c451466cb3acd68c2d27356c2257214 Mon Sep 17 00:00:00 2001 From: toints Date: Sun, 3 Mar 2024 16:22:01 +0800 Subject: [PATCH 2/4] Fixed: fixed transaction with partial success --- pallets/liquidation/src/lib.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pallets/liquidation/src/lib.rs b/pallets/liquidation/src/lib.rs index 2bab813..7b4c6b7 100644 --- a/pallets/liquidation/src/lib.rs +++ b/pallets/liquidation/src/lib.rs @@ -305,7 +305,7 @@ pub mod pallet { calls.push(utility_call); } - pallet_utility::Pallet::::batch( + pallet_utility::Pallet::::batch_all( frame_system::RawOrigin::Signed(system_account).into(), calls, ) @@ -385,7 +385,7 @@ pub mod pallet { origin, treasury_account.into(), treasury_amount, - ); + )?; let mut transfers = Vec::new(); /* @@ -459,6 +459,7 @@ pub mod pallet { }, Err(e) => { log::error!("Error occurred while executing reserve_transfer_assets: {:?}", e); + Self::deposit_event(Event::Error(Error::::XcmError.into())); return Err(Error::::XcmError.into()); }, } From 7b3ad98a5e417f7223b815c4ea5a1067cb3e0ab9 Mon Sep 17 00:00:00 2001 From: toints Date: Mon, 4 Mar 2024 17:13:18 +0800 Subject: [PATCH 3/4] Fixed: add minimum liquidation threshold --- pallets/liquidation/src/lib.rs | 14 +++++++++++++- runtime/src/lib.rs | 2 ++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/pallets/liquidation/src/lib.rs b/pallets/liquidation/src/lib.rs index 7b4c6b7..3738cf4 100644 --- a/pallets/liquidation/src/lib.rs +++ b/pallets/liquidation/src/lib.rs @@ -91,6 +91,10 @@ pub mod pallet { #[pallet::constant] type ExistentialDeposit: Get; + ///minimum liquidation threshold + #[pallet::constant] + type MinLiquidationThreshold: Get; + /// system accountId #[pallet::constant] type SystemAccountName: Get<&'static str>; @@ -245,7 +249,15 @@ pub mod pallet { *income = income.saturating_add(current_block_fee_u128) }); - if count % T::ProfitDistributionCycle::get() == Zero::zero() { + let min_liquidation_threshold: Balance = + ::MinLiquidationThreshold::get() + .try_into() + .unwrap_or_else(|_| 0); + let profit = TotalIncome::::get().saturating_sub(TotalCost::::get()); + + if profit >= min_liquidation_threshold + && count % T::ProfitDistributionCycle::get() == Zero::zero() + { DistributionBlockCount::::put(BlockNumberFor::::zero()); match Self::distribute_profit() { Ok(_) => { diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index cfdc5ed..e5745d5 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -910,6 +910,7 @@ parameter_types! { pub const OperationRatio: Perbill = Perbill::from_percent(25); // 25% for maintenance pub const ProfitDistributionCycle: BlockNumber = 10; pub const ExistDeposit: Balance = EXISTENTIAL_DEPOSIT; + pub const MinLiquidationThreshold: Balance = MILLIUNIT * 20; pub const SystemAccountName: &'static str = "system"; pub const TreasuryAccountName: &'static str = "treasury"; pub const OperationAccountName: &'static str = "maintenance"; @@ -925,6 +926,7 @@ impl pallet_liquidation::Config for Runtime { type TreasuryRatio = TreasuryRatio; type OperationRatio = OperationRatio; type ExistentialDeposit = ExistDeposit; + type MinLiquidationThreshold = MinLiquidationThreshold; type SystemAccountName = SystemAccountName; type TreasuryAccountName = TreasuryAccountName; type OperationAccountName = OperationAccountName; From 235e57ef5d4c8555a25c86e026b9ad7e08f8b292 Mon Sep 17 00:00:00 2001 From: toints Date: Mon, 4 Mar 2024 17:36:58 +0800 Subject: [PATCH 4/4] Fixed: fixed mock compile failed --- pallets/liquidation/src/mock.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pallets/liquidation/src/mock.rs b/pallets/liquidation/src/mock.rs index c072240..a2b1a09 100644 --- a/pallets/liquidation/src/mock.rs +++ b/pallets/liquidation/src/mock.rs @@ -74,6 +74,7 @@ parameter_types! { pub const OperationRatio: Perbill = Perbill::from_percent(25); // 25% for maintenance pub const ProfitDistributionCycle: BlockNumber = 10; pub const ExistDeposit: Balance = EXISTENTIAL_DEPOSIT; + pub const MinLiquidationThreshold: Balance = MILLIUNIT * 20; pub const SystemAccountName: &'static str = "system"; pub const TreasuryAccountName: &'static str = "treasury"; pub const OperationAccountName: &'static str = "maintenance"; @@ -283,6 +284,7 @@ impl pallet_liquidation::Config for Test { type TreasuryRatio = TreasuryRatio; type OperationRatio = OperationRatio; type ExistentialDeposit = ExistDeposit; + type MinLiquidationThreshold = MinLiquidationThreshold; type SystemAccountName = SystemAccountName; type TreasuryAccountName = TreasuryAccountName; type OperationAccountName = OperationAccountName;