From b0a58c0430b77cbdcac1efd60fcb96e1136e4c4b Mon Sep 17 00:00:00 2001 From: SunTiebing <87381708+SunTiebing@users.noreply.github.com> Date: Thu, 31 Oct 2024 22:46:35 +0800 Subject: [PATCH] Feat/flexible fee ban vbnc (#1488) * Prohibit setting VBNC as the default fee currency. * Modify code formatting. * Add data migration code. --- pallets/flexible-fee/src/lib.rs | 12 ++- pallets/flexible-fee/src/migrations/mod.rs | 3 + pallets/flexible-fee/src/migrations/v3.rs | 118 +++++++++++++++++++++ pallets/flexible-fee/src/tests.rs | 18 +++- runtime/bifrost-kusama/src/lib.rs | 1 + 5 files changed, 149 insertions(+), 3 deletions(-) create mode 100644 pallets/flexible-fee/src/migrations/v3.rs diff --git a/pallets/flexible-fee/src/lib.rs b/pallets/flexible-fee/src/lib.rs index 48a0652096..074b0e18d0 100644 --- a/pallets/flexible-fee/src/lib.rs +++ b/pallets/flexible-fee/src/lib.rs @@ -159,7 +159,7 @@ pub mod pallet { } /// The current storage version, we set to 2 our new version. - const STORAGE_VERSION: StorageVersion = StorageVersion::new(2); + const STORAGE_VERSION: StorageVersion = StorageVersion::new(3); /// Universal fee currency order list for all users #[pallet::storage] @@ -188,12 +188,19 @@ pub mod pallet { #[pallet::error] pub enum Error { + /// The account does not have enough balance to perform the operation. NotEnoughBalance, + /// An error occurred during currency conversion. ConversionError, + /// No weight or fee information is available for the requested operation. WeightAndFeeNotExist, + /// The message cannot be weighed, possibly due to insufficient information. UnweighableMessage, + /// The XCM execution has failed. XcmExecutionFailed, + /// The specified currency is not supported by the system. CurrencyNotSupport, + /// The maximum number of currencies that can be handled has been reached. MaxCurrenciesReached, } @@ -212,6 +219,9 @@ pub mod pallet { let who = ensure_signed(origin)?; if let Some(fee_currency) = ¤cy_id { + // VBNC is not supported. + ensure!(fee_currency != &VBNC, Error::::CurrencyNotSupport); + UserDefaultFeeCurrency::::insert(&who, fee_currency); } else { UserDefaultFeeCurrency::::remove(&who); diff --git a/pallets/flexible-fee/src/migrations/mod.rs b/pallets/flexible-fee/src/migrations/mod.rs index 504be9301a..0ec4683cca 100644 --- a/pallets/flexible-fee/src/migrations/mod.rs +++ b/pallets/flexible-fee/src/migrations/mod.rs @@ -18,3 +18,6 @@ /// Version 2. pub mod v2; + +/// Version 3. +pub mod v3; diff --git a/pallets/flexible-fee/src/migrations/v3.rs b/pallets/flexible-fee/src/migrations/v3.rs new file mode 100644 index 0000000000..f381014f2a --- /dev/null +++ b/pallets/flexible-fee/src/migrations/v3.rs @@ -0,0 +1,118 @@ +// This file is part of Bifrost. + +// Copyright (C) Liebi Technologies PTE. LTD. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use crate::*; +use bifrost_primitives::BNC; +use frame_support::traits::OnRuntimeUpgrade; +#[cfg(feature = "try-runtime")] +use sp_runtime::TryRuntimeError; + +const LOG_TARGET: &str = "flexible-fee::migration"; + +pub struct MigrateToV3(sp_std::marker::PhantomData); +impl OnRuntimeUpgrade for MigrateToV3 { + fn on_runtime_upgrade() -> frame_support::weights::Weight { + // Check the storage version + let onchain_version = Pallet::::on_chain_storage_version(); + if onchain_version < 3 { + log::info!(target: LOG_TARGET, "Start to migrate flexible-fee storage..."); + + let mut count: u64 = 0; + + // Traversal UserDefaultFeeCurrency storage + UserDefaultFeeCurrency::::iter().for_each(|(account_id, currency_id)| { + // If currency_id is vbnc, change it to bnc + if currency_id == VBNC { + count += 1; + UserDefaultFeeCurrency::::insert(account_id, BNC); + } + }); + + // Update the storage version + StorageVersion::new(3).put::>(); + + // Return the consumed weight + Weight::from(T::DbWeight::get().reads_writes(count + 1, count + 1)) + } else { + // We don't do anything here. + Weight::zero() + } + } + + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result, TryRuntimeError> { + let total_count = UserDefaultFeeCurrency::::iter().count(); + + let mut vbnc_count: u64 = 0; + UserDefaultFeeCurrency::::iter().for_each(|(_, currency_id)| { + if currency_id == VBNC { + vbnc_count += 1; + } + }); + + // print out the pre-migrate storage count + log::info!( + target: LOG_TARGET, + "UserDefaultFeeCurrency pre-migrate storage total count: {:?}", + total_count + ); + log::info!( + target: LOG_TARGET, + "UserDefaultFeeCurrency pre-migrate storage vbnc count: {:?}", + vbnc_count + ); + Ok((total_count as u64).encode()) + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade(cnt: Vec) -> Result<(), TryRuntimeError> { + let old_total_count: u64 = Decode::decode(&mut cnt.as_slice()) + .expect("the state parameter should be something that was generated by pre_upgrade"); + + let new_total_count = UserDefaultFeeCurrency::::iter().count(); + + let mut new_vbnc_count: u64 = 0; + UserDefaultFeeCurrency::::iter().for_each(|(_, currency_id)| { + if currency_id == VBNC { + new_vbnc_count += 1; + } + }); + + // print out the post-migrate storage count + log::info!( + target: LOG_TARGET, + "UserDefaultFeeCurrency post-migrate storage total count: {:?}", + new_total_count + ); + log::info!( + target: LOG_TARGET, + "UserDefaultFeeCurrency post-migrate storage vbnc count: {:?}", + new_vbnc_count + ); + + ensure!( + new_total_count as u64 == old_total_count, + "Post-migration storage total count does not match pre-migration total count" + ); + ensure!( + new_vbnc_count == 0, + "Post-migration storage vbnc count does not match pre-migration vbnc count" + ); + Ok(()) + } +} diff --git a/pallets/flexible-fee/src/tests.rs b/pallets/flexible-fee/src/tests.rs index ce373e01e3..e7ffb47f11 100644 --- a/pallets/flexible-fee/src/tests.rs +++ b/pallets/flexible-fee/src/tests.rs @@ -21,10 +21,11 @@ #![cfg(test)] use crate::{ impls::on_charge_transaction::PaymentInfo, mock::*, BlockNumberFor, BoundedVec, Config, - DispatchError::BadOrigin, UserDefaultFeeCurrency, + DispatchError::BadOrigin, Error, UserDefaultFeeCurrency, }; use bifrost_primitives::{ - AccountFeeCurrency, BalanceCmp, CurrencyId, TryConvertFrom, BNC, DOT, KSM, MANTA, VDOT, WETH, + AccountFeeCurrency, BalanceCmp, CurrencyId, TryConvertFrom, BNC, DOT, KSM, MANTA, VBNC, VDOT, + WETH, }; use frame_support::{ assert_noop, assert_ok, @@ -151,6 +152,19 @@ fn set_user_default_fee_currency_should_work() { }); } +#[test] +fn set_user_default_fee_currency_should_fail_with_error_currency() { + new_test_ext().execute_with(|| { + let origin_signed_alice = RuntimeOrigin::signed(ALICE); + assert_noop!( + FlexibleFee::set_user_default_fee_currency(origin_signed_alice.clone(), Some(VBNC)), + Error::::CurrencyNotSupport + ); + + assert_eq!(UserDefaultFeeCurrency::::get(ALICE).is_none(), true); + }); +} + #[test] fn set_default_fee_currency_list_should_work() { new_test_ext().execute_with(|| { diff --git a/runtime/bifrost-kusama/src/lib.rs b/runtime/bifrost-kusama/src/lib.rs index e0ecd6cb53..22d139ec3c 100644 --- a/runtime/bifrost-kusama/src/lib.rs +++ b/runtime/bifrost-kusama/src/lib.rs @@ -2034,6 +2034,7 @@ pub mod migrations { >, // permanent migration, do not remove pallet_xcm::migration::MigrateToLatestXcmVersion, + bifrost_flexible_fee::migrations::v3::MigrateToV3, ); }