From a6ebec6fd527f1d20dacfcb07c27815653d7a157 Mon Sep 17 00:00:00 2001 From: herryho Date: Thu, 28 Mar 2024 14:36:33 +0800 Subject: [PATCH 1/4] cross-chain-transaction-fee --- Cargo.lock | 1 + integration-tests/bifrost-kusama/src/slp.rs | 2 +- pallets/slp/Cargo.toml | 2 + pallets/slp/src/agents/astar_agent/agent.rs | 44 +++++++++-- pallets/slp/src/agents/common.rs | 35 ++++++++- .../agents/parachain_staking_agent/agent.rs | 8 ++ pallets/slp/src/agents/phala_agent/agent.rs | 38 ++++++++-- .../slp/src/agents/polkadot_agent/agent.rs | 74 ++++++++++++++++--- pallets/slp/src/lib.rs | 52 ++++++++++++- pallets/slp/src/mocks/mock.rs | 3 + pallets/slp/src/mocks/mock_kusama.rs | 6 ++ pallets/slp/src/tests/kusama_tests.rs | 13 ++++ pallets/slp/src/weights.rs | 6 ++ primitives/src/lib.rs | 1 + runtime/bifrost-kusama/src/lib.rs | 2 + .../bifrost-kusama/src/weights/bifrost_slp.rs | 5 ++ runtime/bifrost-polkadot/src/lib.rs | 2 + .../src/weights/bifrost_slp.rs | 5 ++ 18 files changed, 271 insertions(+), 28 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 84e1f3cb7..9fd8f32cb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1808,6 +1808,7 @@ dependencies = [ "bifrost-currencies", "bifrost-parachain-staking", "bifrost-primitives", + "bifrost-stable-pool", "bifrost-vtoken-minting", "bifrost-xcm-interface", "cumulus-primitives-core", diff --git a/integration-tests/bifrost-kusama/src/slp.rs b/integration-tests/bifrost-kusama/src/slp.rs index 97e90fc5c..5e1b10a3b 100644 --- a/integration-tests/bifrost-kusama/src/slp.rs +++ b/integration-tests/bifrost-kusama/src/slp.rs @@ -379,7 +379,7 @@ fn transfer_to() { Kusama::execute_with(|| { assert_eq!( kusama_runtime::Balances::free_balance(&AccountId::from(KSM_DELEGATOR_0_ACCOUNT)), - 10049999921672574 + 10050009921672574 ); }); } diff --git a/pallets/slp/Cargo.toml b/pallets/slp/Cargo.toml index 744061662..8bc788577 100644 --- a/pallets/slp/Cargo.toml +++ b/pallets/slp/Cargo.toml @@ -32,6 +32,7 @@ bifrost-xcm-interface = { workspace = true } bifrost-vtoken-minting = { workspace = true } bifrost-asset-registry = { workspace = true } bifrost-parachain-staking = { workspace = true } +bifrost-stable-pool = { workspace = true } [dev-dependencies] hex = "0.4.3" @@ -72,6 +73,7 @@ std = [ "bifrost-asset-registry/std", "bifrost-parachain-staking/std", "orml-xtokens/std", + "bifrost-stable-pool/std", ] runtime-benchmarks = [ diff --git a/pallets/slp/src/agents/astar_agent/agent.rs b/pallets/slp/src/agents/astar_agent/agent.rs index 7b00b87c8..fb9abee3c 100644 --- a/pallets/slp/src/agents/astar_agent/agent.rs +++ b/pallets/slp/src/agents/astar_agent/agent.rs @@ -129,7 +129,7 @@ impl // Wrap the xcm message as it is sent from a subaccount of the parachain account, and // send it out. - let (query_id, timeout, _fee, xcm_message) = + let (query_id, timeout, fee, xcm_message) = Pallet::::construct_xcm_as_subaccount_with_query_id( XcmOperationType::Bond, call.encode(), @@ -138,6 +138,10 @@ impl weight_and_fee, )?; + // withdraw this xcm fee from treasury. If treasury doesn't have this money, stop the + // process. + Pallet::::burn_fee_from_source_account(fee, currency_id)?; + // Insert a delegator ledger update record into DelegatorLedgerXcmUpdateQueue. Self::insert_delegator_ledger_update_entry( who, @@ -171,7 +175,7 @@ impl // Wrap the xcm message as it is sent from a subaccount of the parachain account, and // send it out. - Pallet::::construct_xcm_and_send_as_subaccount_without_query_id( + let fee = Pallet::::construct_xcm_and_send_as_subaccount_without_query_id( XcmOperationType::Payout, call, who, @@ -179,6 +183,10 @@ impl weight_and_fee, )?; + // withdraw this xcm fee from treasury. If treasury doesn't have this money, stop the + // process. + Pallet::::burn_fee_from_source_account(fee, currency_id)?; + Ok(Zero::zero()) } @@ -220,7 +228,7 @@ impl // Wrap the xcm message as it is sent from a subaccount of the parachain account, and // send it out. - let (query_id, timeout, _, xcm_message) = + let (query_id, timeout, fee, xcm_message) = Pallet::::construct_xcm_as_subaccount_with_query_id( XcmOperationType::Unbond, call.encode(), @@ -229,6 +237,10 @@ impl weight_and_fee, )?; + // withdraw this xcm fee from treasury. If treasury doesn't have this money, stop the + // process. + Pallet::::burn_fee_from_source_account(fee, currency_id)?; + // Insert a delegator ledger update record into DelegatorLedgerXcmUpdateQueue. Self::insert_delegator_ledger_update_entry( who, @@ -323,7 +335,7 @@ impl // Wrap the xcm message as it is sent from a subaccount of the parachain account, and // send it out. - Pallet::::construct_xcm_and_send_as_subaccount_without_query_id( + let fee = Pallet::::construct_xcm_and_send_as_subaccount_without_query_id( XcmOperationType::Payout, call, who, @@ -331,6 +343,10 @@ impl weight_and_fee, )?; + // withdraw this xcm fee from treasury. If treasury doesn't have this money, stop the + // process. + Pallet::::burn_fee_from_source_account(fee, currency_id)?; + Ok(Zero::zero()) } @@ -355,7 +371,7 @@ impl // Wrap the xcm message as it is sent from a subaccount of the parachain account, and // send it out. - let (query_id, timeout, _fee, xcm_message) = + let (query_id, timeout, fee, xcm_message) = Pallet::::construct_xcm_as_subaccount_with_query_id( XcmOperationType::Liquidize, call.encode(), @@ -364,6 +380,10 @@ impl weight_and_fee, )?; + // withdraw this xcm fee from treasury. If treasury doesn't have this money, stop the + // process. + Pallet::::burn_fee_from_source_account(fee, currency_id)?; + // Insert a delegator ledger update record into DelegatorLedgerXcmUpdateQueue. Self::insert_delegator_ledger_update_entry( who, @@ -450,7 +470,7 @@ impl // Wrap the xcm message as it is sent from a subaccount of the parachain account, and // send it out. - Pallet::::construct_xcm_and_send_as_subaccount_without_query_id( + let fee = Pallet::::construct_xcm_and_send_as_subaccount_without_query_id( XcmOperationType::TransferBack, call.encode(), from, @@ -458,6 +478,10 @@ impl weight_and_fee, )?; + // withdraw this xcm fee from treasury. If treasury doesn't have this money, stop the + // process. + Pallet::::burn_fee_from_source_account(fee, currency_id)?; + Ok(()) } @@ -481,6 +505,14 @@ impl let (entrance_account, _) = T::VtokenMinting::get_entrance_and_exit_accounts(); ensure!(from_account_id == entrance_account, Error::::InvalidAccount); + // transfer supplementary fee from treasury to the "from" account. Return the added up + // amount + let amount = Pallet::::get_transfer_to_added_amount_and_supplement( + from_account_id, + amount, + currency_id, + )?; + Pallet::::do_transfer_to(from, to, amount, currency_id)?; Ok(()) diff --git a/pallets/slp/src/agents/common.rs b/pallets/slp/src/agents/common.rs index 911c62faa..b541b7e2f 100644 --- a/pallets/slp/src/agents/common.rs +++ b/pallets/slp/src/agents/common.rs @@ -21,9 +21,10 @@ use crate::{ ParachainStakingLedgerUpdateEntry, ParachainStakingLedgerUpdateOperation, TIMEOUT_BLOCKS, }, traits::QueryResponseManager, - vec, BalanceOf, BlockNumberFor, BoundedVec, Box, Config, CurrencyDelays, DelegationsOccupied, - DelegatorLatestTuneRecord, DelegatorLedgerXcmUpdateQueue, DelegatorLedgers, DelegatorNextIndex, - DelegatorsIndex2Multilocation, DelegatorsMultilocation2Index, Encode, Event, FeeSources, + vec, AccountIdOf, BalanceOf, BlockNumberFor, BoundedVec, Box, Config, CurrencyDelays, + DelegationsOccupied, DelegatorLatestTuneRecord, DelegatorLedgerXcmUpdateQueue, + DelegatorLedgers, DelegatorNextIndex, DelegatorsIndex2Multilocation, + DelegatorsMultilocation2Index, Encode, Event, FeeSources, Junction::{AccountId32, Parachain}, Junctions::X1, Ledger, LedgerUpdateEntry, MinimumsAndMaximums, MultiLocation, Pallet, TimeUnit, Validators, @@ -35,7 +36,7 @@ use orml_traits::{MultiCurrency, XcmTransfer}; use polkadot_parachain_primitives::primitives::Sibling; use sp_core::{Get, U256}; use sp_runtime::{ - traits::{AccountIdConversion, UniqueSaturatedFrom, UniqueSaturatedInto}, + traits::{AccountIdConversion, CheckedAdd, UniqueSaturatedFrom, UniqueSaturatedInto}, DispatchResult, Saturating, }; use xcm::{opaque::v3::Instruction, v3::prelude::*, VersionedMultiLocation}; @@ -629,4 +630,30 @@ impl Pallet { Ok(Some(unlock_time_unit)) } + + pub(crate) fn get_transfer_to_added_amount_and_supplement( + from: AccountIdOf, + amount: BalanceOf, + currency_id: CurrencyId, + ) -> Result, Error> { + // get transfer_to extra fee + let (_weight, supplementary_fee) = T::XcmWeightAndFeeHandler::get_operation_weight_and_fee( + currency_id, + XcmOperationType::TransferTo, + ) + .ok_or(Error::::WeightAndFeeNotExists)?; + + // transfer supplementary_fee from treasury to "from" account + // get fee source first + let (source_location, _reserved_fee) = + FeeSources::::get(currency_id).ok_or(Error::::FeeSourceNotExist)?; + let source_account = Self::native_multilocation_to_account(&source_location)?; + + // transfer supplementary_fee from treasury to "from" account + T::MultiCurrency::transfer(currency_id, &source_account, &from, supplementary_fee) + .map_err(|_| Error::::Unexpected)?; + let added_amount = amount.checked_add(&supplementary_fee).ok_or(Error::::OverFlow)?; + + Ok(added_amount) + } } diff --git a/pallets/slp/src/agents/parachain_staking_agent/agent.rs b/pallets/slp/src/agents/parachain_staking_agent/agent.rs index b1cb100bb..f142c3f9b 100644 --- a/pallets/slp/src/agents/parachain_staking_agent/agent.rs +++ b/pallets/slp/src/agents/parachain_staking_agent/agent.rs @@ -1448,6 +1448,14 @@ impl T::MultiCurrency::transfer(currency_id, &from_account_id, &to_account, amount) .map_err(|_| Error::::Unexpected)?; } else { + // transfer supplementary fee from treasury to the "from" account. Return the added up + // amount + let amount = Pallet::::get_transfer_to_added_amount_and_supplement( + from_account_id, + amount, + currency_id, + )?; + Pallet::::do_transfer_to(from, to, amount, currency_id)?; } diff --git a/pallets/slp/src/agents/phala_agent/agent.rs b/pallets/slp/src/agents/phala_agent/agent.rs index 84cb5119a..8b617335a 100644 --- a/pallets/slp/src/agents/phala_agent/agent.rs +++ b/pallets/slp/src/agents/phala_agent/agent.rs @@ -136,7 +136,7 @@ impl // Wrap the xcm message as it is sent from a subaccount of the parachain account, and // send it out. - let (query_id, timeout, _fee, xcm_message) = + let (query_id, timeout, fee, xcm_message) = Pallet::::construct_xcm_as_subaccount_with_query_id( XcmOperationType::Bond, calls, @@ -145,6 +145,10 @@ impl weight_and_fee, )?; + // withdraw this xcm fee from treasury. If treasury doesn't have this money, stop the + // process. + Pallet::::burn_fee_from_source_account(fee, currency_id)?; + // Calculate how many shares we can get by the amount at current price let shares = if let Some(MultiLocation { parents: _, @@ -253,7 +257,7 @@ impl // Wrap the xcm message as it is sent from a subaccount of the parachain account, and // send it out. - let (query_id, timeout, _fee, xcm_message) = + let (query_id, timeout, fee, xcm_message) = Pallet::::construct_xcm_as_subaccount_with_query_id( XcmOperationType::Unbond, call, @@ -262,6 +266,10 @@ impl weight_and_fee, )?; + // withdraw this xcm fee from treasury. If treasury doesn't have this money, stop the + // process. + Pallet::::burn_fee_from_source_account(fee, currency_id)?; + // Insert a delegator ledger update record into DelegatorLedgerXcmUpdateQueue. Self::insert_delegator_ledger_update_entry( who, @@ -487,7 +495,7 @@ impl // Wrap the xcm message as it is sent from a subaccount of the parachain account, and // send it out. - let (query_id, _timeout, _fee, xcm_message) = + let (query_id, _timeout, fee, xcm_message) = Pallet::::construct_xcm_as_subaccount_with_query_id( XcmOperationType::Payout, call, @@ -496,6 +504,10 @@ impl weight_and_fee, )?; + // withdraw this xcm fee from treasury. If treasury doesn't have this money, stop the + // process. + Pallet::::burn_fee_from_source_account(fee, currency_id)?; + // Send out the xcm message. let dest = Pallet::::get_para_multilocation_by_currency_id(currency_id)?; send_xcm::(dest, xcm_message).map_err(|_e| Error::::XcmFailure)?; @@ -588,7 +600,7 @@ impl // Wrap the xcm message as it is sent from a subaccount of the parachain account, and // send it out. - Pallet::::construct_xcm_and_send_as_subaccount_without_query_id( + let fee = Pallet::::construct_xcm_and_send_as_subaccount_without_query_id( XcmOperationType::TransferBack, call.encode(), from, @@ -596,6 +608,10 @@ impl weight_and_fee, )?; + // withdraw this xcm fee from treasury. If treasury doesn't have this money, stop the + // process. + Pallet::::burn_fee_from_source_account(fee, currency_id)?; + Ok(()) } @@ -619,6 +635,14 @@ impl let (entrance_account, _) = T::VtokenMinting::get_entrance_and_exit_accounts(); ensure!(from_account_id == entrance_account, Error::::InvalidAccount); + // transfer supplementary fee from treasury to the "from" account. Return the added up + // amount + let amount = Pallet::::get_transfer_to_added_amount_and_supplement( + from_account_id, + amount, + currency_id, + )?; + Pallet::::do_transfer_to(from, to, amount, currency_id)?; Ok(()) @@ -653,7 +677,7 @@ impl // Wrap the xcm message as it is sent from a subaccount of the parachain account, and // send it out. - let (query_id, _timeout, _fee, xcm_message) = + let (query_id, _timeout, fee, xcm_message) = Pallet::::construct_xcm_as_subaccount_with_query_id( XcmOperationType::ConvertAsset, call.encode(), @@ -662,6 +686,10 @@ impl weight_and_fee, )?; + // withdraw this xcm fee from treasury. If treasury doesn't have this money, stop the + // process. + Pallet::::burn_fee_from_source_account(fee, currency_id)?; + // Send out the xcm message. let dest = Pallet::::get_para_multilocation_by_currency_id(currency_id)?; send_xcm::(dest, xcm_message).map_err(|_e| Error::::XcmFailure)?; diff --git a/pallets/slp/src/agents/polkadot_agent/agent.rs b/pallets/slp/src/agents/polkadot_agent/agent.rs index 98ed5f1a0..cc2f297fd 100644 --- a/pallets/slp/src/agents/polkadot_agent/agent.rs +++ b/pallets/slp/src/agents/polkadot_agent/agent.rs @@ -119,7 +119,7 @@ impl // Wrap the xcm message as it is sent from a subaccount of the parachain account, and // send it out. - let (query_id, timeout, _fee, xcm_message) = + let (query_id, timeout, fee, xcm_message) = Pallet::::construct_xcm_as_subaccount_with_query_id( XcmOperationType::Bond, call, @@ -128,6 +128,10 @@ impl weight_and_fee, )?; + // withdraw this xcm fee from treasury. If treasury doesn't have this money, stop the + // process. + Pallet::::burn_fee_from_source_account(fee, currency_id)?; + // Create a new delegator ledger // The real bonded amount will be updated by services once the xcm transaction succeeds. let ledger = SubstrateLedger::> { @@ -196,7 +200,7 @@ impl // Wrap the xcm message as it is sent from a subaccount of the parachain account, and // send it out. - let (query_id, timeout, _fee, xcm_message) = + let (query_id, timeout, fee, xcm_message) = Pallet::::construct_xcm_as_subaccount_with_query_id( XcmOperationType::BondExtra, call, @@ -205,6 +209,10 @@ impl weight_and_fee, )?; + // withdraw this xcm fee from treasury. If treasury doesn't have this money, stop the + // process. + Pallet::::burn_fee_from_source_account(fee, currency_id)?; + // Insert a delegator ledger update record into DelegatorLedgerXcmUpdateQueue. Self::insert_delegator_ledger_update_entry( who, @@ -269,7 +277,7 @@ impl // Wrap the xcm message as it is sent from a subaccount of the parachain account, and // send it out. - let (query_id, timeout, _fee, xcm_message) = + let (query_id, timeout, fee, xcm_message) = Pallet::::construct_xcm_as_subaccount_with_query_id( XcmOperationType::Unbond, call, @@ -278,6 +286,10 @@ impl weight_and_fee, )?; + // withdraw this xcm fee from treasury. If treasury doesn't have this money, stop the + // process. + Pallet::::burn_fee_from_source_account(fee, currency_id)?; + // Insert a delegator ledger update record into DelegatorLedgerXcmUpdateQueue. Self::insert_delegator_ledger_update_entry( who, @@ -318,7 +330,7 @@ impl // Wrap the xcm message as it is sent from a subaccount of the parachain account, and // send it out. - let (query_id, timeout, _fee, xcm_message) = + let (query_id, timeout, fee, xcm_message) = Pallet::::construct_xcm_as_subaccount_with_query_id( XcmOperationType::Unbond, call, @@ -327,6 +339,10 @@ impl weight_and_fee, )?; + // withdraw this xcm fee from treasury. If treasury doesn't have this money, stop the + // process. + Pallet::::burn_fee_from_source_account(fee, currency_id)?; + // Insert a delegator ledger update record into DelegatorLedgerXcmUpdateQueue. Self::insert_delegator_ledger_update_entry( who, @@ -389,7 +405,7 @@ impl // Wrap the xcm message as it is sent from a subaccount of the parachain account, and // send it out. - let (query_id, timeout, _fee, xcm_message) = + let (query_id, timeout, fee, xcm_message) = Pallet::::construct_xcm_as_subaccount_with_query_id( XcmOperationType::Rebond, call, @@ -398,6 +414,10 @@ impl weight_and_fee, )?; + // withdraw this xcm fee from treasury. If treasury doesn't have this money, stop the + // process. + Pallet::::burn_fee_from_source_account(fee, currency_id)?; + // Insert a delegator ledger update record into DelegatorLedgerXcmUpdateQueue. Self::insert_delegator_ledger_update_entry( who, @@ -457,7 +477,7 @@ impl // Wrap the xcm message as it is sent from a subaccount of the parachain account, and // send it out. - let (query_id, timeout, _fee, xcm_message) = + let (query_id, timeout, fee, xcm_message) = Pallet::::construct_xcm_as_subaccount_with_query_id( XcmOperationType::Delegate, call, @@ -466,6 +486,10 @@ impl weight_and_fee, )?; + // withdraw this xcm fee from treasury. If treasury doesn't have this money, stop the + // process. + Pallet::::burn_fee_from_source_account(fee, currency_id)?; + // Insert a query record to the ValidatorsByDelegatorXcmUpdateQueue storage. Self::insert_validators_by_delegator_update_entry( who, @@ -531,7 +555,7 @@ impl }; // Wrap the xcm message as it is sent from a subaccount of the parachain account, and // send it out. - let (query_id, timeout, _fee, xcm_message) = + let (query_id, timeout, fee, xcm_message) = Pallet::::construct_xcm_as_subaccount_with_query_id( XcmOperationType::Delegate, call, @@ -540,6 +564,10 @@ impl weight_and_fee, )?; + // withdraw this xcm fee from treasury. If treasury doesn't have this money, stop the + // process. + Pallet::::burn_fee_from_source_account(fee, currency_id)?; + // Insert a query record to the ValidatorsByDelegatorXcmUpdateQueue storage. Self::insert_validators_by_delegator_update_entry( who, @@ -602,7 +630,7 @@ impl // Wrap the xcm message as it is sent from a subaccount of the parachain account, and // send it out. - Pallet::::construct_xcm_and_send_as_subaccount_without_query_id( + let fee = Pallet::::construct_xcm_and_send_as_subaccount_without_query_id( XcmOperationType::Payout, call, who, @@ -610,6 +638,10 @@ impl weight_and_fee, )?; + // withdraw this xcm fee from treasury. If treasury doesn't have this money, stop the + // process. + Pallet::::burn_fee_from_source_account(fee, currency_id)?; + // Both tokenpool increment and delegator ledger update need to be conducted by backend // services. @@ -650,7 +682,7 @@ impl // Wrap the xcm message as it is sent from a subaccount of the parachain account, and // send it out. - let (query_id, timeout, _fee, xcm_message) = + let (query_id, timeout, fee, xcm_message) = Pallet::::construct_xcm_as_subaccount_with_query_id( XcmOperationType::Liquidize, call, @@ -659,6 +691,10 @@ impl weight_and_fee, )?; + // withdraw this xcm fee from treasury. If treasury doesn't have this money, stop the + // process. + Pallet::::burn_fee_from_source_account(fee, currency_id)?; + // Insert a delegator ledger update record into DelegatorLedgerXcmUpdateQueue. Self::insert_delegator_ledger_update_entry( who, @@ -700,7 +736,7 @@ impl // Wrap the xcm message as it is sent from a subaccount of the parachain account, and // send it out. - let (query_id, timeout, _fee, xcm_message) = + let (query_id, timeout, fee, xcm_message) = Pallet::::construct_xcm_as_subaccount_with_query_id( XcmOperationType::Chill, call, @@ -709,6 +745,10 @@ impl weight_and_fee, )?; + // withdraw this xcm fee from treasury. If treasury doesn't have this money, stop the + // process. + Pallet::::burn_fee_from_source_account(fee, currency_id)?; + // Get active amount, if not zero, create an update entry. let ledger = DelegatorLedgers::::get(currency_id, who).ok_or(Error::::DelegatorNotBonded)?; @@ -791,7 +831,7 @@ impl // Wrap the xcm message as it is sent from a subaccount of the parachain account, and // send it out. - Pallet::::construct_xcm_and_send_as_subaccount_without_query_id( + let fee = Pallet::::construct_xcm_and_send_as_subaccount_without_query_id( XcmOperationType::TransferBack, call, from, @@ -799,6 +839,10 @@ impl weight_and_fee, )?; + // withdraw this xcm fee from treasury. If treasury doesn't have this money, stop the + // process. + Pallet::::burn_fee_from_source_account(fee, currency_id)?; + Ok(()) } @@ -822,6 +866,14 @@ impl let (entrance_account, _) = T::VtokenMinting::get_entrance_and_exit_accounts(); ensure!(from_account_id == entrance_account, Error::::InvalidAccount); + // transfer supplementary fee from treasury to the "from" account. Return the added up + // amount + let amount = Pallet::::get_transfer_to_added_amount_and_supplement( + from_account_id, + amount, + currency_id, + )?; + Pallet::::do_transfer_to(from, to, amount, currency_id)?; Ok(()) diff --git a/pallets/slp/src/lib.rs b/pallets/slp/src/lib.rs index 999c3688c..ef066bfef 100644 --- a/pallets/slp/src/lib.rs +++ b/pallets/slp/src/lib.rs @@ -36,8 +36,10 @@ use bifrost_primitives::{ currency::{BNC, KSM, MANTA, MOVR, PHA}, traits::XcmDestWeightAndFeeHandler, CurrencyId, CurrencyIdExt, DerivativeAccountHandler, DerivativeIndex, SlpHostingFeeProvider, - SlpOperator, TimeUnit, VtokenMintingOperator, XcmOperationType, ASTR, DOT, FIL, GLMR, + SlpOperator, TimeUnit, TokenInfo, VtokenMintingOperator, XcmOperationType, ASTR, DOT, FIL, + GLMR, }; +use bifrost_stable_pool::traits::StablePoolHandler; use cumulus_primitives_core::{relay_chain::HashT, ParaId}; use frame_support::{pallet_prelude::*, traits::Contains, weights::Weight}; use frame_system::{ @@ -164,6 +166,15 @@ pub mod pallet { BalanceOf, AccountIdOf, >; + + type StablePoolHandler: StablePoolHandler< + Balance = BalanceOf, + AccountId = AccountIdOf, + CurrencyId = CurrencyId, + >; + + #[pallet::constant] + type TreasuryAccount: Get; } #[pallet::error] @@ -246,6 +257,9 @@ pub mod pallet { ExceedMaxLengthLimit, /// Transfer to failed TransferToError, + StablePoolNotFound, + StablePoolTokenIndexNotFound, + ExceedLimit, } #[pallet::event] @@ -2358,6 +2372,42 @@ pub mod pallet { Ok(()) } + + #[pallet::call_index(47)] + #[pallet::weight(::WeightInfo::convert_treasury_vtoken())] + pub fn convert_treasury_vtoken( + origin: OriginFor, + vtoken: CurrencyId, + amount: BalanceOf, + ) -> DispatchResult { + T::ControlOrigin::ensure_origin(origin)?; + ensure!(amount > Zero::zero(), Error::::AmountZero); + + let token = vtoken.to_token().map_err(|_| Error::::NotSupportedCurrencyId)?; + let (pool_id, _, _) = T::StablePoolHandler::get_pool_id(&vtoken, &token) + .ok_or(Error::::StablePoolNotFound)?; + + let vtoken_index = T::StablePoolHandler::get_pool_token_index(pool_id, vtoken) + .ok_or(Error::::StablePoolTokenIndexNotFound)?; + let token_index = T::StablePoolHandler::get_pool_token_index(pool_id, token) + .ok_or(Error::::StablePoolTokenIndexNotFound)?; + + // ensure swap balance not exceed a 10 unit + let decimals = token.decimals().unwrap_or_default(); + let max_amount = decimals.checked_mul(10).ok_or(Error::::OverFlow)?; + ensure!(amount <= BalanceOf::::from(max_amount), Error::::ExceedLimit); + + // swap vtoken from treasury account for token + let treasury = T::TreasuryAccount::get(); + T::StablePoolHandler::swap( + &treasury, + pool_id, + vtoken_index, + token_index, + amount, + Zero::zero(), + ) + } } impl Pallet { diff --git a/pallets/slp/src/mocks/mock.rs b/pallets/slp/src/mocks/mock.rs index 3519cd97b..6538ff9d1 100644 --- a/pallets/slp/src/mocks/mock.rs +++ b/pallets/slp/src/mocks/mock.rs @@ -403,6 +403,7 @@ parameter_types! { pub const MaxTypeEntryPerBlock: u32 = 10; pub const MaxRefundPerBlock: u32 = 10; pub const MaxLengthLimit: u32 = 100; + pub BifrostTreasuryAccount: AccountId = PalletId(*b"bf/trsry").into_account_truncating(); } impl QueryResponseManager for () { @@ -467,6 +468,8 @@ impl Config for Runtime { type MaxLengthLimit = MaxLengthLimit; type XcmWeightAndFeeHandler = XcmDestWeightAndFee; type ChannelCommission = (); + type StablePoolHandler = (); + type TreasuryAccount = BifrostTreasuryAccount; } pub struct XcmDestWeightAndFee; diff --git a/pallets/slp/src/mocks/mock_kusama.rs b/pallets/slp/src/mocks/mock_kusama.rs index 13d477254..3957af5b1 100644 --- a/pallets/slp/src/mocks/mock_kusama.rs +++ b/pallets/slp/src/mocks/mock_kusama.rs @@ -492,6 +492,10 @@ impl QueryResponseManager for Substrat } } +parameter_types! { + pub BifrostTreasuryAccount: AccountId = PalletId(*b"bf/trsry").into_account_truncating(); +} + impl Config for Runtime { type RuntimeEvent = RuntimeEvent; type RuntimeOrigin = RuntimeOrigin; @@ -512,6 +516,8 @@ impl Config for Runtime { type MaxLengthLimit = MaxLengthLimit; type XcmWeightAndFeeHandler = XcmDestWeightAndFee; type ChannelCommission = (); + type StablePoolHandler = (); + type TreasuryAccount = BifrostTreasuryAccount; } pub struct XcmDestWeightAndFee; diff --git a/pallets/slp/src/tests/kusama_tests.rs b/pallets/slp/src/tests/kusama_tests.rs index c367ac970..217695b50 100644 --- a/pallets/slp/src/tests/kusama_tests.rs +++ b/pallets/slp/src/tests/kusama_tests.rs @@ -539,6 +539,19 @@ fn bond_works() { ExtBuilder::default().build().execute_with(|| { register_subaccount_index_0(); + let bob_32 = Pallet::::account_id_to_account_32(BOB).unwrap(); + let bob_location = Pallet::::account_32_to_local_location(bob_32).unwrap(); + + // set fee source to Bob + assert_ok!(Slp::set_fee_source( + RuntimeOrigin::signed(ALICE), + DOT, + Some((bob_location, 1_000_000_000_000)) + )); + + // deposit some DOT to Bob, for transfer fee burning + assert_ok!(Currencies::deposit(DOT, &BOB, 2_000_000_000_000)); + // Bond 1 ksm for sub-account index 0 assert_ok!(Slp::bond( RuntimeOrigin::signed(ALICE), diff --git a/pallets/slp/src/weights.rs b/pallets/slp/src/weights.rs index 1f4733b93..01b151ccf 100644 --- a/pallets/slp/src/weights.rs +++ b/pallets/slp/src/weights.rs @@ -97,6 +97,7 @@ pub trait WeightInfo { fn set_validator_boost_list() -> Weight; fn add_to_validator_boost_list() -> Weight; fn remove_from_validator_boot_list() -> Weight; + fn convert_treasury_vtoken() -> Weight; } // For backwards compatibility and tests @@ -835,4 +836,9 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } + fn convert_treasury_vtoken() -> Weight { + Weight::from_parts(42_190_000, 3911) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } } diff --git a/primitives/src/lib.rs b/primitives/src/lib.rs index dcf7710f2..510fcabf1 100644 --- a/primitives/src/lib.rs +++ b/primitives/src/lib.rs @@ -336,6 +336,7 @@ pub enum XcmOperationType { Vote, RemoveVote, Any, + SupplementaryFee, } pub struct ExtraFeeInfo { diff --git a/runtime/bifrost-kusama/src/lib.rs b/runtime/bifrost-kusama/src/lib.rs index 6e037eb02..0ad5868fa 100644 --- a/runtime/bifrost-kusama/src/lib.rs +++ b/runtime/bifrost-kusama/src/lib.rs @@ -1422,6 +1422,8 @@ impl bifrost_slp::Config for Runtime { type MaxLengthLimit = MaxLengthLimit; type XcmWeightAndFeeHandler = XcmInterface; type ChannelCommission = ChannelCommission; + type StablePoolHandler = StablePool; + type TreasuryAccount = BifrostTreasuryAccount; } impl bifrost_vstoken_conversion::Config for Runtime { diff --git a/runtime/bifrost-kusama/src/weights/bifrost_slp.rs b/runtime/bifrost-kusama/src/weights/bifrost_slp.rs index 52bdd66e0..53f9ffc70 100644 --- a/runtime/bifrost-kusama/src/weights/bifrost_slp.rs +++ b/runtime/bifrost-kusama/src/weights/bifrost_slp.rs @@ -788,4 +788,9 @@ impl bifrost_slp::WeightInfo for BifrostWeight { .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } + fn convert_treasury_vtoken() -> Weight { + Weight::from_parts(42_190_000, 3911) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } } diff --git a/runtime/bifrost-polkadot/src/lib.rs b/runtime/bifrost-polkadot/src/lib.rs index 3d593ca0b..b5d03a29c 100644 --- a/runtime/bifrost-polkadot/src/lib.rs +++ b/runtime/bifrost-polkadot/src/lib.rs @@ -1249,6 +1249,8 @@ impl bifrost_slp::Config for Runtime { type MaxLengthLimit = MaxLengthLimit; type XcmWeightAndFeeHandler = XcmInterface; type ChannelCommission = ChannelCommission; + type StablePoolHandler = StablePool; + type TreasuryAccount = BifrostTreasuryAccount; } parameter_types! { diff --git a/runtime/bifrost-polkadot/src/weights/bifrost_slp.rs b/runtime/bifrost-polkadot/src/weights/bifrost_slp.rs index 52bdd66e0..53f9ffc70 100644 --- a/runtime/bifrost-polkadot/src/weights/bifrost_slp.rs +++ b/runtime/bifrost-polkadot/src/weights/bifrost_slp.rs @@ -788,4 +788,9 @@ impl bifrost_slp::WeightInfo for BifrostWeight { .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } + fn convert_treasury_vtoken() -> Weight { + Weight::from_parts(42_190_000, 3911) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } } From f1c231c4aa581f5e72b516b3143d165beadada80 Mon Sep 17 00:00:00 2001 From: herryho Date: Thu, 28 Mar 2024 15:50:44 +0800 Subject: [PATCH 2/4] fixes --- pallets/fee-share/src/mock.rs | 4 +++- pallets/slpx/src/mock.rs | 2 ++ pallets/system-maker/src/mock.rs | 4 +++- pallets/system-staking/src/mock.rs | 2 ++ pallets/ve-minting/src/mock.rs | 7 +++++++ pallets/vtoken-minting/src/mock.rs | 7 +++++++ 6 files changed, 24 insertions(+), 2 deletions(-) diff --git a/pallets/fee-share/src/mock.rs b/pallets/fee-share/src/mock.rs index db657f8cb..827642c33 100644 --- a/pallets/fee-share/src/mock.rs +++ b/pallets/fee-share/src/mock.rs @@ -57,7 +57,7 @@ use crate as bifrost_fee_share; pub type BlockNumber = u64; pub type Amount = i128; -pub type Balance = u64; +pub type Balance = u128; pub type AccountId = AccountId32; pub const ALICE: AccountId = AccountId32::new([0u8; 32]); @@ -301,6 +301,8 @@ impl bifrost_slp::Config for Runtime { type MaxLengthLimit = MaxLengthLimit; type XcmWeightAndFeeHandler = (); type ChannelCommission = (); + type StablePoolHandler = (); + type TreasuryAccount = TreasuryAccount; } parameter_type_with_key! { diff --git a/pallets/slpx/src/mock.rs b/pallets/slpx/src/mock.rs index 7c3b2bb60..090449b08 100644 --- a/pallets/slpx/src/mock.rs +++ b/pallets/slpx/src/mock.rs @@ -501,6 +501,8 @@ impl bifrost_slp::Config for Test { type MaxLengthLimit = MaxLengthLimit; type XcmWeightAndFeeHandler = (); type ChannelCommission = (); + type StablePoolHandler = (); + type TreasuryAccount = BifrostFeeAccount; } #[cfg(feature = "runtime-benchmarks")] diff --git a/pallets/system-maker/src/mock.rs b/pallets/system-maker/src/mock.rs index f9bcf9662..75b86e5fc 100644 --- a/pallets/system-maker/src/mock.rs +++ b/pallets/system-maker/src/mock.rs @@ -57,7 +57,7 @@ use crate as bifrost_system_maker; pub type BlockNumber = u64; pub type Amount = i128; -pub type Balance = u64; +pub type Balance = u128; pub type AccountId = AccountId32; pub const ALICE: AccountId = AccountId32::new([0u8; 32]); @@ -308,6 +308,8 @@ impl bifrost_slp::Config for Runtime { type MaxLengthLimit = MaxLengthLimit; type XcmWeightAndFeeHandler = (); type ChannelCommission = (); + type StablePoolHandler = (); + type TreasuryAccount = TreasuryAccount; } parameter_type_with_key! { diff --git a/pallets/system-staking/src/mock.rs b/pallets/system-staking/src/mock.rs index 07d0dcea9..f873d7977 100644 --- a/pallets/system-staking/src/mock.rs +++ b/pallets/system-staking/src/mock.rs @@ -331,6 +331,8 @@ impl bifrost_slp::Config for Runtime { type MaxLengthLimit = MaxLengthLimit; type XcmWeightAndFeeHandler = (); type ChannelCommission = (); + type StablePoolHandler = (); + type TreasuryAccount = TreasuryAccount; } parameter_types! { diff --git a/pallets/ve-minting/src/mock.rs b/pallets/ve-minting/src/mock.rs index c0bb5b044..88401d1e4 100644 --- a/pallets/ve-minting/src/mock.rs +++ b/pallets/ve-minting/src/mock.rs @@ -359,6 +359,11 @@ impl SlpxOperator for SlpxInterface { } } +pub const TREASURY_ACCOUNT: AccountId = AccountId32::new([9u8; 32]); +parameter_types! { + pub const TreasuryAccount: AccountId32 = TREASURY_ACCOUNT; +} + impl bifrost_slp::Config for Runtime { type RuntimeEvent = RuntimeEvent; type RuntimeOrigin = RuntimeOrigin; @@ -379,6 +384,8 @@ impl bifrost_slp::Config for Runtime { type MaxLengthLimit = MaxLengthLimit; type XcmWeightAndFeeHandler = (); type ChannelCommission = (); + type StablePoolHandler = (); + type TreasuryAccount = TreasuryAccount; } parameter_types! { diff --git a/pallets/vtoken-minting/src/mock.rs b/pallets/vtoken-minting/src/mock.rs index fab99b559..23a0a6c0d 100644 --- a/pallets/vtoken-minting/src/mock.rs +++ b/pallets/vtoken-minting/src/mock.rs @@ -339,6 +339,11 @@ impl SlpxOperator for SlpxInterface { } } +pub const TREASURY_ACCOUNT: AccountId = AccountId32::new([9u8; 32]); +parameter_types! { + pub const TreasuryAccount: AccountId32 = TREASURY_ACCOUNT; +} + impl bifrost_slp::Config for Runtime { type RuntimeEvent = RuntimeEvent; type RuntimeOrigin = RuntimeOrigin; @@ -359,6 +364,8 @@ impl bifrost_slp::Config for Runtime { type MaxLengthLimit = MaxLengthLimit; type XcmWeightAndFeeHandler = (); type ChannelCommission = (); + type StablePoolHandler = (); + type TreasuryAccount = TreasuryAccount; } parameter_types! { From 1c02fac800e7f14430cce97476cb53b5f9ddf6eb Mon Sep 17 00:00:00 2001 From: herryho Date: Fri, 29 Mar 2024 00:20:23 +0800 Subject: [PATCH 3/4] fix benchmarks --- pallets/slp/src/benchmarking.rs | 174 +++++++++++++++++++++++++------- 1 file changed, 138 insertions(+), 36 deletions(-) diff --git a/pallets/slp/src/benchmarking.rs b/pallets/slp/src/benchmarking.rs index 1a2d0cd9f..8bfe90170 100644 --- a/pallets/slp/src/benchmarking.rs +++ b/pallets/slp/src/benchmarking.rs @@ -22,6 +22,7 @@ use crate::*; use frame_benchmarking::v2::*; use frame_support::assert_ok; +use sp_runtime::traits::UniqueSaturatedFrom; const DELEGATOR1: MultiLocation = MultiLocation { parents: 1, interior: X1(AccountId32 { network: None, id: [1u8; 32] }) }; @@ -52,14 +53,33 @@ pub fn init_bond(origin: ::RuntimeOrigin) set_mins_and_maxs::(origin.clone()); DelegatorsMultilocation2Index::::insert(KSM, DELEGATOR1, 0); + let fee_source_location = Pallet::::account_32_to_local_location( + Pallet::::account_id_to_account_32(whitelisted_caller()).unwrap(), + ) + .unwrap(); + FeeSources::::insert(KSM, (fee_source_location, BalanceOf::::from(4100000000u32))); + + assert_ok!(::MultiCurrency::deposit( + KSM, + &whitelisted_caller(), + BalanceOf::::unique_saturated_from(100_000_000_000_000u128), + )); + T::XcmWeightAndFeeHandler::set_xcm_dest_weight_and_fee( KSM, XcmOperationType::Bond, - Some((Weight::from_parts(4000000000, 100000), 4000000000u32.into())), + Some((Weight::from_parts(4000000000, 100000), 0u32.into())), ) .unwrap(); - assert_ok!(Pallet::::bond(origin, KSM, Box::new(DELEGATOR1), 10u32.into(), None, None)); + assert_ok!(Pallet::::bond( + origin, + KSM, + Box::new(DELEGATOR1), + 10u32.into(), + None, + Some((100.into(), 100u32.into())) + )); } pub fn init_ongoing_time(origin: ::RuntimeOrigin) { @@ -104,10 +124,22 @@ mod benchmarks { set_mins_and_maxs::(origin.clone()); DelegatorsMultilocation2Index::::insert(KSM, DELEGATOR1, 0); + let fee_source_location = Pallet::::account_32_to_local_location( + Pallet::::account_id_to_account_32(whitelisted_caller()).unwrap(), + ) + .unwrap(); + FeeSources::::insert(KSM, (fee_source_location, BalanceOf::::from(4100000000u32))); + + assert_ok!(::MultiCurrency::deposit( + KSM, + &whitelisted_caller(), + BalanceOf::::unique_saturated_from(100_000_000_000_000u128), + )); + T::XcmWeightAndFeeHandler::set_xcm_dest_weight_and_fee( KSM, XcmOperationType::Bond, - Some((Weight::from_parts(4000000000, 100000), 4000000000u32.into())), + Some((Weight::from_parts(4000000000, 100000), 0u32.into())), )?; #[extrinsic_call] @@ -117,7 +149,7 @@ mod benchmarks { Box::new(DELEGATOR1), 10u32.into(), None, - None, + Some((100.into(), 100u32.into())), ); Ok(()) @@ -132,7 +164,7 @@ mod benchmarks { T::XcmWeightAndFeeHandler::set_xcm_dest_weight_and_fee( KSM, XcmOperationType::BondExtra, - Some((Weight::from_parts(4000000000, 100000), 4000000000u32.into())), + Some((Weight::from_parts(4000000000, 100000), 0u32.into())), )?; #[extrinsic_call] @@ -142,7 +174,7 @@ mod benchmarks { Box::new(DELEGATOR1), None, 10u32.into(), - None, + Some((100.into(), 100u32.into())), ); Ok(()) @@ -158,7 +190,7 @@ mod benchmarks { T::XcmWeightAndFeeHandler::set_xcm_dest_weight_and_fee( KSM, XcmOperationType::Unbond, - Some((Weight::from_parts(4000000000, 100000), 4000000000u32.into())), + Some((Weight::from_parts(4000000000, 100000), 0u32.into())), )?; #[extrinsic_call] @@ -168,7 +200,7 @@ mod benchmarks { Box::new(DELEGATOR1), None, 0u32.into(), - None, + Some((100.into(), 100u32.into())), ); Ok(()) @@ -184,11 +216,16 @@ mod benchmarks { T::XcmWeightAndFeeHandler::set_xcm_dest_weight_and_fee( KSM, XcmOperationType::Unbond, - Some((Weight::from_parts(4000000000, 100000), 4000000000u32.into())), + Some((Weight::from_parts(4000000000, 100000), 0u32.into())), )?; #[extrinsic_call] - _(origin as ::RuntimeOrigin, KSM, Box::new(DELEGATOR1), None); + _( + origin as ::RuntimeOrigin, + KSM, + Box::new(DELEGATOR1), + Some((100.into(), 100u32.into())), + ); Ok(()) } @@ -203,7 +240,7 @@ mod benchmarks { T::XcmWeightAndFeeHandler::set_xcm_dest_weight_and_fee( KSM, XcmOperationType::Rebond, - Some((Weight::from_parts(4000000000, 100000), 4000000000u32.into())), + Some((Weight::from_parts(4000000000, 100000), 0u32.into())), )?; #[extrinsic_call] @@ -213,7 +250,7 @@ mod benchmarks { Box::new(DELEGATOR1), None, Some(0u32.into()), - None, + Some((100.into(), 100u32.into())), ); Ok(()) @@ -229,7 +266,7 @@ mod benchmarks { T::XcmWeightAndFeeHandler::set_xcm_dest_weight_and_fee( KSM, XcmOperationType::Delegate, - Some((Weight::from_parts(4000000000, 100000), 4000000000u32.into())), + Some((Weight::from_parts(4000000000, 100000), 0u32.into())), )?; #[extrinsic_call] @@ -238,7 +275,7 @@ mod benchmarks { KSM, Box::new(DELEGATOR1), vec![DELEGATOR1], - None, + Some((100.into(), 100u32.into())), ); Ok(()) @@ -258,7 +295,7 @@ mod benchmarks { T::XcmWeightAndFeeHandler::set_xcm_dest_weight_and_fee( KSM, XcmOperationType::Delegate, - Some((Weight::from_parts(4000000000, 100000), 4000000000u32.into())), + Some((Weight::from_parts(4000000000, 100000), 0u32.into())), )?; #[extrinsic_call] @@ -267,7 +304,7 @@ mod benchmarks { KSM, Box::new(DELEGATOR1), vec![DELEGATOR1], - None, + Some((100.into(), 100u32.into())), ); Ok(()) @@ -283,7 +320,7 @@ mod benchmarks { T::XcmWeightAndFeeHandler::set_xcm_dest_weight_and_fee( KSM, XcmOperationType::Delegate, - Some((Weight::from_parts(4000000000, 100000), 4000000000u32.into())), + Some((Weight::from_parts(4000000000, 100000), 0u32.into())), )?; #[extrinsic_call] @@ -292,7 +329,7 @@ mod benchmarks { KSM, Box::new(DELEGATOR1), Some(vec![DELEGATOR1]), - None, + Some((100.into(), 100u32.into())), ); Ok(()) @@ -304,10 +341,22 @@ mod benchmarks { .map_err(|_| BenchmarkError::Weightless)?; DelegatorsMultilocation2Index::::insert(KSM, DELEGATOR1, 0); + let fee_source_location = Pallet::::account_32_to_local_location( + Pallet::::account_id_to_account_32(whitelisted_caller()).unwrap(), + ) + .unwrap(); + FeeSources::::insert(KSM, (fee_source_location, BalanceOf::::from(4100000000u32))); + + assert_ok!(::MultiCurrency::deposit( + KSM, + &whitelisted_caller(), + BalanceOf::::unique_saturated_from(100_000_000_000_000u128), + )); + T::XcmWeightAndFeeHandler::set_xcm_dest_weight_and_fee( KSM, XcmOperationType::Payout, - Some((Weight::from_parts(4000000000, 100000), 4000000000u32.into())), + Some((Weight::from_parts(4000000000, 100000), 0u32.into())), )?; #[extrinsic_call] @@ -317,7 +366,7 @@ mod benchmarks { Box::new(DELEGATOR1), Box::new(DELEGATOR1), Some(TimeUnit::Era(0)), - None, + Some((100.into(), 100u32.into())), ); Ok(()) @@ -330,10 +379,22 @@ mod benchmarks { set_mins_and_maxs::(origin.clone()); DelegatorsMultilocation2Index::::insert(KSM, DELEGATOR1, 0); + let fee_source_location = Pallet::::account_32_to_local_location( + Pallet::::account_id_to_account_32(whitelisted_caller()).unwrap(), + ) + .unwrap(); + FeeSources::::insert(KSM, (fee_source_location, BalanceOf::::from(4100000000u32))); + + assert_ok!(::MultiCurrency::deposit( + KSM, + &whitelisted_caller(), + BalanceOf::::unique_saturated_from(100_000_000_000_000u128), + )); + T::XcmWeightAndFeeHandler::set_xcm_dest_weight_and_fee( KSM, XcmOperationType::Liquidize, - Some((Weight::from_parts(4000000000, 100000), 4000000000u32.into())), + Some((Weight::from_parts(4000000000, 100000), 0u32.into())), )?; #[extrinsic_call] @@ -344,7 +405,7 @@ mod benchmarks { Some(TimeUnit::SlashingSpan(0)), None, None, - None, + Some((100.into(), 100u32.into())), ); Ok(()) @@ -360,11 +421,16 @@ mod benchmarks { T::XcmWeightAndFeeHandler::set_xcm_dest_weight_and_fee( KSM, XcmOperationType::Chill, - Some((Weight::from_parts(4000000000, 100000), 4000000000u32.into())), + Some((Weight::from_parts(4000000000, 100000), 0u32.into())), )?; #[extrinsic_call] - _(origin as ::RuntimeOrigin, KSM, Box::new(DELEGATOR1), None); + _( + origin as ::RuntimeOrigin, + KSM, + Box::new(DELEGATOR1), + Some((100.into(), 100u32.into())), + ); Ok(()) } @@ -376,10 +442,22 @@ mod benchmarks { set_mins_and_maxs::(origin.clone()); DelegatorsMultilocation2Index::::insert(KSM, DELEGATOR1, 0); + let fee_source_location = Pallet::::account_32_to_local_location( + Pallet::::account_id_to_account_32(whitelisted_caller()).unwrap(), + ) + .unwrap(); + FeeSources::::insert(KSM, (fee_source_location, BalanceOf::::from(4100000000u32))); + + assert_ok!(::MultiCurrency::deposit( + KSM, + &whitelisted_caller(), + BalanceOf::::unique_saturated_from(100_000_000_000_000u128), + )); + T::XcmWeightAndFeeHandler::set_xcm_dest_weight_and_fee( KSM, XcmOperationType::TransferBack, - Some((Weight::from_parts(4000000000, 100000), 4000000000u32.into())), + Some((Weight::from_parts(4000000000, 100000), 0u32.into())), )?; let (_, exit_account) = ::VtokenMinting::get_entrance_and_exit_accounts(); @@ -393,7 +471,7 @@ mod benchmarks { Box::new(DELEGATOR1), Box::new(to), 10u32.into(), - None, + Some((100.into(), 100u32.into())), ); Ok(()) @@ -406,10 +484,22 @@ mod benchmarks { set_mins_and_maxs::(origin.clone()); DelegatorsMultilocation2Index::::insert(KSM, DELEGATOR1, 0); + let fee_source_location = Pallet::::account_32_to_local_location( + Pallet::::account_id_to_account_32(whitelisted_caller()).unwrap(), + ) + .unwrap(); + FeeSources::::insert(KSM, (fee_source_location, BalanceOf::::from(4100000000u32))); + + assert_ok!(::MultiCurrency::deposit( + KSM, + &whitelisted_caller(), + BalanceOf::::unique_saturated_from(100_000_000_000_000u128), + )); + T::XcmWeightAndFeeHandler::set_xcm_dest_weight_and_fee( KSM, XcmOperationType::TransferTo, - Some((Weight::from_parts(4000000000, 100000), 4000000000u32.into())), + Some((Weight::from_parts(4000000000, 100000), 0u32.into())), )?; let (entrance_account, _) = ::VtokenMinting::get_entrance_and_exit_accounts(); @@ -434,10 +524,22 @@ mod benchmarks { .map_err(|_| BenchmarkError::Weightless)?; DelegatorsMultilocation2Index::::insert(PHA, DELEGATOR1, 0); + let fee_source_location = Pallet::::account_32_to_local_location( + Pallet::::account_id_to_account_32(whitelisted_caller()).unwrap(), + ) + .unwrap(); + FeeSources::::insert(PHA, (fee_source_location, BalanceOf::::from(4100000000u32))); + + assert_ok!(::MultiCurrency::deposit( + PHA, + &whitelisted_caller(), + BalanceOf::::unique_saturated_from(100_000_000_000_000u128), + )); + T::XcmWeightAndFeeHandler::set_xcm_dest_weight_and_fee( PHA, XcmOperationType::ConvertAsset, - Some((Weight::from_parts(4000000000, 100000), 4000000000u32.into())), + Some((Weight::from_parts(4000000000, 100000), 0u32.into())), )?; DelegatorLedgers::::insert( @@ -461,7 +563,7 @@ mod benchmarks { Box::new(DELEGATOR1), 10u32.into(), true, - None, + Some((100.into(), 100u32.into())), ); Ok(()) @@ -515,7 +617,7 @@ mod benchmarks { .map_err(|_| BenchmarkError::Weightless)?; init_ongoing_time::(origin.clone()); - let (_, exit_account) = T::VtokenMinting::get_entrance_and_exit_accounts(); + let (_, exit_account) = ::VtokenMinting::get_entrance_and_exit_accounts(); orml_tokens::Pallet::::deposit( KSM, &exit_account, @@ -541,12 +643,12 @@ mod benchmarks { DelegatorsMultilocation2Index::::insert(KSM, DELEGATOR1, 0); - FeeSources::::insert(KSM, (from, BalanceOf::::from(1000u32))); + FeeSources::::insert(KSM, (from, BalanceOf::::from(4100000000u32))); T::XcmWeightAndFeeHandler::set_xcm_dest_weight_and_fee( KSM, XcmOperationType::TransferTo, - Some((Weight::from_parts(4000000000, 100000), 4000000000u32.into())), + Some((Weight::from_parts(4000000000, 100000), 0u32.into())), )?; #[extrinsic_call] @@ -859,7 +961,7 @@ mod benchmarks { T::XcmWeightAndFeeHandler::set_xcm_dest_weight_and_fee( KSM, XcmOperationType::Delegate, - Some((Weight::from_parts(4000000000, 100000), 4000000000u32.into())), + Some((Weight::from_parts(4000000000, 100000), 0u32.into())), )?; assert_ok!(Pallet::::delegate( @@ -867,7 +969,7 @@ mod benchmarks { KSM, Box::new(DELEGATOR1), vec![DELEGATOR1], - None + Some((100.into(), 100u32.into())) )); ValidatorsByDelegatorXcmUpdateQueue::::insert( 1u64, @@ -898,7 +1000,7 @@ mod benchmarks { T::XcmWeightAndFeeHandler::set_xcm_dest_weight_and_fee( KSM, XcmOperationType::Delegate, - Some((Weight::from_parts(4000000000, 100000), 4000000000u32.into())), + Some((Weight::from_parts(4000000000, 100000), 0u32.into())), )?; assert_ok!(Pallet::::delegate( @@ -906,7 +1008,7 @@ mod benchmarks { KSM, Box::new(DELEGATOR1), vec![DELEGATOR1], - None + Some((100.into(), 100u32.into())) )); ValidatorsByDelegatorXcmUpdateQueue::::insert( 1u64, From 3206a16a231794572ded60416e3a9e065b9deab0 Mon Sep 17 00:00:00 2001 From: herryho Date: Fri, 29 Mar 2024 13:09:47 +0800 Subject: [PATCH 4/4] fix decimals --- pallets/fee-share/src/mock.rs | 1 + pallets/slp/src/lib.rs | 23 ++++++++++++++++++----- pallets/slp/src/mocks/mock.rs | 1 + pallets/slp/src/mocks/mock_kusama.rs | 1 + pallets/slpx/src/mock.rs | 1 + pallets/system-maker/src/mock.rs | 1 + pallets/system-staking/src/mock.rs | 1 + pallets/ve-minting/src/mock.rs | 1 + pallets/vtoken-minting/src/mock.rs | 1 + runtime/bifrost-kusama/src/lib.rs | 1 + runtime/bifrost-polkadot/src/lib.rs | 1 + 11 files changed, 28 insertions(+), 5 deletions(-) diff --git a/pallets/fee-share/src/mock.rs b/pallets/fee-share/src/mock.rs index 827642c33..e361e254f 100644 --- a/pallets/fee-share/src/mock.rs +++ b/pallets/fee-share/src/mock.rs @@ -302,6 +302,7 @@ impl bifrost_slp::Config for Runtime { type XcmWeightAndFeeHandler = (); type ChannelCommission = (); type StablePoolHandler = (); + type AssetIdMaps = AssetIdMaps; type TreasuryAccount = TreasuryAccount; } diff --git a/pallets/slp/src/lib.rs b/pallets/slp/src/lib.rs index ef066bfef..1d91ff1b5 100644 --- a/pallets/slp/src/lib.rs +++ b/pallets/slp/src/lib.rs @@ -31,13 +31,14 @@ pub use crate::{ Junction::AccountId32, Junctions::X1, }; +use bifrost_asset_registry::AssetMetadata; use bifrost_parachain_staking::ParachainStakingInterface; use bifrost_primitives::{ currency::{BNC, KSM, MANTA, MOVR, PHA}, traits::XcmDestWeightAndFeeHandler, - CurrencyId, CurrencyIdExt, DerivativeAccountHandler, DerivativeIndex, SlpHostingFeeProvider, - SlpOperator, TimeUnit, TokenInfo, VtokenMintingOperator, XcmOperationType, ASTR, DOT, FIL, - GLMR, + CurrencyId, CurrencyIdExt, CurrencyIdMapping, DerivativeAccountHandler, DerivativeIndex, + SlpHostingFeeProvider, SlpOperator, TimeUnit, VtokenMintingOperator, XcmOperationType, ASTR, + DOT, FIL, GLMR, }; use bifrost_stable_pool::traits::StablePoolHandler; use cumulus_primitives_core::{relay_chain::HashT, ParaId}; @@ -173,6 +174,13 @@ pub mod pallet { CurrencyId = CurrencyId, >; + // asset registry to get asset metadata + type AssetIdMaps: CurrencyIdMapping< + CurrencyId, + MultiLocation, + AssetMetadata>, + >; + #[pallet::constant] type TreasuryAccount: Get; } @@ -2393,8 +2401,13 @@ pub mod pallet { .ok_or(Error::::StablePoolTokenIndexNotFound)?; // ensure swap balance not exceed a 10 unit - let decimals = token.decimals().unwrap_or_default(); - let max_amount = decimals.checked_mul(10).ok_or(Error::::OverFlow)?; + let metadata = T::AssetIdMaps::get_currency_metadata(vtoken) + .ok_or(Error::::NotSupportedCurrencyId)?; + let decimals = metadata.decimals; + + // 10 * 10^decimals + let max_amount = + 10u32.pow(decimals.into()).checked_mul(10).ok_or(Error::::OverFlow)?; ensure!(amount <= BalanceOf::::from(max_amount), Error::::ExceedLimit); // swap vtoken from treasury account for token diff --git a/pallets/slp/src/mocks/mock.rs b/pallets/slp/src/mocks/mock.rs index 6538ff9d1..7a9644618 100644 --- a/pallets/slp/src/mocks/mock.rs +++ b/pallets/slp/src/mocks/mock.rs @@ -469,6 +469,7 @@ impl Config for Runtime { type XcmWeightAndFeeHandler = XcmDestWeightAndFee; type ChannelCommission = (); type StablePoolHandler = (); + type AssetIdMaps = AssetIdMaps; type TreasuryAccount = BifrostTreasuryAccount; } diff --git a/pallets/slp/src/mocks/mock_kusama.rs b/pallets/slp/src/mocks/mock_kusama.rs index 3957af5b1..8d461cb68 100644 --- a/pallets/slp/src/mocks/mock_kusama.rs +++ b/pallets/slp/src/mocks/mock_kusama.rs @@ -517,6 +517,7 @@ impl Config for Runtime { type XcmWeightAndFeeHandler = XcmDestWeightAndFee; type ChannelCommission = (); type StablePoolHandler = (); + type AssetIdMaps = AssetIdMaps; type TreasuryAccount = BifrostTreasuryAccount; } diff --git a/pallets/slpx/src/mock.rs b/pallets/slpx/src/mock.rs index 090449b08..84ebdd73b 100644 --- a/pallets/slpx/src/mock.rs +++ b/pallets/slpx/src/mock.rs @@ -502,6 +502,7 @@ impl bifrost_slp::Config for Test { type XcmWeightAndFeeHandler = (); type ChannelCommission = (); type StablePoolHandler = (); + type AssetIdMaps = AssetIdMaps; type TreasuryAccount = BifrostFeeAccount; } diff --git a/pallets/system-maker/src/mock.rs b/pallets/system-maker/src/mock.rs index 75b86e5fc..2d507313a 100644 --- a/pallets/system-maker/src/mock.rs +++ b/pallets/system-maker/src/mock.rs @@ -309,6 +309,7 @@ impl bifrost_slp::Config for Runtime { type XcmWeightAndFeeHandler = (); type ChannelCommission = (); type StablePoolHandler = (); + type AssetIdMaps = AssetIdMaps; type TreasuryAccount = TreasuryAccount; } diff --git a/pallets/system-staking/src/mock.rs b/pallets/system-staking/src/mock.rs index f873d7977..7aa4d3e55 100644 --- a/pallets/system-staking/src/mock.rs +++ b/pallets/system-staking/src/mock.rs @@ -332,6 +332,7 @@ impl bifrost_slp::Config for Runtime { type XcmWeightAndFeeHandler = (); type ChannelCommission = (); type StablePoolHandler = (); + type AssetIdMaps = AssetIdMaps; type TreasuryAccount = TreasuryAccount; } diff --git a/pallets/ve-minting/src/mock.rs b/pallets/ve-minting/src/mock.rs index 88401d1e4..fb92ca834 100644 --- a/pallets/ve-minting/src/mock.rs +++ b/pallets/ve-minting/src/mock.rs @@ -385,6 +385,7 @@ impl bifrost_slp::Config for Runtime { type XcmWeightAndFeeHandler = (); type ChannelCommission = (); type StablePoolHandler = (); + type AssetIdMaps = AssetIdMaps; type TreasuryAccount = TreasuryAccount; } diff --git a/pallets/vtoken-minting/src/mock.rs b/pallets/vtoken-minting/src/mock.rs index 23a0a6c0d..6fb8258f5 100644 --- a/pallets/vtoken-minting/src/mock.rs +++ b/pallets/vtoken-minting/src/mock.rs @@ -365,6 +365,7 @@ impl bifrost_slp::Config for Runtime { type XcmWeightAndFeeHandler = (); type ChannelCommission = (); type StablePoolHandler = (); + type AssetIdMaps = AssetIdMaps; type TreasuryAccount = TreasuryAccount; } diff --git a/runtime/bifrost-kusama/src/lib.rs b/runtime/bifrost-kusama/src/lib.rs index 0ad5868fa..51b4fdec0 100644 --- a/runtime/bifrost-kusama/src/lib.rs +++ b/runtime/bifrost-kusama/src/lib.rs @@ -1423,6 +1423,7 @@ impl bifrost_slp::Config for Runtime { type XcmWeightAndFeeHandler = XcmInterface; type ChannelCommission = ChannelCommission; type StablePoolHandler = StablePool; + type AssetIdMaps = AssetIdMaps; type TreasuryAccount = BifrostTreasuryAccount; } diff --git a/runtime/bifrost-polkadot/src/lib.rs b/runtime/bifrost-polkadot/src/lib.rs index b5d03a29c..e26eac162 100644 --- a/runtime/bifrost-polkadot/src/lib.rs +++ b/runtime/bifrost-polkadot/src/lib.rs @@ -1250,6 +1250,7 @@ impl bifrost_slp::Config for Runtime { type XcmWeightAndFeeHandler = XcmInterface; type ChannelCommission = ChannelCommission; type StablePoolHandler = StablePool; + type AssetIdMaps = AssetIdMaps; type TreasuryAccount = BifrostTreasuryAccount; }