From de7fe50e4f67d9aad2c61344a98c4c0c6273460a Mon Sep 17 00:00:00 2001 From: Edwin Wang Date: Wed, 20 Mar 2024 12:55:40 +0800 Subject: [PATCH 01/10] Bump version to v0.9.96 --- Cargo.lock | 2 +- node/cli/Cargo.toml | 24 ++++++++++++------------ runtime/bifrost-kusama/src/lib.rs | 2 +- runtime/bifrost-polkadot/src/lib.rs | 2 +- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index be9e774e9..84e1f3cb7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -997,7 +997,7 @@ dependencies = [ [[package]] name = "bifrost-cli" -version = "0.9.94" +version = "0.9.96" dependencies = [ "bifrost-primitives", "bifrost-service", diff --git a/node/cli/Cargo.toml b/node/cli/Cargo.toml index b5eec22cb..420bb8a5a 100644 --- a/node/cli/Cargo.toml +++ b/node/cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "bifrost-cli" -version = "0.9.94" +version = "0.9.96" authors = ["Liebi Technologies "] description = "Bifrost Parachain Node" build = "build.rs" @@ -17,7 +17,7 @@ crate-type = ["cdylib", "rlib"] [dependencies] # third-party dependencies -clap = { workspace = true, features = ["derive"] } +clap = { workspace = true, features = ["derive"] } parity-scale-codec = { workspace = true } log = { workspace = true } @@ -27,8 +27,8 @@ sp-core = { workspace = true } sp-runtime = { workspace = true } # client dependencies -sc-executor = { workspace = true } -sc-service = { workspace = true, optional = true } +sc-executor = { workspace = true } +sc-service = { workspace = true, optional = true } sc-sysinfo = { workspace = true } sc-telemetry = { workspace = true } sc-tracing = { workspace = true } @@ -61,17 +61,17 @@ substrate-build-script-utils = { workspace = true, optional = true } [features] default = ["cli"] cli = [ - "node-inspect", - "sc-cli", - "frame-benchmarking-cli", - 'try-runtime-cli', - "sc-service", - "substrate-build-script-utils", + "node-inspect", + "sc-cli", + "frame-benchmarking-cli", + 'try-runtime-cli', + "sc-service", + "substrate-build-script-utils", ] runtime-benchmarks = ["bifrost-service/runtime-benchmarks"] with-bifrost-runtime = [ - "bifrost-service/with-bifrost-kusama-runtime", - "bifrost-service/with-bifrost-polkadot-runtime", + "bifrost-service/with-bifrost-kusama-runtime", + "bifrost-service/with-bifrost-polkadot-runtime", ] with-bifrost-kusama-runtime = ["bifrost-service/with-bifrost-kusama-runtime"] with-bifrost-polkadot-runtime = ["bifrost-service/with-bifrost-polkadot-runtime"] diff --git a/runtime/bifrost-kusama/src/lib.rs b/runtime/bifrost-kusama/src/lib.rs index 3d773665b..020384641 100644 --- a/runtime/bifrost-kusama/src/lib.rs +++ b/runtime/bifrost-kusama/src/lib.rs @@ -142,7 +142,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("bifrost"), impl_name: create_runtime_str!("bifrost"), authoring_version: 1, - spec_version: 994, + spec_version: 996, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 1, diff --git a/runtime/bifrost-polkadot/src/lib.rs b/runtime/bifrost-polkadot/src/lib.rs index f1b2721cc..7c84c254a 100644 --- a/runtime/bifrost-polkadot/src/lib.rs +++ b/runtime/bifrost-polkadot/src/lib.rs @@ -140,7 +140,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("bifrost_polkadot"), impl_name: create_runtime_str!("bifrost_polkadot"), authoring_version: 0, - spec_version: 994, + spec_version: 996, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 1, From 73e6f292ebd13469afc2bf151d92205cea5fec84 Mon Sep 17 00:00:00 2001 From: NingBo Wang <2536935847@qq.com> Date: Wed, 20 Mar 2024 16:53:27 +0800 Subject: [PATCH 02/10] Slpx adds force_add_order (#1212) --- pallets/slpx/src/lib.rs | 32 ++++++++++++++++++++++++++++++++ pallets/slpx/src/tests.rs | 11 +++++++++++ 2 files changed, 43 insertions(+) diff --git a/pallets/slpx/src/lib.rs b/pallets/slpx/src/lib.rs index ad86e21ab..790973a12 100644 --- a/pallets/slpx/src/lib.rs +++ b/pallets/slpx/src/lib.rs @@ -78,6 +78,7 @@ pub mod pallet { pallet_prelude::{ValueQuery, *}, weights::WeightMeter, }; + use frame_system::ensure_root; use zenlink_protocol::{AssetId, ExportZenlink}; #[pallet::pallet] @@ -695,6 +696,37 @@ pub mod pallet { Self::deposit_event(Event::SetDelayBlock { delay_block }); Ok(().into()) } + + #[pallet::call_index(12)] + #[pallet::weight(T::DbWeight::get().reads(1) + T::DbWeight::get().writes(1))] + pub fn force_add_order( + origin: OriginFor, + slpx_contract_derivative_account: AccountIdOf, + evm_caller: H160, + currency_id: CurrencyIdOf, + target_chain: TargetChain>, + remark: BoundedVec>, + order_type: OrderType, + ) -> DispatchResultWithPostInfo { + ensure_root(origin)?; + let order = Order { + create_block_number: >::block_number(), + currency_amount: Default::default(), + source_chain_caller: OrderCaller::Evm(evm_caller), + bifrost_chain_caller: slpx_contract_derivative_account, + derivative_account: Self::h160_to_account_id(evm_caller), + order_type, + currency_id, + remark, + target_chain, + }; + + OrderQueue::::mutate(|order_queue| -> DispatchResultWithPostInfo { + order_queue.try_push(order.clone()).map_err(|_| Error::::ArgumentsError)?; + Self::deposit_event(Event::::CreateOrder { order }); + Ok(().into()) + }) + } } } diff --git a/pallets/slpx/src/tests.rs b/pallets/slpx/src/tests.rs index e1e542084..8eaebd2e0 100644 --- a/pallets/slpx/src/tests.rs +++ b/pallets/slpx/src/tests.rs @@ -359,6 +359,17 @@ fn test_add_order() { TargetChain::Astar(source_chain_caller) )); assert_eq!(OrderQueue::::get().len(), 2usize); + assert_ok!(Slpx::force_add_order( + RuntimeOrigin::root(), + ALICE, + source_chain_caller, + VDOT, + TargetChain::Astar(source_chain_caller), + BoundedVec::default(), + OrderType::Mint + )); + assert_eq!(OrderQueue::::get().len(), 3usize); + println!("{:?}", OrderQueue::::get()); }) } From 4bb8477ab9fb3427791cc75cdd8c1b0d8335b9bf Mon Sep 17 00:00:00 2001 From: Edwin Date: Sun, 24 Mar 2024 12:36:33 +0800 Subject: [PATCH 03/10] Vtoken voting auto unlock (#1214) * Auto unlock vtoken voting * Add migration --- pallets/vtoken-voting/src/lib.rs | 52 ++++++++++------- pallets/vtoken-voting/src/migration.rs | 77 ++++++++++++++++++++++++++ pallets/vtoken-voting/src/tests.rs | 60 +++++++++++++------- runtime/bifrost-kusama/src/lib.rs | 11 +--- runtime/bifrost-polkadot/src/lib.rs | 12 +--- 5 files changed, 153 insertions(+), 59 deletions(-) diff --git a/pallets/vtoken-voting/src/lib.rs b/pallets/vtoken-voting/src/lib.rs index b515e5bae..5a06d33c3 100644 --- a/pallets/vtoken-voting/src/lib.rs +++ b/pallets/vtoken-voting/src/lib.rs @@ -86,7 +86,7 @@ pub mod pallet { use super::*; /// The current storage version. - const STORAGE_VERSION: StorageVersion = StorageVersion::new(2); + const STORAGE_VERSION: StorageVersion = StorageVersion::new(3); #[pallet::pallet] #[pallet::storage_version(STORAGE_VERSION)] @@ -273,7 +273,7 @@ pub mod pallet { _, Twox64Concat, AccountIdOf, - BoundedVec<(PollIndex, BalanceOf), T::MaxVotes>, + BoundedVec<(CurrencyIdOf, BalanceOf), T::MaxVotes>, ValueQuery, >; @@ -543,7 +543,7 @@ pub mod pallet { Self::ensure_no_pending_vote(vtoken, poll_index)?; Self::try_remove_vote(&who, vtoken, poll_index, UnvoteScope::OnlyExpired)?; - Self::update_lock(&who, vtoken, &poll_index)?; + Self::update_lock(&who, vtoken)?; Self::deposit_event(Event::::Unlocked { who, vtoken, poll_index }); @@ -713,7 +713,7 @@ pub mod pallet { // rollback vote let _ = PendingDelegatorVotes::::clear(u32::MAX, None); Self::try_remove_vote(&who, vtoken, poll_index, UnvoteScope::Any)?; - Self::update_lock(&who, vtoken, &poll_index)?; + Self::update_lock(&who, vtoken)?; if let Some((old_vote, vtoken_balance)) = maybe_old_vote { Self::try_vote(&who, vtoken, poll_index, old_vote, vtoken_balance)?; } @@ -880,7 +880,7 @@ pub mod pallet { } // Extend the lock to `balance` (rather than setting it) since we don't know // what other votes are in place. - Self::extend_lock(&who, vtoken, &poll_index, vtoken_balance)?; + Self::set_lock(&who, vtoken, voting.locked_balance())?; Ok((old_vote, total_vote)) }) }) @@ -947,36 +947,46 @@ pub mod pallet { /// Rejig the lock on an account. It will never get more stringent (since that would /// indicate a security hole) but may be reduced from what they are currently. - pub(crate) fn update_lock( - who: &AccountIdOf, - vtoken: CurrencyIdOf, - poll_index: &PollIndex, - ) -> DispatchResult { - VotingFor::::mutate(who, |voting| { + pub(crate) fn update_lock(who: &AccountIdOf, vtoken: CurrencyIdOf) -> DispatchResult { + let lock_needed = VotingFor::::mutate(who, |voting| { voting.rejig(T::RelaychainBlockNumberProvider::current_block_number()); + voting.locked_balance() }); - let lock_needed = ClassLocksFor::::mutate(who, |locks| { - locks.retain(|x| &x.0 != poll_index); - locks.iter().map(|x| x.1).max().unwrap_or(Zero::zero()) - }); + if lock_needed.is_zero() { + ClassLocksFor::::mutate(who, |locks| { + locks.retain(|x| x.0 != vtoken); + }); T::MultiCurrency::remove_lock(CONVICTION_VOTING_ID, vtoken, who) } else { + ClassLocksFor::::mutate(who, |locks| { + match locks.iter().position(|x| x.0 == vtoken) { + Some(i) => locks[i].1 = lock_needed, + None => { + let ok = locks.try_push((vtoken, lock_needed)).is_ok(); + debug_assert!( + ok, + "Vec bounded by number of classes; \ + all items in Vec associated with a unique class; \ + qed" + ); + }, + } + }); T::MultiCurrency::set_lock(CONVICTION_VOTING_ID, vtoken, who, lock_needed) } } - fn extend_lock( + fn set_lock( who: &AccountIdOf, vtoken: CurrencyIdOf, - poll_index: &PollIndex, amount: BalanceOf, ) -> DispatchResult { ClassLocksFor::::mutate(who, |locks| { - match locks.iter().position(|x| &x.0 == poll_index) { - Some(i) => locks[i].1 = locks[i].1.max(amount), + match locks.iter().position(|x| x.0 == vtoken) { + Some(i) => locks[i].1 = amount, None => { - let ok = locks.try_push((*poll_index, amount)).is_ok(); + let ok = locks.try_push((vtoken, amount)).is_ok(); debug_assert!( ok, "Vec bounded by number of classes; \ @@ -986,7 +996,7 @@ pub mod pallet { }, } }); - T::MultiCurrency::extend_lock(CONVICTION_VOTING_ID, vtoken, who, amount) + T::MultiCurrency::set_lock(CONVICTION_VOTING_ID, vtoken, who, amount) } fn send_xcm_with_notify( diff --git a/pallets/vtoken-voting/src/migration.rs b/pallets/vtoken-voting/src/migration.rs index 6e33c89ed..cfa58e706 100644 --- a/pallets/vtoken-voting/src/migration.rs +++ b/pallets/vtoken-voting/src/migration.rs @@ -51,6 +51,15 @@ pub mod v2 { use frame_support::{pallet_prelude::StorageVersion, traits::OnRuntimeUpgrade}; use sp_runtime::traits::Get; + #[storage_alias] + pub(super) type ClassLocksFor = StorageMap< + Pallet, + Twox64Concat, + AccountIdOf, + BoundedVec<(PollIndex, BalanceOf), ConstU32<256>>, + ValueQuery, + >; + pub struct MigrateToV2(sp_std::marker::PhantomData, sp_std::marker::PhantomData); impl>> OnRuntimeUpgrade for MigrateToV2 { fn on_runtime_upgrade() -> Weight { @@ -131,3 +140,71 @@ pub fn migrate_to_v2>>() -> Weight { weight } + +pub mod v3 { + use super::*; + use crate::{Config, CurrencyIdOf, Pallet}; + use cumulus_primitives_core::Weight; + use frame_support::{pallet_prelude::StorageVersion, traits::OnRuntimeUpgrade}; + use sp_runtime::traits::Get; + + pub struct MigrateToV3(sp_std::marker::PhantomData, sp_std::marker::PhantomData); + impl>> OnRuntimeUpgrade for MigrateToV3 { + fn on_runtime_upgrade() -> Weight { + if StorageVersion::get::>() == 2 { + let weight_consumed = migrate_to_v3::(); + log::info!("Migrating vtoken-voting storage to v3"); + StorageVersion::new(3).put::>(); + weight_consumed + } else { + log::warn!("vtoken-voting migration should be removed."); + T::DbWeight::get().reads(1) + } + } + + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result, sp_runtime::DispatchError> { + log::info!( + "vtoken-voting before migration: version: {:?}", + StorageVersion::get::>(), + ); + log::info!( + "vtoken-voting before migration: ClassLocksFor v2 count: {}", + v2::ClassLocksFor::::iter().count(), + ); + + Ok(Vec::new()) + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade(_: Vec) -> Result<(), sp_runtime::DispatchError> { + log::info!( + "vtoken-voting after migration: version: {:?}", + StorageVersion::get::>(), + ); + log::info!( + "vtoken-voting after migration: ClassLocksFor v3 count: {}", + ClassLocksFor::::iter().count() + ); + + Ok(()) + } + } +} + +pub fn migrate_to_v3>>() -> Weight { + let mut weight: Weight = Weight::zero(); + + let token = C::get(); + let vtoken = token.to_vtoken().unwrap(); + ClassLocksFor::::translate::)>, _>( + |_: T::AccountId, locks: Vec<(PollIndex, BalanceOf)>| { + let max_locked_balance = locks.iter().fold(BalanceOf::::zero(), |a, i| a.max(i.1)); + log::info!("Migrated max_locked_balance for {:?}...", max_locked_balance); + weight += T::DbWeight::get().writes(1); + Some(BoundedVec::try_from(vec![(vtoken, max_locked_balance)]).unwrap()) + }, + ); + + weight +} diff --git a/pallets/vtoken-voting/src/tests.rs b/pallets/vtoken-voting/src/tests.rs index 789f38e34..cc353e09a 100644 --- a/pallets/vtoken-voting/src/tests.rs +++ b/pallets/vtoken-voting/src/tests.rs @@ -84,7 +84,7 @@ fn basic_voting_works() { assert_ok!(VtokenVoting::try_remove_vote(&ALICE, vtoken, poll_index, UnvoteScope::Any)); assert_eq!(tally(vtoken, poll_index), Tally::from_parts(0, 0, 0)); - assert_ok!(VtokenVoting::update_lock(&ALICE, vtoken, &poll_index)); + assert_ok!(VtokenVoting::update_lock(&ALICE, vtoken)); assert_eq!(usable_balance(vtoken, &ALICE), 10); }); } @@ -108,7 +108,7 @@ fn voting_balance_gets_locked() { assert_ok!(VtokenVoting::try_remove_vote(&ALICE, vtoken, poll_index, UnvoteScope::Any)); assert_eq!(tally(vtoken, poll_index), Tally::from_parts(0, 0, 0)); - assert_ok!(VtokenVoting::update_lock(&ALICE, vtoken, &poll_index)); + assert_ok!(VtokenVoting::update_lock(&ALICE, vtoken)); assert_eq!(usable_balance(vtoken, &ALICE), 10); }); } @@ -172,7 +172,7 @@ fn unsuccessful_conviction_vote_balance_can_be_unlocked() { )); RelaychainDataProvider::set_block_number(13); assert_ok!(VtokenVoting::try_remove_vote(&ALICE, vtoken, poll_index, UnvoteScope::Any)); - assert_ok!(VtokenVoting::update_lock(&ALICE, vtoken, &poll_index)); + assert_ok!(VtokenVoting::update_lock(&ALICE, vtoken)); assert_eq!(usable_balance(vtoken, &ALICE), 10); }); } @@ -208,7 +208,7 @@ fn successful_conviction_vote_balance_stays_locked_for_correct_time() { assert_ok!(VtokenVoting::try_remove_vote(&i, vtoken, poll_index, UnvoteScope::Any)); } for i in 1..=5 { - assert_ok!(VtokenVoting::update_lock(&i, vtoken, &poll_index)); + assert_ok!(VtokenVoting::update_lock(&i, vtoken)); assert_eq!(usable_balance(vtoken, &i), 10 * i as u128); } }); @@ -221,13 +221,33 @@ fn lock_amalgamation_valid_with_multiple_removed_votes() { let response = response_success(); assert_ok!(VtokenVoting::vote(RuntimeOrigin::signed(ALICE), vtoken, 0, aye(5, 1))); - assert_ok!(VtokenVoting::vote(RuntimeOrigin::signed(ALICE), vtoken, 1, aye(10, 1))); - assert_ok!(VtokenVoting::vote(RuntimeOrigin::signed(ALICE), vtoken, 2, aye(5, 2))); - assert_eq!(usable_balance(vtoken, &ALICE), 0); - assert_ok!(VtokenVoting::notify_vote(origin_response(), 0, response.clone())); + assert_eq!( + ClassLocksFor::::get(&ALICE), + BoundedVec::<(CurrencyId, u128), ConstU32<256>>::try_from(vec![(vtoken, 5),]).unwrap() + ); + + assert_ok!(VtokenVoting::vote(RuntimeOrigin::signed(ALICE), vtoken, 1, aye(10, 1))); assert_ok!(VtokenVoting::notify_vote(origin_response(), 1, response.clone())); + assert_eq!( + ClassLocksFor::::get(&ALICE), + BoundedVec::<(CurrencyId, u128), ConstU32<256>>::try_from(vec![(vtoken, 10),]).unwrap() + ); + + assert_ok!(VtokenVoting::vote(RuntimeOrigin::signed(ALICE), vtoken, 1, aye(5, 1))); assert_ok!(VtokenVoting::notify_vote(origin_response(), 2, response.clone())); + assert_eq!( + ClassLocksFor::::get(&ALICE), + BoundedVec::<(CurrencyId, u128), ConstU32<256>>::try_from(vec![(vtoken, 5),]).unwrap() + ); + assert_eq!(usable_balance(vtoken, &ALICE), 5); + + assert_ok!(VtokenVoting::vote(RuntimeOrigin::signed(ALICE), vtoken, 2, aye(10, 2))); + assert_ok!(VtokenVoting::notify_vote(origin_response(), 3, response.clone())); + assert_eq!( + ClassLocksFor::::get(&ALICE), + BoundedVec::<(CurrencyId, u128), ConstU32<256>>::try_from(vec![(vtoken, 10),]).unwrap() + ); assert_ok!(VtokenVoting::set_referendum_status( RuntimeOrigin::root(), @@ -254,11 +274,11 @@ fn lock_amalgamation_valid_with_multiple_removed_votes() { vtoken, locking_period, )); + assert_eq!(VoteLockingPeriod::::get(vtoken), Some(10)); assert_eq!( ClassLocksFor::::get(&ALICE), - BoundedVec::<(u32, u128), ConstU32<256>>::try_from(vec![(0, 5), (1, 10), (2, 5)]) - .unwrap() + BoundedVec::<(CurrencyId, u128), ConstU32<256>>::try_from(vec![(vtoken, 10),]).unwrap() ); RelaychainDataProvider::set_block_number(10); @@ -266,21 +286,24 @@ fn lock_amalgamation_valid_with_multiple_removed_votes() { VtokenVoting::unlock(RuntimeOrigin::signed(ALICE), vtoken, 0), Error::::NoPermissionYet ); + assert_eq!(VotingFor::::get(&ALICE).locked_balance(), 10); + assert_eq!(usable_balance(vtoken, &ALICE), 0); RelaychainDataProvider::set_block_number(11); assert_ok!(VtokenVoting::unlock(RuntimeOrigin::signed(ALICE), vtoken, 0)); + assert_eq!(VotingFor::::get(&ALICE).locked_balance(), 10); assert_eq!(usable_balance(vtoken, &ALICE), 0); assert_eq!( ClassLocksFor::::get(&ALICE), - BoundedVec::<(u32, u128), ConstU32<256>>::try_from(vec![(1, 10), (2, 5)]).unwrap() + BoundedVec::<(CurrencyId, u128), ConstU32<256>>::try_from(vec![(vtoken, 10),]).unwrap() ); RelaychainDataProvider::set_block_number(11); assert_ok!(VtokenVoting::unlock(RuntimeOrigin::signed(ALICE), vtoken, 1)); - assert_eq!(usable_balance(vtoken, &ALICE), 5); + assert_eq!(usable_balance(vtoken, &ALICE), 0); assert_eq!( ClassLocksFor::::get(&ALICE), - BoundedVec::<(u32, u128), ConstU32<256>>::try_from(vec![(2, 5)]).unwrap() + BoundedVec::<(CurrencyId, u128), ConstU32<256>>::try_from(vec![(vtoken, 10)]).unwrap() ); RelaychainDataProvider::set_block_number(21); @@ -288,7 +311,7 @@ fn lock_amalgamation_valid_with_multiple_removed_votes() { assert_eq!(usable_balance(vtoken, &ALICE), 10); assert_eq!( ClassLocksFor::::get(&ALICE), - BoundedVec::<(u32, u128), ConstU32<256>>::try_from(vec![]).unwrap() + BoundedVec::<(CurrencyId, u128), ConstU32<256>>::try_from(vec![]).unwrap() ); }); } @@ -333,29 +356,28 @@ fn removed_votes_when_referendum_killed() { assert_eq!( ClassLocksFor::::get(&ALICE), - BoundedVec::<(u32, u128), ConstU32<256>>::try_from(vec![(0, 5), (1, 10), (2, 5)]) - .unwrap() + BoundedVec::<(CurrencyId, u128), ConstU32<256>>::try_from(vec![(vtoken, 10),]).unwrap() ); assert_ok!(VtokenVoting::unlock(RuntimeOrigin::signed(ALICE), vtoken, 0)); assert_eq!(usable_balance(vtoken, &ALICE), 0); assert_eq!( ClassLocksFor::::get(&ALICE), - BoundedVec::<(u32, u128), ConstU32<256>>::try_from(vec![(1, 10), (2, 5)]).unwrap() + BoundedVec::<(CurrencyId, u128), ConstU32<256>>::try_from(vec![(vtoken, 10),]).unwrap() ); assert_ok!(VtokenVoting::unlock(RuntimeOrigin::signed(ALICE), vtoken, 1)); assert_eq!(usable_balance(vtoken, &ALICE), 5); assert_eq!( ClassLocksFor::::get(&ALICE), - BoundedVec::<(u32, u128), ConstU32<256>>::try_from(vec![(2, 5)]).unwrap() + BoundedVec::<(CurrencyId, u128), ConstU32<256>>::try_from(vec![(vtoken, 5)]).unwrap() ); assert_ok!(VtokenVoting::unlock(RuntimeOrigin::signed(ALICE), vtoken, 2)); assert_eq!(usable_balance(vtoken, &ALICE), 10); assert_eq!( ClassLocksFor::::get(&ALICE), - BoundedVec::<(u32, u128), ConstU32<256>>::try_from(vec![]).unwrap() + BoundedVec::<(CurrencyId, u128), ConstU32<256>>::try_from(vec![]).unwrap() ); }); } diff --git a/runtime/bifrost-kusama/src/lib.rs b/runtime/bifrost-kusama/src/lib.rs index 020384641..6e037eb02 100644 --- a/runtime/bifrost-kusama/src/lib.rs +++ b/runtime/bifrost-kusama/src/lib.rs @@ -2071,15 +2071,8 @@ pub mod migrations { use super::*; /// Unreleased migrations. Add new ones here: - pub type Unreleased = ( - crate::migration::v1::RestoreReferendaV1, - crate::migration::v1::RestoreReferendaV1< - crate::migration::FellowshipReferendaData, - Runtime, - governance::fellowship::FellowshipReferendaInstance, - >, - bifrost_slpx::migration::BifrostKusamaAddCurrencyToSupportXcmFee, - ); + pub type Unreleased = + (bifrost_vtoken_voting::migration::v3::MigrateToV3,); } /// Executive: handles dispatch to the various modules. diff --git a/runtime/bifrost-polkadot/src/lib.rs b/runtime/bifrost-polkadot/src/lib.rs index 7c84c254a..3d593ca0b 100644 --- a/runtime/bifrost-polkadot/src/lib.rs +++ b/runtime/bifrost-polkadot/src/lib.rs @@ -1875,16 +1875,8 @@ pub mod migrations { use super::*; /// Unreleased migrations. Add new ones here: - pub type Unreleased = ( - bifrost_asset_registry::migration::InsertBNCMetadata, - crate::migration::v1::RestoreReferendaV1, - crate::migration::v1::RestoreReferendaV1< - crate::migration::FellowshipReferendaData, - Runtime, - governance::fellowship::FellowshipReferendaInstance, - >, - bifrost_slpx::migration::BifrostPolkadotAddCurrencyToSupportXcmFee, - ); + pub type Unreleased = + (bifrost_vtoken_voting::migration::v3::MigrateToV3,); } /// Executive: handles dispatch to the various modules. From 802d57dfac16a5021c94f23e0cd064fcaaf8b998 Mon Sep 17 00:00:00 2001 From: Edwin Wang Date: Tue, 26 Mar 2024 11:59:23 +0800 Subject: [PATCH 04/10] Fix vtoken locked balance --- pallets/vtoken-voting/src/lib.rs | 10 +++++++--- pallets/vtoken-voting/src/tests.rs | 16 ++++++++++++++++ pallets/vtoken-voting/src/vote.rs | 8 ++++++++ 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/pallets/vtoken-voting/src/lib.rs b/pallets/vtoken-voting/src/lib.rs index 5a06d33c3..dd3ee2f27 100644 --- a/pallets/vtoken-voting/src/lib.rs +++ b/pallets/vtoken-voting/src/lib.rs @@ -880,7 +880,7 @@ pub mod pallet { } // Extend the lock to `balance` (rather than setting it) since we don't know // what other votes are in place. - Self::set_lock(&who, vtoken, voting.locked_balance())?; + Self::set_lock(&who, vtoken, voting.locked_vtoken_balance())?; Ok((old_vote, total_vote)) }) }) @@ -977,7 +977,7 @@ pub mod pallet { } } - fn set_lock( + pub(crate) fn set_lock( who: &AccountIdOf, vtoken: CurrencyIdOf, amount: BalanceOf, @@ -996,7 +996,11 @@ pub mod pallet { }, } }); - T::MultiCurrency::set_lock(CONVICTION_VOTING_ID, vtoken, who, amount) + if amount.is_zero() { + T::MultiCurrency::remove_lock(CONVICTION_VOTING_ID, vtoken, who) + } else { + T::MultiCurrency::set_lock(CONVICTION_VOTING_ID, vtoken, who, amount) + } } fn send_xcm_with_notify( diff --git a/pallets/vtoken-voting/src/tests.rs b/pallets/vtoken-voting/src/tests.rs index cc353e09a..c74ddec5d 100644 --- a/pallets/vtoken-voting/src/tests.rs +++ b/pallets/vtoken-voting/src/tests.rs @@ -1258,3 +1258,19 @@ fn tally_convert_works() { aye(0, 1) ); } + +#[test] +fn set_lock_works() { + new_test_ext().execute_with(|| { + let vtoken = VKSM; + + assert_ok!(VtokenVoting::set_lock(&ALICE, vtoken, 10)); + assert_eq!(usable_balance(vtoken, &ALICE), 0); + + assert_ok!(VtokenVoting::set_lock(&ALICE, vtoken, 1)); + assert_eq!(usable_balance(vtoken, &ALICE), 9); + + assert_ok!(VtokenVoting::set_lock(&ALICE, vtoken, 0)); + assert_eq!(usable_balance(vtoken, &ALICE), 10); + }); +} diff --git a/pallets/vtoken-voting/src/vote.rs b/pallets/vtoken-voting/src/vote.rs index 6699f2eda..9b53f979d 100644 --- a/pallets/vtoken-voting/src/vote.rs +++ b/pallets/vtoken-voting/src/vote.rs @@ -420,6 +420,14 @@ where } } + pub fn locked_vtoken_balance(&self) -> Balance { + match self { + Voting::Casting(Casting { votes, prior, .. }) => + votes.iter().map(|i| i.3).fold(prior.locked(), |a, i| a.max(i)), + Voting::Delegating(Delegating { balance, prior, .. }) => *balance.max(&prior.locked()), + } + } + pub fn set_common( &mut self, delegations: Delegations, From fc856651c9cf9322016fdbde79b3112cbb92799f Mon Sep 17 00:00:00 2001 From: Edwin Wang Date: Tue, 26 Mar 2024 14:33:32 +0800 Subject: [PATCH 05/10] Fix --- pallets/vtoken-voting/src/vote.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pallets/vtoken-voting/src/vote.rs b/pallets/vtoken-voting/src/vote.rs index 9b53f979d..2797fe136 100644 --- a/pallets/vtoken-voting/src/vote.rs +++ b/pallets/vtoken-voting/src/vote.rs @@ -422,9 +422,9 @@ where pub fn locked_vtoken_balance(&self) -> Balance { match self { - Voting::Casting(Casting { votes, prior, .. }) => - votes.iter().map(|i| i.3).fold(prior.locked(), |a, i| a.max(i)), - Voting::Delegating(Delegating { balance, prior, .. }) => *balance.max(&prior.locked()), + Voting::Casting(Casting { votes, .. }) => + votes.iter().map(|i| i.3).fold(Zero::zero(), |a, i| a.max(i)), + Voting::Delegating(Delegating { .. }) => Zero::zero(), } } From 4facc44a4db13b81b2c71b6fd9fabf90ca86c5c6 Mon Sep 17 00:00:00 2001 From: yooml Date: Thu, 28 Mar 2024 10:37:48 +0800 Subject: [PATCH 06/10] =?UTF-8?q?refactor:=20=F0=9F=92=A1=20modify=20base?= =?UTF-8?q?=20tx=20fees=20(#1215)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- runtime/bifrost-kusama/src/constants.rs | 2 +- runtime/bifrost-polkadot/src/constants.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/runtime/bifrost-kusama/src/constants.rs b/runtime/bifrost-kusama/src/constants.rs index f380305a6..1c3ffc3bb 100644 --- a/runtime/bifrost-kusama/src/constants.rs +++ b/runtime/bifrost-kusama/src/constants.rs @@ -46,7 +46,7 @@ pub mod currency { type Balance = Balance; fn polynomial() -> WeightToFeeCoefficients { // extrinsic base weight (smallest non-zero weight) is mapped to 1/10 CENT: - let p = base_tx_fee::() * 580; + let p = base_tx_fee::() * 240; let q = Balance::from(ExtrinsicBaseWeight::get().ref_time()); smallvec![WeightToFeeCoefficient { degree: 1, diff --git a/runtime/bifrost-polkadot/src/constants.rs b/runtime/bifrost-polkadot/src/constants.rs index a6c5cd6ec..3c71b00e6 100644 --- a/runtime/bifrost-polkadot/src/constants.rs +++ b/runtime/bifrost-polkadot/src/constants.rs @@ -48,7 +48,7 @@ pub mod currency { type Balance = Balance; fn polynomial() -> WeightToFeeCoefficients { // extrinsic base weight (smallest non-zero weight) is mapped to 1/10 CENT: - let p = base_tx_fee::() * 580; + let p = base_tx_fee::() * 240; let q = Balance::from(ExtrinsicBaseWeight::get().ref_time()); smallvec![WeightToFeeCoefficient { degree: 1, From ab5adf622462ae0c5c3c6cd0b4091261c5444732 Mon Sep 17 00:00:00 2001 From: Herry Ho <45537372+herryho@users.noreply.github.com> Date: Fri, 29 Mar 2024 14:55:38 +0800 Subject: [PATCH 07/10] cross-chain-transaction-fee (#1216) * cross-chain-transaction-fee * fixes * fix benchmarks * fix decimals --- Cargo.lock | 1 + integration-tests/bifrost-kusama/src/slp.rs | 2 +- pallets/fee-share/src/mock.rs | 5 +- 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/benchmarking.rs | 174 ++++++++++++++---- pallets/slp/src/lib.rs | 67 ++++++- pallets/slp/src/mocks/mock.rs | 4 + pallets/slp/src/mocks/mock_kusama.rs | 7 + pallets/slp/src/tests/kusama_tests.rs | 13 ++ pallets/slp/src/weights.rs | 6 + pallets/slpx/src/mock.rs | 3 + pallets/system-maker/src/mock.rs | 5 +- pallets/system-staking/src/mock.rs | 3 + pallets/ve-minting/src/mock.rs | 8 + pallets/vtoken-minting/src/mock.rs | 8 + primitives/src/lib.rs | 1 + runtime/bifrost-kusama/src/lib.rs | 3 + .../bifrost-kusama/src/weights/bifrost_slp.rs | 5 + runtime/bifrost-polkadot/src/lib.rs | 3 + .../src/weights/bifrost_slp.rs | 5 + 25 files changed, 457 insertions(+), 67 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/fee-share/src/mock.rs b/pallets/fee-share/src/mock.rs index db657f8cb..e361e254f 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,9 @@ impl bifrost_slp::Config for Runtime { type MaxLengthLimit = MaxLengthLimit; type XcmWeightAndFeeHandler = (); type ChannelCommission = (); + type StablePoolHandler = (); + type AssetIdMaps = AssetIdMaps; + type TreasuryAccount = TreasuryAccount; } parameter_type_with_key! { 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/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, diff --git a/pallets/slp/src/lib.rs b/pallets/slp/src/lib.rs index 999c3688c..1d91ff1b5 100644 --- a/pallets/slp/src/lib.rs +++ b/pallets/slp/src/lib.rs @@ -31,13 +31,16 @@ 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, 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}; use frame_support::{pallet_prelude::*, traits::Contains, weights::Weight}; use frame_system::{ @@ -164,6 +167,22 @@ pub mod pallet { BalanceOf, AccountIdOf, >; + + type StablePoolHandler: StablePoolHandler< + Balance = BalanceOf, + AccountId = AccountIdOf, + CurrencyId = CurrencyId, + >; + + // asset registry to get asset metadata + type AssetIdMaps: CurrencyIdMapping< + CurrencyId, + MultiLocation, + AssetMetadata>, + >; + + #[pallet::constant] + type TreasuryAccount: Get; } #[pallet::error] @@ -246,6 +265,9 @@ pub mod pallet { ExceedMaxLengthLimit, /// Transfer to failed TransferToError, + StablePoolNotFound, + StablePoolTokenIndexNotFound, + ExceedLimit, } #[pallet::event] @@ -2358,6 +2380,47 @@ 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 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 + 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..7a9644618 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,9 @@ impl Config for Runtime { type MaxLengthLimit = MaxLengthLimit; type XcmWeightAndFeeHandler = XcmDestWeightAndFee; type ChannelCommission = (); + type StablePoolHandler = (); + type AssetIdMaps = AssetIdMaps; + 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..8d461cb68 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,9 @@ impl Config for Runtime { type MaxLengthLimit = MaxLengthLimit; type XcmWeightAndFeeHandler = XcmDestWeightAndFee; type ChannelCommission = (); + type StablePoolHandler = (); + type AssetIdMaps = AssetIdMaps; + 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/pallets/slpx/src/mock.rs b/pallets/slpx/src/mock.rs index 7c3b2bb60..84ebdd73b 100644 --- a/pallets/slpx/src/mock.rs +++ b/pallets/slpx/src/mock.rs @@ -501,6 +501,9 @@ impl bifrost_slp::Config for Test { type MaxLengthLimit = MaxLengthLimit; type XcmWeightAndFeeHandler = (); type ChannelCommission = (); + type StablePoolHandler = (); + type AssetIdMaps = AssetIdMaps; + 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..2d507313a 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,9 @@ impl bifrost_slp::Config for Runtime { type MaxLengthLimit = MaxLengthLimit; type XcmWeightAndFeeHandler = (); type ChannelCommission = (); + type StablePoolHandler = (); + type AssetIdMaps = AssetIdMaps; + 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..7aa4d3e55 100644 --- a/pallets/system-staking/src/mock.rs +++ b/pallets/system-staking/src/mock.rs @@ -331,6 +331,9 @@ impl bifrost_slp::Config for Runtime { type MaxLengthLimit = MaxLengthLimit; type XcmWeightAndFeeHandler = (); type ChannelCommission = (); + type StablePoolHandler = (); + type AssetIdMaps = AssetIdMaps; + type TreasuryAccount = TreasuryAccount; } parameter_types! { diff --git a/pallets/ve-minting/src/mock.rs b/pallets/ve-minting/src/mock.rs index c0bb5b044..fb92ca834 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,9 @@ impl bifrost_slp::Config for Runtime { type MaxLengthLimit = MaxLengthLimit; type XcmWeightAndFeeHandler = (); type ChannelCommission = (); + type StablePoolHandler = (); + type AssetIdMaps = AssetIdMaps; + type TreasuryAccount = TreasuryAccount; } parameter_types! { diff --git a/pallets/vtoken-minting/src/mock.rs b/pallets/vtoken-minting/src/mock.rs index fab99b559..6fb8258f5 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,9 @@ impl bifrost_slp::Config for Runtime { type MaxLengthLimit = MaxLengthLimit; type XcmWeightAndFeeHandler = (); type ChannelCommission = (); + type StablePoolHandler = (); + type AssetIdMaps = AssetIdMaps; + type TreasuryAccount = TreasuryAccount; } parameter_types! { 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..51b4fdec0 100644 --- a/runtime/bifrost-kusama/src/lib.rs +++ b/runtime/bifrost-kusama/src/lib.rs @@ -1422,6 +1422,9 @@ impl bifrost_slp::Config for Runtime { type MaxLengthLimit = MaxLengthLimit; type XcmWeightAndFeeHandler = XcmInterface; type ChannelCommission = ChannelCommission; + type StablePoolHandler = StablePool; + type AssetIdMaps = AssetIdMaps; + 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..e26eac162 100644 --- a/runtime/bifrost-polkadot/src/lib.rs +++ b/runtime/bifrost-polkadot/src/lib.rs @@ -1249,6 +1249,9 @@ impl bifrost_slp::Config for Runtime { type MaxLengthLimit = MaxLengthLimit; type XcmWeightAndFeeHandler = XcmInterface; type ChannelCommission = ChannelCommission; + type StablePoolHandler = StablePool; + type AssetIdMaps = AssetIdMaps; + 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 a99333a235324ab34a6124d9692eca3c3a22c450 Mon Sep 17 00:00:00 2001 From: yooml Date: Mon, 1 Apr 2024 13:58:17 +0800 Subject: [PATCH 08/10] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20add=20unlock=5Fid?= =?UTF-8?q?=20(#1217)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pallets/vtoken-minting/src/lib.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pallets/vtoken-minting/src/lib.rs b/pallets/vtoken-minting/src/lib.rs index b90c16fa3..050f2b0db 100644 --- a/pallets/vtoken-minting/src/lib.rs +++ b/pallets/vtoken-minting/src/lib.rs @@ -163,6 +163,7 @@ pub mod pallet { token_amount: BalanceOf, vtoken_amount: BalanceOf, fee: BalanceOf, + unlock_id: UnlockId, }, RedeemSuccess { unlock_id: UnlockId, @@ -183,6 +184,7 @@ pub mod pallet { token_amount: BalanceOf, vtoken_amount: BalanceOf, fee: BalanceOf, + unlock_id: UnlockId, }, UnlockDurationSet { token_id: CurrencyIdOf, @@ -639,6 +641,7 @@ pub mod pallet { token_amount: unlock_amount, vtoken_amount, fee, + unlock_id, }); Ok(()) } @@ -1344,6 +1347,7 @@ pub mod pallet { .map_err(|_| Error::::CalculationOverflow)? .unique_saturated_into(); + let next_id = Self::token_unlock_next_id(token_id); match OngoingTimeUnit::::get(token_id) { Some(time_unit) => { // Calculate the time to be locked @@ -1366,7 +1370,6 @@ pub mod pallet { .ok_or(Error::::CalculationOverflow)?; Ok(()) })?; - let next_id = Self::token_unlock_next_id(token_id); TokenUnlockLedger::::insert( &token_id, &next_id, @@ -1459,6 +1462,7 @@ pub mod pallet { vtoken_amount, token_amount, fee: redeem_fee, + unlock_id: next_id, }); Ok(Some(T::WeightInfo::redeem() + extra_weight).into()) } From 63f81c3fba0f1916cb5dd0bc7228ddf88c61f651 Mon Sep 17 00:00:00 2001 From: Herry Ho <45537372+herryho@users.noreply.github.com> Date: Mon, 1 Apr 2024 19:20:24 +0800 Subject: [PATCH 09/10] clean-outdated-vbl (#1218) --- pallets/slp/src/benchmarking.rs | 22 ++++ pallets/slp/src/lib.rs | 77 +++++++++++++ pallets/slp/src/tests/manta_tests.rs | 101 ++++++++++++++++++ pallets/slp/src/weights.rs | 6 ++ pallets/slpx/src/benchmarking.rs | 1 - .../bifrost-kusama/src/weights/bifrost_slp.rs | 5 + .../src/weights/bifrost_slp.rs | 5 + 7 files changed, 216 insertions(+), 1 deletion(-) diff --git a/pallets/slp/src/benchmarking.rs b/pallets/slp/src/benchmarking.rs index 8bfe90170..f372dbf6e 100644 --- a/pallets/slp/src/benchmarking.rs +++ b/pallets/slp/src/benchmarking.rs @@ -1083,6 +1083,28 @@ mod benchmarks { Ok(()) } + #[benchmark] + fn clean_outdated_validator_boost_list() -> Result<(), BenchmarkError> { + let origin = ::ControlOrigin::try_successful_origin() + .map_err(|_| BenchmarkError::Weightless)?; + set_mins_and_maxs::(origin.clone()); + + frame_system::Pallet::::set_block_number(1u32.into()); + + assert_ok!(Pallet::::add_to_validator_boost_list( + origin.clone() as ::RuntimeOrigin, + KSM, + Box::new(DELEGATOR1) + )); + + frame_system::Pallet::::set_block_number((1 + SIX_MONTHS).into()); + + #[extrinsic_call] + _(origin as ::RuntimeOrigin, KSM, 1u8); + + Ok(()) + } + // `cargo test -p bifrost-slp --all-features` impl_benchmark_test_suite!( Pallet, diff --git a/pallets/slp/src/lib.rs b/pallets/slp/src/lib.rs index 1d91ff1b5..0b587e947 100644 --- a/pallets/slp/src/lib.rs +++ b/pallets/slp/src/lib.rs @@ -44,6 +44,7 @@ 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::{ + ensure_signed, pallet_prelude::{BlockNumberFor, OriginFor}, RawOrigin, }; @@ -90,6 +91,7 @@ pub type CurrencyIdOf = <::MultiCurrency as MultiCurrency< ::AccountId, >>::CurrencyId; const SIX_MONTHS: u32 = 5 * 60 * 24 * 180; +const ITERATE_LENGTH: usize = 100; #[frame_support::pallet] pub mod pallet { @@ -268,6 +270,8 @@ pub mod pallet { StablePoolNotFound, StablePoolTokenIndexNotFound, ExceedLimit, + InvalidPageNumber, + NoMoreValidatorBoostListForCurrency, } #[pallet::event] @@ -522,6 +526,14 @@ pub mod pallet { currency_id: CurrencyId, who: MultiLocation, }, + OutdatedValidatorBoostListCleaned { + currency_id: CurrencyId, + page: u8, + // already removed num + remove_num: u32, + // still to iterate num + num_left: u32, + }, } /// The current storage version, we set to 3 our new version(after migrate stroage from vec t @@ -2421,6 +2433,71 @@ pub mod pallet { Zero::zero(), ) } + + #[pallet::call_index(48)] + #[pallet::weight(::WeightInfo::clean_outdated_validator_boost_list())] + pub fn clean_outdated_validator_boost_list( + origin: OriginFor, + token: CurrencyId, + // start from 1 + page: u8, + ) -> DispatchResult { + ensure_signed(origin)?; + let page = page as usize; + ensure!(page > 0, Error::::InvalidPageNumber); + + let validator_boost_list_len = ValidatorBoostList::::decode_len(token) + .ok_or(Error::::NoMoreValidatorBoostListForCurrency)?; + + let previous_count = (page - 1) * ITERATE_LENGTH; + ensure!( + validator_boost_list_len > previous_count, + Error::::NoMoreValidatorBoostListForCurrency + ); + + // calculate next page number left + let num_left = if validator_boost_list_len > (previous_count + ITERATE_LENGTH) { + validator_boost_list_len - previous_count - ITERATE_LENGTH + } else { + 0 + }; + + let current_block_number = >::block_number(); + let mut remove_num = 0; + // for each validator in the validator boost list, if the due block number is less than + // or equal to the current block number, remove it + ValidatorBoostList::::mutate(token, |validator_boost_list_op| { + if let Some(ref mut validator_boost_list) = validator_boost_list_op { + let mut remove_index = vec![]; + for (index, (_validator, due_block_number)) in validator_boost_list + .iter() + .skip(previous_count) + .take(ITERATE_LENGTH) + .enumerate() + { + if *due_block_number <= current_block_number { + remove_index.push(index + previous_count); + } + } + + // remove from the end to the start + for index in remove_index.iter().rev() { + validator_boost_list.remove(*index); + remove_num += 1; + } + } + }); + + // Deposit event. + Pallet::::deposit_event(Event::OutdatedValidatorBoostListCleaned { + currency_id: token, + page: page as u8, + remove_num, + num_left: num_left as u32, + }); + + Ok(()) + } } impl Pallet { diff --git a/pallets/slp/src/tests/manta_tests.rs b/pallets/slp/src/tests/manta_tests.rs index e5b8485f7..886195541 100644 --- a/pallets/slp/src/tests/manta_tests.rs +++ b/pallets/slp/src/tests/manta_tests.rs @@ -1918,3 +1918,104 @@ fn remove_from_validator_boost_list_should_work() { assert_eq!(Slp::get_validator_boost_list(MANTA), None); }); } + +#[test] +fn clean_outdated_validator_boost_list_work() { + ExtBuilder::default().build().execute_with(|| { + manta_setup(); + + // no validator boost list exists for this currency + assert_noop!( + Slp::clean_outdated_validator_boost_list(RuntimeOrigin::signed(ALICE), MANTA, 1), + Error::::NoMoreValidatorBoostListForCurrency + ); + + let validator_list_output_1 = + BoundedVec::try_from(vec![(VALIDATOR_0_LOCATION, SIX_MONTHS as u64 + 300)]).unwrap(); + let validator_list_output_2 = BoundedVec::try_from(vec![( + VALIDATOR_0_LOCATION, + SIX_MONTHS as u64 + 300 + SIX_MONTHS as u64, + )]) + .unwrap(); + let validator_list_output_3 = BoundedVec::try_from(vec![ + (VALIDATOR_0_LOCATION, SIX_MONTHS as u64 + 300 + SIX_MONTHS as u64), + (VALIDATOR_1_LOCATION, SIX_MONTHS as u64 + 400), + ]) + .unwrap(); + + assert_ok!(Slp::add_to_validator_boost_list( + RuntimeOrigin::signed(ALICE), + MANTA, + Box::new(VALIDATOR_0_LOCATION) + )); + + assert_eq!(Slp::get_validator_boost_list(MANTA), Some(validator_list_output_1)); + + let bounded_validator_0 = BoundedVec::try_from(vec![VALIDATOR_0_LOCATION]).unwrap(); + assert_eq!(Slp::get_validators(MANTA), Some(bounded_validator_0.clone())); + + System::set_block_number(400); + + assert_ok!(Slp::add_to_validator_boost_list( + RuntimeOrigin::signed(ALICE), + MANTA, + Box::new(VALIDATOR_0_LOCATION) + )); + + assert_eq!(Slp::get_validators(MANTA), Some(bounded_validator_0)); + + assert_eq!(Slp::get_validator_boost_list(MANTA), Some(validator_list_output_2.clone())); + + assert_ok!(Slp::add_to_validator_boost_list( + RuntimeOrigin::signed(ALICE), + MANTA, + Box::new(VALIDATOR_1_LOCATION) + )); + + assert_eq!(Slp::get_validator_boost_list(MANTA), Some(validator_list_output_3.clone())); + let bounded_validator_0_1 = + BoundedVec::try_from(vec![VALIDATOR_0_LOCATION, VALIDATOR_1_LOCATION]).unwrap(); + assert_eq!(Slp::get_validators(MANTA), Some(bounded_validator_0_1),); + + // no validator due yet. Everything should be kept after calling + // clean_outdated_validator_boost_list + System::set_block_number(399 + SIX_MONTHS as u64); + + assert_ok!(Slp::clean_outdated_validator_boost_list( + RuntimeOrigin::signed(ALICE), + MANTA, + 1 + )); + assert_eq!(Slp::get_validator_boost_list(MANTA), Some(validator_list_output_3)); + + // move to block SIX_MONTHS + 400, validator 1 should be removable + System::set_block_number(400 + SIX_MONTHS as u64); + + // page at least 1 + assert_noop!( + Slp::clean_outdated_validator_boost_list(RuntimeOrigin::signed(ALICE), MANTA, 0), + Error::::InvalidPageNumber + ); + + // successfully clean outdated validator boost list + assert_ok!(Slp::clean_outdated_validator_boost_list( + RuntimeOrigin::signed(ALICE), + MANTA, + 1 + )); + assert_eq!(Slp::get_validator_boost_list(MANTA), Some(validator_list_output_2.clone())); + + // do it again + assert_ok!(Slp::clean_outdated_validator_boost_list( + RuntimeOrigin::signed(ALICE), + MANTA, + 1 + )); + assert_eq!(Slp::get_validator_boost_list(MANTA), Some(validator_list_output_2)); + + assert_noop!( + Slp::clean_outdated_validator_boost_list(RuntimeOrigin::signed(ALICE), MANTA, 2), + Error::::NoMoreValidatorBoostListForCurrency + ); + }); +} diff --git a/pallets/slp/src/weights.rs b/pallets/slp/src/weights.rs index 01b151ccf..5011255da 100644 --- a/pallets/slp/src/weights.rs +++ b/pallets/slp/src/weights.rs @@ -98,6 +98,7 @@ pub trait WeightInfo { fn add_to_validator_boost_list() -> Weight; fn remove_from_validator_boot_list() -> Weight; fn convert_treasury_vtoken() -> Weight; + fn clean_outdated_validator_boost_list() -> Weight; } // For backwards compatibility and tests @@ -841,4 +842,9 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } + fn clean_outdated_validator_boost_list() -> 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/pallets/slpx/src/benchmarking.rs b/pallets/slpx/src/benchmarking.rs index a196b3c7e..3e58fb064 100644 --- a/pallets/slpx/src/benchmarking.rs +++ b/pallets/slpx/src/benchmarking.rs @@ -55,7 +55,6 @@ fn init_whitelist() -> (T::AccountId #[benchmarks(where T: Config + bifrost_asset_registry::Config + bifrost_stable_pool::Config + bifrost_stable_asset::Config + orml_tokens::Config)] mod benchmarks { use super::*; - use bifrost_stable_pool::AtLeast64BitUnsignedOf; use frame_benchmarking::impl_benchmark_test_suite; #[benchmark] diff --git a/runtime/bifrost-kusama/src/weights/bifrost_slp.rs b/runtime/bifrost-kusama/src/weights/bifrost_slp.rs index 53f9ffc70..7b4b8cdb0 100644 --- a/runtime/bifrost-kusama/src/weights/bifrost_slp.rs +++ b/runtime/bifrost-kusama/src/weights/bifrost_slp.rs @@ -793,4 +793,9 @@ impl bifrost_slp::WeightInfo for BifrostWeight { .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } + fn clean_outdated_validator_boost_list() -> 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/weights/bifrost_slp.rs b/runtime/bifrost-polkadot/src/weights/bifrost_slp.rs index 53f9ffc70..7b4b8cdb0 100644 --- a/runtime/bifrost-polkadot/src/weights/bifrost_slp.rs +++ b/runtime/bifrost-polkadot/src/weights/bifrost_slp.rs @@ -793,4 +793,9 @@ impl bifrost_slp::WeightInfo for BifrostWeight { .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } + fn clean_outdated_validator_boost_list() -> Weight { + Weight::from_parts(42_190_000, 3911) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } } From a3f8dbbbabdbd635e7b4f2cdc1cf9be636f7eb4c Mon Sep 17 00:00:00 2001 From: Herry Ho <45537372+herryho@users.noreply.github.com> Date: Mon, 1 Apr 2024 21:00:16 +0800 Subject: [PATCH 10/10] query token decimals instead of vtoken (#1219) --- pallets/slp/src/lib.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/pallets/slp/src/lib.rs b/pallets/slp/src/lib.rs index 0b587e947..fb9c4da7d 100644 --- a/pallets/slp/src/lib.rs +++ b/pallets/slp/src/lib.rs @@ -53,7 +53,7 @@ pub use primitives::Ledger; use sp_arithmetic::{per_things::Permill, traits::Zero}; use sp_core::{bounded::BoundedVec, H160}; use sp_io::hashing::blake2_256; -use sp_runtime::traits::{CheckedAdd, CheckedSub, Convert, TrailingZeroInput}; +use sp_runtime::traits::{CheckedAdd, CheckedSub, Convert, TrailingZeroInput, UniqueSaturatedFrom}; use sp_std::{boxed::Box, vec, vec::Vec}; pub use weights::WeightInfo; use xcm::{ @@ -2413,14 +2413,17 @@ pub mod pallet { .ok_or(Error::::StablePoolTokenIndexNotFound)?; // ensure swap balance not exceed a 10 unit - let metadata = T::AssetIdMaps::get_currency_metadata(vtoken) + let metadata = T::AssetIdMaps::get_currency_metadata(token) .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); + let max_amount: u128 = + 10u128.pow(decimals.into()).checked_mul(10).ok_or(Error::::OverFlow)?; + ensure!( + amount <= BalanceOf::::unique_saturated_from(max_amount), + Error::::ExceedLimit + ); // swap vtoken from treasury account for token let treasury = T::TreasuryAccount::get();