From 897528a182255075160ef936e61b52e203f96587 Mon Sep 17 00:00:00 2001
From: SunTiebing <1045060705@qq.com>
Date: Thu, 19 Sep 2024 12:06:24 +0800
Subject: [PATCH 01/31] Bifrost v0.14.0

---
 Cargo.lock                          | 2 +-
 node/cli/Cargo.toml                 | 2 +-
 runtime/bifrost-kusama/src/lib.rs   | 2 +-
 runtime/bifrost-polkadot/src/lib.rs | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 008dbdeaa..3bcd412b1 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1011,7 +1011,7 @@ dependencies = [
 
 [[package]]
 name = "bifrost-cli"
-version = "0.13.0"
+version = "0.14.0"
 dependencies = [
  "bifrost-primitives",
  "bifrost-service",
diff --git a/node/cli/Cargo.toml b/node/cli/Cargo.toml
index 1adb0e8fb..11b753212 100644
--- a/node/cli/Cargo.toml
+++ b/node/cli/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "bifrost-cli"
-version = "0.13.0"
+version = "0.14.0"
 authors = ["Liebi Technologies <bifrost@liebi.com>"]
 description = "Bifrost Parachain Node"
 build = "build.rs"
diff --git a/runtime/bifrost-kusama/src/lib.rs b/runtime/bifrost-kusama/src/lib.rs
index ee116c46a..eacd32e5b 100644
--- a/runtime/bifrost-kusama/src/lib.rs
+++ b/runtime/bifrost-kusama/src/lib.rs
@@ -145,7 +145,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
 	spec_name: create_runtime_str!("bifrost"),
 	impl_name: create_runtime_str!("bifrost"),
 	authoring_version: 1,
-	spec_version: 13000,
+	spec_version: 14000,
 	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 db5bd4b9a..c35de71bb 100644
--- a/runtime/bifrost-polkadot/src/lib.rs
+++ b/runtime/bifrost-polkadot/src/lib.rs
@@ -169,7 +169,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: 13000,
+	spec_version: 14000,
 	impl_version: 0,
 	apis: RUNTIME_API_VERSIONS,
 	transaction_version: 1,

From ef3c9edaf8e73f9467c6e36ecc9cc6cffd9498de Mon Sep 17 00:00:00 2001
From: SunTiebing <87381708+SunTiebing@users.noreply.github.com>
Date: Mon, 23 Sep 2024 13:12:44 +0800
Subject: [PATCH 02/31] Feat/optimize salp (#1433)

* Backup salp pallet

* remove unused BancorHandler

* remove unused Call of SALP

* remove extra fee of bifrost_salp::Call::contribute in runtime

* adjust test and benchmarking

* remove unused interface type of SALP

* fix clippy
---
 pallets/deprecated/salp/Cargo.toml            |   78 +
 pallets/deprecated/salp/rpc/Cargo.toml        |   16 +
 .../salp/rpc/runtime-api/Cargo.toml           |   18 +
 .../salp/rpc/runtime-api/src/lib.rs           |   35 +
 pallets/deprecated/salp/rpc/src/lib.rs        |  101 +
 pallets/deprecated/salp/src/benchmarking.rs   |  558 ++++++
 pallets/deprecated/salp/src/lib.rs            | 1756 +++++++++++++++++
 pallets/deprecated/salp/src/mock.rs           |  641 ++++++
 pallets/deprecated/salp/src/tests.rs          | 1604 +++++++++++++++
 pallets/deprecated/salp/src/weights.rs        |  458 +++++
 pallets/flexible-fee/src/tests.rs             |   43 -
 pallets/salp/src/benchmarking.rs              |  246 +--
 pallets/salp/src/lib.rs                       | 1164 ++++-------
 pallets/salp/src/mock.rs                      |    8 +-
 pallets/salp/src/tests.rs                     |  592 +-----
 pallets/salp/src/weights.rs                   |   89 -
 primitives/src/traits.rs                      |   12 +-
 runtime/bifrost-kusama/src/lib.rs             |    5 -
 .../src/weights/bifrost_salp.rs               |   85 -
 runtime/bifrost-kusama/src/xcm_config.rs      |    7 +-
 runtime/bifrost-polkadot/src/lib.rs           |    5 -
 .../src/weights/bifrost_salp.rs               |   85 -
 runtime/bifrost-polkadot/src/xcm_config.rs    |    7 +-
 23 files changed, 5606 insertions(+), 2007 deletions(-)
 create mode 100644 pallets/deprecated/salp/Cargo.toml
 create mode 100644 pallets/deprecated/salp/rpc/Cargo.toml
 create mode 100644 pallets/deprecated/salp/rpc/runtime-api/Cargo.toml
 create mode 100644 pallets/deprecated/salp/rpc/runtime-api/src/lib.rs
 create mode 100644 pallets/deprecated/salp/rpc/src/lib.rs
 create mode 100644 pallets/deprecated/salp/src/benchmarking.rs
 create mode 100644 pallets/deprecated/salp/src/lib.rs
 create mode 100644 pallets/deprecated/salp/src/mock.rs
 create mode 100644 pallets/deprecated/salp/src/tests.rs
 create mode 100644 pallets/deprecated/salp/src/weights.rs

diff --git a/pallets/deprecated/salp/Cargo.toml b/pallets/deprecated/salp/Cargo.toml
new file mode 100644
index 000000000..ae26cb32e
--- /dev/null
+++ b/pallets/deprecated/salp/Cargo.toml
@@ -0,0 +1,78 @@
+[package]
+name = "bifrost-salp"
+version = "0.8.0"
+authors = ["Edwin Wang <lark930@gmail.com>", "Ron yang<yrong1997@gmail.com>"]
+edition = "2021"
+
+[dependencies]
+parity-scale-codec = { workspace = true, features = ["derive"] }
+scale-info = { workspace = true, features = ["derive"] }
+log = { workspace = true }
+bifrost-primitives = { workspace = true }
+frame-support = { workspace = true }
+frame-system = { workspace = true }
+frame-benchmarking = { workspace = true, optional = true }
+sp-std = { workspace = true }
+sp-io = { workspace = true }
+sp-runtime = { workspace = true }
+sp-arithmetic = { workspace = true }
+orml-traits = { workspace = true }
+orml-tokens = { workspace = true }
+bifrost-xcm-interface = { workspace = true }
+zenlink-protocol = { workspace = true }
+cumulus-primitives-core = { workspace = true }
+pallet-xcm = { workspace = true }
+xcm = { workspace = true }
+xcm-builder = { workspace = true }
+bifrost-stable-pool = { workspace = true }
+bifrost-stable-asset = { workspace = true }
+bifrost-vtoken-minting = { workspace = true }
+
+[dev-dependencies]
+pallet-multisig = { workspace = true }
+pallet-sudo = { workspace = true }
+pallet-collective = { workspace = true }
+sp-core = { workspace = true }
+bifrost-currencies = { workspace = true }
+orml-xtokens = { workspace = true }
+pallet-balances = { workspace = true }
+bifrost-asset-registry = { workspace = true }
+xcm-executor = { workspace = true }
+
+
+[features]
+default = ["std"]
+std = [
+	"parity-scale-codec/std",
+	"scale-info/std",
+	"log/std",
+	"bifrost-primitives/std",
+	"frame-support/std",
+	"frame-system/std",
+	"sp-std/std",
+	"sp-io/std",
+	"sp-runtime/std",
+	"sp-arithmetic/std",
+	"orml-traits/std",
+	"bifrost-xcm-interface/std",
+	"xcm-builder/std",
+	"zenlink-protocol/std",
+	"bifrost-asset-registry/std",
+	"cumulus-primitives-core/std",
+	"pallet-xcm/std",
+	"pallet-sudo/std",
+	"xcm/std",
+	"pallet-multisig/std",
+	"pallet-collective/std",
+	"orml-xtokens/std",
+]
+
+runtime-benchmarks = [
+	"frame-benchmarking",
+	"frame-support/runtime-benchmarks",
+	"frame-system/runtime-benchmarks",
+	"xcm-builder/runtime-benchmarks",
+	"pallet-xcm/runtime-benchmarks",
+	"pallet-collective/runtime-benchmarks",
+]
+try-runtime = [ "frame-support/try-runtime" ]
diff --git a/pallets/deprecated/salp/rpc/Cargo.toml b/pallets/deprecated/salp/rpc/Cargo.toml
new file mode 100644
index 000000000..1015d62ab
--- /dev/null
+++ b/pallets/deprecated/salp/rpc/Cargo.toml
@@ -0,0 +1,16 @@
+[package]
+name = "bifrost-salp-rpc"
+version = "0.8.0"
+authors = ["Ron Yang <yrong1997@gmail.com>"]
+edition = "2021"
+
+[dependencies]
+parity-scale-codec = { workspace = true, features = ["derive"] }
+jsonrpsee = { workspace = true, features = ["server", "macros"] }
+sp-api = { workspace = true }
+sp-runtime = { workspace = true }
+sp-blockchain = { workspace = true }
+sp-core = { workspace = true }
+sp-rpc = { workspace = true }
+bifrost-primitives = { workspace = true }
+bifrost-salp-rpc-runtime-api = { workspace = true }
diff --git a/pallets/deprecated/salp/rpc/runtime-api/Cargo.toml b/pallets/deprecated/salp/rpc/runtime-api/Cargo.toml
new file mode 100644
index 000000000..4d40d9b24
--- /dev/null
+++ b/pallets/deprecated/salp/rpc/runtime-api/Cargo.toml
@@ -0,0 +1,18 @@
+[package]
+name = "bifrost-salp-rpc-runtime-api"
+version = "0.8.0"
+authors = ["Ron Yang<yrong1997@gmail.com>"]
+edition = "2021"
+
+[dependencies]
+parity-scale-codec = { workspace = true, features = ["derive"] }
+sp-api = { workspace = true }
+bifrost-primitives = { workspace = true }
+
+[features]
+default = ["std"]
+std = [
+	"parity-scale-codec/std",
+	"sp-api/std",
+	"bifrost-primitives/std",
+]
diff --git a/pallets/deprecated/salp/rpc/runtime-api/src/lib.rs b/pallets/deprecated/salp/rpc/runtime-api/src/lib.rs
new file mode 100644
index 000000000..108b16270
--- /dev/null
+++ b/pallets/deprecated/salp/rpc/runtime-api/src/lib.rs
@@ -0,0 +1,35 @@
+// 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 <https://www.gnu.org/licenses/>.
+
+#![cfg_attr(not(feature = "std"), no_std)]
+
+use bifrost_primitives::{Balance, RpcContributionStatus};
+use parity_scale_codec::Codec;
+use sp_api::decl_runtime_apis;
+
+decl_runtime_apis! {
+	pub trait SalpRuntimeApi<ParaId,AccountId> where
+		ParaId: Codec,
+		AccountId: Codec,
+	{
+		fn get_contribution(
+			index: ParaId,
+			who: AccountId
+		) -> (Balance,RpcContributionStatus);
+	}
+}
diff --git a/pallets/deprecated/salp/rpc/src/lib.rs b/pallets/deprecated/salp/rpc/src/lib.rs
new file mode 100644
index 000000000..ebd2a8222
--- /dev/null
+++ b/pallets/deprecated/salp/rpc/src/lib.rs
@@ -0,0 +1,101 @@
+// 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 <https://www.gnu.org/licenses/>.
+
+use std::{marker::PhantomData, sync::Arc};
+
+use bifrost_primitives::{Balance, RpcContributionStatus};
+pub use bifrost_salp_rpc_runtime_api::{self as runtime_api, SalpRuntimeApi};
+use jsonrpsee::{
+	core::{async_trait, RpcResult},
+	proc_macros::rpc,
+	types::error::{ErrorCode, ErrorObject},
+};
+use parity_scale_codec::Codec;
+use sp_api::ProvideRuntimeApi;
+use sp_blockchain::HeaderBackend;
+use sp_rpc::number::NumberOrHex;
+use sp_runtime::{sp_std::convert::TryInto, traits::Block as BlockT};
+
+#[derive(Clone, Debug)]
+pub struct SalpRpc<C, Block> {
+	client: Arc<C>,
+	_marker: PhantomData<Block>,
+}
+
+impl<C, Block> SalpRpc<C, Block> {
+	pub fn new(client: Arc<C>) -> Self {
+		Self { client, _marker: PhantomData }
+	}
+}
+
+fn convert_rpc_params(value: Balance) -> RpcResult<NumberOrHex> {
+	value.try_into().map_err(|e| {
+		ErrorObject::owned(
+			ErrorCode::InvalidParams.code(),
+			format!("{} doesn't fit in NumberOrHex representation", value),
+			Some(format!("{:?}", e)),
+		)
+	})
+}
+
+#[rpc(client, server)]
+pub trait SalpRpcApi<BlockHash, ParaId, AccountId> {
+	/// rpc method for getting current contribution
+	#[method(name = "salp_getContribution")]
+	fn get_contribution(
+		&self,
+		index: ParaId,
+		who: AccountId,
+		at: Option<BlockHash>,
+	) -> RpcResult<(NumberOrHex, RpcContributionStatus)>;
+}
+
+#[async_trait]
+impl<C, Block, ParaId, AccountId> SalpRpcApiServer<<Block as BlockT>::Hash, ParaId, AccountId>
+	for SalpRpc<C, Block>
+where
+	Block: BlockT,
+	C: Send + Sync + 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block>,
+	C::Api: SalpRuntimeApi<Block, ParaId, AccountId>,
+	ParaId: Codec,
+	AccountId: Codec,
+{
+	fn get_contribution(
+		&self,
+		index: ParaId,
+		account: AccountId,
+		at: Option<<Block as BlockT>::Hash>,
+	) -> RpcResult<(NumberOrHex, RpcContributionStatus)> {
+		let salp_rpc_api = self.client.runtime_api();
+		let at = at.unwrap_or_else(|| self.client.info().best_hash);
+
+		let rs = salp_rpc_api.get_contribution(at, index, account);
+
+		match rs {
+			Ok((val, status)) => match convert_rpc_params(val) {
+				Ok(value) => Ok((value, status)),
+				Err(e) => Err(e),
+			},
+			Err(e) => Err(ErrorObject::owned(
+				ErrorCode::InternalError.code(),
+				"Failed to get salp contribution.",
+				Some(format!("{:?}", e)),
+			)),
+		}
+	}
+}
diff --git a/pallets/deprecated/salp/src/benchmarking.rs b/pallets/deprecated/salp/src/benchmarking.rs
new file mode 100644
index 000000000..cbb3f249b
--- /dev/null
+++ b/pallets/deprecated/salp/src/benchmarking.rs
@@ -0,0 +1,558 @@
+// 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 <https://www.gnu.org/licenses/>.
+
+// Ensure we're `no_std` when compiling for Wasm.
+#[cfg(feature = "runtime-benchmarks")]
+use crate::{Pallet as Salp, *};
+use bifrost_primitives::{CurrencyId, ParaId, XcmOperationType, KSM, VSKSM};
+use bifrost_stable_pool::AtLeast64BitUnsignedOf;
+use bifrost_xcm_interface::XcmWeightAndFee;
+use frame_benchmarking::v2::*;
+use frame_support::assert_ok;
+use frame_system::{pallet_prelude::BlockNumberFor, RawOrigin};
+use sp_runtime::{
+	traits::{AccountIdConversion, Bounded, StaticLookup, UniqueSaturatedFrom},
+	SaturatedConversion,
+};
+use sp_std::prelude::*;
+
+fn assert_last_event<T: Config>(generic_event: <T as Config>::RuntimeEvent) {
+	let events = frame_system::Pallet::<T>::events();
+	let system_event: <T as frame_system::Config>::RuntimeEvent = generic_event.into();
+	// compare to the last event record
+	let frame_system::EventRecord { event, .. } = &events[events.len() - 1];
+	assert_eq!(event, &system_event);
+}
+
+fn create_fund<T: Config>(id: u32) -> ParaId {
+	let cap = BalanceOf::<T>::max_value();
+	let first_period = 0u32.into();
+	let last_period = 7u32.into();
+	let para_id = id;
+
+	assert_ok!(Salp::<T>::create(RawOrigin::Root.into(), para_id, cap, first_period, last_period));
+
+	para_id
+}
+
+fn contribute_fund<T: Config + bifrost_xcm_interface::Config>(
+	index: ParaId,
+) -> (T::AccountId, BalanceOf<T>)
+where
+	<<T as bifrost_xcm_interface::Config>::MultiCurrency as MultiCurrency<
+		<T as frame_system::Config>::AccountId,
+	>>::CurrencyId: From<CurrencyId>,
+{
+	let who: T::AccountId = whitelisted_caller();
+	let value = T::MinContribution::get();
+	assert_ok!(Salp::<T>::set_balance(&who, value));
+	XcmWeightAndFee::<T>::insert(
+		bifrost_xcm_interface::CurrencyIdOf::<T>::from(KSM.into()),
+		XcmOperationType::UmpContributeTransact,
+		(
+			Weight::from_parts(4000000000, 100000),
+			bifrost_xcm_interface::BalanceOf::<T>::from(4000000000u32),
+		),
+	);
+	assert_ok!(Salp::<T>::contribute(RawOrigin::Signed(who.clone()).into(), index, value));
+	QueryIdContributionInfo::<T>::insert(0u64, (index, who.clone(), value));
+	MultisigConfirmAccount::<T>::put(who.clone());
+	(who, value)
+}
+
+#[benchmarks(
+where T: Config + bifrost_stable_pool::Config + bifrost_stable_asset::Config + orml_tokens::Config<CurrencyId = CurrencyId> + bifrost_vtoken_minting::Config + bifrost_xcm_interface::Config + zenlink_protocol::Config<AssetId = zenlink_protocol::AssetId>,
+<<T as bifrost_xcm_interface::Config>::MultiCurrency as MultiCurrency<<T as frame_system::Config>::AccountId>>::CurrencyId: From<CurrencyId>
+)]
+mod benchmarks {
+	use super::*;
+
+	#[benchmark]
+	fn contribute() {
+		let fund_index = create_fund::<T>(1);
+		let caller: T::AccountId = whitelisted_caller();
+		let contribution = T::MinContribution::get();
+		XcmWeightAndFee::<T>::insert(
+			bifrost_xcm_interface::CurrencyIdOf::<T>::from(KSM.into()),
+			XcmOperationType::UmpContributeTransact,
+			(
+				Weight::from_parts(4000000000, 100000),
+				bifrost_xcm_interface::BalanceOf::<T>::from(4000000000u32),
+			),
+		);
+		assert_ok!(Salp::<T>::set_balance(&caller, contribution));
+
+		#[extrinsic_call]
+		_(RawOrigin::Signed(caller.clone()), fund_index, contribution);
+	}
+
+	#[benchmark]
+	fn refund() {
+		let fund_index = create_fund::<T>(1);
+		let (caller, contribution) = contribute_fund::<T>(fund_index);
+		assert_ok!(Pallet::<T>::confirm_contribute(
+			RawOrigin::Signed(caller.clone()).into(),
+			0u64,
+			true
+		));
+
+		assert_ok!(Salp::<T>::fund_fail(RawOrigin::Root.into(), fund_index));
+		assert_ok!(Salp::<T>::withdraw(RawOrigin::Root.into(), fund_index));
+		let fund = Funds::<T>::get(fund_index).unwrap();
+		let (_, status) = Salp::<T>::contribution(fund.trie_index, &caller);
+		assert_eq!(status, ContributionStatus::Idle);
+
+		#[extrinsic_call]
+		_(RawOrigin::Signed(caller.clone()), fund_index, 0u32.into(), 7u32.into(), contribution);
+
+		let (_, status) = Salp::<T>::contribution(fund.trie_index, &caller);
+		assert_eq!(status, ContributionStatus::Idle);
+		assert_last_event::<T>(
+			Event::<T>::Refunded(
+				caller.clone(),
+				fund_index,
+				0u32.into(),
+				7u32.into(),
+				contribution,
+			)
+			.into(),
+		)
+	}
+
+	#[benchmark]
+	fn unlock() {
+		let fund_index = create_fund::<T>(1);
+		let (caller, _) = contribute_fund::<T>(fund_index);
+		assert_ok!(Pallet::<T>::confirm_contribute(
+			RawOrigin::Signed(caller.clone()).into(),
+			0u64,
+			true
+		));
+
+		assert_ok!(Salp::<T>::fund_success(RawOrigin::Root.into(), fund_index));
+
+		#[extrinsic_call]
+		_(RawOrigin::Signed(caller.clone()), caller.clone(), fund_index);
+	}
+
+	#[benchmark]
+	fn batch_unlock() {
+		let fund_index = create_fund::<T>(1);
+		let caller: T::AccountId = whitelisted_caller();
+		for _ in 0..5 {
+			let (caller, _) = contribute_fund::<T>(fund_index);
+			assert_ok!(Pallet::<T>::confirm_contribute(
+				RawOrigin::Signed(caller.clone()).into(),
+				0u64,
+				true
+			));
+		}
+
+		assert_ok!(Salp::<T>::fund_success(RawOrigin::Root.into(), fund_index));
+
+		#[extrinsic_call]
+		_(RawOrigin::Signed(caller.clone()), fund_index);
+	}
+
+	#[benchmark]
+	fn redeem() {
+		let fund_index = create_fund::<T>(1);
+		let (caller, contribution) = contribute_fund::<T>(fund_index);
+		assert_ok!(Pallet::<T>::confirm_contribute(
+			RawOrigin::Signed(caller.clone()).into(),
+			0u64,
+			true
+		));
+
+		assert_ok!(Salp::<T>::fund_success(RawOrigin::Root.into(), fund_index));
+		assert_ok!(Salp::<T>::unlock(
+			RawOrigin::Signed(caller.clone()).into(),
+			caller.clone(),
+			fund_index
+		));
+		assert_ok!(Salp::<T>::fund_retire(RawOrigin::Root.into(), fund_index));
+		assert_ok!(Salp::<T>::withdraw(RawOrigin::Root.into(), fund_index));
+		assert_eq!(RedeemPool::<T>::get(), T::MinContribution::get());
+
+		#[extrinsic_call]
+		_(RawOrigin::Signed(caller.clone()), fund_index, contribution);
+
+		assert_eq!(RedeemPool::<T>::get(), 0_u32.saturated_into());
+	}
+
+	#[benchmark]
+	fn set_multisig_confirm_account() {
+		#[extrinsic_call]
+		_(RawOrigin::Root, whitelisted_caller());
+	}
+
+	#[benchmark]
+	fn fund_success() {
+		let fund_index = create_fund::<T>(1);
+		let (caller, _) = contribute_fund::<T>(fund_index);
+		assert_ok!(Pallet::<T>::confirm_contribute(
+			RawOrigin::Signed(caller.clone()).into(),
+			0u64,
+			true
+		));
+
+		#[extrinsic_call]
+		_(RawOrigin::Root, fund_index);
+	}
+
+	#[benchmark]
+	fn fund_fail() {
+		let fund_index = create_fund::<T>(1);
+		let (caller, _) = contribute_fund::<T>(fund_index);
+		assert_ok!(Pallet::<T>::confirm_contribute(
+			RawOrigin::Signed(caller.clone()).into(),
+			0u64,
+			true
+		));
+
+		#[extrinsic_call]
+		_(RawOrigin::Root, fund_index);
+	}
+
+	#[benchmark]
+	fn continue_fund() {
+		let fund_index = create_fund::<T>(1);
+		let (caller, _) = contribute_fund::<T>(fund_index);
+		assert_ok!(Pallet::<T>::confirm_contribute(
+			RawOrigin::Signed(caller.clone()).into(),
+			0u64,
+			true
+		));
+
+		assert_ok!(Salp::<T>::fund_fail(RawOrigin::Root.into(), fund_index));
+		assert_ok!(Salp::<T>::withdraw(RawOrigin::Root.into(), fund_index));
+		#[extrinsic_call]
+		_(RawOrigin::Root, fund_index, 0u32.into(), 3u32.into());
+	}
+
+	#[benchmark]
+	fn fund_retire() {
+		let fund_index = create_fund::<T>(1);
+		let (caller, _) = contribute_fund::<T>(fund_index);
+		assert_ok!(Pallet::<T>::confirm_contribute(
+			RawOrigin::Signed(caller.clone()).into(),
+			0u64,
+			true
+		));
+
+		assert_ok!(Salp::<T>::fund_success(RawOrigin::Root.into(), fund_index));
+		assert_ok!(Salp::<T>::unlock(
+			RawOrigin::Signed(caller.clone()).into(),
+			caller.clone(),
+			fund_index
+		));
+		#[extrinsic_call]
+		_(RawOrigin::Root, fund_index);
+	}
+
+	#[benchmark]
+	fn fund_end() {
+		let fund_index = create_fund::<T>(1);
+		let (caller, _) = contribute_fund::<T>(fund_index);
+		assert_ok!(Pallet::<T>::confirm_contribute(
+			RawOrigin::Signed(caller.clone()).into(),
+			0u64,
+			true
+		));
+
+		assert_ok!(Salp::<T>::fund_fail(RawOrigin::Root.into(), fund_index));
+		assert_ok!(Salp::<T>::withdraw(RawOrigin::Root.into(), fund_index));
+		#[extrinsic_call]
+		_(RawOrigin::Root, fund_index);
+	}
+
+	#[benchmark]
+	fn create() {
+		#[extrinsic_call]
+		_(RawOrigin::Root, 2001u32, BalanceOf::<T>::max_value(), 0u32.into(), 3u32.into());
+	}
+
+	#[benchmark]
+	fn edit() {
+		create_fund::<T>(2001u32);
+		#[extrinsic_call]
+		_(
+			RawOrigin::Root,
+			2001u32,
+			BalanceOf::<T>::max_value(),
+			BalanceOf::<T>::max_value(),
+			0u32.into(),
+			8u32.into(),
+			None,
+		);
+	}
+
+	#[benchmark]
+	fn confirm_contribute() {
+		let fund_index = create_fund::<T>(1);
+		let (caller, _) = contribute_fund::<T>(fund_index);
+
+		#[extrinsic_call]
+		_(RawOrigin::Signed(caller), 0, true)
+	}
+
+	#[benchmark]
+	fn withdraw() {
+		let fund_index = create_fund::<T>(1);
+		contribute_fund::<T>(fund_index);
+
+		assert_ok!(Salp::<T>::fund_fail(RawOrigin::Root.into(), fund_index));
+		#[extrinsic_call]
+		_(RawOrigin::Root, fund_index)
+	}
+
+	#[benchmark]
+	fn dissolve_refunded() {
+		let fund_index = create_fund::<T>(1);
+		let (caller, _) = contribute_fund::<T>(fund_index);
+		assert_ok!(Pallet::<T>::confirm_contribute(
+			RawOrigin::Signed(caller.clone()).into(),
+			0u64,
+			true
+		));
+
+		assert_ok!(Salp::<T>::fund_fail(RawOrigin::Root.into(), fund_index));
+		assert_ok!(Salp::<T>::withdraw(RawOrigin::Root.into(), fund_index));
+		assert_ok!(Salp::<T>::continue_fund(
+			RawOrigin::Root.into(),
+			fund_index,
+			2,
+			T::SlotLength::get() + 1
+		));
+		#[extrinsic_call]
+		_(RawOrigin::Root, fund_index, 0, 7)
+	}
+
+	#[benchmark]
+	fn dissolve() {
+		let fund_index = create_fund::<T>(1);
+		let (caller, _) = contribute_fund::<T>(fund_index);
+		assert_ok!(Pallet::<T>::confirm_contribute(
+			RawOrigin::Signed(caller.clone()).into(),
+			0u64,
+			true
+		));
+
+		assert_ok!(Salp::<T>::fund_success(RawOrigin::Root.into(), fund_index));
+		assert_ok!(Salp::<T>::fund_retire(RawOrigin::Root.into(), fund_index));
+		assert_ok!(Salp::<T>::withdraw(RawOrigin::Root.into(), fund_index));
+		assert_ok!(Salp::<T>::fund_end(RawOrigin::Root.into(), fund_index));
+		#[extrinsic_call]
+		_(RawOrigin::Root, fund_index)
+	}
+
+	#[benchmark]
+	fn buyback() {
+		let caller: T::AccountId = whitelisted_caller();
+		let relay_currency_id = <T as Config>::RelayChainToken::get();
+		let relay_vstoken_id =
+			<T as Config>::CurrencyIdConversion::convert_to_vstoken(relay_currency_id).unwrap();
+
+		let caller_lookup: <T::Lookup as StaticLookup>::Source =
+			T::Lookup::unlookup(caller.clone());
+		assert_ok!(zenlink_protocol::Pallet::<T>::create_pair(
+			RawOrigin::Root.into(),
+			zenlink_protocol::AssetId { chain_id: 2001, asset_type: 2, asset_index: 516 },
+			zenlink_protocol::AssetId { chain_id: 2001, asset_type: 2, asset_index: 1028 },
+			caller_lookup
+		));
+
+		let buybck_caller = T::BuybackPalletId::get().into_account_truncating();
+		assert_ok!(<T as pallet::Config>::MultiCurrency::deposit(
+			relay_currency_id,
+			&buybck_caller,
+			BalanceOf::<T>::unique_saturated_from(1_000_000_000_000_000u128)
+		));
+		assert_ok!(<T as pallet::Config>::MultiCurrency::deposit(
+			relay_vstoken_id,
+			&buybck_caller,
+			BalanceOf::<T>::unique_saturated_from(1_000_000_000_000_000u128)
+		));
+
+		assert_ok!(zenlink_protocol::Pallet::<T>::add_liquidity(
+			RawOrigin::Signed(buybck_caller).into(),
+			zenlink_protocol::AssetId { chain_id: 2001, asset_type: 2, asset_index: 516 },
+			zenlink_protocol::AssetId { chain_id: 2001, asset_type: 2, asset_index: 1028 },
+			1_000_000_000_000u128,
+			100_000_000_000_000u128,
+			0u128,
+			0u128,
+			BlockNumberFor::<T>::from(10u32),
+		));
+
+		#[extrinsic_call]
+		_(RawOrigin::Signed(caller), BalanceOf::<T>::unique_saturated_from(1000u128))
+	}
+
+	#[benchmark]
+	fn buyback_vstoken_by_stable_pool() {
+		let caller: T::AccountId = whitelisted_caller();
+		let fee_account: T::AccountId = account("seed", 1, 1);
+		let buyback_account: T::AccountId = T::BuybackPalletId::get().into_account_truncating();
+
+		let amounts1: AtLeast64BitUnsignedOf<T> = 1_000_000_000_000u128.into();
+		let amounts: <T as bifrost_stable_asset::pallet::Config>::Balance = amounts1.into();
+		assert_ok!(bifrost_stable_pool::Pallet::<T>::create_pool(
+			RawOrigin::Root.into(),
+			vec![KSM.into(), VSKSM.into()],
+			vec![1u128.into(), 1u128.into()],
+			0u128.into(),
+			0u128.into(),
+			0u128.into(),
+			220u128.into(),
+			fee_account.clone(),
+			fee_account.clone(),
+			1000000000000u128.into()
+		));
+		assert_ok!(bifrost_stable_pool::Pallet::<T>::edit_token_rate(
+			RawOrigin::Root.into(),
+			0,
+			vec![
+				(VSKSM.into(), (1u128.into(), 1u128.into())),
+				(KSM.into(), (10u128.into(), 30u128.into()))
+			]
+		));
+
+		assert_ok!(<T as pallet::Config>::MultiCurrency::deposit(
+			KSM,
+			&buyback_account,
+			BalanceOf::<T>::unique_saturated_from(1_000_000_000_000_000_000u128)
+		));
+		assert_ok!(<T as pallet::Config>::MultiCurrency::deposit(
+			KSM,
+			&caller,
+			BalanceOf::<T>::unique_saturated_from(1_000_000_000_000_000_000u128)
+		));
+		assert_ok!(<T as pallet::Config>::MultiCurrency::deposit(
+			VSKSM,
+			&caller,
+			BalanceOf::<T>::unique_saturated_from(1_000_000_000_000_000_000u128)
+		));
+
+		assert_ok!(bifrost_stable_pool::Pallet::<T>::add_liquidity(
+			RawOrigin::Signed(caller.clone()).into(),
+			0,
+			vec![amounts, amounts],
+			amounts
+		));
+		let minimum_mint_value =
+			bifrost_vtoken_minting::BalanceOf::<T>::unique_saturated_from(0u128);
+		let token_amount =
+			bifrost_vtoken_minting::BalanceOf::<T>::unique_saturated_from(1_000_000_000_000u128);
+		assert_ok!(bifrost_vtoken_minting::Pallet::<T>::set_minimum_mint(
+			RawOrigin::Root.into(),
+			KSM,
+			minimum_mint_value
+		));
+		assert_ok!(bifrost_vtoken_minting::Pallet::<T>::mint(
+			RawOrigin::Signed(caller.clone()).into(),
+			KSM,
+			token_amount,
+			BoundedVec::default(),
+			None
+		));
+		#[extrinsic_call]
+		_(RawOrigin::Signed(caller), 0, KSM, 1_000_000_000u32.into())
+	}
+
+	#[benchmark]
+	fn reserve() {
+		let fund_index = create_fund::<T>(1);
+		let (caller, contribution) = contribute_fund::<T>(fund_index);
+		assert_ok!(Pallet::<T>::confirm_contribute(
+			RawOrigin::Signed(caller.clone()).into(),
+			0u64,
+			true
+		));
+
+		assert_ok!(Salp::<T>::fund_success(RawOrigin::Root.into(), fund_index));
+		assert_ok!(Salp::<T>::unlock(
+			RawOrigin::Signed(caller.clone()).into(),
+			caller.clone(),
+			fund_index
+		));
+
+		#[extrinsic_call]
+		_(RawOrigin::Signed(caller.clone()), fund_index, contribution, false);
+	}
+
+	#[benchmark]
+	fn cancel_reservation() {
+		let fund_index = create_fund::<T>(1);
+		let (caller, contribution) = contribute_fund::<T>(fund_index);
+		assert_ok!(Pallet::<T>::confirm_contribute(
+			RawOrigin::Signed(caller.clone()).into(),
+			0u64,
+			true
+		));
+
+		assert_ok!(Salp::<T>::fund_success(RawOrigin::Root.into(), fund_index));
+		assert_ok!(Salp::<T>::unlock(
+			RawOrigin::Signed(caller.clone()).into(),
+			caller.clone(),
+			fund_index
+		));
+		assert_ok!(Salp::<T>::reserve(
+			RawOrigin::Signed(caller.clone()).into(),
+			fund_index,
+			contribution,
+			false
+		));
+
+		#[extrinsic_call]
+		_(RawOrigin::Signed(caller.clone()), fund_index);
+	}
+
+	#[benchmark]
+	fn batch_handle_reserve() {
+		let fund_index = create_fund::<T>(1);
+		let (caller, contribution) = contribute_fund::<T>(fund_index);
+		assert_ok!(Pallet::<T>::confirm_contribute(
+			RawOrigin::Signed(caller.clone()).into(),
+			0u64,
+			true
+		));
+
+		assert_ok!(Salp::<T>::fund_success(RawOrigin::Root.into(), fund_index));
+		assert_ok!(Salp::<T>::unlock(
+			RawOrigin::Signed(caller.clone()).into(),
+			caller.clone(),
+			fund_index
+		));
+		assert_ok!(Salp::<T>::reserve(
+			RawOrigin::Signed(caller.clone()).into(),
+			fund_index,
+			contribution,
+			false
+		));
+		assert_ok!(Salp::<T>::fund_retire(RawOrigin::Root.into(), fund_index));
+		assert_ok!(Salp::<T>::withdraw(RawOrigin::Root.into(), fund_index));
+		assert_eq!(RedeemPool::<T>::get(), T::MinContribution::get());
+
+		#[extrinsic_call]
+		_(RawOrigin::Signed(caller.clone()), fund_index);
+	}
+
+	//   `cargo test -p pallet-example-basic --all-features`, you will see one line per case:
+	impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test);
+}
diff --git a/pallets/deprecated/salp/src/lib.rs b/pallets/deprecated/salp/src/lib.rs
new file mode 100644
index 000000000..b2fae3ff3
--- /dev/null
+++ b/pallets/deprecated/salp/src/lib.rs
@@ -0,0 +1,1756 @@
+// 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 <https://www.gnu.org/licenses/>.
+
+// Ensure we're `no_std` when compiling for Wasm.
+#![cfg_attr(not(feature = "std"), no_std)]
+
+#[cfg(feature = "runtime-benchmarks")]
+pub mod benchmarking;
+#[cfg(test)]
+pub mod mock;
+#[cfg(test)]
+mod tests;
+pub mod weights;
+pub use weights::WeightInfo;
+
+// Re-export pallet items so that they can be accessed from the crate namespace.
+use bifrost_primitives::{
+	ContributionStatus, CurrencyIdConversion, CurrencyIdRegister, TrieIndex, TryConvertFrom,
+	VtokenMintingInterface,
+};
+use bifrost_stable_pool::{traits::StablePoolHandler, StableAssetPoolId};
+use bifrost_xcm_interface::ChainId;
+use cumulus_primitives_core::{QueryId, Response};
+use frame_support::{pallet_prelude::*, sp_runtime::SaturatedConversion, traits::LockIdentifier};
+use orml_traits::MultiCurrency;
+pub use pallet::*;
+use pallet_xcm::ensure_response;
+use scale_info::TypeInfo;
+use sp_runtime::traits::One;
+use zenlink_protocol::{AssetId, ExportZenlink};
+
+pub type AccountIdOf<T> = <T as frame_system::Config>::AccountId;
+
+type BalanceOf<T> = <<T as Config>::MultiCurrency as MultiCurrency<AccountIdOf<T>>>::Balance;
+
+#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
+pub enum FundStatus {
+	Ongoing,
+	Retired,
+	Success,
+	Failed,
+	RefundWithdrew,
+	RedeemWithdrew,
+	FailedToContinue,
+	End,
+}
+
+impl Default for FundStatus {
+	fn default() -> Self {
+		FundStatus::Ongoing
+	}
+}
+
+/// Information on a funding effort for a pre-existing parachain. We assume that the parachain
+/// ID is known as it's used for the key of the storage item for which this is the value
+/// (`Funds`).
+#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
+#[codec(dumb_trait_bound)]
+pub struct FundInfo<Balance, LeasePeriod> {
+	/// The total amount raised.
+	pub raised: Balance,
+	/// A hard-cap on the amount that may be contributed.
+	pub cap: Balance,
+	/// First slot in range to bid on; it's actually a LeasePeriod, but that's the same type as
+	/// BlockNumber.
+	pub first_slot: LeasePeriod,
+	/// Last slot in range to bid on; it's actually a LeasePeriod, but that's the same type as
+	/// BlockNumber.
+	pub last_slot: LeasePeriod,
+	/// Index used for the child trie of this fund
+	pub trie_index: TrieIndex,
+	/// Fund status
+	pub status: FundStatus,
+}
+
+#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, Default)]
+pub struct ReserveInfo<Balance> {
+	value: Balance,
+	if_mint: bool,
+}
+
+#[frame_support::pallet]
+pub mod pallet {
+	// Import various types used to declare pallet in scope.
+	use bifrost_primitives::{
+		BancorHandler, CurrencyId, CurrencyId::VSBond, LeasePeriod, MessageId, Nonce, ParaId,
+	};
+	use bifrost_xcm_interface::traits::XcmHelper;
+	use frame_support::{
+		pallet_prelude::{storage::child, *},
+		sp_runtime::traits::{AccountIdConversion, CheckedAdd, Hash, Saturating, Zero},
+		storage::ChildTriePrefixIterator,
+		PalletId,
+	};
+	use frame_system::pallet_prelude::*;
+	use orml_traits::{
+		currency::TransferAll, MultiCurrency, MultiLockableCurrency, MultiReservableCurrency,
+	};
+	use sp_arithmetic::Percent;
+	use sp_std::{convert::TryInto, prelude::*};
+	use xcm::v3::MaybeErrorCode;
+
+	use super::*;
+
+	#[pallet::config]
+	pub trait Config: frame_system::Config {
+		type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
+		type RuntimeOrigin: IsType<<Self as frame_system::Config>::RuntimeOrigin>
+			+ Into<Result<pallet_xcm::Origin, <Self as Config>::RuntimeOrigin>>;
+
+		type RuntimeCall: Parameter + From<Call<Self>>;
+
+		/// ModuleID for the crowdloan module. An appropriate value could be
+		/// ```ModuleId(*b"py/cfund")```
+		#[pallet::constant]
+		type PalletId: Get<PalletId>;
+
+		/// The minimum amount that may be contributed into a crowdloan. Should almost certainly be
+		/// at least ExistentialDeposit.
+		#[pallet::constant]
+		type MinContribution: Get<BalanceOf<Self>>;
+
+		#[pallet::constant]
+		type RelayChainToken: Get<CurrencyId>;
+
+		/// The number of blocks over which a single period lasts.
+		#[pallet::constant]
+		type LeasePeriod: Get<BlockNumberFor<Self>>;
+
+		#[pallet::constant]
+		type VSBondValidPeriod: Get<BlockNumberFor<Self>>;
+
+		/// The time interval from 1:1 redeem-pool to bancor-pool to release.
+		#[pallet::constant]
+		type ReleaseCycle: Get<BlockNumberFor<Self>>;
+
+		/// The release ratio from the 1:1 redeem-pool to the bancor-pool per cycle.
+		///
+		/// **NOTE: THE RELEASE RATIO MUST BE IN [0, 1].**
+		#[pallet::constant]
+		type ReleaseRatio: Get<Percent>;
+
+		#[pallet::constant]
+		type RemoveKeysLimit: Get<u32>;
+
+		#[pallet::constant]
+		type SlotLength: Get<LeasePeriod>;
+
+		type MultiCurrency: TransferAll<AccountIdOf<Self>>
+			+ MultiCurrency<AccountIdOf<Self>, CurrencyId = CurrencyId>
+			+ MultiReservableCurrency<AccountIdOf<Self>, CurrencyId = CurrencyId>
+			+ MultiLockableCurrency<AccountIdOf<Self>>;
+
+		type BancorPool: BancorHandler<BalanceOf<Self>>;
+
+		type EnsureConfirmAsGovernance: EnsureOrigin<<Self as frame_system::Config>::RuntimeOrigin>;
+
+		type WeightInfo: WeightInfo;
+
+		/// The XcmInterface to manage the staking of sub-account on relaychain.
+		type XcmInterface: XcmHelper<AccountIdOf<Self>, BalanceOf<Self>>;
+
+		#[pallet::constant]
+		type TreasuryAccount: Get<Self::AccountId>;
+
+		#[pallet::constant]
+		type BuybackPalletId: Get<PalletId>;
+
+		type DexOperator: ExportZenlink<Self::AccountId, AssetId>;
+
+		type CurrencyIdConversion: CurrencyIdConversion<CurrencyId>;
+
+		type CurrencyIdRegister: CurrencyIdRegister<CurrencyId>;
+
+		type ParachainId: Get<cumulus_primitives_core::ParaId>;
+
+		type StablePool: StablePoolHandler<Balance = BalanceOf<Self>, AccountId = Self::AccountId>;
+
+		type VtokenMinting: VtokenMintingInterface<Self::AccountId, CurrencyId, BalanceOf<Self>>;
+
+		#[pallet::constant]
+		type LockId: Get<LockIdentifier>;
+
+		#[pallet::constant]
+		type BatchLimit: Get<u32>;
+	}
+
+	#[pallet::pallet]
+	#[pallet::without_storage_info]
+	pub struct Pallet<T>(_);
+
+	#[pallet::event]
+	#[pallet::generate_deposit(pub(super) fn deposit_event)]
+	pub enum Event<T: Config> {
+		/// Create a new crowdloaning campaign. [fund_index]
+		Created(ParaId),
+		/// Contributing to a crowd sale. [who, fund_index, amount]
+		Contributing(AccountIdOf<T>, ParaId, BalanceOf<T>, MessageId),
+		/// Contributed to a crowd sale. [who, fund_index, amount]
+		Contributed(AccountIdOf<T>, ParaId, BalanceOf<T>),
+		/// Fail on contribute to crowd sale. [who, fund_index, amount]
+		ContributeFailed(AccountIdOf<T>, ParaId, BalanceOf<T>),
+		/// Withdrew full balance of a contributor. [who, fund_index, amount]
+		Withdrew(ParaId, BalanceOf<T>),
+		/// refund to account. [who, fund_index,value]
+		Refunded(AccountIdOf<T>, ParaId, LeasePeriod, LeasePeriod, BalanceOf<T>),
+		/// all refund
+		AllRefunded(ParaId),
+		/// redeem to account. [who, fund_index, first_slot, last_slot, value]
+		Redeemed(AccountIdOf<T>, ParaId, LeasePeriod, LeasePeriod, BalanceOf<T>),
+		/// Fund is edited. [fund_index]
+		Edited(ParaId),
+		/// Fund is dissolved. [fund_index]
+		Dissolved(ParaId),
+		/// The vsToken/vsBond was be unlocked. [who, fund_index, value]
+		Unlocked(AccountIdOf<T>, ParaId, BalanceOf<T>),
+		AllUnlocked(ParaId),
+		/// Fund status change
+		Failed(ParaId),
+		Success(ParaId),
+		Retired(ParaId),
+		End(ParaId),
+		Continued(ParaId, LeasePeriod, LeasePeriod),
+		RefundedDissolved(ParaId, LeasePeriod, LeasePeriod),
+		Buyback(BalanceOf<T>),
+		VstokenUnlocked(AccountIdOf<T>),
+		BuybackByStablePool {
+			pool_id: StableAssetPoolId,
+			currency_id_in: CurrencyId,
+			value: BalanceOf<T>,
+		},
+		Reserved {
+			who: AccountIdOf<T>,
+			para_id: ParaId,
+			value: BalanceOf<T>,
+			if_mint: bool,
+		},
+		ReservationCancelled {
+			who: AccountIdOf<T>,
+			para_id: ParaId,
+		},
+		ReservationFullyHandled {
+			para_id: ParaId,
+		},
+		ReservationHandled {
+			para_id: ParaId,
+		},
+	}
+
+	#[pallet::error]
+	pub enum Error<T> {
+		/// The first slot needs to at least be less than 3 `max_value`.
+		FirstSlotTooFarInFuture,
+		/// Last slot must be greater than first slot.
+		LastSlotBeforeFirstSlot,
+		/// The last slot cannot be more then 3 slots after the first slot.
+		LastSlotTooFarInFuture,
+		/// There was an overflow.
+		Overflow,
+		/// The contribution was below the minimum, `MinContribution`.
+		ContributionTooSmall,
+		/// The account doesn't have any contribution to the fund.
+		ZeroContribution,
+		/// Invalid fund index.
+		InvalidParaId,
+		/// Invalid fund status.
+		InvalidFundStatus,
+		/// Invalid contribution status.
+		InvalidContributionStatus,
+		/// Contributions exceed maximum amount.
+		CapExceeded,
+		/// The fund has been registered.
+		FundAlreadyCreated,
+		/// Crosschain xcm failed
+		XcmFailed,
+		/// Don't have enough vsToken/vsBond to refund
+		NotEnoughReservedAssetsToRefund,
+		/// Don't have enough token to refund by users
+		NotEnoughBalanceInRefundPool,
+		/// Don't have enough vsToken/vsBond to unlock
+		NotEnoughBalanceToUnlock,
+		/// The vsBond is expired now
+		VSBondExpired,
+		/// The vsBond cannot be redeemed by now
+		UnRedeemableNow,
+		/// Dont have enough vsToken/vsBond to redeem
+		NotEnoughFreeAssetsToRedeem,
+		/// Don't have enough token to redeem by users
+		NotEnoughBalanceInRedeemPool,
+		NotEnoughBalanceInFund,
+		InvalidFundSameSlot,
+		InvalidFundNotExist,
+		InvalidRefund,
+		NotEnoughBalanceToContribute,
+		NotSupportTokenType,
+		/// Responder is not a relay chain
+		ResponderNotRelayChain,
+		/// No contribution record found
+		NotFindContributionValue,
+		ArgumentsError,
+	}
+
+	/// Multisig confirm account
+	#[pallet::storage]
+	pub type MultisigConfirmAccount<T: Config> = StorageValue<_, AccountIdOf<T>, OptionQuery>;
+
+	/// Tracker for the next available fund index
+	#[pallet::storage]
+	pub(super) type CurrentTrieIndex<T: Config> = StorageValue<_, TrieIndex, ValueQuery>;
+
+	/// Tracker for the next nonce index
+	#[pallet::storage]
+	pub(super) type CurrentNonce<T: Config> =
+		StorageMap<_, Blake2_128Concat, ParaId, Nonce, ValueQuery>;
+
+	/// Record contribution
+	#[pallet::storage]
+	pub type QueryIdContributionInfo<T: Config> =
+		StorageMap<_, Blake2_128Concat, QueryId, (ParaId, AccountIdOf<T>, BalanceOf<T>)>;
+
+	/// Info on all of the funds.
+	#[pallet::storage]
+	pub(super) type Funds<T: Config> = StorageMap<
+		_,
+		Blake2_128Concat,
+		ParaId,
+		Option<FundInfo<BalanceOf<T>, LeasePeriod>>,
+		ValueQuery,
+	>;
+
+	/// The balance can be redeemed to users.
+	#[pallet::storage]
+	pub type RedeemPool<T: Config> = StorageValue<_, BalanceOf<T>, ValueQuery>;
+
+	#[pallet::storage]
+	pub(super) type FailedFundsToRefund<T: Config> = StorageNMap<
+		_,
+		(
+			NMapKey<Blake2_128Concat, ParaId>,
+			NMapKey<Blake2_128Concat, LeasePeriod>,
+			NMapKey<Blake2_128Concat, LeasePeriod>,
+		),
+		Option<FundInfo<BalanceOf<T>, LeasePeriod>>,
+		ValueQuery,
+	>;
+
+	#[pallet::storage]
+	pub type ReserveInfos<T: Config> = StorageDoubleMap<
+		_,
+		Twox64Concat,
+		ParaId,
+		Twox64Concat,
+		T::AccountId,
+		ReserveInfo<BalanceOf<T>>,
+		ValueQuery,
+	>;
+
+	#[pallet::genesis_config]
+	#[derive(frame_support::DefaultNoBound)]
+	pub struct GenesisConfig<T: Config> {
+		pub initial_multisig_account: Option<AccountIdOf<T>>,
+	}
+
+	#[pallet::genesis_build]
+	impl<T: Config> BuildGenesisConfig for GenesisConfig<T> {
+		fn build(&self) {
+			if let Some(ref key) = self.initial_multisig_account {
+				MultisigConfirmAccount::<T>::put(key)
+			}
+		}
+	}
+
+	#[pallet::call]
+	impl<T: Config> Pallet<T> {
+		#[pallet::call_index(0)]
+		#[pallet::weight(T::WeightInfo::set_multisig_confirm_account())]
+		pub fn set_multisig_confirm_account(
+			origin: OriginFor<T>,
+			account: AccountIdOf<T>,
+		) -> DispatchResult {
+			T::EnsureConfirmAsGovernance::ensure_origin(origin)?;
+
+			Self::set_multisig_account(account);
+
+			Ok(())
+		}
+
+		#[pallet::call_index(1)]
+		#[pallet::weight(T::WeightInfo::fund_success())]
+		pub fn fund_success(
+			origin: OriginFor<T>,
+			#[pallet::compact] index: ParaId,
+		) -> DispatchResult {
+			T::EnsureConfirmAsGovernance::ensure_origin(origin)?;
+
+			let fund = Funds::<T>::get(index).ok_or(Error::<T>::InvalidParaId)?;
+			ensure!(fund.status == FundStatus::Ongoing, Error::<T>::InvalidFundStatus);
+
+			let fund_new = FundInfo { status: FundStatus::Success, ..fund };
+			Funds::<T>::insert(index, Some(fund_new));
+			Self::deposit_event(Event::<T>::Success(index));
+
+			Ok(())
+		}
+
+		#[pallet::call_index(2)]
+		#[pallet::weight(T::WeightInfo::fund_fail())]
+		pub fn fund_fail(origin: OriginFor<T>, #[pallet::compact] index: ParaId) -> DispatchResult {
+			T::EnsureConfirmAsGovernance::ensure_origin(origin)?;
+
+			// crownload is failed, so enable the withdrawal function of vsToken/vsBond
+			let fund = Funds::<T>::get(index).ok_or(Error::<T>::InvalidParaId)?;
+			ensure!(fund.status == FundStatus::Ongoing, Error::<T>::InvalidFundStatus);
+
+			let fund_new = FundInfo { status: FundStatus::Failed, ..fund };
+			Funds::<T>::insert(index, Some(fund_new));
+			Self::deposit_event(Event::<T>::Failed(index));
+
+			Ok(())
+		}
+
+		#[pallet::call_index(3)]
+		#[pallet::weight(T::WeightInfo::continue_fund())]
+		pub fn continue_fund(
+			origin: OriginFor<T>,
+			#[pallet::compact] index: ParaId,
+			#[pallet::compact] first_slot: LeasePeriod,
+			#[pallet::compact] last_slot: LeasePeriod,
+		) -> DispatchResult {
+			T::EnsureConfirmAsGovernance::ensure_origin(origin)?;
+
+			// crownload is failed, so enable the withdrawal function of vsToken/vsBond
+			let fund = Funds::<T>::get(index).ok_or(Error::<T>::InvalidParaId)?;
+			ensure!(fund.status == FundStatus::RefundWithdrew, Error::<T>::InvalidFundStatus);
+			ensure!(
+				fund.first_slot != first_slot || fund.last_slot != last_slot,
+				Error::<T>::InvalidFundSameSlot
+			);
+
+			let fund_old = FundInfo { status: FundStatus::FailedToContinue, ..fund };
+			FailedFundsToRefund::<T>::insert(
+				(index, fund.first_slot, fund.last_slot),
+				Some(fund_old.clone()),
+			);
+			let fund_new = FundInfo { status: FundStatus::Ongoing, first_slot, last_slot, ..fund };
+			Funds::<T>::insert(index, Some(fund_new));
+
+			match T::RelayChainToken::get() {
+				CurrencyId::Token(token_symbol) =>
+					if !T::CurrencyIdRegister::check_vsbond_registered(
+						token_symbol,
+						index,
+						first_slot,
+						last_slot,
+					) {
+						T::CurrencyIdRegister::register_vsbond_metadata(
+							token_symbol,
+							index,
+							first_slot,
+							last_slot,
+						)?;
+					},
+				CurrencyId::Token2(token_id) => {
+					if !T::CurrencyIdRegister::check_vsbond2_registered(
+						token_id, index, first_slot, last_slot,
+					) {
+						T::CurrencyIdRegister::register_vsbond2_metadata(
+							token_id, index, first_slot, last_slot,
+						)?;
+					}
+				},
+				_ => (),
+			}
+
+			Self::deposit_event(Event::<T>::Continued(
+				index,
+				fund_old.first_slot,
+				fund_old.last_slot,
+			));
+
+			Ok(())
+		}
+
+		#[pallet::call_index(4)]
+		#[pallet::weight(T::WeightInfo::fund_retire())]
+		pub fn fund_retire(
+			origin: OriginFor<T>,
+			#[pallet::compact] index: ParaId,
+		) -> DispatchResult {
+			T::EnsureConfirmAsGovernance::ensure_origin(origin)?;
+
+			let fund = Funds::<T>::get(index).ok_or(Error::<T>::InvalidParaId)?;
+			ensure!(fund.status == FundStatus::Success, Error::<T>::InvalidFundStatus);
+
+			let fund_new = FundInfo { status: FundStatus::Retired, ..fund };
+			Funds::<T>::insert(index, Some(fund_new));
+			Self::deposit_event(Event::<T>::Retired(index));
+
+			Ok(())
+		}
+
+		#[pallet::call_index(5)]
+		#[pallet::weight(T::WeightInfo::fund_end())]
+		pub fn fund_end(origin: OriginFor<T>, #[pallet::compact] index: ParaId) -> DispatchResult {
+			T::EnsureConfirmAsGovernance::ensure_origin(origin)?;
+
+			let fund = Funds::<T>::get(index).ok_or(Error::<T>::InvalidParaId)?;
+			ensure!(
+				fund.status == FundStatus::RefundWithdrew ||
+					fund.status == FundStatus::RedeemWithdrew,
+				Error::<T>::InvalidFundStatus
+			);
+
+			let fund_new = FundInfo { status: FundStatus::End, ..fund };
+			Funds::<T>::insert(index, Some(fund_new));
+			Self::deposit_event(Event::<T>::End(index));
+
+			Ok(())
+		}
+
+		/// Create a new crowdloaning campaign for a parachain slot deposit for the current auction.
+		#[pallet::call_index(6)]
+		#[pallet::weight(T::WeightInfo::create())]
+		pub fn create(
+			origin: OriginFor<T>,
+			#[pallet::compact] index: ParaId,
+			#[pallet::compact] cap: BalanceOf<T>,
+			#[pallet::compact] first_slot: LeasePeriod,
+			#[pallet::compact] last_slot: LeasePeriod,
+		) -> DispatchResult {
+			T::EnsureConfirmAsGovernance::ensure_origin(origin)?;
+
+			ensure!(!Funds::<T>::contains_key(index), Error::<T>::FundAlreadyCreated);
+
+			ensure!(first_slot <= last_slot, Error::<T>::LastSlotBeforeFirstSlot);
+
+			let last_slot_limit = first_slot
+				.checked_add(((T::SlotLength::get() as u32) - 1).into())
+				.ok_or(Error::<T>::FirstSlotTooFarInFuture)?;
+			ensure!(last_slot <= last_slot_limit, Error::<T>::LastSlotTooFarInFuture);
+
+			Funds::<T>::insert(
+				index,
+				Some(FundInfo {
+					raised: Zero::zero(),
+					cap,
+					first_slot,
+					last_slot,
+					trie_index: Self::next_trie_index()?,
+					status: FundStatus::Ongoing,
+				}),
+			);
+
+			match T::RelayChainToken::get() {
+				CurrencyId::Token(token_symbol) =>
+					if !T::CurrencyIdRegister::check_vsbond_registered(
+						token_symbol,
+						index,
+						first_slot,
+						last_slot,
+					) {
+						T::CurrencyIdRegister::register_vsbond_metadata(
+							token_symbol,
+							index,
+							first_slot,
+							last_slot,
+						)?;
+					},
+				CurrencyId::Token2(token_id) => {
+					if !T::CurrencyIdRegister::check_vsbond2_registered(
+						token_id, index, first_slot, last_slot,
+					) {
+						T::CurrencyIdRegister::register_vsbond2_metadata(
+							token_id, index, first_slot, last_slot,
+						)?;
+					}
+				},
+				_ => (),
+			}
+
+			Self::deposit_event(Event::<T>::Created(index));
+
+			Ok(())
+		}
+
+		/// Edit the configuration for an in-progress crowdloan.
+		///
+		/// Can only be called by Root origin.
+		#[pallet::call_index(7)]
+		#[pallet::weight(T::WeightInfo::edit())]
+		pub fn edit(
+			origin: OriginFor<T>,
+			#[pallet::compact] index: ParaId,
+			#[pallet::compact] cap: BalanceOf<T>,
+			#[pallet::compact] raised: BalanceOf<T>,
+			#[pallet::compact] first_slot: LeasePeriod,
+			#[pallet::compact] last_slot: LeasePeriod,
+			fund_status: Option<FundStatus>,
+		) -> DispatchResult {
+			T::EnsureConfirmAsGovernance::ensure_origin(origin)?;
+
+			let fund = Funds::<T>::get(index).ok_or(Error::<T>::InvalidParaId)?;
+
+			let status = match fund_status {
+				None => fund.status,
+				Some(status) => status,
+			};
+			Funds::<T>::insert(
+				index,
+				Some(FundInfo {
+					cap,
+					first_slot,
+					last_slot,
+					status,
+					raised,
+					trie_index: fund.trie_index,
+				}),
+			);
+			Self::deposit_event(Event::<T>::Edited(index));
+			Ok(())
+		}
+
+		/// Contribute to a crowd sale. This will transfer some balance over to fund a parachain
+		/// slot. It will be withdrawable in two instances: the parachain becomes retired; or the
+		/// slot is unable to be purchased and the timeout expires.
+		#[pallet::call_index(8)]
+		#[pallet::weight(T::WeightInfo::contribute())]
+		pub fn contribute(
+			origin: OriginFor<T>,
+			#[pallet::compact] index: ParaId,
+			#[pallet::compact] value: BalanceOf<T>,
+		) -> DispatchResult {
+			let who = ensure_signed(origin.clone())?;
+
+			let fund = Funds::<T>::get(index).ok_or(Error::<T>::InvalidParaId)?;
+			ensure!(fund.status == FundStatus::Ongoing, Error::<T>::InvalidFundStatus);
+
+			ensure!(value >= T::MinContribution::get(), Error::<T>::ContributionTooSmall);
+
+			let raised = fund.raised.checked_add(&value).ok_or(Error::<T>::Overflow)?;
+			ensure!(raised <= fund.cap, Error::<T>::CapExceeded);
+
+			let (contributed, status) = Self::contribution(fund.trie_index, &who);
+			ensure!(
+				status == ContributionStatus::Idle ||
+					status == ContributionStatus::Refunded ||
+					status == ContributionStatus::Redeemed ||
+					status == ContributionStatus::Unlocked,
+				Error::<T>::InvalidContributionStatus
+			);
+
+			ensure!(
+				T::MultiCurrency::can_reserve(T::RelayChainToken::get(), &who, value),
+				Error::<T>::NotEnoughBalanceToContribute
+			);
+
+			T::MultiCurrency::reserve(T::RelayChainToken::get(), &who, value)?;
+
+			Self::put_contribution(
+				fund.trie_index,
+				&who,
+				contributed,
+				ContributionStatus::Contributing(value),
+			);
+
+			let message_id = T::XcmInterface::contribute(who.clone(), index, value)?;
+
+			Self::deposit_event(Event::Contributing(who, index, value, message_id));
+			Ok(())
+		}
+
+		/// Confirm contribute
+		#[pallet::call_index(9)]
+		#[pallet::weight(T::WeightInfo::confirm_contribute())]
+		pub fn confirm_contribute(
+			origin: OriginFor<T>,
+			query_id: QueryId,
+			is_success: bool,
+		) -> DispatchResult {
+			let confirmor = ensure_signed(origin.clone())?;
+			if Some(confirmor) != MultisigConfirmAccount::<T>::get() {
+				return Err(DispatchError::BadOrigin.into());
+			}
+
+			let (index, contributer, _amount) = QueryIdContributionInfo::<T>::get(query_id)
+				.ok_or(Error::<T>::NotFindContributionValue)?;
+
+			let fund = Funds::<T>::get(index).ok_or(Error::<T>::InvalidParaId)?;
+			let can_confirm = fund.status == FundStatus::Ongoing ||
+				fund.status == FundStatus::Failed ||
+				fund.status == FundStatus::Success;
+			ensure!(can_confirm, Error::<T>::InvalidFundStatus);
+
+			let (contributed, status) = Self::contribution(fund.trie_index, &contributer);
+			ensure!(status.is_contributing(), Error::<T>::InvalidContributionStatus);
+			let contributing = status.contributing();
+
+			let vs_token = T::CurrencyIdConversion::convert_to_vstoken(T::RelayChainToken::get())
+				.map_err(|_| Error::<T>::NotSupportTokenType)?;
+			let vs_bond = T::CurrencyIdConversion::convert_to_vsbond(
+				T::RelayChainToken::get(),
+				index,
+				fund.first_slot,
+				fund.last_slot,
+			)
+			.map_err(|_| Error::<T>::NotSupportTokenType)?;
+
+			if is_success {
+				// Issue reserved vsToken/vsBond to contributor
+				T::MultiCurrency::deposit(vs_token, &contributer, contributing)?;
+				T::MultiCurrency::deposit(vs_bond, &contributer, contributing)?;
+
+				// Update the raised of fund
+				let fund_new =
+					FundInfo { raised: fund.raised.saturating_add(contributing), ..fund };
+				Funds::<T>::insert(index, Some(fund_new));
+
+				T::MultiCurrency::unreserve(T::RelayChainToken::get(), &contributer, contributing);
+				T::MultiCurrency::transfer(
+					T::RelayChainToken::get(),
+					&contributer,
+					&Self::fund_account_id(index),
+					contributing,
+				)?;
+
+				// Update the contribution of contributer
+				let contributed_new = contributed.saturating_add(contributing);
+				Self::put_contribution(
+					fund.trie_index,
+					&contributer,
+					contributed_new,
+					ContributionStatus::Idle,
+				);
+				Self::deposit_event(Event::Contributed(contributer, index, contributing));
+			} else {
+				// Update the contribution of contributer
+				Self::put_contribution(
+					fund.trie_index,
+					&contributer,
+					contributed,
+					ContributionStatus::Idle,
+				);
+				T::MultiCurrency::unreserve(T::RelayChainToken::get(), &contributer, contributing);
+				Self::deposit_event(Event::ContributeFailed(contributer, index, contributing));
+			}
+
+			QueryIdContributionInfo::<T>::remove(query_id);
+
+			Ok(())
+		}
+
+		/// Unlock the reserved vsToken/vsBond after fund success
+		#[pallet::call_index(10)]
+		#[pallet::weight(T::WeightInfo::unlock())]
+		pub fn unlock(
+			origin: OriginFor<T>,
+			who: AccountIdOf<T>,
+			#[pallet::compact] index: ParaId,
+		) -> DispatchResult {
+			ensure_signed(origin)?;
+			let fund = Funds::<T>::get(index).ok_or(Error::<T>::InvalidParaId)?;
+
+			let (contributed, _) = Self::contribution(fund.trie_index, &who);
+
+			let vs_token = T::CurrencyIdConversion::convert_to_vstoken(T::RelayChainToken::get())
+				.map_err(|_| Error::<T>::NotSupportTokenType)?;
+			let vs_bond = T::CurrencyIdConversion::convert_to_vsbond(
+				T::RelayChainToken::get(),
+				index,
+				fund.first_slot,
+				fund.last_slot,
+			)
+			.map_err(|_| Error::<T>::NotSupportTokenType)?;
+
+			T::MultiCurrency::unreserve(vs_token, &who, contributed);
+			T::MultiCurrency::unreserve(vs_bond, &who, contributed);
+
+			Self::deposit_event(Event::<T>::Unlocked(who, index, contributed));
+
+			Ok(())
+		}
+
+		#[pallet::call_index(11)]
+		#[pallet::weight(T::WeightInfo::unlock())]
+		pub fn unlock_by_vsbond(
+			origin: OriginFor<T>,
+			who: AccountIdOf<T>,
+			vsbond: CurrencyId,
+		) -> DispatchResult {
+			ensure_signed(origin)?;
+
+			let index = match vsbond {
+				CurrencyId::VSBond(token_symbol, paraid, first_slot, last_slot) => {
+					if !T::CurrencyIdRegister::check_vsbond_registered(
+						token_symbol,
+						paraid,
+						first_slot,
+						last_slot,
+					) {
+						return Err(Error::<T>::NotSupportTokenType.into());
+					}
+					paraid
+				},
+				CurrencyId::VSBond2(token_id, paraid, first_slot, last_slot) => {
+					if !T::CurrencyIdRegister::check_vsbond2_registered(
+						token_id, paraid, first_slot, last_slot,
+					) {
+						return Err(Error::<T>::NotSupportTokenType.into());
+					}
+					paraid
+				},
+				_ => return Err(Error::<T>::NotSupportTokenType.into()),
+			};
+
+			let fund = Funds::<T>::get(index).ok_or(Error::<T>::InvalidParaId)?;
+
+			let (contributed, _) = Self::contribution(fund.trie_index, &who);
+
+			let vs_token = T::CurrencyIdConversion::convert_to_vstoken(T::RelayChainToken::get())
+				.map_err(|_| Error::<T>::NotSupportTokenType)?;
+			let vs_bond = T::CurrencyIdConversion::convert_to_vsbond(
+				T::RelayChainToken::get(),
+				index,
+				fund.first_slot,
+				fund.last_slot,
+			)
+			.map_err(|_| Error::<T>::NotSupportTokenType)?;
+
+			T::MultiCurrency::unreserve(vs_token, &who, contributed);
+			T::MultiCurrency::unreserve(vs_bond, &who, contributed);
+
+			Self::deposit_event(Event::<T>::Unlocked(who, index, contributed));
+			Ok(())
+		}
+
+		#[pallet::call_index(12)]
+		#[pallet::weight(T::WeightInfo::unlock())]
+		pub fn unlock_vstoken(origin: OriginFor<T>, who: AccountIdOf<T>) -> DispatchResult {
+			ensure_signed(origin)?;
+
+			match T::RelayChainToken::get() {
+				CurrencyId::Token(token_symbol) => {
+					let vsbond_list = vec![
+						VSBond(token_symbol, 2106, 19, 26),
+						VSBond(token_symbol, 2011, 19, 26),
+						VSBond(token_symbol, 2102, 18, 25),
+						VSBond(token_symbol, 2102, 19, 26),
+						VSBond(token_symbol, 2101, 18, 25),
+						VSBond(token_symbol, 2100, 18, 25),
+						VSBond(token_symbol, 2100, 17, 24),
+						VSBond(token_symbol, 2095, 17, 24),
+						VSBond(token_symbol, 2096, 17, 24),
+						VSBond(token_symbol, 2087, 17, 24),
+						VSBond(token_symbol, 2085, 15, 22),
+						VSBond(token_symbol, 2092, 15, 22),
+						VSBond(token_symbol, 2088, 15, 22),
+						VSBond(token_symbol, 2090, 15, 22),
+					];
+
+					let vs_token =
+						T::CurrencyIdConversion::convert_to_vstoken(T::RelayChainToken::get())
+							.map_err(|_| Error::<T>::NotSupportTokenType)?;
+					let reserved_vstoken = T::MultiCurrency::reserved_balance(vs_token, &who);
+					T::MultiCurrency::unreserve(vs_token, &who, reserved_vstoken);
+					vsbond_list.into_iter().for_each(|vs_bond| {
+						let reserved_vsbond = T::MultiCurrency::reserved_balance(vs_bond, &who);
+						T::MultiCurrency::unreserve(vs_bond, &who, reserved_vsbond);
+					});
+				},
+				_ => return Err(DispatchError::BadOrigin.into()),
+			}
+
+			Self::deposit_event(Event::<T>::VstokenUnlocked(who));
+			Ok(())
+		}
+
+		/// Unlock the reserved vsToken/vsBond after fund success
+		#[pallet::call_index(13)]
+		#[pallet::weight(T::WeightInfo::batch_unlock())]
+		pub fn batch_unlock(
+			origin: OriginFor<T>,
+			#[pallet::compact] index: ParaId,
+		) -> DispatchResult {
+			ensure_signed(origin)?;
+
+			let fund = Funds::<T>::get(index).ok_or(Error::<T>::InvalidParaId)?;
+
+			let mut unlock_count = 0u32;
+			let contributions = Self::contribution_iterator(fund.trie_index);
+			// Assume everyone will be refunded.
+			let mut all_unlocked = true;
+
+			for (who, (contributed, status)) in contributions {
+				if unlock_count >= T::RemoveKeysLimit::get() {
+					// Not everyone was able to be refunded this time around.
+					all_unlocked = false;
+					break;
+				}
+				if status != ContributionStatus::Unlocked {
+					let vs_token =
+						T::CurrencyIdConversion::convert_to_vstoken(T::RelayChainToken::get())
+							.map_err(|_| Error::<T>::NotSupportTokenType)?;
+					let vs_bond = T::CurrencyIdConversion::convert_to_vsbond(
+						T::RelayChainToken::get(),
+						index,
+						fund.first_slot,
+						fund.last_slot,
+					)
+					.map_err(|_| Error::<T>::NotSupportTokenType)?;
+					T::MultiCurrency::unreserve(vs_token, &who, contributed);
+					T::MultiCurrency::unreserve(vs_bond, &who, contributed);
+
+					unlock_count += 1;
+				}
+			}
+
+			if all_unlocked {
+				Self::deposit_event(Event::<T>::AllUnlocked(index));
+			}
+
+			Ok(())
+		}
+
+		/// Withdraw full balance of the parachain.
+		/// - `index`: The parachain to whose crowdloan the contribution was made.
+		#[pallet::call_index(14)]
+		#[pallet::weight(T::WeightInfo::withdraw())]
+		pub fn withdraw(origin: OriginFor<T>, #[pallet::compact] index: ParaId) -> DispatchResult {
+			T::EnsureConfirmAsGovernance::ensure_origin(origin.clone())?;
+
+			let fund = Funds::<T>::get(index).ok_or(Error::<T>::InvalidParaId)?;
+			let can = fund.status == FundStatus::Failed || fund.status == FundStatus::Retired;
+			ensure!(can, Error::<T>::InvalidFundStatus);
+
+			let amount_withdrew = fund.raised;
+			let total = RedeemPool::<T>::get()
+				.checked_add(&amount_withdrew)
+				.ok_or(Error::<T>::Overflow)?;
+			RedeemPool::<T>::set(total);
+
+			if fund.status == FundStatus::Retired {
+				let fund_new = FundInfo { status: FundStatus::RedeemWithdrew, ..fund };
+				Funds::<T>::insert(index, Some(fund_new));
+			} else if fund.status == FundStatus::Failed {
+				let fund_new = FundInfo { status: FundStatus::RefundWithdrew, ..fund };
+				Funds::<T>::insert(index, Some(fund_new));
+			}
+
+			Self::deposit_event(Event::Withdrew(index, amount_withdrew));
+
+			Ok(())
+		}
+
+		#[pallet::call_index(15)]
+		#[pallet::weight(T::WeightInfo::refund())]
+		pub fn refund(
+			origin: OriginFor<T>,
+			#[pallet::compact] index: ParaId,
+			#[pallet::compact] first_slot: LeasePeriod,
+			#[pallet::compact] last_slot: LeasePeriod,
+			#[pallet::compact] value: BalanceOf<T>,
+		) -> DispatchResult {
+			let who = ensure_signed(origin.clone())?;
+
+			let mut fund = Self::find_fund(index, first_slot, last_slot)
+				.map_err(|_| Error::<T>::InvalidFundNotExist)?;
+			ensure!(
+				fund.status == FundStatus::FailedToContinue ||
+					fund.status == FundStatus::RefundWithdrew,
+				Error::<T>::InvalidRefund
+			);
+			ensure!(
+				fund.first_slot == first_slot && fund.last_slot == last_slot,
+				Error::<T>::InvalidRefund
+			);
+			ensure!(fund.raised >= value, Error::<T>::NotEnoughBalanceInFund);
+			ensure!(RedeemPool::<T>::get() >= value, Error::<T>::NotEnoughBalanceInRefundPool);
+
+			let vs_token = T::CurrencyIdConversion::convert_to_vstoken(T::RelayChainToken::get())
+				.map_err(|_| Error::<T>::NotSupportTokenType)?;
+			let vs_bond = T::CurrencyIdConversion::convert_to_vsbond(
+				T::RelayChainToken::get(),
+				index,
+				fund.first_slot,
+				fund.last_slot,
+			)
+			.map_err(|_| Error::<T>::NotSupportTokenType)?;
+			T::MultiCurrency::ensure_can_withdraw(vs_token, &who, value)
+				.map_err(|_e| Error::<T>::NotEnoughFreeAssetsToRedeem)?;
+			T::MultiCurrency::ensure_can_withdraw(vs_bond, &who, value)
+				.map_err(|_e| Error::<T>::NotEnoughFreeAssetsToRedeem)?;
+
+			T::MultiCurrency::withdraw(vs_token, &who, value)?;
+			T::MultiCurrency::withdraw(vs_bond, &who, value)?;
+
+			RedeemPool::<T>::set(RedeemPool::<T>::get().saturating_sub(value));
+			let mut fund_new = Funds::<T>::get(index).ok_or(Error::<T>::InvalidParaId)?;
+			fund_new.raised = fund_new.raised.saturating_sub(value);
+			Funds::<T>::insert(index, Some(fund_new));
+			if fund.status == FundStatus::FailedToContinue {
+				fund.raised = fund.raised.saturating_sub(value);
+				FailedFundsToRefund::<T>::insert(
+					(index, first_slot, last_slot),
+					Some(fund.clone()),
+				);
+			}
+
+			T::MultiCurrency::transfer(
+				T::RelayChainToken::get(),
+				&Self::fund_account_id(index),
+				&who,
+				value,
+			)?;
+
+			Self::deposit_event(Event::Refunded(
+				who,
+				index,
+				fund.first_slot,
+				fund.last_slot,
+				value,
+			));
+
+			Ok(())
+		}
+
+		#[pallet::call_index(16)]
+		#[pallet::weight(T::WeightInfo::redeem())]
+		pub fn redeem(
+			origin: OriginFor<T>,
+			#[pallet::compact] index: ParaId,
+			#[pallet::compact] value: BalanceOf<T>,
+		) -> DispatchResult {
+			let who = ensure_signed(origin.clone())?;
+
+			let mut fund = Funds::<T>::get(index).ok_or(Error::<T>::InvalidParaId)?;
+			ensure!(fund.status == FundStatus::RedeemWithdrew, Error::<T>::InvalidFundStatus);
+			ensure!(fund.raised >= value, Error::<T>::NotEnoughBalanceInRedeemPool);
+
+			let vs_token = T::CurrencyIdConversion::convert_to_vstoken(T::RelayChainToken::get())
+				.map_err(|_| Error::<T>::NotSupportTokenType)?;
+			let vs_bond = T::CurrencyIdConversion::convert_to_vsbond(
+				T::RelayChainToken::get(),
+				index,
+				fund.first_slot,
+				fund.last_slot,
+			)
+			.map_err(|_| Error::<T>::NotSupportTokenType)?;
+
+			ensure!(RedeemPool::<T>::get() >= value, Error::<T>::NotEnoughBalanceInRedeemPool);
+			let cur_block = <frame_system::Pallet<T>>::block_number();
+			let expired = Self::is_expired(cur_block, fund.last_slot)?;
+			ensure!(!expired, Error::<T>::VSBondExpired);
+			T::MultiCurrency::ensure_can_withdraw(vs_token, &who, value)
+				.map_err(|_e| Error::<T>::NotEnoughFreeAssetsToRedeem)?;
+			T::MultiCurrency::ensure_can_withdraw(vs_bond, &who, value)
+				.map_err(|_e| Error::<T>::NotEnoughFreeAssetsToRedeem)?;
+
+			T::MultiCurrency::withdraw(vs_token, &who, value)?;
+			T::MultiCurrency::withdraw(vs_bond, &who, value)?;
+			RedeemPool::<T>::set(RedeemPool::<T>::get().saturating_sub(value));
+
+			fund.raised = fund.raised.saturating_sub(value);
+			Funds::<T>::insert(index, Some(fund.clone()));
+
+			T::MultiCurrency::transfer(
+				T::RelayChainToken::get(),
+				&Self::fund_account_id(index),
+				&who,
+				value,
+			)?;
+			Self::deposit_event(Event::Redeemed(
+				who,
+				index,
+				fund.first_slot,
+				fund.last_slot,
+				value,
+			));
+
+			Ok(())
+		}
+
+		/// Remove a fund after the retirement period has ended and all funds have been returned.
+		#[pallet::call_index(17)]
+		#[pallet::weight(T::WeightInfo::dissolve_refunded())]
+		pub fn dissolve_refunded(
+			origin: OriginFor<T>,
+			#[pallet::compact] index: ParaId,
+			#[pallet::compact] first_slot: LeasePeriod,
+			#[pallet::compact] last_slot: LeasePeriod,
+		) -> DispatchResult {
+			T::EnsureConfirmAsGovernance::ensure_origin(origin)?;
+
+			let fund = FailedFundsToRefund::<T>::get((index, first_slot, last_slot))
+				.ok_or(Error::<T>::InvalidRefund)?;
+
+			ensure!(fund.status == FundStatus::FailedToContinue, Error::<T>::InvalidFundStatus);
+
+			FailedFundsToRefund::<T>::remove((index, first_slot, last_slot));
+
+			Self::deposit_event(Event::<T>::RefundedDissolved(index, first_slot, last_slot));
+
+			Ok(())
+		}
+
+		/// Remove a fund after the retirement period has ended and all funds have been returned.
+		#[pallet::call_index(18)]
+		#[pallet::weight(T::WeightInfo::dissolve())]
+		pub fn dissolve(origin: OriginFor<T>, #[pallet::compact] index: ParaId) -> DispatchResult {
+			T::EnsureConfirmAsGovernance::ensure_origin(origin)?;
+
+			let mut fund = Funds::<T>::get(index).ok_or(Error::<T>::InvalidParaId)?;
+			ensure!(fund.status == FundStatus::End, Error::<T>::InvalidFundStatus);
+
+			let mut refund_count = 0u32;
+			// Try killing the crowdloan child trie and Assume everyone will be refunded.
+			let contributions = Self::contribution_iterator(fund.trie_index);
+			let mut all_refunded = true;
+			#[allow(clippy::explicit_counter_loop)]
+			for (who, (balance, _)) in contributions {
+				if refund_count >= T::RemoveKeysLimit::get() {
+					// Not everyone was able to be refunded this time around.
+					all_refunded = false;
+					break;
+				}
+				Self::kill_contribution(fund.trie_index, &who);
+				fund.raised = fund.raised.saturating_sub(balance);
+				refund_count += 1;
+			}
+
+			if all_refunded {
+				let from = &Self::fund_account_id(index);
+				let relay_currency_id = T::RelayChainToken::get();
+				let fund_account_balance = T::MultiCurrency::free_balance(relay_currency_id, from);
+				T::MultiCurrency::transfer(
+					relay_currency_id,
+					from,
+					&T::TreasuryAccount::get(),
+					Percent::from_percent(25) * fund_account_balance,
+				)?;
+				T::MultiCurrency::transfer(
+					relay_currency_id,
+					from,
+					&T::BuybackPalletId::get().into_account_truncating(),
+					Percent::from_percent(75) * fund_account_balance,
+				)?;
+				Funds::<T>::remove(index);
+				Self::deposit_event(Event::<T>::Dissolved(index));
+			}
+
+			Ok(())
+		}
+
+		#[pallet::call_index(19)]
+		#[pallet::weight(T::WeightInfo::buyback())]
+		pub fn buyback(
+			origin: OriginFor<T>,
+			#[pallet::compact] value: BalanceOf<T>,
+		) -> DispatchResult {
+			let _who = ensure_signed(origin.clone())?;
+
+			let relay_currency_id = T::RelayChainToken::get();
+			let relay_vstoken_id = T::CurrencyIdConversion::convert_to_vstoken(relay_currency_id)
+				.map_err(|_| Error::<T>::NotSupportTokenType)?;
+			let relay_asset_id: AssetId =
+				AssetId::try_convert_from(relay_currency_id, T::ParachainId::get().into())
+					.map_err(|_| DispatchError::Other("Conversion Error."))?;
+			let relay_vstoken_asset_id: AssetId =
+				AssetId::try_convert_from(relay_vstoken_id, T::ParachainId::get().into())
+					.map_err(|_| DispatchError::Other("Conversion Error."))?;
+			let path = vec![relay_asset_id, relay_vstoken_asset_id];
+
+			T::DexOperator::inner_swap_exact_assets_for_assets(
+				&T::BuybackPalletId::get().into_account_truncating(),
+				value.saturated_into(),
+				Percent::from_percent(50).saturating_reciprocal_mul(value).saturated_into(),
+				&path,
+				&T::TreasuryAccount::get(),
+			)?;
+
+			Self::deposit_event(Event::<T>::Buyback(value));
+
+			Ok(())
+		}
+
+		#[pallet::call_index(20)]
+		#[pallet::weight(T::WeightInfo::confirm_contribute())]
+		pub fn confirm_contribution(
+			origin: OriginFor<T>,
+			query_id: QueryId,
+			response: Response,
+		) -> DispatchResult {
+			let responder = ensure_response(<T as Config>::RuntimeOrigin::from(origin))?;
+			ensure!(responder == xcm::v4::Location::parent(), Error::<T>::ResponderNotRelayChain);
+
+			let (index, contributer, _amount) = QueryIdContributionInfo::<T>::get(query_id)
+				.ok_or(Error::<T>::NotFindContributionValue)?;
+
+			let fund = Funds::<T>::get(index).ok_or(Error::<T>::InvalidParaId)?;
+			let can_confirm = fund.status == FundStatus::Ongoing ||
+				fund.status == FundStatus::Failed ||
+				fund.status == FundStatus::Success;
+			ensure!(can_confirm, Error::<T>::InvalidFundStatus);
+
+			let (contributed, status) = Self::contribution(fund.trie_index, &contributer);
+			ensure!(status.is_contributing(), Error::<T>::InvalidContributionStatus);
+			let contributing = status.contributing();
+
+			let vs_token = T::CurrencyIdConversion::convert_to_vstoken(T::RelayChainToken::get())
+				.map_err(|_| Error::<T>::NotSupportTokenType)?;
+			let vs_bond = T::CurrencyIdConversion::convert_to_vsbond(
+				T::RelayChainToken::get(),
+				index,
+				fund.first_slot,
+				fund.last_slot,
+			)
+			.map_err(|_| Error::<T>::NotSupportTokenType)?;
+
+			if let Response::DispatchResult(MaybeErrorCode::Success) = response {
+				// Issue reserved vsToken/vsBond to contributor
+				T::MultiCurrency::deposit(vs_token, &contributer, contributing)?;
+				T::MultiCurrency::deposit(vs_bond, &contributer, contributing)?;
+
+				// Update the raised of fund
+				let fund_new =
+					FundInfo { raised: fund.raised.saturating_add(contributing), ..fund };
+				Funds::<T>::insert(index, Some(fund_new));
+
+				T::MultiCurrency::unreserve(T::RelayChainToken::get(), &contributer, contributing);
+				T::MultiCurrency::transfer(
+					T::RelayChainToken::get(),
+					&contributer,
+					&Self::fund_account_id(index),
+					contributing,
+				)?;
+
+				// Update the contribution of contributer
+				let contributed_new = contributed.saturating_add(contributing);
+				Self::put_contribution(
+					fund.trie_index,
+					&contributer,
+					contributed_new,
+					ContributionStatus::Idle,
+				);
+				Self::deposit_event(Event::Contributed(contributer, index, contributing));
+			} else {
+				// Update the contribution of contributer
+				Self::put_contribution(
+					fund.trie_index,
+					&contributer,
+					contributed,
+					ContributionStatus::Idle,
+				);
+				T::MultiCurrency::unreserve(T::RelayChainToken::get(), &contributer, contributing);
+				Self::deposit_event(Event::ContributeFailed(contributer, index, contributing));
+			}
+			QueryIdContributionInfo::<T>::remove(query_id);
+			Ok(())
+		}
+
+		#[pallet::call_index(21)]
+		#[pallet::weight(T::WeightInfo::buyback_vstoken_by_stable_pool())]
+		pub fn buyback_vstoken_by_stable_pool(
+			origin: OriginFor<T>,
+			pool_id: StableAssetPoolId,
+			currency_id_in: CurrencyId,
+			value: BalanceOf<T>,
+		) -> DispatchResult {
+			let _who = ensure_signed(origin)?;
+
+			let relay_currency_id = T::RelayChainToken::get();
+			let relay_vtoken_id = T::CurrencyIdConversion::convert_to_vtoken(relay_currency_id)
+				.map_err(|_| Error::<T>::NotSupportTokenType)?;
+			let relay_vstoken_id = T::CurrencyIdConversion::convert_to_vstoken(relay_currency_id)
+				.map_err(|_| Error::<T>::NotSupportTokenType)?;
+
+			match currency_id_in {
+				cid if cid == relay_currency_id => {
+					T::StablePool::swap(
+						&T::BuybackPalletId::get().into_account_truncating(),
+						pool_id,
+						T::StablePool::get_pool_token_index(pool_id, relay_currency_id)
+							.ok_or(Error::<T>::ArgumentsError)?,
+						T::StablePool::get_pool_token_index(pool_id, relay_vstoken_id)
+							.ok_or(Error::<T>::ArgumentsError)?,
+						value.saturated_into(),
+						Percent::from_percent(50).saturating_reciprocal_mul(value).saturated_into(),
+					)?;
+				},
+				cid if cid == relay_vtoken_id => {
+					let token_value = T::VtokenMinting::vtoken_to_token(
+						relay_currency_id,
+						relay_vtoken_id,
+						value,
+					)?;
+					T::StablePool::swap(
+						&T::BuybackPalletId::get().into_account_truncating(),
+						pool_id,
+						T::StablePool::get_pool_token_index(pool_id, relay_vtoken_id)
+							.ok_or(Error::<T>::ArgumentsError)?,
+						T::StablePool::get_pool_token_index(pool_id, relay_vstoken_id)
+							.ok_or(Error::<T>::ArgumentsError)?,
+						value.saturated_into(),
+						Percent::from_percent(50)
+							.saturating_reciprocal_mul(token_value)
+							.saturated_into(),
+					)?;
+				},
+				_ => return Err(Error::<T>::ArgumentsError.into()),
+			}
+
+			Self::deposit_event(Event::<T>::BuybackByStablePool { pool_id, currency_id_in, value });
+			Ok(())
+		}
+
+		#[pallet::call_index(22)]
+		#[pallet::weight(T::WeightInfo::reserve())]
+		pub fn reserve(
+			origin: OriginFor<T>,
+			index: ParaId,
+			value: BalanceOf<T>,
+			if_mint: bool,
+		) -> DispatchResult {
+			let who = ensure_signed(origin)?;
+			let fund = Funds::<T>::get(index).ok_or(Error::<T>::InvalidParaId)?;
+
+			ensure!(
+				fund.status == FundStatus::Ongoing || fund.status == FundStatus::Success,
+				Error::<T>::InvalidFundStatus
+			);
+
+			let vs_token = T::CurrencyIdConversion::convert_to_vstoken(T::RelayChainToken::get())
+				.map_err(|_| Error::<T>::NotSupportTokenType)?;
+			let vs_bond = T::CurrencyIdConversion::convert_to_vsbond(
+				T::RelayChainToken::get(),
+				index,
+				fund.first_slot,
+				fund.last_slot,
+			)
+			.map_err(|_| Error::<T>::NotSupportTokenType)?;
+
+			T::MultiCurrency::ensure_can_withdraw(vs_token, &who, value)?;
+			T::MultiCurrency::ensure_can_withdraw(vs_bond, &who, value)?;
+			let mut info = ReserveInfos::<T>::get(index, &who);
+			info.value = info.value.checked_add(&value).ok_or(Error::<T>::Overflow)?;
+			info.if_mint = if_mint;
+			T::MultiCurrency::extend_lock(T::LockId::get(), vs_token, &who, info.value)?;
+			T::MultiCurrency::extend_lock(T::LockId::get(), vs_bond, &who, info.value)?;
+
+			ReserveInfos::<T>::insert(index, &who, info);
+
+			Self::deposit_event(Event::<T>::Reserved { who, para_id: index, value, if_mint });
+			Ok(())
+		}
+
+		#[pallet::call_index(23)]
+		#[pallet::weight(T::WeightInfo::batch_handle_reserve())]
+		pub fn batch_handle_reserve(origin: OriginFor<T>, index: ParaId) -> DispatchResult {
+			let _who = ensure_signed(origin.clone())?;
+
+			let mut fund = Funds::<T>::get(index).ok_or(Error::<T>::InvalidParaId)?;
+			let vs_token = T::CurrencyIdConversion::convert_to_vstoken(T::RelayChainToken::get())
+				.map_err(|_| Error::<T>::NotSupportTokenType)?;
+			let vs_bond = T::CurrencyIdConversion::convert_to_vsbond(
+				T::RelayChainToken::get(),
+				index,
+				fund.first_slot,
+				fund.last_slot,
+			)
+			.map_err(|_| Error::<T>::NotSupportTokenType)?;
+
+			match fund.status {
+				FundStatus::RedeemWithdrew => {
+					ReserveInfos::<T>::iter_prefix(index)
+						.take(T::BatchLimit::get() as usize)
+						.try_for_each(|(contributer, info)| -> DispatchResult {
+							T::MultiCurrency::remove_lock(
+								T::LockId::get(),
+								vs_token,
+								&contributer,
+							)?;
+							T::MultiCurrency::remove_lock(T::LockId::get(), vs_bond, &contributer)?;
+							Self::redeem_for_reserve(
+								contributer.clone(),
+								index,
+								info.value,
+								&mut fund,
+								vs_token,
+								vs_bond,
+							)?;
+							ReserveInfos::<T>::remove(index, &contributer);
+							if info.if_mint {
+								T::VtokenMinting::mint(
+									contributer,
+									T::RelayChainToken::get(),
+									info.value,
+									BoundedVec::default(),
+									None,
+								)
+								.map_err(|_| Error::<T>::NotSupportTokenType)?;
+							}
+							Ok(())
+						})?;
+				},
+				FundStatus::RefundWithdrew => {
+					ReserveInfos::<T>::iter_prefix(index)
+						.take(T::BatchLimit::get() as usize)
+						.try_for_each(|(contributer, info)| -> DispatchResult {
+							T::MultiCurrency::remove_lock(
+								T::LockId::get(),
+								vs_token,
+								&contributer,
+							)?;
+							T::MultiCurrency::remove_lock(T::LockId::get(), vs_bond, &contributer)?;
+							Self::refund_for_reserve(
+								contributer.clone(),
+								index,
+								fund.first_slot,
+								fund.last_slot,
+								info.value,
+								vs_token,
+								vs_bond,
+							)?;
+							ReserveInfos::<T>::remove(index, &contributer);
+							if info.if_mint {
+								T::VtokenMinting::mint(
+									contributer,
+									T::RelayChainToken::get(),
+									info.value,
+									BoundedVec::default(),
+									None,
+								)
+								.map_err(|_| Error::<T>::NotSupportTokenType)?;
+							}
+							Ok(())
+						})?;
+				},
+				_ => return Err(Error::<T>::InvalidFundStatus.into()),
+			}
+
+			if ReserveInfos::<T>::iter_prefix(index).count() != 0 {
+				Self::deposit_event(Event::<T>::ReservationHandled { para_id: index });
+			} else {
+				Self::deposit_event(Event::<T>::ReservationFullyHandled { para_id: index });
+			}
+			Ok(())
+		}
+
+		#[pallet::call_index(24)]
+		#[pallet::weight(T::WeightInfo::cancel_reservation())]
+		pub fn cancel_reservation(origin: OriginFor<T>, index: ParaId) -> DispatchResult {
+			let who = ensure_signed(origin)?;
+
+			let fund = Funds::<T>::get(index).ok_or(Error::<T>::InvalidParaId)?;
+
+			let vs_token = T::CurrencyIdConversion::convert_to_vstoken(T::RelayChainToken::get())
+				.map_err(|_| Error::<T>::NotSupportTokenType)?;
+			let vs_bond = T::CurrencyIdConversion::convert_to_vsbond(
+				T::RelayChainToken::get(),
+				index,
+				fund.first_slot,
+				fund.last_slot,
+			)
+			.map_err(|_| Error::<T>::NotSupportTokenType)?;
+			T::MultiCurrency::remove_lock(T::LockId::get(), vs_token, &who)?;
+			T::MultiCurrency::remove_lock(T::LockId::get(), vs_bond, &who)?;
+			ReserveInfos::<T>::remove(index, &who);
+
+			Self::deposit_event(Event::<T>::ReservationCancelled { who, para_id: index });
+			Ok(())
+		}
+	}
+
+	#[pallet::hooks]
+	impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
+		fn on_initialize(n: BlockNumberFor<T>) -> Weight {
+			// Release x% KSM/DOT from redeem-pool to bancor-pool per cycle
+			if n != Zero::zero() && (n % T::ReleaseCycle::get()) == Zero::zero() {
+				if let Ok(rp_balance) = TryInto::<u128>::try_into(RedeemPool::<T>::get()) {
+					// Calculate the release amount
+					let release_amount = T::ReleaseRatio::get() * rp_balance;
+
+					// Must be ok
+					if let Ok(release_amount) = TryInto::<BalanceOf<T>>::try_into(release_amount) {
+						// Increase the balance of bancor-pool by release-amount
+						if let Ok(()) =
+							T::BancorPool::add_token(T::RelayChainToken::get(), release_amount)
+						{
+							RedeemPool::<T>::set(
+								RedeemPool::<T>::get().saturating_sub(release_amount),
+							);
+						}
+					} else {
+						log::warn!("Overflow: The balance of redeem-pool exceeds u128.");
+					}
+				}
+			}
+			T::DbWeight::get().reads(1)
+		}
+	}
+
+	impl<T: Config> Pallet<T> {
+		/// set multisig account
+		pub fn set_multisig_account(account: AccountIdOf<T>) {
+			MultisigConfirmAccount::<T>::put(account);
+		}
+		/// Check if the vsBond is `past` the redeemable date
+		pub(crate) fn is_expired(
+			block: BlockNumberFor<T>,
+			last_slot: LeasePeriod,
+		) -> Result<bool, Error<T>> {
+			let block_begin_redeem = Self::block_end_of_lease_period_index(last_slot);
+			let block_end_redeem = block_begin_redeem.saturating_add(T::VSBondValidPeriod::get());
+
+			Ok(block >= block_end_redeem)
+		}
+
+		/// Check if the vsBond is `in` the redeemable date
+		#[allow(dead_code)]
+		pub(crate) fn can_redeem(
+			block: BlockNumberFor<T>,
+			last_slot: LeasePeriod,
+		) -> Result<bool, Error<T>> {
+			let block_begin_redeem = Self::block_end_of_lease_period_index(last_slot);
+			let block_end_redeem = block_begin_redeem.saturating_add(T::VSBondValidPeriod::get());
+
+			Ok(block >= block_begin_redeem && block < block_end_redeem)
+		}
+
+		pub(crate) fn block_end_of_lease_period_index(slot: LeasePeriod) -> BlockNumberFor<T> {
+			(BlockNumberFor::<T>::from(slot) + One::one()).saturating_mul(T::LeasePeriod::get())
+		}
+
+		pub fn find_fund(
+			index: ParaId,
+			first_slot: LeasePeriod,
+			last_slot: LeasePeriod,
+		) -> Result<FundInfo<BalanceOf<T>, LeasePeriod>, Error<T>> {
+			return match FailedFundsToRefund::<T>::get((index, first_slot, last_slot)) {
+				Some(fund) => Ok(fund),
+				_ => match Funds::<T>::get(index) {
+					Some(fund) => Ok(fund),
+					_ => Err(Error::<T>::InvalidFundNotExist),
+				},
+			};
+		}
+
+		pub fn fund_account_id(index: ParaId) -> T::AccountId {
+			T::PalletId::get().into_sub_account_truncating(index)
+		}
+
+		pub(crate) fn id_from_index(index: TrieIndex) -> child::ChildInfo {
+			let mut buf = Vec::new();
+			buf.extend_from_slice(&(T::PalletId::get().0));
+			buf.extend_from_slice(&index.encode()[..]);
+			child::ChildInfo::new_default(T::Hashing::hash(&buf[..]).as_ref())
+		}
+
+		pub fn contribution(
+			index: TrieIndex,
+			who: &AccountIdOf<T>,
+		) -> (BalanceOf<T>, ContributionStatus<BalanceOf<T>>) {
+			who.using_encoded(|b| {
+				child::get_or_default::<(BalanceOf<T>, ContributionStatus<BalanceOf<T>>)>(
+					&Self::id_from_index(index),
+					b,
+				)
+			})
+		}
+
+		pub fn contribution_by_fund(
+			index: ParaId,
+			who: &AccountIdOf<T>,
+		) -> Result<(BalanceOf<T>, ContributionStatus<BalanceOf<T>>), Error<T>> {
+			let fund = Funds::<T>::get(index).ok_or(Error::<T>::InvalidParaId)?;
+			let (contributed, status) = Self::contribution(fund.trie_index, who);
+			Ok((contributed, status))
+		}
+
+		pub(crate) fn contribution_iterator(
+			index: TrieIndex,
+		) -> ChildTriePrefixIterator<(
+			AccountIdOf<T>,
+			(BalanceOf<T>, ContributionStatus<BalanceOf<T>>),
+		)> {
+			ChildTriePrefixIterator::<_>::with_prefix_over_key::<Identity>(
+				&Self::id_from_index(index),
+				&[],
+			)
+		}
+
+		pub(crate) fn next_trie_index() -> Result<TrieIndex, Error<T>> {
+			CurrentTrieIndex::<T>::try_mutate(|ti| {
+				*ti = ti.checked_add(1).ok_or(Error::<T>::Overflow)?;
+				Ok(*ti - 1)
+			})
+		}
+
+		fn put_contribution(
+			index: TrieIndex,
+			who: &AccountIdOf<T>,
+			contributed: BalanceOf<T>,
+			status: ContributionStatus<BalanceOf<T>>,
+		) {
+			who.using_encoded(|b| {
+				child::put(&Self::id_from_index(index), b, &(contributed, status))
+			});
+		}
+
+		fn kill_contribution(index: TrieIndex, who: &AccountIdOf<T>) {
+			who.using_encoded(|b| child::kill(&Self::id_from_index(index), b));
+		}
+
+		#[allow(dead_code)]
+		pub(crate) fn set_balance(who: &AccountIdOf<T>, value: BalanceOf<T>) -> DispatchResult {
+			T::MultiCurrency::deposit(T::RelayChainToken::get(), who, value)
+		}
+
+		pub fn redeem_for_reserve(
+			who: AccountIdOf<T>,
+			index: ParaId,
+			value: BalanceOf<T>,
+			fund: &mut FundInfo<BalanceOf<T>, LeasePeriod>,
+			vs_token: CurrencyId,
+			vs_bond: CurrencyId,
+		) -> DispatchResult {
+			ensure!(fund.raised >= value, Error::<T>::NotEnoughBalanceInRedeemPool);
+
+			ensure!(RedeemPool::<T>::get() >= value, Error::<T>::NotEnoughBalanceInRedeemPool);
+			let cur_block = <frame_system::Pallet<T>>::block_number();
+			let expired = Self::is_expired(cur_block, fund.last_slot)?;
+			ensure!(!expired, Error::<T>::VSBondExpired);
+			T::MultiCurrency::ensure_can_withdraw(vs_token, &who, value)
+				.map_err(|_e| Error::<T>::NotEnoughFreeAssetsToRedeem)?;
+			T::MultiCurrency::ensure_can_withdraw(vs_bond, &who, value)
+				.map_err(|_e| Error::<T>::NotEnoughFreeAssetsToRedeem)?;
+
+			T::MultiCurrency::withdraw(vs_token, &who, value)?;
+			T::MultiCurrency::withdraw(vs_bond, &who, value)?;
+			RedeemPool::<T>::set(RedeemPool::<T>::get().saturating_sub(value));
+
+			fund.raised = fund.raised.saturating_sub(value);
+			Funds::<T>::insert(index, Some(fund.clone()));
+
+			T::MultiCurrency::transfer(
+				T::RelayChainToken::get(),
+				&Self::fund_account_id(index),
+				&who,
+				value,
+			)?;
+			Self::deposit_event(Event::Redeemed(
+				who,
+				index,
+				fund.first_slot,
+				fund.last_slot,
+				value,
+			));
+
+			Ok(())
+		}
+
+		pub fn refund_for_reserve(
+			who: AccountIdOf<T>,
+			index: ParaId,
+			first_slot: LeasePeriod,
+			last_slot: LeasePeriod,
+			value: BalanceOf<T>,
+			vs_token: CurrencyId,
+			vs_bond: CurrencyId,
+		) -> DispatchResult {
+			let mut fund = Self::find_fund(index, first_slot, last_slot)
+				.map_err(|_| Error::<T>::InvalidFundNotExist)?;
+			ensure!(
+				fund.status == FundStatus::FailedToContinue ||
+					fund.status == FundStatus::RefundWithdrew,
+				Error::<T>::InvalidRefund
+			);
+			ensure!(
+				fund.first_slot == first_slot && fund.last_slot == last_slot,
+				Error::<T>::InvalidRefund
+			);
+			ensure!(fund.raised >= value, Error::<T>::NotEnoughBalanceInFund);
+			ensure!(RedeemPool::<T>::get() >= value, Error::<T>::NotEnoughBalanceInRefundPool);
+
+			T::MultiCurrency::ensure_can_withdraw(vs_token, &who, value)
+				.map_err(|_e| Error::<T>::NotEnoughFreeAssetsToRedeem)?;
+			T::MultiCurrency::ensure_can_withdraw(vs_bond, &who, value)
+				.map_err(|_e| Error::<T>::NotEnoughFreeAssetsToRedeem)?;
+
+			T::MultiCurrency::withdraw(vs_token, &who, value)?;
+			T::MultiCurrency::withdraw(vs_bond, &who, value)?;
+
+			RedeemPool::<T>::set(RedeemPool::<T>::get().saturating_sub(value));
+			let mut fund_new = Funds::<T>::get(index).ok_or(Error::<T>::InvalidParaId)?;
+			fund_new.raised = fund_new.raised.saturating_sub(value);
+			Funds::<T>::insert(index, Some(fund_new));
+			if fund.status == FundStatus::FailedToContinue {
+				fund.raised = fund.raised.saturating_sub(value);
+				FailedFundsToRefund::<T>::insert(
+					(index, first_slot, last_slot),
+					Some(fund.clone()),
+				);
+			}
+
+			T::MultiCurrency::transfer(
+				T::RelayChainToken::get(),
+				&Self::fund_account_id(index),
+				&who,
+				value,
+			)?;
+
+			Self::deposit_event(Event::Refunded(
+				who,
+				index,
+				fund.first_slot,
+				fund.last_slot,
+				value,
+			));
+
+			Ok(())
+		}
+	}
+}
+
+impl<T: Config>
+	bifrost_xcm_interface::SalpHelper<AccountIdOf<T>, <T as Config>::RuntimeCall, BalanceOf<T>>
+	for Pallet<T>
+{
+	fn confirm_contribute_call() -> <T as Config>::RuntimeCall {
+		let call = Call::<T>::confirm_contribution { query_id: 0, response: Default::default() };
+		<T as Config>::RuntimeCall::from(call)
+	}
+
+	fn bind_query_id_and_contribution(
+		query_id: QueryId,
+		index: ChainId,
+		contributer: AccountIdOf<T>,
+		amount: BalanceOf<T>,
+	) {
+		QueryIdContributionInfo::<T>::insert(query_id, (index, contributer, amount));
+	}
+}
diff --git a/pallets/deprecated/salp/src/mock.rs b/pallets/deprecated/salp/src/mock.rs
new file mode 100644
index 000000000..4d1bf1435
--- /dev/null
+++ b/pallets/deprecated/salp/src/mock.rs
@@ -0,0 +1,641 @@
+// 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 <https://www.gnu.org/licenses/>.
+
+// Ensure we're `no_std` when compiling for Wasm.
+
+#![cfg(test)]
+
+use crate::*;
+use bifrost_asset_registry::AssetIdMaps;
+use bifrost_primitives::{
+	Amount, Balance, CurrencyId, CurrencyId::*, MessageId, MockXcmExecutor, ParaId, SlpOperator,
+	SlpxOperator, TokenSymbol, TokenSymbol::*, VKSM,
+};
+use bifrost_xcm_interface::traits::XcmHelper;
+use cumulus_primitives_core::ParaId as Pid;
+use frame_support::{
+	construct_runtime, derive_impl, ord_parameter_types, parameter_types,
+	sp_runtime::{DispatchError, DispatchResult, SaturatedConversion},
+	traits::{ConstU128, ConstU64, EnsureOrigin, Everything, Get, Nothing},
+	weights::Weight,
+	PalletId,
+};
+use frame_system::{EnsureRoot, EnsureSignedBy, RawOrigin};
+use orml_traits::{location::RelativeReserveProvider, parameter_type_with_key, MultiCurrency};
+use sp_arithmetic::Percent;
+use sp_core::ConstU32;
+pub use sp_runtime::Perbill;
+use sp_runtime::{
+	traits::{Convert, IdentityLookup, UniqueSaturatedInto},
+	BuildStorage,
+};
+use sp_std::marker::PhantomData;
+use xcm::prelude::*;
+use xcm_builder::{FixedWeightBounds, FrameTransactionalProcessor};
+use xcm_executor::XcmExecutor;
+use zenlink_protocol::{
+	AssetBalance, AssetId as ZenlinkAssetId, LocalAssetHandler, PairLpGenerate, ZenlinkMultiAssets,
+};
+
+use crate as salp;
+use bifrost_primitives::MoonbeamChainId;
+
+pub(crate) type AccountId = <<Signature as sp_runtime::traits::Verify>::Signer as sp_runtime::traits::IdentifyAccount>::AccountId;
+pub(crate) type Block = frame_system::mocking::MockBlock<Test>;
+pub(crate) type BlockNumber = u32;
+pub(crate) type Signature = sp_runtime::MultiSignature;
+
+construct_runtime!(
+	pub enum Test {
+		System: frame_system,
+		Sudo: pallet_sudo,
+		Balances: pallet_balances,
+		Currencies: bifrost_currencies,
+		Tokens: orml_tokens,
+		XTokens: orml_xtokens,
+		Multisig: pallet_multisig,
+		Salp: salp,
+		ZenlinkProtocol: zenlink_protocol,
+		AssetRegistry: bifrost_asset_registry,
+		PolkadotXcm: pallet_xcm,
+		StableAsset: bifrost_stable_asset,
+		StablePool: bifrost_stable_pool,
+		VtokenMinting: bifrost_vtoken_minting,
+		XcmInterface: bifrost_xcm_interface,
+	}
+);
+
+parameter_types! {
+	pub const NativeCurrencyId: CurrencyId = CurrencyId::Native(TokenSymbol::ASG);
+	pub const RelayCurrencyId: CurrencyId = CurrencyId::Token(TokenSymbol::KSM);
+	pub const StableCurrencyId: CurrencyId = CurrencyId::Stable(TokenSymbol::KUSD);
+}
+
+parameter_types! {
+	pub const BlockHashCount: BlockNumber = 250;
+}
+
+#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)]
+impl frame_system::Config for Test {
+	type AccountData = pallet_balances::AccountData<Balance>;
+	type AccountId = AccountId;
+	type Block = Block;
+	type Lookup = IdentityLookup<Self::AccountId>;
+}
+
+parameter_types! {
+	pub const ExistentialDeposit: u128 = 1;
+	pub const TransferFee: u128 = 0;
+	pub const CreationFee: u128 = 0;
+	pub const TransactionByteFee: u128 = 0;
+	pub const MaxLocks: u32 = 999_999;
+	pub const MaxReserves: u32 = 999_999;
+}
+
+impl pallet_balances::Config for Test {
+	type AccountStore = System;
+	/// The type for recording an account's balance.
+	type Balance = Balance;
+	type DustRemoval = ();
+	/// The ubiquitous event type.
+	type RuntimeEvent = RuntimeEvent;
+	type ExistentialDeposit = ExistentialDeposit;
+	type MaxLocks = MaxLocks;
+	type MaxReserves = MaxReserves;
+	type ReserveIdentifier = [u8; 8];
+	type WeightInfo = pallet_balances::weights::SubstrateWeight<Test>;
+	type RuntimeHoldReason = RuntimeHoldReason;
+	type RuntimeFreezeReason = RuntimeFreezeReason;
+	type FreezeIdentifier = ();
+	type MaxFreezes = ConstU32<0>;
+}
+
+parameter_types! {
+	pub const DepositBase: Balance = 0;
+	pub const DepositFactor: Balance = 0;
+	pub const MaxSignatories: u16 = 100;
+}
+
+impl pallet_multisig::Config for Test {
+	type RuntimeCall = RuntimeCall;
+	type Currency = Balances;
+	type DepositBase = DepositBase;
+	type DepositFactor = DepositFactor;
+	type RuntimeEvent = RuntimeEvent;
+	type MaxSignatories = MaxSignatories;
+	type WeightInfo = pallet_multisig::weights::SubstrateWeight<Test>;
+}
+
+impl pallet_sudo::Config for Test {
+	type RuntimeCall = RuntimeCall;
+	type RuntimeEvent = RuntimeEvent;
+	type WeightInfo = ();
+}
+
+orml_traits::parameter_type_with_key! {
+	pub ExistentialDeposits: |_currency_id: CurrencyId| -> Balance {
+		0
+	};
+}
+
+impl orml_tokens::Config for Test {
+	type Amount = Amount;
+	type Balance = Balance;
+	type CurrencyId = CurrencyId;
+	type DustRemovalWhitelist = Nothing;
+	type RuntimeEvent = RuntimeEvent;
+	type ExistentialDeposits = ExistentialDeposits;
+	type MaxLocks = MaxLocks;
+	type MaxReserves = ();
+	type ReserveIdentifier = [u8; 8];
+	type WeightInfo = ();
+	type CurrencyHooks = ();
+}
+
+pub type BifrostToken =
+	bifrost_currencies::BasicCurrencyAdapter<Test, Balances, Amount, BlockNumber>;
+
+impl bifrost_currencies::Config for Test {
+	type GetNativeCurrencyId = NativeCurrencyId;
+	type MultiCurrency = Tokens;
+	type NativeCurrency = BifrostToken;
+	type WeightInfo = ();
+}
+
+parameter_types! {
+	pub const ZenlinkPalletId: PalletId = PalletId(*b"/zenlink");
+	pub const GetExchangeFee: (u32, u32) = (3, 1000);   // 0.3%
+	pub const SelfParaId: u32 = 2001;
+}
+
+impl zenlink_protocol::Config for Test {
+	type RuntimeEvent = RuntimeEvent;
+	type MultiAssetsHandler = MultiAssets;
+	type PalletId = ZenlinkPalletId;
+	type SelfParaId = SelfParaId;
+	type TargetChains = ();
+	type WeightInfo = ();
+	type AssetId = ZenlinkAssetId;
+	type LpGenerate = PairLpGenerate<Self>;
+}
+
+ord_parameter_types! {
+	pub const CouncilAccount: AccountId = AccountId::from([1u8; 32]);
+}
+impl bifrost_asset_registry::Config for Test {
+	type RuntimeEvent = RuntimeEvent;
+	type Currency = Balances;
+	type RegisterOrigin = EnsureSignedBy<CouncilAccount, AccountId>;
+	type WeightInfo = ();
+}
+
+type MultiAssets = ZenlinkMultiAssets<ZenlinkProtocol, Balances, LocalAssetAdaptor<Currencies>>;
+
+// Below is the implementation of tokens manipulation functions other than native token.
+pub struct LocalAssetAdaptor<Local>(PhantomData<Local>);
+
+impl<Local, AccountId> LocalAssetHandler<AccountId> for LocalAssetAdaptor<Local>
+where
+	Local: MultiCurrency<AccountId, CurrencyId = CurrencyId>,
+{
+	fn local_balance_of(asset_id: ZenlinkAssetId, who: &AccountId) -> AssetBalance {
+		let currency_id: CurrencyId = asset_id.try_into().unwrap();
+		Local::free_balance(currency_id, &who).saturated_into()
+	}
+
+	fn local_total_supply(asset_id: ZenlinkAssetId) -> AssetBalance {
+		let currency_id: CurrencyId = asset_id.try_into().unwrap();
+		Local::total_issuance(currency_id).saturated_into()
+	}
+
+	fn local_is_exists(asset_id: ZenlinkAssetId) -> bool {
+		let rs: Result<CurrencyId, _> = asset_id.try_into();
+		match rs {
+			Ok(_) => true,
+			Err(_) => false,
+		}
+	}
+
+	fn local_transfer(
+		asset_id: ZenlinkAssetId,
+		origin: &AccountId,
+		target: &AccountId,
+		amount: AssetBalance,
+	) -> DispatchResult {
+		let currency_id: CurrencyId = asset_id.try_into().unwrap();
+		Local::transfer(currency_id, &origin, &target, amount.unique_saturated_into())?;
+
+		Ok(())
+	}
+
+	fn local_deposit(
+		asset_id: ZenlinkAssetId,
+		origin: &AccountId,
+		amount: AssetBalance,
+	) -> Result<AssetBalance, DispatchError> {
+		let currency_id: CurrencyId = asset_id.try_into().unwrap();
+		Local::deposit(currency_id, &origin, amount.unique_saturated_into())?;
+		return Ok(amount);
+	}
+
+	fn local_withdraw(
+		asset_id: ZenlinkAssetId,
+		origin: &AccountId,
+		amount: AssetBalance,
+	) -> Result<AssetBalance, DispatchError> {
+		let currency_id: CurrencyId = asset_id.try_into().unwrap();
+		Local::withdraw(currency_id, &origin, amount.unique_saturated_into())?;
+
+		Ok(amount)
+	}
+}
+
+pub const TREASURY_ACCOUNT: AccountId = AccountId::new([9u8; 32]);
+
+parameter_types! {
+	pub const MinContribution: Balance = 10;
+	pub const BifrostCrowdloanId: PalletId = PalletId(*b"bf/salp#");
+	pub const RemoveKeysLimit: u32 = 50;
+	pub const SlotLength: BlockNumber = 8u32 as BlockNumber;
+	pub const LeasePeriod: BlockNumber = 6 * WEEKS;
+	pub const VSBondValidPeriod: BlockNumber = 30 * DAYS;
+	pub const ReleaseCycle: BlockNumber = 1 * DAYS;
+	pub const ReleaseRatio: Percent = Percent::from_percent(50);
+	pub ConfirmMuitiSigAccount: AccountId = Multisig::multi_account_id(&vec![
+		ALICE,
+		BRUCE,
+		CATHI
+	],2);
+	pub const TreasuryAccount: AccountId = TREASURY_ACCOUNT;
+	pub const BuybackPalletId: PalletId = PalletId(*b"bf/salpc");
+	pub const BatchLimit: u32 = 50;
+}
+
+pub struct EnsureConfirmAsGovernance;
+impl EnsureOrigin<RuntimeOrigin> for EnsureConfirmAsGovernance {
+	type Success = AccountId;
+
+	fn try_origin(o: RuntimeOrigin) -> Result<Self::Success, RuntimeOrigin> {
+		Into::<Result<RawOrigin<AccountId>, RuntimeOrigin>>::into(o).and_then(|o| match o {
+			RawOrigin::Signed(who) => Ok(who),
+			RawOrigin::Root => Ok(ConfirmMuitiSigAccount::get()),
+			r => Err(RuntimeOrigin::from(r)),
+		})
+	}
+
+	#[cfg(feature = "runtime-benchmarks")]
+	fn try_successful_origin() -> Result<RuntimeOrigin, ()> {
+		Ok(RuntimeOrigin::from(RawOrigin::Signed(ConfirmMuitiSigAccount::get())))
+	}
+}
+
+// To control the result returned by `MockXcmExecutor`
+pub(crate) static mut MOCK_XCM_RESULT: (bool, bool) = (true, true);
+
+// Mock XcmExecutor
+pub struct MockSalpXcmExecutor;
+
+impl XcmHelper<crate::AccountIdOf<Test>, crate::BalanceOf<Test>> for MockSalpXcmExecutor {
+	fn contribute(
+		_contributer: AccountId,
+		_index: ParaId,
+		_value: Balance,
+	) -> Result<MessageId, DispatchError> {
+		let result = unsafe { MOCK_XCM_RESULT.0 };
+
+		match result {
+			true => Ok([0; 32]),
+			false => Err(DispatchError::BadOrigin),
+		}
+	}
+}
+
+pub struct EnsurePoolAssetId;
+impl bifrost_stable_asset::traits::ValidateAssetId<CurrencyId> for EnsurePoolAssetId {
+	fn validate(_: CurrencyId) -> bool {
+		true
+	}
+}
+parameter_types! {
+	pub const StableAssetPalletId: PalletId = PalletId(*b"nuts/sta");
+}
+
+impl bifrost_stable_asset::Config for Test {
+	type RuntimeEvent = RuntimeEvent;
+	type AssetId = CurrencyId;
+	type Balance = Balance;
+	type Assets = Tokens;
+	type PalletId = StableAssetPalletId;
+	type AtLeast64BitUnsigned = u128;
+	type FeePrecision = ConstU128<10_000_000_000>;
+	type APrecision = ConstU128<100>;
+	type PoolAssetLimit = ConstU32<5>;
+	type SwapExactOverAmount = ConstU128<100>;
+	type WeightInfo = ();
+	type ListingOrigin = EnsureSignedBy<CouncilAccount, AccountId>;
+	type EnsurePoolAssetId = EnsurePoolAssetId;
+}
+
+impl bifrost_stable_pool::Config for Test {
+	type WeightInfo = ();
+	type ControlOrigin = EnsureConfirmAsGovernance;
+	type CurrencyId = CurrencyId;
+	type MultiCurrency = Tokens;
+	type StableAsset = StableAsset;
+	type VtokenMinting = VtokenMinting;
+	type CurrencyIdConversion = AssetIdMaps<Test>;
+	type CurrencyIdRegister = AssetIdMaps<Test>;
+}
+
+parameter_types! {
+	pub const MaximumUnlockIdOfUser: u32 = 1_000;
+	pub const MaximumUnlockIdOfTimeUnit: u32 = 1_000;
+	pub BifrostEntranceAccount: PalletId = PalletId(*b"bf/vtkin");
+	pub BifrostExitAccount: PalletId = PalletId(*b"bf/vtout");
+	pub IncentivePoolAccount: PalletId = PalletId(*b"bf/inpoo");
+}
+
+pub struct SlpxInterface;
+impl SlpxOperator<Balance> for SlpxInterface {
+	fn get_moonbeam_transfer_to_fee() -> Balance {
+		Default::default()
+	}
+}
+
+parameter_type_with_key! {
+	pub ParachainMinFee: |_location: Location| -> Option<u128> {
+		Some(u128::MAX)
+	};
+}
+
+parameter_types! {
+	pub SelfRelativeLocation: Location = Location::here();
+	pub const MaxAssetsForTransfer: usize = 2;
+}
+
+impl orml_xtokens::Config for Test {
+	type RuntimeEvent = RuntimeEvent;
+	type Balance = Balance;
+	type CurrencyId = CurrencyId;
+	type CurrencyIdConvert = ();
+	type AccountIdToLocation = ();
+	type UniversalLocation = UniversalLocation;
+	type SelfLocation = SelfRelativeLocation;
+	type XcmExecutor = XcmExecutor<XcmConfig>;
+	type Weigher = FixedWeightBounds<UnitWeightCost, RuntimeCall, MaxInstructions>;
+	type BaseXcmWeight = ();
+	type MaxAssetsForTransfer = MaxAssetsForTransfer;
+	type MinXcmFee = ParachainMinFee;
+	type LocationsFilter = Everything;
+	type ReserveProvider = RelativeReserveProvider;
+	type RateLimiter = ();
+	type RateLimiterId = ();
+}
+
+pub struct Slp;
+// Functions to be called by other pallets.
+impl SlpOperator<CurrencyId> for Slp {
+	fn all_delegation_requests_occupied(_currency_id: CurrencyId) -> bool {
+		true
+	}
+}
+
+impl bifrost_vtoken_minting::Config for Test {
+	type RuntimeEvent = RuntimeEvent;
+	type MultiCurrency = Tokens;
+	type ControlOrigin = EnsureConfirmAsGovernance;
+	type MaximumUnlockIdOfUser = MaximumUnlockIdOfUser;
+	type MaximumUnlockIdOfTimeUnit = MaximumUnlockIdOfTimeUnit;
+	type EntranceAccount = BifrostEntranceAccount;
+	type ExitAccount = BifrostExitAccount;
+	type FeeAccount = CouncilAccount;
+	type RedeemFeeAccount = CouncilAccount;
+	type BifrostSlp = Slp;
+	type RelayChainToken = RelayCurrencyId;
+	type CurrencyIdConversion = AssetIdMaps<Test>;
+	type CurrencyIdRegister = AssetIdMaps<Test>;
+	type WeightInfo = ();
+	type OnRedeemSuccess = ();
+	type XcmTransfer = XTokens;
+	type MoonbeamChainId = MoonbeamChainId;
+	type BifrostSlpx = SlpxInterface;
+	type ChannelCommission = ();
+	type MaxLockRecords = ConstU32<100>;
+	type IncentivePoolAccount = IncentivePoolAccount;
+	type BbBNC = ();
+	type AssetIdMaps = AssetIdMaps<Test>;
+}
+
+parameter_types! {
+	pub const SalpLockId: LockIdentifier = *b"salplock";
+}
+
+impl salp::Config for Test {
+	type BancorPool = ();
+	type RuntimeEvent = RuntimeEvent;
+	type RuntimeCall = RuntimeCall;
+	type RuntimeOrigin = RuntimeOrigin;
+	type LeasePeriod = LeasePeriod;
+	type MinContribution = MinContribution;
+	type MultiCurrency = Tokens;
+	type PalletId = BifrostCrowdloanId;
+	type RelayChainToken = RelayCurrencyId;
+	type ReleaseCycle = ReleaseCycle;
+	type ReleaseRatio = ReleaseRatio;
+	type RemoveKeysLimit = RemoveKeysLimit;
+	type SlotLength = SlotLength;
+	type VSBondValidPeriod = VSBondValidPeriod;
+	type EnsureConfirmAsGovernance = EnsureConfirmAsGovernance;
+	type WeightInfo = ();
+	type XcmInterface = MockSalpXcmExecutor;
+	type TreasuryAccount = TreasuryAccount;
+	type BuybackPalletId = BuybackPalletId;
+	type DexOperator = ZenlinkProtocol;
+	type CurrencyIdConversion = AssetIdMaps<Test>;
+	type CurrencyIdRegister = AssetIdMaps<Test>;
+	type ParachainId = ParaInfo;
+	type StablePool = StablePool;
+	type VtokenMinting = VtokenMinting;
+	type LockId = SalpLockId;
+	type BatchLimit = BatchLimit;
+}
+
+parameter_types! {
+	// One XCM operation is 200_000_000 XcmWeight, cross-chain transfer ~= 2x of transfer = 3_000_000_000
+	pub UnitWeightCost: Weight = Weight::from_parts(200_000_000, 0);
+	pub const MaxInstructions: u32 = 100;
+	pub UniversalLocation: InteriorLocation = Parachain(2001).into();
+	pub const RelayNetwork: NetworkId = NetworkId::Kusama;
+}
+
+pub struct XcmConfig;
+impl xcm_executor::Config for XcmConfig {
+	type AssetClaims = PolkadotXcm;
+	type AssetTransactor = ();
+	type AssetTrap = PolkadotXcm;
+	type Barrier = ();
+	type RuntimeCall = RuntimeCall;
+	type IsReserve = ();
+	type IsTeleporter = ();
+	type UniversalLocation = UniversalLocation;
+	type OriginConverter = ();
+	type ResponseHandler = PolkadotXcm;
+	type SubscriptionService = PolkadotXcm;
+	type Trader = ();
+	type Weigher = FixedWeightBounds<UnitWeightCost, RuntimeCall, MaxInstructions>;
+	type XcmSender = ();
+	type PalletInstancesInfo = AllPalletsWithSystem;
+	type MaxAssetsIntoHolding = ConstU32<64>;
+	type FeeManager = ();
+	type MessageExporter = ();
+	type UniversalAliases = Nothing;
+	type CallDispatcher = RuntimeCall;
+	type SafeCallFilter = Everything;
+	type AssetLocker = ();
+	type AssetExchanger = ();
+	type Aliasers = Nothing;
+	type TransactionalProcessor = FrameTransactionalProcessor;
+	type HrmpNewChannelOpenRequestHandler = ();
+	type HrmpChannelAcceptedHandler = ();
+	type HrmpChannelClosingHandler = ();
+	type XcmRecorder = ();
+}
+
+#[cfg(feature = "runtime-benchmarks")]
+parameter_types! {
+	pub ReachableDest: Option<Location> = Some(Parent.into());
+}
+
+impl pallet_xcm::Config for Test {
+	type RuntimeEvent = RuntimeEvent;
+	type ExecuteXcmOrigin = xcm_builder::EnsureXcmOrigin<RuntimeOrigin, ()>;
+	type UniversalLocation = UniversalLocation;
+	type SendXcmOrigin = xcm_builder::EnsureXcmOrigin<RuntimeOrigin, ()>;
+	type Weigher = FixedWeightBounds<UnitWeightCost, RuntimeCall, MaxInstructions>;
+	type XcmExecuteFilter = Nothing;
+	type XcmExecutor = XcmExecutor<XcmConfig>;
+	type XcmReserveTransferFilter = Everything;
+	type XcmRouter = ();
+	type XcmTeleportFilter = Nothing;
+	type RuntimeOrigin = RuntimeOrigin;
+	type RuntimeCall = RuntimeCall;
+	const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100;
+	type AdvertisedXcmVersion = ConstU32<2>;
+	type Currency = Balances;
+	type CurrencyMatcher = ();
+	type TrustedLockers = ();
+	type SovereignAccountOf = ();
+	type MaxLockers = ConstU32<8>;
+	type WeightInfo = pallet_xcm::TestWeightInfo;
+	type AdminOrigin = EnsureRoot<AccountId>;
+	type MaxRemoteLockConsumers = ConstU32<0>;
+	type RemoteLockConsumerIdentifier = ();
+}
+
+pub struct BifrostAccountIdToMultiLocation;
+impl Convert<AccountId, Location> for BifrostAccountIdToMultiLocation {
+	fn convert(account: AccountId) -> Location {
+		(AccountId32 { network: None, id: account.into() }).into()
+	}
+}
+
+impl bifrost_xcm_interface::Config for Test {
+	type RuntimeEvent = RuntimeEvent;
+	type UpdateOrigin = EnsureRoot<AccountId>;
+	type MultiCurrency = Currencies;
+	type RelayNetwork = RelayNetwork;
+	type RelaychainCurrencyId = RelayCurrencyId;
+	type ParachainSovereignAccount = TreasuryAccount;
+	type XcmExecutor = MockXcmExecutor;
+	type AccountIdToLocation = BifrostAccountIdToMultiLocation;
+	type SalpHelper = Salp;
+	type ParachainId = ParaInfo;
+	type CallBackTimeOut = ConstU64<10>;
+	type CurrencyIdConvert = AssetIdMaps<Test>;
+}
+
+pub struct ParaInfo;
+impl Get<Pid> for ParaInfo {
+	fn get() -> Pid {
+		Pid::from(2001)
+	}
+}
+
+pub(crate) fn new_test_ext() -> sp_io::TestExternalities {
+	let mut t = frame_system::GenesisConfig::<Test>::default().build_storage().unwrap();
+	pub const DOLLARS: Balance = 1_000_000_000_000;
+
+	let currency = vec![
+		(Native(BNC), DOLLARS / 100, None),
+		(Stable(KUSD), DOLLARS / 10_000, None),
+		(Token(KSM), DOLLARS / 10_000, None),
+		(Token(ZLK), DOLLARS / 1000_000, None),
+		(Token(KAR), DOLLARS / 10_000, None),
+		(Token(RMRK), DOLLARS / 1000_000, None),
+		(Token(PHA), 4 * DOLLARS / 100, None),
+		(Token(MOVR), DOLLARS / 1000_000, None),
+		(Token(DOT), DOLLARS / 1000_000, None),
+	];
+	let vcurrency = vec![Native(BNC), Token(KSM), Token(MOVR)];
+	let vsbond = vec![];
+	bifrost_asset_registry::GenesisConfig::<Test> {
+		currency,
+		vcurrency,
+		vsbond,
+		phantom: Default::default(),
+	}
+	.assimilate_storage(&mut t)
+	.unwrap();
+
+	pallet_sudo::GenesisConfig::<Test> { key: Some(ALICE) }
+		.assimilate_storage(&mut t)
+		.unwrap();
+
+	orml_tokens::GenesisConfig::<Test> {
+		balances: vec![
+			(ALICE, NativeCurrencyId::get(), INIT_BALANCE),
+			(ALICE, RelayCurrencyId::get(), INIT_BALANCE),
+			(ALICE, CurrencyId::VSToken(TokenSymbol::KSM), INIT_BALANCE),
+			(ALICE, VKSM, INIT_BALANCE),
+			(BRUCE, NativeCurrencyId::get(), INIT_BALANCE),
+			(BRUCE, RelayCurrencyId::get(), INIT_BALANCE),
+			(CATHI, NativeCurrencyId::get(), INIT_BALANCE),
+			(CATHI, RelayCurrencyId::get(), INIT_BALANCE),
+		],
+	}
+	.assimilate_storage(&mut t)
+	.unwrap();
+
+	crate::GenesisConfig::<Test> { initial_multisig_account: Some(ALICE) }
+		.assimilate_storage(&mut t)
+		.unwrap();
+
+	t.into()
+}
+
+// These time units are defined in number of blocks.
+pub const MINUTES: BlockNumber = 60 / (12 as BlockNumber);
+pub const HOURS: BlockNumber = MINUTES * 60;
+pub const DAYS: BlockNumber = HOURS * 24;
+pub const WEEKS: BlockNumber = DAYS * 7;
+
+pub(crate) const ALICE: AccountId = AccountId::new([0u8; 32]);
+pub(crate) const BRUCE: AccountId = AccountId::new([1u8; 32]);
+pub(crate) const CATHI: AccountId = AccountId::new([2u8; 32]);
+
+pub(crate) const INIT_BALANCE: Balance = 100_000;
diff --git a/pallets/deprecated/salp/src/tests.rs b/pallets/deprecated/salp/src/tests.rs
new file mode 100644
index 000000000..31d5870cf
--- /dev/null
+++ b/pallets/deprecated/salp/src/tests.rs
@@ -0,0 +1,1604 @@
+// 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 <https://www.gnu.org/licenses/>.
+
+// Ensure we're `no_std` when compiling for Wasm.
+
+use crate::{mock::*, Error, FundStatus, *};
+use bifrost_primitives::{ContributionStatus, CurrencyId, TokenSymbol, KSM, VKSM, VSKSM};
+use bifrost_xcm_interface::SalpHelper;
+use frame_support::{assert_noop, assert_ok};
+use frame_system::pallet_prelude::BlockNumberFor;
+use orml_traits::{MultiCurrency, MultiReservableCurrency};
+use sp_runtime::{traits::AccountIdConversion, DispatchError};
+use zenlink_protocol::AssetId;
+
+#[test]
+fn create_fund_should_work() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_ok!(Funds::<Test>::get(3_000).ok_or(()));
+		assert_eq!(CurrentTrieIndex::<Test>::get(), 1);
+	});
+}
+
+#[test]
+fn create_fund_with_wrong_origin_should_fail() {
+	new_test_ext().execute_with(|| {
+		assert_noop!(
+			Salp::create(RuntimeOrigin::none(), 3_000, 1_000, 1, SlotLength::get()),
+			DispatchError::BadOrigin,
+		);
+	});
+}
+
+#[test]
+fn create_fund_existed_should_fail() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+
+		assert_noop!(
+			Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()),
+			Error::<Test>::FundAlreadyCreated,
+		);
+	});
+}
+
+#[test]
+fn create_fund_exceed_slot_limit_should_fail() {
+	new_test_ext().execute_with(|| {
+		assert_noop!(
+			Salp::create(Some(ALICE).into(), 3_000, 1_000, 0, SlotLength::get()),
+			Error::<Test>::LastSlotTooFarInFuture,
+		);
+	});
+}
+
+#[test]
+fn create_fund_first_slot_bigger_than_last_slot_should_fail() {
+	new_test_ext().execute_with(|| {
+		assert_noop!(
+			Salp::create(Some(ALICE).into(), 3_000, 1_000, SlotLength::get(), 0),
+			Error::<Test>::LastSlotBeforeFirstSlot,
+		);
+	});
+}
+
+#[test]
+fn set_fund_success_should_work() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_ok!(Salp::fund_success(Some(ALICE).into(), 3_000));
+
+		// Check status
+		let fund = Funds::<Test>::get(3_000).unwrap();
+		assert_eq!(fund.status, FundStatus::Success);
+	});
+}
+
+#[test]
+fn set_fund_success_with_wrong_origin_should_fail() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_noop!(Salp::fund_success(RuntimeOrigin::none(), 3_000), DispatchError::BadOrigin);
+	})
+}
+
+#[test]
+fn set_fund_success_with_wrong_para_id_should_fail() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_noop!(Salp::fund_success(Some(ALICE).into(), 4_000), Error::<Test>::InvalidParaId);
+	});
+}
+
+#[test]
+fn set_fund_success_with_wrong_fund_status_should_fail() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_ok!(Salp::fund_fail(Some(ALICE).into(), 3_000));
+		assert_noop!(
+			Salp::fund_success(Some(ALICE).into(), 3_000),
+			Error::<Test>::InvalidFundStatus
+		);
+	});
+}
+
+#[test]
+fn set_fund_fail_should_work() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_ok!(Salp::fund_fail(Some(ALICE).into(), 3_000));
+
+		// Check status
+		let fund = Funds::<Test>::get(3_000).unwrap();
+		assert_eq!(fund.status, FundStatus::Failed);
+	});
+}
+
+#[test]
+fn set_fund_fail_with_wrong_origin_should_fail() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_noop!(Salp::fund_fail(RuntimeOrigin::none(), 3_000), DispatchError::BadOrigin);
+	});
+}
+
+#[test]
+fn set_fund_fail_with_wrong_para_id_should_fail() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_noop!(Salp::fund_fail(Some(ALICE).into(), 4_000), Error::<Test>::InvalidParaId);
+	});
+}
+
+#[test]
+fn set_fund_fail_with_wrong_fund_status_should_fail() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_ok!(Salp::fund_success(Some(ALICE).into(), 3_000));
+		assert_noop!(Salp::fund_fail(Some(ALICE).into(), 3_000), Error::<Test>::InvalidFundStatus);
+	});
+}
+
+#[test]
+fn set_fund_retire_should_work() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_ok!(Salp::fund_success(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::fund_retire(Some(ALICE).into(), 3_000));
+
+		// Check status
+		let fund = Funds::<Test>::get(3_000).unwrap();
+		assert_eq!(fund.status, FundStatus::Retired);
+	});
+}
+
+#[test]
+fn set_fund_retire_with_wrong_origin_should_fail() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_ok!(Salp::fund_success(Some(ALICE).into(), 3_000));
+		assert_noop!(Salp::fund_retire(RuntimeOrigin::none(), 3_000), DispatchError::BadOrigin);
+	});
+}
+
+#[test]
+fn set_fund_retire_with_wrong_para_id_should_fail() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_ok!(Salp::fund_success(Some(ALICE).into(), 3_000));
+		assert_noop!(Salp::fund_retire(Some(ALICE).into(), 4_000), Error::<Test>::InvalidParaId);
+	});
+}
+
+#[test]
+fn set_fund_retire_with_with_wrong_fund_status_should_fail() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_noop!(
+			Salp::fund_retire(Some(ALICE).into(), 3_000),
+			Error::<Test>::InvalidFundStatus
+		);
+	});
+}
+
+#[test]
+fn set_fund_end_should_work() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_ok!(Salp::fund_success(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::fund_retire(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::withdraw(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::fund_end(Some(ALICE).into(), 3_000));
+
+		// Check storage
+		let fund = Funds::<Test>::get(3_000).unwrap();
+		assert_eq!(fund.status, FundStatus::End);
+	});
+}
+
+#[test]
+fn set_fund_end_with_wrong_origin_should_fail() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_ok!(Salp::fund_success(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::fund_retire(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::withdraw(Some(ALICE).into(), 3_000));
+
+		assert_noop!(Salp::fund_end(RuntimeOrigin::none(), 3_000), DispatchError::BadOrigin);
+	});
+}
+
+#[test]
+fn set_fund_end_with_wrong_wrong_para_id_should_fail() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_ok!(Salp::fund_success(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::fund_retire(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::withdraw(Some(ALICE).into(), 3_000));
+
+		assert_noop!(Salp::fund_end(Some(ALICE).into(), 4_000), Error::<Test>::InvalidParaId);
+	});
+}
+
+#[test]
+fn set_fund_end_with_wrong_fund_status_should_fail() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_ok!(Salp::fund_success(Some(ALICE).into(), 3_000));
+
+		assert_noop!(Salp::fund_end(Some(ALICE).into(), 3_000), Error::<Test>::InvalidFundStatus);
+	});
+}
+
+#[test]
+fn unlock_should_work() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_ok!(Salp::contribute(Some(BRUCE).into(), 3_000, 100));
+		Salp::bind_query_id_and_contribution(0, 3_000, BRUCE, 100);
+		assert_ok!(Salp::confirm_contribute(Some(ALICE).into(), 0, true,));
+		assert_ok!(Salp::fund_success(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::unlock(Some(BRUCE).into(), BRUCE, 3_000));
+
+		let vs_token =
+			<Test as Config>::CurrencyIdConversion::convert_to_vstoken(RelayCurrencyId::get())
+				.unwrap();
+		let vs_bond = <Test as Config>::CurrencyIdConversion::convert_to_vsbond(
+			RelayCurrencyId::get(),
+			3_000,
+			1,
+			SlotLength::get(),
+		)
+		.unwrap();
+
+		assert_eq!(Tokens::accounts(BRUCE, vs_token).free, 100);
+		assert_eq!(Tokens::accounts(BRUCE, vs_token).frozen, 0);
+		assert_eq!(Tokens::accounts(BRUCE, vs_token).reserved, 0);
+		assert_eq!(Tokens::accounts(BRUCE, vs_bond).free, 100);
+		assert_eq!(Tokens::accounts(BRUCE, vs_bond).frozen, 0);
+		assert_eq!(Tokens::accounts(BRUCE, vs_bond).reserved, 0);
+	});
+}
+
+#[test]
+fn unlock_by_vsbond_should_work() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_ok!(Salp::contribute(Some(BRUCE).into(), 3_000, 100));
+		Salp::bind_query_id_and_contribution(0, 3_000, BRUCE, 100);
+		assert_ok!(Salp::confirm_contribute(Some(ALICE).into(), 0, true,));
+		assert_ok!(Salp::fund_success(Some(ALICE).into(), 3_000));
+
+		let vs_token =
+			<Test as Config>::CurrencyIdConversion::convert_to_vstoken(RelayCurrencyId::get())
+				.unwrap();
+		let vs_bond = <Test as Config>::CurrencyIdConversion::convert_to_vsbond(
+			RelayCurrencyId::get(),
+			3_000,
+			1,
+			SlotLength::get(),
+		)
+		.unwrap();
+
+		assert_ok!(Salp::unlock_by_vsbond(Some(BRUCE).into(), BRUCE, vs_bond));
+		assert_eq!(Tokens::accounts(BRUCE, vs_token).free, 100);
+		assert_eq!(Tokens::accounts(BRUCE, vs_token).frozen, 0);
+		assert_eq!(Tokens::accounts(BRUCE, vs_token).reserved, 0);
+		assert_eq!(Tokens::accounts(BRUCE, vs_bond).free, 100);
+		assert_eq!(Tokens::accounts(BRUCE, vs_bond).frozen, 0);
+		assert_eq!(Tokens::accounts(BRUCE, vs_bond).reserved, 0);
+	});
+}
+
+#[test]
+fn unlock_vstoken_should_work() {
+	new_test_ext().execute_with(|| {
+		let vs_token =
+			<Test as Config>::CurrencyIdConversion::convert_to_vstoken(RelayCurrencyId::get())
+				.unwrap();
+		assert_ok!(<Test as Config>::MultiCurrency::reserve(vs_token, &ALICE, 1));
+
+		assert_eq!(Tokens::accounts(ALICE, vs_token).free, 99999);
+		assert_eq!(Tokens::accounts(ALICE, vs_token).frozen, 0);
+		assert_eq!(Tokens::accounts(ALICE, vs_token).reserved, 1);
+		assert_ok!(Salp::unlock_vstoken(Some(BRUCE).into(), ALICE));
+		assert_eq!(Tokens::accounts(ALICE, vs_token).free, 100000);
+		assert_eq!(Tokens::accounts(ALICE, vs_token).frozen, 0);
+		assert_eq!(Tokens::accounts(ALICE, vs_token).reserved, 0);
+
+		assert_ok!(Salp::create(Some(ALICE).into(), 2_100, 1_000, 18, 25));
+		assert_ok!(Salp::contribute(Some(BRUCE).into(), 2_100, 100));
+		Salp::bind_query_id_and_contribution(0, 2_100, BRUCE, 100);
+		assert_ok!(Salp::confirm_contribute(Some(ALICE).into(), 0, true,));
+		assert_ok!(Salp::fund_success(Some(ALICE).into(), 2_100));
+		let vs_bond = <Test as Config>::CurrencyIdConversion::convert_to_vsbond(
+			RelayCurrencyId::get(),
+			2_100,
+			18,
+			25,
+		)
+		.unwrap();
+		assert_ok!(<Test as Config>::MultiCurrency::reserve(vs_bond, &BRUCE, 1));
+		assert_eq!(Tokens::accounts(BRUCE, vs_bond).free, 99);
+		assert_eq!(Tokens::accounts(BRUCE, vs_bond).frozen, 0);
+		assert_eq!(Tokens::accounts(BRUCE, vs_bond).reserved, 1);
+		assert_ok!(Salp::unlock_vstoken(Some(BRUCE).into(), BRUCE));
+		assert_eq!(Tokens::accounts(BRUCE, vs_bond).free, 100);
+		assert_eq!(Tokens::accounts(BRUCE, vs_bond).frozen, 0);
+		assert_eq!(Tokens::accounts(BRUCE, vs_bond).reserved, 0);
+	});
+}
+
+#[test]
+fn contribute_should_work() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_ok!(Salp::contribute(Some(BRUCE).into(), 3_000, 100));
+		Salp::bind_query_id_and_contribution(0, 3_000, BRUCE, 100);
+		assert_ok!(Salp::confirm_contribute(Some(ALICE).into(), 0, true));
+
+		let fund = Funds::<Test>::get(3_000).unwrap();
+		let (contributed, status) = Salp::contribution(fund.trie_index, &BRUCE);
+		assert_eq!(fund.raised, 100);
+		assert_eq!(contributed, 100);
+		assert_eq!(status, ContributionStatus::Idle);
+
+		let vs_token =
+			<Test as Config>::CurrencyIdConversion::convert_to_vstoken(RelayCurrencyId::get())
+				.unwrap();
+		let vs_bond = <Test as Config>::CurrencyIdConversion::convert_to_vsbond(
+			RelayCurrencyId::get(),
+			3_000,
+			1,
+			SlotLength::get(),
+		)
+		.unwrap();
+		assert_eq!(Tokens::accounts(BRUCE, vs_token).free, 100);
+		assert_eq!(Tokens::accounts(BRUCE, vs_bond).free, 100);
+	});
+}
+
+#[test]
+fn double_contribute_should_work() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_ok!(Salp::contribute(Some(BRUCE).into(), 3_000, 100));
+		Salp::bind_query_id_and_contribution(0, 3_000, BRUCE, 100);
+		assert_ok!(Salp::confirm_contribute(Some(ALICE).into(), 0, true,));
+		assert_ok!(Salp::contribute(Some(BRUCE).into(), 3_000, 100));
+		Salp::bind_query_id_and_contribution(0, 3_000, BRUCE, 100);
+		assert_ok!(Salp::confirm_contribute(Some(ALICE).into(), 0, true,));
+
+		// Check the contribution
+		let fund = Funds::<Test>::get(3_000).unwrap();
+		let (contributed, status) = Salp::contribution(fund.trie_index, &BRUCE);
+		assert_eq!(fund.raised, 200);
+		assert_eq!(contributed, 200);
+		assert_eq!(status, ContributionStatus::Idle);
+
+		let vs_token =
+			<Test as Config>::CurrencyIdConversion::convert_to_vstoken(RelayCurrencyId::get())
+				.unwrap();
+		let vs_bond = <Test as Config>::CurrencyIdConversion::convert_to_vsbond(
+			RelayCurrencyId::get(),
+			3_000,
+			1,
+			SlotLength::get(),
+		)
+		.unwrap();
+		assert_eq!(Tokens::accounts(BRUCE, vs_token).free, 200);
+		assert_eq!(Tokens::accounts(BRUCE, vs_bond).free, 200);
+	});
+}
+
+#[test]
+fn contribute_when_xcm_error_should_work() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_ok!(Salp::contribute(Some(BRUCE).into(), 3_000, 100));
+		Salp::bind_query_id_and_contribution(0, 3_000, BRUCE, 100);
+		assert_ok!(Salp::confirm_contribute(Some(ALICE).into(), 0, false,));
+
+		let fund = Funds::<Test>::get(3_000).unwrap();
+		let (contributed, status) = Salp::contribution(fund.trie_index, &BRUCE);
+		assert_eq!(fund.raised, 0);
+		assert_eq!(contributed, 0);
+		assert_eq!(status, ContributionStatus::Idle);
+
+		let vs_token =
+			<Test as Config>::CurrencyIdConversion::convert_to_vstoken(RelayCurrencyId::get())
+				.unwrap();
+		let vs_bond = <Test as Config>::CurrencyIdConversion::convert_to_vsbond(
+			RelayCurrencyId::get(),
+			3_000,
+			1,
+			SlotLength::get(),
+		)
+		.unwrap();
+		assert_eq!(Tokens::accounts(BRUCE, vs_token).free, 0);
+		assert_eq!(Tokens::accounts(BRUCE, vs_token).frozen, 0);
+		assert_eq!(Tokens::accounts(BRUCE, vs_token).reserved, 0);
+		assert_eq!(Tokens::accounts(BRUCE, vs_bond).free, 0);
+		assert_eq!(Tokens::accounts(BRUCE, vs_bond).frozen, 0);
+		assert_eq!(Tokens::accounts(BRUCE, vs_bond).reserved, 0);
+	});
+}
+
+#[test]
+fn confirm_contribute_later_should_work() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_ok!(Salp::contribute(Some(BRUCE).into(), 3_000, 100));
+		Salp::bind_query_id_and_contribution(0, 3_000, BRUCE, 100);
+		assert_ok!(Salp::fund_success(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::confirm_contribute(Some(ALICE).into(), 0, true,));
+
+		let fund = Funds::<Test>::get(3_000).unwrap();
+		let (contributed, status) = Salp::contribution(fund.trie_index, &BRUCE);
+		assert_eq!(fund.raised, 100);
+		assert_eq!(contributed, 100);
+		assert_eq!(status, ContributionStatus::Idle);
+
+		let vs_token =
+			<Test as Config>::CurrencyIdConversion::convert_to_vstoken(RelayCurrencyId::get())
+				.unwrap();
+		let vs_bond = <Test as Config>::CurrencyIdConversion::convert_to_vsbond(
+			RelayCurrencyId::get(),
+			3_000,
+			1,
+			SlotLength::get(),
+		)
+		.unwrap();
+		assert_eq!(Tokens::accounts(BRUCE, vs_token).free, 100);
+		assert_eq!(Tokens::accounts(BRUCE, vs_bond).free, 100);
+	});
+}
+
+#[test]
+fn contribute_with_wrong_origin_should_fail() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_noop!(Salp::contribute(RuntimeOrigin::none(), 3_000, 100), DispatchError::BadOrigin);
+
+		assert_noop!(
+			Salp::confirm_contribute(RuntimeOrigin::none(), 0, true),
+			DispatchError::BadOrigin,
+		);
+	});
+}
+
+#[test]
+fn contribute_with_low_contribution_should_fail() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_noop!(
+			Salp::contribute(Some(BRUCE).into(), 3_000, MinContribution::get() - 1),
+			Error::<Test>::ContributionTooSmall
+		);
+	});
+}
+
+#[test]
+fn contribute_with_wrong_para_id_should_fail() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_noop!(
+			Salp::contribute(Some(BRUCE).into(), 4_000, 100),
+			Error::<Test>::InvalidParaId
+		);
+	});
+}
+
+#[test]
+fn contribute_with_wrong_fund_status_should_fail() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_ok!(Salp::fund_success(Some(ALICE).into(), 3_000,));
+		assert_noop!(
+			Salp::contribute(Some(BRUCE).into(), 3_000, 100),
+			Error::<Test>::InvalidFundStatus
+		);
+	});
+}
+
+#[test]
+fn contribute_exceed_cap_should_fail() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_noop!(
+			Salp::contribute(Some(BRUCE).into(), 3_000, 1_001),
+			Error::<Test>::CapExceeded
+		);
+	});
+}
+
+#[test]
+fn contribute_when_contributing_should_fail() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_noop!(
+			Salp::confirm_contribute(Some(ALICE).into(), 0, true),
+			Error::<Test>::NotFindContributionValue
+		);
+	});
+}
+
+#[test]
+fn confirm_contribute_when_not_in_contributing_should_fail() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_ok!(Salp::contribute(Some(BRUCE).into(), 3_000, 100));
+
+		assert_noop!(
+			Salp::contribute(Some(BRUCE).into(), 3_000, 100),
+			Error::<Test>::InvalidContributionStatus
+		);
+	});
+}
+
+#[test]
+fn contribute_with_when_ump_wrong_should_fail() {
+	// TODO: Require an solution to settle with parallel test workflow
+}
+
+#[test]
+fn withdraw_should_work() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_ok!(Salp::contribute(Some(BRUCE).into(), 3_000, 100));
+		Salp::bind_query_id_and_contribution(0, 3_000, BRUCE, 100);
+		assert_ok!(Salp::confirm_contribute(Some(ALICE).into(), 0, true,));
+		assert_ok!(Salp::fund_success(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::fund_retire(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::withdraw(Some(ALICE).into(), 3_000));
+
+		let fund = Funds::<Test>::get(3_000).unwrap();
+		assert_eq!(fund.status, FundStatus::RedeemWithdrew);
+
+		assert_ok!(Salp::create(Some(ALICE).into(), 4_000, 1_000, 1, SlotLength::get()));
+		assert_ok!(Salp::contribute(Some(BRUCE).into(), 4_000, 100));
+		Salp::bind_query_id_and_contribution(0, 4_000, BRUCE, 100);
+		assert_ok!(Salp::confirm_contribute(Some(ALICE).into(), 0, true,));
+		assert_ok!(Salp::fund_fail(Some(ALICE).into(), 4_000));
+		assert_ok!(Salp::withdraw(Some(ALICE).into(), 4_000));
+
+		let fund = Funds::<Test>::get(4_000).unwrap();
+		assert_eq!(fund.status, FundStatus::RefundWithdrew);
+	});
+}
+
+#[test]
+fn withdraw_when_xcm_error_should_work() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_ok!(Salp::contribute(Some(BRUCE).into(), 3_000, 100));
+		Salp::bind_query_id_and_contribution(0, 3_000, BRUCE, 100);
+		assert_ok!(Salp::confirm_contribute(Some(ALICE).into(), 0, true,));
+		assert_ok!(Salp::fund_success(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::fund_retire(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::withdraw(Some(ALICE).into(), 3_000));
+
+		let fund = Funds::<Test>::get(3_000).unwrap();
+		assert_eq!(fund.status, FundStatus::RedeemWithdrew);
+
+		assert_ok!(Salp::create(Some(ALICE).into(), 4_000, 1_000, 1, SlotLength::get()));
+		assert_ok!(Salp::contribute(Some(BRUCE).into(), 4_000, 100));
+		Salp::bind_query_id_and_contribution(0, 4_000, BRUCE, 100);
+		assert_ok!(Salp::confirm_contribute(Some(ALICE).into(), 0, true,));
+		assert_ok!(Salp::fund_fail(Some(ALICE).into(), 4_000));
+		assert_ok!(Salp::withdraw(Some(ALICE).into(), 4_000));
+
+		let fund = Funds::<Test>::get(4_000).unwrap();
+		assert_eq!(fund.status, FundStatus::RefundWithdrew);
+	});
+}
+
+#[test]
+fn double_withdraw_same_fund_should_fail() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_ok!(Salp::contribute(Some(BRUCE).into(), 3_000, 100));
+		Salp::bind_query_id_and_contribution(0, 3_000, BRUCE, 100);
+		assert_ok!(Salp::confirm_contribute(Some(ALICE).into(), 0, true,));
+		assert_ok!(Salp::fund_success(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::fund_retire(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::withdraw(Some(ALICE).into(), 3_000));
+		assert_noop!(Salp::withdraw(Some(ALICE).into(), 3_000), Error::<Test>::InvalidFundStatus);
+
+		let fund = Funds::<Test>::get(3_000).unwrap();
+		assert_eq!(fund.status, FundStatus::RedeemWithdrew);
+
+		assert_ok!(Salp::create(Some(ALICE).into(), 4_000, 1_000, 1, SlotLength::get()));
+		assert_ok!(Salp::contribute(Some(BRUCE).into(), 4_000, 100));
+		Salp::bind_query_id_and_contribution(0, 4_000, BRUCE, 100);
+		assert_ok!(Salp::confirm_contribute(Some(ALICE).into(), 0, true,));
+		assert_ok!(Salp::fund_fail(Some(ALICE).into(), 4_000));
+		assert_ok!(Salp::withdraw(Some(ALICE).into(), 4_000));
+		assert_noop!(Salp::withdraw(Some(ALICE).into(), 4_000), Error::<Test>::InvalidFundStatus);
+
+		let fund = Funds::<Test>::get(4_000).unwrap();
+		assert_eq!(fund.status, FundStatus::RefundWithdrew);
+	});
+}
+
+#[test]
+fn double_withdraw_same_fund_when_one_of_xcm_error_should_work() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_ok!(Salp::contribute(Some(BRUCE).into(), 3_000, 100));
+		Salp::bind_query_id_and_contribution(0, 3_000, BRUCE, 100);
+		assert_ok!(Salp::confirm_contribute(Some(ALICE).into(), 0, true,));
+		assert_ok!(Salp::fund_success(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::fund_retire(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::withdraw(Some(ALICE).into(), 3_000));
+		assert_noop!(Salp::withdraw(Some(ALICE).into(), 3_000), Error::<Test>::InvalidFundStatus);
+	});
+}
+
+#[test]
+fn withdraw_with_wrong_origin_should_fail() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_ok!(Salp::fund_success(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::fund_retire(Some(ALICE).into(), 3_000));
+
+		assert_noop!(Salp::withdraw(RuntimeOrigin::none(), 3_000), DispatchError::BadOrigin);
+	});
+}
+
+#[test]
+fn withdraw_with_wrong_para_id_should_fail() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_ok!(Salp::fund_success(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::fund_retire(Some(ALICE).into(), 3_000));
+
+		assert_noop!(Salp::withdraw(Some(ALICE).into(), 4_000), Error::<Test>::InvalidParaId);
+	});
+}
+
+#[test]
+fn withdraw_with_wrong_fund_status_should_fail() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_ok!(Salp::fund_success(Some(ALICE).into(), 3_000));
+
+		assert_noop!(Salp::withdraw(Some(ALICE).into(), 3_000), Error::<Test>::InvalidFundStatus);
+	});
+}
+
+#[test]
+fn withdraw_with_when_ump_wrong_should_fail() {
+	// TODO: Require an solution to settle with parallel test workflow
+}
+
+#[test]
+fn refund_should_work() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_ok!(Salp::contribute(Some(BRUCE).into(), 3_000, 100));
+		Salp::bind_query_id_and_contribution(0, 3_000, BRUCE, 100);
+		assert_ok!(Salp::confirm_contribute(Some(ALICE).into(), 0, true,));
+		assert_ok!(Salp::fund_fail(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::withdraw(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::refund(Some(BRUCE).into(), 3_000, 1, SlotLength::get(), 100));
+
+		let vs_token =
+			<Test as Config>::CurrencyIdConversion::convert_to_vstoken(RelayCurrencyId::get())
+				.unwrap();
+		let vs_bond = <Test as Config>::CurrencyIdConversion::convert_to_vsbond(
+			RelayCurrencyId::get(),
+			3_000,
+			1,
+			SlotLength::get(),
+		)
+		.unwrap();
+		assert_eq!(Tokens::accounts(BRUCE, vs_token).free, 0);
+		assert_eq!(Tokens::accounts(BRUCE, vs_token).frozen, 0);
+		assert_eq!(Tokens::accounts(BRUCE, vs_token).reserved, 0);
+		assert_eq!(Tokens::accounts(BRUCE, vs_bond).free, 0);
+		assert_eq!(Tokens::accounts(BRUCE, vs_bond).frozen, 0);
+		assert_eq!(Tokens::accounts(BRUCE, vs_bond).reserved, 0);
+		assert_eq!(Tokens::accounts(BRUCE, RelayCurrencyId::get()).free, INIT_BALANCE);
+		assert_eq!(Tokens::accounts(BRUCE, RelayCurrencyId::get()).frozen, 0);
+		assert_eq!(Tokens::accounts(BRUCE, RelayCurrencyId::get()).reserved, 0);
+	});
+}
+
+#[test]
+fn refund_when_xcm_error_should_work() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_ok!(Salp::contribute(Some(BRUCE).into(), 3_000, 100));
+		Salp::bind_query_id_and_contribution(0, 3_000, BRUCE, 100);
+		assert_ok!(Salp::confirm_contribute(Some(ALICE).into(), 0, true,));
+		assert_ok!(Salp::fund_fail(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::withdraw(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::refund(Some(BRUCE).into(), 3_000, 1, SlotLength::get(), 100));
+
+		let vs_token =
+			<Test as Config>::CurrencyIdConversion::convert_to_vstoken(RelayCurrencyId::get())
+				.unwrap();
+		let vs_bond = <Test as Config>::CurrencyIdConversion::convert_to_vsbond(
+			RelayCurrencyId::get(),
+			3_000,
+			1,
+			SlotLength::get(),
+		)
+		.unwrap();
+		assert_eq!(Tokens::accounts(BRUCE, vs_token).free, 0);
+		assert_eq!(Tokens::accounts(BRUCE, vs_token).frozen, 0);
+		assert_eq!(Tokens::accounts(BRUCE, vs_token).reserved, 0);
+		assert_eq!(Tokens::accounts(BRUCE, vs_bond).free, 0);
+		assert_eq!(Tokens::accounts(BRUCE, vs_bond).frozen, 0);
+		assert_eq!(Tokens::accounts(BRUCE, vs_bond).reserved, 0);
+	});
+}
+
+#[test]
+fn double_refund_when_one_of_xcm_error_should_work() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_ok!(Salp::contribute(Some(BRUCE).into(), 3_000, 100));
+		Salp::bind_query_id_and_contribution(0, 3_000, BRUCE, 100);
+		assert_ok!(Salp::confirm_contribute(Some(ALICE).into(), 0, true,));
+		assert_ok!(Salp::fund_fail(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::withdraw(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::refund(Some(BRUCE).into(), 3_000, 1, SlotLength::get(), 100));
+		assert_noop!(
+			Salp::refund(Some(BRUCE).into(), 3_000, 1, SlotLength::get(), 100),
+			Error::<Test>::NotEnoughBalanceInFund
+		);
+	});
+}
+
+#[test]
+fn refund_with_wrong_origin_should_fail() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_ok!(Salp::contribute(Some(BRUCE).into(), 3_000, 100));
+		Salp::bind_query_id_and_contribution(0, 3_000, BRUCE, 100);
+		assert_ok!(Salp::confirm_contribute(Some(ALICE).into(), 0, true,));
+		assert_ok!(Salp::fund_fail(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::withdraw(Some(ALICE).into(), 3_000));
+
+		assert_noop!(
+			Salp::refund(RuntimeOrigin::root(), 3_000, 1, SlotLength::get(), 100),
+			DispatchError::BadOrigin
+		);
+		assert_noop!(
+			Salp::refund(RuntimeOrigin::none(), 3_000, 1, SlotLength::get(), 100),
+			DispatchError::BadOrigin
+		);
+
+		assert_ok!(Salp::refund(Some(BRUCE).into(), 3_000, 1, SlotLength::get(), 100));
+	});
+}
+
+#[test]
+fn refund_with_wrong_para_id_should_fail() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_ok!(Salp::fund_fail(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::withdraw(Some(ALICE).into(), 3_000));
+
+		assert_noop!(
+			Salp::refund(Some(BRUCE).into(), 4_000, 1, SlotLength::get(), 100),
+			Error::<Test>::InvalidFundNotExist
+		);
+	});
+}
+
+#[test]
+fn dissolve_should_work() {
+	new_test_ext().execute_with(|| {
+		let remove_times = 4;
+		let contribute_account_num = remove_times * RemoveKeysLimit::get();
+
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 10_000, 1, SlotLength::get()));
+		for i in 0..contribute_account_num {
+			let ract = AccountId::new([(i as u8); 32]);
+			assert_ok!(Tokens::deposit(RelayCurrencyId::get(), &ract, 10));
+			assert_ok!(Salp::contribute(Some(ract.clone()).into(), 3_000, 10));
+			Salp::bind_query_id_and_contribution(0, 3_000, ract, 10);
+			assert_ok!(Salp::confirm_contribute(Some(ALICE).into(), 0, true,));
+		}
+		assert_ok!(Salp::fund_success(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::fund_retire(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::withdraw(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::fund_end(Some(ALICE).into(), 3_000));
+
+		for _ in 0..remove_times {
+			assert_ok!(Salp::dissolve(Some(ALICE).into(), 3_000));
+		}
+
+		assert!(Funds::<Test>::get(3_000).is_none());
+		assert!(Salp::contribution_iterator(0).next().is_none());
+	});
+}
+
+#[test]
+fn dissolve_with_wrong_origin_should_fail() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_ok!(Salp::fund_success(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::fund_retire(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::withdraw(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::fund_end(Some(ALICE).into(), 3_000));
+
+		assert_noop!(Salp::dissolve(RuntimeOrigin::none(), 3_000), DispatchError::BadOrigin);
+	});
+}
+
+#[test]
+fn dissolve_with_wrong_para_id_should_fail() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_ok!(Salp::fund_success(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::fund_retire(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::withdraw(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::fund_end(Some(ALICE).into(), 3_000));
+
+		assert_noop!(Salp::dissolve(Some(ALICE).into(), 4_000), Error::<Test>::InvalidParaId);
+	});
+}
+
+#[test]
+fn dissolve_with_wrong_fund_status_should_fail() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_ok!(Salp::fund_success(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::fund_retire(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::withdraw(Some(ALICE).into(), 3_000));
+
+		assert_noop!(Salp::dissolve(Some(ALICE).into(), 3_000), Error::<Test>::InvalidFundStatus);
+	});
+}
+
+#[test]
+fn redeem_should_work() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_ok!(Salp::contribute(Some(BRUCE).into(), 3_000, 100));
+		Salp::bind_query_id_and_contribution(0, 3_000, BRUCE, 100);
+		assert_ok!(Salp::confirm_contribute(Some(ALICE).into(), 0, true,));
+
+		assert_eq!(Tokens::accounts(BRUCE, RelayCurrencyId::get()).free, INIT_BALANCE - 100);
+		assert_eq!(Tokens::accounts(BRUCE, RelayCurrencyId::get()).frozen, 0);
+		assert_eq!(Tokens::accounts(BRUCE, RelayCurrencyId::get()).reserved, 0);
+
+		assert_eq!(
+			Tokens::accounts(Salp::fund_account_id(3_000), RelayCurrencyId::get()).free,
+			100
+		);
+		assert_eq!(
+			Tokens::accounts(Salp::fund_account_id(3_000), RelayCurrencyId::get()).frozen,
+			0
+		);
+		assert_eq!(
+			Tokens::accounts(Salp::fund_account_id(3_000), RelayCurrencyId::get()).reserved,
+			0
+		);
+
+		assert_ok!(Salp::fund_success(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::unlock(Some(BRUCE).into(), BRUCE, 3_000));
+
+		// Mock the BlockNumber
+		let block_begin_redeem = (SlotLength::get() + 1) * LeasePeriod::get();
+		System::set_block_number(block_begin_redeem.into());
+
+		assert_ok!(Salp::fund_retire(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::withdraw(Some(ALICE).into(), 3_000));
+
+		let vs_token =
+			<Test as Config>::CurrencyIdConversion::convert_to_vstoken(RelayCurrencyId::get())
+				.unwrap();
+		let vs_bond = <Test as Config>::CurrencyIdConversion::convert_to_vsbond(
+			RelayCurrencyId::get(),
+			3_000,
+			1,
+			SlotLength::get(),
+		)
+		.unwrap();
+
+		assert_ok!(<Tokens as MultiCurrency<AccountId>>::transfer(vs_token, &BRUCE, &CATHI, 50));
+		assert_ok!(<Tokens as MultiCurrency<AccountId>>::transfer(vs_bond, &BRUCE, &CATHI, 50));
+
+		assert_ok!(Salp::redeem(Some(BRUCE).into(), 3_000, 50));
+
+		assert_eq!(Tokens::accounts(BRUCE, vs_token).free, 0);
+		assert_eq!(Tokens::accounts(BRUCE, vs_token).frozen, 0);
+		assert_eq!(Tokens::accounts(BRUCE, vs_token).reserved, 0);
+		assert_eq!(Tokens::accounts(BRUCE, vs_bond).free, 0);
+		assert_eq!(Tokens::accounts(BRUCE, vs_bond).frozen, 0);
+		assert_eq!(Tokens::accounts(BRUCE, vs_bond).reserved, 0);
+		assert_eq!(Tokens::accounts(BRUCE, RelayCurrencyId::get()).free, INIT_BALANCE - 50);
+		assert_eq!(Tokens::accounts(BRUCE, RelayCurrencyId::get()).frozen, 0);
+		assert_eq!(Tokens::accounts(BRUCE, RelayCurrencyId::get()).reserved, 0);
+
+		assert_ok!(Salp::redeem(Some(CATHI).into(), 3_000, 50));
+
+		assert_eq!(Tokens::accounts(CATHI, vs_token).free, 0);
+		assert_eq!(Tokens::accounts(CATHI, vs_token).frozen, 0);
+		assert_eq!(Tokens::accounts(CATHI, vs_token).reserved, 0);
+		assert_eq!(Tokens::accounts(CATHI, vs_bond).free, 0);
+		assert_eq!(Tokens::accounts(CATHI, vs_bond).frozen, 0);
+		assert_eq!(Tokens::accounts(CATHI, vs_bond).reserved, 0);
+		assert_eq!(Tokens::accounts(CATHI, RelayCurrencyId::get()).free, INIT_BALANCE + 50);
+		assert_eq!(Tokens::accounts(CATHI, RelayCurrencyId::get()).frozen, 0);
+		assert_eq!(Tokens::accounts(CATHI, RelayCurrencyId::get()).reserved, 0);
+	});
+}
+
+#[test]
+fn redeem_with_speical_vsbond_should_work() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 2001, 1_000, 13, 20));
+		assert_ok!(Salp::contribute(Some(BRUCE).into(), 2001, 100));
+		Salp::bind_query_id_and_contribution(0, 2001, BRUCE, 100);
+		assert_ok!(Salp::confirm_contribute(Some(ALICE).into(), 0, true,));
+
+		assert_eq!(Tokens::accounts(BRUCE, RelayCurrencyId::get()).free, INIT_BALANCE - 100);
+		assert_eq!(Tokens::accounts(BRUCE, RelayCurrencyId::get()).frozen, 0);
+		assert_eq!(Tokens::accounts(BRUCE, RelayCurrencyId::get()).reserved, 0);
+
+		assert_eq!(Tokens::accounts(Salp::fund_account_id(2001), RelayCurrencyId::get()).free, 100);
+		assert_eq!(Tokens::accounts(Salp::fund_account_id(2001), RelayCurrencyId::get()).frozen, 0);
+		assert_eq!(
+			Tokens::accounts(Salp::fund_account_id(2001), RelayCurrencyId::get()).reserved,
+			0
+		);
+
+		assert_ok!(Salp::fund_success(Some(ALICE).into(), 2001));
+		assert_ok!(Salp::unlock(Some(BRUCE).into(), BRUCE, 2001));
+
+		// Mock the BlockNumber
+		let block_begin_redeem = (SlotLength::get() + 1) * LeasePeriod::get();
+		System::set_block_number(block_begin_redeem.into());
+
+		assert_ok!(Salp::fund_retire(Some(ALICE).into(), 2001));
+		assert_ok!(Salp::withdraw(Some(ALICE).into(), 2001));
+
+		let vs_token =
+			<Test as Config>::CurrencyIdConversion::convert_to_vstoken(RelayCurrencyId::get())
+				.unwrap();
+		let vs_bond = <Test as Config>::CurrencyIdConversion::convert_to_vsbond(
+			RelayCurrencyId::get(),
+			2001,
+			13,
+			20,
+		)
+		.unwrap();
+
+		assert_ok!(<Tokens as MultiCurrency<AccountId>>::transfer(vs_token, &BRUCE, &CATHI, 50));
+		assert_ok!(<Tokens as MultiCurrency<AccountId>>::transfer(vs_bond, &BRUCE, &CATHI, 50));
+
+		assert_ok!(Salp::redeem(Some(BRUCE).into(), 2001, 50));
+
+		assert_eq!(Tokens::accounts(BRUCE, vs_token).free, 0);
+		assert_eq!(Tokens::accounts(BRUCE, vs_token).frozen, 0);
+		assert_eq!(Tokens::accounts(BRUCE, vs_token).reserved, 0);
+		assert_eq!(Tokens::accounts(BRUCE, vs_bond).free, 0);
+		assert_eq!(Tokens::accounts(BRUCE, vs_bond).frozen, 0);
+		assert_eq!(Tokens::accounts(BRUCE, vs_bond).reserved, 0);
+		assert_eq!(Tokens::accounts(BRUCE, RelayCurrencyId::get()).free, INIT_BALANCE - 50);
+		assert_eq!(Tokens::accounts(BRUCE, RelayCurrencyId::get()).frozen, 0);
+		assert_eq!(Tokens::accounts(BRUCE, RelayCurrencyId::get()).reserved, 0);
+
+		assert_ok!(Salp::redeem(Some(CATHI).into(), 2001, 50));
+
+		assert_eq!(Tokens::accounts(CATHI, vs_token).free, 0);
+		assert_eq!(Tokens::accounts(CATHI, vs_token).frozen, 0);
+		assert_eq!(Tokens::accounts(CATHI, vs_token).reserved, 0);
+		assert_eq!(Tokens::accounts(CATHI, vs_bond).free, 0);
+		assert_eq!(Tokens::accounts(CATHI, vs_bond).frozen, 0);
+		assert_eq!(Tokens::accounts(CATHI, vs_bond).reserved, 0);
+		assert_eq!(Tokens::accounts(CATHI, RelayCurrencyId::get()).free, INIT_BALANCE + 50);
+		assert_eq!(Tokens::accounts(CATHI, RelayCurrencyId::get()).frozen, 0);
+		assert_eq!(Tokens::accounts(CATHI, RelayCurrencyId::get()).reserved, 0);
+	});
+}
+
+#[test]
+fn redeem_with_wrong_origin_should_fail() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_ok!(Salp::contribute(Some(BRUCE).into(), 3_000, 100));
+		Salp::bind_query_id_and_contribution(0, 3_000, BRUCE, 100);
+		assert_ok!(Salp::confirm_contribute(Some(ALICE).into(), 0, true,));
+		assert_ok!(Salp::fund_success(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::unlock(Some(BRUCE).into(), BRUCE, 3_000));
+
+		// Mock the BlockNumber
+		let block_begin_redeem = (SlotLength::get() + 1) * LeasePeriod::get();
+		System::set_block_number(block_begin_redeem.into());
+
+		assert_ok!(Salp::fund_retire(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::withdraw(Some(ALICE).into(), 3_000));
+
+		assert_noop!(Salp::redeem(RuntimeOrigin::root(), 3_000, 50), DispatchError::BadOrigin);
+		assert_noop!(Salp::redeem(RuntimeOrigin::none(), 3_000, 50), DispatchError::BadOrigin);
+	});
+}
+
+#[test]
+fn redeem_with_not_redeemable_vsbond_should_fail() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_ok!(Salp::contribute(Some(BRUCE).into(), 3_000, 100));
+		Salp::bind_query_id_and_contribution(0, 3_000, BRUCE, 100);
+		assert_ok!(Salp::confirm_contribute(Some(ALICE).into(), 0, true,));
+		assert_ok!(Salp::fund_success(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::unlock(Some(BRUCE).into(), BRUCE, 3_000));
+
+		// Mock the BlockNumber
+		let block_not_redeemable = LeasePeriod::get();
+		System::set_block_number(block_not_redeemable.into());
+
+		let vs_token =
+			<Test as Config>::CurrencyIdConversion::convert_to_vstoken(RelayCurrencyId::get())
+				.unwrap();
+		let vs_bond = <Test as Config>::CurrencyIdConversion::convert_to_vsbond(
+			RelayCurrencyId::get(),
+			3_000,
+			1,
+			SlotLength::get(),
+		)
+		.unwrap();
+
+		assert_ok!(<Tokens as MultiCurrency<AccountId>>::transfer(vs_token, &BRUCE, &CATHI, 50));
+		assert_ok!(<Tokens as MultiCurrency<AccountId>>::transfer(vs_bond, &BRUCE, &CATHI, 50));
+
+		assert_noop!(Salp::redeem(Some(BRUCE).into(), 3_000, 50), Error::<Test>::InvalidFundStatus);
+
+		assert_noop!(Salp::redeem(Some(CATHI).into(), 3_000, 50), Error::<Test>::InvalidFundStatus);
+	});
+}
+
+#[test]
+fn redeem_without_enough_vsassets_should_fail() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_ok!(Salp::contribute(Some(BRUCE).into(), 3_000, 100));
+		Salp::bind_query_id_and_contribution(0, 3_000, BRUCE, 100);
+		assert_ok!(Salp::confirm_contribute(Some(ALICE).into(), 0, true,));
+		assert_ok!(Salp::fund_success(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::unlock(Some(BRUCE).into(), BRUCE, 3_000));
+
+		// Mock the BlockNumber
+		let block_begin_redeem = (SlotLength::get() + 1) * LeasePeriod::get();
+		System::set_block_number(block_begin_redeem.into());
+
+		assert_ok!(Salp::fund_retire(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::withdraw(Some(ALICE).into(), 3_000));
+
+		let vs_token =
+			<Test as Config>::CurrencyIdConversion::convert_to_vstoken(RelayCurrencyId::get())
+				.unwrap();
+		let vs_bond = <Test as Config>::CurrencyIdConversion::convert_to_vsbond(
+			RelayCurrencyId::get(),
+			3_000,
+			1,
+			SlotLength::get(),
+		)
+		.unwrap();
+
+		assert_ok!(<Tokens as MultiCurrency<AccountId>>::transfer(vs_token, &BRUCE, &CATHI, 50));
+		assert_ok!(<Tokens as MultiCurrency<AccountId>>::transfer(vs_bond, &BRUCE, &CATHI, 50));
+
+		assert_noop!(
+			Salp::redeem(Some(BRUCE).into(), 3_000, 60),
+			Error::<Test>::NotEnoughFreeAssetsToRedeem
+		);
+
+		assert_noop!(
+			Salp::redeem(Some(CATHI).into(), 3_000, 60),
+			Error::<Test>::NotEnoughFreeAssetsToRedeem
+		);
+	});
+}
+
+#[test]
+fn redeem_without_enough_balance_in_pool_should_fail() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_ok!(Salp::contribute(Some(BRUCE).into(), 3_000, 100));
+		Salp::bind_query_id_and_contribution(0, 3_000, BRUCE, 100);
+		assert_ok!(Salp::confirm_contribute(Some(ALICE).into(), 0, true,));
+		assert_ok!(Salp::fund_success(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::unlock(Some(BRUCE).into(), BRUCE, 3_000));
+
+		// Mock the BlockNumber
+		let block_begin_redeem = (SlotLength::get() + 1) * LeasePeriod::get();
+		System::set_block_number(block_begin_redeem.into());
+
+		assert_ok!(Salp::fund_retire(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::withdraw(Some(ALICE).into(), 3_000));
+
+		// Before withdraw
+		assert_noop!(
+			Salp::redeem(Some(BRUCE).into(), 3_000, 200),
+			Error::<Test>::NotEnoughBalanceInRedeemPool
+		);
+	});
+}
+
+#[test]
+fn redeem_with_when_ump_wrong_should_fail() {
+	// TODO: Require an solution to settle with parallel test workflow
+}
+
+#[test]
+fn release_from_redeem_to_bancor_should_work() {
+	fn run_to_block(n: BlockNumber) {
+		use frame_support::traits::Hooks;
+		while System::block_number() <= n.into() {
+			Salp::on_finalize(System::block_number());
+			System::on_finalize(System::block_number());
+			System::set_block_number(System::block_number() + 1);
+			System::on_initialize(System::block_number());
+			Salp::on_initialize(System::block_number());
+		}
+	}
+
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_ok!(Salp::contribute(Some(BRUCE).into(), 3_000, 100));
+		Salp::bind_query_id_and_contribution(0, 3_000, BRUCE, 100);
+		assert_ok!(Salp::confirm_contribute(Some(ALICE).into(), 0, true,));
+		assert_ok!(Salp::fund_success(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::unlock(Some(BRUCE).into(), BRUCE, 3_000));
+		assert_ok!(Salp::fund_retire(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::withdraw(Some(ALICE).into(), 3_000));
+
+		run_to_block(ReleaseCycle::get());
+
+		// TODO: Check the balance of bancor(Waiting Bancor to Support..)
+	});
+}
+
+// Utilities Test
+#[test]
+fn check_next_trie_index() {
+	new_test_ext().execute_with(|| {
+		for i in 0..100 {
+			assert_eq!(CurrentTrieIndex::<Test>::get(), i);
+			assert_ok!(Salp::next_trie_index());
+		}
+	});
+}
+
+#[test]
+fn batch_unlock_should_work() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_ok!(Salp::contribute(Some(BRUCE).into(), 3_000, 100));
+		Salp::bind_query_id_and_contribution(0, 3_000, BRUCE, 100);
+		assert_ok!(Salp::confirm_contribute(Some(ALICE).into(), 0, true,));
+		assert_ok!(Salp::fund_success(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::batch_unlock(Some(ALICE).into(), 3_000));
+	})
+}
+
+#[test]
+fn unlock_when_fund_ongoing_should_work() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_ok!(Salp::contribute(Some(BRUCE).into(), 3_000, 100));
+		Salp::bind_query_id_and_contribution(0, 3_000, BRUCE, 100);
+		assert_ok!(Salp::confirm_contribute(Some(ALICE).into(), 0, true,));
+		assert_ok!(Salp::unlock(Some(BRUCE).into(), BRUCE, 3_000));
+
+		let vs_token =
+			<Test as Config>::CurrencyIdConversion::convert_to_vstoken(RelayCurrencyId::get())
+				.unwrap();
+		let vs_bond = <Test as Config>::CurrencyIdConversion::convert_to_vsbond(
+			RelayCurrencyId::get(),
+			3_000,
+			1,
+			SlotLength::get(),
+		)
+		.unwrap();
+
+		assert_eq!(Tokens::accounts(BRUCE, vs_token).free, 100);
+		assert_eq!(Tokens::accounts(BRUCE, vs_token).frozen, 0);
+		assert_eq!(Tokens::accounts(BRUCE, vs_token).reserved, 0);
+		assert_eq!(Tokens::accounts(BRUCE, vs_bond).free, 100);
+		assert_eq!(Tokens::accounts(BRUCE, vs_bond).frozen, 0);
+		assert_eq!(Tokens::accounts(BRUCE, vs_bond).reserved, 0);
+	});
+}
+
+#[test]
+fn set_confirmor_should_work() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_ok!(Salp::contribute(Some(BRUCE).into(), 3_000, 100));
+		Salp::bind_query_id_and_contribution(0, 3_000, BRUCE, 100);
+		assert_noop!(
+			Salp::confirm_contribute(Some(BRUCE).into(), 0, true),
+			DispatchError::BadOrigin,
+		);
+		assert_ok!(Salp::set_multisig_confirm_account(Some(ALICE).into(), BRUCE));
+		assert_ok!(Salp::confirm_contribute(Some(BRUCE).into(), 0, true,));
+	});
+}
+
+#[test]
+fn refund_meanwhile_issue_should_work() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_ok!(Salp::contribute(Some(BRUCE).into(), 3_000, 100));
+		Salp::bind_query_id_and_contribution(0, 3_000, BRUCE, 100);
+		assert_ok!(Salp::confirm_contribute(Some(ALICE).into(), 0, true,));
+		assert_ok!(Salp::fund_fail(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::withdraw(Some(ALICE).into(), 3_000));
+		let vs_bond_old = <Test as Config>::CurrencyIdConversion::convert_to_vsbond(
+			RelayCurrencyId::get(),
+			3_000,
+			1,
+			SlotLength::get(),
+		)
+		.unwrap();
+		assert_eq!(Tokens::accounts(BRUCE, vs_bond_old).free, 100);
+		assert_eq!(
+			<Test as Config>::CurrencyIdRegister::check_vsbond_registered(
+				TokenSymbol::KSM,
+				3_000,
+				2,
+				SlotLength::get() + 1
+			),
+			false
+		);
+		assert_ok!(Salp::continue_fund(Some(ALICE).into(), 3_000, 2, SlotLength::get() + 1));
+		assert_eq!(
+			<Test as Config>::CurrencyIdRegister::check_vsbond_registered(
+				TokenSymbol::KSM,
+				3_000,
+				2,
+				SlotLength::get() + 1
+			),
+			true
+		);
+		let old_fund = FailedFundsToRefund::<Test>::get((3_000, 1, SlotLength::get())).unwrap();
+		assert_eq!(old_fund.first_slot, 1);
+		assert_eq!(old_fund.raised, 100);
+		let mut new_fund = Funds::<Test>::get(3_000).unwrap();
+		assert_eq!(new_fund.first_slot, 2);
+		assert_eq!(new_fund.raised, 100);
+		let vs_bond_new = <Test as Config>::CurrencyIdConversion::convert_to_vsbond(
+			RelayCurrencyId::get(),
+			3_000,
+			2,
+			SlotLength::get() + 1,
+		)
+		.unwrap();
+		assert_ok!(Salp::contribute(Some(BRUCE).into(), 3_000, 100));
+		Salp::bind_query_id_and_contribution(0, 3_000, BRUCE, 100);
+		assert_ok!(Salp::confirm_contribute(Some(ALICE).into(), 0, true,));
+		new_fund = Funds::<Test>::get(3_000).unwrap();
+		assert_eq!(new_fund.raised, 200);
+		assert_eq!(Tokens::accounts(BRUCE, vs_bond_new).free, 100);
+		// refund from old failed fund should success
+		assert_ok!(Salp::refund(Some(BRUCE).into(), 3_000, 1, SlotLength::get(), 50));
+		assert_eq!(Tokens::accounts(BRUCE, vs_bond_old).free, 50);
+		// refund from new fund should failed
+		assert_noop!(
+			Salp::refund(Some(BRUCE).into(), 3_000, 2, SlotLength::get() + 1, 100),
+			Error::<Test>::InvalidRefund,
+		);
+		// refund from not exist fund should failed
+		assert_noop!(
+			Salp::refund(Some(BRUCE).into(), 4_000, 2, SlotLength::get() + 1, 100),
+			Error::<Test>::InvalidFundNotExist,
+		);
+		// after dissolve failed fund refund from old should fail
+		assert_ok!(Salp::dissolve_refunded(Some(ALICE).into(), 3_000, 1, SlotLength::get()));
+		assert_noop!(
+			Salp::refund(Some(BRUCE).into(), 3_000, 1, SlotLength::get(), 50),
+			Error::<Test>::InvalidRefund,
+		);
+		// after new fund finally success redeem should success
+		assert_ok!(Salp::fund_success(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::fund_retire(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::withdraw(Some(ALICE).into(), 3_000));
+		assert_eq!(
+			Tokens::accounts(Salp::fund_account_id(3_000), RelayCurrencyId::get()).free,
+			150
+		);
+		assert_ok!(Salp::redeem(Some(BRUCE).into(), 3_000, 50));
+		assert_eq!(Tokens::accounts(BRUCE, vs_bond_new).free, 50);
+		// after fund dissolved redeem should fail
+		assert_ok!(Salp::fund_end(Some(ALICE).into(), 3_000));
+		assert_eq!(
+			Tokens::accounts(Salp::fund_account_id(3_000), RelayCurrencyId::get()).free,
+			100
+		);
+		assert_ok!(Salp::dissolve(Some(ALICE).into(), 3_000));
+		assert_eq!(Tokens::accounts(Salp::fund_account_id(3_000), RelayCurrencyId::get()).free, 0);
+		let treasury_account: AccountId = TreasuryAccount::get();
+		assert_eq!(Tokens::accounts(treasury_account, RelayCurrencyId::get()).free, 25);
+		let buyback_account: AccountId = BuybackPalletId::get().into_account_truncating();
+		assert_eq!(Tokens::accounts(buyback_account.clone(), RelayCurrencyId::get()).free, 75);
+		assert_noop!(Salp::redeem(Some(BRUCE).into(), 3_000, 50), Error::<Test>::InvalidParaId);
+
+		let para_id = 2001u32;
+		let asset_0_currency_id: AssetId =
+			AssetId::try_convert_from(RelayCurrencyId::get(), para_id).unwrap();
+		let asset_1_currency_id: AssetId =
+			AssetId::try_convert_from(CurrencyId::VSToken(TokenSymbol::KSM), para_id).unwrap();
+		assert_ok!(ZenlinkProtocol::create_pair(
+			RuntimeOrigin::root(),
+			asset_0_currency_id,
+			asset_1_currency_id,
+			ALICE
+		));
+		let deadline: BlockNumberFor<Test> =
+			<frame_system::Pallet<Test>>::block_number() + BlockNumberFor::<Test>::from(100u32);
+		assert_ok!(ZenlinkProtocol::add_liquidity(
+			RuntimeOrigin::signed(ALICE),
+			asset_0_currency_id,
+			asset_1_currency_id,
+			1000,
+			2200,
+			1,
+			1,
+			deadline
+		));
+		assert_noop!(
+			Salp::buyback(Some(ALICE).into(), 80),
+			orml_tokens::Error::<Test>::BalanceTooLow
+		);
+		assert_ok!(Salp::buyback(Some(ALICE).into(), 70));
+		assert_noop!(
+			Salp::buyback(Some(ALICE).into(), 10),
+			zenlink_protocol::Error::<Test>::InsufficientTargetAmount
+		);
+
+		let amounts = vec![1_000u128, 1_000u128];
+		assert_ok!(StablePool::create_pool(
+			RuntimeOrigin::signed(ALICE),
+			vec![KSM, VKSM],
+			vec![1u128.into(), 1u128.into()],
+			0u128.into(),
+			0u128.into(),
+			0u128.into(),
+			220u128.into(),
+			ALICE,
+			ALICE,
+			1000000000000u128.into()
+		));
+		assert_ok!(StablePool::edit_token_rate(
+			RuntimeOrigin::signed(ALICE),
+			0,
+			vec![(KSM, (1, 1)), (VKSM, (10, 11))]
+		));
+		assert_ok!(StablePool::add_liquidity(
+			RuntimeOrigin::signed(ALICE).into(),
+			0,
+			amounts.clone(),
+			0
+		));
+		assert_ok!(StablePool::create_pool(
+			RuntimeOrigin::signed(ALICE),
+			vec![KSM, VSKSM],
+			vec![1u128.into(), 1u128.into()],
+			0u128.into(),
+			0u128.into(),
+			0u128.into(),
+			220u128.into(),
+			ALICE,
+			ALICE,
+			1000000000000u128.into()
+		));
+		assert_ok!(StablePool::edit_token_rate(
+			RuntimeOrigin::signed(ALICE),
+			1,
+			vec![(VSKSM, (1, 1)), (KSM, (10, 30))]
+		));
+		assert_ok!(StablePool::add_liquidity(
+			RuntimeOrigin::signed(ALICE).into(),
+			1,
+			amounts.clone(),
+			0
+		));
+		assert_ok!(StablePool::create_pool(
+			RuntimeOrigin::signed(ALICE),
+			vec![VSKSM, VKSM],
+			vec![1u128.into(), 1u128.into()],
+			0u128.into(),
+			0u128.into(),
+			0u128.into(),
+			220u128.into(),
+			ALICE,
+			ALICE,
+			1000000000000u128.into()
+		));
+		assert_ok!(StablePool::edit_token_rate(
+			RuntimeOrigin::signed(ALICE),
+			2,
+			vec![(VSKSM, (1, 1)), (VKSM, (10, 11))]
+		));
+		assert_ok!(StablePool::add_liquidity(RuntimeOrigin::signed(ALICE).into(), 2, amounts, 0));
+
+		assert_ok!(VtokenMinting::set_minimum_mint(RuntimeOrigin::signed(ALICE), KSM, 0));
+		assert_ok!(VtokenMinting::mint(
+			Some(ALICE).into(),
+			KSM,
+			2_000,
+			BoundedVec::default(),
+			None
+		));
+		assert_ok!(Tokens::set_balance(RuntimeOrigin::root(), ALICE, VKSM, 0, 0));
+		assert_noop!(
+			Salp::buyback_vstoken_by_stable_pool(Some(ALICE).into(), 0, VKSM, 70),
+			Error::<Test>::ArgumentsError
+		);
+		assert_noop!(
+			Salp::buyback_vstoken_by_stable_pool(Some(ALICE).into(), 1, KSM, 100),
+			orml_tokens::Error::<Test>::BalanceTooLow
+		);
+		let token_value = VtokenMinting::token_to_vtoken(KSM, VKSM, 100);
+		assert_eq!(token_value, Ok(100));
+		assert_eq!(Tokens::free_balance(KSM, &ALICE), 95000);
+		assert_ok!(Tokens::set_balance(RuntimeOrigin::root(), buyback_account, KSM, 100, 0));
+
+		assert_ok!(Salp::buyback_vstoken_by_stable_pool(Some(BRUCE).into(), 1, KSM, 100));
+		assert_eq!(Tokens::free_balance(VSKSM, &BRUCE), 100);
+	});
+}
+
+#[test]
+fn edit_fund_should_work() {
+	new_test_ext().execute_with(|| {
+		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+		assert_ok!(Salp::contribute(Some(BRUCE).into(), 3_000, 100));
+		Salp::bind_query_id_and_contribution(0, 3_000, BRUCE, 100);
+		assert_ok!(Salp::confirm_contribute(Some(ALICE).into(), 0, true,));
+		assert_ok!(Salp::fund_fail(Some(ALICE).into(), 3_000));
+		let mut fund = Funds::<Test>::get(3_000).unwrap();
+		assert_eq!(fund.raised, 100);
+
+		assert_ok!(Salp::edit(
+			Some(ALICE).into(),
+			3_000,
+			1_000,
+			150,
+			2,
+			SlotLength::get() + 1,
+			Some(FundStatus::Ongoing)
+		));
+		fund = Funds::<Test>::get(3_000).unwrap();
+		assert_eq!(fund.raised, 150);
+		assert_eq!(fund.status, FundStatus::Ongoing);
+	});
+}
+
+fn reserve_init() -> (CurrencyId, CurrencyId) {
+	assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
+	assert_ok!(Salp::contribute(Some(BRUCE).into(), 3_000, 100));
+	Salp::bind_query_id_and_contribution(0, 3_000, BRUCE, 100);
+	assert_ok!(Salp::confirm_contribute(Some(ALICE).into(), 0, true,));
+
+	assert_ok!(Salp::fund_success(Some(ALICE).into(), 3_000));
+	assert_ok!(Salp::unlock(Some(BRUCE).into(), BRUCE, 3_000));
+
+	// Mock the BlockNumber
+	let block_begin_redeem = (SlotLength::get() + 1) * LeasePeriod::get();
+	System::set_block_number(block_begin_redeem.into());
+
+	let vs_token =
+		<Test as Config>::CurrencyIdConversion::convert_to_vstoken(RelayCurrencyId::get()).unwrap();
+	let vs_bond = <Test as Config>::CurrencyIdConversion::convert_to_vsbond(
+		RelayCurrencyId::get(),
+		3_000,
+		1,
+		SlotLength::get(),
+	)
+	.unwrap();
+	(vs_token, vs_bond)
+}
+
+#[test]
+fn batch_handle_reserve_should_work() {
+	new_test_ext().execute_with(|| {
+		let (vs_token, vs_bond) = reserve_init();
+
+		assert_ok!(Salp::reserve(Some(BRUCE).into(), 3_000, 50, false));
+		assert_ok!(<Tokens as MultiCurrency<AccountId>>::transfer(vs_token, &BRUCE, &CATHI, 50));
+		assert_ok!(<Tokens as MultiCurrency<AccountId>>::transfer(vs_bond, &BRUCE, &CATHI, 50));
+		assert_ok!(Salp::reserve(Some(CATHI).into(), 3_000, 10, false));
+		assert_ok!(Salp::reserve(Some(CATHI).into(), 3_000, 40, false));
+		assert_eq!(Tokens::accounts(CATHI, vs_token).frozen, 50);
+		assert_ok!(Salp::fund_retire(Some(ALICE).into(), 3_000));
+		assert_ok!(Salp::withdraw(Some(ALICE).into(), 3_000));
+
+		assert_eq!(Tokens::accounts(BRUCE, vs_token).free, 50);
+		assert_ok!(Salp::batch_handle_reserve(Some(BRUCE).into(), 3_000));
+		assert_eq!(ReserveInfos::<Test>::get(3_000, BRUCE).value, 0);
+
+		assert_eq!(Tokens::accounts(BRUCE, vs_token).free, 0);
+		assert_eq!(Tokens::accounts(BRUCE, vs_token).frozen, 0);
+		assert_eq!(Tokens::accounts(BRUCE, vs_token).reserved, 0);
+		assert_eq!(Tokens::accounts(BRUCE, vs_bond).free, 0);
+		assert_eq!(Tokens::accounts(BRUCE, vs_bond).frozen, 0);
+		assert_eq!(Tokens::accounts(BRUCE, vs_bond).reserved, 0);
+		assert_eq!(Tokens::accounts(BRUCE, RelayCurrencyId::get()).free, INIT_BALANCE - 50);
+		assert_eq!(Tokens::accounts(BRUCE, RelayCurrencyId::get()).frozen, 0);
+		assert_eq!(Tokens::accounts(BRUCE, RelayCurrencyId::get()).reserved, 0);
+
+		assert_eq!(Tokens::accounts(CATHI, vs_token).free, 0);
+		assert_eq!(Tokens::accounts(CATHI, vs_token).frozen, 0);
+		assert_eq!(Tokens::accounts(CATHI, vs_token).reserved, 0);
+		assert_eq!(Tokens::accounts(CATHI, vs_bond).free, 0);
+		assert_eq!(Tokens::accounts(CATHI, vs_bond).frozen, 0);
+		assert_eq!(Tokens::accounts(CATHI, vs_bond).reserved, 0);
+		assert_eq!(Tokens::accounts(CATHI, RelayCurrencyId::get()).free, INIT_BALANCE + 50);
+		assert_eq!(Tokens::accounts(CATHI, RelayCurrencyId::get()).frozen, 0);
+		assert_eq!(Tokens::accounts(CATHI, RelayCurrencyId::get()).reserved, 0);
+	});
+}
+
+#[test]
+fn batch_handle_reserve_should_fail() {
+	new_test_ext().execute_with(|| {
+		let (_vs_token, _vs_bond) = reserve_init();
+
+		assert_noop!(
+			Salp::batch_handle_reserve(Some(BRUCE).into(), 3_000),
+			Error::<Test>::InvalidFundStatus,
+		);
+		assert_ok!(Salp::reserve(Some(BRUCE).into(), 3_000, 100, false));
+		assert_noop!(
+			Salp::batch_handle_reserve(Some(BRUCE).into(), 3_000),
+			Error::<Test>::InvalidFundStatus,
+		);
+	});
+}
+
+#[test]
+fn reserve_should_fail() {
+	new_test_ext().execute_with(|| {
+		let (_vs_token, _vs_bond) = reserve_init();
+
+		assert_noop!(
+			Salp::reserve(Some(CATHI).into(), 3_000, 10, false),
+			orml_tokens::Error::<Test>::BalanceTooLow,
+		);
+	});
+}
+
+#[test]
+fn reserve_should_work() {
+	new_test_ext().execute_with(|| {
+		let (vs_token, _vs_bond) = reserve_init();
+
+		assert_eq!(Tokens::accounts(BRUCE, vs_token).frozen, 0);
+		assert_ok!(Salp::reserve(Some(BRUCE).into(), 3_000, 100, false));
+		assert_eq!(Tokens::accounts(BRUCE, vs_token).frozen, 100);
+		assert_eq!(Tokens::accounts(BRUCE, vs_token).free, 100);
+		assert_ok!(Salp::cancel_reservation(Some(BRUCE).into(), 3_000));
+		assert_ok!(Salp::cancel_reservation(Some(BRUCE).into(), 3_000));
+		assert_eq!(Tokens::accounts(BRUCE, vs_token).frozen, 0);
+		assert_ok!(Salp::reserve(Some(BRUCE).into(), 3_000, 50, false));
+		assert_eq!(ReserveInfos::<Test>::get(3_000, BRUCE).value, 50);
+		assert_eq!(Tokens::accounts(BRUCE, vs_token).frozen, 50);
+		assert_eq!(Tokens::accounts(BRUCE, vs_token).free, 100);
+	});
+}
diff --git a/pallets/deprecated/salp/src/weights.rs b/pallets/deprecated/salp/src/weights.rs
new file mode 100644
index 000000000..50abb1130
--- /dev/null
+++ b/pallets/deprecated/salp/src/weights.rs
@@ -0,0 +1,458 @@
+// 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 <https://www.gnu.org/licenses/>.
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! Autogenerated weights for bifrost_salp
+//!
+//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
+//! DATE: 2023-09-14, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! HOSTNAME: `bifrost-jenkins`, CPU: `Intel(R) Xeon(R) CPU E5-26xx v4`
+//! WASM-EXECUTION: Compiled, CHAIN: Some("bifrost-kusama-local"), DB CACHE: 1024
+
+// Executed Command:
+// target/release/bifrost
+// benchmark
+// pallet
+// --chain=bifrost-kusama-local
+// --steps=50
+// --repeat=20
+// --pallet=bifrost_salp
+// --extrinsic=*
+// --execution=wasm
+// --wasm-execution=compiled
+// --heap-pages=4096
+// --output=./pallets/salp/src/weights.rs
+// --template=./weight-template/pallet-weight-template.hbs
+
+#![cfg_attr(rustfmt, rustfmt_skip)]
+#![allow(unused_parens)]
+#![allow(unused_imports)]
+
+use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
+use sp_std::marker::PhantomData;
+
+/// Weight functions needed for bifrost_salp.
+pub trait WeightInfo {
+	fn contribute() -> Weight;
+	fn refund() -> Weight;
+	fn unlock() -> Weight;
+	fn batch_unlock() -> Weight;
+	fn redeem() -> Weight;
+	fn set_multisig_confirm_account() -> Weight;
+	fn fund_success() -> Weight;
+	fn fund_fail() -> Weight;
+	fn continue_fund() -> Weight;
+	fn fund_retire() -> Weight;
+	fn fund_end() -> Weight;
+	fn create() -> Weight;
+	fn edit() -> Weight;
+	fn confirm_contribute() -> Weight;
+	fn withdraw() -> Weight;
+	fn dissolve_refunded() -> Weight;
+	fn dissolve() -> Weight;
+	fn buyback() -> Weight;
+	fn buyback_vstoken_by_stable_pool() -> Weight;
+	fn reserve() -> Weight;
+	fn batch_handle_reserve() -> Weight;
+	fn cancel_reservation() -> Weight;
+}
+
+// For backwards compatibility and tests
+impl WeightInfo for () {
+	/// Storage: Salp Funds (r:1 w:0)
+	/// Proof Skipped: Salp Funds (max_values: None, max_size: None, mode: Measured)
+	/// Storage: AssetRegistry CurrencyMetadatas (r:1 w:0)
+	/// Proof Skipped: AssetRegistry CurrencyMetadatas (max_values: None, max_size: None, mode: Measured)
+	/// Storage: Tokens Accounts (r:1 w:1)
+	/// Proof: Tokens Accounts (max_values: None, max_size: Some(118), added: 2593, mode: MaxEncodedLen)
+	/// Storage: XcmInterface XcmWeightAndFee (r:1 w:0)
+	/// Proof Skipped: XcmInterface XcmWeightAndFee (max_values: None, max_size: None, mode: Measured)
+	/// Storage: PolkadotXcm QueryCounter (r:1 w:1)
+	/// Proof Skipped: PolkadotXcm QueryCounter (max_values: Some(1), max_size: None, mode: Measured)
+	/// Storage: ParachainInfo ParachainId (r:1 w:0)
+	/// Proof: ParachainInfo ParachainId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen)
+	/// Storage: Salp QueryIdContributionInfo (r:0 w:1)
+	/// Proof Skipped: Salp QueryIdContributionInfo (max_values: None, max_size: None, mode: Measured)
+	/// Storage: PolkadotXcm Queries (r:0 w:1)
+	/// Proof Skipped: PolkadotXcm Queries (max_values: None, max_size: None, mode: Measured)
+	/// Storage: unknown `0xd861ea1ebf4800d4b89f4ff787ad79ee96d9a708c85b57da7eb8f9ddeda61291` (r:1 w:1)
+	/// Proof Skipped: unknown `0xd861ea1ebf4800d4b89f4ff787ad79ee96d9a708c85b57da7eb8f9ddeda61291` (r:1 w:1)
+	fn contribute() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `2252`
+		//  Estimated: `5717`
+		// Minimum execution time: 175_000_000 picoseconds.
+		Weight::from_parts(177_879_000, 5717)
+			.saturating_add(RocksDbWeight::get().reads(7_u64))
+			.saturating_add(RocksDbWeight::get().writes(5_u64))
+	}
+	/// Storage: Salp FailedFundsToRefund (r:1 w:0)
+	/// Proof Skipped: Salp FailedFundsToRefund (max_values: None, max_size: None, mode: Measured)
+	/// Storage: Salp Funds (r:1 w:1)
+	/// Proof Skipped: Salp Funds (max_values: None, max_size: None, mode: Measured)
+	/// Storage: Salp RedeemPool (r:1 w:1)
+	/// Proof Skipped: Salp RedeemPool (max_values: Some(1), max_size: None, mode: Measured)
+	/// Storage: Tokens Accounts (r:4 w:4)
+	/// Proof: Tokens Accounts (max_values: None, max_size: Some(118), added: 2593, mode: MaxEncodedLen)
+	/// Storage: AssetRegistry CurrencyMetadatas (r:1 w:0)
+	/// Proof Skipped: AssetRegistry CurrencyMetadatas (max_values: None, max_size: None, mode: Measured)
+	/// Storage: Tokens TotalIssuance (r:2 w:2)
+	/// Proof: Tokens TotalIssuance (max_values: None, max_size: Some(38), added: 2513, mode: MaxEncodedLen)
+	/// Storage: System Account (r:1 w:1)
+	/// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen)
+	fn refund() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `2375`
+		//  Estimated: `11362`
+		// Minimum execution time: 267_454_000 picoseconds.
+		Weight::from_parts(270_319_000, 11362)
+			.saturating_add(RocksDbWeight::get().reads(11_u64))
+			.saturating_add(RocksDbWeight::get().writes(9_u64))
+	}
+	/// Storage: Salp Funds (r:1 w:0)
+	/// Proof Skipped: Salp Funds (max_values: None, max_size: None, mode: Measured)
+	/// Storage: Tokens Accounts (r:2 w:2)
+	/// Proof: Tokens Accounts (max_values: None, max_size: Some(118), added: 2593, mode: MaxEncodedLen)
+	/// Storage: AssetRegistry CurrencyMetadatas (r:1 w:0)
+	/// Proof Skipped: AssetRegistry CurrencyMetadatas (max_values: None, max_size: None, mode: Measured)
+	/// Storage: unknown `0xd861ea1ebf4800d4b89f4ff787ad79ee96d9a708c85b57da7eb8f9ddeda61291` (r:1 w:0)
+	/// Proof Skipped: unknown `0xd861ea1ebf4800d4b89f4ff787ad79ee96d9a708c85b57da7eb8f9ddeda61291` (r:1 w:0)
+	fn unlock() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `1962`
+		//  Estimated: `6176`
+		// Minimum execution time: 129_578_000 picoseconds.
+		Weight::from_parts(130_658_000, 6176)
+			.saturating_add(RocksDbWeight::get().reads(5_u64))
+			.saturating_add(RocksDbWeight::get().writes(2_u64))
+	}
+	/// Storage: Salp Funds (r:1 w:0)
+	/// Proof Skipped: Salp Funds (max_values: None, max_size: None, mode: Measured)
+	/// Storage: Tokens Accounts (r:2 w:2)
+	/// Proof: Tokens Accounts (max_values: None, max_size: Some(118), added: 2593, mode: MaxEncodedLen)
+	/// Storage: AssetRegistry CurrencyMetadatas (r:1 w:0)
+	/// Proof Skipped: AssetRegistry CurrencyMetadatas (max_values: None, max_size: None, mode: Measured)
+	/// Storage: unknown `0x` (r:1 w:0)
+	/// Proof Skipped: unknown `0x` (r:1 w:0)
+	/// Storage: unknown `0xd861ea1ebf4800d4b89f4ff787ad79ee96d9a708c85b57da7eb8f9ddeda61291` (r:1 w:0)
+	/// Proof Skipped: unknown `0xd861ea1ebf4800d4b89f4ff787ad79ee96d9a708c85b57da7eb8f9ddeda61291` (r:1 w:0)
+	fn batch_unlock() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `1995`
+		//  Estimated: `6176`
+		// Minimum execution time: 143_054_000 picoseconds.
+		Weight::from_parts(146_914_000, 6176)
+			.saturating_add(RocksDbWeight::get().reads(6_u64))
+			.saturating_add(RocksDbWeight::get().writes(2_u64))
+	}
+	/// Storage: Salp Funds (r:1 w:1)
+	/// Proof Skipped: Salp Funds (max_values: None, max_size: None, mode: Measured)
+	/// Storage: Salp RedeemPool (r:1 w:1)
+	/// Proof Skipped: Salp RedeemPool (max_values: Some(1), max_size: None, mode: Measured)
+	/// Storage: Tokens Accounts (r:4 w:4)
+	/// Proof: Tokens Accounts (max_values: None, max_size: Some(118), added: 2593, mode: MaxEncodedLen)
+	/// Storage: AssetRegistry CurrencyMetadatas (r:1 w:0)
+	/// Proof Skipped: AssetRegistry CurrencyMetadatas (max_values: None, max_size: None, mode: Measured)
+	/// Storage: Tokens TotalIssuance (r:2 w:2)
+	/// Proof: Tokens TotalIssuance (max_values: None, max_size: Some(38), added: 2513, mode: MaxEncodedLen)
+	/// Storage: System Account (r:1 w:1)
+	/// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen)
+	fn redeem() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `2356`
+		//  Estimated: `11362`
+		// Minimum execution time: 255_416_000 picoseconds.
+		Weight::from_parts(257_010_000, 11362)
+			.saturating_add(RocksDbWeight::get().reads(10_u64))
+			.saturating_add(RocksDbWeight::get().writes(9_u64))
+	}
+	/// Storage: Salp MultisigConfirmAccount (r:0 w:1)
+	/// Proof Skipped: Salp MultisigConfirmAccount (max_values: Some(1), max_size: None, mode: Measured)
+	fn set_multisig_confirm_account() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `0`
+		//  Estimated: `0`
+		// Minimum execution time: 10_258_000 picoseconds.
+		Weight::from_parts(10_624_000, 0)
+			.saturating_add(RocksDbWeight::get().writes(1_u64))
+	}
+	/// Storage: Salp Funds (r:1 w:1)
+	/// Proof Skipped: Salp Funds (max_values: None, max_size: None, mode: Measured)
+	fn fund_success() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `292`
+		//  Estimated: `3757`
+		// Minimum execution time: 42_399_000 picoseconds.
+		Weight::from_parts(43_690_000, 3757)
+			.saturating_add(RocksDbWeight::get().reads(1_u64))
+			.saturating_add(RocksDbWeight::get().writes(1_u64))
+	}
+	/// Storage: Salp Funds (r:1 w:1)
+	/// Proof Skipped: Salp Funds (max_values: None, max_size: None, mode: Measured)
+	fn fund_fail() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `292`
+		//  Estimated: `3757`
+		// Minimum execution time: 42_250_000 picoseconds.
+		Weight::from_parts(42_892_000, 3757)
+			.saturating_add(RocksDbWeight::get().reads(1_u64))
+			.saturating_add(RocksDbWeight::get().writes(1_u64))
+	}
+	/// Storage: Salp Funds (r:1 w:1)
+	/// Proof Skipped: Salp Funds (max_values: None, max_size: None, mode: Measured)
+	/// Storage: AssetRegistry CurrencyMetadatas (r:2 w:1)
+	/// Proof Skipped: AssetRegistry CurrencyMetadatas (max_values: None, max_size: None, mode: Measured)
+	/// Storage: Salp FailedFundsToRefund (r:0 w:1)
+	/// Proof Skipped: Salp FailedFundsToRefund (max_values: None, max_size: None, mode: Measured)
+	fn continue_fund() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `1061`
+		//  Estimated: `7001`
+		// Minimum execution time: 99_887_000 picoseconds.
+		Weight::from_parts(101_067_000, 7001)
+			.saturating_add(RocksDbWeight::get().reads(3_u64))
+			.saturating_add(RocksDbWeight::get().writes(3_u64))
+	}
+	/// Storage: Salp Funds (r:1 w:1)
+	/// Proof Skipped: Salp Funds (max_values: None, max_size: None, mode: Measured)
+	fn fund_retire() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `292`
+		//  Estimated: `3757`
+		// Minimum execution time: 40_648_000 picoseconds.
+		Weight::from_parts(43_146_000, 3757)
+			.saturating_add(RocksDbWeight::get().reads(1_u64))
+			.saturating_add(RocksDbWeight::get().writes(1_u64))
+	}
+	/// Storage: Salp Funds (r:1 w:1)
+	/// Proof Skipped: Salp Funds (max_values: None, max_size: None, mode: Measured)
+	fn fund_end() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `325`
+		//  Estimated: `3790`
+		// Minimum execution time: 41_871_000 picoseconds.
+		Weight::from_parts(42_961_000, 3790)
+			.saturating_add(RocksDbWeight::get().reads(1_u64))
+			.saturating_add(RocksDbWeight::get().writes(1_u64))
+	}
+	/// Storage: Salp Funds (r:1 w:1)
+	/// Proof Skipped: Salp Funds (max_values: None, max_size: None, mode: Measured)
+	/// Storage: Salp CurrentTrieIndex (r:1 w:1)
+	/// Proof Skipped: Salp CurrentTrieIndex (max_values: Some(1), max_size: None, mode: Measured)
+	/// Storage: AssetRegistry CurrencyMetadatas (r:2 w:1)
+	/// Proof Skipped: AssetRegistry CurrencyMetadatas (max_values: None, max_size: None, mode: Measured)
+	fn create() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `833`
+		//  Estimated: `6773`
+		// Minimum execution time: 81_834_000 picoseconds.
+		Weight::from_parts(84_230_000, 6773)
+			.saturating_add(RocksDbWeight::get().reads(4_u64))
+			.saturating_add(RocksDbWeight::get().writes(3_u64))
+	}
+	/// Storage: Salp Funds (r:1 w:1)
+	/// Proof Skipped: Salp Funds (max_values: None, max_size: None, mode: Measured)
+	fn edit() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `292`
+		//  Estimated: `3757`
+		// Minimum execution time: 39_217_000 picoseconds.
+		Weight::from_parts(39_954_000, 3757)
+			.saturating_add(RocksDbWeight::get().reads(1_u64))
+			.saturating_add(RocksDbWeight::get().writes(1_u64))
+	}
+	/// Storage: Salp MultisigConfirmAccount (r:1 w:0)
+	/// Proof Skipped: Salp MultisigConfirmAccount (max_values: Some(1), max_size: None, mode: Measured)
+	/// Storage: Salp QueryIdContributionInfo (r:1 w:1)
+	/// Proof Skipped: Salp QueryIdContributionInfo (max_values: None, max_size: None, mode: Measured)
+	/// Storage: Salp Funds (r:1 w:1)
+	/// Proof Skipped: Salp Funds (max_values: None, max_size: None, mode: Measured)
+	/// Storage: Tokens Accounts (r:4 w:4)
+	/// Proof: Tokens Accounts (max_values: None, max_size: Some(118), added: 2593, mode: MaxEncodedLen)
+	/// Storage: AssetRegistry CurrencyMetadatas (r:1 w:0)
+	/// Proof Skipped: AssetRegistry CurrencyMetadatas (max_values: None, max_size: None, mode: Measured)
+	/// Storage: Tokens TotalIssuance (r:2 w:2)
+	/// Proof: Tokens TotalIssuance (max_values: None, max_size: Some(38), added: 2513, mode: MaxEncodedLen)
+	/// Storage: System Account (r:1 w:1)
+	/// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen)
+	/// Storage: unknown `0xd861ea1ebf4800d4b89f4ff787ad79ee96d9a708c85b57da7eb8f9ddeda61291` (r:1 w:1)
+	/// Proof Skipped: unknown `0xd861ea1ebf4800d4b89f4ff787ad79ee96d9a708c85b57da7eb8f9ddeda61291` (r:1 w:1)
+	fn confirm_contribute() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `2556`
+		//  Estimated: `11362`
+		// Minimum execution time: 278_991_000 picoseconds.
+		Weight::from_parts(282_446_000, 11362)
+			.saturating_add(RocksDbWeight::get().reads(12_u64))
+			.saturating_add(RocksDbWeight::get().writes(10_u64))
+	}
+	/// Storage: Salp Funds (r:1 w:1)
+	/// Proof Skipped: Salp Funds (max_values: None, max_size: None, mode: Measured)
+	/// Storage: Salp RedeemPool (r:1 w:1)
+	/// Proof Skipped: Salp RedeemPool (max_values: Some(1), max_size: None, mode: Measured)
+	fn withdraw() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `325`
+		//  Estimated: `3790`
+		// Minimum execution time: 40_979_000 picoseconds.
+		Weight::from_parts(46_708_000, 3790)
+			.saturating_add(RocksDbWeight::get().reads(2_u64))
+			.saturating_add(RocksDbWeight::get().writes(2_u64))
+	}
+	/// Storage: Salp FailedFundsToRefund (r:1 w:1)
+	/// Proof Skipped: Salp FailedFundsToRefund (max_values: None, max_size: None, mode: Measured)
+	fn dissolve_refunded() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `403`
+		//  Estimated: `3868`
+		// Minimum execution time: 53_494_000 picoseconds.
+		Weight::from_parts(54_236_000, 3868)
+			.saturating_add(RocksDbWeight::get().reads(1_u64))
+			.saturating_add(RocksDbWeight::get().writes(1_u64))
+	}
+	/// Storage: Salp Funds (r:1 w:1)
+	/// Proof Skipped: Salp Funds (max_values: None, max_size: None, mode: Measured)
+	/// Storage: Tokens Accounts (r:3 w:3)
+	/// Proof: Tokens Accounts (max_values: None, max_size: Some(118), added: 2593, mode: MaxEncodedLen)
+	/// Storage: AssetRegistry CurrencyMetadatas (r:1 w:0)
+	/// Proof Skipped: AssetRegistry CurrencyMetadatas (max_values: None, max_size: None, mode: Measured)
+	/// Storage: System Account (r:3 w:3)
+	/// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen)
+	/// Storage: unknown `0x` (r:1 w:0)
+	/// Proof Skipped: unknown `0x` (r:1 w:0)
+	/// Storage: unknown `0xd861ea1ebf4800d4b89f4ff787ad79ee96d9a708c85b57da7eb8f9ddeda61291` (r:1 w:1)
+	/// Proof Skipped: unknown `0xd861ea1ebf4800d4b89f4ff787ad79ee96d9a708c85b57da7eb8f9ddeda61291` (r:1 w:1)
+	fn dissolve() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `2063`
+		//  Estimated: `8799`
+		// Minimum execution time: 253_989_000 picoseconds.
+		Weight::from_parts(256_988_000, 8799)
+			.saturating_add(RocksDbWeight::get().reads(10_u64))
+			.saturating_add(RocksDbWeight::get().writes(8_u64))
+	}
+	/// Storage: ParachainInfo ParachainId (r:1 w:0)
+	/// Proof: ParachainInfo ParachainId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen)
+	/// Storage: Tokens Accounts (r:4 w:4)
+	/// Proof: Tokens Accounts (max_values: None, max_size: Some(118), added: 2593, mode: MaxEncodedLen)
+	/// Storage: AssetRegistry CurrencyMetadatas (r:1 w:0)
+	/// Proof Skipped: AssetRegistry CurrencyMetadatas (max_values: None, max_size: None, mode: Measured)
+	/// Storage: System Account (r:3 w:1)
+	/// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen)
+	/// Storage: ZenlinkProtocol PairStatuses (r:1 w:0)
+	/// Proof Skipped: ZenlinkProtocol PairStatuses (max_values: None, max_size: None, mode: Measured)
+	fn buyback() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `2284`
+		//  Estimated: `11362`
+		// Minimum execution time: 241_398_000 picoseconds.
+		Weight::from_parts(244_975_000, 11362)
+			.saturating_add(RocksDbWeight::get().reads(10_u64))
+			.saturating_add(RocksDbWeight::get().writes(5_u64))
+	}
+	/// Storage: StableAsset Pools (r:1 w:1)
+	/// Proof Skipped: StableAsset Pools (max_values: None, max_size: None, mode: Measured)
+	/// Storage: Tokens Accounts (r:4 w:4)
+	/// Proof: Tokens Accounts (max_values: None, max_size: Some(118), added: 2593, mode: MaxEncodedLen)
+	/// Storage: StableAsset TokenRateCaches (r:2 w:0)
+	/// Proof Skipped: StableAsset TokenRateCaches (max_values: None, max_size: None, mode: Measured)
+	/// Storage: AssetRegistry CurrencyMetadatas (r:1 w:0)
+	/// Proof Skipped: AssetRegistry CurrencyMetadatas (max_values: None, max_size: None, mode: Measured)
+	/// Storage: System Account (r:2 w:1)
+	/// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen)
+	fn buyback_vstoken_by_stable_pool() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `2438`
+		//  Estimated: `11362`
+		// Minimum execution time: 361_674_000 picoseconds.
+		Weight::from_parts(370_099_000, 11362)
+			.saturating_add(RocksDbWeight::get().reads(10_u64))
+			.saturating_add(RocksDbWeight::get().writes(6_u64))
+	}
+	/// Storage: Salp Funds (r:1 w:0)
+	/// Proof Skipped: Salp Funds (max_values: None, max_size: None, mode: Measured)
+	/// Storage: Tokens Accounts (r:2 w:2)
+	/// Proof: Tokens Accounts (max_values: None, max_size: Some(118), added: 2593, mode: MaxEncodedLen)
+	/// Storage: Salp ReserveInfos (r:1 w:1)
+	/// Proof Skipped: Salp ReserveInfos (max_values: None, max_size: None, mode: Measured)
+	/// Storage: Tokens Locks (r:2 w:2)
+	/// Proof: Tokens Locks (max_values: None, max_size: Some(1271), added: 3746, mode: MaxEncodedLen)
+	/// Storage: AssetRegistry CurrencyMetadatas (r:1 w:0)
+	/// Proof Skipped: AssetRegistry CurrencyMetadatas (max_values: None, max_size: None, mode: Measured)
+	fn reserve() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `1737`
+		//  Estimated: `8482`
+		// Minimum execution time: 807_976_000 picoseconds.
+		Weight::from_parts(814_218_000, 0)
+			.saturating_add(Weight::from_parts(0, 8482))
+			.saturating_add(RocksDbWeight::get().reads(7))
+			.saturating_add(RocksDbWeight::get().writes(5))
+	}
+	/// Storage: Salp Funds (r:1 w:0)
+	/// Proof Skipped: Salp Funds (max_values: None, max_size: None, mode: Measured)
+	/// Storage: Tokens Locks (r:2 w:2)
+	/// Proof: Tokens Locks (max_values: None, max_size: Some(1271), added: 3746, mode: MaxEncodedLen)
+	/// Storage: Tokens Accounts (r:2 w:2)
+	/// Proof: Tokens Accounts (max_values: None, max_size: Some(118), added: 2593, mode: MaxEncodedLen)
+	/// Storage: AssetRegistry CurrencyMetadatas (r:1 w:0)
+	/// Proof Skipped: AssetRegistry CurrencyMetadatas (max_values: None, max_size: None, mode: Measured)
+	/// Storage: Salp ReserveInfos (r:0 w:1)
+	/// Proof Skipped: Salp ReserveInfos (max_values: None, max_size: None, mode: Measured)
+	fn cancel_reservation() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `1935`
+		//  Estimated: `8482`
+		// Minimum execution time: 853_491_000 picoseconds.
+		Weight::from_parts(858_070_000, 0)
+			.saturating_add(Weight::from_parts(0, 8482))
+			.saturating_add(RocksDbWeight::get().reads(6))
+			.saturating_add(RocksDbWeight::get().writes(5))
+	}
+	/// Storage: Salp Funds (r:1 w:1)
+	/// Proof Skipped: Salp Funds (max_values: None, max_size: None, mode: Measured)
+	/// Storage: Salp ReserveInfos (r:2 w:1)
+	/// Proof Skipped: Salp ReserveInfos (max_values: None, max_size: None, mode: Measured)
+	/// Storage: Tokens Locks (r:2 w:2)
+	/// Proof: Tokens Locks (max_values: None, max_size: Some(1271), added: 3746, mode: MaxEncodedLen)
+	/// Storage: Tokens Accounts (r:4 w:4)
+	/// Proof: Tokens Accounts (max_values: None, max_size: Some(118), added: 2593, mode: MaxEncodedLen)
+	/// Storage: AssetRegistry CurrencyMetadatas (r:1 w:0)
+	/// Proof Skipped: AssetRegistry CurrencyMetadatas (max_values: None, max_size: None, mode: Measured)
+	/// Storage: Salp RedeemPool (r:1 w:1)
+	/// Proof Skipped: Salp RedeemPool (max_values: Some(1), max_size: None, mode: Measured)
+	/// Storage: Tokens TotalIssuance (r:2 w:2)
+	/// Proof: Tokens TotalIssuance (max_values: None, max_size: Some(38), added: 2513, mode: MaxEncodedLen)
+	/// Storage: System Account (r:1 w:1)
+	/// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen)
+	fn batch_handle_reserve() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `2540`
+		//  Estimated: `11362`
+		// Minimum execution time: 1_848_798_000 picoseconds.
+		Weight::from_parts(1_859_469_000, 0)
+			.saturating_add(Weight::from_parts(0, 11362))
+			.saturating_add(RocksDbWeight::get().reads(14))
+			.saturating_add(RocksDbWeight::get().writes(12))
+	}
+}
diff --git a/pallets/flexible-fee/src/tests.rs b/pallets/flexible-fee/src/tests.rs
index ce373e01e..a365b46d4 100644
--- a/pallets/flexible-fee/src/tests.rs
+++ b/pallets/flexible-fee/src/tests.rs
@@ -327,49 +327,6 @@ fn correct_and_deposit_fee_should_work() {
 	});
 }
 
-#[test]
-fn correct_and_deposit_fee_with_tip() {
-	new_test_ext().execute_with(|| {
-		basic_setup();
-
-		let corrected_fee = 5 * 10u128.pow(12);
-		let tip = 5 * 10u128.pow(12);
-
-		assert_eq!(Currencies::free_balance(BNC, &ALICE), 1000 * 10u128.pow(12));
-
-		let already_withdrawn = Some(PaymentInfo::Native(10 * 10u128.pow(12)));
-		assert_ok!(FlexibleFee::correct_and_deposit_fee(
-			&ALICE,
-			&info(),
-			&post_info(),
-			corrected_fee,
-			tip,
-			already_withdrawn
-		));
-		assert_eq!(Currencies::free_balance(BNC, &ALICE), 1005 * 10u128.pow(12));
-
-		let corrected_fee = 10 * 10u128.pow(12);
-		let tip = 10 * 10u128.pow(12);
-		assert_eq!(Currencies::free_balance(DOT, &ALICE), 1000 * 10u128.pow(10));
-
-		let already_withdrawn = Some(PaymentInfo::NonNative(
-			1 * 10u128.pow(10),
-			DOT,
-			FixedU128::from_inner(200_000_000_000_000_000),
-			FixedU128::from(5),
-		));
-		assert_ok!(FlexibleFee::correct_and_deposit_fee(
-			&ALICE,
-			&info(),
-			&post_info(),
-			corrected_fee,
-			tip,
-			already_withdrawn
-		));
-		assert_eq!(Currencies::free_balance(DOT, &ALICE), 10006 * 10u128.pow(9));
-	});
-}
-
 #[test]
 fn get_currency_asset_id_should_work() {
 	new_test_ext().execute_with(|| {
diff --git a/pallets/salp/src/benchmarking.rs b/pallets/salp/src/benchmarking.rs
index cbb3f249b..a5d987e16 100644
--- a/pallets/salp/src/benchmarking.rs
+++ b/pallets/salp/src/benchmarking.rs
@@ -24,12 +24,11 @@ use bifrost_stable_pool::AtLeast64BitUnsignedOf;
 use bifrost_xcm_interface::XcmWeightAndFee;
 use frame_benchmarking::v2::*;
 use frame_support::assert_ok;
-use frame_system::{pallet_prelude::BlockNumberFor, RawOrigin};
+use frame_system::RawOrigin;
 use sp_runtime::{
-	traits::{AccountIdConversion, Bounded, StaticLookup, UniqueSaturatedFrom},
+	traits::{AccountIdConversion, Bounded, UniqueSaturatedFrom},
 	SaturatedConversion,
 };
-use sp_std::prelude::*;
 
 fn assert_last_event<T: Config>(generic_event: <T as Config>::RuntimeEvent) {
 	let events = frame_system::Pallet::<T>::events();
@@ -81,25 +80,7 @@ where T: Config + bifrost_stable_pool::Config + bifrost_stable_asset::Config + o
 )]
 mod benchmarks {
 	use super::*;
-
-	#[benchmark]
-	fn contribute() {
-		let fund_index = create_fund::<T>(1);
-		let caller: T::AccountId = whitelisted_caller();
-		let contribution = T::MinContribution::get();
-		XcmWeightAndFee::<T>::insert(
-			bifrost_xcm_interface::CurrencyIdOf::<T>::from(KSM.into()),
-			XcmOperationType::UmpContributeTransact,
-			(
-				Weight::from_parts(4000000000, 100000),
-				bifrost_xcm_interface::BalanceOf::<T>::from(4000000000u32),
-			),
-		);
-		assert_ok!(Salp::<T>::set_balance(&caller, contribution));
-
-		#[extrinsic_call]
-		_(RawOrigin::Signed(caller.clone()), fund_index, contribution);
-	}
+	use scale_info::prelude::vec;
 
 	#[benchmark]
 	fn refund() {
@@ -134,41 +115,6 @@ mod benchmarks {
 		)
 	}
 
-	#[benchmark]
-	fn unlock() {
-		let fund_index = create_fund::<T>(1);
-		let (caller, _) = contribute_fund::<T>(fund_index);
-		assert_ok!(Pallet::<T>::confirm_contribute(
-			RawOrigin::Signed(caller.clone()).into(),
-			0u64,
-			true
-		));
-
-		assert_ok!(Salp::<T>::fund_success(RawOrigin::Root.into(), fund_index));
-
-		#[extrinsic_call]
-		_(RawOrigin::Signed(caller.clone()), caller.clone(), fund_index);
-	}
-
-	#[benchmark]
-	fn batch_unlock() {
-		let fund_index = create_fund::<T>(1);
-		let caller: T::AccountId = whitelisted_caller();
-		for _ in 0..5 {
-			let (caller, _) = contribute_fund::<T>(fund_index);
-			assert_ok!(Pallet::<T>::confirm_contribute(
-				RawOrigin::Signed(caller.clone()).into(),
-				0u64,
-				true
-			));
-		}
-
-		assert_ok!(Salp::<T>::fund_success(RawOrigin::Root.into(), fund_index));
-
-		#[extrinsic_call]
-		_(RawOrigin::Signed(caller.clone()), fund_index);
-	}
-
 	#[benchmark]
 	fn redeem() {
 		let fund_index = create_fund::<T>(1);
@@ -195,56 +141,6 @@ mod benchmarks {
 		assert_eq!(RedeemPool::<T>::get(), 0_u32.saturated_into());
 	}
 
-	#[benchmark]
-	fn set_multisig_confirm_account() {
-		#[extrinsic_call]
-		_(RawOrigin::Root, whitelisted_caller());
-	}
-
-	#[benchmark]
-	fn fund_success() {
-		let fund_index = create_fund::<T>(1);
-		let (caller, _) = contribute_fund::<T>(fund_index);
-		assert_ok!(Pallet::<T>::confirm_contribute(
-			RawOrigin::Signed(caller.clone()).into(),
-			0u64,
-			true
-		));
-
-		#[extrinsic_call]
-		_(RawOrigin::Root, fund_index);
-	}
-
-	#[benchmark]
-	fn fund_fail() {
-		let fund_index = create_fund::<T>(1);
-		let (caller, _) = contribute_fund::<T>(fund_index);
-		assert_ok!(Pallet::<T>::confirm_contribute(
-			RawOrigin::Signed(caller.clone()).into(),
-			0u64,
-			true
-		));
-
-		#[extrinsic_call]
-		_(RawOrigin::Root, fund_index);
-	}
-
-	#[benchmark]
-	fn continue_fund() {
-		let fund_index = create_fund::<T>(1);
-		let (caller, _) = contribute_fund::<T>(fund_index);
-		assert_ok!(Pallet::<T>::confirm_contribute(
-			RawOrigin::Signed(caller.clone()).into(),
-			0u64,
-			true
-		));
-
-		assert_ok!(Salp::<T>::fund_fail(RawOrigin::Root.into(), fund_index));
-		assert_ok!(Salp::<T>::withdraw(RawOrigin::Root.into(), fund_index));
-		#[extrinsic_call]
-		_(RawOrigin::Root, fund_index, 0u32.into(), 3u32.into());
-	}
-
 	#[benchmark]
 	fn fund_retire() {
 		let fund_index = create_fund::<T>(1);
@@ -281,12 +177,6 @@ mod benchmarks {
 		_(RawOrigin::Root, fund_index);
 	}
 
-	#[benchmark]
-	fn create() {
-		#[extrinsic_call]
-		_(RawOrigin::Root, 2001u32, BalanceOf::<T>::max_value(), 0u32.into(), 3u32.into());
-	}
-
 	#[benchmark]
 	fn edit() {
 		create_fund::<T>(2001u32);
@@ -302,15 +192,6 @@ mod benchmarks {
 		);
 	}
 
-	#[benchmark]
-	fn confirm_contribute() {
-		let fund_index = create_fund::<T>(1);
-		let (caller, _) = contribute_fund::<T>(fund_index);
-
-		#[extrinsic_call]
-		_(RawOrigin::Signed(caller), 0, true)
-	}
-
 	#[benchmark]
 	fn withdraw() {
 		let fund_index = create_fund::<T>(1);
@@ -361,49 +242,6 @@ mod benchmarks {
 		_(RawOrigin::Root, fund_index)
 	}
 
-	#[benchmark]
-	fn buyback() {
-		let caller: T::AccountId = whitelisted_caller();
-		let relay_currency_id = <T as Config>::RelayChainToken::get();
-		let relay_vstoken_id =
-			<T as Config>::CurrencyIdConversion::convert_to_vstoken(relay_currency_id).unwrap();
-
-		let caller_lookup: <T::Lookup as StaticLookup>::Source =
-			T::Lookup::unlookup(caller.clone());
-		assert_ok!(zenlink_protocol::Pallet::<T>::create_pair(
-			RawOrigin::Root.into(),
-			zenlink_protocol::AssetId { chain_id: 2001, asset_type: 2, asset_index: 516 },
-			zenlink_protocol::AssetId { chain_id: 2001, asset_type: 2, asset_index: 1028 },
-			caller_lookup
-		));
-
-		let buybck_caller = T::BuybackPalletId::get().into_account_truncating();
-		assert_ok!(<T as pallet::Config>::MultiCurrency::deposit(
-			relay_currency_id,
-			&buybck_caller,
-			BalanceOf::<T>::unique_saturated_from(1_000_000_000_000_000u128)
-		));
-		assert_ok!(<T as pallet::Config>::MultiCurrency::deposit(
-			relay_vstoken_id,
-			&buybck_caller,
-			BalanceOf::<T>::unique_saturated_from(1_000_000_000_000_000u128)
-		));
-
-		assert_ok!(zenlink_protocol::Pallet::<T>::add_liquidity(
-			RawOrigin::Signed(buybck_caller).into(),
-			zenlink_protocol::AssetId { chain_id: 2001, asset_type: 2, asset_index: 516 },
-			zenlink_protocol::AssetId { chain_id: 2001, asset_type: 2, asset_index: 1028 },
-			1_000_000_000_000u128,
-			100_000_000_000_000u128,
-			0u128,
-			0u128,
-			BlockNumberFor::<T>::from(10u32),
-		));
-
-		#[extrinsic_call]
-		_(RawOrigin::Signed(caller), BalanceOf::<T>::unique_saturated_from(1000u128))
-	}
-
 	#[benchmark]
 	fn buyback_vstoken_by_stable_pool() {
 		let caller: T::AccountId = whitelisted_caller();
@@ -475,84 +313,6 @@ mod benchmarks {
 		_(RawOrigin::Signed(caller), 0, KSM, 1_000_000_000u32.into())
 	}
 
-	#[benchmark]
-	fn reserve() {
-		let fund_index = create_fund::<T>(1);
-		let (caller, contribution) = contribute_fund::<T>(fund_index);
-		assert_ok!(Pallet::<T>::confirm_contribute(
-			RawOrigin::Signed(caller.clone()).into(),
-			0u64,
-			true
-		));
-
-		assert_ok!(Salp::<T>::fund_success(RawOrigin::Root.into(), fund_index));
-		assert_ok!(Salp::<T>::unlock(
-			RawOrigin::Signed(caller.clone()).into(),
-			caller.clone(),
-			fund_index
-		));
-
-		#[extrinsic_call]
-		_(RawOrigin::Signed(caller.clone()), fund_index, contribution, false);
-	}
-
-	#[benchmark]
-	fn cancel_reservation() {
-		let fund_index = create_fund::<T>(1);
-		let (caller, contribution) = contribute_fund::<T>(fund_index);
-		assert_ok!(Pallet::<T>::confirm_contribute(
-			RawOrigin::Signed(caller.clone()).into(),
-			0u64,
-			true
-		));
-
-		assert_ok!(Salp::<T>::fund_success(RawOrigin::Root.into(), fund_index));
-		assert_ok!(Salp::<T>::unlock(
-			RawOrigin::Signed(caller.clone()).into(),
-			caller.clone(),
-			fund_index
-		));
-		assert_ok!(Salp::<T>::reserve(
-			RawOrigin::Signed(caller.clone()).into(),
-			fund_index,
-			contribution,
-			false
-		));
-
-		#[extrinsic_call]
-		_(RawOrigin::Signed(caller.clone()), fund_index);
-	}
-
-	#[benchmark]
-	fn batch_handle_reserve() {
-		let fund_index = create_fund::<T>(1);
-		let (caller, contribution) = contribute_fund::<T>(fund_index);
-		assert_ok!(Pallet::<T>::confirm_contribute(
-			RawOrigin::Signed(caller.clone()).into(),
-			0u64,
-			true
-		));
-
-		assert_ok!(Salp::<T>::fund_success(RawOrigin::Root.into(), fund_index));
-		assert_ok!(Salp::<T>::unlock(
-			RawOrigin::Signed(caller.clone()).into(),
-			caller.clone(),
-			fund_index
-		));
-		assert_ok!(Salp::<T>::reserve(
-			RawOrigin::Signed(caller.clone()).into(),
-			fund_index,
-			contribution,
-			false
-		));
-		assert_ok!(Salp::<T>::fund_retire(RawOrigin::Root.into(), fund_index));
-		assert_ok!(Salp::<T>::withdraw(RawOrigin::Root.into(), fund_index));
-		assert_eq!(RedeemPool::<T>::get(), T::MinContribution::get());
-
-		#[extrinsic_call]
-		_(RawOrigin::Signed(caller.clone()), fund_index);
-	}
-
 	//   `cargo test -p pallet-example-basic --all-features`, you will see one line per case:
 	impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test);
 }
diff --git a/pallets/salp/src/lib.rs b/pallets/salp/src/lib.rs
index b2fae3ff3..a1a09090d 100644
--- a/pallets/salp/src/lib.rs
+++ b/pallets/salp/src/lib.rs
@@ -30,19 +30,17 @@ pub use weights::WeightInfo;
 
 // Re-export pallet items so that they can be accessed from the crate namespace.
 use bifrost_primitives::{
-	ContributionStatus, CurrencyIdConversion, CurrencyIdRegister, TrieIndex, TryConvertFrom,
-	VtokenMintingInterface,
+	ContributionStatus, CurrencyIdConversion, CurrencyIdRegister, TrieIndex, VtokenMintingInterface,
 };
 use bifrost_stable_pool::{traits::StablePoolHandler, StableAssetPoolId};
 use bifrost_xcm_interface::ChainId;
 use cumulus_primitives_core::{QueryId, Response};
-use frame_support::{pallet_prelude::*, sp_runtime::SaturatedConversion, traits::LockIdentifier};
+use frame_support::{pallet_prelude::*, sp_runtime::SaturatedConversion};
 use orml_traits::MultiCurrency;
 pub use pallet::*;
 use pallet_xcm::ensure_response;
 use scale_info::TypeInfo;
 use sp_runtime::traits::One;
-use zenlink_protocol::{AssetId, ExportZenlink};
 
 pub type AccountIdOf<T> = <T as frame_system::Config>::AccountId;
 
@@ -97,9 +95,7 @@ pub struct ReserveInfo<Balance> {
 #[frame_support::pallet]
 pub mod pallet {
 	// Import various types used to declare pallet in scope.
-	use bifrost_primitives::{
-		BancorHandler, CurrencyId, CurrencyId::VSBond, LeasePeriod, MessageId, Nonce, ParaId,
-	};
+	use bifrost_primitives::{CurrencyId, LeasePeriod, MessageId, Nonce, ParaId};
 	use bifrost_xcm_interface::traits::XcmHelper;
 	use frame_support::{
 		pallet_prelude::{storage::child, *},
@@ -166,8 +162,6 @@ pub mod pallet {
 			+ MultiReservableCurrency<AccountIdOf<Self>, CurrencyId = CurrencyId>
 			+ MultiLockableCurrency<AccountIdOf<Self>>;
 
-		type BancorPool: BancorHandler<BalanceOf<Self>>;
-
 		type EnsureConfirmAsGovernance: EnsureOrigin<<Self as frame_system::Config>::RuntimeOrigin>;
 
 		type WeightInfo: WeightInfo;
@@ -181,23 +175,13 @@ pub mod pallet {
 		#[pallet::constant]
 		type BuybackPalletId: Get<PalletId>;
 
-		type DexOperator: ExportZenlink<Self::AccountId, AssetId>;
-
 		type CurrencyIdConversion: CurrencyIdConversion<CurrencyId>;
 
 		type CurrencyIdRegister: CurrencyIdRegister<CurrencyId>;
 
-		type ParachainId: Get<cumulus_primitives_core::ParaId>;
-
 		type StablePool: StablePoolHandler<Balance = BalanceOf<Self>, AccountId = Self::AccountId>;
 
 		type VtokenMinting: VtokenMintingInterface<Self::AccountId, CurrencyId, BalanceOf<Self>>;
-
-		#[pallet::constant]
-		type LockId: Get<LockIdentifier>;
-
-		#[pallet::constant]
-		type BatchLimit: Get<u32>;
 	}
 
 	#[pallet::pallet]
@@ -387,115 +371,6 @@ pub mod pallet {
 
 	#[pallet::call]
 	impl<T: Config> Pallet<T> {
-		#[pallet::call_index(0)]
-		#[pallet::weight(T::WeightInfo::set_multisig_confirm_account())]
-		pub fn set_multisig_confirm_account(
-			origin: OriginFor<T>,
-			account: AccountIdOf<T>,
-		) -> DispatchResult {
-			T::EnsureConfirmAsGovernance::ensure_origin(origin)?;
-
-			Self::set_multisig_account(account);
-
-			Ok(())
-		}
-
-		#[pallet::call_index(1)]
-		#[pallet::weight(T::WeightInfo::fund_success())]
-		pub fn fund_success(
-			origin: OriginFor<T>,
-			#[pallet::compact] index: ParaId,
-		) -> DispatchResult {
-			T::EnsureConfirmAsGovernance::ensure_origin(origin)?;
-
-			let fund = Funds::<T>::get(index).ok_or(Error::<T>::InvalidParaId)?;
-			ensure!(fund.status == FundStatus::Ongoing, Error::<T>::InvalidFundStatus);
-
-			let fund_new = FundInfo { status: FundStatus::Success, ..fund };
-			Funds::<T>::insert(index, Some(fund_new));
-			Self::deposit_event(Event::<T>::Success(index));
-
-			Ok(())
-		}
-
-		#[pallet::call_index(2)]
-		#[pallet::weight(T::WeightInfo::fund_fail())]
-		pub fn fund_fail(origin: OriginFor<T>, #[pallet::compact] index: ParaId) -> DispatchResult {
-			T::EnsureConfirmAsGovernance::ensure_origin(origin)?;
-
-			// crownload is failed, so enable the withdrawal function of vsToken/vsBond
-			let fund = Funds::<T>::get(index).ok_or(Error::<T>::InvalidParaId)?;
-			ensure!(fund.status == FundStatus::Ongoing, Error::<T>::InvalidFundStatus);
-
-			let fund_new = FundInfo { status: FundStatus::Failed, ..fund };
-			Funds::<T>::insert(index, Some(fund_new));
-			Self::deposit_event(Event::<T>::Failed(index));
-
-			Ok(())
-		}
-
-		#[pallet::call_index(3)]
-		#[pallet::weight(T::WeightInfo::continue_fund())]
-		pub fn continue_fund(
-			origin: OriginFor<T>,
-			#[pallet::compact] index: ParaId,
-			#[pallet::compact] first_slot: LeasePeriod,
-			#[pallet::compact] last_slot: LeasePeriod,
-		) -> DispatchResult {
-			T::EnsureConfirmAsGovernance::ensure_origin(origin)?;
-
-			// crownload is failed, so enable the withdrawal function of vsToken/vsBond
-			let fund = Funds::<T>::get(index).ok_or(Error::<T>::InvalidParaId)?;
-			ensure!(fund.status == FundStatus::RefundWithdrew, Error::<T>::InvalidFundStatus);
-			ensure!(
-				fund.first_slot != first_slot || fund.last_slot != last_slot,
-				Error::<T>::InvalidFundSameSlot
-			);
-
-			let fund_old = FundInfo { status: FundStatus::FailedToContinue, ..fund };
-			FailedFundsToRefund::<T>::insert(
-				(index, fund.first_slot, fund.last_slot),
-				Some(fund_old.clone()),
-			);
-			let fund_new = FundInfo { status: FundStatus::Ongoing, first_slot, last_slot, ..fund };
-			Funds::<T>::insert(index, Some(fund_new));
-
-			match T::RelayChainToken::get() {
-				CurrencyId::Token(token_symbol) =>
-					if !T::CurrencyIdRegister::check_vsbond_registered(
-						token_symbol,
-						index,
-						first_slot,
-						last_slot,
-					) {
-						T::CurrencyIdRegister::register_vsbond_metadata(
-							token_symbol,
-							index,
-							first_slot,
-							last_slot,
-						)?;
-					},
-				CurrencyId::Token2(token_id) => {
-					if !T::CurrencyIdRegister::check_vsbond2_registered(
-						token_id, index, first_slot, last_slot,
-					) {
-						T::CurrencyIdRegister::register_vsbond2_metadata(
-							token_id, index, first_slot, last_slot,
-						)?;
-					}
-				},
-				_ => (),
-			}
-
-			Self::deposit_event(Event::<T>::Continued(
-				index,
-				fund_old.first_slot,
-				fund_old.last_slot,
-			));
-
-			Ok(())
-		}
-
 		#[pallet::call_index(4)]
 		#[pallet::weight(T::WeightInfo::fund_retire())]
 		pub fn fund_retire(
@@ -533,71 +408,6 @@ pub mod pallet {
 			Ok(())
 		}
 
-		/// Create a new crowdloaning campaign for a parachain slot deposit for the current auction.
-		#[pallet::call_index(6)]
-		#[pallet::weight(T::WeightInfo::create())]
-		pub fn create(
-			origin: OriginFor<T>,
-			#[pallet::compact] index: ParaId,
-			#[pallet::compact] cap: BalanceOf<T>,
-			#[pallet::compact] first_slot: LeasePeriod,
-			#[pallet::compact] last_slot: LeasePeriod,
-		) -> DispatchResult {
-			T::EnsureConfirmAsGovernance::ensure_origin(origin)?;
-
-			ensure!(!Funds::<T>::contains_key(index), Error::<T>::FundAlreadyCreated);
-
-			ensure!(first_slot <= last_slot, Error::<T>::LastSlotBeforeFirstSlot);
-
-			let last_slot_limit = first_slot
-				.checked_add(((T::SlotLength::get() as u32) - 1).into())
-				.ok_or(Error::<T>::FirstSlotTooFarInFuture)?;
-			ensure!(last_slot <= last_slot_limit, Error::<T>::LastSlotTooFarInFuture);
-
-			Funds::<T>::insert(
-				index,
-				Some(FundInfo {
-					raised: Zero::zero(),
-					cap,
-					first_slot,
-					last_slot,
-					trie_index: Self::next_trie_index()?,
-					status: FundStatus::Ongoing,
-				}),
-			);
-
-			match T::RelayChainToken::get() {
-				CurrencyId::Token(token_symbol) =>
-					if !T::CurrencyIdRegister::check_vsbond_registered(
-						token_symbol,
-						index,
-						first_slot,
-						last_slot,
-					) {
-						T::CurrencyIdRegister::register_vsbond_metadata(
-							token_symbol,
-							index,
-							first_slot,
-							last_slot,
-						)?;
-					},
-				CurrencyId::Token2(token_id) => {
-					if !T::CurrencyIdRegister::check_vsbond2_registered(
-						token_id, index, first_slot, last_slot,
-					) {
-						T::CurrencyIdRegister::register_vsbond2_metadata(
-							token_id, index, first_slot, last_slot,
-						)?;
-					}
-				},
-				_ => (),
-			}
-
-			Self::deposit_event(Event::<T>::Created(index));
-
-			Ok(())
-		}
-
 		/// Edit the configuration for an in-progress crowdloan.
 		///
 		/// Can only be called by Root origin.
@@ -635,361 +445,60 @@ pub mod pallet {
 			Ok(())
 		}
 
-		/// Contribute to a crowd sale. This will transfer some balance over to fund a parachain
-		/// slot. It will be withdrawable in two instances: the parachain becomes retired; or the
-		/// slot is unable to be purchased and the timeout expires.
-		#[pallet::call_index(8)]
-		#[pallet::weight(T::WeightInfo::contribute())]
-		pub fn contribute(
-			origin: OriginFor<T>,
-			#[pallet::compact] index: ParaId,
-			#[pallet::compact] value: BalanceOf<T>,
-		) -> DispatchResult {
-			let who = ensure_signed(origin.clone())?;
+		/// Withdraw full balance of the parachain.
+		/// - `index`: The parachain to whose crowdloan the contribution was made.
+		#[pallet::call_index(14)]
+		#[pallet::weight(T::WeightInfo::withdraw())]
+		pub fn withdraw(origin: OriginFor<T>, #[pallet::compact] index: ParaId) -> DispatchResult {
+			T::EnsureConfirmAsGovernance::ensure_origin(origin.clone())?;
 
 			let fund = Funds::<T>::get(index).ok_or(Error::<T>::InvalidParaId)?;
-			ensure!(fund.status == FundStatus::Ongoing, Error::<T>::InvalidFundStatus);
-
-			ensure!(value >= T::MinContribution::get(), Error::<T>::ContributionTooSmall);
-
-			let raised = fund.raised.checked_add(&value).ok_or(Error::<T>::Overflow)?;
-			ensure!(raised <= fund.cap, Error::<T>::CapExceeded);
-
-			let (contributed, status) = Self::contribution(fund.trie_index, &who);
-			ensure!(
-				status == ContributionStatus::Idle ||
-					status == ContributionStatus::Refunded ||
-					status == ContributionStatus::Redeemed ||
-					status == ContributionStatus::Unlocked,
-				Error::<T>::InvalidContributionStatus
-			);
-
-			ensure!(
-				T::MultiCurrency::can_reserve(T::RelayChainToken::get(), &who, value),
-				Error::<T>::NotEnoughBalanceToContribute
-			);
+			let can = fund.status == FundStatus::Failed || fund.status == FundStatus::Retired;
+			ensure!(can, Error::<T>::InvalidFundStatus);
 
-			T::MultiCurrency::reserve(T::RelayChainToken::get(), &who, value)?;
+			let amount_withdrew = fund.raised;
+			let total = RedeemPool::<T>::get()
+				.checked_add(&amount_withdrew)
+				.ok_or(Error::<T>::Overflow)?;
+			RedeemPool::<T>::set(total);
 
-			Self::put_contribution(
-				fund.trie_index,
-				&who,
-				contributed,
-				ContributionStatus::Contributing(value),
-			);
+			if fund.status == FundStatus::Retired {
+				let fund_new = FundInfo { status: FundStatus::RedeemWithdrew, ..fund };
+				Funds::<T>::insert(index, Some(fund_new));
+			} else if fund.status == FundStatus::Failed {
+				let fund_new = FundInfo { status: FundStatus::RefundWithdrew, ..fund };
+				Funds::<T>::insert(index, Some(fund_new));
+			}
 
-			let message_id = T::XcmInterface::contribute(who.clone(), index, value)?;
+			Self::deposit_event(Event::Withdrew(index, amount_withdrew));
 
-			Self::deposit_event(Event::Contributing(who, index, value, message_id));
 			Ok(())
 		}
 
-		/// Confirm contribute
-		#[pallet::call_index(9)]
-		#[pallet::weight(T::WeightInfo::confirm_contribute())]
-		pub fn confirm_contribute(
+		#[pallet::call_index(15)]
+		#[pallet::weight(T::WeightInfo::refund())]
+		pub fn refund(
 			origin: OriginFor<T>,
-			query_id: QueryId,
-			is_success: bool,
+			#[pallet::compact] index: ParaId,
+			#[pallet::compact] first_slot: LeasePeriod,
+			#[pallet::compact] last_slot: LeasePeriod,
+			#[pallet::compact] value: BalanceOf<T>,
 		) -> DispatchResult {
-			let confirmor = ensure_signed(origin.clone())?;
-			if Some(confirmor) != MultisigConfirmAccount::<T>::get() {
-				return Err(DispatchError::BadOrigin.into());
-			}
+			let who = ensure_signed(origin.clone())?;
 
-			let (index, contributer, _amount) = QueryIdContributionInfo::<T>::get(query_id)
-				.ok_or(Error::<T>::NotFindContributionValue)?;
-
-			let fund = Funds::<T>::get(index).ok_or(Error::<T>::InvalidParaId)?;
-			let can_confirm = fund.status == FundStatus::Ongoing ||
-				fund.status == FundStatus::Failed ||
-				fund.status == FundStatus::Success;
-			ensure!(can_confirm, Error::<T>::InvalidFundStatus);
-
-			let (contributed, status) = Self::contribution(fund.trie_index, &contributer);
-			ensure!(status.is_contributing(), Error::<T>::InvalidContributionStatus);
-			let contributing = status.contributing();
-
-			let vs_token = T::CurrencyIdConversion::convert_to_vstoken(T::RelayChainToken::get())
-				.map_err(|_| Error::<T>::NotSupportTokenType)?;
-			let vs_bond = T::CurrencyIdConversion::convert_to_vsbond(
-				T::RelayChainToken::get(),
-				index,
-				fund.first_slot,
-				fund.last_slot,
-			)
-			.map_err(|_| Error::<T>::NotSupportTokenType)?;
-
-			if is_success {
-				// Issue reserved vsToken/vsBond to contributor
-				T::MultiCurrency::deposit(vs_token, &contributer, contributing)?;
-				T::MultiCurrency::deposit(vs_bond, &contributer, contributing)?;
-
-				// Update the raised of fund
-				let fund_new =
-					FundInfo { raised: fund.raised.saturating_add(contributing), ..fund };
-				Funds::<T>::insert(index, Some(fund_new));
-
-				T::MultiCurrency::unreserve(T::RelayChainToken::get(), &contributer, contributing);
-				T::MultiCurrency::transfer(
-					T::RelayChainToken::get(),
-					&contributer,
-					&Self::fund_account_id(index),
-					contributing,
-				)?;
-
-				// Update the contribution of contributer
-				let contributed_new = contributed.saturating_add(contributing);
-				Self::put_contribution(
-					fund.trie_index,
-					&contributer,
-					contributed_new,
-					ContributionStatus::Idle,
-				);
-				Self::deposit_event(Event::Contributed(contributer, index, contributing));
-			} else {
-				// Update the contribution of contributer
-				Self::put_contribution(
-					fund.trie_index,
-					&contributer,
-					contributed,
-					ContributionStatus::Idle,
-				);
-				T::MultiCurrency::unreserve(T::RelayChainToken::get(), &contributer, contributing);
-				Self::deposit_event(Event::ContributeFailed(contributer, index, contributing));
-			}
-
-			QueryIdContributionInfo::<T>::remove(query_id);
-
-			Ok(())
-		}
-
-		/// Unlock the reserved vsToken/vsBond after fund success
-		#[pallet::call_index(10)]
-		#[pallet::weight(T::WeightInfo::unlock())]
-		pub fn unlock(
-			origin: OriginFor<T>,
-			who: AccountIdOf<T>,
-			#[pallet::compact] index: ParaId,
-		) -> DispatchResult {
-			ensure_signed(origin)?;
-			let fund = Funds::<T>::get(index).ok_or(Error::<T>::InvalidParaId)?;
-
-			let (contributed, _) = Self::contribution(fund.trie_index, &who);
-
-			let vs_token = T::CurrencyIdConversion::convert_to_vstoken(T::RelayChainToken::get())
-				.map_err(|_| Error::<T>::NotSupportTokenType)?;
-			let vs_bond = T::CurrencyIdConversion::convert_to_vsbond(
-				T::RelayChainToken::get(),
-				index,
-				fund.first_slot,
-				fund.last_slot,
-			)
-			.map_err(|_| Error::<T>::NotSupportTokenType)?;
-
-			T::MultiCurrency::unreserve(vs_token, &who, contributed);
-			T::MultiCurrency::unreserve(vs_bond, &who, contributed);
-
-			Self::deposit_event(Event::<T>::Unlocked(who, index, contributed));
-
-			Ok(())
-		}
-
-		#[pallet::call_index(11)]
-		#[pallet::weight(T::WeightInfo::unlock())]
-		pub fn unlock_by_vsbond(
-			origin: OriginFor<T>,
-			who: AccountIdOf<T>,
-			vsbond: CurrencyId,
-		) -> DispatchResult {
-			ensure_signed(origin)?;
-
-			let index = match vsbond {
-				CurrencyId::VSBond(token_symbol, paraid, first_slot, last_slot) => {
-					if !T::CurrencyIdRegister::check_vsbond_registered(
-						token_symbol,
-						paraid,
-						first_slot,
-						last_slot,
-					) {
-						return Err(Error::<T>::NotSupportTokenType.into());
-					}
-					paraid
-				},
-				CurrencyId::VSBond2(token_id, paraid, first_slot, last_slot) => {
-					if !T::CurrencyIdRegister::check_vsbond2_registered(
-						token_id, paraid, first_slot, last_slot,
-					) {
-						return Err(Error::<T>::NotSupportTokenType.into());
-					}
-					paraid
-				},
-				_ => return Err(Error::<T>::NotSupportTokenType.into()),
-			};
-
-			let fund = Funds::<T>::get(index).ok_or(Error::<T>::InvalidParaId)?;
-
-			let (contributed, _) = Self::contribution(fund.trie_index, &who);
-
-			let vs_token = T::CurrencyIdConversion::convert_to_vstoken(T::RelayChainToken::get())
-				.map_err(|_| Error::<T>::NotSupportTokenType)?;
-			let vs_bond = T::CurrencyIdConversion::convert_to_vsbond(
-				T::RelayChainToken::get(),
-				index,
-				fund.first_slot,
-				fund.last_slot,
-			)
-			.map_err(|_| Error::<T>::NotSupportTokenType)?;
-
-			T::MultiCurrency::unreserve(vs_token, &who, contributed);
-			T::MultiCurrency::unreserve(vs_bond, &who, contributed);
-
-			Self::deposit_event(Event::<T>::Unlocked(who, index, contributed));
-			Ok(())
-		}
-
-		#[pallet::call_index(12)]
-		#[pallet::weight(T::WeightInfo::unlock())]
-		pub fn unlock_vstoken(origin: OriginFor<T>, who: AccountIdOf<T>) -> DispatchResult {
-			ensure_signed(origin)?;
-
-			match T::RelayChainToken::get() {
-				CurrencyId::Token(token_symbol) => {
-					let vsbond_list = vec![
-						VSBond(token_symbol, 2106, 19, 26),
-						VSBond(token_symbol, 2011, 19, 26),
-						VSBond(token_symbol, 2102, 18, 25),
-						VSBond(token_symbol, 2102, 19, 26),
-						VSBond(token_symbol, 2101, 18, 25),
-						VSBond(token_symbol, 2100, 18, 25),
-						VSBond(token_symbol, 2100, 17, 24),
-						VSBond(token_symbol, 2095, 17, 24),
-						VSBond(token_symbol, 2096, 17, 24),
-						VSBond(token_symbol, 2087, 17, 24),
-						VSBond(token_symbol, 2085, 15, 22),
-						VSBond(token_symbol, 2092, 15, 22),
-						VSBond(token_symbol, 2088, 15, 22),
-						VSBond(token_symbol, 2090, 15, 22),
-					];
-
-					let vs_token =
-						T::CurrencyIdConversion::convert_to_vstoken(T::RelayChainToken::get())
-							.map_err(|_| Error::<T>::NotSupportTokenType)?;
-					let reserved_vstoken = T::MultiCurrency::reserved_balance(vs_token, &who);
-					T::MultiCurrency::unreserve(vs_token, &who, reserved_vstoken);
-					vsbond_list.into_iter().for_each(|vs_bond| {
-						let reserved_vsbond = T::MultiCurrency::reserved_balance(vs_bond, &who);
-						T::MultiCurrency::unreserve(vs_bond, &who, reserved_vsbond);
-					});
-				},
-				_ => return Err(DispatchError::BadOrigin.into()),
-			}
-
-			Self::deposit_event(Event::<T>::VstokenUnlocked(who));
-			Ok(())
-		}
-
-		/// Unlock the reserved vsToken/vsBond after fund success
-		#[pallet::call_index(13)]
-		#[pallet::weight(T::WeightInfo::batch_unlock())]
-		pub fn batch_unlock(
-			origin: OriginFor<T>,
-			#[pallet::compact] index: ParaId,
-		) -> DispatchResult {
-			ensure_signed(origin)?;
-
-			let fund = Funds::<T>::get(index).ok_or(Error::<T>::InvalidParaId)?;
-
-			let mut unlock_count = 0u32;
-			let contributions = Self::contribution_iterator(fund.trie_index);
-			// Assume everyone will be refunded.
-			let mut all_unlocked = true;
-
-			for (who, (contributed, status)) in contributions {
-				if unlock_count >= T::RemoveKeysLimit::get() {
-					// Not everyone was able to be refunded this time around.
-					all_unlocked = false;
-					break;
-				}
-				if status != ContributionStatus::Unlocked {
-					let vs_token =
-						T::CurrencyIdConversion::convert_to_vstoken(T::RelayChainToken::get())
-							.map_err(|_| Error::<T>::NotSupportTokenType)?;
-					let vs_bond = T::CurrencyIdConversion::convert_to_vsbond(
-						T::RelayChainToken::get(),
-						index,
-						fund.first_slot,
-						fund.last_slot,
-					)
-					.map_err(|_| Error::<T>::NotSupportTokenType)?;
-					T::MultiCurrency::unreserve(vs_token, &who, contributed);
-					T::MultiCurrency::unreserve(vs_bond, &who, contributed);
-
-					unlock_count += 1;
-				}
-			}
-
-			if all_unlocked {
-				Self::deposit_event(Event::<T>::AllUnlocked(index));
-			}
-
-			Ok(())
-		}
-
-		/// Withdraw full balance of the parachain.
-		/// - `index`: The parachain to whose crowdloan the contribution was made.
-		#[pallet::call_index(14)]
-		#[pallet::weight(T::WeightInfo::withdraw())]
-		pub fn withdraw(origin: OriginFor<T>, #[pallet::compact] index: ParaId) -> DispatchResult {
-			T::EnsureConfirmAsGovernance::ensure_origin(origin.clone())?;
-
-			let fund = Funds::<T>::get(index).ok_or(Error::<T>::InvalidParaId)?;
-			let can = fund.status == FundStatus::Failed || fund.status == FundStatus::Retired;
-			ensure!(can, Error::<T>::InvalidFundStatus);
-
-			let amount_withdrew = fund.raised;
-			let total = RedeemPool::<T>::get()
-				.checked_add(&amount_withdrew)
-				.ok_or(Error::<T>::Overflow)?;
-			RedeemPool::<T>::set(total);
-
-			if fund.status == FundStatus::Retired {
-				let fund_new = FundInfo { status: FundStatus::RedeemWithdrew, ..fund };
-				Funds::<T>::insert(index, Some(fund_new));
-			} else if fund.status == FundStatus::Failed {
-				let fund_new = FundInfo { status: FundStatus::RefundWithdrew, ..fund };
-				Funds::<T>::insert(index, Some(fund_new));
-			}
-
-			Self::deposit_event(Event::Withdrew(index, amount_withdrew));
-
-			Ok(())
-		}
-
-		#[pallet::call_index(15)]
-		#[pallet::weight(T::WeightInfo::refund())]
-		pub fn refund(
-			origin: OriginFor<T>,
-			#[pallet::compact] index: ParaId,
-			#[pallet::compact] first_slot: LeasePeriod,
-			#[pallet::compact] last_slot: LeasePeriod,
-			#[pallet::compact] value: BalanceOf<T>,
-		) -> DispatchResult {
-			let who = ensure_signed(origin.clone())?;
-
-			let mut fund = Self::find_fund(index, first_slot, last_slot)
-				.map_err(|_| Error::<T>::InvalidFundNotExist)?;
-			ensure!(
-				fund.status == FundStatus::FailedToContinue ||
-					fund.status == FundStatus::RefundWithdrew,
-				Error::<T>::InvalidRefund
-			);
-			ensure!(
-				fund.first_slot == first_slot && fund.last_slot == last_slot,
-				Error::<T>::InvalidRefund
-			);
-			ensure!(fund.raised >= value, Error::<T>::NotEnoughBalanceInFund);
-			ensure!(RedeemPool::<T>::get() >= value, Error::<T>::NotEnoughBalanceInRefundPool);
+			let mut fund = Self::find_fund(index, first_slot, last_slot)
+				.map_err(|_| Error::<T>::InvalidFundNotExist)?;
+			ensure!(
+				fund.status == FundStatus::FailedToContinue ||
+					fund.status == FundStatus::RefundWithdrew,
+				Error::<T>::InvalidRefund
+			);
+			ensure!(
+				fund.first_slot == first_slot && fund.last_slot == last_slot,
+				Error::<T>::InvalidRefund
+			);
+			ensure!(fund.raised >= value, Error::<T>::NotEnoughBalanceInFund);
+			ensure!(RedeemPool::<T>::get() >= value, Error::<T>::NotEnoughBalanceInRefundPool);
 
 			let vs_token = T::CurrencyIdConversion::convert_to_vstoken(T::RelayChainToken::get())
 				.map_err(|_| Error::<T>::NotSupportTokenType)?;
@@ -1165,38 +674,7 @@ pub mod pallet {
 			Ok(())
 		}
 
-		#[pallet::call_index(19)]
-		#[pallet::weight(T::WeightInfo::buyback())]
-		pub fn buyback(
-			origin: OriginFor<T>,
-			#[pallet::compact] value: BalanceOf<T>,
-		) -> DispatchResult {
-			let _who = ensure_signed(origin.clone())?;
-
-			let relay_currency_id = T::RelayChainToken::get();
-			let relay_vstoken_id = T::CurrencyIdConversion::convert_to_vstoken(relay_currency_id)
-				.map_err(|_| Error::<T>::NotSupportTokenType)?;
-			let relay_asset_id: AssetId =
-				AssetId::try_convert_from(relay_currency_id, T::ParachainId::get().into())
-					.map_err(|_| DispatchError::Other("Conversion Error."))?;
-			let relay_vstoken_asset_id: AssetId =
-				AssetId::try_convert_from(relay_vstoken_id, T::ParachainId::get().into())
-					.map_err(|_| DispatchError::Other("Conversion Error."))?;
-			let path = vec![relay_asset_id, relay_vstoken_asset_id];
-
-			T::DexOperator::inner_swap_exact_assets_for_assets(
-				&T::BuybackPalletId::get().into_account_truncating(),
-				value.saturated_into(),
-				Percent::from_percent(50).saturating_reciprocal_mul(value).saturated_into(),
-				&path,
-				&T::TreasuryAccount::get(),
-			)?;
-
-			Self::deposit_event(Event::<T>::Buyback(value));
-
-			Ok(())
-		}
-
+		// unused but xcm-interface
 		#[pallet::call_index(20)]
 		#[pallet::weight(T::WeightInfo::confirm_contribute())]
 		pub fn confirm_contribution(
@@ -1326,53 +804,252 @@ pub mod pallet {
 			Self::deposit_event(Event::<T>::BuybackByStablePool { pool_id, currency_id_in, value });
 			Ok(())
 		}
+	}
 
-		#[pallet::call_index(22)]
-		#[pallet::weight(T::WeightInfo::reserve())]
-		pub fn reserve(
-			origin: OriginFor<T>,
-			index: ParaId,
-			value: BalanceOf<T>,
-			if_mint: bool,
-		) -> DispatchResult {
-			let who = ensure_signed(origin)?;
-			let fund = Funds::<T>::get(index).ok_or(Error::<T>::InvalidParaId)?;
+	#[pallet::hooks]
+	impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
+		fn on_initialize(n: BlockNumberFor<T>) -> Weight {
+			// Release x% KSM/DOT from redeem-pool to bancor-pool per cycle
+			if n != Zero::zero() && (n % T::ReleaseCycle::get()) == Zero::zero() {
+				if let Ok(rp_balance) = TryInto::<u128>::try_into(RedeemPool::<T>::get()) {
+					// Calculate the release amount
+					let release_amount = T::ReleaseRatio::get() * rp_balance;
 
-			ensure!(
-				fund.status == FundStatus::Ongoing || fund.status == FundStatus::Success,
-				Error::<T>::InvalidFundStatus
-			);
+					// Must be ok
+					if let Err(_) = TryInto::<BalanceOf<T>>::try_into(release_amount) {
+						log::warn!("Overflow: The balance of redeem-pool exceeds u128.");
+					}
+				}
+			}
+			T::DbWeight::get().reads(1)
+		}
+	}
 
-			let vs_token = T::CurrencyIdConversion::convert_to_vstoken(T::RelayChainToken::get())
-				.map_err(|_| Error::<T>::NotSupportTokenType)?;
-			let vs_bond = T::CurrencyIdConversion::convert_to_vsbond(
-				T::RelayChainToken::get(),
+	// These methods are no longer in use and are now only called for testing and benchmarking
+	// purposes.
+	impl<T: Config> Pallet<T> {
+		pub(crate) fn fund_success(origin: OriginFor<T>, index: ParaId) -> DispatchResult {
+			T::EnsureConfirmAsGovernance::ensure_origin(origin)?;
+
+			let fund = Funds::<T>::get(index).ok_or(Error::<T>::InvalidParaId)?;
+			ensure!(fund.status == FundStatus::Ongoing, Error::<T>::InvalidFundStatus);
+
+			let fund_new = FundInfo { status: FundStatus::Success, ..fund };
+			Funds::<T>::insert(index, Some(fund_new));
+			Self::deposit_event(Event::<T>::Success(index));
+
+			Ok(())
+		}
+
+		pub(crate) fn fund_fail(origin: OriginFor<T>, index: ParaId) -> DispatchResult {
+			T::EnsureConfirmAsGovernance::ensure_origin(origin)?;
+
+			// crownload is failed, so enable the withdrawal function of vsToken/vsBond
+			let fund = crate::pallet::Funds::<T>::get(index)
+				.ok_or(crate::pallet::Error::<T>::InvalidParaId)?;
+			ensure!(fund.status == FundStatus::Ongoing, Error::<T>::InvalidFundStatus);
+
+			let fund_new = crate::FundInfo { status: crate::FundStatus::Failed, ..fund };
+			crate::pallet::Funds::<T>::insert(index, Some(fund_new));
+			Self::deposit_event(crate::pallet::Event::<T>::Failed(index));
+
+			Ok(())
+		}
+
+		pub(crate) fn continue_fund(
+			origin: OriginFor<T>,
+			index: ParaId,
+			first_slot: LeasePeriod,
+			last_slot: LeasePeriod,
+		) -> DispatchResult {
+			T::EnsureConfirmAsGovernance::ensure_origin(origin)?;
+
+			// crownload is failed, so enable the withdrawal function of vsToken/vsBond
+			let fund = Funds::<T>::get(index).ok_or(Error::<T>::InvalidParaId)?;
+			ensure!(fund.status == FundStatus::RefundWithdrew, Error::<T>::InvalidFundStatus);
+			ensure!(
+				fund.first_slot != first_slot || fund.last_slot != last_slot,
+				Error::<T>::InvalidFundSameSlot
+			);
+
+			let fund_old = FundInfo { status: FundStatus::FailedToContinue, ..fund };
+			FailedFundsToRefund::<T>::insert(
+				(index, fund.first_slot, fund.last_slot),
+				Some(fund_old.clone()),
+			);
+			let fund_new = FundInfo { status: FundStatus::Ongoing, first_slot, last_slot, ..fund };
+			Funds::<T>::insert(index, Some(fund_new));
+
+			match T::RelayChainToken::get() {
+				CurrencyId::Token(token_symbol) =>
+					if !T::CurrencyIdRegister::check_vsbond_registered(
+						token_symbol,
+						index,
+						first_slot,
+						last_slot,
+					) {
+						T::CurrencyIdRegister::register_vsbond_metadata(
+							token_symbol,
+							index,
+							first_slot,
+							last_slot,
+						)?;
+					},
+				CurrencyId::Token2(token_id) => {
+					if !T::CurrencyIdRegister::check_vsbond2_registered(
+						token_id, index, first_slot, last_slot,
+					) {
+						T::CurrencyIdRegister::register_vsbond2_metadata(
+							token_id, index, first_slot, last_slot,
+						)?;
+					}
+				},
+				_ => (),
+			}
+
+			Self::deposit_event(Event::<T>::Continued(
 				index,
-				fund.first_slot,
-				fund.last_slot,
-			)
-			.map_err(|_| Error::<T>::NotSupportTokenType)?;
+				fund_old.first_slot,
+				fund_old.last_slot,
+			));
+
+			Ok(())
+		}
+
+		/// Create a new crowdloaning campaign for a parachain slot deposit for the current auction.
+		pub(crate) fn create(
+			origin: OriginFor<T>,
+			index: ParaId,
+			cap: BalanceOf<T>,
+			first_slot: LeasePeriod,
+			last_slot: LeasePeriod,
+		) -> DispatchResult {
+			T::EnsureConfirmAsGovernance::ensure_origin(origin)?;
 
-			T::MultiCurrency::ensure_can_withdraw(vs_token, &who, value)?;
-			T::MultiCurrency::ensure_can_withdraw(vs_bond, &who, value)?;
-			let mut info = ReserveInfos::<T>::get(index, &who);
-			info.value = info.value.checked_add(&value).ok_or(Error::<T>::Overflow)?;
-			info.if_mint = if_mint;
-			T::MultiCurrency::extend_lock(T::LockId::get(), vs_token, &who, info.value)?;
-			T::MultiCurrency::extend_lock(T::LockId::get(), vs_bond, &who, info.value)?;
+			ensure!(!Funds::<T>::contains_key(index), Error::<T>::FundAlreadyCreated);
 
-			ReserveInfos::<T>::insert(index, &who, info);
+			ensure!(first_slot <= last_slot, Error::<T>::LastSlotBeforeFirstSlot);
+
+			let last_slot_limit = first_slot
+				.checked_add(((T::SlotLength::get() as u32) - 1).into())
+				.ok_or(Error::<T>::FirstSlotTooFarInFuture)?;
+			ensure!(last_slot <= last_slot_limit, Error::<T>::LastSlotTooFarInFuture);
+
+			Funds::<T>::insert(
+				index,
+				Some(FundInfo {
+					raised: Zero::zero(),
+					cap,
+					first_slot,
+					last_slot,
+					trie_index: Self::next_trie_index()?,
+					status: FundStatus::Ongoing,
+				}),
+			);
+
+			match T::RelayChainToken::get() {
+				CurrencyId::Token(token_symbol) =>
+					if !T::CurrencyIdRegister::check_vsbond_registered(
+						token_symbol,
+						index,
+						first_slot,
+						last_slot,
+					) {
+						T::CurrencyIdRegister::register_vsbond_metadata(
+							token_symbol,
+							index,
+							first_slot,
+							last_slot,
+						)?;
+					},
+				CurrencyId::Token2(token_id) => {
+					if !T::CurrencyIdRegister::check_vsbond2_registered(
+						token_id, index, first_slot, last_slot,
+					) {
+						T::CurrencyIdRegister::register_vsbond2_metadata(
+							token_id, index, first_slot, last_slot,
+						)?;
+					}
+				},
+				_ => (),
+			}
+
+			Self::deposit_event(Event::<T>::Created(index));
 
-			Self::deposit_event(Event::<T>::Reserved { who, para_id: index, value, if_mint });
 			Ok(())
 		}
 
-		#[pallet::call_index(23)]
-		#[pallet::weight(T::WeightInfo::batch_handle_reserve())]
-		pub fn batch_handle_reserve(origin: OriginFor<T>, index: ParaId) -> DispatchResult {
-			let _who = ensure_signed(origin.clone())?;
+		/// Contribute to a crowd sale. This will transfer some balance over to fund a parachain
+		/// slot. It will be withdrawable in two instances: the parachain becomes retired; or the
+		/// slot is unable to be purchased and the timeout expires.
+		pub(crate) fn contribute(
+			origin: OriginFor<T>,
+			index: ParaId,
+			value: BalanceOf<T>,
+		) -> DispatchResult {
+			let who = ensure_signed(origin.clone())?;
+
+			let fund = Funds::<T>::get(index).ok_or(Error::<T>::InvalidParaId)?;
+			ensure!(fund.status == FundStatus::Ongoing, Error::<T>::InvalidFundStatus);
+
+			ensure!(value >= T::MinContribution::get(), Error::<T>::ContributionTooSmall);
+
+			let raised = fund.raised.checked_add(&value).ok_or(Error::<T>::Overflow)?;
+			ensure!(raised <= fund.cap, Error::<T>::CapExceeded);
+
+			let (contributed, status) = Self::contribution(fund.trie_index, &who);
+			ensure!(
+				status == ContributionStatus::Idle ||
+					status == ContributionStatus::Refunded ||
+					status == ContributionStatus::Redeemed ||
+					status == ContributionStatus::Unlocked,
+				Error::<T>::InvalidContributionStatus
+			);
+
+			ensure!(
+				T::MultiCurrency::can_reserve(T::RelayChainToken::get(), &who, value),
+				Error::<T>::NotEnoughBalanceToContribute
+			);
+
+			T::MultiCurrency::reserve(T::RelayChainToken::get(), &who, value)?;
+
+			Self::put_contribution(
+				fund.trie_index,
+				&who,
+				contributed,
+				ContributionStatus::Contributing(value),
+			);
+
+			let message_id = T::XcmInterface::contribute(who.clone(), index, value)?;
+
+			Self::deposit_event(Event::Contributing(who, index, value, message_id));
+			Ok(())
+		}
+
+		/// Confirm contribute
+		pub(crate) fn confirm_contribute(
+			origin: OriginFor<T>,
+			query_id: QueryId,
+			is_success: bool,
+		) -> DispatchResult {
+			let confirmor = ensure_signed(origin.clone())?;
+			if Some(confirmor) != MultisigConfirmAccount::<T>::get() {
+				return Err(DispatchError::BadOrigin.into());
+			}
+
+			let (index, contributer, _amount) = QueryIdContributionInfo::<T>::get(query_id)
+				.ok_or(Error::<T>::NotFindContributionValue)?;
+
+			let fund = Funds::<T>::get(index).ok_or(Error::<T>::InvalidParaId)?;
+			let can_confirm = fund.status == FundStatus::Ongoing ||
+				fund.status == FundStatus::Failed ||
+				fund.status == FundStatus::Success;
+			ensure!(can_confirm, Error::<T>::InvalidFundStatus);
+
+			let (contributed, status) = Self::contribution(fund.trie_index, &contributer);
+			ensure!(status.is_contributing(), Error::<T>::InvalidContributionStatus);
+			let contributing = status.contributing();
 
-			let mut fund = Funds::<T>::get(index).ok_or(Error::<T>::InvalidParaId)?;
 			let vs_token = T::CurrencyIdConversion::convert_to_vstoken(T::RelayChainToken::get())
 				.map_err(|_| Error::<T>::NotSupportTokenType)?;
 			let vs_bond = T::CurrencyIdConversion::convert_to_vsbond(
@@ -1383,90 +1060,61 @@ pub mod pallet {
 			)
 			.map_err(|_| Error::<T>::NotSupportTokenType)?;
 
-			match fund.status {
-				FundStatus::RedeemWithdrew => {
-					ReserveInfos::<T>::iter_prefix(index)
-						.take(T::BatchLimit::get() as usize)
-						.try_for_each(|(contributer, info)| -> DispatchResult {
-							T::MultiCurrency::remove_lock(
-								T::LockId::get(),
-								vs_token,
-								&contributer,
-							)?;
-							T::MultiCurrency::remove_lock(T::LockId::get(), vs_bond, &contributer)?;
-							Self::redeem_for_reserve(
-								contributer.clone(),
-								index,
-								info.value,
-								&mut fund,
-								vs_token,
-								vs_bond,
-							)?;
-							ReserveInfos::<T>::remove(index, &contributer);
-							if info.if_mint {
-								T::VtokenMinting::mint(
-									contributer,
-									T::RelayChainToken::get(),
-									info.value,
-									BoundedVec::default(),
-									None,
-								)
-								.map_err(|_| Error::<T>::NotSupportTokenType)?;
-							}
-							Ok(())
-						})?;
-				},
-				FundStatus::RefundWithdrew => {
-					ReserveInfos::<T>::iter_prefix(index)
-						.take(T::BatchLimit::get() as usize)
-						.try_for_each(|(contributer, info)| -> DispatchResult {
-							T::MultiCurrency::remove_lock(
-								T::LockId::get(),
-								vs_token,
-								&contributer,
-							)?;
-							T::MultiCurrency::remove_lock(T::LockId::get(), vs_bond, &contributer)?;
-							Self::refund_for_reserve(
-								contributer.clone(),
-								index,
-								fund.first_slot,
-								fund.last_slot,
-								info.value,
-								vs_token,
-								vs_bond,
-							)?;
-							ReserveInfos::<T>::remove(index, &contributer);
-							if info.if_mint {
-								T::VtokenMinting::mint(
-									contributer,
-									T::RelayChainToken::get(),
-									info.value,
-									BoundedVec::default(),
-									None,
-								)
-								.map_err(|_| Error::<T>::NotSupportTokenType)?;
-							}
-							Ok(())
-						})?;
-				},
-				_ => return Err(Error::<T>::InvalidFundStatus.into()),
-			}
+			if is_success {
+				// Issue reserved vsToken/vsBond to contributor
+				T::MultiCurrency::deposit(vs_token, &contributer, contributing)?;
+				T::MultiCurrency::deposit(vs_bond, &contributer, contributing)?;
+
+				// Update the raised of fund
+				let fund_new =
+					FundInfo { raised: fund.raised.saturating_add(contributing), ..fund };
+				Funds::<T>::insert(index, Some(fund_new));
+
+				T::MultiCurrency::unreserve(T::RelayChainToken::get(), &contributer, contributing);
+				T::MultiCurrency::transfer(
+					T::RelayChainToken::get(),
+					&contributer,
+					&Self::fund_account_id(index),
+					contributing,
+				)?;
 
-			if ReserveInfos::<T>::iter_prefix(index).count() != 0 {
-				Self::deposit_event(Event::<T>::ReservationHandled { para_id: index });
+				// Update the contribution of contributer
+				let contributed_new = contributed.saturating_add(contributing);
+				Self::put_contribution(
+					fund.trie_index,
+					&contributer,
+					contributed_new,
+					ContributionStatus::Idle,
+				);
+				Self::deposit_event(Event::Contributed(contributer, index, contributing));
 			} else {
-				Self::deposit_event(Event::<T>::ReservationFullyHandled { para_id: index });
+				// Update the contribution of contributer
+				Self::put_contribution(
+					fund.trie_index,
+					&contributer,
+					contributed,
+					ContributionStatus::Idle,
+				);
+				T::MultiCurrency::unreserve(T::RelayChainToken::get(), &contributer, contributing);
+				Self::deposit_event(Event::ContributeFailed(contributer, index, contributing));
 			}
+
+			QueryIdContributionInfo::<T>::remove(query_id);
+
 			Ok(())
 		}
 
-		#[pallet::call_index(24)]
-		#[pallet::weight(T::WeightInfo::cancel_reservation())]
-		pub fn cancel_reservation(origin: OriginFor<T>, index: ParaId) -> DispatchResult {
-			let who = ensure_signed(origin)?;
-
+		/// Unlock the reserved vsToken/vsBond after fund success
+		pub(crate) fn unlock(
+			origin: OriginFor<T>,
+			who: AccountIdOf<T>,
+			index: ParaId,
+		) -> DispatchResult {
+			ensure_signed(origin)?;
 			let fund = Funds::<T>::get(index).ok_or(Error::<T>::InvalidParaId)?;
 
+			let (contributed, _) = Self::contribution(fund.trie_index, &who);
+
 			let vs_token = T::CurrencyIdConversion::convert_to_vstoken(T::RelayChainToken::get())
 				.map_err(|_| Error::<T>::NotSupportTokenType)?;
 			let vs_bond = T::CurrencyIdConversion::convert_to_vsbond(
@@ -1476,48 +1124,17 @@ pub mod pallet {
 				fund.last_slot,
 			)
 			.map_err(|_| Error::<T>::NotSupportTokenType)?;
-			T::MultiCurrency::remove_lock(T::LockId::get(), vs_token, &who)?;
-			T::MultiCurrency::remove_lock(T::LockId::get(), vs_bond, &who)?;
-			ReserveInfos::<T>::remove(index, &who);
 
-			Self::deposit_event(Event::<T>::ReservationCancelled { who, para_id: index });
-			Ok(())
-		}
-	}
+			T::MultiCurrency::unreserve(vs_token, &who, contributed);
+			T::MultiCurrency::unreserve(vs_bond, &who, contributed);
 
-	#[pallet::hooks]
-	impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
-		fn on_initialize(n: BlockNumberFor<T>) -> Weight {
-			// Release x% KSM/DOT from redeem-pool to bancor-pool per cycle
-			if n != Zero::zero() && (n % T::ReleaseCycle::get()) == Zero::zero() {
-				if let Ok(rp_balance) = TryInto::<u128>::try_into(RedeemPool::<T>::get()) {
-					// Calculate the release amount
-					let release_amount = T::ReleaseRatio::get() * rp_balance;
+			Self::deposit_event(Event::<T>::Unlocked(who, index, contributed));
 
-					// Must be ok
-					if let Ok(release_amount) = TryInto::<BalanceOf<T>>::try_into(release_amount) {
-						// Increase the balance of bancor-pool by release-amount
-						if let Ok(()) =
-							T::BancorPool::add_token(T::RelayChainToken::get(), release_amount)
-						{
-							RedeemPool::<T>::set(
-								RedeemPool::<T>::get().saturating_sub(release_amount),
-							);
-						}
-					} else {
-						log::warn!("Overflow: The balance of redeem-pool exceeds u128.");
-					}
-				}
-			}
-			T::DbWeight::get().reads(1)
+			Ok(())
 		}
 	}
 
 	impl<T: Config> Pallet<T> {
-		/// set multisig account
-		pub fn set_multisig_account(account: AccountIdOf<T>) {
-			MultisigConfirmAccount::<T>::put(account);
-		}
 		/// Check if the vsBond is `past` the redeemable date
 		pub(crate) fn is_expired(
 			block: BlockNumberFor<T>,
@@ -1529,18 +1146,6 @@ pub mod pallet {
 			Ok(block >= block_end_redeem)
 		}
 
-		/// Check if the vsBond is `in` the redeemable date
-		#[allow(dead_code)]
-		pub(crate) fn can_redeem(
-			block: BlockNumberFor<T>,
-			last_slot: LeasePeriod,
-		) -> Result<bool, Error<T>> {
-			let block_begin_redeem = Self::block_end_of_lease_period_index(last_slot);
-			let block_end_redeem = block_begin_redeem.saturating_add(T::VSBondValidPeriod::get());
-
-			Ok(block >= block_begin_redeem && block < block_end_redeem)
-		}
-
 		pub(crate) fn block_end_of_lease_period_index(slot: LeasePeriod) -> BlockNumberFor<T> {
 			(BlockNumberFor::<T>::from(slot) + One::one()).saturating_mul(T::LeasePeriod::get())
 		}
@@ -1625,114 +1230,9 @@ pub mod pallet {
 			who.using_encoded(|b| child::kill(&Self::id_from_index(index), b));
 		}
 
-		#[allow(dead_code)]
 		pub(crate) fn set_balance(who: &AccountIdOf<T>, value: BalanceOf<T>) -> DispatchResult {
 			T::MultiCurrency::deposit(T::RelayChainToken::get(), who, value)
 		}
-
-		pub fn redeem_for_reserve(
-			who: AccountIdOf<T>,
-			index: ParaId,
-			value: BalanceOf<T>,
-			fund: &mut FundInfo<BalanceOf<T>, LeasePeriod>,
-			vs_token: CurrencyId,
-			vs_bond: CurrencyId,
-		) -> DispatchResult {
-			ensure!(fund.raised >= value, Error::<T>::NotEnoughBalanceInRedeemPool);
-
-			ensure!(RedeemPool::<T>::get() >= value, Error::<T>::NotEnoughBalanceInRedeemPool);
-			let cur_block = <frame_system::Pallet<T>>::block_number();
-			let expired = Self::is_expired(cur_block, fund.last_slot)?;
-			ensure!(!expired, Error::<T>::VSBondExpired);
-			T::MultiCurrency::ensure_can_withdraw(vs_token, &who, value)
-				.map_err(|_e| Error::<T>::NotEnoughFreeAssetsToRedeem)?;
-			T::MultiCurrency::ensure_can_withdraw(vs_bond, &who, value)
-				.map_err(|_e| Error::<T>::NotEnoughFreeAssetsToRedeem)?;
-
-			T::MultiCurrency::withdraw(vs_token, &who, value)?;
-			T::MultiCurrency::withdraw(vs_bond, &who, value)?;
-			RedeemPool::<T>::set(RedeemPool::<T>::get().saturating_sub(value));
-
-			fund.raised = fund.raised.saturating_sub(value);
-			Funds::<T>::insert(index, Some(fund.clone()));
-
-			T::MultiCurrency::transfer(
-				T::RelayChainToken::get(),
-				&Self::fund_account_id(index),
-				&who,
-				value,
-			)?;
-			Self::deposit_event(Event::Redeemed(
-				who,
-				index,
-				fund.first_slot,
-				fund.last_slot,
-				value,
-			));
-
-			Ok(())
-		}
-
-		pub fn refund_for_reserve(
-			who: AccountIdOf<T>,
-			index: ParaId,
-			first_slot: LeasePeriod,
-			last_slot: LeasePeriod,
-			value: BalanceOf<T>,
-			vs_token: CurrencyId,
-			vs_bond: CurrencyId,
-		) -> DispatchResult {
-			let mut fund = Self::find_fund(index, first_slot, last_slot)
-				.map_err(|_| Error::<T>::InvalidFundNotExist)?;
-			ensure!(
-				fund.status == FundStatus::FailedToContinue ||
-					fund.status == FundStatus::RefundWithdrew,
-				Error::<T>::InvalidRefund
-			);
-			ensure!(
-				fund.first_slot == first_slot && fund.last_slot == last_slot,
-				Error::<T>::InvalidRefund
-			);
-			ensure!(fund.raised >= value, Error::<T>::NotEnoughBalanceInFund);
-			ensure!(RedeemPool::<T>::get() >= value, Error::<T>::NotEnoughBalanceInRefundPool);
-
-			T::MultiCurrency::ensure_can_withdraw(vs_token, &who, value)
-				.map_err(|_e| Error::<T>::NotEnoughFreeAssetsToRedeem)?;
-			T::MultiCurrency::ensure_can_withdraw(vs_bond, &who, value)
-				.map_err(|_e| Error::<T>::NotEnoughFreeAssetsToRedeem)?;
-
-			T::MultiCurrency::withdraw(vs_token, &who, value)?;
-			T::MultiCurrency::withdraw(vs_bond, &who, value)?;
-
-			RedeemPool::<T>::set(RedeemPool::<T>::get().saturating_sub(value));
-			let mut fund_new = Funds::<T>::get(index).ok_or(Error::<T>::InvalidParaId)?;
-			fund_new.raised = fund_new.raised.saturating_sub(value);
-			Funds::<T>::insert(index, Some(fund_new));
-			if fund.status == FundStatus::FailedToContinue {
-				fund.raised = fund.raised.saturating_sub(value);
-				FailedFundsToRefund::<T>::insert(
-					(index, first_slot, last_slot),
-					Some(fund.clone()),
-				);
-			}
-
-			T::MultiCurrency::transfer(
-				T::RelayChainToken::get(),
-				&Self::fund_account_id(index),
-				&who,
-				value,
-			)?;
-
-			Self::deposit_event(Event::Refunded(
-				who,
-				index,
-				fund.first_slot,
-				fund.last_slot,
-				value,
-			));
-
-			Ok(())
-		}
 	}
 }
 
diff --git a/pallets/salp/src/mock.rs b/pallets/salp/src/mock.rs
index 4d1bf1435..e2138c859 100644
--- a/pallets/salp/src/mock.rs
+++ b/pallets/salp/src/mock.rs
@@ -20,7 +20,6 @@
 
 #![cfg(test)]
 
-use crate::*;
 use bifrost_asset_registry::AssetIdMaps;
 use bifrost_primitives::{
 	Amount, Balance, CurrencyId, CurrencyId::*, MessageId, MockXcmExecutor, ParaId, SlpOperator,
@@ -31,7 +30,7 @@ use cumulus_primitives_core::ParaId as Pid;
 use frame_support::{
 	construct_runtime, derive_impl, ord_parameter_types, parameter_types,
 	sp_runtime::{DispatchError, DispatchResult, SaturatedConversion},
-	traits::{ConstU128, ConstU64, EnsureOrigin, Everything, Get, Nothing},
+	traits::{ConstU128, ConstU64, EnsureOrigin, Everything, Get, LockIdentifier, Nothing},
 	weights::Weight,
 	PalletId,
 };
@@ -446,7 +445,6 @@ parameter_types! {
 }
 
 impl salp::Config for Test {
-	type BancorPool = ();
 	type RuntimeEvent = RuntimeEvent;
 	type RuntimeCall = RuntimeCall;
 	type RuntimeOrigin = RuntimeOrigin;
@@ -465,14 +463,10 @@ impl salp::Config for Test {
 	type XcmInterface = MockSalpXcmExecutor;
 	type TreasuryAccount = TreasuryAccount;
 	type BuybackPalletId = BuybackPalletId;
-	type DexOperator = ZenlinkProtocol;
 	type CurrencyIdConversion = AssetIdMaps<Test>;
 	type CurrencyIdRegister = AssetIdMaps<Test>;
-	type ParachainId = ParaInfo;
 	type StablePool = StablePool;
 	type VtokenMinting = VtokenMinting;
-	type LockId = SalpLockId;
-	type BatchLimit = BatchLimit;
 }
 
 parameter_types! {
diff --git a/pallets/salp/src/tests.rs b/pallets/salp/src/tests.rs
index 31d5870cf..40b486f12 100644
--- a/pallets/salp/src/tests.rs
+++ b/pallets/salp/src/tests.rs
@@ -19,142 +19,14 @@
 // Ensure we're `no_std` when compiling for Wasm.
 
 use crate::{mock::*, Error, FundStatus, *};
-use bifrost_primitives::{ContributionStatus, CurrencyId, TokenSymbol, KSM, VKSM, VSKSM};
+use bifrost_primitives::{CurrencyId, TokenSymbol, TryConvertFrom, KSM, VKSM, VSKSM};
 use bifrost_xcm_interface::SalpHelper;
 use frame_support::{assert_noop, assert_ok};
 use frame_system::pallet_prelude::BlockNumberFor;
-use orml_traits::{MultiCurrency, MultiReservableCurrency};
+use orml_traits::MultiCurrency;
 use sp_runtime::{traits::AccountIdConversion, DispatchError};
 use zenlink_protocol::AssetId;
 
-#[test]
-fn create_fund_should_work() {
-	new_test_ext().execute_with(|| {
-		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
-		assert_ok!(Funds::<Test>::get(3_000).ok_or(()));
-		assert_eq!(CurrentTrieIndex::<Test>::get(), 1);
-	});
-}
-
-#[test]
-fn create_fund_with_wrong_origin_should_fail() {
-	new_test_ext().execute_with(|| {
-		assert_noop!(
-			Salp::create(RuntimeOrigin::none(), 3_000, 1_000, 1, SlotLength::get()),
-			DispatchError::BadOrigin,
-		);
-	});
-}
-
-#[test]
-fn create_fund_existed_should_fail() {
-	new_test_ext().execute_with(|| {
-		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
-
-		assert_noop!(
-			Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()),
-			Error::<Test>::FundAlreadyCreated,
-		);
-	});
-}
-
-#[test]
-fn create_fund_exceed_slot_limit_should_fail() {
-	new_test_ext().execute_with(|| {
-		assert_noop!(
-			Salp::create(Some(ALICE).into(), 3_000, 1_000, 0, SlotLength::get()),
-			Error::<Test>::LastSlotTooFarInFuture,
-		);
-	});
-}
-
-#[test]
-fn create_fund_first_slot_bigger_than_last_slot_should_fail() {
-	new_test_ext().execute_with(|| {
-		assert_noop!(
-			Salp::create(Some(ALICE).into(), 3_000, 1_000, SlotLength::get(), 0),
-			Error::<Test>::LastSlotBeforeFirstSlot,
-		);
-	});
-}
-
-#[test]
-fn set_fund_success_should_work() {
-	new_test_ext().execute_with(|| {
-		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
-		assert_ok!(Salp::fund_success(Some(ALICE).into(), 3_000));
-
-		// Check status
-		let fund = Funds::<Test>::get(3_000).unwrap();
-		assert_eq!(fund.status, FundStatus::Success);
-	});
-}
-
-#[test]
-fn set_fund_success_with_wrong_origin_should_fail() {
-	new_test_ext().execute_with(|| {
-		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
-		assert_noop!(Salp::fund_success(RuntimeOrigin::none(), 3_000), DispatchError::BadOrigin);
-	})
-}
-
-#[test]
-fn set_fund_success_with_wrong_para_id_should_fail() {
-	new_test_ext().execute_with(|| {
-		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
-		assert_noop!(Salp::fund_success(Some(ALICE).into(), 4_000), Error::<Test>::InvalidParaId);
-	});
-}
-
-#[test]
-fn set_fund_success_with_wrong_fund_status_should_fail() {
-	new_test_ext().execute_with(|| {
-		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
-		assert_ok!(Salp::fund_fail(Some(ALICE).into(), 3_000));
-		assert_noop!(
-			Salp::fund_success(Some(ALICE).into(), 3_000),
-			Error::<Test>::InvalidFundStatus
-		);
-	});
-}
-
-#[test]
-fn set_fund_fail_should_work() {
-	new_test_ext().execute_with(|| {
-		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
-		assert_ok!(Salp::fund_fail(Some(ALICE).into(), 3_000));
-
-		// Check status
-		let fund = Funds::<Test>::get(3_000).unwrap();
-		assert_eq!(fund.status, FundStatus::Failed);
-	});
-}
-
-#[test]
-fn set_fund_fail_with_wrong_origin_should_fail() {
-	new_test_ext().execute_with(|| {
-		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
-		assert_noop!(Salp::fund_fail(RuntimeOrigin::none(), 3_000), DispatchError::BadOrigin);
-	});
-}
-
-#[test]
-fn set_fund_fail_with_wrong_para_id_should_fail() {
-	new_test_ext().execute_with(|| {
-		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
-		assert_noop!(Salp::fund_fail(Some(ALICE).into(), 4_000), Error::<Test>::InvalidParaId);
-	});
-}
-
-#[test]
-fn set_fund_fail_with_wrong_fund_status_should_fail() {
-	new_test_ext().execute_with(|| {
-		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
-		assert_ok!(Salp::fund_success(Some(ALICE).into(), 3_000));
-		assert_noop!(Salp::fund_fail(Some(ALICE).into(), 3_000), Error::<Test>::InvalidFundStatus);
-	});
-}
-
 #[test]
 fn set_fund_retire_should_work() {
 	new_test_ext().execute_with(|| {
@@ -246,317 +118,6 @@ fn set_fund_end_with_wrong_fund_status_should_fail() {
 	});
 }
 
-#[test]
-fn unlock_should_work() {
-	new_test_ext().execute_with(|| {
-		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
-		assert_ok!(Salp::contribute(Some(BRUCE).into(), 3_000, 100));
-		Salp::bind_query_id_and_contribution(0, 3_000, BRUCE, 100);
-		assert_ok!(Salp::confirm_contribute(Some(ALICE).into(), 0, true,));
-		assert_ok!(Salp::fund_success(Some(ALICE).into(), 3_000));
-		assert_ok!(Salp::unlock(Some(BRUCE).into(), BRUCE, 3_000));
-
-		let vs_token =
-			<Test as Config>::CurrencyIdConversion::convert_to_vstoken(RelayCurrencyId::get())
-				.unwrap();
-		let vs_bond = <Test as Config>::CurrencyIdConversion::convert_to_vsbond(
-			RelayCurrencyId::get(),
-			3_000,
-			1,
-			SlotLength::get(),
-		)
-		.unwrap();
-
-		assert_eq!(Tokens::accounts(BRUCE, vs_token).free, 100);
-		assert_eq!(Tokens::accounts(BRUCE, vs_token).frozen, 0);
-		assert_eq!(Tokens::accounts(BRUCE, vs_token).reserved, 0);
-		assert_eq!(Tokens::accounts(BRUCE, vs_bond).free, 100);
-		assert_eq!(Tokens::accounts(BRUCE, vs_bond).frozen, 0);
-		assert_eq!(Tokens::accounts(BRUCE, vs_bond).reserved, 0);
-	});
-}
-
-#[test]
-fn unlock_by_vsbond_should_work() {
-	new_test_ext().execute_with(|| {
-		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
-		assert_ok!(Salp::contribute(Some(BRUCE).into(), 3_000, 100));
-		Salp::bind_query_id_and_contribution(0, 3_000, BRUCE, 100);
-		assert_ok!(Salp::confirm_contribute(Some(ALICE).into(), 0, true,));
-		assert_ok!(Salp::fund_success(Some(ALICE).into(), 3_000));
-
-		let vs_token =
-			<Test as Config>::CurrencyIdConversion::convert_to_vstoken(RelayCurrencyId::get())
-				.unwrap();
-		let vs_bond = <Test as Config>::CurrencyIdConversion::convert_to_vsbond(
-			RelayCurrencyId::get(),
-			3_000,
-			1,
-			SlotLength::get(),
-		)
-		.unwrap();
-
-		assert_ok!(Salp::unlock_by_vsbond(Some(BRUCE).into(), BRUCE, vs_bond));
-		assert_eq!(Tokens::accounts(BRUCE, vs_token).free, 100);
-		assert_eq!(Tokens::accounts(BRUCE, vs_token).frozen, 0);
-		assert_eq!(Tokens::accounts(BRUCE, vs_token).reserved, 0);
-		assert_eq!(Tokens::accounts(BRUCE, vs_bond).free, 100);
-		assert_eq!(Tokens::accounts(BRUCE, vs_bond).frozen, 0);
-		assert_eq!(Tokens::accounts(BRUCE, vs_bond).reserved, 0);
-	});
-}
-
-#[test]
-fn unlock_vstoken_should_work() {
-	new_test_ext().execute_with(|| {
-		let vs_token =
-			<Test as Config>::CurrencyIdConversion::convert_to_vstoken(RelayCurrencyId::get())
-				.unwrap();
-		assert_ok!(<Test as Config>::MultiCurrency::reserve(vs_token, &ALICE, 1));
-
-		assert_eq!(Tokens::accounts(ALICE, vs_token).free, 99999);
-		assert_eq!(Tokens::accounts(ALICE, vs_token).frozen, 0);
-		assert_eq!(Tokens::accounts(ALICE, vs_token).reserved, 1);
-		assert_ok!(Salp::unlock_vstoken(Some(BRUCE).into(), ALICE));
-		assert_eq!(Tokens::accounts(ALICE, vs_token).free, 100000);
-		assert_eq!(Tokens::accounts(ALICE, vs_token).frozen, 0);
-		assert_eq!(Tokens::accounts(ALICE, vs_token).reserved, 0);
-
-		assert_ok!(Salp::create(Some(ALICE).into(), 2_100, 1_000, 18, 25));
-		assert_ok!(Salp::contribute(Some(BRUCE).into(), 2_100, 100));
-		Salp::bind_query_id_and_contribution(0, 2_100, BRUCE, 100);
-		assert_ok!(Salp::confirm_contribute(Some(ALICE).into(), 0, true,));
-		assert_ok!(Salp::fund_success(Some(ALICE).into(), 2_100));
-		let vs_bond = <Test as Config>::CurrencyIdConversion::convert_to_vsbond(
-			RelayCurrencyId::get(),
-			2_100,
-			18,
-			25,
-		)
-		.unwrap();
-		assert_ok!(<Test as Config>::MultiCurrency::reserve(vs_bond, &BRUCE, 1));
-		assert_eq!(Tokens::accounts(BRUCE, vs_bond).free, 99);
-		assert_eq!(Tokens::accounts(BRUCE, vs_bond).frozen, 0);
-		assert_eq!(Tokens::accounts(BRUCE, vs_bond).reserved, 1);
-		assert_ok!(Salp::unlock_vstoken(Some(BRUCE).into(), BRUCE));
-		assert_eq!(Tokens::accounts(BRUCE, vs_bond).free, 100);
-		assert_eq!(Tokens::accounts(BRUCE, vs_bond).frozen, 0);
-		assert_eq!(Tokens::accounts(BRUCE, vs_bond).reserved, 0);
-	});
-}
-
-#[test]
-fn contribute_should_work() {
-	new_test_ext().execute_with(|| {
-		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
-		assert_ok!(Salp::contribute(Some(BRUCE).into(), 3_000, 100));
-		Salp::bind_query_id_and_contribution(0, 3_000, BRUCE, 100);
-		assert_ok!(Salp::confirm_contribute(Some(ALICE).into(), 0, true));
-
-		let fund = Funds::<Test>::get(3_000).unwrap();
-		let (contributed, status) = Salp::contribution(fund.trie_index, &BRUCE);
-		assert_eq!(fund.raised, 100);
-		assert_eq!(contributed, 100);
-		assert_eq!(status, ContributionStatus::Idle);
-
-		let vs_token =
-			<Test as Config>::CurrencyIdConversion::convert_to_vstoken(RelayCurrencyId::get())
-				.unwrap();
-		let vs_bond = <Test as Config>::CurrencyIdConversion::convert_to_vsbond(
-			RelayCurrencyId::get(),
-			3_000,
-			1,
-			SlotLength::get(),
-		)
-		.unwrap();
-		assert_eq!(Tokens::accounts(BRUCE, vs_token).free, 100);
-		assert_eq!(Tokens::accounts(BRUCE, vs_bond).free, 100);
-	});
-}
-
-#[test]
-fn double_contribute_should_work() {
-	new_test_ext().execute_with(|| {
-		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
-		assert_ok!(Salp::contribute(Some(BRUCE).into(), 3_000, 100));
-		Salp::bind_query_id_and_contribution(0, 3_000, BRUCE, 100);
-		assert_ok!(Salp::confirm_contribute(Some(ALICE).into(), 0, true,));
-		assert_ok!(Salp::contribute(Some(BRUCE).into(), 3_000, 100));
-		Salp::bind_query_id_and_contribution(0, 3_000, BRUCE, 100);
-		assert_ok!(Salp::confirm_contribute(Some(ALICE).into(), 0, true,));
-
-		// Check the contribution
-		let fund = Funds::<Test>::get(3_000).unwrap();
-		let (contributed, status) = Salp::contribution(fund.trie_index, &BRUCE);
-		assert_eq!(fund.raised, 200);
-		assert_eq!(contributed, 200);
-		assert_eq!(status, ContributionStatus::Idle);
-
-		let vs_token =
-			<Test as Config>::CurrencyIdConversion::convert_to_vstoken(RelayCurrencyId::get())
-				.unwrap();
-		let vs_bond = <Test as Config>::CurrencyIdConversion::convert_to_vsbond(
-			RelayCurrencyId::get(),
-			3_000,
-			1,
-			SlotLength::get(),
-		)
-		.unwrap();
-		assert_eq!(Tokens::accounts(BRUCE, vs_token).free, 200);
-		assert_eq!(Tokens::accounts(BRUCE, vs_bond).free, 200);
-	});
-}
-
-#[test]
-fn contribute_when_xcm_error_should_work() {
-	new_test_ext().execute_with(|| {
-		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
-		assert_ok!(Salp::contribute(Some(BRUCE).into(), 3_000, 100));
-		Salp::bind_query_id_and_contribution(0, 3_000, BRUCE, 100);
-		assert_ok!(Salp::confirm_contribute(Some(ALICE).into(), 0, false,));
-
-		let fund = Funds::<Test>::get(3_000).unwrap();
-		let (contributed, status) = Salp::contribution(fund.trie_index, &BRUCE);
-		assert_eq!(fund.raised, 0);
-		assert_eq!(contributed, 0);
-		assert_eq!(status, ContributionStatus::Idle);
-
-		let vs_token =
-			<Test as Config>::CurrencyIdConversion::convert_to_vstoken(RelayCurrencyId::get())
-				.unwrap();
-		let vs_bond = <Test as Config>::CurrencyIdConversion::convert_to_vsbond(
-			RelayCurrencyId::get(),
-			3_000,
-			1,
-			SlotLength::get(),
-		)
-		.unwrap();
-		assert_eq!(Tokens::accounts(BRUCE, vs_token).free, 0);
-		assert_eq!(Tokens::accounts(BRUCE, vs_token).frozen, 0);
-		assert_eq!(Tokens::accounts(BRUCE, vs_token).reserved, 0);
-		assert_eq!(Tokens::accounts(BRUCE, vs_bond).free, 0);
-		assert_eq!(Tokens::accounts(BRUCE, vs_bond).frozen, 0);
-		assert_eq!(Tokens::accounts(BRUCE, vs_bond).reserved, 0);
-	});
-}
-
-#[test]
-fn confirm_contribute_later_should_work() {
-	new_test_ext().execute_with(|| {
-		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
-		assert_ok!(Salp::contribute(Some(BRUCE).into(), 3_000, 100));
-		Salp::bind_query_id_and_contribution(0, 3_000, BRUCE, 100);
-		assert_ok!(Salp::fund_success(Some(ALICE).into(), 3_000));
-		assert_ok!(Salp::confirm_contribute(Some(ALICE).into(), 0, true,));
-
-		let fund = Funds::<Test>::get(3_000).unwrap();
-		let (contributed, status) = Salp::contribution(fund.trie_index, &BRUCE);
-		assert_eq!(fund.raised, 100);
-		assert_eq!(contributed, 100);
-		assert_eq!(status, ContributionStatus::Idle);
-
-		let vs_token =
-			<Test as Config>::CurrencyIdConversion::convert_to_vstoken(RelayCurrencyId::get())
-				.unwrap();
-		let vs_bond = <Test as Config>::CurrencyIdConversion::convert_to_vsbond(
-			RelayCurrencyId::get(),
-			3_000,
-			1,
-			SlotLength::get(),
-		)
-		.unwrap();
-		assert_eq!(Tokens::accounts(BRUCE, vs_token).free, 100);
-		assert_eq!(Tokens::accounts(BRUCE, vs_bond).free, 100);
-	});
-}
-
-#[test]
-fn contribute_with_wrong_origin_should_fail() {
-	new_test_ext().execute_with(|| {
-		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
-		assert_noop!(Salp::contribute(RuntimeOrigin::none(), 3_000, 100), DispatchError::BadOrigin);
-
-		assert_noop!(
-			Salp::confirm_contribute(RuntimeOrigin::none(), 0, true),
-			DispatchError::BadOrigin,
-		);
-	});
-}
-
-#[test]
-fn contribute_with_low_contribution_should_fail() {
-	new_test_ext().execute_with(|| {
-		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
-		assert_noop!(
-			Salp::contribute(Some(BRUCE).into(), 3_000, MinContribution::get() - 1),
-			Error::<Test>::ContributionTooSmall
-		);
-	});
-}
-
-#[test]
-fn contribute_with_wrong_para_id_should_fail() {
-	new_test_ext().execute_with(|| {
-		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
-		assert_noop!(
-			Salp::contribute(Some(BRUCE).into(), 4_000, 100),
-			Error::<Test>::InvalidParaId
-		);
-	});
-}
-
-#[test]
-fn contribute_with_wrong_fund_status_should_fail() {
-	new_test_ext().execute_with(|| {
-		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
-		assert_ok!(Salp::fund_success(Some(ALICE).into(), 3_000,));
-		assert_noop!(
-			Salp::contribute(Some(BRUCE).into(), 3_000, 100),
-			Error::<Test>::InvalidFundStatus
-		);
-	});
-}
-
-#[test]
-fn contribute_exceed_cap_should_fail() {
-	new_test_ext().execute_with(|| {
-		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
-		assert_noop!(
-			Salp::contribute(Some(BRUCE).into(), 3_000, 1_001),
-			Error::<Test>::CapExceeded
-		);
-	});
-}
-
-#[test]
-fn contribute_when_contributing_should_fail() {
-	new_test_ext().execute_with(|| {
-		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
-		assert_noop!(
-			Salp::confirm_contribute(Some(ALICE).into(), 0, true),
-			Error::<Test>::NotFindContributionValue
-		);
-	});
-}
-
-#[test]
-fn confirm_contribute_when_not_in_contributing_should_fail() {
-	new_test_ext().execute_with(|| {
-		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
-		assert_ok!(Salp::contribute(Some(BRUCE).into(), 3_000, 100));
-
-		assert_noop!(
-			Salp::contribute(Some(BRUCE).into(), 3_000, 100),
-			Error::<Test>::InvalidContributionStatus
-		);
-	});
-}
-
-#[test]
-fn contribute_with_when_ump_wrong_should_fail() {
-	// TODO: Require an solution to settle with parallel test workflow
-}
-
 #[test]
 fn withdraw_should_work() {
 	new_test_ext().execute_with(|| {
@@ -1184,18 +745,6 @@ fn check_next_trie_index() {
 	});
 }
 
-#[test]
-fn batch_unlock_should_work() {
-	new_test_ext().execute_with(|| {
-		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
-		assert_ok!(Salp::contribute(Some(BRUCE).into(), 3_000, 100));
-		Salp::bind_query_id_and_contribution(0, 3_000, BRUCE, 100);
-		assert_ok!(Salp::confirm_contribute(Some(ALICE).into(), 0, true,));
-		assert_ok!(Salp::fund_success(Some(ALICE).into(), 3_000));
-		assert_ok!(Salp::batch_unlock(Some(ALICE).into(), 3_000));
-	})
-}
-
 #[test]
 fn unlock_when_fund_ongoing_should_work() {
 	new_test_ext().execute_with(|| {
@@ -1225,21 +774,6 @@ fn unlock_when_fund_ongoing_should_work() {
 	});
 }
 
-#[test]
-fn set_confirmor_should_work() {
-	new_test_ext().execute_with(|| {
-		assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
-		assert_ok!(Salp::contribute(Some(BRUCE).into(), 3_000, 100));
-		Salp::bind_query_id_and_contribution(0, 3_000, BRUCE, 100);
-		assert_noop!(
-			Salp::confirm_contribute(Some(BRUCE).into(), 0, true),
-			DispatchError::BadOrigin,
-		);
-		assert_ok!(Salp::set_multisig_confirm_account(Some(ALICE).into(), BRUCE));
-		assert_ok!(Salp::confirm_contribute(Some(BRUCE).into(), 0, true,));
-	});
-}
-
 #[test]
 fn refund_meanwhile_issue_should_work() {
 	new_test_ext().execute_with(|| {
@@ -1361,15 +895,6 @@ fn refund_meanwhile_issue_should_work() {
 			1,
 			deadline
 		));
-		assert_noop!(
-			Salp::buyback(Some(ALICE).into(), 80),
-			orml_tokens::Error::<Test>::BalanceTooLow
-		);
-		assert_ok!(Salp::buyback(Some(ALICE).into(), 70));
-		assert_noop!(
-			Salp::buyback(Some(ALICE).into(), 10),
-			zenlink_protocol::Error::<Test>::InsufficientTargetAmount
-		);
 
 		let amounts = vec![1_000u128, 1_000u128];
 		assert_ok!(StablePool::create_pool(
@@ -1489,116 +1014,3 @@ fn edit_fund_should_work() {
 		assert_eq!(fund.status, FundStatus::Ongoing);
 	});
 }
-
-fn reserve_init() -> (CurrencyId, CurrencyId) {
-	assert_ok!(Salp::create(Some(ALICE).into(), 3_000, 1_000, 1, SlotLength::get()));
-	assert_ok!(Salp::contribute(Some(BRUCE).into(), 3_000, 100));
-	Salp::bind_query_id_and_contribution(0, 3_000, BRUCE, 100);
-	assert_ok!(Salp::confirm_contribute(Some(ALICE).into(), 0, true,));
-
-	assert_ok!(Salp::fund_success(Some(ALICE).into(), 3_000));
-	assert_ok!(Salp::unlock(Some(BRUCE).into(), BRUCE, 3_000));
-
-	// Mock the BlockNumber
-	let block_begin_redeem = (SlotLength::get() + 1) * LeasePeriod::get();
-	System::set_block_number(block_begin_redeem.into());
-
-	let vs_token =
-		<Test as Config>::CurrencyIdConversion::convert_to_vstoken(RelayCurrencyId::get()).unwrap();
-	let vs_bond = <Test as Config>::CurrencyIdConversion::convert_to_vsbond(
-		RelayCurrencyId::get(),
-		3_000,
-		1,
-		SlotLength::get(),
-	)
-	.unwrap();
-	(vs_token, vs_bond)
-}
-
-#[test]
-fn batch_handle_reserve_should_work() {
-	new_test_ext().execute_with(|| {
-		let (vs_token, vs_bond) = reserve_init();
-
-		assert_ok!(Salp::reserve(Some(BRUCE).into(), 3_000, 50, false));
-		assert_ok!(<Tokens as MultiCurrency<AccountId>>::transfer(vs_token, &BRUCE, &CATHI, 50));
-		assert_ok!(<Tokens as MultiCurrency<AccountId>>::transfer(vs_bond, &BRUCE, &CATHI, 50));
-		assert_ok!(Salp::reserve(Some(CATHI).into(), 3_000, 10, false));
-		assert_ok!(Salp::reserve(Some(CATHI).into(), 3_000, 40, false));
-		assert_eq!(Tokens::accounts(CATHI, vs_token).frozen, 50);
-		assert_ok!(Salp::fund_retire(Some(ALICE).into(), 3_000));
-		assert_ok!(Salp::withdraw(Some(ALICE).into(), 3_000));
-
-		assert_eq!(Tokens::accounts(BRUCE, vs_token).free, 50);
-		assert_ok!(Salp::batch_handle_reserve(Some(BRUCE).into(), 3_000));
-		assert_eq!(ReserveInfos::<Test>::get(3_000, BRUCE).value, 0);
-
-		assert_eq!(Tokens::accounts(BRUCE, vs_token).free, 0);
-		assert_eq!(Tokens::accounts(BRUCE, vs_token).frozen, 0);
-		assert_eq!(Tokens::accounts(BRUCE, vs_token).reserved, 0);
-		assert_eq!(Tokens::accounts(BRUCE, vs_bond).free, 0);
-		assert_eq!(Tokens::accounts(BRUCE, vs_bond).frozen, 0);
-		assert_eq!(Tokens::accounts(BRUCE, vs_bond).reserved, 0);
-		assert_eq!(Tokens::accounts(BRUCE, RelayCurrencyId::get()).free, INIT_BALANCE - 50);
-		assert_eq!(Tokens::accounts(BRUCE, RelayCurrencyId::get()).frozen, 0);
-		assert_eq!(Tokens::accounts(BRUCE, RelayCurrencyId::get()).reserved, 0);
-
-		assert_eq!(Tokens::accounts(CATHI, vs_token).free, 0);
-		assert_eq!(Tokens::accounts(CATHI, vs_token).frozen, 0);
-		assert_eq!(Tokens::accounts(CATHI, vs_token).reserved, 0);
-		assert_eq!(Tokens::accounts(CATHI, vs_bond).free, 0);
-		assert_eq!(Tokens::accounts(CATHI, vs_bond).frozen, 0);
-		assert_eq!(Tokens::accounts(CATHI, vs_bond).reserved, 0);
-		assert_eq!(Tokens::accounts(CATHI, RelayCurrencyId::get()).free, INIT_BALANCE + 50);
-		assert_eq!(Tokens::accounts(CATHI, RelayCurrencyId::get()).frozen, 0);
-		assert_eq!(Tokens::accounts(CATHI, RelayCurrencyId::get()).reserved, 0);
-	});
-}
-
-#[test]
-fn batch_handle_reserve_should_fail() {
-	new_test_ext().execute_with(|| {
-		let (_vs_token, _vs_bond) = reserve_init();
-
-		assert_noop!(
-			Salp::batch_handle_reserve(Some(BRUCE).into(), 3_000),
-			Error::<Test>::InvalidFundStatus,
-		);
-		assert_ok!(Salp::reserve(Some(BRUCE).into(), 3_000, 100, false));
-		assert_noop!(
-			Salp::batch_handle_reserve(Some(BRUCE).into(), 3_000),
-			Error::<Test>::InvalidFundStatus,
-		);
-	});
-}
-
-#[test]
-fn reserve_should_fail() {
-	new_test_ext().execute_with(|| {
-		let (_vs_token, _vs_bond) = reserve_init();
-
-		assert_noop!(
-			Salp::reserve(Some(CATHI).into(), 3_000, 10, false),
-			orml_tokens::Error::<Test>::BalanceTooLow,
-		);
-	});
-}
-
-#[test]
-fn reserve_should_work() {
-	new_test_ext().execute_with(|| {
-		let (vs_token, _vs_bond) = reserve_init();
-
-		assert_eq!(Tokens::accounts(BRUCE, vs_token).frozen, 0);
-		assert_ok!(Salp::reserve(Some(BRUCE).into(), 3_000, 100, false));
-		assert_eq!(Tokens::accounts(BRUCE, vs_token).frozen, 100);
-		assert_eq!(Tokens::accounts(BRUCE, vs_token).free, 100);
-		assert_ok!(Salp::cancel_reservation(Some(BRUCE).into(), 3_000));
-		assert_ok!(Salp::cancel_reservation(Some(BRUCE).into(), 3_000));
-		assert_eq!(Tokens::accounts(BRUCE, vs_token).frozen, 0);
-		assert_ok!(Salp::reserve(Some(BRUCE).into(), 3_000, 50, false));
-		assert_eq!(ReserveInfos::<Test>::get(3_000, BRUCE).value, 50);
-		assert_eq!(Tokens::accounts(BRUCE, vs_token).frozen, 50);
-		assert_eq!(Tokens::accounts(BRUCE, vs_token).free, 100);
-	});
-}
diff --git a/pallets/salp/src/weights.rs b/pallets/salp/src/weights.rs
index 50abb1130..c82206189 100644
--- a/pallets/salp/src/weights.rs
+++ b/pallets/salp/src/weights.rs
@@ -56,7 +56,6 @@ pub trait WeightInfo {
 	fn contribute() -> Weight;
 	fn refund() -> Weight;
 	fn unlock() -> Weight;
-	fn batch_unlock() -> Weight;
 	fn redeem() -> Weight;
 	fn set_multisig_confirm_account() -> Weight;
 	fn fund_success() -> Weight;
@@ -72,9 +71,6 @@ pub trait WeightInfo {
 	fn dissolve() -> Weight;
 	fn buyback() -> Weight;
 	fn buyback_vstoken_by_stable_pool() -> Weight;
-	fn reserve() -> Weight;
-	fn batch_handle_reserve() -> Weight;
-	fn cancel_reservation() -> Weight;
 }
 
 // For backwards compatibility and tests
@@ -146,25 +142,6 @@ impl WeightInfo for () {
 			.saturating_add(RocksDbWeight::get().reads(5_u64))
 			.saturating_add(RocksDbWeight::get().writes(2_u64))
 	}
-	/// Storage: Salp Funds (r:1 w:0)
-	/// Proof Skipped: Salp Funds (max_values: None, max_size: None, mode: Measured)
-	/// Storage: Tokens Accounts (r:2 w:2)
-	/// Proof: Tokens Accounts (max_values: None, max_size: Some(118), added: 2593, mode: MaxEncodedLen)
-	/// Storage: AssetRegistry CurrencyMetadatas (r:1 w:0)
-	/// Proof Skipped: AssetRegistry CurrencyMetadatas (max_values: None, max_size: None, mode: Measured)
-	/// Storage: unknown `0x` (r:1 w:0)
-	/// Proof Skipped: unknown `0x` (r:1 w:0)
-	/// Storage: unknown `0xd861ea1ebf4800d4b89f4ff787ad79ee96d9a708c85b57da7eb8f9ddeda61291` (r:1 w:0)
-	/// Proof Skipped: unknown `0xd861ea1ebf4800d4b89f4ff787ad79ee96d9a708c85b57da7eb8f9ddeda61291` (r:1 w:0)
-	fn batch_unlock() -> Weight {
-		// Proof Size summary in bytes:
-		//  Measured:  `1995`
-		//  Estimated: `6176`
-		// Minimum execution time: 143_054_000 picoseconds.
-		Weight::from_parts(146_914_000, 6176)
-			.saturating_add(RocksDbWeight::get().reads(6_u64))
-			.saturating_add(RocksDbWeight::get().writes(2_u64))
-	}
 	/// Storage: Salp Funds (r:1 w:1)
 	/// Proof Skipped: Salp Funds (max_values: None, max_size: None, mode: Measured)
 	/// Storage: Salp RedeemPool (r:1 w:1)
@@ -389,70 +366,4 @@ impl WeightInfo for () {
 			.saturating_add(RocksDbWeight::get().reads(10_u64))
 			.saturating_add(RocksDbWeight::get().writes(6_u64))
 	}
-	/// Storage: Salp Funds (r:1 w:0)
-	/// Proof Skipped: Salp Funds (max_values: None, max_size: None, mode: Measured)
-	/// Storage: Tokens Accounts (r:2 w:2)
-	/// Proof: Tokens Accounts (max_values: None, max_size: Some(118), added: 2593, mode: MaxEncodedLen)
-	/// Storage: Salp ReserveInfos (r:1 w:1)
-	/// Proof Skipped: Salp ReserveInfos (max_values: None, max_size: None, mode: Measured)
-	/// Storage: Tokens Locks (r:2 w:2)
-	/// Proof: Tokens Locks (max_values: None, max_size: Some(1271), added: 3746, mode: MaxEncodedLen)
-	/// Storage: AssetRegistry CurrencyMetadatas (r:1 w:0)
-	/// Proof Skipped: AssetRegistry CurrencyMetadatas (max_values: None, max_size: None, mode: Measured)
-	fn reserve() -> Weight {
-		// Proof Size summary in bytes:
-		//  Measured:  `1737`
-		//  Estimated: `8482`
-		// Minimum execution time: 807_976_000 picoseconds.
-		Weight::from_parts(814_218_000, 0)
-			.saturating_add(Weight::from_parts(0, 8482))
-			.saturating_add(RocksDbWeight::get().reads(7))
-			.saturating_add(RocksDbWeight::get().writes(5))
-	}
-	/// Storage: Salp Funds (r:1 w:0)
-	/// Proof Skipped: Salp Funds (max_values: None, max_size: None, mode: Measured)
-	/// Storage: Tokens Locks (r:2 w:2)
-	/// Proof: Tokens Locks (max_values: None, max_size: Some(1271), added: 3746, mode: MaxEncodedLen)
-	/// Storage: Tokens Accounts (r:2 w:2)
-	/// Proof: Tokens Accounts (max_values: None, max_size: Some(118), added: 2593, mode: MaxEncodedLen)
-	/// Storage: AssetRegistry CurrencyMetadatas (r:1 w:0)
-	/// Proof Skipped: AssetRegistry CurrencyMetadatas (max_values: None, max_size: None, mode: Measured)
-	/// Storage: Salp ReserveInfos (r:0 w:1)
-	/// Proof Skipped: Salp ReserveInfos (max_values: None, max_size: None, mode: Measured)
-	fn cancel_reservation() -> Weight {
-		// Proof Size summary in bytes:
-		//  Measured:  `1935`
-		//  Estimated: `8482`
-		// Minimum execution time: 853_491_000 picoseconds.
-		Weight::from_parts(858_070_000, 0)
-			.saturating_add(Weight::from_parts(0, 8482))
-			.saturating_add(RocksDbWeight::get().reads(6))
-			.saturating_add(RocksDbWeight::get().writes(5))
-	}
-	/// Storage: Salp Funds (r:1 w:1)
-	/// Proof Skipped: Salp Funds (max_values: None, max_size: None, mode: Measured)
-	/// Storage: Salp ReserveInfos (r:2 w:1)
-	/// Proof Skipped: Salp ReserveInfos (max_values: None, max_size: None, mode: Measured)
-	/// Storage: Tokens Locks (r:2 w:2)
-	/// Proof: Tokens Locks (max_values: None, max_size: Some(1271), added: 3746, mode: MaxEncodedLen)
-	/// Storage: Tokens Accounts (r:4 w:4)
-	/// Proof: Tokens Accounts (max_values: None, max_size: Some(118), added: 2593, mode: MaxEncodedLen)
-	/// Storage: AssetRegistry CurrencyMetadatas (r:1 w:0)
-	/// Proof Skipped: AssetRegistry CurrencyMetadatas (max_values: None, max_size: None, mode: Measured)
-	/// Storage: Salp RedeemPool (r:1 w:1)
-	/// Proof Skipped: Salp RedeemPool (max_values: Some(1), max_size: None, mode: Measured)
-	/// Storage: Tokens TotalIssuance (r:2 w:2)
-	/// Proof: Tokens TotalIssuance (max_values: None, max_size: Some(38), added: 2513, mode: MaxEncodedLen)
-	/// Storage: System Account (r:1 w:1)
-	/// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen)
-	fn batch_handle_reserve() -> Weight {
-		// Proof Size summary in bytes:
-		//  Measured:  `2540`
-		//  Estimated: `11362`
-		// Minimum execution time: 1_848_798_000 picoseconds.
-		Weight::from_parts(1_859_469_000, 0)
-			.saturating_add(Weight::from_parts(0, 11362))
-			.saturating_add(RocksDbWeight::get().reads(14))
-			.saturating_add(RocksDbWeight::get().writes(12))
-	}
 }
diff --git a/primitives/src/traits.rs b/primitives/src/traits.rs
index dc36f5fc1..a3423ec73 100644
--- a/primitives/src/traits.rs
+++ b/primitives/src/traits.rs
@@ -31,7 +31,7 @@ use sp_runtime::{
 	traits::{
 		AccountIdConversion, AtLeast32BitUnsigned, ConstU32, MaybeSerializeDeserialize, Zero,
 	},
-	BoundedVec, DispatchError, DispatchResult, TokenError, TypeId,
+	BoundedVec, DispatchError, DispatchResult, TypeId,
 };
 use sp_std::{cmp::Ordering, fmt::Debug, vec::Vec};
 
@@ -81,16 +81,6 @@ pub trait MultiCurrencyExt<AccountId> {
 	) -> DispatchResult;
 }
 
-pub trait BancorHandler<Balance> {
-	fn add_token(currency_id: super::CurrencyId, amount: Balance) -> DispatchResult;
-}
-
-impl<Balance> BancorHandler<Balance> for () {
-	fn add_token(_currency_id: super::CurrencyId, _amount: Balance) -> DispatchResult {
-		DispatchResult::from(DispatchError::Token(TokenError::FundsUnavailable))
-	}
-}
-
 pub trait CheckSubAccount<T: Encode + Decode> {
 	fn check_sub_account<S: Decode>(&self, account: &T) -> bool;
 }
diff --git a/runtime/bifrost-kusama/src/lib.rs b/runtime/bifrost-kusama/src/lib.rs
index 24fe2de75..130d63e80 100644
--- a/runtime/bifrost-kusama/src/lib.rs
+++ b/runtime/bifrost-kusama/src/lib.rs
@@ -1147,7 +1147,6 @@ parameter_types! {
 }
 
 impl bifrost_salp::Config for Runtime {
-	type BancorPool = ();
 	type RuntimeEvent = RuntimeEvent;
 	type RuntimeOrigin = RuntimeOrigin;
 	type RuntimeCall = RuntimeCall;
@@ -1166,14 +1165,10 @@ impl bifrost_salp::Config for Runtime {
 	type XcmInterface = XcmInterface;
 	type TreasuryAccount = BifrostTreasuryAccount;
 	type BuybackPalletId = BuybackPalletId;
-	type DexOperator = ZenlinkProtocol;
 	type CurrencyIdConversion = AssetIdMaps<Runtime>;
 	type CurrencyIdRegister = AssetIdMaps<Runtime>;
-	type ParachainId = ParachainInfo;
 	type StablePool = StablePool;
 	type VtokenMinting = VtokenMinting;
-	type LockId = SalpLockId;
-	type BatchLimit = BatchLimit;
 }
 
 parameter_types! {
diff --git a/runtime/bifrost-kusama/src/weights/bifrost_salp.rs b/runtime/bifrost-kusama/src/weights/bifrost_salp.rs
index 754136ff7..79c1612f5 100644
--- a/runtime/bifrost-kusama/src/weights/bifrost_salp.rs
+++ b/runtime/bifrost-kusama/src/weights/bifrost_salp.rs
@@ -121,25 +121,6 @@ impl<T: frame_system::Config> bifrost_salp::WeightInfo for BifrostWeight<T> {
 			.saturating_add(T::DbWeight::get().reads(5))
 			.saturating_add(T::DbWeight::get().writes(2))
 	}
-	// Storage: Salp Funds (r:1 w:0)
-	// Proof Skipped: Salp Funds (max_values: None, max_size: None, mode: Measured)
-	// Storage: Tokens Accounts (r:2 w:2)
-	// Proof: Tokens Accounts (max_values: None, max_size: Some(118), added: 2593, mode: MaxEncodedLen)
-	// Storage: AssetRegistry CurrencyMetadatas (r:1 w:0)
-	// Proof Skipped: AssetRegistry CurrencyMetadatas (max_values: None, max_size: None, mode: Measured)
-	// Storage: unknown `0x` (r:1 w:0)
-	// Proof Skipped: unknown `0x` (r:1 w:0)
-	// Storage: unknown `0xd861ea1ebf4800d4b89f4ff787ad79ee96d9a708c85b57da7eb8f9ddeda61291` (r:1 w:0)
-	// Proof Skipped: unknown `0xd861ea1ebf4800d4b89f4ff787ad79ee96d9a708c85b57da7eb8f9ddeda61291` (r:1 w:0)
-	fn batch_unlock() -> Weight {
-		// Proof Size summary in bytes:
-		//  Measured:  `1995`
-		//  Estimated: `6176`
-		// Minimum execution time: 142_535 nanoseconds.
-		Weight::from_parts(144_730_000, 6176)
-			.saturating_add(T::DbWeight::get().reads(6))
-			.saturating_add(T::DbWeight::get().writes(2))
-	}
 	// Storage: Salp Funds (r:1 w:1)
 	// Proof Skipped: Salp Funds (max_values: None, max_size: None, mode: Measured)
 	// Storage: Salp RedeemPool (r:1 w:1)
@@ -364,70 +345,4 @@ impl<T: frame_system::Config> bifrost_salp::WeightInfo for BifrostWeight<T> {
 			.saturating_add(T::DbWeight::get().reads(10))
 			.saturating_add(T::DbWeight::get().writes(6))
 	}
-	/// Storage: Salp Funds (r:1 w:0)
-	/// Proof Skipped: Salp Funds (max_values: None, max_size: None, mode: Measured)
-	/// Storage: Tokens Accounts (r:2 w:2)
-	/// Proof: Tokens Accounts (max_values: None, max_size: Some(118), added: 2593, mode: MaxEncodedLen)
-	/// Storage: Salp ReserveInfos (r:1 w:1)
-	/// Proof Skipped: Salp ReserveInfos (max_values: None, max_size: None, mode: Measured)
-	/// Storage: Tokens Locks (r:2 w:2)
-	/// Proof: Tokens Locks (max_values: None, max_size: Some(1271), added: 3746, mode: MaxEncodedLen)
-	/// Storage: AssetRegistry CurrencyMetadatas (r:1 w:0)
-	/// Proof Skipped: AssetRegistry CurrencyMetadatas (max_values: None, max_size: None, mode: Measured)
-	fn reserve() -> Weight {
-		// Proof Size summary in bytes:
-		//  Measured:  `1737`
-		//  Estimated: `8482`
-		// Minimum execution time: 807_976_000 picoseconds.
-		Weight::from_parts(814_218_000, 0)
-			.saturating_add(Weight::from_parts(0, 8482))
-			.saturating_add(T::DbWeight::get().reads(7))
-			.saturating_add(T::DbWeight::get().writes(5))
-	}
-	/// Storage: Salp Funds (r:1 w:0)
-	/// Proof Skipped: Salp Funds (max_values: None, max_size: None, mode: Measured)
-	/// Storage: Tokens Locks (r:2 w:2)
-	/// Proof: Tokens Locks (max_values: None, max_size: Some(1271), added: 3746, mode: MaxEncodedLen)
-	/// Storage: Tokens Accounts (r:2 w:2)
-	/// Proof: Tokens Accounts (max_values: None, max_size: Some(118), added: 2593, mode: MaxEncodedLen)
-	/// Storage: AssetRegistry CurrencyMetadatas (r:1 w:0)
-	/// Proof Skipped: AssetRegistry CurrencyMetadatas (max_values: None, max_size: None, mode: Measured)
-	/// Storage: Salp ReserveInfos (r:0 w:1)
-	/// Proof Skipped: Salp ReserveInfos (max_values: None, max_size: None, mode: Measured)
-	fn cancel_reservation() -> Weight {
-		// Proof Size summary in bytes:
-		//  Measured:  `1935`
-		//  Estimated: `8482`
-		// Minimum execution time: 853_491_000 picoseconds.
-		Weight::from_parts(858_070_000, 0)
-			.saturating_add(Weight::from_parts(0, 8482))
-			.saturating_add(T::DbWeight::get().reads(6))
-			.saturating_add(T::DbWeight::get().writes(5))
-	}
-	/// Storage: Salp Funds (r:1 w:1)
-	/// Proof Skipped: Salp Funds (max_values: None, max_size: None, mode: Measured)
-	/// Storage: Salp ReserveInfos (r:2 w:1)
-	/// Proof Skipped: Salp ReserveInfos (max_values: None, max_size: None, mode: Measured)
-	/// Storage: Tokens Locks (r:2 w:2)
-	/// Proof: Tokens Locks (max_values: None, max_size: Some(1271), added: 3746, mode: MaxEncodedLen)
-	/// Storage: Tokens Accounts (r:4 w:4)
-	/// Proof: Tokens Accounts (max_values: None, max_size: Some(118), added: 2593, mode: MaxEncodedLen)
-	/// Storage: AssetRegistry CurrencyMetadatas (r:1 w:0)
-	/// Proof Skipped: AssetRegistry CurrencyMetadatas (max_values: None, max_size: None, mode: Measured)
-	/// Storage: Salp RedeemPool (r:1 w:1)
-	/// Proof Skipped: Salp RedeemPool (max_values: Some(1), max_size: None, mode: Measured)
-	/// Storage: Tokens TotalIssuance (r:2 w:2)
-	/// Proof: Tokens TotalIssuance (max_values: None, max_size: Some(38), added: 2513, mode: MaxEncodedLen)
-	/// Storage: System Account (r:1 w:1)
-	/// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen)
-	fn batch_handle_reserve() -> Weight {
-		// Proof Size summary in bytes:
-		//  Measured:  `2540`
-		//  Estimated: `11362`
-		// Minimum execution time: 1_848_798_000 picoseconds.
-		Weight::from_parts(1_859_469_000, 0)
-			.saturating_add(Weight::from_parts(0, 11362))
-			.saturating_add(T::DbWeight::get().reads(14))
-			.saturating_add(T::DbWeight::get().writes(12))
-	}
 }
diff --git a/runtime/bifrost-kusama/src/xcm_config.rs b/runtime/bifrost-kusama/src/xcm_config.rs
index c56411628..612f2366c 100644
--- a/runtime/bifrost-kusama/src/xcm_config.rs
+++ b/runtime/bifrost-kusama/src/xcm_config.rs
@@ -351,12 +351,7 @@ impl Contains<RuntimeCall> for SafeCallFilter {
 				bifrost_farming::Call::withdraw_claim { .. }
 			) |
 			RuntimeCall::Salp(
-				bifrost_salp::Call::contribute { .. } |
-				bifrost_salp::Call::batch_unlock { .. } |
-				bifrost_salp::Call::redeem { .. } |
-				bifrost_salp::Call::unlock { .. } |
-				bifrost_salp::Call::unlock_by_vsbond { .. } |
-				bifrost_salp::Call::unlock_vstoken { .. }
+				bifrost_salp::Call::redeem { .. }
 			) |
 			RuntimeCall::VSBondAuction(
 				bifrost_vsbond_auction::Call::clinch_order { .. } |
diff --git a/runtime/bifrost-polkadot/src/lib.rs b/runtime/bifrost-polkadot/src/lib.rs
index 778aad7b6..a823373e4 100644
--- a/runtime/bifrost-polkadot/src/lib.rs
+++ b/runtime/bifrost-polkadot/src/lib.rs
@@ -1031,7 +1031,6 @@ parameter_types! {
 }
 
 impl bifrost_salp::Config for Runtime {
-	type BancorPool = ();
 	type RuntimeEvent = RuntimeEvent;
 	type RuntimeOrigin = RuntimeOrigin;
 	type RuntimeCall = RuntimeCall;
@@ -1050,14 +1049,10 @@ impl bifrost_salp::Config for Runtime {
 	type XcmInterface = XcmInterface;
 	type TreasuryAccount = BifrostTreasuryAccount;
 	type BuybackPalletId = BuybackPalletId;
-	type DexOperator = ZenlinkProtocol;
 	type CurrencyIdConversion = AssetIdMaps<Runtime>;
 	type CurrencyIdRegister = AssetIdMaps<Runtime>;
-	type ParachainId = ParachainInfo;
 	type StablePool = StablePool;
 	type VtokenMinting = VtokenMinting;
-	type LockId = SalpLockId;
-	type BatchLimit = BatchLimit;
 }
 
 impl bifrost_asset_registry::Config for Runtime {
diff --git a/runtime/bifrost-polkadot/src/weights/bifrost_salp.rs b/runtime/bifrost-polkadot/src/weights/bifrost_salp.rs
index 754136ff7..79c1612f5 100644
--- a/runtime/bifrost-polkadot/src/weights/bifrost_salp.rs
+++ b/runtime/bifrost-polkadot/src/weights/bifrost_salp.rs
@@ -121,25 +121,6 @@ impl<T: frame_system::Config> bifrost_salp::WeightInfo for BifrostWeight<T> {
 			.saturating_add(T::DbWeight::get().reads(5))
 			.saturating_add(T::DbWeight::get().writes(2))
 	}
-	// Storage: Salp Funds (r:1 w:0)
-	// Proof Skipped: Salp Funds (max_values: None, max_size: None, mode: Measured)
-	// Storage: Tokens Accounts (r:2 w:2)
-	// Proof: Tokens Accounts (max_values: None, max_size: Some(118), added: 2593, mode: MaxEncodedLen)
-	// Storage: AssetRegistry CurrencyMetadatas (r:1 w:0)
-	// Proof Skipped: AssetRegistry CurrencyMetadatas (max_values: None, max_size: None, mode: Measured)
-	// Storage: unknown `0x` (r:1 w:0)
-	// Proof Skipped: unknown `0x` (r:1 w:0)
-	// Storage: unknown `0xd861ea1ebf4800d4b89f4ff787ad79ee96d9a708c85b57da7eb8f9ddeda61291` (r:1 w:0)
-	// Proof Skipped: unknown `0xd861ea1ebf4800d4b89f4ff787ad79ee96d9a708c85b57da7eb8f9ddeda61291` (r:1 w:0)
-	fn batch_unlock() -> Weight {
-		// Proof Size summary in bytes:
-		//  Measured:  `1995`
-		//  Estimated: `6176`
-		// Minimum execution time: 142_535 nanoseconds.
-		Weight::from_parts(144_730_000, 6176)
-			.saturating_add(T::DbWeight::get().reads(6))
-			.saturating_add(T::DbWeight::get().writes(2))
-	}
 	// Storage: Salp Funds (r:1 w:1)
 	// Proof Skipped: Salp Funds (max_values: None, max_size: None, mode: Measured)
 	// Storage: Salp RedeemPool (r:1 w:1)
@@ -364,70 +345,4 @@ impl<T: frame_system::Config> bifrost_salp::WeightInfo for BifrostWeight<T> {
 			.saturating_add(T::DbWeight::get().reads(10))
 			.saturating_add(T::DbWeight::get().writes(6))
 	}
-	/// Storage: Salp Funds (r:1 w:0)
-	/// Proof Skipped: Salp Funds (max_values: None, max_size: None, mode: Measured)
-	/// Storage: Tokens Accounts (r:2 w:2)
-	/// Proof: Tokens Accounts (max_values: None, max_size: Some(118), added: 2593, mode: MaxEncodedLen)
-	/// Storage: Salp ReserveInfos (r:1 w:1)
-	/// Proof Skipped: Salp ReserveInfos (max_values: None, max_size: None, mode: Measured)
-	/// Storage: Tokens Locks (r:2 w:2)
-	/// Proof: Tokens Locks (max_values: None, max_size: Some(1271), added: 3746, mode: MaxEncodedLen)
-	/// Storage: AssetRegistry CurrencyMetadatas (r:1 w:0)
-	/// Proof Skipped: AssetRegistry CurrencyMetadatas (max_values: None, max_size: None, mode: Measured)
-	fn reserve() -> Weight {
-		// Proof Size summary in bytes:
-		//  Measured:  `1737`
-		//  Estimated: `8482`
-		// Minimum execution time: 807_976_000 picoseconds.
-		Weight::from_parts(814_218_000, 0)
-			.saturating_add(Weight::from_parts(0, 8482))
-			.saturating_add(T::DbWeight::get().reads(7))
-			.saturating_add(T::DbWeight::get().writes(5))
-	}
-	/// Storage: Salp Funds (r:1 w:0)
-	/// Proof Skipped: Salp Funds (max_values: None, max_size: None, mode: Measured)
-	/// Storage: Tokens Locks (r:2 w:2)
-	/// Proof: Tokens Locks (max_values: None, max_size: Some(1271), added: 3746, mode: MaxEncodedLen)
-	/// Storage: Tokens Accounts (r:2 w:2)
-	/// Proof: Tokens Accounts (max_values: None, max_size: Some(118), added: 2593, mode: MaxEncodedLen)
-	/// Storage: AssetRegistry CurrencyMetadatas (r:1 w:0)
-	/// Proof Skipped: AssetRegistry CurrencyMetadatas (max_values: None, max_size: None, mode: Measured)
-	/// Storage: Salp ReserveInfos (r:0 w:1)
-	/// Proof Skipped: Salp ReserveInfos (max_values: None, max_size: None, mode: Measured)
-	fn cancel_reservation() -> Weight {
-		// Proof Size summary in bytes:
-		//  Measured:  `1935`
-		//  Estimated: `8482`
-		// Minimum execution time: 853_491_000 picoseconds.
-		Weight::from_parts(858_070_000, 0)
-			.saturating_add(Weight::from_parts(0, 8482))
-			.saturating_add(T::DbWeight::get().reads(6))
-			.saturating_add(T::DbWeight::get().writes(5))
-	}
-	/// Storage: Salp Funds (r:1 w:1)
-	/// Proof Skipped: Salp Funds (max_values: None, max_size: None, mode: Measured)
-	/// Storage: Salp ReserveInfos (r:2 w:1)
-	/// Proof Skipped: Salp ReserveInfos (max_values: None, max_size: None, mode: Measured)
-	/// Storage: Tokens Locks (r:2 w:2)
-	/// Proof: Tokens Locks (max_values: None, max_size: Some(1271), added: 3746, mode: MaxEncodedLen)
-	/// Storage: Tokens Accounts (r:4 w:4)
-	/// Proof: Tokens Accounts (max_values: None, max_size: Some(118), added: 2593, mode: MaxEncodedLen)
-	/// Storage: AssetRegistry CurrencyMetadatas (r:1 w:0)
-	/// Proof Skipped: AssetRegistry CurrencyMetadatas (max_values: None, max_size: None, mode: Measured)
-	/// Storage: Salp RedeemPool (r:1 w:1)
-	/// Proof Skipped: Salp RedeemPool (max_values: Some(1), max_size: None, mode: Measured)
-	/// Storage: Tokens TotalIssuance (r:2 w:2)
-	/// Proof: Tokens TotalIssuance (max_values: None, max_size: Some(38), added: 2513, mode: MaxEncodedLen)
-	/// Storage: System Account (r:1 w:1)
-	/// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen)
-	fn batch_handle_reserve() -> Weight {
-		// Proof Size summary in bytes:
-		//  Measured:  `2540`
-		//  Estimated: `11362`
-		// Minimum execution time: 1_848_798_000 picoseconds.
-		Weight::from_parts(1_859_469_000, 0)
-			.saturating_add(Weight::from_parts(0, 11362))
-			.saturating_add(T::DbWeight::get().reads(14))
-			.saturating_add(T::DbWeight::get().writes(12))
-	}
 }
diff --git a/runtime/bifrost-polkadot/src/xcm_config.rs b/runtime/bifrost-polkadot/src/xcm_config.rs
index 9c43feb13..88d9b9db3 100644
--- a/runtime/bifrost-polkadot/src/xcm_config.rs
+++ b/runtime/bifrost-polkadot/src/xcm_config.rs
@@ -258,12 +258,7 @@ impl Contains<RuntimeCall> for SafeCallFilter {
 				bifrost_farming::Call::withdraw_claim { .. }
 			) |
 			RuntimeCall::Salp(
-				bifrost_salp::Call::contribute { .. } |
-				bifrost_salp::Call::batch_unlock { .. } |
-				bifrost_salp::Call::redeem { .. } |
-				bifrost_salp::Call::unlock { .. } |
-				bifrost_salp::Call::unlock_by_vsbond { .. } |
-				bifrost_salp::Call::unlock_vstoken { .. }
+				bifrost_salp::Call::redeem { .. }
 			) |
 			RuntimeCall::TokenConversion(
 				bifrost_vstoken_conversion::Call::vsbond_convert_to_vstoken { .. } |

From 394f7291226875ba911a4b7c71e627102e3d7c78 Mon Sep 17 00:00:00 2001
From: NingBo Wang <2536935847@qq.com>
Date: Mon, 23 Sep 2024 13:24:50 +0800
Subject: [PATCH 03/31] Optimised calculation of evm fee (#1434)

* Optimised calculation of evm fee

* Update gas_fee_price to weth_price
---
 pallets/fee-share/src/lib.rs                  |   8 +-
 pallets/fee-share/src/mock.rs                 |  12 +-
 .../src/impls/on_charge_transaction.rs        |   6 +-
 pallets/flexible-fee/src/lib.rs               |   8 +-
 pallets/flexible-fee/src/mock.rs              |   4 +-
 pallets/flexible-fee/src/mock_price.rs        |  48 +++---
 pallets/lend-market/src/lib.rs                |   6 +-
 pallets/lend-market/src/mock.rs               |  12 +-
 pallets/lend-market/src/tests.rs              |  10 +-
 .../lend-market/src/tests/interest_rate.rs    |   2 +-
 .../lend-market/src/tests/liquidate_borrow.rs |  19 ++-
 pallets/leverage-staking/src/mock.rs          |  14 +-
 pallets/prices/src/lib.rs                     |  36 ++--
 pallets/traits/src/lib.rs                     |   2 +-
 primitives/src/price.rs                       |   3 +-
 runtime/bifrost-kusama/src/lib.rs             |   6 +-
 runtime/bifrost-polkadot/src/evm/evm_fee.rs   | 129 ++++++---------
 runtime/bifrost-polkadot/src/evm/mod.rs       |  23 +--
 runtime/bifrost-polkadot/src/evm/runner.rs    |  60 ++++++-
 runtime/bifrost-polkadot/src/lib.rs           |   6 +-
 runtime/common/src/lib.rs                     |   4 -
 runtime/common/src/price.rs                   | 116 -------------
 runtime/common/src/ratio.rs                   | 154 ------------------
 23 files changed, 215 insertions(+), 473 deletions(-)
 delete mode 100644 runtime/common/src/price.rs
 delete mode 100644 runtime/common/src/ratio.rs

diff --git a/pallets/fee-share/src/lib.rs b/pallets/fee-share/src/lib.rs
index df6049865..cc1b45fd1 100644
--- a/pallets/fee-share/src/lib.rs
+++ b/pallets/fee-share/src/lib.rs
@@ -30,7 +30,7 @@ mod benchmarking;
 
 pub mod weights;
 
-use bifrost_primitives::{CurrencyId, DistributionId, Price, PriceFeeder};
+use bifrost_primitives::{CurrencyId, DistributionId, OraclePriceProvider, Price};
 use frame_support::{
 	pallet_prelude::*,
 	sp_runtime::{
@@ -102,7 +102,7 @@ pub mod pallet {
 		type FeeSharePalletId: Get<PalletId>;
 
 		/// The oracle price feeder
-		type PriceFeeder: PriceFeeder;
+		type OraclePriceProvider: OraclePriceProvider;
 	}
 
 	#[pallet::event]
@@ -492,8 +492,8 @@ pub mod pallet {
 		}
 
 		pub fn get_price(currency_id: CurrencyIdOf<T>) -> Result<Price, DispatchError> {
-			let (price, _) =
-				T::PriceFeeder::get_price(&currency_id).ok_or(Error::<T>::PriceOracleNotReady)?;
+			let (price, _) = T::OraclePriceProvider::get_price(&currency_id)
+				.ok_or(Error::<T>::PriceOracleNotReady)?;
 			log::trace!(
 				target: "fee-share::get_price", "price: {:?}", price.into_inner()
 			);
diff --git a/pallets/fee-share/src/mock.rs b/pallets/fee-share/src/mock.rs
index 3e7060766..16945802b 100644
--- a/pallets/fee-share/src/mock.rs
+++ b/pallets/fee-share/src/mock.rs
@@ -182,7 +182,7 @@ impl bifrost_fee_share::Config for Runtime {
 	type ControlOrigin = EnsureSignedBy<One, AccountId>;
 	type WeightInfo = ();
 	type FeeSharePalletId = FeeSharePalletId;
-	type PriceFeeder = MockPriceFeeder;
+	type OraclePriceProvider = MockOraclePriceProvider;
 }
 
 impl pallet_prices::Config for Runtime {
@@ -224,7 +224,7 @@ impl DataFeeder<CurrencyId, TimeStampedPrice, AccountId> for MockDataProvider {
 		Ok(())
 	}
 }
-pub struct MockPriceFeeder;
+pub struct MockOraclePriceProvider;
 #[derive(Encode, Decode, Clone, Copy, RuntimeDebug)]
 pub struct CurrencyIdWrap(CurrencyId);
 
@@ -242,7 +242,7 @@ impl PartialEq for CurrencyIdWrap {
 
 impl Eq for CurrencyIdWrap {}
 
-impl MockPriceFeeder {
+impl MockOraclePriceProvider {
 	thread_local! {
 		pub static PRICES: RefCell<HashMap<CurrencyIdWrap, Option<PriceDetail>>> = {
 			RefCell::new(
@@ -269,15 +269,11 @@ impl MockPriceFeeder {
 	}
 }
 
-impl PriceFeeder for MockPriceFeeder {
+impl OraclePriceProvider for MockOraclePriceProvider {
 	fn get_price(asset_id: &CurrencyId) -> Option<PriceDetail> {
 		Self::PRICES.with(|prices| *prices.borrow().get(&CurrencyIdWrap(*asset_id)).unwrap())
 	}
 
-	fn get_normal_price(_asset_id: &CurrencyId) -> Option<u128> {
-		todo!()
-	}
-
 	fn get_amount_by_prices(
 		_currency_in: &CurrencyId,
 		_amount_in: bifrost_primitives::Balance,
diff --git a/pallets/flexible-fee/src/impls/on_charge_transaction.rs b/pallets/flexible-fee/src/impls/on_charge_transaction.rs
index 0f217eed5..336605884 100644
--- a/pallets/flexible-fee/src/impls/on_charge_transaction.rs
+++ b/pallets/flexible-fee/src/impls/on_charge_transaction.rs
@@ -17,7 +17,7 @@
 // along with this program. If not, see <https://www.gnu.org/licenses/>.
 
 use crate::{Config, ExtraFeeByCall, Pallet};
-use bifrost_primitives::{Balance, CurrencyId, Price, PriceFeeder, BNC};
+use bifrost_primitives::{Balance, CurrencyId, OraclePriceProvider, Price, BNC};
 use orml_traits::MultiCurrency;
 use pallet_transaction_payment::OnChargeTransaction;
 use parity_scale_codec::Encode;
@@ -124,7 +124,7 @@ where
 				),
 				PaymentInfo::NonNative(paid_fee, fee_currency, bnc_price, fee_currency_price) => {
 					// calculate corrected_fee in the non-native currency
-					let converted_corrected_fee = T::PriceFeeder::get_amount_by_prices(
+					let converted_corrected_fee = T::OraclePriceProvider::get_amount_by_prices(
 						&BNC,
 						corrected_fee,
 						bnc_price,
@@ -133,7 +133,7 @@ where
 					)
 					.ok_or(TransactionValidityError::Invalid(InvalidTransaction::Payment))?;
 					let refund = paid_fee.saturating_sub(converted_corrected_fee);
-					let converted_tip = T::PriceFeeder::get_amount_by_prices(
+					let converted_tip = T::OraclePriceProvider::get_amount_by_prices(
 						&BNC,
 						tip,
 						bnc_price,
diff --git a/pallets/flexible-fee/src/lib.rs b/pallets/flexible-fee/src/lib.rs
index f0e76dec7..889b9f494 100644
--- a/pallets/flexible-fee/src/lib.rs
+++ b/pallets/flexible-fee/src/lib.rs
@@ -22,7 +22,7 @@ pub use crate::pallet::*;
 use bifrost_primitives::{
 	currency::{VGLMR, VMANTA, WETH},
 	traits::XcmDestWeightAndFeeHandler,
-	Balance, BalanceCmp, CurrencyId, DerivativeIndex, Price, PriceFeeder, TryConvertFrom,
+	Balance, BalanceCmp, CurrencyId, DerivativeIndex, OraclePriceProvider, Price, TryConvertFrom,
 	XcmOperationType, BNC, DOT, GLMR, MANTA, VBNC, VDOT,
 };
 use bifrost_xcm_interface::{polkadot::RelaychainCall, traits::parachains, PolkadotXcmCall};
@@ -74,7 +74,7 @@ pub enum TargetChain {
 #[frame_support::pallet]
 pub mod pallet {
 	use super::*;
-	use bifrost_primitives::{Balance, PriceFeeder};
+	use bifrost_primitives::{Balance, OraclePriceProvider};
 	use frame_support::traits::fungibles::Inspect;
 
 	#[pallet::config]
@@ -91,7 +91,7 @@ pub mod pallet {
 		/// Zenlink interface
 		type DexOperator: ExportZenlink<Self::AccountId, AssetId>;
 		/// The oracle price feeder
-		type PriceFeeder: PriceFeeder;
+		type OraclePriceProvider: OraclePriceProvider;
 		/// The only origin that can set universal fee currency order list
 		type ControlOrigin: EnsureOrigin<Self::RuntimeOrigin>;
 		/// Get the weight and fee for executing Xcm.
@@ -389,7 +389,7 @@ impl<T: Config> Pallet<T> {
 				}
 			} else {
 				let (fee_amount, price_in, price_out) =
-					T::PriceFeeder::get_oracle_amount_by_currency_and_amount_in(
+					T::OraclePriceProvider::get_oracle_amount_by_currency_and_amount_in(
 						&BNC,
 						fee_amount,
 						&currency_id,
diff --git a/pallets/flexible-fee/src/mock.rs b/pallets/flexible-fee/src/mock.rs
index 3dea71af4..d8ef4559d 100644
--- a/pallets/flexible-fee/src/mock.rs
+++ b/pallets/flexible-fee/src/mock.rs
@@ -19,7 +19,7 @@
 #![cfg(test)]
 
 use super::*;
-use crate::{self as flexible_fee, mock_price::MockPriceFeeder};
+use crate::{self as flexible_fee, mock_price::MockOraclePriceProvider};
 use bifrost_currencies::BasicCurrencyAdapter;
 use bifrost_primitives::{Balance, CurrencyId, TokenSymbol};
 use cumulus_primitives_core::ParaId as Pid;
@@ -167,7 +167,7 @@ impl crate::Config for Test {
 	type RelaychainCurrencyId = RelayCurrencyId;
 	type XcmRouter = ();
 	type PalletId = FlexibleFeePalletId;
-	type PriceFeeder = MockPriceFeeder;
+	type OraclePriceProvider = MockOraclePriceProvider;
 }
 
 pub struct XcmDestWeightAndFee;
diff --git a/pallets/flexible-fee/src/mock_price.rs b/pallets/flexible-fee/src/mock_price.rs
index 80e7d0bca..18374e46e 100644
--- a/pallets/flexible-fee/src/mock_price.rs
+++ b/pallets/flexible-fee/src/mock_price.rs
@@ -19,8 +19,8 @@
 #![cfg(test)]
 
 use bifrost_primitives::{
-	Balance, CurrencyId, Price, PriceDetail, PriceFeeder, BNC, DOT, DOT_U, KSM, MANTA, VDOT, VKSM,
-	WETH,
+	Balance, CurrencyId, OraclePriceProvider, Price, PriceDetail, BNC, DOT, DOT_U, KSM, MANTA,
+	VDOT, VKSM, WETH,
 };
 use frame_support::parameter_types;
 use sp_runtime::FixedU128;
@@ -39,8 +39,8 @@ parameter_types! {
 	]);
 }
 
-pub struct MockPriceFeeder;
-impl MockPriceFeeder {
+pub struct MockOraclePriceProvider;
+impl MockOraclePriceProvider {
 	pub fn set_price(currency_id: CurrencyId, price: Price) {
 		let mut storage_price = StoragePrice::get();
 		match storage_price.get(&currency_id) {
@@ -55,7 +55,7 @@ impl MockPriceFeeder {
 	}
 }
 
-impl PriceFeeder for MockPriceFeeder {
+impl OraclePriceProvider for MockOraclePriceProvider {
 	fn get_price(currency_id: &CurrencyId) -> Option<PriceDetail> {
 		match StoragePrice::get().get(currency_id) {
 			Some((price, _)) => Some((*price, 0)),
@@ -63,10 +63,6 @@ impl PriceFeeder for MockPriceFeeder {
 		}
 	}
 
-	fn get_normal_price(_asset_id: &CurrencyId) -> Option<u128> {
-		todo!()
-	}
-
 	fn get_amount_by_prices(
 		currency_in: &CurrencyId,
 		amount_in: Balance,
@@ -119,14 +115,14 @@ mod test {
 	#[test]
 	fn set_price() {
 		assert_eq!(
-			MockPriceFeeder::get_price(&BNC),
+			MockOraclePriceProvider::get_price(&BNC),
 			Some((FixedU128::from_inner(200_000_000_000_000_000), 0))
 		);
-		MockPriceFeeder::set_price(BNC, FixedU128::from(100));
-		assert_eq!(MockPriceFeeder::get_price(&BNC), Some((FixedU128::from(100), 0)));
+		MockOraclePriceProvider::set_price(BNC, FixedU128::from(100));
+		assert_eq!(MockOraclePriceProvider::get_price(&BNC), Some((FixedU128::from(100), 0)));
 
-		MockPriceFeeder::set_price(DOT, FixedU128::from(100));
-		assert_eq!(MockPriceFeeder::get_price(&DOT), Some((FixedU128::from(100), 0)));
+		MockOraclePriceProvider::set_price(DOT, FixedU128::from(100));
+		assert_eq!(MockOraclePriceProvider::get_price(&DOT), Some((FixedU128::from(100), 0)));
 	}
 
 	#[test]
@@ -137,19 +133,27 @@ mod test {
 		let usdt_amount = 20 * 10u128.pow(6);
 		let manta_amount = 25 * 10u128.pow(18);
 		assert_eq!(
-			MockPriceFeeder::get_oracle_amount_by_currency_and_amount_in(&BNC, bnc_amount, &DOT),
+			MockOraclePriceProvider::get_oracle_amount_by_currency_and_amount_in(
+				&BNC, bnc_amount, &DOT
+			),
 			Some((dot_amount, FixedU128::from_inner(200_000_000_000_000_000), FixedU128::from(5)))
 		);
 		assert_eq!(
-			MockPriceFeeder::get_oracle_amount_by_currency_and_amount_in(&BNC, bnc_amount, &DOT_U),
+			MockOraclePriceProvider::get_oracle_amount_by_currency_and_amount_in(
+				&BNC, bnc_amount, &DOT_U
+			),
 			Some((usdt_amount, FixedU128::from_inner(200_000_000_000_000_000), FixedU128::from(1)))
 		);
 		assert_eq!(
-			MockPriceFeeder::get_oracle_amount_by_currency_and_amount_in(&BNC, bnc_amount, &KSM),
+			MockOraclePriceProvider::get_oracle_amount_by_currency_and_amount_in(
+				&BNC, bnc_amount, &KSM
+			),
 			Some((ksm_amount, FixedU128::from_inner(200_000_000_000_000_000), FixedU128::from(20)))
 		);
 		assert_eq!(
-			MockPriceFeeder::get_oracle_amount_by_currency_and_amount_in(&BNC, bnc_amount, &MANTA),
+			MockOraclePriceProvider::get_oracle_amount_by_currency_and_amount_in(
+				&BNC, bnc_amount, &MANTA
+			),
 			Some((
 				manta_amount,
 				FixedU128::from_inner(200_000_000_000_000_000),
@@ -157,11 +161,15 @@ mod test {
 			))
 		);
 		assert_eq!(
-			MockPriceFeeder::get_oracle_amount_by_currency_and_amount_in(&DOT, dot_amount, &DOT_U),
+			MockOraclePriceProvider::get_oracle_amount_by_currency_and_amount_in(
+				&DOT, dot_amount, &DOT_U
+			),
 			Some((usdt_amount, FixedU128::from(5), FixedU128::from(1)))
 		);
 		assert_eq!(
-			MockPriceFeeder::get_oracle_amount_by_currency_and_amount_in(&DOT, dot_amount, &KSM),
+			MockOraclePriceProvider::get_oracle_amount_by_currency_and_amount_in(
+				&DOT, dot_amount, &KSM
+			),
 			Some((ksm_amount, FixedU128::from(5), FixedU128::from(20)))
 		);
 	}
diff --git a/pallets/lend-market/src/lib.rs b/pallets/lend-market/src/lib.rs
index 45b0903be..743701a0e 100644
--- a/pallets/lend-market/src/lib.rs
+++ b/pallets/lend-market/src/lib.rs
@@ -26,7 +26,7 @@ use core::cmp::max;
 
 pub use crate::rate_model::*;
 use bifrost_primitives::{
-	Balance, CurrencyId, Liquidity, Price, PriceFeeder, Rate, Ratio, Shortfall, Timestamp,
+	Balance, CurrencyId, Liquidity, OraclePriceProvider, Price, Rate, Ratio, Shortfall, Timestamp,
 };
 use frame_support::{
 	pallet_prelude::*,
@@ -103,7 +103,7 @@ pub mod pallet {
 		type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
 
 		/// The oracle price feeder
-		type PriceFeeder: PriceFeeder;
+		type OraclePriceProvider: OraclePriceProvider;
 
 		/// The loan's module id, keep all collaterals of CDPs.
 		#[pallet::constant]
@@ -1959,7 +1959,7 @@ impl<T: Config> Pallet<T> {
 	// Returns `Err` if the oracle price not ready
 	pub fn get_price(asset_id: AssetIdOf<T>) -> Result<Price, DispatchError> {
 		let (price, _) =
-			T::PriceFeeder::get_price(&asset_id).ok_or(Error::<T>::PriceOracleNotReady)?;
+			T::OraclePriceProvider::get_price(&asset_id).ok_or(Error::<T>::PriceOracleNotReady)?;
 		if price.is_zero() {
 			return Err(Error::<T>::PriceIsZero.into());
 		}
diff --git a/pallets/lend-market/src/mock.rs b/pallets/lend-market/src/mock.rs
index 294c4e24e..eecf3f21d 100644
--- a/pallets/lend-market/src/mock.rs
+++ b/pallets/lend-market/src/mock.rs
@@ -205,7 +205,7 @@ impl SortedMembers<AccountId> for AliceCreatePoolOrigin {
 	}
 }
 
-pub struct MockPriceFeeder;
+pub struct MockOraclePriceProvider;
 #[derive(Encode, Decode, Clone, Copy, RuntimeDebug)]
 pub struct CurrencyIdWrap(CurrencyId);
 
@@ -223,7 +223,7 @@ impl PartialEq for CurrencyIdWrap {
 
 impl Eq for CurrencyIdWrap {}
 
-impl MockPriceFeeder {
+impl MockOraclePriceProvider {
 	thread_local! {
 		pub static PRICES: RefCell<HashMap<CurrencyIdWrap, Option<PriceDetail>>> = {
 			RefCell::new(
@@ -250,15 +250,11 @@ impl MockPriceFeeder {
 	}
 }
 
-impl PriceFeeder for MockPriceFeeder {
+impl OraclePriceProvider for MockOraclePriceProvider {
 	fn get_price(asset_id: &CurrencyId) -> Option<PriceDetail> {
 		Self::PRICES.with(|prices| *prices.borrow().get(&CurrencyIdWrap(*asset_id)).unwrap())
 	}
 
-	fn get_normal_price(_asset_id: &CurrencyId) -> Option<u128> {
-		todo!()
-	}
-
 	fn get_amount_by_prices(
 		_currency_in: &CurrencyId,
 		_amount_in: Balance,
@@ -327,7 +323,7 @@ parameter_types! {
 
 impl Config for Test {
 	type RuntimeEvent = RuntimeEvent;
-	type PriceFeeder = MockPriceFeeder;
+	type OraclePriceProvider = MockOraclePriceProvider;
 	type PalletId = LendMarketPalletId;
 	type ReserveOrigin = EnsureRoot<AccountId>;
 	type UpdateOrigin = EnsureRoot<AccountId>;
diff --git a/pallets/lend-market/src/tests.rs b/pallets/lend-market/src/tests.rs
index f8e2aec9e..b17c7a9df 100644
--- a/pallets/lend-market/src/tests.rs
+++ b/pallets/lend-market/src/tests.rs
@@ -656,7 +656,7 @@ fn get_account_liquidation_threshold_liquidity_works() {
 		assert_eq!(liquidity, FixedU128::from_inner(unit(20)));
 		assert_eq!(lf_liquidity, FixedU128::from_inner(unit(10)));
 
-		MockPriceFeeder::set_price(KSM, 2.into());
+		MockOraclePriceProvider::set_price(KSM, 2.into());
 		let (liquidity, shortfall, lf_liquidity, _) =
 			LendMarket::get_account_liquidation_threshold_liquidity(&ALICE).unwrap();
 
@@ -1259,10 +1259,10 @@ fn get_price_works() {
 			BNC,
 			vec![DOT, BNC, KSM, DOT_U, PHA]
 		));
-		MockPriceFeeder::set_price(DOT, 0.into());
+		MockOraclePriceProvider::set_price(DOT, 0.into());
 		assert_noop!(LendMarket::get_price(DOT), Error::<Test>::PriceIsZero);
 
-		MockPriceFeeder::set_price(DOT, 2.into());
+		MockOraclePriceProvider::set_price(DOT, 2.into());
 		assert_eq!(LendMarket::get_price(DOT).unwrap(), Price::saturating_from_integer(2));
 	})
 }
@@ -1813,7 +1813,7 @@ fn reward_calculation_after_liquidate_borrow_works() {
 		assert_eq!(almost_equal(RewardAccrued::<Test>::get(ALICE), unit(14)), true);
 		assert_eq!(almost_equal(RewardAccrued::<Test>::get(BOB), unit(16)), true);
 
-		MockPriceFeeder::set_price(KSM, 2.into());
+		MockOraclePriceProvider::set_price(KSM, 2.into());
 		// since we set liquidate_threshold more than collateral_factor,with KSM price as 2 alice
 		// not shortfall yet. so we can not liquidate_borrow here
 		assert_noop!(
@@ -1828,7 +1828,7 @@ fn reward_calculation_after_liquidate_borrow_works() {
 		// Bob KSM Deposit: 500
 		// Bob KSM Borrow: 75
 		// incentive_reward_account DOT Deposit: 75*0.03 = 2.25
-		MockPriceFeeder::set_price(KSM, 3.into());
+		MockOraclePriceProvider::set_price(KSM, 3.into());
 		assert_ok!(LendMarket::liquidate_borrow(
 			RuntimeOrigin::signed(BOB),
 			ALICE,
diff --git a/pallets/lend-market/src/tests/interest_rate.rs b/pallets/lend-market/src/tests/interest_rate.rs
index 8bd5a22ba..fa391ca8f 100644
--- a/pallets/lend-market/src/tests/interest_rate.rs
+++ b/pallets/lend-market/src/tests/interest_rate.rs
@@ -371,7 +371,7 @@ fn accrue_interest_works_after_liquidate_borrow() {
 		assert_eq!(BorrowIndex::<Test>::get(KSM), Rate::one());
 		TimestampPallet::set_timestamp(12000);
 		// Adjust KSM price to make shortfall
-		MockPriceFeeder::set_price(KSM, 2.into());
+		MockOraclePriceProvider::set_price(KSM, 2.into());
 		// BOB repay the KSM loan and get DOT callateral from ALICE
 		assert_ok!(LendMarket::liquidate_borrow(
 			RuntimeOrigin::signed(BOB),
diff --git a/pallets/lend-market/src/tests/liquidate_borrow.rs b/pallets/lend-market/src/tests/liquidate_borrow.rs
index 9e04e4a1e..17cb806da 100644
--- a/pallets/lend-market/src/tests/liquidate_borrow.rs
+++ b/pallets/lend-market/src/tests/liquidate_borrow.rs
@@ -1,6 +1,7 @@
 use crate::{
 	mock::{
-		new_test_ext, LendMarket, MockPriceFeeder, RuntimeOrigin, ALICE, BOB, DOT, DOT_U, KSM, *,
+		new_test_ext, LendMarket, MockOraclePriceProvider, RuntimeOrigin, ALICE, BOB, DOT, DOT_U,
+		KSM, *,
 	},
 	tests::unit,
 	Error, MarketState,
@@ -23,7 +24,7 @@ fn liquidate_borrow_allowed_works() {
 		initial_setup();
 		alice_borrows_100_ksm();
 		// Adjust KSM price to make shortfall
-		MockPriceFeeder::set_price(KSM, 2.into());
+		MockOraclePriceProvider::set_price(KSM, 2.into());
 		let ksm_market = LendMarket::market(KSM).unwrap();
 		// Here the balance sheet of Alice is:
 		// Collateral   LendMarket
@@ -82,8 +83,8 @@ fn lf_liquidate_borrow_allowed_works() {
 
 		// CDOT's price is highly relative to DOT's price in real runtime. Thus we must update them
 		// at the same time.
-		MockPriceFeeder::set_price(DOT, 2.into());
-		MockPriceFeeder::set_price(PHA, 2.into());
+		MockOraclePriceProvider::set_price(DOT, 2.into());
+		MockOraclePriceProvider::set_price(PHA, 2.into());
 		// ALICE
 		// Collateral                 Borrowed
 		// DOT_U  $100                 DOT $400
@@ -113,7 +114,7 @@ fn deposit_of_borrower_must_be_collateral() {
 		initial_setup();
 		alice_borrows_100_ksm();
 		// Adjust KSM price to make shortfall
-		MockPriceFeeder::set_price(KSM, 2.into());
+		MockOraclePriceProvider::set_price(KSM, 2.into());
 		let market = LendMarket::market(KSM).unwrap();
 		assert_noop!(
 			LendMarket::liquidate_borrow_allowed(&ALICE, KSM, unit(51), &market),
@@ -134,7 +135,7 @@ fn collateral_value_must_be_greater_than_liquidation_value() {
 		assert_ok!(LendMarket::add_market_bond(RuntimeOrigin::root(), BNC, vec![DOT, BNC, KSM]));
 		initial_setup();
 		alice_borrows_100_ksm();
-		MockPriceFeeder::set_price(KSM, Rate::from_float(2000.0));
+		MockOraclePriceProvider::set_price(KSM, Rate::from_float(2000.0));
 		LendMarket::mutate_market(KSM, |market| {
 			market.liquidate_incentive = Rate::from_float(200.0);
 			market.clone()
@@ -156,7 +157,7 @@ fn full_workflow_works_as_expected() {
 		initial_setup();
 		alice_borrows_100_ksm();
 		// adjust KSM price to make ALICE generate shortfall
-		MockPriceFeeder::set_price(KSM, 2.into());
+		MockOraclePriceProvider::set_price(KSM, 2.into());
 		// BOB repay the KSM borrow balance and get DOT from ALICE
 		assert_ok!(LendMarket::liquidate_borrow(
 			RuntimeOrigin::signed(BOB),
@@ -227,7 +228,7 @@ fn liquidator_cannot_take_inactive_market_currency() {
 		initial_setup();
 		alice_borrows_100_ksm();
 		// Adjust KSM price to make shortfall
-		MockPriceFeeder::set_price(KSM, 2.into());
+		MockOraclePriceProvider::set_price(KSM, 2.into());
 		assert_ok!(LendMarket::mutate_market(DOT, |stored_market| {
 			stored_market.state = MarketState::Supervision;
 			stored_market.clone()
@@ -247,7 +248,7 @@ fn liquidator_can_not_repay_more_than_the_close_factor_pct_multiplier() {
 		assert_ok!(LendMarket::add_market_bond(RuntimeOrigin::root(), BNC, vec![DOT, BNC, KSM]));
 		initial_setup();
 		alice_borrows_100_ksm();
-		MockPriceFeeder::set_price(KSM, 20.into());
+		MockOraclePriceProvider::set_price(KSM, 20.into());
 		assert_noop!(
 			LendMarket::liquidate_borrow(RuntimeOrigin::signed(BOB), ALICE, KSM, unit(51), DOT),
 			Error::<Test>::TooMuchRepay
diff --git a/pallets/leverage-staking/src/mock.rs b/pallets/leverage-staking/src/mock.rs
index a7c9944cf..f7ab5dd74 100644
--- a/pallets/leverage-staking/src/mock.rs
+++ b/pallets/leverage-staking/src/mock.rs
@@ -22,7 +22,7 @@ use bifrost_asset_registry::AssetIdMaps;
 pub use bifrost_primitives::{
 	currency::*, Balance, CurrencyId, CurrencyIdMapping, SlpOperator, SlpxOperator, TokenSymbol,
 };
-use bifrost_primitives::{Moment, MoonbeamChainId, Price, PriceDetail, PriceFeeder, Ratio};
+use bifrost_primitives::{Moment, MoonbeamChainId, OraclePriceProvider, Price, PriceDetail, Ratio};
 use bifrost_runtime_common::milli;
 use frame_support::{
 	derive_impl, ord_parameter_types, parameter_types,
@@ -340,7 +340,7 @@ impl pallet_timestamp::Config for Test {
 	type WeightInfo = ();
 }
 
-pub struct MockPriceFeeder;
+pub struct MockOraclePriceProvider;
 #[derive(Encode, Decode, Clone, Copy, RuntimeDebug)]
 pub struct CurrencyIdWrap(CurrencyId);
 
@@ -387,7 +387,7 @@ impl DataFeeder<CurrencyId, TimeStampedPrice, u128> for MockDataProvider {
 	}
 }
 
-impl MockPriceFeeder {
+impl MockOraclePriceProvider {
 	thread_local! {
 		pub static PRICES: RefCell<HashMap<CurrencyIdWrap, Option<PriceDetail>>> = {
 			RefCell::new(
@@ -414,15 +414,11 @@ impl MockPriceFeeder {
 	}
 }
 
-impl PriceFeeder for MockPriceFeeder {
+impl OraclePriceProvider for MockOraclePriceProvider {
 	fn get_price(asset_id: &CurrencyId) -> Option<PriceDetail> {
 		Self::PRICES.with(|prices| *prices.borrow().get(&CurrencyIdWrap(*asset_id)).unwrap())
 	}
 
-	fn get_normal_price(_asset_id: &CurrencyId) -> Option<u128> {
-		todo!()
-	}
-
 	fn get_amount_by_prices(
 		_currency_in: &CurrencyId,
 		_amount_in: Balance,
@@ -450,7 +446,7 @@ parameter_types! {
 
 impl lend_market::Config for Test {
 	type RuntimeEvent = RuntimeEvent;
-	type PriceFeeder = MockPriceFeeder;
+	type OraclePriceProvider = MockOraclePriceProvider;
 	type PalletId = LendMarketPalletId;
 	type ReserveOrigin = EnsureRoot<u128>;
 	type UpdateOrigin = EnsureRoot<u128>;
diff --git a/pallets/prices/src/lib.rs b/pallets/prices/src/lib.rs
index 859826e63..a65516974 100644
--- a/pallets/prices/src/lib.rs
+++ b/pallets/prices/src/lib.rs
@@ -17,15 +17,15 @@
 //! ## Overview
 //!
 //! This pallet provides the price from Oracle Module by implementing the
-//! `PriceFeeder` trait. In case of emergency, the price can be set directly
+//! `OraclePriceProvider` trait. In case of emergency, the price can be set directly
 //! by Oracle Collective.
 
 #![cfg_attr(not(feature = "std"), no_std)]
 
 use bifrost_asset_registry::AssetMetadata;
 use bifrost_primitives::{
-	Balance, CurrencyId, CurrencyIdMapping, Price, PriceDetail, PriceFeeder, TimeStampedPrice,
-	TokenInfo,
+	Balance, CurrencyId, CurrencyIdMapping, OraclePriceProvider, Price, PriceDetail,
+	TimeStampedPrice, TokenInfo,
 };
 use frame_support::{dispatch::DispatchClass, pallet_prelude::*, transactional};
 use frame_system::pallet_prelude::*;
@@ -144,7 +144,7 @@ pub mod pallet {
 			price: Price,
 		) -> DispatchResultWithPostInfo {
 			T::FeederOrigin::ensure_origin(origin)?;
-			<Pallet<T> as EmergencyPriceFeeder<CurrencyId, Price>>::set_emergency_price(
+			<Pallet<T> as EmergencyOraclePriceProvider<CurrencyId, Price>>::set_emergency_price(
 				asset_id, price,
 			);
 			Ok(().into())
@@ -159,7 +159,9 @@ pub mod pallet {
 			asset_id: CurrencyId,
 		) -> DispatchResultWithPostInfo {
 			T::FeederOrigin::ensure_origin(origin)?;
-			<Pallet<T> as EmergencyPriceFeeder<CurrencyId, Price>>::reset_emergency_price(asset_id);
+			<Pallet<T> as EmergencyOraclePriceProvider<CurrencyId, Price>>::reset_emergency_price(
+				asset_id,
+			);
 			Ok(().into())
 		}
 
@@ -226,7 +228,7 @@ impl<T: Config> Pallet<T> {
 	}
 }
 
-impl<T: Config> PriceFeeder for Pallet<T> {
+impl<T: Config> OraclePriceProvider for Pallet<T> {
 	/// Returns the uniform format price and timestamp by asset id.
 	/// Formula: `price = oracle_price * 10.pow(18 - asset_decimal)`
 	/// We use `oracle_price.checked_div(&FixedU128::from_inner(mantissa))` represent that.
@@ -245,16 +247,6 @@ impl<T: Config> PriceFeeder for Pallet<T> {
 		})
 	}
 
-	fn get_normal_price(asset_id: &CurrencyId) -> Option<u128> {
-		let decimals = Self::get_asset_mantissa(asset_id)?;
-		EmergencyPrice::<T>::get(asset_id)
-			.and_then(|p| Some(p.into_inner().saturating_div(decimals)))
-			.or_else(|| {
-				T::Source::get(&asset_id)
-					.and_then(|price| Some(price.value.into_inner().saturating_div(decimals)))
-			})
-	}
-
 	/// Get the amount of currencies according to the input price data.
 	/// Parameters:
 	/// - `currency_in`: The currency to be converted.
@@ -296,13 +288,17 @@ impl<T: Config> PriceFeeder for Pallet<T> {
 		currency_out: &CurrencyId,
 	) -> Option<(Balance, Price, Price)> {
 		let price_in = Self::get_storage_price(currency_in)?;
-		let price_out = Self::get_storage_price(currency_out)?;
-		Self::get_amount_by_prices(currency_in, amount_in, price_in, currency_out, price_out)
-			.map(|amount_out| (amount_out, price_in, price_out))
+		if currency_in == currency_out {
+			Some((amount_in, price_in, price_in))
+		} else {
+			let price_out = Self::get_storage_price(currency_out)?;
+			Self::get_amount_by_prices(currency_in, amount_in, price_in, currency_out, price_out)
+				.map(|amount_out| (amount_out, price_in, price_out))
+		}
 	}
 }
 
-impl<T: Config> EmergencyPriceFeeder<CurrencyId, Price> for Pallet<T> {
+impl<T: Config> EmergencyOraclePriceProvider<CurrencyId, Price> for Pallet<T> {
 	/// Set emergency price
 	fn set_emergency_price(asset_id: CurrencyId, price: Price) {
 		// set price direct
diff --git a/pallets/traits/src/lib.rs b/pallets/traits/src/lib.rs
index b51ec1b7d..3de362e4a 100644
--- a/pallets/traits/src/lib.rs
+++ b/pallets/traits/src/lib.rs
@@ -11,7 +11,7 @@ pub trait EmergencyCallFilter<Call> {
 	fn contains(call: &Call) -> bool;
 }
 
-pub trait EmergencyPriceFeeder<CurrencyId, Price> {
+pub trait EmergencyOraclePriceProvider<CurrencyId, Price> {
 	fn set_emergency_price(asset_id: CurrencyId, price: Price);
 	fn reset_emergency_price(asset_id: CurrencyId);
 }
diff --git a/primitives/src/price.rs b/primitives/src/price.rs
index 22e09d2a5..aaaebe435 100644
--- a/primitives/src/price.rs
+++ b/primitives/src/price.rs
@@ -18,9 +18,8 @@
 
 use crate::{Balance, CurrencyId, Price, PriceDetail};
 
-pub trait PriceFeeder {
+pub trait OraclePriceProvider {
 	fn get_price(asset_id: &CurrencyId) -> Option<PriceDetail>;
-	fn get_normal_price(asset_id: &CurrencyId) -> Option<u128>;
 	fn get_amount_by_prices(
 		currency_in: &CurrencyId,
 		amount_in: Balance,
diff --git a/runtime/bifrost-kusama/src/lib.rs b/runtime/bifrost-kusama/src/lib.rs
index 065d18b90..0e5bf5da9 100644
--- a/runtime/bifrost-kusama/src/lib.rs
+++ b/runtime/bifrost-kusama/src/lib.rs
@@ -1040,7 +1040,7 @@ impl bifrost_flexible_fee::Config for Runtime {
 	type RelaychainCurrencyId = RelayCurrencyId;
 	type XcmRouter = XcmRouter;
 	type PalletId = FlexibleFeePalletId;
-	type PriceFeeder = Prices;
+	type OraclePriceProvider = Prices;
 }
 
 parameter_types! {
@@ -1326,7 +1326,7 @@ impl bifrost_fee_share::Config for Runtime {
 	type ControlOrigin = CoreAdminOrCouncil;
 	type WeightInfo = weights::bifrost_fee_share::BifrostWeight<Runtime>;
 	type FeeSharePalletId = FeeSharePalletId;
-	type PriceFeeder = Prices;
+	type OraclePriceProvider = Prices;
 }
 
 impl bifrost_cross_in_out::Config for Runtime {
@@ -1621,7 +1621,7 @@ impl pallet_prices::Config for Runtime {
 impl lend_market::Config for Runtime {
 	type RuntimeEvent = RuntimeEvent;
 	type PalletId = LendMarketPalletId;
-	type PriceFeeder = Prices;
+	type OraclePriceProvider = Prices;
 	type ReserveOrigin = TechAdminOrCouncil;
 	type UpdateOrigin = TechAdminOrCouncil;
 	type WeightInfo = lend_market::weights::BifrostWeight<Runtime>;
diff --git a/runtime/bifrost-polkadot/src/evm/evm_fee.rs b/runtime/bifrost-polkadot/src/evm/evm_fee.rs
index 01656d02b..ce0de8c0d 100644
--- a/runtime/bifrost-polkadot/src/evm/evm_fee.rs
+++ b/runtime/bifrost-polkadot/src/evm/evm_fee.rs
@@ -17,39 +17,38 @@
 // along with this program. If not, see <https://www.gnu.org/licenses/>.
 
 use crate::Currencies;
-use bifrost_primitives::{AccountFeeCurrency, Balance, CurrencyId};
-use bifrost_runtime_common::Ratio;
-use frame_support::traits::{Get, OnUnbalanced, TryDrop};
+use bifrost_primitives::{
+	AccountFeeCurrency, Balance, CurrencyId, OraclePriceProvider, Price, WETH,
+};
+use frame_support::traits::TryDrop;
 use orml_traits::MultiCurrency;
 use pallet_evm::{AddressMapping, Error, OnChargeEVMTransaction};
 use sp_core::{H160, U256};
-use sp_runtime::{
-	helpers_128bit::multiply_by_rational_with_rounding,
-	traits::{Convert, UniqueSaturatedInto},
-	Rounding,
-};
+use sp_runtime::traits::UniqueSaturatedInto;
 use sp_std::marker::PhantomData;
 
-#[derive(Copy, Clone, Default)]
+#[derive(Copy, Debug, Clone, Default, PartialEq)]
 pub struct EvmPaymentInfo {
-	amount: Balance,
-	currency_id: CurrencyId,
-	price: Ratio,
+	fee_amount: Balance,
+	fee_currency: CurrencyId,
+	fee_currency_price: Price,
+	weth_price: Price,
 }
 
 impl EvmPaymentInfo {
 	pub fn merge(self, other: Self) -> Self {
 		EvmPaymentInfo {
-			amount: self.amount.saturating_add(other.amount),
-			currency_id: self.currency_id,
-			price: self.price,
+			fee_amount: self.fee_amount.saturating_add(other.fee_amount),
+			fee_currency: self.fee_currency,
+			fee_currency_price: self.fee_currency_price,
+			weth_price: self.weth_price,
 		}
 	}
 }
 
 impl TryDrop for EvmPaymentInfo {
 	fn try_drop(self) -> Result<(), Self> {
-		if self.amount == 0 {
+		if self.fee_amount == 0 {
 			Ok(())
 		} else {
 			Err(self)
@@ -58,27 +57,21 @@ impl TryDrop for EvmPaymentInfo {
 }
 
 /// Implements the transaction payment for EVM transactions.
-/// Supports multi-currency fees based on what is provided by AC - account currency.
-pub struct TransferEvmFees<OU, AC, EC, C, MC>(PhantomData<(OU, AC, EC, C, MC)>);
+/// Supports multi-currency fees based on what is provided by AccountFeeCurrency - account currency.
+pub struct TransferEvmFees<AC, MC, Price>(PhantomData<(AC, MC, Price)>);
 
-impl<T, OU, AC, EC, C, MC> OnChargeEVMTransaction<T> for TransferEvmFees<OU, AC, EC, C, MC>
+impl<T, AC, MC, Price> OnChargeEVMTransaction<T> for TransferEvmFees<AC, MC, Price>
 where
 	T: pallet_evm::Config,
-	OU: OnUnbalanced<EvmPaymentInfo>,
-	U256: UniqueSaturatedInto<Balance>,
 	AC: AccountFeeCurrency<T::AccountId>, // AccountCurrency
-	EC: Get<CurrencyId>,                  // Evm default fee asset
-	C: Convert<(CurrencyId, CurrencyId, Balance), Option<(Balance, Ratio)>>, /* Conversion from
-	                                       * default fee
-	                                       * asset to account
-	                                       * currency */
-	U256: UniqueSaturatedInto<Balance>,
+	Price: OraclePriceProvider,           // PriceProvider
 	MC: MultiCurrency<T::AccountId, CurrencyId = CurrencyId, Balance = Balance>,
+	U256: UniqueSaturatedInto<Balance>,
 	sp_runtime::AccountId32: From<<T as frame_system::Config>::AccountId>,
 {
 	type LiquidityInfo = Option<EvmPaymentInfo>;
 
-	fn withdraw_fee(who: &H160, fee: U256) -> Result<Self::LiquidityInfo, pallet_evm::Error<T>> {
+	fn withdraw_fee(who: &H160, fee: U256) -> Result<Self::LiquidityInfo, Error<T>> {
 		if fee.is_zero() {
 			return Ok(None);
 		}
@@ -87,14 +80,18 @@ where
 		let fee_currency =
 			AC::get_fee_currency(&account_id, fee).map_err(|_| Error::<T>::BalanceLow)?;
 
-		let Some((converted, price)) =
-			C::convert((EC::get(), fee_currency, fee.unique_saturated_into()))
+		let Some((fee_amount, weth_price, fee_currency_price)) =
+			Price::get_oracle_amount_by_currency_and_amount_in(
+				&WETH,
+				fee.unique_saturated_into(),
+				&fee_currency,
+			)
 		else {
 			return Err(Error::<T>::WithdrawFailed);
 		};
 
 		// Ensure that converted fee is not zero
-		if converted == 0 {
+		if fee_amount == 0 {
 			return Err(Error::<T>::WithdrawFailed);
 		}
 
@@ -103,13 +100,13 @@ where
 			"Withdrew fee from account {:?} in currency {:?} amount {:?}",
 			account_id,
 			fee_currency,
-			converted
+			fee_amount
 		);
 
-		MC::withdraw(fee_currency, &account_id, converted)
+		MC::withdraw(fee_currency, &account_id, fee_amount)
 			.map_err(|_| Error::<T>::WithdrawFailed)?;
 
-		Ok(Some(EvmPaymentInfo { amount: converted, currency_id: fee_currency, price }))
+		Ok(Some(EvmPaymentInfo { fee_amount, fee_currency, fee_currency_price, weth_price }))
 	}
 
 	fn correct_and_deposit_fee(
@@ -118,71 +115,51 @@ where
 		_base_fee: U256,
 		already_withdrawn: Self::LiquidityInfo,
 	) -> Self::LiquidityInfo {
-		if let Some(paid) = already_withdrawn {
+		if let Some(payment_info) = already_withdrawn {
 			let account_id = T::AddressMapping::into_account_id(*who);
 
-			// fee / weth = amounts[1] / amounts[0]
-			// fee =  weth * amounts[1] / amounts[0]
-			let adjusted_paid = if let Some(converted_corrected_fee) =
-				multiply_by_rational_with_rounding(
-					corrected_fee.unique_saturated_into(),
-					paid.price.n,
-					paid.price.d,
-					Rounding::Up,
-				) {
+			let adjusted_paid = if let Some(converted_corrected_fee) = Price::get_amount_by_prices(
+				&WETH,
+				corrected_fee.unique_saturated_into(),
+				payment_info.weth_price,
+				&payment_info.fee_currency,
+				payment_info.fee_currency_price,
+			) {
 				// Calculate how much refund we should return
-				let refund_amount = paid.amount.saturating_sub(converted_corrected_fee);
+				let refund_amount = payment_info.fee_amount.saturating_sub(converted_corrected_fee);
 
 				// refund to the account that paid the fees. If this fails, the
 				// account might have dropped below the existential balance. In
 				// that case we don't refund anything.
 				let refund_imbalance =
-					match MC::deposit(paid.currency_id, &account_id, refund_amount) {
+					match MC::deposit(payment_info.fee_currency, &account_id, refund_amount) {
 						Ok(_) => 0,
 						Err(_) => refund_amount,
 					};
 				// figure out how much is left to mint back
 				// refund_amount already minted back to account, imbalance is what is left to mint
 				// if any
-				paid.amount.saturating_sub(refund_amount).saturating_add(refund_imbalance)
+				payment_info
+					.fee_amount
+					.saturating_sub(refund_amount)
+					.saturating_add(refund_imbalance)
 			} else {
 				// if conversion failed for some reason, we refund the whole amount back to treasury
-				paid.amount
+				payment_info.fee_amount
 			};
 
 			// We can simply refund all the remaining amount back to treasury
-			OU::on_unbalanced(EvmPaymentInfo {
-				amount: adjusted_paid,
-				currency_id: paid.currency_id,
-				price: paid.price,
-			});
-			return None;
+			let result = Currencies::deposit(
+				payment_info.fee_currency,
+				&crate::BifrostTreasuryAccount::get(),
+				adjusted_paid,
+			);
+			debug_assert_eq!(result, Ok(()));
 		}
 		None
 	}
 
 	fn pay_priority_fee(tip: Self::LiquidityInfo) {
-		if let Some(tip) = tip {
-			OU::on_unbalanced(tip);
-		}
-	}
-}
-
-pub struct DepositEvmFeeToTreasury;
-impl OnUnbalanced<EvmPaymentInfo> for DepositEvmFeeToTreasury {
-	// this is called for substrate-based transactions
-	fn on_unbalanceds<B>(amounts: impl Iterator<Item = EvmPaymentInfo>) {
-		Self::on_unbalanced(amounts.fold(EvmPaymentInfo::default(), |i, x| x.merge(i)))
-	}
-
-	// this is called from pallet_evm for Ethereum-based transactions
-	// (technically, it calls on_unbalanced, which calls this when non-zero)
-	fn on_nonzero_unbalanced(payment_info: EvmPaymentInfo) {
-		let result = Currencies::deposit(
-			payment_info.currency_id,
-			&crate::BifrostTreasuryAccount::get(),
-			payment_info.amount,
-		);
-		debug_assert_eq!(result, Ok(()));
+		debug_assert_eq!(tip, None);
 	}
 }
diff --git a/runtime/bifrost-polkadot/src/evm/mod.rs b/runtime/bifrost-polkadot/src/evm/mod.rs
index db779492e..9b154e959 100644
--- a/runtime/bifrost-polkadot/src/evm/mod.rs
+++ b/runtime/bifrost-polkadot/src/evm/mod.rs
@@ -23,17 +23,14 @@ use pallet_evm::EnsureAddressTruncated;
 use pallet_transaction_payment::Multiplier;
 use primitive_types::U256;
 
-use bifrost_primitives::{currency::WETH, CurrencyId};
-use bifrost_runtime_common::price::{
-	ConvertAmount, FeeAssetBalanceInCurrency, OraclePriceProvider,
-};
-
 pub use crate::evm::accounts_conversion::{ExtendedAddressMapping, FindAuthorTruncated};
 use crate::{
-	evm::runner::WrapRunner, governance::TechAdminOrCouncil, Aura, ConstU32, DynamicFee,
-	EVMChainId, Prices, Runtime, RuntimeEvent, Timestamp, Weight, EVM, MAXIMUM_BLOCK_WEIGHT,
-	NORMAL_DISPATCH_RATIO, WEIGHT_REF_TIME_PER_SECOND,
+	evm::runner::{FeeAssetBalanceInCurrency, WrapRunner},
+	governance::TechAdminOrCouncil,
+	Aura, ConstU32, DynamicFee, EVMChainId, Runtime, RuntimeEvent, Timestamp, Weight, EVM,
+	MAXIMUM_BLOCK_WEIGHT, NORMAL_DISPATCH_RATIO, WEIGHT_REF_TIME_PER_SECOND,
 };
+use bifrost_primitives::{currency::WETH, CurrencyId};
 
 mod accounts_conversion;
 mod evm_fee;
@@ -107,18 +104,16 @@ impl pallet_evm::Config for Runtime {
 		Self,
 		pallet_evm::runner::stack::Runner<Self>, // Evm runner that we wrap
 		FeeAssetBalanceInCurrency<
-			crate::Runtime,
-			ConvertAmount<OraclePriceProvider<Prices>>,
+			Runtime,
+			crate::Prices,      // Price provider
 			crate::FlexibleFee, // Get account's fee payment asset
 			crate::Currencies,  // Account balance inspector
 		>,
 	>;
 	type OnChargeTransaction = evm_fee::TransferEvmFees<
-		evm_fee::DepositEvmFeeToTreasury,
 		crate::FlexibleFee, // Get account's fee payment asset
-		WethAssetId,
-		ConvertAmount<OraclePriceProvider<Prices>>,
-		crate::Currencies, // Multi currency support
+		crate::Currencies,  // Multi currency support
+		crate::Prices,      // Price provider
 	>;
 	type OnCreate = ();
 	type FindAuthor = FindAuthorTruncated<Aura>;
diff --git a/runtime/bifrost-polkadot/src/evm/runner.rs b/runtime/bifrost-polkadot/src/evm/runner.rs
index 4e1e1058c..1bce82653 100644
--- a/runtime/bifrost-polkadot/src/evm/runner.rs
+++ b/runtime/bifrost-polkadot/src/evm/runner.rs
@@ -22,16 +22,68 @@
 //! asset.
 //!
 //! Shamelessly copied from pallet-evm and modified to support multi-currency fees.
+
 use crate::{evm::WethAssetId, Weight};
-use bifrost_primitives::{AccountFeeCurrencyBalanceInCurrency, Balance};
+use bifrost_primitives::{
+	AccountFeeCurrency, AccountFeeCurrencyBalanceInCurrency, Balance, CurrencyId,
+	OraclePriceProvider,
+};
 use fp_evm::{Account, TransactionValidationError};
-use frame_support::traits::Get;
+use frame_support::traits::{
+	tokens::{Fortitude, Preservation},
+	Get,
+};
 use pallet_evm::{
 	runner::Runner, AddressMapping, CallInfo, Config, CreateInfo, FeeCalculator, RunnerError,
 };
 use primitive_types::{H160, H256, U256};
-use sp_runtime::traits::UniqueSaturatedInto;
-use sp_std::vec::Vec;
+use sp_runtime::{traits::UniqueSaturatedInto, DispatchError};
+use sp_std::{marker::PhantomData, vec::Vec};
+
+/// AccountFeeCurrencyBalanceInCurrency implementation for the FeeAssetBalanceInCurrency.
+/// Provides account's balance of fee asset currency in a given currency
+pub struct FeeAssetBalanceInCurrency<T, Price, AC, I>(PhantomData<(T, Price, AC, I)>);
+
+impl<T, Price, AC, I> AccountFeeCurrencyBalanceInCurrency<T::AccountId>
+	for FeeAssetBalanceInCurrency<T, Price, AC, I>
+where
+	T: frame_system::Config,
+	Price: OraclePriceProvider,
+	AC: AccountFeeCurrency<T::AccountId>,
+	I: frame_support::traits::fungibles::Inspect<
+		T::AccountId,
+		AssetId = CurrencyId,
+		Balance = Balance,
+	>,
+{
+	type Output = (Balance, Weight);
+	type Error = DispatchError;
+
+	fn get_balance_in_currency(
+		to_currency: CurrencyId,
+		account: &T::AccountId,
+		fee: U256,
+	) -> Result<Self::Output, DispatchError> {
+		let from_currency = AC::get_fee_currency(account, fee)
+			.map_err(|_| DispatchError::Other("Get Currency Error."))?;
+		let account_balance =
+			I::reducible_balance(from_currency, account, Preservation::Preserve, Fortitude::Polite);
+		let price_weight = T::DbWeight::get().reads(2); // 1 read to get currency and 1 read to get balance
+
+		if from_currency == to_currency {
+			return Ok((account_balance, price_weight));
+		}
+
+		let Some((converted, _, _)) = Price::get_oracle_amount_by_currency_and_amount_in(
+			&from_currency,
+			account_balance,
+			&to_currency,
+		) else {
+			return Ok((0, price_weight));
+		};
+		Ok((converted, price_weight))
+	}
+}
 
 pub struct WrapRunner<T, R, B>(sp_std::marker::PhantomData<(T, R, B)>);
 
diff --git a/runtime/bifrost-polkadot/src/lib.rs b/runtime/bifrost-polkadot/src/lib.rs
index e95f50633..6560618d8 100644
--- a/runtime/bifrost-polkadot/src/lib.rs
+++ b/runtime/bifrost-polkadot/src/lib.rs
@@ -925,7 +925,7 @@ impl bifrost_flexible_fee::Config for Runtime {
 	type RelaychainCurrencyId = RelayCurrencyId;
 	type XcmRouter = XcmRouter;
 	type PalletId = FlexibleFeePalletId;
-	type PriceFeeder = Prices;
+	type OraclePriceProvider = Prices;
 }
 
 parameter_types! {
@@ -1187,7 +1187,7 @@ impl bifrost_fee_share::Config for Runtime {
 	type ControlOrigin = CoreAdminOrCouncil;
 	type WeightInfo = weights::bifrost_fee_share::BifrostWeight<Runtime>;
 	type FeeSharePalletId = FeeSharePalletId;
-	type PriceFeeder = Prices;
+	type OraclePriceProvider = Prices;
 }
 
 impl bifrost_cross_in_out::Config for Runtime {
@@ -1462,7 +1462,7 @@ impl pallet_prices::Config for Runtime {
 impl lend_market::Config for Runtime {
 	type RuntimeEvent = RuntimeEvent;
 	type PalletId = LendMarketPalletId;
-	type PriceFeeder = Prices;
+	type OraclePriceProvider = Prices;
 	type ReserveOrigin = TechAdminOrCouncil;
 	type UpdateOrigin = TechAdminOrCouncil;
 	type WeightInfo = lend_market::weights::BifrostWeight<Runtime>;
diff --git a/runtime/common/src/lib.rs b/runtime/common/src/lib.rs
index 4b44c00e4..c7fccfce8 100644
--- a/runtime/common/src/lib.rs
+++ b/runtime/common/src/lib.rs
@@ -32,10 +32,6 @@ use sp_runtime::{traits::Bounded, FixedPointNumber, Perquintill};
 pub mod constants;
 pub mod currency_adapter;
 pub mod currency_converter;
-pub mod price;
-pub mod ratio;
-
-pub use ratio::Ratio;
 
 #[cfg(test)]
 mod tests;
diff --git a/runtime/common/src/price.rs b/runtime/common/src/price.rs
deleted file mode 100644
index c4e628af7..000000000
--- a/runtime/common/src/price.rs
+++ /dev/null
@@ -1,116 +0,0 @@
-// 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 <https://www.gnu.org/licenses/>.
-
-use frame_support::{
-	pallet_prelude::Get,
-	traits::tokens::{Fortitude, Preservation},
-};
-use sp_core::U256;
-use sp_runtime::{
-	helpers_128bit::multiply_by_rational_with_rounding, traits::Convert, DispatchError, Rounding,
-};
-use sp_std::marker::PhantomData;
-use xcm::latest::Weight;
-
-use bifrost_primitives::{
-	AccountFeeCurrency, AccountFeeCurrencyBalanceInCurrency, Balance, CurrencyId, PriceFeeder,
-	PriceProvider,
-};
-
-use crate::Ratio;
-
-pub struct OraclePriceProvider<PF>(PhantomData<PF>);
-
-impl<PF> PriceProvider for OraclePriceProvider<PF>
-where
-	PF: PriceFeeder,
-{
-	type Price = Ratio;
-
-	fn get_price(asset_a: CurrencyId, asset_b: CurrencyId) -> Option<Self::Price> {
-		if let Some(a) = PF::get_normal_price(&asset_a) {
-			if let Some(b) = PF::get_normal_price(&asset_b) {
-				Some(Ratio::from((a, b)))
-			} else {
-				None
-			}
-		} else {
-			None
-		}
-	}
-}
-
-pub struct FeeAssetBalanceInCurrency<T, C, AC, I>(PhantomData<(T, C, AC, I)>);
-
-impl<T, C, AC, I> AccountFeeCurrencyBalanceInCurrency<T::AccountId>
-	for FeeAssetBalanceInCurrency<T, C, AC, I>
-where
-	T: frame_system::Config,
-	C: Convert<(CurrencyId, CurrencyId, Balance), Option<(Balance, Ratio)>>,
-	AC: AccountFeeCurrency<T::AccountId>,
-	I: frame_support::traits::fungibles::Inspect<
-		T::AccountId,
-		AssetId = CurrencyId,
-		Balance = Balance,
-	>,
-{
-	type Output = (Balance, Weight);
-	type Error = DispatchError;
-
-	fn get_balance_in_currency(
-		to_currency: CurrencyId,
-		account: &T::AccountId,
-		fee: U256,
-	) -> Result<Self::Output, DispatchError> {
-		let from_currency = AC::get_fee_currency(account, fee)
-			.map_err(|_| DispatchError::Other("Get Currency Error."))?;
-		let account_balance =
-			I::reducible_balance(from_currency, account, Preservation::Preserve, Fortitude::Polite);
-		let price_weight = T::DbWeight::get().reads(2); // 1 read to get currency and 1 read to get balance
-
-		if from_currency == to_currency {
-			return Ok((account_balance, price_weight));
-		}
-
-		let Some((converted, _)) = C::convert((from_currency, to_currency, account_balance)) else {
-			return Ok((0, price_weight));
-		};
-		Ok((converted, price_weight))
-	}
-}
-
-pub struct ConvertAmount<P>(PhantomData<P>);
-
-// Converts `amount` of `from_currency` to `to_currency` using given oracle
-// Input: (from_currency, to_currency, amount)
-// Output: Option<(converted_amount, price)>
-impl<P> Convert<(CurrencyId, CurrencyId, Balance), Option<(Balance, Ratio)>> for ConvertAmount<P>
-where
-	P: PriceProvider<Price = Ratio>,
-{
-	fn convert(
-		(from_currency, to_currency, amount): (CurrencyId, CurrencyId, Balance),
-	) -> Option<(Balance, Ratio)> {
-		if from_currency == to_currency {
-			return Some((amount, Ratio::one()));
-		}
-		let price = P::get_price(from_currency, to_currency)?;
-		let converted = multiply_by_rational_with_rounding(amount, price.n, price.d, Rounding::Up)?;
-		Some((converted, price))
-	}
-}
diff --git a/runtime/common/src/ratio.rs b/runtime/common/src/ratio.rs
deleted file mode 100644
index 01022e8e7..000000000
--- a/runtime/common/src/ratio.rs
+++ /dev/null
@@ -1,154 +0,0 @@
-// 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 <https://www.gnu.org/licenses/>.
-
-use core::cmp::{Ord, Ordering, PartialOrd};
-use num_traits::Zero;
-use parity_scale_codec::{Decode, Encode, MaxEncodedLen};
-use scale_info::TypeInfo;
-use serde::{Deserialize, Serialize};
-use sp_arithmetic::helpers_128bit;
-
-/// A rational number represented by a `n`umerator and `d`enominator.
-#[derive(
-	Clone,
-	Copy,
-	Default,
-	PartialEq,
-	Eq,
-	Encode,
-	Decode,
-	Serialize,
-	Deserialize,
-	TypeInfo,
-	MaxEncodedLen,
-)]
-pub struct Ratio {
-	pub n: u128,
-	pub d: u128,
-}
-
-impl Ratio {
-	/// Build from a raw `n/d`. Ensures that `d > 0`.
-	pub const fn new(n: u128, d: u128) -> Self {
-		// reimplement `.max(1)` so this can be `const`
-		let d = if d > 0 { d } else { 1 };
-		Self { n, d }
-	}
-
-	/// Build from a raw `n/d`. This could lead to / 0 if not properly handled.
-	pub const fn new_unchecked(n: u128, d: u128) -> Self {
-		Self { n, d }
-	}
-
-	/// Return a representation of one.
-	///
-	/// Note that more than one combination of `n` and `d` can be one.
-	pub const fn one() -> Self {
-		Self::new_unchecked(1, 1)
-	}
-
-	/// Return whether `self` is one.
-	///
-	/// Should a denominator of 0 happen, this function will return `false`.
-	///
-	/// Note that more than one combination of `n` and `d` can be one.
-	pub const fn is_one(&self) -> bool {
-		self.d > 0 && self.n == self.d
-	}
-
-	/// Return a representation of zero.
-	///
-	/// Note that any combination of `n == 0` and `d` represents zero.
-	pub const fn zero() -> Self {
-		Self::new_unchecked(0, 1)
-	}
-
-	/// Return whether `self` is zero.
-	///
-	/// Note that any combination of `n == 0` and `d` represents zero.
-	pub const fn is_zero(&self) -> bool {
-		self.n == 0
-	}
-
-	/// Invert `n/d` to `d/n`.
-	///
-	/// NOTE: Zero inverts to zero.
-	pub const fn inverted(self) -> Self {
-		if self.is_zero() {
-			self
-		} else {
-			Self { n: self.d, d: self.n }
-		}
-	}
-}
-
-impl From<Ratio> for (u128, u128) {
-	fn from(ratio: Ratio) -> (u128, u128) {
-		(ratio.n, ratio.d)
-	}
-}
-
-impl From<u128> for Ratio {
-	fn from(n: u128) -> Self {
-		Self::new(n, 1)
-	}
-}
-
-impl From<(u128, u128)> for Ratio {
-	fn from((n, d): (u128, u128)) -> Self {
-		Self::new(n, d)
-	}
-}
-
-impl PartialOrd for Ratio {
-	fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
-		Some(self.cmp(other))
-	}
-}
-
-// Taken from Substrate's `Rational128`.
-impl Ord for Ratio {
-	fn cmp(&self, other: &Self) -> Ordering {
-		if self.d == other.d {
-			self.n.cmp(&other.n)
-		} else if self.d.is_zero() {
-			Ordering::Greater
-		} else if other.d.is_zero() {
-			Ordering::Less
-		} else {
-			let self_n = helpers_128bit::to_big_uint(self.n) * helpers_128bit::to_big_uint(other.d);
-			let other_n =
-				helpers_128bit::to_big_uint(other.n) * helpers_128bit::to_big_uint(self.d);
-			self_n.cmp(&other_n)
-		}
-	}
-}
-
-#[cfg(feature = "std")]
-impl sp_std::fmt::Debug for Ratio {
-	fn fmt(&self, f: &mut sp_std::fmt::Formatter<'_>) -> sp_std::fmt::Result {
-		write!(f, "Ratio({} / {} ≈ {:.8})", self.n, self.d, self.n as f64 / self.d as f64)
-	}
-}
-
-#[cfg(not(feature = "std"))]
-impl sp_std::fmt::Debug for Ratio {
-	fn fmt(&self, f: &mut sp_std::fmt::Formatter<'_>) -> sp_std::fmt::Result {
-		write!(f, "Ratio({} / {})", self.n, self.d)
-	}
-}

From 1a87eecda03607ecac5c8eaeb501bc5e29cf078e Mon Sep 17 00:00:00 2001
From: MJLNSN <96321798+MJLNSN@users.noreply.github.com>
Date: Wed, 25 Sep 2024 10:20:52 +0800
Subject: [PATCH 04/31] Moved PalletId and AccountId to primitives. (#1437)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* Bifrost v0.13.0

* Remove getter in buy-back. (#1354)

* Bifrost v0.12.0

* remove old migrations

* Fix vtokenVoting.removeDelegatorVote (#1288)

* add PollClass type

* add the calss parameter to the remove_delegator_vote method

* Add metadata hash (#1299)

* feat: 🎸 add buy-back

* Bifrost v0.10.001

* feat: 🎸 benchmark

* SLPx mint support commission id (#1261)

* Add vtoken exchange rate rpc (#1260)

* fix: 🐛 add event (#1263)

* add update_currency_metadata function (#1259)

* add update_currency_metadata function

* fix: 🐛 correct update_currency_metadata weight

* add the use of Vec (#1264)

* Add vtoken exchange rate rpc

* add the use of Vec

* Upgrade to Polkadot-SDK v1.7.0 (#1262)

* Bifrost v0.10.0

* fix: 🐛 clippy

* Fix chain spec (#1243)

* Upgrade to polkadot-v1.7.0

---------

Co-authored-by: SunTiebing <1045060705@qq.com>
Co-authored-by: Edwin Wang <lark930@gmail.com>

* Fix compile

* feat: 🎸 add metadata-hash-extension (#1265)

* feat: 🎸 add metadata-hash-extension

* Fix compile (#1266)

* Fix/fix vtoken voting unlock (#1267)

* update the exchange rate of vtokenminting of vtokenvoting test

* Resolve the frozen anomaly when unlocking

* Revert "feat: 🎸 add metadata-hash-extension (#1265)" (#1268)

This reverts commit 489fc9c6adeae44d23edf449e74fde3d6aa40bc3.

* rename the version number to 0.11.0

* Slp supports XCMv4 and reconstruct integration tests (#1272)

* Fix compile

* Reconstruct integration tests and slp supports XCMv4

* Fix slp construct_xcm_message

* Feat/slpx mint add commission (#1273)

* SLPx mint support commission id

* remove the channel_id parameter from the mint method

* add mint_with_channel_id method

* perform data migration for OrderQueue storage

* slpx: set the default value of channel_id to 0

* resolve conflicts

* change the location of the old data structure during storage migration

* Feat/add vtoken exchange rate rpc (#1274)

* Add vtoken exchange rate rpc

* add the use of Vec

* supplement the RPC logic && fix bugs

* adjust the RPC exchange rate precision to three decimal places

* fix clippy

* fix bug: storage migration anomaly (#1276)

* SLPx mint support commission id

* remove the channel_id parameter from the mint method

* add mint_with_channel_id method

* perform data migration for OrderQueue storage

* slpx: set the default value of channel_id to 0

* resolve conflicts

* change the location of the old data structure during storage migration

* fix bug: storage migration anomaly

* Slp removes refund (#1275)

* Slp removes refund

* Fix clippy

* Feat/add vtoken exchange rate rpc (#1277)

* Add vtoken exchange rate rpc

* add the use of Vec

* supplement the RPC logic && fix bugs

* adjust the RPC exchange rate precision to three decimal places

* fix clippy

* supplement omissions: adjust the RPC exchange rate precision to three decimal places

* Remove dmp queue (#1279)

* fix: 🐛 CheckMetadataHash to false

* fix: 🐛 update sp-api

* refactor: 💡 fmt

* fix: 🐛 add metadata-hash

* fix: 🐛 add feature metadata-hash

* fix: 🐛 rm metadata-hash feature

---------

Co-authored-by: SunTiebing <1045060705@qq.com>
Co-authored-by: SunTiebing <87381708+SunTiebing@users.noreply.github.com>
Co-authored-by: NingBo Wang <2536935847@qq.com>
Co-authored-by: Edwin Wang <lark930@gmail.com>

* refactor: 💡 update MaxTurnout and whitelisted_caller track (#1304)

* Allow to receive and send Ethereum assets (#1305)

* feat: 🎸 add buy-back

* Bifrost v0.10.001

* feat: 🎸 benchmark

* SLPx mint support commission id (#1261)

* Add vtoken exchange rate rpc (#1260)

* fix: 🐛 add event (#1263)

* add update_currency_metadata function (#1259)

* add update_currency_metadata function

* fix: 🐛 correct update_currency_metadata weight

* add the use of Vec (#1264)

* Add vtoken exchange rate rpc

* add the use of Vec

* Upgrade to Polkadot-SDK v1.7.0 (#1262)

* Bifrost v0.10.0

* fix: 🐛 clippy

* Fix chain spec (#1243)

* Upgrade to polkadot-v1.7.0

---------

Co-authored-by: SunTiebing <1045060705@qq.com>
Co-authored-by: Edwin Wang <lark930@gmail.com>

* feat: 🎸 add metadata-hash-extension (#1265)

* Fix compile (#1266)

* Fix/fix vtoken voting unlock (#1267)

* update the exchange rate of vtokenminting of vtokenvoting test

* Resolve the frozen anomaly when unlocking

* Revert "feat: 🎸 add metadata-hash-extension (#1265)" (#1268)

This reverts commit 489fc9c6adeae44d23edf449e74fde3d6aa40bc3.

* rename the version number to 0.11.0

* Slp supports XCMv4 and reconstruct integration tests (#1272)

* Fix compile

* Reconstruct integration tests and slp supports XCMv4

* Fix slp construct_xcm_message

* Feat/slpx mint add commission (#1273)

* SLPx mint support commission id

* remove the channel_id parameter from the mint method

* add mint_with_channel_id method

* perform data migration for OrderQueue storage

* slpx: set the default value of channel_id to 0

* resolve conflicts

* change the location of the old data structure during storage migration

* Feat/add vtoken exchange rate rpc (#1274)

* Add vtoken exchange rate rpc

* add the use of Vec

* supplement the RPC logic && fix bugs

* adjust the RPC exchange rate precision to three decimal places

* fix clippy

* fix bug: storage migration anomaly (#1276)

* SLPx mint support commission id

* remove the channel_id parameter from the mint method

* add mint_with_channel_id method

* perform data migration for OrderQueue storage

* slpx: set the default value of channel_id to 0

* resolve conflicts

* change the location of the old data structure during storage migration

* fix bug: storage migration anomaly

* Slp removes refund (#1275)

* Slp removes refund

* Fix clippy

* Allow to receive and send Ethereum assets

* Add constants

---------

Co-authored-by: yooml <ymlll0508@gmail.com>
Co-authored-by: SunTiebing <1045060705@qq.com>
Co-authored-by: SunTiebing <87381708+SunTiebing@users.noreply.github.com>
Co-authored-by: Edwin Wang <lark930@gmail.com>

* Disable supplement_fee_reserve (#1306)

* Remove call_switchgear and add tx_pause (#1308)

* Remove call_switchgear and add tx_pause

* Fix clippy

* Optimize flexible fee (#1307)

* Optimize flexible fee

* Fix bug

* Fix bug

* Add PalletId

* Add error handle

* feat: 🎸 add market-bond

* fix: 🐛 test-all

* fix: 🐛 try-runtime

* Add the channel_id field to the Minted event

* Upgrade to polkadot-v1.13.0 (#1312)

* Upgrade to polkadot-v1.13.0

* remove the warning

* Fix dep issues

* Upgrade to polkadot-v1.13.0

* supplement and upgrade the code

* Upgrade the new parts from v0.12.0

* Fix dep issues

* format Cargo.toml

* Modify the AddOrigin type of the fellowship in bifrost-polkadot

* Cancel the cross-in-out migration.

* fix clippy

---------

Co-authored-by: hqwangningbo <2536935847@qq.com>

* Use github dependencies (#1314)

* Fix flexible_fee TransferTo (#1315)

* Fix generate_genesis_state (#1317)

* Optimize oracle (#1318)

* refactor: 💡 optimize orml-oracle

* fix: 🐛 MinimumTimestampInterval

* style: 💄 rename to MaximumValueInterval

* Add some tests for ve-minting

* Add some tests for ve-minting

* Integrate evm (#1319)

* Update dep

* Ingrate EVM

* Fix deps

* Add precompiles.rs

* Remove pallet-hotfix-sufficients

* Add pallet-evm-accounts

* Evm precompiles

* EVM integration

* Fix compile

* Fix rpc

* Fix `encode_evm_address` and `decode_evm_address`

* Fix evm precompile multicurrency

* Implementing Erc20Mapping using xc-20 standard

* Compatible with BNC Decimal

* Increase min_gas_price

* feat: enable dev mode with manual seal & fix pending block problem

* Add copyright and fix some bugs

* Change native token to WETH

* Support evm flexible fee

* Add inner_swap_exact_assets_for_assets to evm withdraw fee

* Remove swap

* EVM migration from bifrost kusama to bifrost polkadot

* Fix erc20 precompile

* Use OraclePrice

* Fix some errors

* feat: add prices genesis config & optimize dev mode code

* Fix conflicts

* Fix some errors

* Fix clippy

* Format Cargo.toml

* Remove unused code

* Fix clippy

* Fix some errors

* Fix erc20 precompile

---------

Co-authored-by: Edwin Wang <lark930@gmail.com>
Co-authored-by: Damian.lu <wsteth@outlook.com>

* Fix try-runtime (#1323)

* Fix manual seal

* Fix manual seal (#1324)

* fix: 🐛 fellowship collective data (#1325)

* fix: add parachain mock inherent data provider

* Fix ethereum transfer fee (#1328)

* Add evm genesis migration (#1338)

* Bifrost v0.12.0 (#1286)

* Bifrost v0.12.0

* remove old migrations

* Fix vtokenVoting.removeDelegatorVote (#1288)

* add PollClass type

* add the calss parameter to the remove_delegator_vote method

* Add metadata hash (#1299)

* feat: 🎸 add buy-back

* Bifrost v0.10.001

* feat: 🎸 benchmark

* SLPx mint support commission id (#1261)

* Add vtoken exchange rate rpc (#1260)

* fix: 🐛 add event (#1263)

* add update_currency_metadata function (#1259)

* add update_currency_metadata function

* fix: 🐛 correct update_currency_metadata weight

* add the use of Vec (#1264)

* Add vtoken exchange rate rpc

* add the use of Vec

* Upgrade to Polkadot-SDK v1.7.0 (#1262)

* Bifrost v0.10.0

* fix: 🐛 clippy

* Fix chain spec (#1243)

* Upgrade to polkadot-v1.7.0

---------

Co-authored-by: SunTiebing <1045060705@qq.com>
Co-authored-by: Edwin Wang <lark930@gmail.com>

* Fix compile

* feat: 🎸 add metadata-hash-extension (#1265)

* feat: 🎸 add metadata-hash-extension

* Fix compile (#1266)

* Fix/fix vtoken voting unlock (#1267)

* update the exchange rate of vtokenminting of vtokenvoting test

* Resolve the frozen anomaly when unlocking

* Revert "feat: 🎸 add metadata-hash-extension (#1265)" (#1268)

This reverts commit 489fc9c6adeae44d23edf449e74fde3d6aa40bc3.

* rename the version number to 0.11.0

* Slp supports XCMv4 and reconstruct integration tests (#1272)

* Fix compile

* Reconstruct integration tests and slp supports XCMv4

* Fix slp construct_xcm_message

* Feat/slpx mint add commission (#1273)

* SLPx mint support commission id

* remove the channel_id parameter from the mint method

* add mint_with_channel_id method

* perform data migration for OrderQueue storage

* slpx: set the default value of channel_id to 0

* resolve conflicts

* change the location of the old data structure during storage migration

* Feat/add vtoken exchange rate rpc (#1274)

* Add vtoken exchange rate rpc

* add the use of Vec

* supplement the RPC logic && fix bugs

* adjust the RPC exchange rate precision to three decimal places

* fix clippy

* fix bug: storage migration anomaly (#1276)

* SLPx mint support commission id

* remove the channel_id parameter from the mint method

* add mint_with_channel_id method

* perform data migration for OrderQueue storage

* slpx: set the default value of channel_id to 0

* resolve conflicts

* change the location of the old data structure during storage migration

* fix bug: storage migration anomaly

* Slp removes refund (#1275)

* Slp removes refund

* Fix clippy

* Feat/add vtoken exchange rate rpc (#1277)

* Add vtoken exchange rate rpc

* add the use of Vec

* supplement the RPC logic && fix bugs

* adjust the RPC exchange rate precision to three decimal places

* fix clippy

* supplement omissions: adjust the RPC exchange rate precision to three decimal places

* Remove dmp queue (#1279)

* fix: 🐛 CheckMetadataHash to false

* fix: 🐛 update sp-api

* refactor: 💡 fmt

* fix: 🐛 add metadata-hash

* fix: 🐛 add feature metadata-hash

* fix: 🐛 rm metadata-hash feature

---------

Co-authored-by: SunTiebing <1045060705@qq.com>
Co-authored-by: SunTiebing <87381708+SunTiebing@users.noreply.github.com>
Co-authored-by: NingBo Wang <2536935847@qq.com>
Co-authored-by: Edwin Wang <lark930@gmail.com>

* refactor: 💡 update MaxTurnout and whitelisted_caller track (#1304)

* Allow to receive and send Ethereum assets (#1305)

* feat: 🎸 add buy-back

* Bifrost v0.10.001

* feat: 🎸 benchmark

* SLPx mint support commission id (#1261)

* Add vtoken exchange rate rpc (#1260)

* fix: 🐛 add event (#1263)

* add update_currency_metadata function (#1259)

* add update_currency_metadata function

* fix: 🐛 correct update_currency_metadata weight

* add the use of Vec (#1264)

* Add vtoken exchange rate rpc

* add the use of Vec

* Upgrade to Polkadot-SDK v1.7.0 (#1262)

* Bifrost v0.10.0

* fix: 🐛 clippy

* Fix chain spec (#1243)

* Upgrade to polkadot-v1.7.0

---------

Co-authored-by: SunTiebing <1045060705@qq.com>
Co-authored-by: Edwin Wang <lark930@gmail.com>

* feat: 🎸 add metadata-hash-extension (#1265)

* Fix compile (#1266)

* Fix/fix vtoken voting unlock (#1267)

* update the exchange rate of vtokenminting of vtokenvoting test

* Resolve the frozen anomaly when unlocking

* Revert "feat: 🎸 add metadata-hash-extension (#1265)" (#1268)

This reverts commit 489fc9c6adeae44d23edf449e74fde3d6aa40bc3.

* rename the version number to 0.11.0

* Slp supports XCMv4 and reconstruct integration tests (#1272)

* Fix compile

* Reconstruct integration tests and slp supports XCMv4

* Fix slp construct_xcm_message

* Feat/slpx mint add commission (#1273)

* SLPx mint support commission id

* remove the channel_id parameter from the mint method

* add mint_with_channel_id method

* perform data migration for OrderQueue storage

* slpx: set the default value of channel_id to 0

* resolve conflicts

* change the location of the old data structure during storage migration

* Feat/add vtoken exchange rate rpc (#1274)

* Add vtoken exchange rate rpc

* add the use of Vec

* supplement the RPC logic && fix bugs

* adjust the RPC exchange rate precision to three decimal places

* fix clippy

* fix bug: storage migration anomaly (#1276)

* SLPx mint support commission id

* remove the channel_id parameter from the mint method

* add mint_with_channel_id method

* perform data migration for OrderQueue storage

* slpx: set the default value of channel_id to 0

* resolve conflicts

* change the location of the old data structure during storage migration

* fix bug: storage migration anomaly

* Slp removes refund (#1275)

* Slp removes refund

* Fix clippy

* Allow to receive and send Ethereum assets

* Add constants

---------

Co-authored-by: yooml <ymlll0508@gmail.com>
Co-authored-by: SunTiebing <1045060705@qq.com>
Co-authored-by: SunTiebing <87381708+SunTiebing@users.noreply.github.com>
Co-authored-by: Edwin Wang <lark930@gmail.com>

* Disable supplement_fee_reserve (#1306)

* Remove call_switchgear and add tx_pause (#1308)

* Remove call_switchgear and add tx_pause

* Fix clippy

* Optimize flexible fee (#1307)

* Optimize flexible fee

* Fix bug

* Fix bug

* Add PalletId

* Add error handle

* feat: 🎸 add market-bond

* fix: 🐛 test-all

* fix: 🐛 try-runtime

* Add the channel_id field to the Minted event

* Upgrade to polkadot-v1.13.0 (#1312)

* Upgrade to polkadot-v1.13.0

* remove the warning

* Fix dep issues

* Upgrade to polkadot-v1.13.0

* supplement and upgrade the code

* Upgrade the new parts from v0.12.0

* Fix dep issues

* format Cargo.toml

* Modify the AddOrigin type of the fellowship in bifrost-polkadot

* Cancel the cross-in-out migration.

* fix clippy

---------

Co-authored-by: hqwangningbo <2536935847@qq.com>

* Use github dependencies (#1314)

* Fix flexible_fee TransferTo (#1315)

* Fix generate_genesis_state (#1317)

* Optimize oracle (#1318)

* refactor: 💡 optimize orml-oracle

* fix: 🐛 MinimumTimestampInterval

* style: 💄 rename to MaximumValueInterval

* Add some tests for ve-minting

* Add some tests for ve-minting

* Integrate evm (#1319)

* Update dep

* Ingrate EVM

* Fix deps

* Add precompiles.rs

* Remove pallet-hotfix-sufficients

* Add pallet-evm-accounts

* Evm precompiles

* EVM integration

* Fix compile

* Fix rpc

* Fix `encode_evm_address` and `decode_evm_address`

* Fix evm precompile multicurrency

* Implementing Erc20Mapping using xc-20 standard

* Compatible with BNC Decimal

* Increase min_gas_price

* feat: enable dev mode with manual seal & fix pending block problem

* Add copyright and fix some bugs

* Change native token to WETH

* Support evm flexible fee

* Add inner_swap_exact_assets_for_assets to evm withdraw fee

* Remove swap

* EVM migration from bifrost kusama to bifrost polkadot

* Fix erc20 precompile

* Use OraclePrice

* Fix some errors

* feat: add prices genesis config & optimize dev mode code

* Fix conflicts

* Fix some errors

* Fix clippy

* Format Cargo.toml

* Remove unused code

* Fix clippy

* Fix some errors

* Fix erc20 precompile

---------

Co-authored-by: Edwin Wang <lark930@gmail.com>
Co-authored-by: Damian.lu <wsteth@outlook.com>

* Fix try-runtime (#1323)

* Fix manual seal

* Fix manual seal (#1324)

* fix: 🐛 fellowship collective data (#1325)

* fix: add parachain mock inherent data provider

* Fix ethereum transfer fee (#1328)

---------

Co-authored-by: Edwin Wang <lark930@gmail.com>
Co-authored-by: yooml <ymlll0508@gmail.com>
Co-authored-by: NingBo Wang <2536935847@qq.com>
Co-authored-by: Gemma <neversaynever333@outlook.com>
Co-authored-by: Damian.lu <wsteth@outlook.com>

* Add evm genesis storage

* [skip ci] Add evmSince

---------

Co-authored-by: SunTiebing <87381708+SunTiebing@users.noreply.github.com>
Co-authored-by: Edwin Wang <lark930@gmail.com>
Co-authored-by: yooml <ymlll0508@gmail.com>
Co-authored-by: Gemma <neversaynever333@outlook.com>
Co-authored-by: Damian.lu <wsteth@outlook.com>

* Bump version to 0.12.1

* Update Cargo.lock

* Fix migration (#1341)

* Bifrost v0.12.0 (#1286)

* Bifrost v0.12.0

* remove old migrations

* Fix vtokenVoting.removeDelegatorVote (#1288)

* add PollClass type

* add the calss parameter to the remove_delegator_vote method

* Add metadata hash (#1299)

* feat: 🎸 add buy-back

* Bifrost v0.10.001

* feat: 🎸 benchmark

* SLPx mint support commission id (#1261)

* Add vtoken exchange rate rpc (#1260)

* fix: 🐛 add event (#1263)

* add update_currency_metadata function (#1259)

* add update_currency_metadata function

* fix: 🐛 correct update_currency_metadata weight

* add the use of Vec (#1264)

* Add vtoken exchange rate rpc

* add the use of Vec

* Upgrade to Polkadot-SDK v1.7.0 (#1262)

* Bifrost v0.10.0

* fix: 🐛 clippy

* Fix chain spec (#1243)

* Upgrade to polkadot-v1.7.0

---------

Co-authored-by: SunTiebing <1045060705@qq.com>
Co-authored-by: Edwin Wang <lark930@gmail.com>

* Fix compile

* feat: 🎸 add metadata-hash-extension (#1265)

* feat: 🎸 add metadata-hash-extension

* Fix compile (#1266)

* Fix/fix vtoken voting unlock (#1267)

* update the exchange rate of vtokenminting of vtokenvoting test

* Resolve the frozen anomaly when unlocking

* Revert "feat: 🎸 add metadata-hash-extension (#1265)" (#1268)

This reverts commit 489fc9c6adeae44d23edf449e74fde3d6aa40bc3.

* rename the version number to 0.11.0

* Slp supports XCMv4 and reconstruct integration tests (#1272)

* Fix compile

* Reconstruct integration tests and slp supports XCMv4

* Fix slp construct_xcm_message

* Feat/slpx mint add commission (#1273)

* SLPx mint support commission id

* remove the channel_id parameter from the mint method

* add mint_with_channel_id method

* perform data migration for OrderQueue storage

* slpx: set the default value of channel_id to 0

* resolve conflicts

* change the location of the old data structure during storage migration

* Feat/add vtoken exchange rate rpc (#1274)

* Add vtoken exchange rate rpc

* add the use of Vec

* supplement the RPC logic && fix bugs

* adjust the RPC exchange rate precision to three decimal places

* fix clippy

* fix bug: storage migration anomaly (#1276)

* SLPx mint support commission id

* remove the channel_id parameter from the mint method

* add mint_with_channel_id method

* perform data migration for OrderQueue storage

* slpx: set the default value of channel_id to 0

* resolve conflicts

* change the location of the old data structure during storage migration

* fix bug: storage migration anomaly

* Slp removes refund (#1275)

* Slp removes refund

* Fix clippy

* Feat/add vtoken exchange rate rpc (#1277)

* Add vtoken exchange rate rpc

* add the use of Vec

* supplement the RPC logic && fix bugs

* adjust the RPC exchange rate precision to three decimal places

* fix clippy

* supplement omissions: adjust the RPC exchange rate precision to three decimal places

* Remove dmp queue (#1279)

* fix: 🐛 CheckMetadataHash to false

* fix: 🐛 update sp-api

* refactor: 💡 fmt

* fix: 🐛 add metadata-hash

* fix: 🐛 add feature metadata-hash

* fix: 🐛 rm metadata-hash feature

---------

Co-authored-by: SunTiebing <1045060705@qq.com>
Co-authored-by: SunTiebing <87381708+SunTiebing@users.noreply.github.com>
Co-authored-by: NingBo Wang <2536935847@qq.com>
Co-authored-by: Edwin Wang <lark930@gmail.com>

* refactor: 💡 update MaxTurnout and whitelisted_caller track (#1304)

* Allow to receive and send Ethereum assets (#1305)

* feat: 🎸 add buy-back

* Bifrost v0.10.001

* feat: 🎸 benchmark

* SLPx mint support commission id (#1261)

* Add vtoken exchange rate rpc (#1260)

* fix: 🐛 add event (#1263)

* add update_currency_metadata function (#1259)

* add update_currency_metadata function

* fix: 🐛 correct update_currency_metadata weight

* add the use of Vec (#1264)

* Add vtoken exchange rate rpc

* add the use of Vec

* Upgrade to Polkadot-SDK v1.7.0 (#1262)

* Bifrost v0.10.0

* fix: 🐛 clippy

* Fix chain spec (#1243)

* Upgrade to polkadot-v1.7.0

---------

Co-authored-by: SunTiebing <1045060705@qq.com>
Co-authored-by: Edwin Wang <lark930@gmail.com>

* feat: 🎸 add metadata-hash-extension (#1265)

* Fix compile (#1266)

* Fix/fix vtoken voting unlock (#1267)

* update the exchange rate of vtokenminting of vtokenvoting test

* Resolve the frozen anomaly when unlocking

* Revert "feat: 🎸 add metadata-hash-extension (#1265)" (#1268)

This reverts commit 489fc9c6adeae44d23edf449e74fde3d6aa40bc3.

* rename the version number to 0.11.0

* Slp supports XCMv4 and reconstruct integration tests (#1272)

* Fix compile

* Reconstruct integration tests and slp supports XCMv4

* Fix slp construct_xcm_message

* Feat/slpx mint add commission (#1273)

* SLPx mint support commission id

* remove the channel_id parameter from the mint method

* add mint_with_channel_id method

* perform data migration for OrderQueue storage

* slpx: set the default value of channel_id to 0

* resolve conflicts

* change the location of the old data structure during storage migration

* Feat/add vtoken exchange rate rpc (#1274)

* Add vtoken exchange rate rpc

* add the use of Vec

* supplement the RPC logic && fix bugs

* adjust the RPC exchange rate precision to three decimal places

* fix clippy

* fix bug: storage migration anomaly (#1276)

* SLPx mint support commission id

* remove the channel_id parameter from the mint method

* add mint_with_channel_id method

* perform data migration for OrderQueue storage

* slpx: set the default value of channel_id to 0

* resolve conflicts

* change the location of the old data structure during storage migration

* fix bug: storage migration anomaly

* Slp removes refund (#1275)

* Slp removes refund

* Fix clippy

* Allow to receive and send Ethereum assets

* Add constants

---------

Co-authored-by: yooml <ymlll0508@gmail.com>
Co-authored-by: SunTiebing <1045060705@qq.com>
Co-authored-by: SunTiebing <87381708+SunTiebing@users.noreply.github.com>
Co-authored-by: Edwin Wang <lark930@gmail.com>

* Disable supplement_fee_reserve (#1306)

* Remove call_switchgear and add tx_pause (#1308)

* Remove call_switchgear and add tx_pause

* Fix clippy

* Optimize flexible fee (#1307)

* Optimize flexible fee

* Fix bug

* Fix bug

* Add PalletId

* Add error handle

* feat: 🎸 add market-bond

* fix: 🐛 test-all

* fix: 🐛 try-runtime

* Add the channel_id field to the Minted event

* Upgrade to polkadot-v1.13.0 (#1312)

* Upgrade to polkadot-v1.13.0

* remove the warning

* Fix dep issues

* Upgrade to polkadot-v1.13.0

* supplement and upgrade the code

* Upgrade the new parts from v0.12.0

* Fix dep issues

* format Cargo.toml

* Modify the AddOrigin type of the fellowship in bifrost-polkadot

* Cancel the cross-in-out migration.

* fix clippy

---------

Co-authored-by: hqwangningbo <2536935847@qq.com>

* Use github dependencies (#1314)

* Fix flexible_fee TransferTo (#1315)

* Fix generate_genesis_state (#1317)

* Optimize oracle (#1318)

* refactor: 💡 optimize orml-oracle

* fix: 🐛 MinimumTimestampInterval

* style: 💄 rename to MaximumValueInterval

* Add some tests for ve-minting

* Add some tests for ve-minting

* Integrate evm (#1319)

* Update dep

* Ingrate EVM

* Fix deps

* Add precompiles.rs

* Remove pallet-hotfix-sufficients

* Add pallet-evm-accounts

* Evm precompiles

* EVM integration

* Fix compile

* Fix rpc

* Fix `encode_evm_address` and `decode_evm_address`

* Fix evm precompile multicurrency

* Implementing Erc20Mapping using xc-20 standard

* Compatible with BNC Decimal

* Increase min_gas_price

* feat: enable dev mode with manual seal & fix pending block problem

* Add copyright and fix some bugs

* Change native token to WETH

* Support evm flexible fee

* Add inner_swap_exact_assets_for_assets to evm withdraw fee

* Remove swap

* EVM migration from bifrost kusama to bifrost polkadot

* Fix erc20 precompile

* Use OraclePrice

* Fix some errors

* feat: add prices genesis config & optimize dev mode code

* Fix conflicts

* Fix some errors

* Fix clippy

* Format Cargo.toml

* Remove unused code

* Fix clippy

* Fix some errors

* Fix erc20 precompile

---------

Co-authored-by: Edwin Wang <lark930@gmail.com>
Co-authored-by: Damian.lu <wsteth@outlook.com>

* Fix try-runtime (#1323)

* Fix manual seal

* Fix manual seal (#1324)

* fix: 🐛 fellowship collective data (#1325)

* fix: add parachain mock inherent data provider

* Fix ethereum transfer fee (#1328)

---------

Co-authored-by: Edwin Wang <lark930@gmail.com>
Co-authored-by: yooml <ymlll0508@gmail.com>
Co-authored-by: NingBo Wang <2536935847@qq.com>
Co-authored-by: Gemma <neversaynever333@outlook.com>
Co-authored-by: Damian.lu <wsteth@outlook.com>

* Add evm genesis storage

* [skip ci] Add evmSince

* Fix migration

* Fix migration

* Remove unused code

---------

Co-authored-by: SunTiebing <87381708+SunTiebing@users.noreply.github.com>
Co-authored-by: Edwin Wang <lark930@gmail.com>
Co-authored-by: yooml <ymlll0508@gmail.com>
Co-authored-by: Gemma <neversaynever333@outlook.com>
Co-authored-by: Damian.lu <wsteth@outlook.com>

* Remove getter in buy-back

---------

Co-authored-by: SunTiebing <1045060705@qq.com>
Co-authored-by: SunTiebing <87381708+SunTiebing@users.noreply.github.com>
Co-authored-by: Edwin Wang <lark930@gmail.com>
Co-authored-by: yooml <ymlll0508@gmail.com>
Co-authored-by: NingBo Wang <2536935847@qq.com>
Co-authored-by: Damian.lu <wsteth@outlook.com>

* Remove getters in xcm-interface (#1352)

* Remove getters in salp. (#1351)

* Remove getter in evm-accounts (#1350)

* Remove getters in slp (#1353)

* Remove getters in slpx (#1360)

* Remove getters in vstoken-conversion. (#1362)

* Remove getters in vtoken-minting. (#1363)

* Remove getter in system-maker. (#1364)

* Remove getter in fee-share (#1365)

* Remove getters in prices (#1367)

* Remove getters in lend-market (#1366)

* Remove getters in ve-minting (#1368)

* Optimize clippy (#1369)

* Deprecated unused pallets (#1383)

* Review format (#1386)

* style: 💄 format

* style: 💄 check-all

* fix: 🐛 bench

* Update buy back (#1387)

* style: 💄 format

* style: 💄 check-all

* fix: 🐛 bench

* feat: 🎸 add destruction_ratio

* fix: 🐛 benchmark

* EVM flexible fee logic optimization (#1370)

* EVM flexible fee logic optimization

* Add comments

* Add support for handling different currency precisions & included error handling.

* Adjust the gas_fee parameter in the get_balance_in_currency method to an exact value

* fix clippy

* add test code of flexiable-fee pallet

* Update fee share (#1395)

* feat: 🎸 add usd_cumulation

* feat: 🎸 bench

* fix: 🐛 fmt

* docs: ✏️ add note

* Feat/change evm address convert rule (#1396)

* Change EVM Address convert rule

* Change EVM Address convert rule

* Remove the unused function:is_evm_account & rename truncated_account_id function to convert_account_id

* fix clippy

* refactor: 💡 move to TechAdmin (#1398)

* refactor: 💡 transfer to BuyBackAccount (#1399)

* Fix mint_with_channel_id weights (#1400)

* Recoverd imgs of banner and logo (#1401)

* feat: 🎸 add fn set_swap_out_min (#1389)

* feat: 🎸 add fn set_swap_out_min

* fix: 🐛 fmt

* fix: 🐛 fmt

* fix: 🐛 error

* feat: 🎸 add bais

* fix: 🐛 add test

* fix: 🐛 rename field bias

* Optimize the `channel-commission` code. (#1390)

* Optimize the `channel-commission` code.

* Replace the insert method with the mutate method

* Added a result check for the clear_prefix method

* Supplement the test code of `channel-commission`.

* Handling Error cases in hooks.

* Optimize the handling of the `check_removed_all` method.

* Remove getters in cross-in-out (#1402)

* Removed getters in channel-commission. (#1404)

* Removed getters in flexible-fee. (#1405)

* Removed getters in channel-commission.

* Removed getters in flexible-fee.

* Removed getters in parachain-staking. (#1406)

* Removed getters in channel-commission.

* Removed getters in flexible-fee.

* Removed getterd in parachain-staking.

* Update buy back (#1407)

* fix: 🐛 add field last_buyback_cycle for accurate judgment

* style: 💄 fmt

* Update ve minting (#1408)

* refactor: 💡 transfer to BuyBackAccount

* feat: 🎸 add auto notify_reward

* Removed getters in stable-asset and system-staking. (#1409)

* Removed getters in channel-commission.

* Removed getters in flexible-fee.

* Removed getterd in parachain-staking.

* Removed getters in stable-asset.

* Removed getters in stable-asset.

* Removed getters in token-issuer. (#1410)

* Removed getters in channel-commission.

* Removed getters in flexible-fee.

* Removed getterd in parachain-staking.

* Removed getters in stable-asset.

* Removed getters in stable-asset.

* Removed getters in token-issuer.

---------

Co-authored-by: Edwin <lark930@gmail.com>

* Moved PrarachainId to primitives. (#1394)

* Moved PrarachainId to primitives

* updated

* bug fixed

* Moved parachain ids to primitives.

* bug fixed

* Fixed error.

* Removed getters in vsbond-auction. (#1412)

* Fix evm TransferEvmFees (#1411)

* Add slp v2 (#1397)

* Add slp v2

* Add slp v2 weights

* Optimize slp v2

* Optimize slp v2

* Remove operator

* Feat/vbnc convert (#1413)

* Add vbnc-convert pallet

* add weights.rs of vbnc-convert pallet

* update token id of VBNC_P

* update weight of vbnc-convert pallet

* Supplement the comments of `vbnc-convert`.

* update VBNCConvert index in Runtime enum

* Optimize vbnc-convert pallet pallet.

* Updated (#1416)

* Add more slp v2 docs (#1419)

* Optimize xcm config (#1417)

* Optimize xcm config

* Fix moonbeam chain id

* Update fee share (#1418)

* refactor: 💡 for review

* fix: 🐛 mv storage

* fix: 🐛 bench

* refactor: 💡 fmt

---------

Co-authored-by: Edwin <lark930@gmail.com>

* Moved PalletId and AccountId to primitives

* Optimize slp v2 (#1423)

* Optimize slp v2

* Optimize weights

* fix: 🐛 redefine system pool id (#1421)

* fix: 🐛 redefine system pool id

* fix: 🐛 auto_notify_reward

* refactor: 💡 rename to bb-bnc

* style: 💄 clippy

* fix: 🐛 rename error

* refactor: 💡 rm BbBNCPalletId

* fix: 🐛 UserFarmingPool bound limit

* Moved CurrencyId to primitives.

* Updated to the latest version.

* change VBNC_P_TOKEN_ID to 5 (#1425)

* updated

* update

* updated

* updated

---------

Co-authored-by: SunTiebing <1045060705@qq.com>
Co-authored-by: SunTiebing <87381708+SunTiebing@users.noreply.github.com>
Co-authored-by: Edwin Wang <lark930@gmail.com>
Co-authored-by: yooml <ymlll0508@gmail.com>
Co-authored-by: NingBo Wang <2536935847@qq.com>
Co-authored-by: Damian.lu <wsteth@outlook.com>
---
 Cargo.lock                                    |  2 +
 pallets/bb-bnc/src/mock.rs                    | 26 +++++-------
 pallets/buy-back/src/mock.rs                  | 24 ++++-------
 pallets/buy-back/src/tests.rs                 |  1 +
 pallets/channel-commission/src/mock.rs        |  8 ++--
 pallets/clouds-convert/src/mock.rs            | 14 ++-----
 pallets/cross-in-out/src/mock.rs              |  7 ++--
 .../deprecated/lightening-redeem/src/mock.rs  |  4 --
 .../deprecated/liquidity-mining/src/mock.rs   |  1 -
 pallets/deprecated/salp-lite/src/mock.rs      |  1 -
 pallets/deprecated/system-maker/src/mock.rs   | 21 ++++------
 pallets/farming/src/mock.rs                   | 19 +++++----
 pallets/fee-share/src/mock.rs                 | 20 ++++------
 pallets/flexible-fee/src/mock.rs              |  6 +--
 pallets/lend-market/src/mock.rs               | 11 -----
 pallets/leverage-staking/src/mock.rs          | 17 +++-----
 pallets/parachain-staking/Cargo.toml          |  1 +
 pallets/parachain-staking/src/mock.rs         |  3 +-
 pallets/salp/src/mock.rs                      | 31 ++++++--------
 pallets/salp/src/tests.rs                     |  4 +-
 pallets/slp-v2/src/mock.rs                    | 12 ++----
 pallets/slp-v2/src/tests.rs                   |  2 +-
 pallets/slp/src/mocks/mock.rs                 | 10 ++---
 pallets/slp/src/mocks/mock_kusama.rs          | 14 ++-----
 pallets/slpx/src/mock.rs                      | 21 ++++------
 pallets/stable-asset/src/mock.rs              |  6 +--
 pallets/stable-pool/src/mock.rs               | 23 ++++-------
 pallets/stable-pool/src/tests.rs              |  2 +-
 pallets/system-staking/src/mock.rs            | 21 ++++------
 pallets/token-issuer/src/mock.rs              |  4 +-
 pallets/vbnc-convert/src/mock.rs              | 10 ++---
 pallets/vsbond-auction/src/mock.rs            |  5 +--
 pallets/vstoken-conversion/src/mock.rs        | 14 ++++---
 pallets/vstoken-conversion/src/tests.rs       |  1 +
 pallets/vtoken-minting/src/mock.rs            | 20 +++-------
 pallets/vtoken-voting/src/mock.rs             |  4 +-
 primitives/Cargo.toml                         |  1 +
 primitives/src/currency.rs                    |  2 +
 primitives/src/lib.rs                         | 40 +++++++++++++++++++
 39 files changed, 181 insertions(+), 252 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 06a763e29..6476ca98b 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1441,6 +1441,7 @@ dependencies = [
 name = "bifrost-parachain-staking"
 version = "3.0.1"
 dependencies = [
+ "bifrost-primitives",
  "frame-benchmarking",
  "frame-support",
  "frame-system",
@@ -1620,6 +1621,7 @@ version = "0.8.0"
 dependencies = [
  "bstringify",
  "frame-support",
+ "hex-literal 0.4.1",
  "orml-oracle",
  "orml-traits",
  "parity-scale-codec",
diff --git a/pallets/bb-bnc/src/mock.rs b/pallets/bb-bnc/src/mock.rs
index 0f5aff4bd..5bfd05d76 100644
--- a/pallets/bb-bnc/src/mock.rs
+++ b/pallets/bb-bnc/src/mock.rs
@@ -23,10 +23,13 @@
 
 use crate as bb_bnc;
 use bifrost_asset_registry::AssetIdMaps;
-use bifrost_primitives::MoonbeamChainId;
 pub use bifrost_primitives::{
 	currency::*, CurrencyId, CurrencyIdMapping, SlpxOperator, TokenSymbol,
 };
+use bifrost_primitives::{
+	BifrostEntranceAccount, BifrostExitAccount, BifrostFeeAccount, BuyBackAccount,
+	IncentivePalletId, IncentivePoolAccount, MoonbeamChainId,
+};
 use bifrost_runtime_common::{micro, milli};
 use bifrost_slp::{QueryId, QueryResponseManager};
 pub use cumulus_primitives_core::ParaId;
@@ -35,10 +38,8 @@ use frame_support::{
 	pallet_prelude::Get,
 	parameter_types,
 	traits::{Everything, Nothing},
-	PalletId,
 };
 use frame_system::{EnsureRoot, EnsureSignedBy};
-use hex_literal::hex;
 use orml_traits::{location::RelativeReserveProvider, parameter_type_with_key};
 use sp_core::ConstU32;
 use sp_runtime::{
@@ -90,7 +91,7 @@ impl frame_system::Config for Runtime {
 }
 
 parameter_types! {
-	pub const NativeCurrencyId: CurrencyId = CurrencyId::Native(TokenSymbol::BNC);
+	pub const NativeCurrencyId: CurrencyId = BNC;
 }
 
 pub type AdaptedBasicCurrency =
@@ -105,11 +106,8 @@ impl bifrost_currencies::Config for Runtime {
 
 parameter_types! {
 	pub const ExistentialDeposit: Balance = 1;
-	// pub const NativeCurrencyId: CurrencyId = CurrencyId::Native(TokenSymbol::BNC);
-	// pub const RelayCurrencyId: CurrencyId = CurrencyId::Token(TokenSymbol::KSM);
-	pub const StableCurrencyId: CurrencyId = CurrencyId::Stable(TokenSymbol::KUSD);
-	// pub SelfParaId: u32 = ParachainInfo::parachain_id().into();
-	pub const PolkadotCurrencyId: CurrencyId = CurrencyId::Token(TokenSymbol::DOT);
+	pub const StableCurrencyId: CurrencyId = KUSD;
+	pub const PolkadotCurrencyId: CurrencyId = DOT;
 }
 
 impl pallet_balances::Config for Runtime {
@@ -192,15 +190,11 @@ impl orml_xtokens::Config for Runtime {
 parameter_types! {
 	pub const MaximumUnlockIdOfUser: u32 = 1_000;
 	pub const MaximumUnlockIdOfTimeUnit: u32 = 1_000;
-	pub BifrostEntranceAccount: PalletId = PalletId(*b"bf/vtkin");
-	pub BifrostExitAccount: PalletId = PalletId(*b"bf/vtout");
-	pub BifrostFeeAccount: AccountId = hex!["e4da05f08e89bf6c43260d96f26fffcfc7deae5b465da08669a9d008e64c2c63"].into();
-	pub IncentivePoolAccount: PalletId = PalletId(*b"bf/inpoo");
 }
 
 ord_parameter_types! {
 	pub const One: AccountId = ALICE;
-	pub const RelayCurrencyId: CurrencyId = CurrencyId::Token(TokenSymbol::KSM);
+	pub const RelayCurrencyId: CurrencyId = KSM;
 }
 
 impl bifrost_vtoken_minting::Config for Runtime {
@@ -240,9 +234,7 @@ impl bifrost_asset_registry::Config for Runtime {
 }
 
 parameter_types! {
-	pub const BbBNCTokenType: CurrencyId = CurrencyId::VToken(TokenSymbol::BNC);
-	pub IncentivePalletId: PalletId = PalletId(*b"bf/bbict");
-	pub const BuyBackAccount: PalletId = PalletId(*b"bf/bybck");
+	pub const BbBNCTokenType: CurrencyId = VBNC;
 	pub const Week: BlockNumber = 50400; // a week
 	pub const MaxBlock: BlockNumber = 10512000; // four years
 	pub const Multiplier: Balance = 10_u128.pow(12);
diff --git a/pallets/buy-back/src/mock.rs b/pallets/buy-back/src/mock.rs
index ae4b9787a..ce98941ad 100644
--- a/pallets/buy-back/src/mock.rs
+++ b/pallets/buy-back/src/mock.rs
@@ -22,8 +22,11 @@
 #![allow(non_upper_case_globals)]
 
 use bifrost_asset_registry::AssetIdMaps;
-use bifrost_primitives::MoonbeamChainId;
-pub use bifrost_primitives::{currency::*, CurrencyId, SlpxOperator, TokenSymbol};
+pub use bifrost_primitives::{currency::*, CurrencyId, SlpxOperator};
+use bifrost_primitives::{
+	BifrostEntranceAccount, BifrostExitAccount, BifrostFeeAccount, BuyBackAccount,
+	IncentivePalletId, IncentivePoolAccount, LiquidityAccount, MoonbeamChainId, ZenlinkPalletId,
+};
 use bifrost_slp::{QueryId, QueryResponseManager};
 pub use cumulus_primitives_core::ParaId;
 use frame_support::{
@@ -32,10 +35,8 @@ use frame_support::{
 	parameter_types,
 	sp_runtime::{traits::ConvertInto, DispatchError, DispatchResult},
 	traits::{Everything, Nothing},
-	PalletId,
 };
 use frame_system::{EnsureRoot, EnsureSignedBy};
-use hex_literal::hex;
 use orml_traits::{location::RelativeReserveProvider, parameter_type_with_key, MultiCurrency};
 use sp_core::ConstU32;
 use sp_runtime::{
@@ -104,7 +105,7 @@ impl frame_system::Config for Runtime {
 }
 
 parameter_types! {
-	pub const GetNativeCurrencyId: CurrencyId = CurrencyId::Native(TokenSymbol::BNC);
+	pub const GetNativeCurrencyId: CurrencyId = BNC;
 }
 
 pub type AdaptedBasicCurrency =
@@ -158,14 +159,11 @@ impl orml_tokens::Config for Runtime {
 
 parameter_types! {
 	pub const TreasuryAccount: AccountId32 = TREASURY_ACCOUNT;
-	pub BifrostVsbondAccount: PalletId = PalletId(*b"bf/salpb");
-	pub const BuyBackAccount: PalletId = PalletId(*b"bf/bybck");
-	pub const LiquidityAccount: PalletId = PalletId(*b"bf/liqdt");
 }
 
 ord_parameter_types! {
 	pub const One: AccountId = ALICE;
-	pub const RelayCurrencyId: CurrencyId = CurrencyId::Token(TokenSymbol::KSM);
+	pub const RelayCurrencyId: CurrencyId = KSM;
 }
 
 impl bifrost_buy_back::Config for Runtime {
@@ -283,10 +281,6 @@ impl orml_xtokens::Config for Runtime {
 parameter_types! {
 	pub const MaximumUnlockIdOfUser: u32 = 10;
 	pub const MaximumUnlockIdOfTimeUnit: u32 = 50;
-	pub BifrostEntranceAccount: PalletId = PalletId(*b"bf/vtkin");
-	pub BifrostExitAccount: PalletId = PalletId(*b"bf/vtout");
-	pub BifrostFeeAccount: AccountId = hex!["e4da05f08e89bf6c43260d96f26fffcfc7deae5b465da08669a9d008e64c2c63"].into();
-	pub IncentivePoolAccount: PalletId = PalletId(*b"bf/inpoo");
 }
 
 impl bifrost_vtoken_minting::Config for Runtime {
@@ -316,7 +310,6 @@ impl bifrost_vtoken_minting::Config for Runtime {
 }
 
 parameter_types! {
-	pub const ZenlinkPalletId: PalletId = PalletId(*b"/zenlink");
 	pub const GetExchangeFee: (u32, u32) = (3, 1000);   // 0.3%
 	pub const SelfParaId: u32 = 2001;
 }
@@ -465,8 +458,7 @@ impl pallet_xcm::Config for Runtime {
 }
 
 parameter_types! {
-	pub const BbBNCTokenType: CurrencyId = CurrencyId::VToken(TokenSymbol::BNC);
-	pub IncentivePalletId: PalletId = PalletId(*b"bf/bbict");
+	pub const BbBNCTokenType: CurrencyId = VBNC;
 	pub const Week: BlockNumber = 50400; // a week
 	pub const MaxBlock: BlockNumber = 10512000; // four years
 	pub const Multiplier: Balance = 10_u128.pow(12);
diff --git a/pallets/buy-back/src/tests.rs b/pallets/buy-back/src/tests.rs
index 485d80d52..864c9dfd9 100644
--- a/pallets/buy-back/src/tests.rs
+++ b/pallets/buy-back/src/tests.rs
@@ -21,6 +21,7 @@
 #![cfg(test)]
 
 use crate::{mock::*, *};
+use bifrost_primitives::IncentivePalletId;
 use frame_support::{assert_noop, assert_ok};
 use sp_arithmetic::per_things::Permill;
 
diff --git a/pallets/channel-commission/src/mock.rs b/pallets/channel-commission/src/mock.rs
index 69ef466b2..aa9c70ae6 100644
--- a/pallets/channel-commission/src/mock.rs
+++ b/pallets/channel-commission/src/mock.rs
@@ -21,8 +21,8 @@
 
 use crate::mock::sp_api_hidden_includes_construct_runtime::hidden_include::traits::OnInitialize;
 use bifrost_primitives::{
-	currency::{BNC, KSM},
-	CurrencyId, TokenSymbol,
+	currency::{ASG, BNC, KSM},
+	CommissionPalletId, CurrencyId,
 };
 use frame_support::{derive_impl, ord_parameter_types, parameter_types, traits::Nothing, PalletId};
 use frame_system::EnsureSignedBy;
@@ -66,7 +66,7 @@ impl frame_system::Config for Runtime {
 }
 
 parameter_types! {
-	pub const GetNativeCurrencyId: CurrencyId = CurrencyId::Native(TokenSymbol::ASG);
+	pub const GetNativeCurrencyId: CurrencyId = ASG;
 }
 
 pub type AdaptedBasicCurrency =
@@ -127,10 +127,8 @@ ord_parameter_types! {
 }
 
 parameter_types! {
-	pub const CommissionPalletId: PalletId = PalletId(*b"bf/comms");
 	pub const ClearingDuration: u32 = 100;
 	pub const NameLengthLimit: u32 = 20;
-	pub const FeeSharePalletId: PalletId = PalletId(*b"bf/feesh");
 	pub BifrostCommissionReceiver: AccountId = AccountId32::new([7u8; 32]);
 }
 
diff --git a/pallets/clouds-convert/src/mock.rs b/pallets/clouds-convert/src/mock.rs
index 72a89989b..b4b455135 100644
--- a/pallets/clouds-convert/src/mock.rs
+++ b/pallets/clouds-convert/src/mock.rs
@@ -24,9 +24,9 @@
 use bifrost_asset_registry::AssetIdMaps;
 use bifrost_primitives::{
 	currency::{BNC, CLOUD, KSM, VBNC, VKSM},
-	CurrencyId, CurrencyIdMapping, TokenSymbol,
+	BuyBackAccount, CloudsPalletId, CurrencyId, CurrencyIdMapping, IncentivePalletId,
 };
-use frame_support::{ord_parameter_types, parameter_types, traits::Nothing, PalletId};
+use frame_support::{ord_parameter_types, parameter_types, traits::Nothing};
 use frame_system::EnsureSignedBy;
 use sp_core::H256;
 use sp_runtime::{
@@ -95,7 +95,7 @@ impl frame_system::Config for Runtime {
 }
 
 parameter_types! {
-	pub const NativeCurrencyId: CurrencyId = CurrencyId::Native(TokenSymbol::BNC);
+	pub const NativeCurrencyId: CurrencyId = BNC;
 }
 
 pub type AdaptedBasicCurrency =
@@ -166,10 +166,6 @@ impl bifrost_asset_registry::Config for Runtime {
 	type WeightInfo = ();
 }
 
-parameter_types! {
-	pub const CloudsPalletId: PalletId = PalletId(*b"bf/cloud");
-}
-
 impl bifrost_clouds_convert::Config for Runtime {
 	type RuntimeEvent = RuntimeEvent;
 	type MultiCurrency = Currencies;
@@ -180,9 +176,7 @@ impl bifrost_clouds_convert::Config for Runtime {
 }
 
 parameter_types! {
-	pub const BbBNCTokenType: CurrencyId = CurrencyId::VToken(TokenSymbol::BNC);
-	pub IncentivePalletId: PalletId = PalletId(*b"bf/bbict");
-	pub const BuyBackAccount: PalletId = PalletId(*b"bf/bybck");
+	pub const BbBNCTokenType: CurrencyId = VBNC;
 	pub const Week: BlockNumber = 50400; // a week
 	pub const MaxBlock: BlockNumber = 10512000; // four years
 	pub const Multiplier: Balance = 10_u128.pow(12);
diff --git a/pallets/cross-in-out/src/mock.rs b/pallets/cross-in-out/src/mock.rs
index 527975bec..c76374cf3 100644
--- a/pallets/cross-in-out/src/mock.rs
+++ b/pallets/cross-in-out/src/mock.rs
@@ -20,8 +20,8 @@
 #![allow(non_upper_case_globals)]
 
 use bifrost_primitives::{
-	currency::{BNC, DOT, KSM, VDOT},
-	CurrencyId, TokenSymbol,
+	currency::{ASG, BNC, DOT, KSM, VDOT},
+	CurrencyId, SlpEntrancePalletId,
 };
 use frame_support::{derive_impl, ord_parameter_types, parameter_types, traits::Nothing, PalletId};
 use frame_system::EnsureSignedBy;
@@ -65,7 +65,7 @@ impl frame_system::Config for Runtime {
 }
 
 parameter_types! {
-	pub const GetNativeCurrencyId: CurrencyId = CurrencyId::Native(TokenSymbol::ASG);
+	pub const GetNativeCurrencyId: CurrencyId = ASG;
 }
 
 pub type AdaptedBasicCurrency =
@@ -126,7 +126,6 @@ ord_parameter_types! {
 }
 
 parameter_types! {
-	pub const SlpEntrancePalletId: PalletId = PalletId(*b"bf/vtkin");
 	pub const MaxLengthLimit: u32 = 100;
 }
 
diff --git a/pallets/deprecated/lightening-redeem/src/mock.rs b/pallets/deprecated/lightening-redeem/src/mock.rs
index bdf14c461..a56b0d582 100644
--- a/pallets/deprecated/lightening-redeem/src/mock.rs
+++ b/pallets/deprecated/lightening-redeem/src/mock.rs
@@ -129,10 +129,6 @@ impl pallet_collective::Config<CouncilCollective> for Runtime {
 	type WeightInfo = pallet_collective::weights::SubstrateWeight<Runtime>;
 }
 
-parameter_types! {
-	pub const LighteningRedeemPalletId: PalletId = PalletId(*b"lighten#");
-}
-
 impl bifrost_lightening_redeem::Config for Runtime {
 	type RuntimeEvent = RuntimeEvent;
 	type MultiCurrency = Tokens;
diff --git a/pallets/deprecated/liquidity-mining/src/mock.rs b/pallets/deprecated/liquidity-mining/src/mock.rs
index bae62a103..8c9ac3b3f 100644
--- a/pallets/deprecated/liquidity-mining/src/mock.rs
+++ b/pallets/deprecated/liquidity-mining/src/mock.rs
@@ -180,7 +180,6 @@ parameter_types! {
 	pub const MinimumDuration: BlockNumber = MINUTES;
 	pub const MaximumApproved: u32 = 4;
 	pub const MaximumOptionRewards: u32 = 7;
-	pub const LiquidityMiningPalletId: PalletId = PalletId(*b"mining##");
 }
 
 impl lm::Config for Test {
diff --git a/pallets/deprecated/salp-lite/src/mock.rs b/pallets/deprecated/salp-lite/src/mock.rs
index 962f5232d..04a8bdafb 100644
--- a/pallets/deprecated/salp-lite/src/mock.rs
+++ b/pallets/deprecated/salp-lite/src/mock.rs
@@ -161,7 +161,6 @@ impl bifrost_currencies::Config for Test {
 
 parameter_types! {
 	pub const MinContribution: Balance = 10;
-	pub const BifrostCrowdloanId: PalletId = PalletId(*b"bf/salp#");
 	pub const RemoveKeysLimit: u32 = 50;
 	pub const SlotLength: BlockNumber = 8u32 as BlockNumber;
 	pub const LeasePeriod: BlockNumber = 6 * WEEKS;
diff --git a/pallets/deprecated/system-maker/src/mock.rs b/pallets/deprecated/system-maker/src/mock.rs
index 756815e07..33f85fb4f 100644
--- a/pallets/deprecated/system-maker/src/mock.rs
+++ b/pallets/deprecated/system-maker/src/mock.rs
@@ -22,8 +22,11 @@
 #![allow(non_upper_case_globals)]
 
 use bifrost_asset_registry::AssetIdMaps;
-use bifrost_primitives::MoonbeamChainId;
-pub use bifrost_primitives::{currency::*, CurrencyId, SlpxOperator, TokenSymbol};
+pub use bifrost_primitives::{currency::*, CurrencyId, SlpxOperator};
+use bifrost_primitives::{
+	BifrostEntranceAccount, BifrostExitAccount, BifrostFeeAccount, IncentivePoolAccount,
+	MoonbeamChainId, SystemMakerPalletId, ZenlinkPalletId,
+};
 use bifrost_slp::{QueryId, QueryResponseManager};
 pub use cumulus_primitives_core::ParaId;
 use frame_support::{
@@ -32,10 +35,8 @@ use frame_support::{
 	parameter_types,
 	sp_runtime::{DispatchError, DispatchResult},
 	traits::{Everything, Nothing},
-	PalletId,
 };
 use frame_system::{EnsureRoot, EnsureSignedBy};
-use hex_literal::hex;
 use orml_traits::{location::RelativeReserveProvider, parameter_type_with_key, MultiCurrency};
 use sp_core::ConstU32;
 use sp_runtime::{
@@ -103,7 +104,7 @@ impl frame_system::Config for Runtime {
 }
 
 parameter_types! {
-	pub const GetNativeCurrencyId: CurrencyId = CurrencyId::Native(TokenSymbol::ASG);
+	pub const GetNativeCurrencyId: CurrencyId = ASG;
 }
 
 pub type AdaptedBasicCurrency =
@@ -157,14 +158,11 @@ impl orml_tokens::Config for Runtime {
 
 parameter_types! {
 	pub const TreasuryAccount: AccountId32 = TREASURY_ACCOUNT;
-	pub BifrostVsbondAccount: PalletId = PalletId(*b"bf/salpb");
-	pub const SystemMakerPalletId: PalletId = PalletId(*b"bf/sysmk");
 }
 
 ord_parameter_types! {
 	pub const One: AccountId = ALICE;
-	// pub const RelayChainTokenSymbolKSM: TokenSymbol = TokenSymbol::KSM;
-	pub const RelayCurrencyId: CurrencyId = CurrencyId::Token(TokenSymbol::KSM);
+	pub const RelayCurrencyId: CurrencyId = KSM;
 }
 
 impl bifrost_system_maker::Config for Runtime {
@@ -282,10 +280,6 @@ impl orml_xtokens::Config for Runtime {
 parameter_types! {
 	pub const MaximumUnlockIdOfUser: u32 = 10;
 	pub const MaximumUnlockIdOfTimeUnit: u32 = 50;
-	pub BifrostEntranceAccount: PalletId = PalletId(*b"bf/vtkin");
-	pub BifrostExitAccount: PalletId = PalletId(*b"bf/vtout");
-	pub BifrostFeeAccount: AccountId = hex!["e4da05f08e89bf6c43260d96f26fffcfc7deae5b465da08669a9d008e64c2c63"].into();
-	pub IncentivePoolAccount: PalletId = PalletId(*b"bf/inpoo");
 }
 
 impl bifrost_vtoken_minting::Config for Runtime {
@@ -315,7 +309,6 @@ impl bifrost_vtoken_minting::Config for Runtime {
 }
 
 parameter_types! {
-	pub const ZenlinkPalletId: PalletId = PalletId(*b"/zenlink");
 	pub const GetExchangeFee: (u32, u32) = (3, 1000);   // 0.3%
 	pub const SelfParaId: u32 = 2001;
 }
diff --git a/pallets/farming/src/mock.rs b/pallets/farming/src/mock.rs
index fe91ffb78..28a443f84 100644
--- a/pallets/farming/src/mock.rs
+++ b/pallets/farming/src/mock.rs
@@ -21,8 +21,13 @@
 #![cfg(test)]
 #![allow(non_upper_case_globals)]
 
-pub use bifrost_primitives::{currency::*, CurrencyId, TokenSymbol};
-use frame_support::{derive_impl, ord_parameter_types, parameter_types, traits::Nothing, PalletId};
+pub use bifrost_primitives::{currency::*, CurrencyId};
+use bifrost_primitives::{
+	currency::{ASG, VBNC},
+	BuyBackAccount, FarmingBoostPalletId, FarmingGaugeRewardIssuerPalletId, FarmingKeeperPalletId,
+	FarmingRewardIssuerPalletId, IncentivePalletId,
+};
+use frame_support::{derive_impl, ord_parameter_types, parameter_types, traits::Nothing};
 use frame_system::EnsureSignedBy;
 use sp_core::ConstU32;
 use sp_runtime::{
@@ -69,7 +74,7 @@ impl frame_system::Config for Runtime {
 }
 
 parameter_types! {
-	pub const GetNativeCurrencyId: CurrencyId = CurrencyId::Native(TokenSymbol::ASG);
+	pub const GetNativeCurrencyId: CurrencyId = ASG;
 }
 
 pub type AdaptedBasicCurrency =
@@ -123,12 +128,8 @@ impl orml_tokens::Config for Runtime {
 }
 
 parameter_types! {
-	pub const FarmingKeeperPalletId: PalletId = PalletId(*b"bf/fmkpr");
-	pub const FarmingRewardIssuerPalletId: PalletId = PalletId(*b"bf/fmrir");
-	pub const FarmingBoostPalletId: PalletId = PalletId(*b"bf/fmbst");
 	pub const TreasuryAccount: AccountId32 = TREASURY_ACCOUNT;
 	pub const WhitelistMaximumLimit: u32 = 10;
-	pub const FarmingGaugeRewardIssuerPalletId: PalletId = PalletId(*b"bf/fmgar");
 }
 
 ord_parameter_types! {
@@ -152,9 +153,7 @@ impl bifrost_farming::Config for Runtime {
 }
 
 parameter_types! {
-	pub const BbBNCTokenType: CurrencyId = CurrencyId::VToken(TokenSymbol::BNC);
-	pub IncentivePalletId: PalletId = PalletId(*b"bf/bbict");
-	pub const BuyBackAccount: PalletId = PalletId(*b"bf/bybck");
+	pub const BbBNCTokenType: CurrencyId = VBNC;
 	pub const Week: BlockNumber = 50400; // a week
 	pub const MaxBlock: BlockNumber = 10512000; // four years
 	pub const Multiplier: Balance = 10_u128.pow(12);
diff --git a/pallets/fee-share/src/mock.rs b/pallets/fee-share/src/mock.rs
index 16945802b..5b404135b 100644
--- a/pallets/fee-share/src/mock.rs
+++ b/pallets/fee-share/src/mock.rs
@@ -23,8 +23,11 @@
 pub use super::*;
 
 use bifrost_asset_registry::AssetIdMaps;
-pub use bifrost_primitives::{currency::*, CurrencyId, Moment, SlpxOperator, TokenSymbol};
-use bifrost_primitives::{MoonbeamChainId, PriceDetail};
+pub use bifrost_primitives::{currency::*, CurrencyId, Moment, SlpxOperator};
+use bifrost_primitives::{
+	BifrostEntranceAccount, BifrostExitAccount, BifrostFeeAccount, FeeSharePalletId,
+	IncentivePoolAccount, MoonbeamChainId, PriceDetail, ZenlinkPalletId,
+};
 use bifrost_slp::{QueryId, QueryResponseManager};
 pub use cumulus_primitives_core::ParaId;
 use frame_support::{
@@ -33,10 +36,8 @@ use frame_support::{
 	parameter_types,
 	sp_runtime::{DispatchError, DispatchResult, FixedPointNumber},
 	traits::{Everything, Nothing},
-	PalletId,
 };
 use frame_system::{EnsureRoot, EnsureSignedBy};
-use hex_literal::hex;
 use orml_traits::{
 	location::RelativeReserveProvider, parameter_type_with_key, DataFeeder, DataProvider,
 	DataProviderExtended, MultiCurrency,
@@ -113,7 +114,7 @@ impl frame_system::Config for Runtime {
 }
 
 parameter_types! {
-	pub const GetNativeCurrencyId: CurrencyId = CurrencyId::Native(TokenSymbol::ASG);
+	pub const GetNativeCurrencyId: CurrencyId = ASG;
 }
 
 pub type AdaptedBasicCurrency =
@@ -167,13 +168,11 @@ impl orml_tokens::Config for Runtime {
 
 parameter_types! {
 	pub const TreasuryAccount: AccountId32 = TREASURY_ACCOUNT;
-	pub BifrostVsbondAccount: PalletId = PalletId(*b"bf/salpb");
-	pub const FeeSharePalletId: PalletId = PalletId(*b"bf/feesh");
 }
 
 ord_parameter_types! {
 	pub const One: AccountId = ALICE;
-	pub const RelayCurrencyId: CurrencyId = CurrencyId::Token(TokenSymbol::KSM);
+	pub const RelayCurrencyId: CurrencyId = KSM;
 }
 
 impl bifrost_fee_share::Config for Runtime {
@@ -394,10 +393,6 @@ impl orml_xtokens::Config for Runtime {
 parameter_types! {
 	pub const MaximumUnlockIdOfUser: u32 = 10;
 	pub const MaximumUnlockIdOfTimeUnit: u32 = 50;
-	pub BifrostEntranceAccount: PalletId = PalletId(*b"bf/vtkin");
-	pub BifrostExitAccount: PalletId = PalletId(*b"bf/vtout");
-	pub BifrostFeeAccount: AccountId = hex!["e4da05f08e89bf6c43260d96f26fffcfc7deae5b465da08669a9d008e64c2c63"].into();
-	pub IncentivePoolAccount: PalletId = PalletId(*b"bf/inpoo");
 }
 
 impl bifrost_vtoken_minting::Config for Runtime {
@@ -427,7 +422,6 @@ impl bifrost_vtoken_minting::Config for Runtime {
 }
 
 parameter_types! {
-	pub const ZenlinkPalletId: PalletId = PalletId(*b"/zenlink");
 	pub const GetExchangeFee: (u32, u32) = (3, 1000);   // 0.3%
 	pub const SelfParaId: u32 = 2001;
 }
diff --git a/pallets/flexible-fee/src/mock.rs b/pallets/flexible-fee/src/mock.rs
index d8ef4559d..7e061dcb0 100644
--- a/pallets/flexible-fee/src/mock.rs
+++ b/pallets/flexible-fee/src/mock.rs
@@ -21,7 +21,7 @@
 use super::*;
 use crate::{self as flexible_fee, mock_price::MockOraclePriceProvider};
 use bifrost_currencies::BasicCurrencyAdapter;
-use bifrost_primitives::{Balance, CurrencyId, TokenSymbol};
+use bifrost_primitives::{Balance, CurrencyId, FlexibleFeePalletId, TokenSymbol, ZenlinkPalletId};
 use cumulus_primitives_core::ParaId as Pid;
 use frame_support::{
 	derive_impl, parameter_types,
@@ -149,7 +149,6 @@ impl orml_tokens::Config for Test {
 parameter_types! {
 	pub const TreasuryAccount: AccountId32 = TREASURY_ACCOUNT;
 	pub const MaxFeeCurrencyOrderListLen: u32 = 50;
-	pub const FlexibleFeePalletId: PalletId = PalletId(*b"bf/flexi");
 }
 
 impl crate::Config for Test {
@@ -196,7 +195,7 @@ impl Get<Pid> for ParaInfo {
 }
 
 parameter_types! {
-	pub const GetNativeCurrencyId: CurrencyId = CurrencyId::Native(TokenSymbol::BNC);
+	pub const GetNativeCurrencyId: CurrencyId = BNC;
 }
 
 impl bifrost_currencies::Config for Test {
@@ -207,7 +206,6 @@ impl bifrost_currencies::Config for Test {
 }
 
 parameter_types! {
-	pub const ZenlinkPalletId: PalletId = PalletId(*b"/zenlink");
 	pub const GetExchangeFee: (u32, u32) = (3, 1000);   // 0.3%
 	pub const SelfParaId: u32 = 2001;
 }
diff --git a/pallets/lend-market/src/mock.rs b/pallets/lend-market/src/mock.rs
index eecf3f21d..9e2ba4bb1 100644
--- a/pallets/lend-market/src/mock.rs
+++ b/pallets/lend-market/src/mock.rs
@@ -22,7 +22,6 @@ pub use bifrost_primitives::{currency::*, *};
 use frame_support::{
 	construct_runtime, derive_impl, parameter_types,
 	traits::{AsEnsureOriginWithArg, Nothing, SortedMembers},
-	PalletId,
 };
 use frame_system::{EnsureRoot, EnsureSigned, EnsureSignedBy};
 use orml_traits::{DataFeeder, DataProvider, DataProviderExtended};
@@ -88,11 +87,6 @@ parameter_types! {
 	pub const MaxLocks: u32 = 50;
 }
 
-parameter_types! {
-	pub const StableCurrencyId: CurrencyId = CurrencyId::Stable(TokenSymbol::KUSD);
-	pub const PolkadotCurrencyId: CurrencyId = CurrencyId::Token(TokenSymbol::DOT);
-}
-
 impl pallet_balances::Config for Test {
 	type AccountStore = frame_system::Pallet<Test>;
 	type Balance = Balance;
@@ -116,10 +110,6 @@ impl bifrost_asset_registry::Config for Test {
 	type WeightInfo = ();
 }
 
-parameter_types! {
-	pub const NativeCurrencyId: CurrencyId = CurrencyId::Native(TokenSymbol::BNC);
-}
-
 orml_traits::parameter_type_with_key! {
 	pub ExistentialDeposits: |currency_id: CurrencyId| -> Balance {
 		match currency_id {
@@ -316,7 +306,6 @@ impl pallet_prices::Config for Test {
 }
 
 parameter_types! {
-	pub const LendMarketPalletId: PalletId = PalletId(*b"bf/ldmkt");
 	pub const RewardAssetId: CurrencyId = BNC;
 	pub const LiquidationFreeAssetId: CurrencyId = DOT;
 }
diff --git a/pallets/leverage-staking/src/mock.rs b/pallets/leverage-staking/src/mock.rs
index f7ab5dd74..dc76e26b3 100644
--- a/pallets/leverage-staking/src/mock.rs
+++ b/pallets/leverage-staking/src/mock.rs
@@ -22,12 +22,14 @@ use bifrost_asset_registry::AssetIdMaps;
 pub use bifrost_primitives::{
 	currency::*, Balance, CurrencyId, CurrencyIdMapping, SlpOperator, SlpxOperator, TokenSymbol,
 };
-use bifrost_primitives::{Moment, MoonbeamChainId, OraclePriceProvider, Price, PriceDetail, Ratio};
+use bifrost_primitives::{
+	BifrostEntranceAccount, BifrostExitAccount, IncentivePoolAccount, LendMarketPalletId, Moment,
+	MoonbeamChainId, OraclePriceProvider, Price, PriceDetail, Ratio, StableAssetPalletId,
+};
 use bifrost_runtime_common::milli;
 use frame_support::{
 	derive_impl, ord_parameter_types, parameter_types,
 	traits::{ConstU128, ConstU32, Everything, Nothing},
-	PalletId,
 };
 use frame_system::{EnsureRoot, EnsureSignedBy};
 use lend_market::{InterestRateModel, JumpModel, Market, MarketState};
@@ -77,7 +79,7 @@ impl frame_system::Config for Test {
 }
 
 parameter_types! {
-	pub const NativeCurrencyId: CurrencyId = CurrencyId::Native(TokenSymbol::BNC);
+	pub const NativeCurrencyId: CurrencyId = BNC;
 }
 
 orml_traits::parameter_type_with_key! {
@@ -235,9 +237,6 @@ impl bifrost_stable_asset::traits::ValidateAssetId<CurrencyId> for EnsurePoolAss
 		true
 	}
 }
-parameter_types! {
-	pub const StableAssetPalletId: PalletId = PalletId(*b"nuts/sta");
-}
 
 impl bifrost_stable_asset::Config for Test {
 	type RuntimeEvent = RuntimeEvent;
@@ -279,9 +278,6 @@ impl leverage_staking::Config for Test {
 parameter_types! {
 	pub const MaximumUnlockIdOfUser: u32 = 1_000;
 	pub const MaximumUnlockIdOfTimeUnit: u32 = 1_000;
-	pub BifrostEntranceAccount: PalletId = PalletId(*b"bf/vtkin");
-	pub BifrostExitAccount: PalletId = PalletId(*b"bf/vtout");
-	pub IncentivePoolAccount: PalletId = PalletId(*b"bf/inpoo");
 }
 
 pub struct SlpxInterface;
@@ -292,7 +288,7 @@ impl SlpxOperator<Balance> for SlpxInterface {
 }
 
 ord_parameter_types! {
-	pub const RelayCurrencyId: CurrencyId = CurrencyId::Token(TokenSymbol::KSM);
+	pub const RelayCurrencyId: CurrencyId = KSM;
 }
 
 impl bifrost_vtoken_minting::Config for Test {
@@ -439,7 +435,6 @@ impl OraclePriceProvider for MockOraclePriceProvider {
 }
 
 parameter_types! {
-	pub const LendMarketPalletId: PalletId = PalletId(*b"bf/ldmkt");
 	pub const RewardAssetId: CurrencyId = BNC;
 	pub const LiquidationFreeAssetId: CurrencyId = DOT;
 }
diff --git a/pallets/parachain-staking/Cargo.toml b/pallets/parachain-staking/Cargo.toml
index c3e5089c3..c9a7d34b9 100644
--- a/pallets/parachain-staking/Cargo.toml
+++ b/pallets/parachain-staking/Cargo.toml
@@ -6,6 +6,7 @@ edition = "2021"
 version = "3.0.1"
 
 [dependencies]
+bifrost-primitives = { workspace = true }
 log = { workspace = true }
 serde = { workspace = true, features = ["derive"] }
 
diff --git a/pallets/parachain-staking/src/mock.rs b/pallets/parachain-staking/src/mock.rs
index 29303a027..45acfb13b 100644
--- a/pallets/parachain-staking/src/mock.rs
+++ b/pallets/parachain-staking/src/mock.rs
@@ -18,7 +18,6 @@
 use frame_support::{
 	construct_runtime, derive_impl, parameter_types,
 	traits::{LockIdentifier, LockableCurrency, OnFinalize, OnInitialize, ReservableCurrency},
-	PalletId,
 };
 use sp_core::ConstU32;
 use sp_runtime::{traits::IdentityLookup, Perbill, Percent};
@@ -29,6 +28,7 @@ use crate::{
 	DelegatorReserveToLockMigrations, DelegatorState, InflationInfo, Points, Range,
 	COLLATOR_LOCK_ID, DELEGATOR_LOCK_ID,
 };
+use bifrost_primitives::ParachainStakingPalletId;
 use sp_runtime::BuildStorage;
 
 pub type AccountId = u64;
@@ -96,7 +96,6 @@ parameter_types! {
 	pub const MinDelegation: u128 = 3;
 	pub AllowInflation: bool = true;
 	pub PaymentInRound: u128 = 10;
-	pub const ParachainStakingPalletId: PalletId = PalletId(*b"bf/stake");
 	pub ToMigrateInvulnables: Vec<AccountId> = vec![
 		0,1
 	];
diff --git a/pallets/salp/src/mock.rs b/pallets/salp/src/mock.rs
index e2138c859..f377cbab3 100644
--- a/pallets/salp/src/mock.rs
+++ b/pallets/salp/src/mock.rs
@@ -22,8 +22,13 @@
 
 use bifrost_asset_registry::AssetIdMaps;
 use bifrost_primitives::{
-	Amount, Balance, CurrencyId, CurrencyId::*, MessageId, MockXcmExecutor, ParaId, SlpOperator,
-	SlpxOperator, TokenSymbol, TokenSymbol::*, VKSM,
+	Amount, Balance, BifrostCrowdloanId, BifrostEntranceAccount, BifrostExitAccount,
+	BuybackPalletId,
+	CurrencyId::{self, *},
+	IncentivePoolAccount, MessageId, MockXcmExecutor, ParaId, SlpOperator, SlpxOperator,
+	StableAssetPalletId,
+	TokenSymbol::{self, *},
+	ZenlinkPalletId, ASG, KSM, KUSD, VKSM,
 };
 use bifrost_xcm_interface::traits::XcmHelper;
 use cumulus_primitives_core::ParaId as Pid;
@@ -32,7 +37,6 @@ use frame_support::{
 	sp_runtime::{DispatchError, DispatchResult, SaturatedConversion},
 	traits::{ConstU128, ConstU64, EnsureOrigin, Everything, Get, LockIdentifier, Nothing},
 	weights::Weight,
-	PalletId,
 };
 use frame_system::{EnsureRoot, EnsureSignedBy, RawOrigin};
 use orml_traits::{location::RelativeReserveProvider, parameter_type_with_key, MultiCurrency};
@@ -80,9 +84,9 @@ construct_runtime!(
 );
 
 parameter_types! {
-	pub const NativeCurrencyId: CurrencyId = CurrencyId::Native(TokenSymbol::ASG);
-	pub const RelayCurrencyId: CurrencyId = CurrencyId::Token(TokenSymbol::KSM);
-	pub const StableCurrencyId: CurrencyId = CurrencyId::Stable(TokenSymbol::KUSD);
+	pub const NativeCurrencyId: CurrencyId = ASG;
+	pub const RelayCurrencyId: CurrencyId = KSM;
+	pub const StableCurrencyId: CurrencyId = KUSD;
 }
 
 parameter_types! {
@@ -177,7 +181,6 @@ impl bifrost_currencies::Config for Test {
 }
 
 parameter_types! {
-	pub const ZenlinkPalletId: PalletId = PalletId(*b"/zenlink");
 	pub const GetExchangeFee: (u32, u32) = (3, 1000);   // 0.3%
 	pub const SelfParaId: u32 = 2001;
 }
@@ -268,7 +271,6 @@ pub const TREASURY_ACCOUNT: AccountId = AccountId::new([9u8; 32]);
 
 parameter_types! {
 	pub const MinContribution: Balance = 10;
-	pub const BifrostCrowdloanId: PalletId = PalletId(*b"bf/salp#");
 	pub const RemoveKeysLimit: u32 = 50;
 	pub const SlotLength: BlockNumber = 8u32 as BlockNumber;
 	pub const LeasePeriod: BlockNumber = 6 * WEEKS;
@@ -281,7 +283,6 @@ parameter_types! {
 		CATHI
 	],2);
 	pub const TreasuryAccount: AccountId = TREASURY_ACCOUNT;
-	pub const BuybackPalletId: PalletId = PalletId(*b"bf/salpc");
 	pub const BatchLimit: u32 = 50;
 }
 
@@ -330,9 +331,6 @@ impl bifrost_stable_asset::traits::ValidateAssetId<CurrencyId> for EnsurePoolAss
 		true
 	}
 }
-parameter_types! {
-	pub const StableAssetPalletId: PalletId = PalletId(*b"nuts/sta");
-}
 
 impl bifrost_stable_asset::Config for Test {
 	type RuntimeEvent = RuntimeEvent;
@@ -364,9 +362,6 @@ impl bifrost_stable_pool::Config for Test {
 parameter_types! {
 	pub const MaximumUnlockIdOfUser: u32 = 1_000;
 	pub const MaximumUnlockIdOfTimeUnit: u32 = 1_000;
-	pub BifrostEntranceAccount: PalletId = PalletId(*b"bf/vtkin");
-	pub BifrostExitAccount: PalletId = PalletId(*b"bf/vtout");
-	pub IncentivePoolAccount: PalletId = PalletId(*b"bf/inpoo");
 }
 
 pub struct SlpxInterface;
@@ -576,8 +571,8 @@ pub(crate) fn new_test_ext() -> sp_io::TestExternalities {
 
 	let currency = vec![
 		(Native(BNC), DOLLARS / 100, None),
-		(Stable(KUSD), DOLLARS / 10_000, None),
-		(Token(KSM), DOLLARS / 10_000, None),
+		(Stable(TokenSymbol::KUSD), DOLLARS / 10_000, None),
+		(Token(TokenSymbol::KSM), DOLLARS / 10_000, None),
 		(Token(ZLK), DOLLARS / 1000_000, None),
 		(Token(KAR), DOLLARS / 10_000, None),
 		(Token(RMRK), DOLLARS / 1000_000, None),
@@ -585,7 +580,7 @@ pub(crate) fn new_test_ext() -> sp_io::TestExternalities {
 		(Token(MOVR), DOLLARS / 1000_000, None),
 		(Token(DOT), DOLLARS / 1000_000, None),
 	];
-	let vcurrency = vec![Native(BNC), Token(KSM), Token(MOVR)];
+	let vcurrency = vec![Native(BNC), Token(TokenSymbol::KSM), Token(MOVR)];
 	let vsbond = vec![];
 	bifrost_asset_registry::GenesisConfig::<Test> {
 		currency,
diff --git a/pallets/salp/src/tests.rs b/pallets/salp/src/tests.rs
index 40b486f12..b30fb0d16 100644
--- a/pallets/salp/src/tests.rs
+++ b/pallets/salp/src/tests.rs
@@ -19,7 +19,9 @@
 // Ensure we're `no_std` when compiling for Wasm.
 
 use crate::{mock::*, Error, FundStatus, *};
-use bifrost_primitives::{CurrencyId, TokenSymbol, TryConvertFrom, KSM, VKSM, VSKSM};
+use bifrost_primitives::{
+	BuybackPalletId, CurrencyId, TokenSymbol, TryConvertFrom, KSM, VKSM, VSKSM,
+};
 use bifrost_xcm_interface::SalpHelper;
 use frame_support::{assert_noop, assert_ok};
 use frame_system::pallet_prelude::BlockNumberFor;
diff --git a/pallets/slp-v2/src/mock.rs b/pallets/slp-v2/src/mock.rs
index 8104a81e8..c4f8990eb 100644
--- a/pallets/slp-v2/src/mock.rs
+++ b/pallets/slp-v2/src/mock.rs
@@ -19,19 +19,18 @@
 use crate as slp_v2;
 use bifrost_asset_registry::AssetIdMaps;
 use bifrost_primitives::{
-	Amount, Balance, BlockNumber, CurrencyId, MockXcmRouter, MockXcmTransfer, SlpOperator,
-	SlpxOperator, BNC, DOT,
+	currency::DOT, Amount, Balance, BifrostEntranceAccount, BifrostExitAccount, BifrostFeeAccount,
+	BlockNumber, CommissionPalletId, CurrencyId, IncentivePoolAccount, MockXcmRouter,
+	MockXcmTransfer, SlpOperator, SlpxOperator, BNC,
 };
 use frame_support::{
 	derive_impl,
 	pallet_prelude::{ConstU32, Get},
 	parameter_types,
 	traits::{Everything, Nothing},
-	PalletId,
 };
 use frame_system as system;
 use frame_system::EnsureRoot;
-use hex_literal::hex;
 use pallet_xcm::EnsureResponse;
 use polkadot_parachain_primitives::primitives::Id as ParaId;
 use sp_core::{crypto::AccountId32, ConstU64};
@@ -142,7 +141,6 @@ parameter_types! {
 	pub UnitWeightCost: Weight = Weight::from_parts(200_000_000, 0);
 	pub const MaxInstructions: u32 = 100;
 	pub UniversalLocation: InteriorLocation = Parachain(2030).into();
-	pub CommissionPalletId: PalletId = PalletId(*b"bf/comms");
 }
 
 pub struct XcmConfig;
@@ -215,11 +213,7 @@ impl Get<ParaId> for ParachainId {
 parameter_types! {
 	pub const MaximumUnlockIdOfUser: u32 = 10;
 	pub const MaximumUnlockIdOfTimeUnit: u32 = 50;
-	pub BifrostEntranceAccount: PalletId = PalletId(*b"bf/vtkin");
-	pub BifrostExitAccount: PalletId = PalletId(*b"bf/vtout");
-	pub BifrostFeeAccount: AccountId = hex!["e4da05f08e89bf6c43260d96f26fffcfc7deae5b465da08669a9d008e64c2c63"].into();
 	pub const RelayCurrencyId: CurrencyId = DOT;
-	pub IncentivePoolAccount: PalletId = PalletId(*b"bf/inpoo");
 }
 
 pub struct SlpxInterface;
diff --git a/pallets/slp-v2/src/tests.rs b/pallets/slp-v2/src/tests.rs
index d2649ecf2..2140d2364 100644
--- a/pallets/slp-v2/src/tests.rs
+++ b/pallets/slp-v2/src/tests.rs
@@ -31,7 +31,7 @@ use crate::{
 	LedgerByStakingProtocolAndDelegator, NextDelegatorIndexByStakingProtocol,
 	ValidatorsByStakingProtocolAndDelegator,
 };
-use bifrost_primitives::{TimeUnit, VtokenMintingOperator, VASTR};
+use bifrost_primitives::{CommissionPalletId, TimeUnit, VtokenMintingOperator, VASTR};
 use cumulus_primitives_core::Weight;
 use frame_support::{assert_noop, assert_ok, traits::fungibles::Mutate};
 use orml_traits::MultiCurrency;
diff --git a/pallets/slp/src/mocks/mock.rs b/pallets/slp/src/mocks/mock.rs
index a5f893b27..4495ad6be 100644
--- a/pallets/slp/src/mocks/mock.rs
+++ b/pallets/slp/src/mocks/mock.rs
@@ -25,7 +25,9 @@ use crate::{Config, DispatchResult, QueryResponseManager, XcmDestWeightAndFeeHan
 use bifrost_asset_registry::AssetIdMaps;
 use bifrost_primitives::{
 	currency::{BNC, KSM},
-	Amount, Balance, CurrencyId, MoonbeamChainId, SlpxOperator, TokenSymbol, XcmOperationType,
+	Amount, Balance, BifrostEntranceAccount, BifrostExitAccount, BifrostFeeAccount, CurrencyId,
+	IncentivePoolAccount, MoonbeamChainId, ParachainStakingPalletId, SlpxOperator, TokenSymbol,
+	XcmOperationType,
 };
 pub use cumulus_primitives_core::ParaId;
 use frame_support::{
@@ -36,7 +38,6 @@ use frame_support::{
 	PalletId,
 };
 use frame_system::{EnsureRoot, EnsureSignedBy};
-use hex_literal::hex;
 use orml_traits::{location::RelativeReserveProvider, parameter_type_with_key};
 use parity_scale_codec::{Decode, Encode};
 use sp_core::{bounded::BoundedVec, hashing::blake2_256, ConstU32};
@@ -185,10 +186,6 @@ impl orml_xtokens::Config for Runtime {
 parameter_types! {
 	pub const MaximumUnlockIdOfUser: u32 = 10;
 	pub const MaximumUnlockIdOfTimeUnit: u32 = 50;
-	pub BifrostEntranceAccount: PalletId = PalletId(*b"bf/vtkin");
-	pub BifrostExitAccount: PalletId = PalletId(*b"bf/vtout");
-	pub BifrostFeeAccount: AccountId = hex!["e4da05f08e89bf6c43260d96f26fffcfc7deae5b465da08669a9d008e64c2c63"].into();
-	pub IncentivePoolAccount: PalletId = PalletId(*b"bf/inpoo");
 }
 
 impl bifrost_vtoken_minting::Config for Runtime {
@@ -237,7 +234,6 @@ parameter_types! {
 	pub const MinDelegation: u128 = 3;
 	pub AllowInflation: bool = true;
 	pub PaymentInRound: u128 = 10;
-	pub const ParachainStakingPalletId: PalletId = PalletId(*b"bf/stake");
 	pub ToMigrateInvulnables: Vec<AccountId> = vec![AccountId32::new([1u8; 32])];
 	pub InitSeedStk: u128 = 10;
 }
diff --git a/pallets/slp/src/mocks/mock_kusama.rs b/pallets/slp/src/mocks/mock_kusama.rs
index 6aeafbf7c..adb01aa24 100644
--- a/pallets/slp/src/mocks/mock_kusama.rs
+++ b/pallets/slp/src/mocks/mock_kusama.rs
@@ -25,8 +25,10 @@ use crate::{Config, DispatchResult, QueryResponseManager};
 use bifrost_asset_registry::AssetIdMaps;
 use bifrost_primitives::{
 	currency::{BNC, KSM, MANTA},
-	Amount, Balance, CurrencyId, MockXcmExecutor, MockXcmRouter, MoonbeamChainId, SlpxOperator,
-	TokenSymbol, XcmDestWeightAndFeeHandler, XcmOperationType,
+	Amount, Balance, BifrostEntranceAccount, BifrostExitAccount, BifrostFeeAccount, CurrencyId,
+	IncentivePoolAccount, MockXcmExecutor, MockXcmRouter, MoonbeamChainId,
+	ParachainStakingPalletId, SlpxOperator, StableAssetPalletId, TokenSymbol,
+	XcmDestWeightAndFeeHandler, XcmOperationType,
 };
 pub use cumulus_primitives_core::ParaId;
 use frame_support::{
@@ -93,9 +95,6 @@ impl bifrost_stable_asset::traits::ValidateAssetId<CurrencyId> for EnsurePoolAss
 		true
 	}
 }
-parameter_types! {
-	pub const StableAssetPalletId: PalletId = PalletId(*b"nuts/sta");
-}
 
 impl bifrost_stable_asset::Config for Runtime {
 	type RuntimeEvent = RuntimeEvent;
@@ -236,10 +235,6 @@ impl orml_xtokens::Config for Runtime {
 parameter_types! {
 	pub const MaximumUnlockIdOfUser: u32 = 10;
 	pub const MaximumUnlockIdOfTimeUnit: u32 = 50;
-	pub BifrostEntranceAccount: PalletId = PalletId(*b"bf/vtkin");
-	pub BifrostExitAccount: PalletId = PalletId(*b"bf/vtout");
-	pub BifrostFeeAccount: AccountId = hex!["e4da05f08e89bf6c43260d96f26fffcfc7deae5b465da08669a9d008e64c2c63"].into();
-	pub IncentivePoolAccount: PalletId = PalletId(*b"bf/inpoo");
 }
 
 pub struct SlpxInterface;
@@ -295,7 +290,6 @@ parameter_types! {
 	pub const MinDelegation: u128 = 3;
 	pub AllowInflation: bool = true;
 	pub PaymentInRound: u128 = 10;
-	pub const ParachainStakingPalletId: PalletId = PalletId(*b"bf/stake");
 	pub ToMigrateInvulnables: Vec<AccountId> = vec![AccountId32::new([1u8; 32])];
 	pub InitSeedStk: u128 = 10;
 }
diff --git a/pallets/slpx/src/mock.rs b/pallets/slpx/src/mock.rs
index ea6eaf1e8..13e32baf7 100644
--- a/pallets/slpx/src/mock.rs
+++ b/pallets/slpx/src/mock.rs
@@ -19,9 +19,12 @@
 
 use crate as slpx;
 use bifrost_asset_registry::AssetIdMaps;
-use bifrost_primitives::MoonbeamChainId;
+use bifrost_primitives::{
+	BifrostEntranceAccount, BifrostExitAccount, BifrostFeeAccount, IncentivePoolAccount,
+	MoonbeamChainId, StableAssetPalletId, ZenlinkPalletId,
+};
 pub use bifrost_primitives::{
-	CurrencyId, CurrencyIdMapping, MockXcmExecutor, SlpxOperator, TokenSymbol, BNC, KSM,
+	CurrencyId, CurrencyIdMapping, MockXcmExecutor, SlpxOperator, BNC, KSM,
 };
 use bifrost_slp::{QueryId, QueryResponseManager};
 use cumulus_primitives_core::ParaId;
@@ -30,10 +33,8 @@ use frame_support::{
 	pallet_prelude::*,
 	parameter_types,
 	traits::{Everything, Nothing},
-	PalletId,
 };
 use frame_system::{EnsureRoot, EnsureSignedBy};
-use hex_literal::hex;
 use orml_traits::{
 	location::RelativeReserveProvider, parameter_type_with_key, xcm_transfer::Transferred,
 	MultiCurrency, XcmTransfer,
@@ -119,7 +120,7 @@ impl pallet_balances::Config for Test {
 }
 
 parameter_types! {
-	pub const GetNativeCurrencyId: CurrencyId = CurrencyId::Native(TokenSymbol::BNC);
+	pub const GetNativeCurrencyId: CurrencyId = BNC;
 }
 
 pub type AdaptedBasicCurrency =
@@ -161,11 +162,7 @@ impl orml_tokens::Config for Test {
 parameter_types! {
 	pub const MaximumUnlockIdOfUser: u32 = 10;
 	pub const MaximumUnlockIdOfTimeUnit: u32 = 50;
-	pub BifrostEntranceAccount: PalletId = PalletId(*b"bf/vtkin");
-	pub BifrostExitAccount: PalletId = PalletId(*b"bf/vtout");
-	pub BifrostFeeAccount: AccountId = hex!["e4da05f08e89bf6c43260d96f26fffcfc7deae5b465da08669a9d008e64c2c63"].into();
 	pub const RelayCurrencyId: CurrencyId = KSM;
-	pub IncentivePoolAccount: PalletId = PalletId(*b"bf/inpoo");
 }
 
 ord_parameter_types! {
@@ -266,7 +263,6 @@ where
 type MultiAssets = ZenlinkMultiAssets<ZenlinkProtocol, Balances, LocalAssetAdaptor<Currencies>>;
 
 parameter_types! {
-	pub const ZenlinkPalletId: PalletId = PalletId(*b"/zenlink");
 	pub const GetExchangeFee: (u32, u32) = (3, 1000);   // 0.3%
 	pub const SelfParaId: u32 = 2001;
 }
@@ -476,9 +472,6 @@ impl bifrost_stable_asset::traits::ValidateAssetId<CurrencyId> for EnsurePoolAss
 		true
 	}
 }
-parameter_types! {
-	pub const StableAssetPalletId: PalletId = PalletId(*b"nuts/sta");
-}
 
 impl bifrost_stable_asset::Config for Test {
 	type RuntimeEvent = RuntimeEvent;
@@ -509,7 +502,7 @@ impl bifrost_stable_pool::Config for Test {
 
 // Pallet slpx configuration
 parameter_types! {
-	pub const NativeCurrencyId: CurrencyId = CurrencyId::Native(TokenSymbol::BNC);
+	pub const NativeCurrencyId: CurrencyId = BNC;
 }
 
 pub struct XTokensMock;
diff --git a/pallets/stable-asset/src/mock.rs b/pallets/stable-asset/src/mock.rs
index ef1811eff..da1c64a1b 100644
--- a/pallets/stable-asset/src/mock.rs
+++ b/pallets/stable-asset/src/mock.rs
@@ -17,12 +17,12 @@
 // along with this program. If not, see <https://www.gnu.org/licenses/>.
 
 use crate as stable_asset;
+use bifrost_primitives::StableAssetPalletId;
 use frame_support::{
 	derive_impl,
 	dispatch::DispatchResult,
 	parameter_types,
 	traits::{ConstU128, ConstU32, Currency, EnsureOrigin, Nothing, OnUnbalanced},
-	PalletId,
 };
 use frame_system::RawOrigin;
 use orml_traits::MultiCurrency;
@@ -266,10 +266,6 @@ impl crate::traits::ValidateAssetId<i64> for EnsurePoolAssetId {
 	}
 }
 
-parameter_types! {
-	pub const StableAssetPalletId: PalletId = PalletId(*b"nuts/sta");
-}
-
 impl stable_asset::Config for Test {
 	type RuntimeEvent = RuntimeEvent;
 	type AssetId = i64;
diff --git a/pallets/stable-pool/src/mock.rs b/pallets/stable-pool/src/mock.rs
index d63321de7..5dd4d6798 100644
--- a/pallets/stable-pool/src/mock.rs
+++ b/pallets/stable-pool/src/mock.rs
@@ -17,17 +17,19 @@
 // along with this program. If not, see <https://www.gnu.org/licenses/>.
 use crate as bifrost_stable_pool;
 use bifrost_asset_registry::AssetIdMaps;
-use bifrost_primitives::MoonbeamChainId;
 pub use bifrost_primitives::{
 	currency::{MOVR, VMOVR},
 	Balance, CurrencyId, CurrencyIdMapping, SlpOperator, SlpxOperator, TokenSymbol, ASTR, BNC, DOT,
 	GLMR, VBNC, VDOT,
 };
+use bifrost_primitives::{
+	BifrostEntranceAccount, BifrostExitAccount, IncentivePoolAccount, MoonbeamChainId,
+	StableAssetPalletId, KSM, KUSD,
+};
 use bifrost_runtime_common::milli;
 use frame_support::{
 	derive_impl, ord_parameter_types, parameter_types,
 	traits::{ConstU128, ConstU32, Everything, Nothing},
-	PalletId,
 };
 use frame_system::{EnsureRoot, EnsureSignedBy};
 use orml_traits::{location::RelativeReserveProvider, parameter_type_with_key};
@@ -63,7 +65,7 @@ impl frame_system::Config for Test {
 }
 
 parameter_types! {
-	pub const NativeCurrencyId: CurrencyId = CurrencyId::Native(TokenSymbol::BNC);
+	pub const NativeCurrencyId: CurrencyId = BNC;
 }
 
 orml_traits::parameter_type_with_key! {
@@ -187,11 +189,8 @@ impl orml_xtokens::Config for Test {
 
 parameter_types! {
 	pub const ExistentialDeposit: Balance = 1;
-	// pub const NativeCurrencyId: CurrencyId = CurrencyId::Native(TokenSymbol::BNC);
-	// pub const RelayCurrencyId: CurrencyId = CurrencyId::Token(TokenSymbol::KSM);
-	pub const StableCurrencyId: CurrencyId = CurrencyId::Stable(TokenSymbol::KUSD);
-	// pub SelfParaId: u32 = ParachainInfo::parachain_id().into();
-	pub const PolkadotCurrencyId: CurrencyId = CurrencyId::Token(TokenSymbol::DOT);
+	pub const StableCurrencyId: CurrencyId = KUSD;
+	pub const PolkadotCurrencyId: CurrencyId = DOT;
 }
 
 impl pallet_balances::Config for Test {
@@ -226,9 +225,6 @@ impl bifrost_stable_asset::traits::ValidateAssetId<CurrencyId> for EnsurePoolAss
 		true
 	}
 }
-parameter_types! {
-	pub const StableAssetPalletId: PalletId = PalletId(*b"nuts/sta");
-}
 
 impl bifrost_stable_asset::Config for Test {
 	type RuntimeEvent = RuntimeEvent;
@@ -260,9 +256,6 @@ impl bifrost_stable_pool::Config for Test {
 parameter_types! {
 	pub const MaximumUnlockIdOfUser: u32 = 1_000;
 	pub const MaximumUnlockIdOfTimeUnit: u32 = 1_000;
-	pub BifrostEntranceAccount: PalletId = PalletId(*b"bf/vtkin");
-	pub BifrostExitAccount: PalletId = PalletId(*b"bf/vtout");
-	pub IncentivePoolAccount: PalletId = PalletId(*b"bf/inpoo");
 }
 
 pub struct SlpxInterface;
@@ -273,7 +266,7 @@ impl SlpxOperator<Balance> for SlpxInterface {
 }
 
 ord_parameter_types! {
-	pub const RelayCurrencyId: CurrencyId = CurrencyId::Token(TokenSymbol::KSM);
+	pub const RelayCurrencyId: CurrencyId = KSM;
 }
 
 impl bifrost_vtoken_minting::Config for Test {
diff --git a/pallets/stable-pool/src/tests.rs b/pallets/stable-pool/src/tests.rs
index 807f32fde..a6277a30a 100644
--- a/pallets/stable-pool/src/tests.rs
+++ b/pallets/stable-pool/src/tests.rs
@@ -16,7 +16,7 @@
 // You should have received a copy of the GNU General Public License
 // along with this program. If not, see <https://www.gnu.org/licenses/>.
 use crate::{mock::*, AssetIdOf, AtLeast64BitUnsignedOf, Error};
-use bifrost_primitives::VtokenMintingOperator;
+use bifrost_primitives::{StableAssetPalletId, VtokenMintingOperator};
 use bifrost_stable_asset::{PoolCount, Pools, StableAssetPoolInfo};
 use frame_support::{assert_noop, assert_ok, BoundedVec};
 use orml_traits::MultiCurrency;
diff --git a/pallets/system-staking/src/mock.rs b/pallets/system-staking/src/mock.rs
index a450972d1..a50e2f26a 100644
--- a/pallets/system-staking/src/mock.rs
+++ b/pallets/system-staking/src/mock.rs
@@ -19,8 +19,12 @@
 #![allow(non_upper_case_globals)]
 
 use bifrost_asset_registry::AssetIdMaps;
-use bifrost_primitives::MoonbeamChainId;
-pub use bifrost_primitives::{currency::*, CurrencyId, SlpxOperator, TokenSymbol};
+pub use bifrost_primitives::{currency::*, CurrencyId, SlpxOperator};
+use bifrost_primitives::{
+	BifrostEntranceAccount, BifrostExitAccount, BifrostFeeAccount, FarmingBoostPalletId,
+	FarmingGaugeRewardIssuerPalletId, FarmingKeeperPalletId, FarmingRewardIssuerPalletId,
+	IncentivePoolAccount, MoonbeamChainId, SystemStakingPalletId,
+};
 use bifrost_slp::{QueryId, QueryResponseManager};
 pub use cumulus_primitives_core::ParaId;
 use cumulus_primitives_core::*;
@@ -29,10 +33,8 @@ use frame_support::{
 	pallet_prelude::Get,
 	parameter_types,
 	traits::{Everything, Nothing, OnFinalize, OnInitialize},
-	PalletId,
 };
 use frame_system::{EnsureRoot, EnsureSignedBy};
-use hex_literal::hex;
 use orml_traits::{location::RelativeReserveProvider, parameter_type_with_key};
 use sp_core::ConstU32;
 use sp_runtime::{
@@ -87,7 +89,7 @@ impl frame_system::Config for Runtime {
 }
 
 parameter_types! {
-	pub const GetNativeCurrencyId: CurrencyId = CurrencyId::Native(TokenSymbol::ASG);
+	pub const GetNativeCurrencyId: CurrencyId = ASG;
 }
 
 pub type AdaptedBasicCurrency =
@@ -173,11 +175,7 @@ impl orml_xtokens::Config for Runtime {
 parameter_types! {
 	pub const MaximumUnlockIdOfUser: u32 = 10;
 	pub const MaximumUnlockIdOfTimeUnit: u32 = 50;
-	pub BifrostEntranceAccount: PalletId = PalletId(*b"bf/vtkin");
-	pub BifrostExitAccount: PalletId = PalletId(*b"bf/vtout");
-	pub BifrostFeeAccount: AccountId = hex!["e4da05f08e89bf6c43260d96f26fffcfc7deae5b465da08669a9d008e64c2c63"].into();
 	pub const RelayCurrencyId: CurrencyId = KSM;
-	pub IncentivePoolAccount: PalletId = PalletId(*b"bf/inpoo");
 }
 
 impl bifrost_vtoken_minting::Config for Runtime {
@@ -277,11 +275,7 @@ impl bifrost_slp::Config for Runtime {
 }
 
 parameter_types! {
-	pub const FarmingKeeperPalletId: PalletId = PalletId(*b"bf/fmkpr");
-	pub const FarmingRewardIssuerPalletId: PalletId = PalletId(*b"bf/fmrir");
-	pub const FarmingBoostPalletId: PalletId = PalletId(*b"bf/fmbst");
 	pub const WhitelistMaximumLimit: u32 = 10;
-	pub const FarmingGaugeRewardIssuerPalletId: PalletId = PalletId(*b"bf/fmgar");
 }
 
 ord_parameter_types! {
@@ -309,7 +303,6 @@ parameter_types! {
 	pub const BlocksPerRound: u32 = 5;
 	pub const MaxTokenLen: u32 = 50;
 	pub const MaxFarmingPoolIdLen: u32 = 100;
-	pub const SystemStakingPalletId: PalletId = PalletId(*b"bf/sysst");
 }
 
 impl system_staking::Config for Runtime {
diff --git a/pallets/token-issuer/src/mock.rs b/pallets/token-issuer/src/mock.rs
index b110b7b22..4764c9e60 100644
--- a/pallets/token-issuer/src/mock.rs
+++ b/pallets/token-issuer/src/mock.rs
@@ -22,7 +22,7 @@
 use crate::Weight;
 use bifrost_primitives::{
 	currency::{BNC, DOT, KSM, VDOT},
-	CurrencyId, TokenSymbol,
+	CurrencyId, ASG,
 };
 use frame_support::{derive_impl, parameter_types, traits::Nothing, PalletId};
 use frame_system::EnsureRoot;
@@ -70,7 +70,7 @@ impl frame_system::Config for Runtime {
 }
 
 parameter_types! {
-	pub const GetNativeCurrencyId: CurrencyId = CurrencyId::Native(TokenSymbol::ASG);
+	pub const GetNativeCurrencyId: CurrencyId = ASG;
 }
 
 pub type AdaptedBasicCurrency =
diff --git a/pallets/vbnc-convert/src/mock.rs b/pallets/vbnc-convert/src/mock.rs
index ce3b49e9f..88d8cc86e 100644
--- a/pallets/vbnc-convert/src/mock.rs
+++ b/pallets/vbnc-convert/src/mock.rs
@@ -24,9 +24,9 @@
 use bifrost_asset_registry::AssetIdMaps;
 use bifrost_primitives::{
 	currency::{BNC, KSM, VBNC, VBNC_P, VKSM},
-	CurrencyId, CurrencyIdMapping, TokenSymbol,
+	CurrencyId, CurrencyIdMapping, VBNCConvertPalletId,
 };
-use frame_support::{ord_parameter_types, parameter_types, traits::Nothing, PalletId};
+use frame_support::{ord_parameter_types, parameter_types, traits::Nothing};
 use frame_system::EnsureSignedBy;
 use sp_core::H256;
 use sp_runtime::{
@@ -94,7 +94,7 @@ impl frame_system::Config for Runtime {
 }
 
 parameter_types! {
-	pub const NativeCurrencyId: CurrencyId = CurrencyId::Native(TokenSymbol::BNC);
+	pub const NativeCurrencyId: CurrencyId = BNC;
 }
 
 pub type AdaptedBasicCurrency =
@@ -165,10 +165,6 @@ impl bifrost_asset_registry::Config for Runtime {
 	type WeightInfo = ();
 }
 
-parameter_types! {
-	pub const VBNCConvertPalletId: PalletId = PalletId(*b"bf/vbncc");
-}
-
 impl bifrost_vbnc_convert::Config for Runtime {
 	type RuntimeEvent = RuntimeEvent;
 	type MultiCurrency = Currencies;
diff --git a/pallets/vsbond-auction/src/mock.rs b/pallets/vsbond-auction/src/mock.rs
index 2e4c9088e..a7ade8803 100644
--- a/pallets/vsbond-auction/src/mock.rs
+++ b/pallets/vsbond-auction/src/mock.rs
@@ -16,7 +16,7 @@
 // You should have received a copy of the GNU General Public License
 // along with this program. If not, see <https://www.gnu.org/licenses/>.
 
-use bifrost_primitives::{Amount, Balance, CurrencyId, TokenSymbol};
+use bifrost_primitives::{Amount, Balance, CurrencyId, TokenSymbol, VsbondAuctionPalletId, KSM};
 #[cfg(feature = "runtime-benchmarks")]
 use frame_benchmarking::{account, whitelisted_caller};
 use frame_support::{
@@ -111,10 +111,9 @@ impl orml_tokens::Config for Test {
 }
 
 parameter_types! {
-	pub const InvoicingCurrency: CurrencyId = CurrencyId::Token(TokenSymbol::KSM);
+	pub const InvoicingCurrency: CurrencyId = KSM;
 	pub const MaximumOrderInTrade: u32 = 5;
 	pub const MinimumSupply: Balance = 0;
-	pub const VsbondAuctionPalletId: PalletId = PalletId(*b"bf/vsbnd");
 	pub BifrostTreasuryAccount: AccountId = PalletId(*b"bf/trsry").into_account_truncating();
 }
 
diff --git a/pallets/vstoken-conversion/src/mock.rs b/pallets/vstoken-conversion/src/mock.rs
index 0e9fa07d8..46e56b292 100644
--- a/pallets/vstoken-conversion/src/mock.rs
+++ b/pallets/vstoken-conversion/src/mock.rs
@@ -21,8 +21,12 @@
 #![cfg(test)]
 #![allow(non_upper_case_globals)]
 
-pub use bifrost_primitives::{currency::*, CurrencyId, TokenSymbol};
-use frame_support::{derive_impl, ord_parameter_types, parameter_types, traits::Nothing, PalletId};
+pub use bifrost_primitives::{currency::*, CurrencyId};
+use bifrost_primitives::{
+	currency::{ASG, KSM},
+	BifrostVsbondAccount,
+};
+use frame_support::{derive_impl, ord_parameter_types, parameter_types, traits::Nothing};
 use frame_system::EnsureSignedBy;
 use sp_core::ConstU32;
 use sp_runtime::{traits::IdentityLookup, AccountId32, BuildStorage};
@@ -66,7 +70,7 @@ impl frame_system::Config for Runtime {
 }
 
 parameter_types! {
-	pub const GetNativeCurrencyId: CurrencyId = CurrencyId::Native(TokenSymbol::ASG);
+	pub const GetNativeCurrencyId: CurrencyId = ASG;
 }
 
 pub type AdaptedBasicCurrency =
@@ -120,13 +124,11 @@ impl orml_tokens::Config for Runtime {
 
 parameter_types! {
 	pub const TreasuryAccount: AccountId32 = TREASURY_ACCOUNT;
-	pub BifrostVsbondAccount: PalletId = PalletId(*b"bf/salpb");
 }
 
 ord_parameter_types! {
 	pub const One: AccountId = ALICE;
-	// pub const RelayCurrencyId: CurrencyId = CurrencyId::Token2(DOT_TOKEN_ID);
-	pub const RelayCurrencyId: CurrencyId = CurrencyId::Token(TokenSymbol::KSM);
+	pub const RelayCurrencyId: CurrencyId = KSM;
 }
 
 impl bifrost_vstoken_conversion::Config for Runtime {
diff --git a/pallets/vstoken-conversion/src/tests.rs b/pallets/vstoken-conversion/src/tests.rs
index d997229fd..c1eb850ad 100644
--- a/pallets/vstoken-conversion/src/tests.rs
+++ b/pallets/vstoken-conversion/src/tests.rs
@@ -20,6 +20,7 @@
 
 #![cfg(test)]
 
+use bifrost_primitives::currency::KSM;
 use frame_support::{assert_noop, assert_ok};
 pub use primitives::{VstokenConversionExchangeFee, VstokenConversionExchangeRate};
 use sp_arithmetic::per_things::Percent;
diff --git a/pallets/vtoken-minting/src/mock.rs b/pallets/vtoken-minting/src/mock.rs
index f04aa0e80..3a7bb38ad 100644
--- a/pallets/vtoken-minting/src/mock.rs
+++ b/pallets/vtoken-minting/src/mock.rs
@@ -25,7 +25,8 @@ use bb_bnc::{BbBNCInterface, Point};
 use bifrost_asset_registry::AssetIdMaps;
 use bifrost_primitives::{
 	currency::{BNC, DOT, FIL, KSM, MOVR, VBNC, VFIL, VKSM, VMOVR},
-	CurrencyId, CurrencyIdMapping, MoonbeamChainId, SlpxOperator, TokenSymbol,
+	BifrostEntranceAccount, BifrostExitAccount, BifrostFeeAccount, CurrencyId, CurrencyIdMapping,
+	IncentivePoolAccount, MoonbeamChainId, SlpxOperator, KUSD,
 };
 use bifrost_runtime_common::{micro, milli};
 use bifrost_slp::{QueryId, QueryResponseManager};
@@ -35,10 +36,8 @@ use frame_support::{
 	pallet_prelude::Get,
 	parameter_types,
 	traits::{Everything, Nothing},
-	PalletId,
 };
 use frame_system::{EnsureRoot, EnsureSignedBy};
-use hex_literal::hex;
 use orml_traits::{location::RelativeReserveProvider, parameter_type_with_key};
 use sp_runtime::{
 	traits::{ConstU32, IdentityLookup},
@@ -89,7 +88,7 @@ impl frame_system::Config for Runtime {
 }
 
 parameter_types! {
-	pub const NativeCurrencyId: CurrencyId = CurrencyId::Native(TokenSymbol::BNC);
+	pub const NativeCurrencyId: CurrencyId = BNC;
 }
 
 pub type AdaptedBasicCurrency =
@@ -104,11 +103,8 @@ impl bifrost_currencies::Config for Runtime {
 
 parameter_types! {
 	pub const ExistentialDeposit: Balance = 1;
-	// pub const NativeCurrencyId: CurrencyId = CurrencyId::Native(TokenSymbol::BNC);
-	// pub const RelayCurrencyId: CurrencyId = CurrencyId::Token(TokenSymbol::KSM);
-	pub const StableCurrencyId: CurrencyId = CurrencyId::Stable(TokenSymbol::KUSD);
-	// pub SelfParaId: u32 = ParachainInfo::parachain_id().into();
-	pub const PolkadotCurrencyId: CurrencyId = CurrencyId::Token(TokenSymbol::DOT);
+	pub const StableCurrencyId: CurrencyId = KUSD;
+	pub const PolkadotCurrencyId: CurrencyId = DOT;
 }
 
 impl pallet_balances::Config for Runtime {
@@ -197,15 +193,11 @@ parameter_types! {
 	pub const MaximumUnlockIdOfUser: u32 = 1_000;
 	pub const MaximumUnlockIdOfTimeUnit: u32 = 1_000;
 	pub const MaxLockRecords: u32 = 64;
-	pub BifrostEntranceAccount: PalletId = PalletId(*b"bf/vtkin");
-	pub BifrostExitAccount: PalletId = PalletId(*b"bf/vtout");
-	pub IncentivePoolAccount: PalletId = PalletId(*b"bf/inpoo");
-	pub BifrostFeeAccount: AccountId = hex!["e4da05f08e89bf6c43260d96f26fffcfc7deae5b465da08669a9d008e64c2c63"].into();
 }
 
 ord_parameter_types! {
 	pub const One: AccountId = ALICE;
-	pub const RelayCurrencyId: CurrencyId = CurrencyId::Token(TokenSymbol::KSM);
+	pub const RelayCurrencyId: CurrencyId = KSM;
 }
 
 impl vtoken_minting::Config for Runtime {
diff --git a/pallets/vtoken-voting/src/mock.rs b/pallets/vtoken-voting/src/mock.rs
index a9bada263..16a6adfc6 100644
--- a/pallets/vtoken-voting/src/mock.rs
+++ b/pallets/vtoken-voting/src/mock.rs
@@ -23,7 +23,7 @@ use crate::{BalanceOf, DerivativeAccountHandler, DerivativeIndex, DispatchResult
 use bifrost_primitives::{
 	currency::{KSM, VBNC, VKSM},
 	traits::XcmDestWeightAndFeeHandler,
-	CurrencyId, MockXcmRouter, TokenSymbol, VTokenSupplyProvider, XcmOperationType,
+	CurrencyId, MockXcmRouter, VTokenSupplyProvider, XcmOperationType, BNC,
 };
 use cumulus_primitives_core::ParaId;
 use frame_support::{
@@ -80,7 +80,7 @@ impl frame_system::Config for Runtime {
 }
 
 parameter_types! {
-	pub const NativeCurrencyId: CurrencyId = CurrencyId::Native(TokenSymbol::BNC);
+	pub const NativeCurrencyId: CurrencyId = BNC;
 }
 
 pub type AdaptedBasicCurrency =
diff --git a/primitives/Cargo.toml b/primitives/Cargo.toml
index c7081880c..93e60be9f 100644
--- a/primitives/Cargo.toml
+++ b/primitives/Cargo.toml
@@ -11,6 +11,7 @@ scale-info = { workspace = true, features = ["derive"] }
 serde = { workspace = true, features = ["derive"] }
 
 frame-support = { workspace = true }
+hex-literal = { workspace = true }
 sp-core = { workspace = true }
 sp-runtime = { workspace = true }
 sp-std = { workspace = true }
diff --git a/primitives/src/currency.rs b/primitives/src/currency.rs
index 3709c2598..e6d1e67f4 100644
--- a/primitives/src/currency.rs
+++ b/primitives/src/currency.rs
@@ -44,6 +44,8 @@ pub const VSKSM: CurrencyId = CurrencyId::VSToken(TokenSymbol::KSM);
 pub const PHA: CurrencyId = CurrencyId::Token(TokenSymbol::PHA);
 pub const VPHA: CurrencyId = CurrencyId::VToken(TokenSymbol::PHA);
 pub const ZLK: CurrencyId = CurrencyId::Token(TokenSymbol::ZLK);
+pub const KUSD: CurrencyId = CurrencyId::Stable(TokenSymbol::KUSD);
+pub const ASG: CurrencyId = CurrencyId::Native(TokenSymbol::ASG);
 
 pub const DOT_TOKEN_ID: u8 = 0u8;
 pub const DOT: CurrencyId = CurrencyId::Token2(DOT_TOKEN_ID);
diff --git a/primitives/src/lib.rs b/primitives/src/lib.rs
index 0040e851d..b711cb02d 100644
--- a/primitives/src/lib.rs
+++ b/primitives/src/lib.rs
@@ -20,6 +20,8 @@
 
 #![cfg_attr(not(feature = "std"), no_std)]
 
+use frame_support::{parameter_types, PalletId};
+use hex_literal::hex;
 use parity_scale_codec::MaxEncodedLen;
 use scale_info::TypeInfo;
 use sp_core::{Decode, Encode, RuntimeDebug, H160};
@@ -156,6 +158,44 @@ pub type DerivativeIndex = u16;
 
 pub type TimeStampedPrice = orml_oracle::TimestampedValue<Price, Moment>;
 
+// Pallet Id
+parameter_types! {
+	pub const BifrostCrowdloanId: PalletId = PalletId(*b"bf/salp#");
+	pub BifrostEntranceAccount: PalletId = PalletId(*b"bf/vtkin");
+	pub BifrostExitAccount: PalletId = PalletId(*b"bf/vtout");
+	pub BifrostVsbondAccount: PalletId = PalletId(*b"bf/salpb");
+	pub const BuyBackAccount: PalletId = PalletId(*b"bf/bybck");
+	pub const BuybackPalletId: PalletId = PalletId(*b"bf/salpc");
+	pub const CloudsPalletId: PalletId = PalletId(*b"bf/cloud");
+	pub const CommissionPalletId: PalletId = PalletId(*b"bf/comms");
+	pub const FarmingBoostPalletId: PalletId = PalletId(*b"bf/fmbst");
+	pub const FarmingGaugeRewardIssuerPalletId: PalletId = PalletId(*b"bf/fmgar");
+	pub const FarmingKeeperPalletId: PalletId = PalletId(*b"bf/fmkpr");
+	pub const FarmingRewardIssuerPalletId: PalletId = PalletId(*b"bf/fmrir");
+	pub const FeeSharePalletId: PalletId = PalletId(*b"bf/feesh");
+	pub const FlexibleFeePalletId: PalletId = PalletId(*b"bf/flexi");
+	pub IncentivePoolAccount: PalletId = PalletId(*b"bf/inpoo");
+	pub IncentivePalletId: PalletId = PalletId(*b"bf/bbict");
+	pub const LendMarketPalletId: PalletId = PalletId(*b"bf/ldmkt");
+	pub const LighteningRedeemPalletId: PalletId = PalletId(*b"lighten#");
+	pub const LiquidityAccount: PalletId = PalletId(*b"bf/liqdt");
+	pub const LiquidityMiningPalletId: PalletId = PalletId(*b"mining##");
+	pub const ParachainStakingPalletId: PalletId = PalletId(*b"bf/stake");
+	pub const SlpEntrancePalletId: PalletId = PalletId(*b"bf/vtkin");
+	pub const StableAssetPalletId: PalletId = PalletId(*b"nuts/sta");
+	pub const SystemMakerPalletId: PalletId = PalletId(*b"bf/sysmk");
+	pub const SystemStakingPalletId: PalletId = PalletId(*b"bf/sysst");
+	pub const VBNCConvertPalletId: PalletId = PalletId(*b"bf/vbncc");
+	pub const VeMintingPalletId: PalletId = PalletId(*b"bf/vemnt");
+	pub const VsbondAuctionPalletId: PalletId = PalletId(*b"bf/vsbnd");
+	pub const ZenlinkPalletId: PalletId = PalletId(*b"/zenlink");
+}
+
+// Account Id
+parameter_types! {
+	pub BifrostFeeAccount: AccountId = hex!["e4da05f08e89bf6c43260d96f26fffcfc7deae5b465da08669a9d008e64c2c63"].into();
+}
+
 // For vtoken-minting
 #[derive(
 	PartialEq, Eq, Clone, Encode, Decode, MaxEncodedLen, RuntimeDebug, scale_info::TypeInfo,

From 0e8f755cddcd9f85de87a44d7c023ec511b00605 Mon Sep 17 00:00:00 2001
From: NingBo Wang <2536935847@qq.com>
Date: Wed, 25 Sep 2024 15:03:48 +0800
Subject: [PATCH 05/31] Optimize xcm interface (#1439)

* Optimize xcm-interface pallet

* Add weights

* Add weights

* Add weights

* Optimize xcm-interface pallet
---
 Cargo.lock                                    |   2 +
 pallets/flexible-fee/src/lib.rs               |  44 +-
 pallets/flexible-fee/src/tests.rs             |  43 ++
 pallets/salp/src/lib.rs                       | 446 +-----------------
 pallets/slp/src/agents/utils.rs               |  42 +-
 pallets/xcm-interface/Cargo.toml              |   5 +-
 pallets/xcm-interface/src/benchmarking.rs     |  43 ++
 pallets/xcm-interface/src/calls.rs            | 128 +----
 pallets/xcm-interface/src/lib.rs              | 330 +++----------
 pallets/xcm-interface/src/mock.rs             | 157 ++++++
 pallets/xcm-interface/src/tests.rs            |  50 ++
 pallets/xcm-interface/src/traits.rs           | 159 -------
 pallets/xcm-interface/src/weights.rs          |  82 ++++
 primitives/src/xcm.rs                         |   2 +
 runtime/bifrost-kusama/Cargo.toml             |   1 +
 runtime/bifrost-kusama/src/lib.rs             |   9 +-
 runtime/bifrost-kusama/src/migration.rs       |   3 -
 .../src/weights/bifrost_xcm_interface.rs      |  78 +++
 runtime/bifrost-kusama/src/weights/mod.rs     |   1 +
 runtime/bifrost-kusama/src/xcm_config.rs      |  33 +-
 runtime/bifrost-polkadot/Cargo.toml           |   1 +
 runtime/bifrost-polkadot/src/lib.rs           |   6 +-
 .../src/weights/bifrost_xcm_interface.rs      |  78 +++
 runtime/bifrost-polkadot/src/weights/mod.rs   |   1 +
 runtime/bifrost-polkadot/src/xcm_config.rs    |  12 +-
 25 files changed, 665 insertions(+), 1091 deletions(-)
 create mode 100644 pallets/xcm-interface/src/benchmarking.rs
 create mode 100644 pallets/xcm-interface/src/mock.rs
 create mode 100644 pallets/xcm-interface/src/tests.rs
 delete mode 100644 pallets/xcm-interface/src/traits.rs
 create mode 100644 pallets/xcm-interface/src/weights.rs
 create mode 100644 runtime/bifrost-kusama/src/weights/bifrost_xcm_interface.rs
 create mode 100644 runtime/bifrost-polkadot/src/weights/bifrost_xcm_interface.rs

diff --git a/Cargo.lock b/Cargo.lock
index 6476ca98b..8c990f909 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2376,11 +2376,13 @@ name = "bifrost-xcm-interface"
 version = "0.8.0"
 dependencies = [
  "bifrost-asset-registry",
+ "bifrost-currencies",
  "bifrost-primitives",
  "cumulus-primitives-core",
  "frame-benchmarking",
  "frame-support",
  "frame-system",
+ "orml-tokens",
  "orml-traits",
  "pallet-balances",
  "pallet-xcm",
diff --git a/pallets/flexible-fee/src/lib.rs b/pallets/flexible-fee/src/lib.rs
index 889b9f494..2b585be1f 100644
--- a/pallets/flexible-fee/src/lib.rs
+++ b/pallets/flexible-fee/src/lib.rs
@@ -22,10 +22,10 @@ pub use crate::pallet::*;
 use bifrost_primitives::{
 	currency::{VGLMR, VMANTA, WETH},
 	traits::XcmDestWeightAndFeeHandler,
-	Balance, BalanceCmp, CurrencyId, DerivativeIndex, OraclePriceProvider, Price, TryConvertFrom,
-	XcmOperationType, BNC, DOT, GLMR, MANTA, VBNC, VDOT,
+	AssetHubChainId, Balance, BalanceCmp, CurrencyId, DerivativeIndex, OraclePriceProvider, Price,
+	TryConvertFrom, XcmOperationType, BNC, DOT, GLMR, MANTA, VBNC, VDOT,
 };
-use bifrost_xcm_interface::{polkadot::RelaychainCall, traits::parachains, PolkadotXcmCall};
+use bifrost_xcm_interface::calls::{PolkadotXcmCall, RelaychainCall};
 use core::convert::Into;
 use cumulus_primitives_core::ParaId;
 use frame_support::{
@@ -274,28 +274,24 @@ impl<T: Config> Pallet<T> {
 				)),
 			};
 
-			let remote_call =
-				RelaychainCall::<BalanceOf<T>, AccountIdOf<T>, BlockNumberFor<T>>::XcmPallet(
-					PolkadotXcmCall::LimitedTeleportAssets(
-						Box::new(Location::new(0, [Parachain(parachains::Statemine::ID)]).into()),
-						Box::new(
-							Location::new(
-								0,
-								[AccountId32 {
-									network: None,
-									id: Sibling::from(T::ParachainId::get())
-										.into_account_truncating(),
-								}],
-							)
-							.into(),
-						),
-						Box::new(asset.into()),
+			let remote_call = RelaychainCall::XcmPallet(PolkadotXcmCall::LimitedTeleportAssets(
+				Box::new(Location::new(0, [Parachain(AssetHubChainId::get())]).into()),
+				Box::new(
+					Location::new(
 						0,
-						Unlimited,
-					),
-				)
-				.encode()
-				.into();
+						[AccountId32 {
+							network: None,
+							id: Sibling::from(T::ParachainId::get()).into_account_truncating(),
+						}],
+					)
+					.into(),
+				),
+				Box::new(asset.into()),
+				0,
+				Unlimited,
+			))
+			.encode()
+			.into();
 
 			let (require_weight_at_most, xcm_fee) =
 				T::XcmWeightAndFeeHandler::get_operation_weight_and_fee(
diff --git a/pallets/flexible-fee/src/tests.rs b/pallets/flexible-fee/src/tests.rs
index a365b46d4..ce373e01e 100644
--- a/pallets/flexible-fee/src/tests.rs
+++ b/pallets/flexible-fee/src/tests.rs
@@ -327,6 +327,49 @@ fn correct_and_deposit_fee_should_work() {
 	});
 }
 
+#[test]
+fn correct_and_deposit_fee_with_tip() {
+	new_test_ext().execute_with(|| {
+		basic_setup();
+
+		let corrected_fee = 5 * 10u128.pow(12);
+		let tip = 5 * 10u128.pow(12);
+
+		assert_eq!(Currencies::free_balance(BNC, &ALICE), 1000 * 10u128.pow(12));
+
+		let already_withdrawn = Some(PaymentInfo::Native(10 * 10u128.pow(12)));
+		assert_ok!(FlexibleFee::correct_and_deposit_fee(
+			&ALICE,
+			&info(),
+			&post_info(),
+			corrected_fee,
+			tip,
+			already_withdrawn
+		));
+		assert_eq!(Currencies::free_balance(BNC, &ALICE), 1005 * 10u128.pow(12));
+
+		let corrected_fee = 10 * 10u128.pow(12);
+		let tip = 10 * 10u128.pow(12);
+		assert_eq!(Currencies::free_balance(DOT, &ALICE), 1000 * 10u128.pow(10));
+
+		let already_withdrawn = Some(PaymentInfo::NonNative(
+			1 * 10u128.pow(10),
+			DOT,
+			FixedU128::from_inner(200_000_000_000_000_000),
+			FixedU128::from(5),
+		));
+		assert_ok!(FlexibleFee::correct_and_deposit_fee(
+			&ALICE,
+			&info(),
+			&post_info(),
+			corrected_fee,
+			tip,
+			already_withdrawn
+		));
+		assert_eq!(Currencies::free_balance(DOT, &ALICE), 10006 * 10u128.pow(9));
+	});
+}
+
 #[test]
 fn get_currency_asset_id_should_work() {
 	new_test_ext().execute_with(|| {
diff --git a/pallets/salp/src/lib.rs b/pallets/salp/src/lib.rs
index a1a09090d..d4943958e 100644
--- a/pallets/salp/src/lib.rs
+++ b/pallets/salp/src/lib.rs
@@ -19,12 +19,6 @@
 // Ensure we're `no_std` when compiling for Wasm.
 #![cfg_attr(not(feature = "std"), no_std)]
 
-#[cfg(feature = "runtime-benchmarks")]
-pub mod benchmarking;
-#[cfg(test)]
-pub mod mock;
-#[cfg(test)]
-mod tests;
 pub mod weights;
 pub use weights::WeightInfo;
 
@@ -33,12 +27,10 @@ use bifrost_primitives::{
 	ContributionStatus, CurrencyIdConversion, CurrencyIdRegister, TrieIndex, VtokenMintingInterface,
 };
 use bifrost_stable_pool::{traits::StablePoolHandler, StableAssetPoolId};
-use bifrost_xcm_interface::ChainId;
-use cumulus_primitives_core::{QueryId, Response};
+use cumulus_primitives_core::QueryId;
 use frame_support::{pallet_prelude::*, sp_runtime::SaturatedConversion};
 use orml_traits::MultiCurrency;
 pub use pallet::*;
-use pallet_xcm::ensure_response;
 use scale_info::TypeInfo;
 use sp_runtime::traits::One;
 
@@ -95,10 +87,10 @@ pub struct ReserveInfo<Balance> {
 #[frame_support::pallet]
 pub mod pallet {
 	// Import various types used to declare pallet in scope.
+	use super::*;
 	use bifrost_primitives::{CurrencyId, LeasePeriod, MessageId, Nonce, ParaId};
-	use bifrost_xcm_interface::traits::XcmHelper;
 	use frame_support::{
-		pallet_prelude::{storage::child, *},
+		pallet_prelude::storage::child,
 		sp_runtime::traits::{AccountIdConversion, CheckedAdd, Hash, Saturating, Zero},
 		storage::ChildTriePrefixIterator,
 		PalletId,
@@ -109,9 +101,6 @@ pub mod pallet {
 	};
 	use sp_arithmetic::Percent;
 	use sp_std::{convert::TryInto, prelude::*};
-	use xcm::v3::MaybeErrorCode;
-
-	use super::*;
 
 	#[pallet::config]
 	pub trait Config: frame_system::Config {
@@ -166,9 +155,6 @@ pub mod pallet {
 
 		type WeightInfo: WeightInfo;
 
-		/// The XcmInterface to manage the staking of sub-account on relaychain.
-		type XcmInterface: XcmHelper<AccountIdOf<Self>, BalanceOf<Self>>;
-
 		#[pallet::constant]
 		type TreasuryAccount: Get<Self::AccountId>;
 
@@ -674,82 +660,6 @@ pub mod pallet {
 			Ok(())
 		}
 
-		// unused but xcm-interface
-		#[pallet::call_index(20)]
-		#[pallet::weight(T::WeightInfo::confirm_contribute())]
-		pub fn confirm_contribution(
-			origin: OriginFor<T>,
-			query_id: QueryId,
-			response: Response,
-		) -> DispatchResult {
-			let responder = ensure_response(<T as Config>::RuntimeOrigin::from(origin))?;
-			ensure!(responder == xcm::v4::Location::parent(), Error::<T>::ResponderNotRelayChain);
-
-			let (index, contributer, _amount) = QueryIdContributionInfo::<T>::get(query_id)
-				.ok_or(Error::<T>::NotFindContributionValue)?;
-
-			let fund = Funds::<T>::get(index).ok_or(Error::<T>::InvalidParaId)?;
-			let can_confirm = fund.status == FundStatus::Ongoing ||
-				fund.status == FundStatus::Failed ||
-				fund.status == FundStatus::Success;
-			ensure!(can_confirm, Error::<T>::InvalidFundStatus);
-
-			let (contributed, status) = Self::contribution(fund.trie_index, &contributer);
-			ensure!(status.is_contributing(), Error::<T>::InvalidContributionStatus);
-			let contributing = status.contributing();
-
-			let vs_token = T::CurrencyIdConversion::convert_to_vstoken(T::RelayChainToken::get())
-				.map_err(|_| Error::<T>::NotSupportTokenType)?;
-			let vs_bond = T::CurrencyIdConversion::convert_to_vsbond(
-				T::RelayChainToken::get(),
-				index,
-				fund.first_slot,
-				fund.last_slot,
-			)
-			.map_err(|_| Error::<T>::NotSupportTokenType)?;
-
-			if let Response::DispatchResult(MaybeErrorCode::Success) = response {
-				// Issue reserved vsToken/vsBond to contributor
-				T::MultiCurrency::deposit(vs_token, &contributer, contributing)?;
-				T::MultiCurrency::deposit(vs_bond, &contributer, contributing)?;
-
-				// Update the raised of fund
-				let fund_new =
-					FundInfo { raised: fund.raised.saturating_add(contributing), ..fund };
-				Funds::<T>::insert(index, Some(fund_new));
-
-				T::MultiCurrency::unreserve(T::RelayChainToken::get(), &contributer, contributing);
-				T::MultiCurrency::transfer(
-					T::RelayChainToken::get(),
-					&contributer,
-					&Self::fund_account_id(index),
-					contributing,
-				)?;
-
-				// Update the contribution of contributer
-				let contributed_new = contributed.saturating_add(contributing);
-				Self::put_contribution(
-					fund.trie_index,
-					&contributer,
-					contributed_new,
-					ContributionStatus::Idle,
-				);
-				Self::deposit_event(Event::Contributed(contributer, index, contributing));
-			} else {
-				// Update the contribution of contributer
-				Self::put_contribution(
-					fund.trie_index,
-					&contributer,
-					contributed,
-					ContributionStatus::Idle,
-				);
-				T::MultiCurrency::unreserve(T::RelayChainToken::get(), &contributer, contributing);
-				Self::deposit_event(Event::ContributeFailed(contributer, index, contributing));
-			}
-			QueryIdContributionInfo::<T>::remove(query_id);
-			Ok(())
-		}
-
 		#[pallet::call_index(21)]
 		#[pallet::weight(T::WeightInfo::buyback_vstoken_by_stable_pool())]
 		pub fn buyback_vstoken_by_stable_pool(
@@ -825,315 +735,6 @@ pub mod pallet {
 		}
 	}
 
-	// These methods are no longer in use and are now only called for testing and benchmarking
-	// purposes.
-	impl<T: Config> Pallet<T> {
-		pub(crate) fn fund_success(origin: OriginFor<T>, index: ParaId) -> DispatchResult {
-			T::EnsureConfirmAsGovernance::ensure_origin(origin)?;
-
-			let fund = Funds::<T>::get(index).ok_or(Error::<T>::InvalidParaId)?;
-			ensure!(fund.status == FundStatus::Ongoing, Error::<T>::InvalidFundStatus);
-
-			let fund_new = FundInfo { status: FundStatus::Success, ..fund };
-			Funds::<T>::insert(index, Some(fund_new));
-			Self::deposit_event(Event::<T>::Success(index));
-
-			Ok(())
-		}
-
-		pub(crate) fn fund_fail(origin: OriginFor<T>, index: ParaId) -> DispatchResult {
-			T::EnsureConfirmAsGovernance::ensure_origin(origin)?;
-
-			// crownload is failed, so enable the withdrawal function of vsToken/vsBond
-			let fund = crate::pallet::Funds::<T>::get(index)
-				.ok_or(crate::pallet::Error::<T>::InvalidParaId)?;
-			ensure!(fund.status == FundStatus::Ongoing, Error::<T>::InvalidFundStatus);
-
-			let fund_new = crate::FundInfo { status: crate::FundStatus::Failed, ..fund };
-			crate::pallet::Funds::<T>::insert(index, Some(fund_new));
-			Self::deposit_event(crate::pallet::Event::<T>::Failed(index));
-
-			Ok(())
-		}
-
-		pub(crate) fn continue_fund(
-			origin: OriginFor<T>,
-			index: ParaId,
-			first_slot: LeasePeriod,
-			last_slot: LeasePeriod,
-		) -> DispatchResult {
-			T::EnsureConfirmAsGovernance::ensure_origin(origin)?;
-
-			// crownload is failed, so enable the withdrawal function of vsToken/vsBond
-			let fund = Funds::<T>::get(index).ok_or(Error::<T>::InvalidParaId)?;
-			ensure!(fund.status == FundStatus::RefundWithdrew, Error::<T>::InvalidFundStatus);
-			ensure!(
-				fund.first_slot != first_slot || fund.last_slot != last_slot,
-				Error::<T>::InvalidFundSameSlot
-			);
-
-			let fund_old = FundInfo { status: FundStatus::FailedToContinue, ..fund };
-			FailedFundsToRefund::<T>::insert(
-				(index, fund.first_slot, fund.last_slot),
-				Some(fund_old.clone()),
-			);
-			let fund_new = FundInfo { status: FundStatus::Ongoing, first_slot, last_slot, ..fund };
-			Funds::<T>::insert(index, Some(fund_new));
-
-			match T::RelayChainToken::get() {
-				CurrencyId::Token(token_symbol) =>
-					if !T::CurrencyIdRegister::check_vsbond_registered(
-						token_symbol,
-						index,
-						first_slot,
-						last_slot,
-					) {
-						T::CurrencyIdRegister::register_vsbond_metadata(
-							token_symbol,
-							index,
-							first_slot,
-							last_slot,
-						)?;
-					},
-				CurrencyId::Token2(token_id) => {
-					if !T::CurrencyIdRegister::check_vsbond2_registered(
-						token_id, index, first_slot, last_slot,
-					) {
-						T::CurrencyIdRegister::register_vsbond2_metadata(
-							token_id, index, first_slot, last_slot,
-						)?;
-					}
-				},
-				_ => (),
-			}
-
-			Self::deposit_event(Event::<T>::Continued(
-				index,
-				fund_old.first_slot,
-				fund_old.last_slot,
-			));
-
-			Ok(())
-		}
-
-		/// Create a new crowdloaning campaign for a parachain slot deposit for the current auction.
-		pub(crate) fn create(
-			origin: OriginFor<T>,
-			index: ParaId,
-			cap: BalanceOf<T>,
-			first_slot: LeasePeriod,
-			last_slot: LeasePeriod,
-		) -> DispatchResult {
-			T::EnsureConfirmAsGovernance::ensure_origin(origin)?;
-
-			ensure!(!Funds::<T>::contains_key(index), Error::<T>::FundAlreadyCreated);
-
-			ensure!(first_slot <= last_slot, Error::<T>::LastSlotBeforeFirstSlot);
-
-			let last_slot_limit = first_slot
-				.checked_add(((T::SlotLength::get() as u32) - 1).into())
-				.ok_or(Error::<T>::FirstSlotTooFarInFuture)?;
-			ensure!(last_slot <= last_slot_limit, Error::<T>::LastSlotTooFarInFuture);
-
-			Funds::<T>::insert(
-				index,
-				Some(FundInfo {
-					raised: Zero::zero(),
-					cap,
-					first_slot,
-					last_slot,
-					trie_index: Self::next_trie_index()?,
-					status: FundStatus::Ongoing,
-				}),
-			);
-
-			match T::RelayChainToken::get() {
-				CurrencyId::Token(token_symbol) =>
-					if !T::CurrencyIdRegister::check_vsbond_registered(
-						token_symbol,
-						index,
-						first_slot,
-						last_slot,
-					) {
-						T::CurrencyIdRegister::register_vsbond_metadata(
-							token_symbol,
-							index,
-							first_slot,
-							last_slot,
-						)?;
-					},
-				CurrencyId::Token2(token_id) => {
-					if !T::CurrencyIdRegister::check_vsbond2_registered(
-						token_id, index, first_slot, last_slot,
-					) {
-						T::CurrencyIdRegister::register_vsbond2_metadata(
-							token_id, index, first_slot, last_slot,
-						)?;
-					}
-				},
-				_ => (),
-			}
-
-			Self::deposit_event(Event::<T>::Created(index));
-
-			Ok(())
-		}
-
-		/// Contribute to a crowd sale. This will transfer some balance over to fund a parachain
-		/// slot. It will be withdrawable in two instances: the parachain becomes retired; or the
-		/// slot is unable to be purchased and the timeout expires.
-		pub(crate) fn contribute(
-			origin: OriginFor<T>,
-			index: ParaId,
-			value: BalanceOf<T>,
-		) -> DispatchResult {
-			let who = ensure_signed(origin.clone())?;
-
-			let fund = Funds::<T>::get(index).ok_or(Error::<T>::InvalidParaId)?;
-			ensure!(fund.status == FundStatus::Ongoing, Error::<T>::InvalidFundStatus);
-
-			ensure!(value >= T::MinContribution::get(), Error::<T>::ContributionTooSmall);
-
-			let raised = fund.raised.checked_add(&value).ok_or(Error::<T>::Overflow)?;
-			ensure!(raised <= fund.cap, Error::<T>::CapExceeded);
-
-			let (contributed, status) = Self::contribution(fund.trie_index, &who);
-			ensure!(
-				status == ContributionStatus::Idle ||
-					status == ContributionStatus::Refunded ||
-					status == ContributionStatus::Redeemed ||
-					status == ContributionStatus::Unlocked,
-				Error::<T>::InvalidContributionStatus
-			);
-
-			ensure!(
-				T::MultiCurrency::can_reserve(T::RelayChainToken::get(), &who, value),
-				Error::<T>::NotEnoughBalanceToContribute
-			);
-
-			T::MultiCurrency::reserve(T::RelayChainToken::get(), &who, value)?;
-
-			Self::put_contribution(
-				fund.trie_index,
-				&who,
-				contributed,
-				ContributionStatus::Contributing(value),
-			);
-
-			let message_id = T::XcmInterface::contribute(who.clone(), index, value)?;
-
-			Self::deposit_event(Event::Contributing(who, index, value, message_id));
-			Ok(())
-		}
-
-		/// Confirm contribute
-		pub(crate) fn confirm_contribute(
-			origin: OriginFor<T>,
-			query_id: QueryId,
-			is_success: bool,
-		) -> DispatchResult {
-			let confirmor = ensure_signed(origin.clone())?;
-			if Some(confirmor) != MultisigConfirmAccount::<T>::get() {
-				return Err(DispatchError::BadOrigin.into());
-			}
-
-			let (index, contributer, _amount) = QueryIdContributionInfo::<T>::get(query_id)
-				.ok_or(Error::<T>::NotFindContributionValue)?;
-
-			let fund = Funds::<T>::get(index).ok_or(Error::<T>::InvalidParaId)?;
-			let can_confirm = fund.status == FundStatus::Ongoing ||
-				fund.status == FundStatus::Failed ||
-				fund.status == FundStatus::Success;
-			ensure!(can_confirm, Error::<T>::InvalidFundStatus);
-
-			let (contributed, status) = Self::contribution(fund.trie_index, &contributer);
-			ensure!(status.is_contributing(), Error::<T>::InvalidContributionStatus);
-			let contributing = status.contributing();
-
-			let vs_token = T::CurrencyIdConversion::convert_to_vstoken(T::RelayChainToken::get())
-				.map_err(|_| Error::<T>::NotSupportTokenType)?;
-			let vs_bond = T::CurrencyIdConversion::convert_to_vsbond(
-				T::RelayChainToken::get(),
-				index,
-				fund.first_slot,
-				fund.last_slot,
-			)
-			.map_err(|_| Error::<T>::NotSupportTokenType)?;
-
-			if is_success {
-				// Issue reserved vsToken/vsBond to contributor
-				T::MultiCurrency::deposit(vs_token, &contributer, contributing)?;
-				T::MultiCurrency::deposit(vs_bond, &contributer, contributing)?;
-
-				// Update the raised of fund
-				let fund_new =
-					FundInfo { raised: fund.raised.saturating_add(contributing), ..fund };
-				Funds::<T>::insert(index, Some(fund_new));
-
-				T::MultiCurrency::unreserve(T::RelayChainToken::get(), &contributer, contributing);
-				T::MultiCurrency::transfer(
-					T::RelayChainToken::get(),
-					&contributer,
-					&Self::fund_account_id(index),
-					contributing,
-				)?;
-
-				// Update the contribution of contributer
-				let contributed_new = contributed.saturating_add(contributing);
-				Self::put_contribution(
-					fund.trie_index,
-					&contributer,
-					contributed_new,
-					ContributionStatus::Idle,
-				);
-				Self::deposit_event(Event::Contributed(contributer, index, contributing));
-			} else {
-				// Update the contribution of contributer
-				Self::put_contribution(
-					fund.trie_index,
-					&contributer,
-					contributed,
-					ContributionStatus::Idle,
-				);
-				T::MultiCurrency::unreserve(T::RelayChainToken::get(), &contributer, contributing);
-				Self::deposit_event(Event::ContributeFailed(contributer, index, contributing));
-			}
-
-			QueryIdContributionInfo::<T>::remove(query_id);
-
-			Ok(())
-		}
-
-		/// Unlock the reserved vsToken/vsBond after fund success
-		pub(crate) fn unlock(
-			origin: OriginFor<T>,
-			who: AccountIdOf<T>,
-			index: ParaId,
-		) -> DispatchResult {
-			ensure_signed(origin)?;
-			let fund = Funds::<T>::get(index).ok_or(Error::<T>::InvalidParaId)?;
-
-			let (contributed, _) = Self::contribution(fund.trie_index, &who);
-
-			let vs_token = T::CurrencyIdConversion::convert_to_vstoken(T::RelayChainToken::get())
-				.map_err(|_| Error::<T>::NotSupportTokenType)?;
-			let vs_bond = T::CurrencyIdConversion::convert_to_vsbond(
-				T::RelayChainToken::get(),
-				index,
-				fund.first_slot,
-				fund.last_slot,
-			)
-			.map_err(|_| Error::<T>::NotSupportTokenType)?;
-
-			T::MultiCurrency::unreserve(vs_token, &who, contributed);
-			T::MultiCurrency::unreserve(vs_bond, &who, contributed);
-
-			Self::deposit_event(Event::<T>::Unlocked(who, index, contributed));
-
-			Ok(())
-		}
-	}
-
 	impl<T: Config> Pallet<T> {
 		/// Check if the vsBond is `past` the redeemable date
 		pub(crate) fn is_expired(
@@ -1208,49 +809,8 @@ pub mod pallet {
 			)
 		}
 
-		pub(crate) fn next_trie_index() -> Result<TrieIndex, Error<T>> {
-			CurrentTrieIndex::<T>::try_mutate(|ti| {
-				*ti = ti.checked_add(1).ok_or(Error::<T>::Overflow)?;
-				Ok(*ti - 1)
-			})
-		}
-
-		fn put_contribution(
-			index: TrieIndex,
-			who: &AccountIdOf<T>,
-			contributed: BalanceOf<T>,
-			status: ContributionStatus<BalanceOf<T>>,
-		) {
-			who.using_encoded(|b| {
-				child::put(&Self::id_from_index(index), b, &(contributed, status))
-			});
-		}
-
 		fn kill_contribution(index: TrieIndex, who: &AccountIdOf<T>) {
 			who.using_encoded(|b| child::kill(&Self::id_from_index(index), b));
 		}
-
-		pub(crate) fn set_balance(who: &AccountIdOf<T>, value: BalanceOf<T>) -> DispatchResult {
-			T::MultiCurrency::deposit(T::RelayChainToken::get(), who, value)
-		}
-	}
-}
-
-impl<T: Config>
-	bifrost_xcm_interface::SalpHelper<AccountIdOf<T>, <T as Config>::RuntimeCall, BalanceOf<T>>
-	for Pallet<T>
-{
-	fn confirm_contribute_call() -> <T as Config>::RuntimeCall {
-		let call = Call::<T>::confirm_contribution { query_id: 0, response: Default::default() };
-		<T as Config>::RuntimeCall::from(call)
-	}
-
-	fn bind_query_id_and_contribution(
-		query_id: QueryId,
-		index: ChainId,
-		contributer: AccountIdOf<T>,
-		amount: BalanceOf<T>,
-	) {
-		QueryIdContributionInfo::<T>::insert(query_id, (index, contributer, amount));
 	}
 }
diff --git a/pallets/slp/src/agents/utils.rs b/pallets/slp/src/agents/utils.rs
index c2cb60474..2c970f99e 100644
--- a/pallets/slp/src/agents/utils.rs
+++ b/pallets/slp/src/agents/utils.rs
@@ -21,8 +21,9 @@ use crate::{
 	ValidatorsByDelegatorUpdateEntry, ValidatorsByDelegatorXcmUpdateQueue, ASTR, DOT, GLMR, H160,
 	KSM, MANTA, MOVR, PHA,
 };
-use bifrost_primitives::CurrencyId;
-use bifrost_xcm_interface::traits::parachains;
+use bifrost_primitives::{
+	AstarChainId, CurrencyId, MantaChainId, MoonbeamChainId, MoonriverChainId, PhalaChainId,
+};
 use frame_support::ensure;
 use parity_scale_codec::Encode;
 use sp_core::Get;
@@ -323,18 +324,16 @@ impl<T: Config> Pallet<T> {
 			KSM | DOT => Ok(xcm::v4::Location::parent()),
 			MOVR => Ok(xcm::v4::Location::new(
 				1,
-				[xcm::v4::prelude::Parachain(parachains::moonriver::ID)],
-			)),
-			GLMR => Ok(xcm::v4::Location::new(
-				1,
-				[xcm::v4::prelude::Parachain(parachains::moonbeam::ID)],
+				[xcm::v4::prelude::Parachain(MoonriverChainId::get())],
 			)),
+			GLMR =>
+				Ok(xcm::v4::Location::new(1, [xcm::v4::prelude::Parachain(MoonbeamChainId::get())])),
 			ASTR =>
-				Ok(xcm::v4::Location::new(1, [xcm::v4::prelude::Parachain(parachains::astar::ID)])),
+				Ok(xcm::v4::Location::new(1, [xcm::v4::prelude::Parachain(AstarChainId::get())])),
 			MANTA =>
-				Ok(xcm::v4::Location::new(1, [xcm::v4::prelude::Parachain(parachains::manta::ID)])),
+				Ok(xcm::v4::Location::new(1, [xcm::v4::prelude::Parachain(MantaChainId::get())])),
 			PHA =>
-				Ok(xcm::v4::Location::new(1, [xcm::v4::prelude::Parachain(parachains::phala::ID)])),
+				Ok(xcm::v4::Location::new(1, [xcm::v4::prelude::Parachain(PhalaChainId::get())])),
 			_ => Err(Error::<T>::NotSupportedCurrencyId),
 		}
 	}
@@ -345,34 +344,21 @@ impl<T: Config> Pallet<T> {
 		match currency_id {
 			MOVR => Ok(MultiLocation {
 				parents: 1,
-				interior: X2(
-					Parachain(parachains::moonriver::ID),
-					PalletInstance(parachains::moonriver::PALLET_ID),
-				),
+				interior: X2(Parachain(MoonriverChainId::get()), PalletInstance(10)),
 			}),
 			GLMR => Ok(MultiLocation {
 				parents: 1,
-				interior: X2(
-					Parachain(parachains::moonbeam::ID),
-					PalletInstance(parachains::moonbeam::PALLET_ID),
-				),
+				interior: X2(Parachain(MoonbeamChainId::get()), PalletInstance(10)),
 			}),
-			MANTA =>
-				Ok(MultiLocation { parents: 1, interior: X1(Parachain(parachains::manta::ID)) }),
+			MANTA => Ok(MultiLocation { parents: 1, interior: X1(Parachain(MantaChainId::get())) }),
 			_ => Err(Error::<T>::NotSupportedCurrencyId),
 		}
 	}
 
 	pub fn convert_currency_to_remote_fee_location(currency_id: CurrencyId) -> xcm::v4::Location {
 		match currency_id {
-			MOVR => xcm::v4::Location::new(
-				0,
-				[xcm::v4::prelude::PalletInstance(parachains::moonriver::PALLET_ID)],
-			),
-			GLMR => xcm::v4::Location::new(
-				0,
-				[xcm::v4::prelude::PalletInstance(parachains::moonbeam::PALLET_ID)],
-			),
+			MOVR => xcm::v4::Location::new(0, [xcm::v4::prelude::PalletInstance(10)]),
+			GLMR => xcm::v4::Location::new(0, [xcm::v4::prelude::PalletInstance(10)]),
 			_ => xcm::v4::Location::here(),
 		}
 	}
diff --git a/pallets/xcm-interface/Cargo.toml b/pallets/xcm-interface/Cargo.toml
index 821e63e22..4ee81ed99 100644
--- a/pallets/xcm-interface/Cargo.toml
+++ b/pallets/xcm-interface/Cargo.toml
@@ -22,6 +22,8 @@ bifrost-primitives = { workspace = true }
 bifrost-asset-registry = { workspace = true }
 
 [dev-dependencies]
+bifrost-currencies = { workspace = true }
+orml-tokens = { workspace = true }
 sp-io = { workspace = true }
 pallet-balances = { workspace = true }
 xcm-executor = { workspace = true }
@@ -43,9 +45,10 @@ std = [
 	"orml-traits/std",
 	"cumulus-primitives-core/std",
 	"bifrost-primitives/std",
+	"bifrost-asset-registry/std",
 ]
 runtime-benchmarks = [
-	"frame-benchmarking",
+	"frame-benchmarking/runtime-benchmarks",
 	"frame-support/runtime-benchmarks",
 	"frame-system/runtime-benchmarks",
 	"pallet-xcm/runtime-benchmarks",
diff --git a/pallets/xcm-interface/src/benchmarking.rs b/pallets/xcm-interface/src/benchmarking.rs
new file mode 100644
index 000000000..9e4e40261
--- /dev/null
+++ b/pallets/xcm-interface/src/benchmarking.rs
@@ -0,0 +1,43 @@
+// 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 <https://www.gnu.org/licenses/>.
+
+#![cfg(feature = "runtime-benchmarks")]
+use super::*;
+use bifrost_primitives::{XcmOperationType, BNC};
+use frame_benchmarking::v2::*;
+use frame_system::RawOrigin;
+
+#[benchmarks]
+mod benchmarks {
+	use super::*;
+
+	#[benchmark]
+	fn update_xcm_dest_weight_and_fee() {
+		let updates = vec![
+			(BNC, XcmOperationType::Bond, Weight::zero(), 0u32.into()),
+			(BNC, XcmOperationType::Bond, Weight::zero(), 0u32.into()),
+			(BNC, XcmOperationType::Bond, Weight::zero(), 0u32.into()),
+			(BNC, XcmOperationType::Bond, Weight::zero(), 0u32.into()),
+			(BNC, XcmOperationType::Bond, Weight::zero(), 0u32.into()),
+		];
+		#[extrinsic_call]
+		_(RawOrigin::Root, updates);
+	}
+
+	impl_benchmark_test_suite!(Pallet, mock::new_test_ext(), mock::Test);
+}
diff --git a/pallets/xcm-interface/src/calls.rs b/pallets/xcm-interface/src/calls.rs
index 8c1cbf002..fc9cc3152 100644
--- a/pallets/xcm-interface/src/calls.rs
+++ b/pallets/xcm-interface/src/calls.rs
@@ -16,28 +16,11 @@
 // You should have received a copy of the GNU General Public License
 // along with this program. If not, see <https://www.gnu.org/licenses/>.
 
-use frame_support::sp_runtime::MultiSignature;
 use parity_scale_codec::{Decode, Encode};
 use sp_runtime::RuntimeDebug;
-use sp_std::{boxed::Box, vec::Vec};
+use sp_std::boxed::Box;
 use xcm::{v4::WeightLimit, VersionedAssets, VersionedLocation};
 
-use crate::ChainId;
-
-#[derive(Encode, Decode, RuntimeDebug)]
-pub enum UtilityCall<RelayChainCall> {
-	#[codec(index = 1)]
-	AsDerivative(u16, RelayChainCall),
-	#[codec(index = 2)]
-	BatchAll(Vec<RelayChainCall>),
-}
-
-#[derive(Encode, Decode, RuntimeDebug)]
-pub enum StakingCall {
-	#[codec(index = 3)]
-	WithdrawUnbonded(u32),
-}
-
 #[derive(Encode, Decode, RuntimeDebug, Clone)]
 pub enum PolkadotXcmCall {
 	#[codec(index = 2)]
@@ -65,111 +48,14 @@ pub enum PolkadotXcmCall {
 	),
 }
 
-#[derive(Encode, Decode, RuntimeDebug, Clone)]
-pub enum SystemCall {
-	#[codec(index = 7)]
-	RemarkWithEvent(Vec<u8>),
-}
-
-pub mod kusama {
-
-	pub use crate::calls::*;
-
-	#[derive(Encode, Decode, RuntimeDebug)]
-	pub enum RelaychainCall<BalanceOf, AccountIdOf, BlockNumberOf> {
-		#[codec(index = 73)]
-		Crowdloan(ContributeCall<BalanceOf, AccountIdOf>),
-		#[codec(index = 30)]
-		Proxy(ProxyCall<AccountIdOf, BlockNumberOf>),
-	}
-
-	#[derive(Encode, Decode, RuntimeDebug)]
-	pub enum AssetHubCall {
-		#[codec(index = 31)]
-		PolkadotXcm(PolkadotXcmCall),
-	}
-}
-
-pub mod polkadot {
-	pub use crate::calls::*;
-
-	#[derive(Encode, Decode, RuntimeDebug)]
-	pub enum RelaychainCall<BalanceOf, AccountIdOf, BlockNumberOf> {
-		#[codec(index = 73)]
-		Crowdloan(ContributeCall<BalanceOf, AccountIdOf>),
-		#[codec(index = 29)]
-		Proxy(ProxyCall<AccountIdOf, BlockNumberOf>),
-		#[codec(index = 99)]
-		XcmPallet(PolkadotXcmCall),
-	}
-
-	#[derive(Encode, Decode, RuntimeDebug)]
-	pub enum AssetHubCall {
-		#[codec(index = 31)]
-		PolkadotXcm(PolkadotXcmCall),
-	}
-}
-
 #[derive(Encode, Decode, RuntimeDebug)]
-pub enum ContributeCall<BalanceOf, AccountIdOf> {
-	#[codec(index = 1)]
-	Contribute(Contribution<BalanceOf>),
-	#[codec(index = 2)]
-	Withdraw(Withdraw<AccountIdOf>),
-	#[codec(index = 6)]
-	AddMemo(AddMemo),
-}
-
-#[derive(PartialEq, Encode, Decode, RuntimeDebug)]
-pub struct Contribution<BalanceOf> {
-	#[codec(compact)]
-	pub index: ChainId,
-	#[codec(compact)]
-	pub value: BalanceOf,
-	pub signature: Option<MultiSignature>,
-}
-
-#[derive(PartialEq, Encode, Decode, RuntimeDebug)]
-pub struct Withdraw<AccountIdOf> {
-	pub who: AccountIdOf,
-	#[codec(compact)]
-	pub index: ChainId,
-}
-
-#[derive(PartialEq, Encode, Decode, RuntimeDebug)]
-pub struct AddMemo {
-	pub index: ChainId,
-	pub memo: Vec<u8>,
-}
-
-#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, RuntimeDebug)]
-pub enum ProxyType {
-	Any,
-	NonTransfer,
-	Governance,
-	Staking,
-	IdentityJudgement,
-	CancelProxy,
+pub enum RelaychainCall {
+	#[codec(index = 99)]
+	XcmPallet(PolkadotXcmCall),
 }
 
 #[derive(Encode, Decode, RuntimeDebug)]
-pub enum ProxyCall<AccountIdOf, BlockNumberOf> {
-	#[codec(index = 1)]
-	Add(AddProxy<AccountIdOf, BlockNumberOf>),
-	#[codec(index = 2)]
-	Remove(RemoveProxy<AccountIdOf, BlockNumberOf>),
-}
-
-#[derive(PartialEq, Encode, Decode, RuntimeDebug)]
-pub struct AddProxy<AccountIdOf, BlockNumberOf> {
-	pub delegate: AccountIdOf,
-	pub proxy_type: ProxyType,
-	pub delay: BlockNumberOf,
-}
-
-#[derive(PartialEq, Encode, Decode, RuntimeDebug)]
-pub struct RemoveProxy<AccountIdOf, BlockNumberOf> {
-	pub delegate: AccountIdOf,
-	pub proxy_type: ProxyType,
-	pub delay: BlockNumberOf,
+pub enum AssetHubCall {
+	#[codec(index = 31)]
+	PolkadotXcm(PolkadotXcmCall),
 }
diff --git a/pallets/xcm-interface/src/lib.rs b/pallets/xcm-interface/src/lib.rs
index ee096d51e..1a9b609ca 100644
--- a/pallets/xcm-interface/src/lib.rs
+++ b/pallets/xcm-interface/src/lib.rs
@@ -17,130 +17,93 @@
 // along with this program. If not, see <https://www.gnu.org/licenses/>.
 
 #![cfg_attr(not(feature = "std"), no_std)]
-#![allow(unused_imports)]
+
+#[cfg(feature = "runtime-benchmarks")]
+mod benchmarking;
 
 pub mod calls;
-pub mod traits;
+pub mod weights;
+pub use weights::WeightInfo;
+mod mock;
+mod tests;
+
+use crate::calls::{AssetHubCall, PolkadotXcmCall};
 use bifrost_asset_registry::AssetMetadata;
-use bifrost_primitives::{traits::XcmDestWeightAndFeeHandler, CurrencyIdMapping, XcmOperationType};
-pub use calls::*;
+use bifrost_primitives::{
+	traits::XcmDestWeightAndFeeHandler, AssetHubLocation, CurrencyId, CurrencyIdMapping,
+	EthereumLocation, XcmOperationType,
+};
+use cumulus_primitives_core::ParaId;
+use frame_support::pallet_prelude::*;
+use frame_system::pallet_prelude::*;
 use orml_traits::MultiCurrency;
 pub use pallet::*;
-use sp_runtime::traits::UniqueSaturatedInto;
-pub use traits::{ChainId, MessageId, Nonce, SalpHelper};
-
-macro_rules! use_relay {
-    ({ $( $code:tt )* }) => {
-        if T::RelayNetwork::get() == NetworkId::Polkadot {
-            use polkadot::RelaychainCall;
-            use polkadot::AssetHubCall;
-
-			$( $code )*
-        } else if T::RelayNetwork::get() == NetworkId::Kusama {
-            use kusama::RelaychainCall;
-            use kusama::AssetHubCall;
-
-			$( $code )*
-        } else {
-            unreachable!()
-        }
-    }
-}
-
-pub(crate) type AccountIdOf<T> = <T as frame_system::Config>::AccountId;
-
-pub type CurrencyIdOf<T> =
-	<<T as Config>::MultiCurrency as MultiCurrency<AccountIdOf<T>>>::CurrencyId;
-
-pub type BalanceOf<T> = <<T as Config>::MultiCurrency as MultiCurrency<AccountIdOf<T>>>::Balance;
+use sp_core::H160;
+use sp_runtime::traits::{Convert, UniqueSaturatedInto};
+use sp_std::{convert::From, prelude::*, vec, vec::Vec};
+use xcm::{
+	v4::{prelude::*, Asset, Location},
+	DoubleEncoded,
+};
+
+type BalanceOf<T> = <<T as Config>::MultiCurrency as MultiCurrency<
+	<T as frame_system::Config>::AccountId,
+>>::Balance;
 
 #[frame_support::pallet]
 pub mod pallet {
-	use cumulus_primitives_core::ParaId;
-	use frame_support::pallet_prelude::*;
-	use frame_system::pallet_prelude::*;
-	use orml_traits::{currency::TransferAll, MultiCurrency, MultiReservableCurrency};
-	use sp_runtime::{traits::Convert, DispatchError};
-	use sp_std::{convert::From, prelude::*, vec, vec::Vec};
-	use xcm::{
-		v4::{prelude::*, Asset, ExecuteXcm, Location},
-		DoubleEncoded, VersionedXcm,
-	};
-
 	use super::*;
-	use crate::traits::*;
 
 	#[pallet::config]
-	pub trait Config: frame_system::Config + pallet_xcm::Config {
+	pub trait Config: frame_system::Config {
 		type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
 
-		type MultiCurrency: TransferAll<AccountIdOf<Self>>
-			+ MultiCurrency<AccountIdOf<Self>>
-			+ MultiReservableCurrency<AccountIdOf<Self>>;
+		type MultiCurrency: MultiCurrency<Self::AccountId, CurrencyId = CurrencyId>;
+
+		// Weight information for extrinsics in this pallet.
+		type WeightInfo: WeightInfo;
 
 		/// Origin represented Governance
 		type UpdateOrigin: EnsureOrigin<<Self as frame_system::Config>::RuntimeOrigin>;
 
-		/// The currency id of the RelayChain
-		#[pallet::constant]
-		type RelaychainCurrencyId: Get<CurrencyIdOf<Self>>;
-
-		/// The account of parachain on the relaychain.
-		#[pallet::constant]
-		type ParachainSovereignAccount: Get<AccountIdOf<Self>>;
-
-		/// XCM executor.
-		type XcmExecutor: ExecuteXcm<<Self as frame_system::Config>::RuntimeCall>;
+		/// Xcm transfer interface
+		type XcmRouter: SendXcm;
 
 		/// Convert `T::AccountId` to `Location`.
-		type AccountIdToLocation: Convert<AccountIdOf<Self>, Location>;
-
-		/// Salp call encode
-		type SalpHelper: SalpHelper<
-			AccountIdOf<Self>,
-			<Self as pallet_xcm::Config>::RuntimeCall,
-			BalanceOf<Self>,
-		>;
+		type AccountIdToLocation: Convert<Self::AccountId, Location>;
 
 		/// Convert Location to `T::CurrencyId`.
 		type CurrencyIdConvert: CurrencyIdMapping<
-			CurrencyIdOf<Self>,
+			CurrencyId,
 			xcm::v3::MultiLocation,
 			AssetMetadata<BalanceOf<Self>>,
 		>;
 
-		#[pallet::constant]
-		type RelayNetwork: Get<NetworkId>;
-
 		#[pallet::constant]
 		type ParachainId: Get<ParaId>;
-
-		#[pallet::constant]
-		type CallBackTimeOut: Get<BlockNumberFor<Self>>;
 	}
 
 	#[pallet::error]
 	pub enum Error<T> {
-		FeeConvertFailed,
-		XcmExecutionFailed,
+		/// Failed to send XCM message.
 		XcmSendFailed,
+		/// The weight and fee for the operation does not exist.
 		OperationWeightAndFeeNotExist,
+		/// Failed to convert currency id.
 		FailToConvert,
+		/// The message is unweighable.
 		UnweighableMessage,
-		LocalExecutionIncomplete,
 	}
 
 	#[pallet::event]
 	#[pallet::generate_deposit(pub(crate) fn deposit_event)]
 	pub enum Event<T: Config> {
-		XcmDestWeightAndFeeUpdated(XcmOperationType, CurrencyIdOf<T>, Weight, BalanceOf<T>),
-		TransferredStatemineMultiAsset(AccountIdOf<T>, BalanceOf<T>),
-		TransferredEthereumAssets(AccountIdOf<T>, sp_core::H160, BalanceOf<T>),
+		XcmDestWeightAndFeeUpdated(XcmOperationType, CurrencyId, Weight, BalanceOf<T>),
+		TransferredEthereumAssets(T::AccountId, H160, BalanceOf<T>),
 	}
 
 	/// The current storage version, we set to 2 our new version(after migrate stroage
 	/// XcmWeightAndFee from SLP module).
-	#[allow(unused)]
 	const STORAGE_VERSION: StorageVersion = StorageVersion::new(2);
 
 	/// The dest weight limit and fee for execution XCM msg sent by XcmInterface. Must be
@@ -151,18 +114,13 @@ pub mod pallet {
 	pub type XcmWeightAndFee<T> = StorageDoubleMap<
 		_,
 		Blake2_128Concat,
-		CurrencyIdOf<T>,
+		CurrencyId,
 		Blake2_128Concat,
 		XcmOperationType,
 		(Weight, BalanceOf<T>),
 		OptionQuery,
 	>;
 
-	// Tracker for the next nonce index
-	#[pallet::storage]
-	pub(super) type CurrentNonce<T: Config> =
-		StorageMap<_, Blake2_128Concat, ChainId, Nonce, ValueQuery>;
-
 	#[pallet::pallet]
 	#[pallet::storage_version(STORAGE_VERSION)]
 	#[pallet::without_storage_info]
@@ -178,10 +136,10 @@ pub mod pallet {
 		/// Parameters:
 		/// - `updates`: vec of tuple: (XcmOperationType, WeightChange, FeeChange).
 		#[pallet::call_index(0)]
-		#[pallet::weight({16_690_000})]
+		#[pallet::weight(T::WeightInfo::update_xcm_dest_weight_and_fee())]
 		pub fn update_xcm_dest_weight_and_fee(
 			origin: OriginFor<T>,
-			updates: Vec<(CurrencyIdOf<T>, XcmOperationType, Weight, BalanceOf<T>)>,
+			updates: Vec<(CurrencyId, XcmOperationType, Weight, BalanceOf<T>)>,
 		) -> DispatchResult {
 			T::UpdateOrigin::ensure_origin(origin)?;
 
@@ -202,89 +160,14 @@ pub mod pallet {
 
 			Ok(())
 		}
-		#[pallet::call_index(1)]
-		#[pallet::weight({2_000_000_000})]
-		pub fn transfer_statemine_assets(
-			origin: OriginFor<T>,
-			amount: BalanceOf<T>,
-			asset_id: u32,
-			dest: Option<AccountIdOf<T>>,
-		) -> DispatchResult {
-			let who = ensure_signed(origin)?;
-			let dest = match dest {
-				Some(account) => account,
-				None => who.clone(),
-			};
-
-			let amount_u128 =
-				TryInto::<u128>::try_into(amount).map_err(|_| Error::<T>::FeeConvertFailed)?;
-
-			// get currency_id from asset_id
-			let asset_location = Location::new(
-				1,
-				[
-					Parachain(parachains::Statemine::ID),
-					PalletInstance(parachains::Statemine::PALLET_ID),
-					GeneralIndex(asset_id.into()),
-				],
-			);
-			let currency_id = T::CurrencyIdConvert::get_currency_id(asset_location)
-				.ok_or(Error::<T>::FailToConvert)?;
-
-			// first, we need to withdraw the statemine asset from the user's account
-			T::MultiCurrency::withdraw(currency_id, &who, amount)?;
-
-			let dst_location = T::AccountIdToLocation::convert(dest.clone());
-
-			let (dest_weight, xcm_fee) = XcmWeightAndFee::<T>::get(
-				T::RelaychainCurrencyId::get(),
-				XcmOperationType::StatemineTransfer,
-			)
-			.ok_or(Error::<T>::OperationWeightAndFeeNotExist)?;
-
-			let xcm_fee_u128 =
-				TryInto::<u128>::try_into(xcm_fee).map_err(|_| Error::<T>::FeeConvertFailed)?;
-
-			let mut assets = Assets::new();
-			let statemine_asset = Asset {
-				id: AssetId(Location::new(
-					0,
-					[
-						PalletInstance(parachains::Statemine::PALLET_ID),
-						GeneralIndex(asset_id.into()),
-					],
-				)),
-				fun: Fungible(amount_u128),
-			};
-			let fee_asset =
-				Asset { id: AssetId(Location::new(1, Here)), fun: Fungible(xcm_fee_u128) };
-			assets.push(statemine_asset.clone());
-			assets.push(fee_asset.clone());
-			let msg = Xcm(vec![
-				WithdrawAsset(assets),
-				BuyExecution { fees: fee_asset, weight_limit: Limited(dest_weight) },
-				DepositAsset { assets: AllCounted(2).into(), beneficiary: dst_location },
-			]);
-
-			pallet_xcm::Pallet::<T>::send_xcm(
-				Here,
-				Location::new(1, Parachain(parachains::Statemine::ID)),
-				msg,
-			)
-			.map_err(|_| Error::<T>::XcmExecutionFailed)?;
-
-			Self::deposit_event(Event::<T>::TransferredStatemineMultiAsset(dest, amount));
-
-			Ok(())
-		}
 
 		#[pallet::call_index(2)]
 		#[pallet::weight({2_000_000_000})]
 		pub fn transfer_ethereum_assets(
 			origin: OriginFor<T>,
-			currency_id: CurrencyIdOf<T>,
+			currency_id: CurrencyId,
 			amount: BalanceOf<T>,
-			to: sp_core::H160,
+			to: H160,
 		) -> DispatchResult {
 			let who = ensure_signed(origin.clone())?;
 			let asset_location =
@@ -306,9 +189,9 @@ pub mod pallet {
 
 			T::MultiCurrency::withdraw(currency_id, &who, amount)?;
 
-			let remote_call: DoubleEncoded<()> = use_relay!({
+			let remote_call: DoubleEncoded<()> =
 				AssetHubCall::PolkadotXcm(PolkadotXcmCall::LimitedReserveTransferAssets(
-					Box::new(Location::new(2, [GlobalConsensus(Ethereum { chain_id: 1 })]).into()),
+					Box::new(EthereumLocation::get().into()),
 					Box::new(
 						Location::new(
 							0,
@@ -321,8 +204,7 @@ pub mod pallet {
 					Unlimited,
 				))
 				.encode()
-				.into()
-			});
+				.into();
 
 			let remote_xcm = Xcm(vec![
 				WithdrawAsset(fee.clone().into()),
@@ -332,73 +214,31 @@ pub mod pallet {
 					require_weight_at_most,
 					call: remote_call,
 				},
+				RefundSurplus,
 				DepositAsset {
 					assets: All.into(),
 					beneficiary: Location::new(1, [Parachain(T::ParachainId::get().into())]),
 				},
 			]);
-			let (ticket, _) = <T as pallet_xcm::Config>::XcmRouter::validate(
-				&mut Some(Location::new(1, [Parachain(parachains::Statemine::ID)])),
-				&mut Some(remote_xcm),
-			)
-			.map_err(|_| Error::<T>::UnweighableMessage)?;
-			<T as pallet_xcm::Config>::XcmRouter::deliver(ticket)
-				.map_err(|_| Error::<T>::XcmExecutionFailed)?;
+			let (ticket, _) =
+				T::XcmRouter::validate(&mut Some(AssetHubLocation::get()), &mut Some(remote_xcm))
+					.map_err(|_| Error::<T>::UnweighableMessage)?;
+			T::XcmRouter::deliver(ticket).map_err(|_| Error::<T>::XcmSendFailed)?;
 			Self::deposit_event(Event::<T>::TransferredEthereumAssets(who, to, amount));
 			Ok(())
 		}
 	}
 
-	impl<T: Config> XcmHelper<AccountIdOf<T>, BalanceOf<T>> for Pallet<T> {
-		fn contribute(
-			contributor: AccountIdOf<T>,
-			index: ChainId,
-			amount: BalanceOf<T>,
-		) -> Result<MessageId, DispatchError> {
-			// Construct contribute call data
-			let contribute_call = Self::build_ump_crowdloan_contribute(index, amount);
-			let (dest_weight, xcm_fee) = XcmWeightAndFee::<T>::get(
-				T::RelaychainCurrencyId::get(),
-				XcmOperationType::UmpContributeTransact,
-			)
-			.ok_or(Error::<T>::OperationWeightAndFeeNotExist)?;
-
-			// Construct confirm_contribute_call
-			let confirm_contribute_call = T::SalpHelper::confirm_contribute_call();
-			// Generate query_id
-			let query_id = pallet_xcm::Pallet::<T>::new_notify_query(
-				Location::parent(),
-				confirm_contribute_call,
-				T::CallBackTimeOut::get(),
-				xcm::v4::Junctions::Here,
-			);
-
-			// Bind query_id and contribution
-			T::SalpHelper::bind_query_id_and_contribution(query_id, index, contributor, amount);
-
-			let (msg_id, msg) =
-				Self::build_ump_transact(query_id, contribute_call, dest_weight, xcm_fee)?;
-
-			let result = pallet_xcm::Pallet::<T>::send_xcm(
-				xcm::v4::Junctions::Here,
-				xcm::v4::Parent,
-				xcm::v4::Xcm::try_from(msg).unwrap(),
-			);
-			ensure!(result.is_ok(), Error::<T>::XcmSendFailed);
-			Ok(msg_id)
-		}
-	}
-
-	impl<T: Config> XcmDestWeightAndFeeHandler<CurrencyIdOf<T>, BalanceOf<T>> for Pallet<T> {
+	impl<T: Config> XcmDestWeightAndFeeHandler<CurrencyId, BalanceOf<T>> for Pallet<T> {
 		fn get_operation_weight_and_fee(
-			token: CurrencyIdOf<T>,
+			token: CurrencyId,
 			operation: XcmOperationType,
 		) -> Option<(Weight, BalanceOf<T>)> {
 			XcmWeightAndFee::<T>::get(token, operation)
 		}
 
 		fn set_xcm_dest_weight_and_fee(
-			currency_id: CurrencyIdOf<T>,
+			currency_id: CurrencyId,
 			operation: XcmOperationType,
 			weight_and_fee: Option<(Weight, BalanceOf<T>)>,
 		) -> DispatchResult {
@@ -411,58 +251,4 @@ pub mod pallet {
 			Ok(())
 		}
 	}
-
-	impl<T: Config> Pallet<T> {
-		pub(crate) fn transact_id(data: &[u8]) -> MessageId {
-			return sp_io::hashing::blake2_256(data);
-		}
-
-		pub(crate) fn build_ump_transact(
-			query_id: QueryId,
-			call: DoubleEncoded<()>,
-			weight: Weight,
-			fee: BalanceOf<T>,
-		) -> Result<(MessageId, Xcm<()>), Error<T>> {
-			let sovereign_account: AccountIdOf<T> = T::ParachainSovereignAccount::get();
-			let sovereign_location: Location = T::AccountIdToLocation::convert(sovereign_account);
-			let fee_amount =
-				TryInto::<u128>::try_into(fee).map_err(|_| Error::<T>::FeeConvertFailed)?;
-			let asset: Asset =
-				Asset { id: AssetId(Location::here()), fun: Fungibility::from(fee_amount) };
-			let message = Xcm(vec![
-				WithdrawAsset(asset.clone().into()),
-				BuyExecution { fees: asset, weight_limit: Unlimited },
-				Transact {
-					origin_kind: OriginKind::SovereignAccount,
-					require_weight_at_most: weight,
-					call,
-				},
-				ReportTransactStatus(QueryResponseInfo {
-					destination: Location::from([Parachain(u32::from(T::ParachainId::get()))]),
-					query_id,
-					max_weight: weight,
-				}),
-				RefundSurplus,
-				DepositAsset { assets: AllCounted(1).into(), beneficiary: sovereign_location },
-			]);
-			let data = VersionedXcm::<()>::from(message.clone()).encode();
-			let id = Self::transact_id(&data[..]);
-			Ok((id, message))
-		}
-
-		pub(crate) fn build_ump_crowdloan_contribute(
-			index: ChainId,
-			value: BalanceOf<T>,
-		) -> DoubleEncoded<()> {
-			use_relay!({
-				let contribute_call =
-					RelaychainCall::Crowdloan::<BalanceOf<T>, AccountIdOf<T>, BlockNumberFor<T>>(
-						ContributeCall::Contribute(Contribution { index, value, signature: None }),
-					)
-					.encode()
-					.into();
-				contribute_call
-			})
-		}
-	}
 }
diff --git a/pallets/xcm-interface/src/mock.rs b/pallets/xcm-interface/src/mock.rs
new file mode 100644
index 000000000..34c94cfcf
--- /dev/null
+++ b/pallets/xcm-interface/src/mock.rs
@@ -0,0 +1,157 @@
+// 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 <https://www.gnu.org/licenses/>.
+
+#![cfg(test)]
+
+use crate as xcm_interface;
+use bifrost_asset_registry::AssetIdMaps;
+use bifrost_primitives::{Amount, Balance, BlockNumber, CurrencyId, MockXcmRouter, BNC};
+use cumulus_primitives_core::ParaId;
+use frame_support::{
+	__private::Get,
+	derive_impl, parameter_types,
+	traits::{Everything, Nothing},
+};
+use frame_system as system;
+use frame_system::EnsureRoot;
+use sp_core::{crypto::AccountId32, ConstU32, H256};
+use sp_runtime::{
+	traits::{BlakeTwo256, IdentityLookup},
+	BuildStorage,
+};
+
+pub type AccountId = AccountId32;
+type Block = frame_system::mocking::MockBlock<Test>;
+
+// Configure a mock runtime to test the pallet.
+frame_support::construct_runtime!(
+	pub enum Test
+	{
+		System: frame_system,
+		XcmInterface: xcm_interface,
+		Balances: pallet_balances,
+		Currencies: bifrost_currencies,
+		Tokens: orml_tokens,
+		AssetRegistry: bifrost_asset_registry,
+	}
+);
+
+parameter_types! {
+	pub const SS58Prefix: u8 = 42;
+}
+
+#[derive_impl(frame_system::config_preludes::TestDefaultConfig)]
+impl system::Config for Test {
+	type BaseCallFilter = Everything;
+	type RuntimeOrigin = RuntimeOrigin;
+	type RuntimeCall = RuntimeCall;
+	type Nonce = u64;
+	type Hash = H256;
+	type Hashing = BlakeTwo256;
+	type AccountId = AccountId;
+	type AccountData = pallet_balances::AccountData<Balance>;
+	type Lookup = IdentityLookup<Self::AccountId>;
+	type Block = Block;
+	type RuntimeEvent = RuntimeEvent;
+	type PalletInfo = PalletInfo;
+	type SS58Prefix = SS58Prefix;
+	type MaxConsumers = frame_support::traits::ConstU32<16>;
+}
+
+orml_traits::parameter_type_with_key! {
+	pub ExistentialDeposits: |_currency_id: CurrencyId| -> Balance {
+		0
+	};
+}
+impl orml_tokens::Config for Test {
+	type Amount = i128;
+	type Balance = Balance;
+	type CurrencyId = CurrencyId;
+	type DustRemovalWhitelist = Nothing;
+	type RuntimeEvent = RuntimeEvent;
+	type ExistentialDeposits = ExistentialDeposits;
+	type MaxLocks = ();
+	type MaxReserves = ();
+	type ReserveIdentifier = [u8; 8];
+	type WeightInfo = ();
+	type CurrencyHooks = ();
+}
+
+parameter_types! {
+	pub const ExistentialDeposit: Balance = 1;
+}
+
+impl pallet_balances::Config for Test {
+	type AccountStore = System;
+	type Balance = Balance;
+	type DustRemoval = ();
+	type RuntimeEvent = RuntimeEvent;
+	type ExistentialDeposit = ExistentialDeposit;
+	type MaxLocks = ();
+	type MaxReserves = ();
+	type ReserveIdentifier = [u8; 8];
+	type WeightInfo = ();
+	type RuntimeHoldReason = RuntimeHoldReason;
+	type RuntimeFreezeReason = RuntimeFreezeReason;
+	type FreezeIdentifier = ();
+	type MaxFreezes = ConstU32<0>;
+}
+
+impl bifrost_asset_registry::Config for Test {
+	type RuntimeEvent = RuntimeEvent;
+	type Currency = Balances;
+	type RegisterOrigin = EnsureRoot<AccountId>;
+	type WeightInfo = ();
+}
+
+parameter_types! {
+	pub const NativeCurrencyId: CurrencyId = BNC;
+}
+
+pub type AdaptedBasicCurrency =
+	bifrost_currencies::BasicCurrencyAdapter<Test, Balances, Amount, BlockNumber>;
+
+impl bifrost_currencies::Config for Test {
+	type GetNativeCurrencyId = NativeCurrencyId;
+	type MultiCurrency = Tokens;
+	type NativeCurrency = AdaptedBasicCurrency;
+	type WeightInfo = ();
+}
+
+pub struct ParachainId;
+impl Get<ParaId> for ParachainId {
+	fn get() -> ParaId {
+		2030.into()
+	}
+}
+
+impl xcm_interface::Config for Test {
+	type RuntimeEvent = RuntimeEvent;
+	type MultiCurrency = Currencies;
+	type WeightInfo = ();
+	type UpdateOrigin = EnsureRoot<AccountId>;
+	type XcmRouter = MockXcmRouter;
+	type AccountIdToLocation = ();
+	type CurrencyIdConvert = AssetIdMaps<Test>;
+	type ParachainId = ParachainId;
+}
+
+// Build genesis storage according to the mock runtime.
+pub fn new_test_ext() -> sp_io::TestExternalities {
+	system::GenesisConfig::<Test>::default().build_storage().unwrap().into()
+}
diff --git a/pallets/xcm-interface/src/tests.rs b/pallets/xcm-interface/src/tests.rs
new file mode 100644
index 000000000..ec3d2a54c
--- /dev/null
+++ b/pallets/xcm-interface/src/tests.rs
@@ -0,0 +1,50 @@
+// 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 <https://www.gnu.org/licenses/>.
+
+#![cfg(test)]
+
+use crate::{
+	mock::{new_test_ext, RuntimeOrigin, Test},
+	Pallet as XcmInterface, XcmWeightAndFee,
+};
+use bifrost_primitives::{XcmOperationType, BNC};
+use frame_support::assert_ok;
+use xcm::v4::Weight;
+
+#[test]
+fn update_xcm_dest_weight_and_fee() {
+	new_test_ext().execute_with(|| {
+		let updates = vec![
+			(BNC, XcmOperationType::Bond, Weight::zero(), 0u128),
+			(BNC, XcmOperationType::Bond, Weight::zero(), 0u128),
+			(BNC, XcmOperationType::Bond, Weight::zero(), 0u128),
+			(BNC, XcmOperationType::Bond, Weight::zero(), 0u128),
+			(BNC, XcmOperationType::Bond, Weight::zero(), 0u128),
+		];
+
+		assert_ok!(XcmInterface::<Test>::update_xcm_dest_weight_and_fee(
+			RuntimeOrigin::root(),
+			updates
+		));
+
+		assert_eq!(
+			XcmWeightAndFee::<Test>::get(BNC, XcmOperationType::Bond),
+			Some((Weight::zero(), 0u128))
+		);
+	})
+}
diff --git a/pallets/xcm-interface/src/traits.rs b/pallets/xcm-interface/src/traits.rs
deleted file mode 100644
index 190dedf12..000000000
--- a/pallets/xcm-interface/src/traits.rs
+++ /dev/null
@@ -1,159 +0,0 @@
-// 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 <https://www.gnu.org/licenses/>.
-
-use core::ops::{Add, Mul};
-
-use parity_scale_codec::{Decode, Encode};
-use scale_info::TypeInfo;
-use sp_runtime::DispatchError;
-use sp_std::prelude::*;
-use xcm::v3::QueryId;
-
-pub type MessageId = [u8; 32];
-
-pub type ChainId = u32;
-
-pub type Nonce = u32;
-
-/// The type used to represent the xcmp transfer direction
-#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo)]
-pub enum TransferOriginType {
-	FromSelf = 0,
-	FromRelayChain = 1,
-	FromSiblingParaChain = 2,
-}
-
-pub struct XcmBaseWeight(u64);
-
-impl XcmBaseWeight {
-	pub fn new(x: u64) -> Self {
-		XcmBaseWeight(x)
-	}
-}
-
-impl From<u64> for XcmBaseWeight {
-	fn from(u: u64) -> Self {
-		XcmBaseWeight(u)
-	}
-}
-
-impl From<XcmBaseWeight> for u64 {
-	fn from(x: XcmBaseWeight) -> Self {
-		x.0.into()
-	}
-}
-
-impl Add for XcmBaseWeight {
-	type Output = Self;
-	fn add(self, other: Self) -> Self::Output {
-		(self.0 + other.0).into()
-	}
-}
-
-impl Mul<u64> for XcmBaseWeight {
-	type Output = Self;
-
-	fn mul(self, rhs: u64) -> Self {
-		XcmBaseWeight::new(self.0 * rhs)
-	}
-}
-
-/// represent the transact type
-#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo)]
-pub enum ParachainTransactType {
-	Xcm = 0,
-	Proxy = 1,
-}
-
-/// represent the proxy type
-#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo)]
-pub enum ParachainTransactProxyType {
-	Primary = 0,
-	Derived = 1,
-}
-
-/// represent the derived proxy account type
-#[repr(u16)]
-pub enum ParachainDerivedProxyAccountType {
-	Salp = 0,
-	Staking = 1,
-}
-
-#[allow(non_snake_case)]
-pub mod parachains {
-	// *********************
-	// Kusama parachains**
-	// *********************
-
-	pub mod karura {
-		pub const ID: u32 = 2000;
-		pub const KAR_KEY: &[u8] = &[0, 128];
-		pub const KUSD_KEY: &[u8] = &[0, 129];
-	}
-
-	pub mod Statemine {
-		pub const ID: u32 = 1000;
-		pub const PALLET_ID: u8 = 50;
-		pub const RMRK_ID: u32 = 8;
-	}
-
-	pub mod phala {
-		pub const ID: u32 = 2004;
-	}
-
-	pub mod moonriver {
-		pub const ID: u32 = 2023;
-		pub const PALLET_ID: u8 = 10;
-	}
-
-	//*********************
-	// Polkadot parachains
-	//*********************
-	pub mod moonbeam {
-		pub const ID: u32 = 2004;
-		pub const PALLET_ID: u8 = 10;
-	}
-
-	pub mod astar {
-		pub const ID: u32 = 2006;
-		pub const PALLET_ID: u8 = 34;
-	}
-
-	pub mod manta {
-		pub const ID: u32 = 2104;
-		pub const PALLET_ID: u8 = 10;
-	}
-}
-
-pub trait XcmHelper<AccountId, Balance> {
-	fn contribute(
-		contributer: AccountId,
-		index: ChainId,
-		value: Balance,
-	) -> Result<MessageId, DispatchError>;
-}
-
-pub trait SalpHelper<AccountId, RuntimeCall, Balance> {
-	fn confirm_contribute_call() -> RuntimeCall;
-	fn bind_query_id_and_contribution(
-		query_id: QueryId,
-		index: ChainId,
-		contributer: AccountId,
-		amount: Balance,
-	);
-}
diff --git a/pallets/xcm-interface/src/weights.rs b/pallets/xcm-interface/src/weights.rs
new file mode 100644
index 000000000..a37027c90
--- /dev/null
+++ b/pallets/xcm-interface/src/weights.rs
@@ -0,0 +1,82 @@
+// 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 <https://www.gnu.org/licenses/>.
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! Autogenerated weights for bifrost_xcm_interface
+//!
+//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
+//! DATE: 2024-09-24, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! HOSTNAME: `bifrost-jenkins`, CPU: `Intel(R) Xeon(R) CPU E5-26xx v4`
+//! WASM-EXECUTION: Compiled, CHAIN: Some("bifrost-polkadot-local"), DB CACHE: 1024
+
+// Executed Command:
+// ./target/release/bifrost
+// benchmark
+// pallet
+// --chain=bifrost-polkadot-local
+// --steps=50
+// --repeat=20
+// --pallet=bifrost_xcm_interface
+// --extrinsic=*
+// --execution=wasm
+// --wasm-execution=compiled
+// --heap-pages=4096
+// --header=./HEADER-GPL3
+// --output=./weight.rs
+// --template
+// ./weight-template/pallet-weight-template.hbs
+
+#![cfg_attr(rustfmt, rustfmt_skip)]
+#![allow(unused_parens)]
+#![allow(unused_imports)]
+
+use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
+use sp_std::marker::PhantomData;
+
+/// Weight functions needed for bifrost_xcm_interface.
+pub trait WeightInfo {
+    fn update_xcm_dest_weight_and_fee() -> Weight;
+}
+
+// For backwards compatibility and tests
+impl WeightInfo for () {
+    /// Storage: `XcmInterface::XcmWeightAndFee` (r:1 w:1)
+    /// Proof: `XcmInterface::XcmWeightAndFee` (`max_values`: None, `max_size`: None, mode: `Measured`)
+    /// Storage: `System::Number` (r:1 w:0)
+    /// Proof: `System::Number` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
+    /// Storage: `System::ExecutionPhase` (r:1 w:0)
+    /// Proof: `System::ExecutionPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `MaxEncodedLen`)
+    /// Storage: `System::EventCount` (r:1 w:1)
+    /// Proof: `System::EventCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
+    /// Storage: `System::Events` (r:1 w:1)
+    /// Proof: `System::Events` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
+    fn update_xcm_dest_weight_and_fee() -> Weight {
+        // Proof Size summary in bytes:
+        //  Measured:  `134`
+        //  Estimated: `3599`
+        // Minimum execution time: 58_775_000 picoseconds.
+        Weight::from_parts(60_153_000, 3599)
+            .saturating_add(RocksDbWeight::get().reads(5_u64))
+            .saturating_add(RocksDbWeight::get().writes(3_u64))
+    }
+}
\ No newline at end of file
diff --git a/primitives/src/xcm.rs b/primitives/src/xcm.rs
index dd3a742ac..b6d59929c 100644
--- a/primitives/src/xcm.rs
+++ b/primitives/src/xcm.rs
@@ -41,6 +41,8 @@ parameter_types! {
 	pub const MantaChainId: u32 = 2104;
 	pub const MoonbeamChainId: u32 = 2004;
 	pub const MoonriverChainId: u32 = 2023;
+	pub const PhalaChainId: u32 = 2035;
+	pub const KaruraChainId: u32 = 2000;
 	pub const EthereumChainId: u64 = 1;
 }
 
diff --git a/runtime/bifrost-kusama/Cargo.toml b/runtime/bifrost-kusama/Cargo.toml
index 0f18e7357..2d123a6fa 100644
--- a/runtime/bifrost-kusama/Cargo.toml
+++ b/runtime/bifrost-kusama/Cargo.toml
@@ -322,6 +322,7 @@ runtime-benchmarks = [
 	"bifrost-slpx/runtime-benchmarks",
 	"bifrost-stable-pool/runtime-benchmarks",
 	"bifrost-vtoken-voting/runtime-benchmarks",
+	"bifrost-xcm-interface/runtime-benchmarks",
 	"lend-market/runtime-benchmarks",
 	"leverage-staking/runtime-benchmarks",
 	"bifrost-channel-commission/runtime-benchmarks",
diff --git a/runtime/bifrost-kusama/src/lib.rs b/runtime/bifrost-kusama/src/lib.rs
index 0e5bf5da9..b5820a869 100644
--- a/runtime/bifrost-kusama/src/lib.rs
+++ b/runtime/bifrost-kusama/src/lib.rs
@@ -128,8 +128,8 @@ use pallet_xcm::{EnsureResponse, QueryStatus};
 use sp_runtime::traits::{IdentityLookup, Verify};
 use xcm::{v3::MultiLocation, v4::prelude::*};
 pub use xcm_config::{
-	parachains, AccountId32Aliases, BifrostTreasuryAccount, ExistentialDeposits, MultiCurrency,
-	Sibling, SiblingParachainConvertsVia, XcmConfig, XcmRouter,
+	AccountId32Aliases, BifrostTreasuryAccount, ExistentialDeposits, MultiCurrency, Sibling,
+	SiblingParachainConvertsVia, XcmConfig, XcmRouter,
 };
 use xcm_executor::{traits::QueryHandler, XcmExecutor};
 
@@ -1053,7 +1053,7 @@ pub fn create_x2_multilocation(index: u16, currency_id: CurrencyId) -> xcm::v3::
 		CurrencyId::Token(TokenSymbol::MOVR) => xcm::v3::Location::new(
 			1,
 			xcm::v3::Junctions::X2(
-				xcm::v3::Junction::Parachain(parachains::moonriver::ID.into()),
+				xcm::v3::Junction::Parachain(MoonriverChainId::get()),
 				xcm::v3::Junction::AccountKey20 {
 					network: None,
 					key: Slp::derivative_account_id_20(
@@ -1162,7 +1162,6 @@ impl bifrost_salp::Config for Runtime {
 	type VSBondValidPeriod = VSBondValidPeriod;
 	type WeightInfo = weights::bifrost_salp::BifrostWeight<Runtime>;
 	type EnsureConfirmAsGovernance = EitherOfDiverse<TechAdminOrCouncil, SALPAdmin>;
-	type XcmInterface = XcmInterface;
 	type TreasuryAccount = BifrostTreasuryAccount;
 	type BuybackPalletId = BuybackPalletId;
 	type CurrencyIdConversion = AssetIdMaps<Runtime>;
@@ -1960,7 +1959,6 @@ mod benches {
 		[bifrost_farming, Farming]
 		[bifrost_fee_share, FeeShare]
 		[bifrost_flexible_fee, FlexibleFee]
-		[bifrost_salp, Salp]
 		[bifrost_slp, Slp]
 		[bifrost_slpx, Slpx]
 		[bifrost_stable_pool, StablePool]
@@ -1973,6 +1971,7 @@ mod benches {
 		[lend_market, LendMarket]
 		[leverage_staking, LeverageStaking]
 		[bifrost_vbnc_convert, VBNCConvert]
+		[bifrost_xcm_interface, XcmInterface]
 		// [bifrost_channel_commission, ChannelCommission]
 	);
 }
diff --git a/runtime/bifrost-kusama/src/migration.rs b/runtime/bifrost-kusama/src/migration.rs
index 0f9cc76bb..c6209c79c 100644
--- a/runtime/bifrost-kusama/src/migration.rs
+++ b/runtime/bifrost-kusama/src/migration.rs
@@ -376,7 +376,6 @@ pub mod system_maker {
 	pub use bifrost_primitives::currency::{KSM, VKSM};
 	use frame_support::{pallet_prelude::PhantomData, traits::OnRuntimeUpgrade};
 	use sp_core::Get;
-	use sp_runtime::traits::Zero;
 	pub struct SystemMakerClearPalletId<T>(PhantomData<T>);
 	impl<T: bifrost_vtoken_minting::Config> OnRuntimeUpgrade for SystemMakerClearPalletId<T> {
 		#[cfg(feature = "try-runtime")]
@@ -418,8 +417,6 @@ pub mod system_maker {
 
 		#[cfg(feature = "try-runtime")]
 		fn post_upgrade(_: sp_std::prelude::Vec<u8>) -> Result<(), sp_runtime::DispatchError> {
-			#[allow(unused_imports)]
-			use frame_support::PalletId;
 			log::info!("Bifrost `post_upgrade`...");
 			let account_id = SystemMakerPalletId::get().into_account_truncating();
 			let ksm_balance = T::MultiCurrency::free_balance(KSM, &account_id);
diff --git a/runtime/bifrost-kusama/src/weights/bifrost_xcm_interface.rs b/runtime/bifrost-kusama/src/weights/bifrost_xcm_interface.rs
new file mode 100644
index 000000000..1682d2414
--- /dev/null
+++ b/runtime/bifrost-kusama/src/weights/bifrost_xcm_interface.rs
@@ -0,0 +1,78 @@
+// 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 <https://www.gnu.org/licenses/>.
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! Autogenerated weights for bifrost_xcm_interface
+//!
+//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
+//! DATE: 2024-09-24, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! HOSTNAME: `bifrost-jenkins`, CPU: `Intel(R) Xeon(R) CPU E5-26xx v4`
+//! WASM-EXECUTION: Compiled, CHAIN: Some("bifrost-polkadot-local"), DB CACHE: 1024
+
+// Executed Command:
+// ./target/release/bifrost
+// benchmark
+// pallet
+// --chain=bifrost-polkadot-local
+// --steps=50
+// --repeat=20
+// --pallet=bifrost_xcm_interface
+// --extrinsic=*
+// --execution=wasm
+// --wasm-execution=compiled
+// --heap-pages=4096
+// --header=./HEADER-GPL3
+// --output=./weight.rs
+// --template
+// ./weight-template/runtime-weight-template.hbs
+
+#![cfg_attr(rustfmt, rustfmt_skip)]
+#![allow(unused_parens)]
+#![allow(unused_imports)]
+
+use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
+use sp_std::marker::PhantomData;
+
+/// Weight functions for bifrost_xcm_interface.
+pub struct BifrostWeight<T>(PhantomData<T>);
+impl<T: frame_system::Config> bifrost_xcm_interface::WeightInfo for BifrostWeight<T> {
+    // Storage: `XcmInterface::XcmWeightAndFee` (r:1 w:1)
+    // Proof: `XcmInterface::XcmWeightAndFee` (`max_values`: None, `max_size`: None, mode: `Measured`)
+    // Storage: `System::Number` (r:1 w:0)
+    // Proof: `System::Number` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
+    // Storage: `System::ExecutionPhase` (r:1 w:0)
+    // Proof: `System::ExecutionPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `MaxEncodedLen`)
+    // Storage: `System::EventCount` (r:1 w:1)
+    // Proof: `System::EventCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
+    // Storage: `System::Events` (r:1 w:1)
+    // Proof: `System::Events` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
+    fn update_xcm_dest_weight_and_fee() -> Weight {
+        // Proof Size summary in bytes:
+        //  Measured:  `134`
+        //  Estimated: `3599`
+        // Minimum execution time: 56_793 nanoseconds.
+        Weight::from_parts(58_130_000, 3599)
+            .saturating_add(T::DbWeight::get().reads(5))
+            .saturating_add(T::DbWeight::get().writes(3))
+    }
+}
\ No newline at end of file
diff --git a/runtime/bifrost-kusama/src/weights/mod.rs b/runtime/bifrost-kusama/src/weights/mod.rs
index 41bea25e1..5de22ec76 100644
--- a/runtime/bifrost-kusama/src/weights/mod.rs
+++ b/runtime/bifrost-kusama/src/weights/mod.rs
@@ -40,6 +40,7 @@ pub mod bifrost_vsbond_auction;
 pub mod bifrost_vstoken_conversion;
 pub mod bifrost_vtoken_minting;
 pub mod bifrost_vtoken_voting;
+pub mod bifrost_xcm_interface;
 pub mod orml_oracle;
 pub mod orml_tokens;
 pub mod pallet_xcm;
diff --git a/runtime/bifrost-kusama/src/xcm_config.rs b/runtime/bifrost-kusama/src/xcm_config.rs
index 612f2366c..8222f6b28 100644
--- a/runtime/bifrost-kusama/src/xcm_config.rs
+++ b/runtime/bifrost-kusama/src/xcm_config.rs
@@ -19,11 +19,10 @@
 use super::*;
 use bifrost_asset_registry::{AssetIdMaps, FixedRateOfAsset};
 use bifrost_primitives::{
-	AccountId, AccountIdToLocation, AssetHubLocation, AssetPrefixFrom, CurrencyId,
-	CurrencyIdMapping, EthereumLocation, KusamaNetwork, KusamaUniversalLocation, NativeAssetFrom,
-	SelfLocation, TokenSymbol,
+	AccountId, AccountIdToLocation, AssetHubChainId, AssetHubLocation, AssetPrefixFrom, CurrencyId,
+	CurrencyIdMapping, EthereumLocation, KaruraChainId, KusamaNetwork, KusamaUniversalLocation,
+	NativeAssetFrom, PhalaChainId, SelfLocation, TokenSymbol,
 };
-pub use bifrost_xcm_interface::traits::{parachains, XcmBaseWeight};
 pub use cumulus_primitives_core::ParaId;
 use frame_support::{parameter_types, sp_runtime::traits::Convert, traits::Get};
 use parity_scale_codec::Encode;
@@ -206,7 +205,7 @@ parameter_types! {
 	pub KarPerSecond: (AssetId, u128,u128) = (
 		Location::new(
 			1,
-			[Parachain(parachains::karura::ID), Junction::from(BoundedVec::try_from(parachains::karura::KAR_KEY.to_vec()).unwrap())]
+			[Parachain(KaruraChainId::get()), Junction::from(BoundedVec::try_from(vec![0,128u8]).unwrap())]
 		).into(),
 		// KAR:KSM = 100:1
 		ksm_per_second::<Runtime>() * 100,
@@ -215,7 +214,7 @@ parameter_types! {
 	pub KusdPerSecond: (AssetId, u128,u128) = (
 		Location::new(
 			1,
-			[Parachain(parachains::karura::ID), Junction::from(BoundedVec::try_from(parachains::karura::KUSD_KEY.to_vec()).unwrap())]
+			[Parachain(KaruraChainId::get()), Junction::from(BoundedVec::try_from(vec![0,129u8]).unwrap())]
 		).into(),
 		// kUSD:KSM = 400:1
 		ksm_per_second::<Runtime>() * 400,
@@ -224,7 +223,7 @@ parameter_types! {
 	pub PhaPerSecond: (AssetId, u128,u128) = (
 		Location::new(
 			1,
-			[Parachain(parachains::phala::ID)],
+			[Parachain(PhalaChainId::get())],
 		).into(),
 		// PHA:KSM = 400:1
 		ksm_per_second::<Runtime>() * 400,
@@ -233,7 +232,7 @@ parameter_types! {
 	pub RmrkPerSecond: (AssetId, u128,u128) = (
 		Location::new(
 			1,
-			[Parachain(parachains::Statemine::ID), GeneralIndex(parachains::Statemine::RMRK_ID.into())]
+			[Parachain(AssetHubChainId::get()), GeneralIndex(50)]
 		).into(),
 		// rmrk:KSM = 10:1
 		ksm_per_second::<Runtime>() * 10 / 100, //rmrk currency decimal as 10
@@ -242,7 +241,7 @@ parameter_types! {
 	pub RmrkNewPerSecond: (AssetId, u128,u128) = (
 		Location::new(
 			1,
-			[Parachain(parachains::Statemine::ID), PalletInstance(parachains::Statemine::PALLET_ID),GeneralIndex(parachains::Statemine::RMRK_ID.into())]
+			[Parachain(AssetHubChainId::get()), PalletInstance(50), GeneralIndex(8)]
 		).into(),
 		// rmrk:KSM = 10:1
 		ksm_per_second::<Runtime>() * 10 / 100, //rmrk currency decimal as 10
@@ -251,7 +250,7 @@ parameter_types! {
 	pub MovrPerSecond: (AssetId, u128,u128) = (
 		Location::new(
 			1,
-			[Parachain(parachains::moonriver::ID), PalletInstance(parachains::moonriver::PALLET_ID.into())]
+			[Parachain(MoonriverChainId::get()), PalletInstance(10)]
 		).into(),
 		// MOVR:KSM = 2.67:1
 		ksm_per_second::<Runtime>() * 267 * 10_000, //movr currency decimal as 18
@@ -369,9 +368,6 @@ impl Contains<RuntimeCall> for SafeCallFilter {
 				bifrost_vtoken_minting::Call::rebond_by_unlock_id { .. } |
 				bifrost_vtoken_minting::Call::redeem { .. }
 			) |
-			RuntimeCall::XcmInterface(
-				bifrost_xcm_interface::Call::transfer_statemine_assets { .. }
-			) |
 			RuntimeCall::Slpx(..) |
 			RuntimeCall::ZenlinkProtocol(
 				zenlink_protocol::Call::add_liquidity { .. } |
@@ -660,16 +656,9 @@ impl bifrost_xcm_interface::Config for Runtime {
 	type RuntimeEvent = RuntimeEvent;
 	type UpdateOrigin = TechAdminOrCouncil;
 	type MultiCurrency = Currencies;
-	type RelayNetwork = KusamaNetwork;
-	type RelaychainCurrencyId = RelayCurrencyId;
-	type ParachainSovereignAccount = ParachainAccount;
-	#[cfg(feature = "runtime-benchmarks")]
-	type XcmExecutor = bifrost_primitives::MockXcmExecutor;
-	#[cfg(not(feature = "runtime-benchmarks"))]
-	type XcmExecutor = XcmExecutor<XcmConfig>;
 	type AccountIdToLocation = AccountIdToLocation;
-	type SalpHelper = Salp;
 	type ParachainId = ParachainInfo;
-	type CallBackTimeOut = ConstU32<10>;
 	type CurrencyIdConvert = AssetIdMaps<Runtime>;
+	type WeightInfo = weights::bifrost_xcm_interface::BifrostWeight<Runtime>;
+	type XcmRouter = XcmRouter;
 }
diff --git a/runtime/bifrost-polkadot/Cargo.toml b/runtime/bifrost-polkadot/Cargo.toml
index e79e6fef5..0888dda20 100644
--- a/runtime/bifrost-polkadot/Cargo.toml
+++ b/runtime/bifrost-polkadot/Cargo.toml
@@ -343,6 +343,7 @@ runtime-benchmarks = [
 	"bifrost-slpx/runtime-benchmarks",
 	"bifrost-stable-pool/runtime-benchmarks",
 	"bifrost-vtoken-voting/runtime-benchmarks",
+	"bifrost-xcm-interface/runtime-benchmarks",
 	"sp-api/disable-logging",
 	"lend-market/runtime-benchmarks",
 	"bifrost-channel-commission/runtime-benchmarks",
diff --git a/runtime/bifrost-polkadot/src/lib.rs b/runtime/bifrost-polkadot/src/lib.rs
index 6560618d8..51238fd02 100644
--- a/runtime/bifrost-polkadot/src/lib.rs
+++ b/runtime/bifrost-polkadot/src/lib.rs
@@ -121,7 +121,7 @@ use sp_runtime::{
 };
 use static_assertions::const_assert;
 use xcm::{v3::MultiLocation, v4::prelude::*};
-pub use xcm_config::{parachains, BifrostTreasuryAccount, MultiCurrency};
+pub use xcm_config::{BifrostTreasuryAccount, MultiCurrency};
 use xcm_executor::{traits::QueryHandler, XcmExecutor};
 
 pub mod governance;
@@ -937,7 +937,7 @@ pub fn create_x2_multilocation(index: u16, currency_id: CurrencyId) -> MultiLoca
 		CurrencyId::Token2(GLMR_TOKEN_ID) => MultiLocation::new(
 			1,
 			xcm::v3::Junctions::X2(
-				xcm::v3::Junction::Parachain(parachains::moonbeam::ID.into()),
+				xcm::v3::Junction::Parachain(MoonbeamChainId::get()),
 				xcm::v3::Junction::AccountKey20 {
 					network: None,
 					key: Slp::derivative_account_id_20(
@@ -1046,7 +1046,6 @@ impl bifrost_salp::Config for Runtime {
 	type VSBondValidPeriod = VSBondValidPeriod;
 	type WeightInfo = weights::bifrost_salp::BifrostWeight<Runtime>;
 	type EnsureConfirmAsGovernance = EitherOfDiverse<TechAdminOrCouncil, SALPAdmin>;
-	type XcmInterface = XcmInterface;
 	type TreasuryAccount = BifrostTreasuryAccount;
 	type BuybackPalletId = BuybackPalletId;
 	type CurrencyIdConversion = AssetIdMaps<Runtime>;
@@ -1926,6 +1925,7 @@ mod benches {
 		[bb_bnc, BbBNC]
 		[bifrost_buy_back, BuyBack]
 		[bifrost_slp_v2, SlpV2]
+		[bifrost_xcm_interface, XcmInterface]
 	);
 }
 
diff --git a/runtime/bifrost-polkadot/src/weights/bifrost_xcm_interface.rs b/runtime/bifrost-polkadot/src/weights/bifrost_xcm_interface.rs
new file mode 100644
index 000000000..1682d2414
--- /dev/null
+++ b/runtime/bifrost-polkadot/src/weights/bifrost_xcm_interface.rs
@@ -0,0 +1,78 @@
+// 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 <https://www.gnu.org/licenses/>.
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! Autogenerated weights for bifrost_xcm_interface
+//!
+//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
+//! DATE: 2024-09-24, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! HOSTNAME: `bifrost-jenkins`, CPU: `Intel(R) Xeon(R) CPU E5-26xx v4`
+//! WASM-EXECUTION: Compiled, CHAIN: Some("bifrost-polkadot-local"), DB CACHE: 1024
+
+// Executed Command:
+// ./target/release/bifrost
+// benchmark
+// pallet
+// --chain=bifrost-polkadot-local
+// --steps=50
+// --repeat=20
+// --pallet=bifrost_xcm_interface
+// --extrinsic=*
+// --execution=wasm
+// --wasm-execution=compiled
+// --heap-pages=4096
+// --header=./HEADER-GPL3
+// --output=./weight.rs
+// --template
+// ./weight-template/runtime-weight-template.hbs
+
+#![cfg_attr(rustfmt, rustfmt_skip)]
+#![allow(unused_parens)]
+#![allow(unused_imports)]
+
+use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
+use sp_std::marker::PhantomData;
+
+/// Weight functions for bifrost_xcm_interface.
+pub struct BifrostWeight<T>(PhantomData<T>);
+impl<T: frame_system::Config> bifrost_xcm_interface::WeightInfo for BifrostWeight<T> {
+    // Storage: `XcmInterface::XcmWeightAndFee` (r:1 w:1)
+    // Proof: `XcmInterface::XcmWeightAndFee` (`max_values`: None, `max_size`: None, mode: `Measured`)
+    // Storage: `System::Number` (r:1 w:0)
+    // Proof: `System::Number` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
+    // Storage: `System::ExecutionPhase` (r:1 w:0)
+    // Proof: `System::ExecutionPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `MaxEncodedLen`)
+    // Storage: `System::EventCount` (r:1 w:1)
+    // Proof: `System::EventCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
+    // Storage: `System::Events` (r:1 w:1)
+    // Proof: `System::Events` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
+    fn update_xcm_dest_weight_and_fee() -> Weight {
+        // Proof Size summary in bytes:
+        //  Measured:  `134`
+        //  Estimated: `3599`
+        // Minimum execution time: 56_793 nanoseconds.
+        Weight::from_parts(58_130_000, 3599)
+            .saturating_add(T::DbWeight::get().reads(5))
+            .saturating_add(T::DbWeight::get().writes(3))
+    }
+}
\ No newline at end of file
diff --git a/runtime/bifrost-polkadot/src/weights/mod.rs b/runtime/bifrost-polkadot/src/weights/mod.rs
index 5ba0dd1b6..c2ecca9ad 100644
--- a/runtime/bifrost-polkadot/src/weights/mod.rs
+++ b/runtime/bifrost-polkadot/src/weights/mod.rs
@@ -41,6 +41,7 @@ pub mod bifrost_vesting;
 pub mod bifrost_vstoken_conversion;
 pub mod bifrost_vtoken_minting;
 pub mod bifrost_vtoken_voting;
+pub mod bifrost_xcm_interface;
 pub mod orml_oracle;
 pub mod orml_tokens;
 pub mod pallet_xcm;
diff --git a/runtime/bifrost-polkadot/src/xcm_config.rs b/runtime/bifrost-polkadot/src/xcm_config.rs
index 88d9b9db3..ede51c1ca 100644
--- a/runtime/bifrost-polkadot/src/xcm_config.rs
+++ b/runtime/bifrost-polkadot/src/xcm_config.rs
@@ -27,7 +27,6 @@ use bifrost_primitives::{
 use bifrost_runtime_common::currency_adapter::{
 	BifrostDropAssets, DepositToAlternative, MultiCurrencyAdapter,
 };
-pub use bifrost_xcm_interface::traits::{parachains, XcmBaseWeight};
 use cumulus_primitives_core::AggregateMessageOrigin;
 pub use cumulus_primitives_core::ParaId;
 use frame_support::{
@@ -276,9 +275,6 @@ impl Contains<RuntimeCall> for SafeCallFilter {
 				bifrost_vtoken_minting::Call::rebond_by_unlock_id { .. } |
 				bifrost_vtoken_minting::Call::redeem { .. }
 			) |
-			RuntimeCall::XcmInterface(
-				bifrost_xcm_interface::Call::transfer_statemine_assets { .. }
-			) |
 			RuntimeCall::Slpx(..) |
 			RuntimeCall::ZenlinkProtocol(
 				zenlink_protocol::Call::add_liquidity { .. } |
@@ -536,13 +532,9 @@ impl bifrost_xcm_interface::Config for Runtime {
 	type RuntimeEvent = RuntimeEvent;
 	type UpdateOrigin = TechAdminOrCouncil;
 	type MultiCurrency = Currencies;
-	type RelayNetwork = PolkadotNetwork;
-	type RelaychainCurrencyId = RelayCurrencyId;
-	type ParachainSovereignAccount = ParachainAccount;
-	type XcmExecutor = XcmExecutor<XcmConfig>;
 	type AccountIdToLocation = AccountIdToLocation;
-	type SalpHelper = Salp;
 	type ParachainId = ParachainInfo;
-	type CallBackTimeOut = ConstU32<10>;
 	type CurrencyIdConvert = AssetIdMaps<Runtime>;
+	type XcmRouter = XcmRouter;
+	type WeightInfo = weights::bifrost_xcm_interface::BifrostWeight<Runtime>;
 }

From c6e240c7b0d7b4a9a4908246ded71a8a1cc3d5cd Mon Sep 17 00:00:00 2001
From: SunTiebing <87381708+SunTiebing@users.noreply.github.com>
Date: Wed, 25 Sep 2024 22:33:40 +0800
Subject: [PATCH 06/31] remove unnecessary call method of cross-in-out (#1440)

&& optimize cross-in-out pallet
---
 pallets/cross-in-out/src/benchmarking.rs      |  48 +---
 pallets/cross-in-out/src/lib.rs               | 219 ++++--------------
 pallets/cross-in-out/src/migrations/mod.rs    |   1 +
 pallets/cross-in-out/src/migrations/v3.rs     |  92 ++++++++
 pallets/cross-in-out/src/mock.rs              |   1 +
 pallets/cross-in-out/src/tests.rs             | 112 +--------
 pallets/cross-in-out/src/weights.rs           |  60 -----
 runtime/bifrost-kusama/src/lib.rs             |   1 +
 .../src/weights/bifrost_cross_in_out.rs       |  56 -----
 runtime/bifrost-polkadot/src/lib.rs           |   1 +
 .../src/weights/bifrost_cross_in_out.rs       |  56 -----
 11 files changed, 150 insertions(+), 497 deletions(-)
 create mode 100644 pallets/cross-in-out/src/migrations/v3.rs

diff --git a/pallets/cross-in-out/src/benchmarking.rs b/pallets/cross-in-out/src/benchmarking.rs
index 31d102378..b769ba1c3 100644
--- a/pallets/cross-in-out/src/benchmarking.rs
+++ b/pallets/cross-in-out/src/benchmarking.rs
@@ -25,7 +25,7 @@ use bifrost_primitives::{CurrencyId, TokenSymbol};
 use frame_benchmarking::v1::{account, benchmarks, whitelisted_caller, BenchmarkError};
 use frame_support::assert_ok;
 use frame_system::RawOrigin;
-use sp_runtime::traits::UniqueSaturatedFrom;
+use sp_runtime::traits::{AccountIdConversion, UniqueSaturatedFrom};
 use xcm::v2::prelude::*;
 
 use super::*;
@@ -33,10 +33,6 @@ use super::*;
 use crate::Pallet as CrossInOut;
 
 benchmarks! {
-	register_currency_for_cross_in_out {
-		let origin = T::ControlOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
-	}: _<T::RuntimeOrigin>(origin,CurrencyId::Token(TokenSymbol::DOT))
-
 	deregister_currency_for_cross_in_out {
 		let origin = T::ControlOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
 		assert_ok!(CrossInOut::<T>::register_currency_for_cross_in_out(
@@ -49,21 +45,6 @@ benchmarks! {
 		let origin = T::ControlOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
 	}: _<T::RuntimeOrigin>(origin,CurrencyId::Token(TokenSymbol::DOT),100u32.into(),100u32.into())
 
-	add_to_issue_whitelist {
-		let origin = T::ControlOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
-		let caller = whitelisted_caller();
-	}: _<T::RuntimeOrigin>(origin,CurrencyId::Token(TokenSymbol::DOT),caller)
-
-	remove_from_issue_whitelist {
-		let origin = T::ControlOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
-		let test_account: T::AccountId = account("seed",1,1);
-		assert_ok!(CrossInOut::<T>::add_to_issue_whitelist(
-			T::ControlOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?,
-			CurrencyId::Token(TokenSymbol::DOT),
-			test_account.clone()
-		));
-	}: _<T::RuntimeOrigin>(origin,CurrencyId::Token(TokenSymbol::DOT),test_account)
-
 	add_to_register_whitelist {
 		let origin = T::ControlOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
 		let caller = whitelisted_caller();
@@ -79,33 +60,6 @@ benchmarks! {
 		));
 	}: _<T::RuntimeOrigin>(origin,CurrencyId::Token(TokenSymbol::DOT),test_account)
 
-	cross_in {
-		let test_account: T::AccountId = account("seed",1,1);
-		assert_ok!(CrossInOut::<T>::register_currency_for_cross_in_out(
-			T::ControlOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?,
-			CurrencyId::Token(TokenSymbol::DOT)
-		));
-
-		assert_ok!(CrossInOut::<T>::set_crossing_minimum_amount(
-			T::ControlOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?,
-			CurrencyId::Token(TokenSymbol::DOT),100u32.into(),100u32.into()
-		));
-
-		assert_ok!(CrossInOut::<T>::add_to_issue_whitelist(
-			T::ControlOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?,
-			CurrencyId::Token(TokenSymbol::DOT),
-			test_account.clone()
-		));
-
-		let location = Box::new(MultiLocation {
-				parents: 0,
-				interior: X1(AccountId32 {
-					network: Any,
-					id: T::EntrancePalletId::get().into_account_truncating(),
-				}),
-			});
-	}: _(RawOrigin::Signed(test_account),location,CurrencyId::Token(TokenSymbol::DOT),100u32.into(),None)
-
 	register_linked_account {
 		let test_account: T::AccountId = account("seed",1,1);
 		assert_ok!(CrossInOut::<T>::add_to_register_whitelist(
diff --git a/pallets/cross-in-out/src/lib.rs b/pallets/cross-in-out/src/lib.rs
index 9cf42a272..f41653467 100644
--- a/pallets/cross-in-out/src/lib.rs
+++ b/pallets/cross-in-out/src/lib.rs
@@ -19,21 +19,17 @@
 // Ensure we're `no_std` when compiling for Wasm.
 #![cfg_attr(not(feature = "std"), no_std)]
 
-// pub use crate::imbalances::{NegativeImbalance, PositiveImbalance};
 extern crate alloc;
 
-use alloc::{vec, vec::Vec};
+use alloc::vec;
 use bifrost_primitives::CurrencyId;
-use frame_support::{ensure, pallet_prelude::*, sp_runtime::traits::AccountIdConversion, PalletId};
+use frame_support::{ensure, pallet_prelude::*, PalletId};
 use frame_system::pallet_prelude::*;
 use orml_traits::MultiCurrency;
 use sp_std::boxed::Box;
 pub use weights::WeightInfo;
 #[allow(deprecated)]
-use xcm::{
-	opaque::v2::{Junction::AccountId32, Junctions::X1, NetworkId::Any},
-	v2::MultiLocation,
-};
+use xcm::v2::MultiLocation;
 
 #[cfg(feature = "runtime-benchmarks")]
 mod benchmarking;
@@ -75,62 +71,49 @@ pub mod pallet {
 
 	#[pallet::error]
 	pub enum Error<T> {
+		/// Indicates that the balance is not sufficient for the requested operation.
 		NotEnoughBalance,
+		/// Indicates that the specified item does not exist.
 		NotExist,
+		/// Indicates that the operation is not allowed for the current context.
 		NotAllowed,
+		/// Indicates that the currency does not support crossing in and out.
 		CurrencyNotSupportCrossInAndOut,
+		/// Indicates that there is no mapping for the specified multilocation.
 		NoMultilocationMapping,
-		NoAccountIdMapping,
+		/// Indicates that the item already exists.
 		AlreadyExist,
+		/// Indicates that there is no minimum crossing amount set for the operation.
 		NoCrossingMinimumSet,
+		/// Indicates that the specified amount is lower than the required minimum.
 		AmountLowerThanMinimum,
-		ExceedMaxLengthLimit,
-		FailedToConvert,
+		/// Indicates that the list has reached its maximum capacity.
+		ListOverflow,
 	}
 
 	#[pallet::event]
 	#[pallet::generate_deposit(pub(crate) fn deposit_event)]
 	pub enum Event<T: Config> {
+		/// Event emitted when a currency is successfully crossed out from a location.
 		CrossedOut {
 			currency_id: CurrencyId,
 			crosser: AccountIdOf<T>,
 			location: MultiLocation,
 			amount: BalanceOf<T>,
 		},
-		CrossedIn {
-			currency_id: CurrencyId,
-			dest: AccountIdOf<T>,
-			location: MultiLocation,
-			amount: BalanceOf<T>,
-			remark: Option<Vec<u8>>,
-		},
-		CurrencyRegistered {
-			currency_id: CurrencyId,
-		},
-		CurrencyDeregistered {
-			currency_id: CurrencyId,
-		},
-		AddedToIssueList {
-			account: AccountIdOf<T>,
-			currency_id: CurrencyId,
-		},
-		RemovedFromIssueList {
-			account: AccountIdOf<T>,
-			currency_id: CurrencyId,
-		},
+		/// Event emitted when a currency is deregistered.
+		CurrencyDeregistered { currency_id: CurrencyId },
+		/// Event emitted when a linked account is successfully registered.
 		LinkedAccountRegistered {
 			currency_id: CurrencyId,
 			who: AccountIdOf<T>,
 			foreign_location: MultiLocation,
 		},
-		AddedToRegisterList {
-			account: AccountIdOf<T>,
-			currency_id: CurrencyId,
-		},
-		RemovedFromRegisterList {
-			account: AccountIdOf<T>,
-			currency_id: CurrencyId,
-		},
+		/// Event emitted when an account is added to the register list.
+		AddedToRegisterList { account: AccountIdOf<T>, currency_id: CurrencyId },
+		/// Event emitted when an account is removed from the register list.
+		RemovedFromRegisterList { account: AccountIdOf<T>, currency_id: CurrencyId },
+		/// Event emitted when the crossing minimum amounts are set for a currency.
 		CrossingMinimumAmountSet {
 			currency_id: CurrencyId,
 			cross_in_minimum: BalanceOf<T>,
@@ -140,7 +123,7 @@ pub mod pallet {
 
 	/// The current storage version, we set to 2 our new version(after migrate stroage from vec t
 	/// boundedVec).
-	const STORAGE_VERSION: StorageVersion = StorageVersion::new(2);
+	const STORAGE_VERSION: StorageVersion = StorageVersion::new(3);
 
 	/// To store currencies that support indirect cross-in and cross-out.
 	#[pallet::storage]
@@ -153,8 +136,8 @@ pub mod pallet {
 
 	/// Accounts in the whitelist can register the mapping between a multilocation and an accountId.
 	#[pallet::storage]
-	pub type RegisterWhiteList<T> =
-		StorageMap<_, Blake2_128Concat, CurrencyId, Vec<AccountIdOf<T>>>;
+	pub type RegisterWhiteList<T: Config> =
+		StorageMap<_, Blake2_128Concat, CurrencyId, BoundedVec<AccountIdOf<T>, T::MaxLengthLimit>>;
 
 	/// Mapping a Bifrost account to a multilocation of a outer chain
 	#[pallet::storage]
@@ -195,58 +178,6 @@ pub mod pallet {
 
 	#[pallet::call]
 	impl<T: Config> Pallet<T> {
-		#[pallet::call_index(0)]
-		#[pallet::weight(T::WeightInfo::cross_in())]
-		pub fn cross_in(
-			origin: OriginFor<T>,
-			location: Box<MultiLocation>,
-			currency_id: CurrencyId,
-			#[pallet::compact] amount: BalanceOf<T>,
-			remark: Option<Vec<u8>>,
-		) -> DispatchResult {
-			let issuer = ensure_signed(origin)?;
-
-			ensure!(
-				CrossCurrencyRegistry::<T>::contains_key(currency_id),
-				Error::<T>::CurrencyNotSupportCrossInAndOut
-			);
-
-			let crossing_minimum_amount = CrossingMinimumAmount::<T>::get(currency_id)
-				.ok_or(Error::<T>::NoCrossingMinimumSet)?;
-			ensure!(amount >= crossing_minimum_amount.0, Error::<T>::AmountLowerThanMinimum);
-
-			let issue_whitelist =
-				IssueWhiteList::<T>::get(currency_id).ok_or(Error::<T>::NotAllowed)?;
-			ensure!(issue_whitelist.contains(&issuer), Error::<T>::NotAllowed);
-
-			let entrance_account_mutlilcaition = Box::new(MultiLocation {
-				parents: 0,
-				interior: X1(AccountId32 {
-					network: Any,
-					id: T::EntrancePalletId::get().into_account_truncating(),
-				}),
-			});
-
-			// If the cross_in destination is entrance account, it is not required to be registered.
-			let dest = if entrance_account_mutlilcaition == location {
-				T::EntrancePalletId::get().into_account_truncating()
-			} else {
-				OuterMultilocationToAccount::<T>::get(currency_id, location.clone())
-					.ok_or(Error::<T>::NoAccountIdMapping)?
-			};
-
-			T::MultiCurrency::deposit(currency_id, &dest, amount)?;
-
-			Self::deposit_event(Event::CrossedIn {
-				dest,
-				currency_id,
-				location: *location,
-				amount,
-				remark,
-			});
-			Ok(())
-		}
-
 		/// Destroy some balance from an account and issue cross-out event.
 		#[pallet::call_index(1)]
 		#[pallet::weight(T::WeightInfo::cross_out())]
@@ -364,25 +295,6 @@ pub mod pallet {
 			Ok(())
 		}
 
-		#[pallet::call_index(4)]
-		#[pallet::weight(T::WeightInfo::register_currency_for_cross_in_out())]
-		pub fn register_currency_for_cross_in_out(
-			origin: OriginFor<T>,
-			currency_id: CurrencyId,
-		) -> DispatchResult {
-			T::ControlOrigin::ensure_origin(origin)?;
-
-			CrossCurrencyRegistry::<T>::mutate_exists(currency_id, |registration| {
-				if registration.is_none() {
-					*registration = Some(());
-
-					Self::deposit_event(Event::CurrencyRegistered { currency_id });
-				}
-			});
-
-			Ok(())
-		}
-
 		#[pallet::call_index(5)]
 		#[pallet::weight(T::WeightInfo::deregister_currency_for_cross_in_out())]
 		pub fn deregister_currency_for_cross_in_out(
@@ -398,63 +310,6 @@ pub mod pallet {
 			Ok(())
 		}
 
-		#[pallet::call_index(6)]
-		#[pallet::weight(T::WeightInfo::add_to_issue_whitelist())]
-		pub fn add_to_issue_whitelist(
-			origin: OriginFor<T>,
-			currency_id: CurrencyId,
-			account: AccountIdOf<T>,
-		) -> DispatchResult {
-			T::ControlOrigin::ensure_origin(origin)?;
-
-			let rs = IssueWhiteList::<T>::get(currency_id);
-			let mut issue_whitelist;
-			if let Some(bounded_vec) = rs {
-				issue_whitelist = bounded_vec.to_vec();
-				ensure!(
-					issue_whitelist.len() < T::MaxLengthLimit::get() as usize,
-					Error::<T>::ExceedMaxLengthLimit
-				);
-				ensure!(!issue_whitelist.contains(&account), Error::<T>::AlreadyExist);
-
-				issue_whitelist.push(account.clone());
-			} else {
-				issue_whitelist = vec![account.clone()];
-			}
-
-			let bounded_issue_whitelist =
-				BoundedVec::try_from(issue_whitelist).map_err(|_| Error::<T>::FailedToConvert)?;
-
-			IssueWhiteList::<T>::insert(currency_id, bounded_issue_whitelist);
-
-			Self::deposit_event(Event::AddedToIssueList { account, currency_id });
-
-			Ok(())
-		}
-
-		#[pallet::call_index(7)]
-		#[pallet::weight(T::WeightInfo::remove_from_issue_whitelist())]
-		pub fn remove_from_issue_whitelist(
-			origin: OriginFor<T>,
-			currency_id: CurrencyId,
-			account: AccountIdOf<T>,
-		) -> DispatchResult {
-			T::ControlOrigin::ensure_origin(origin)?;
-
-			IssueWhiteList::<T>::mutate(currency_id, |issue_whitelist| -> Result<(), Error<T>> {
-				match issue_whitelist {
-					Some(issue_list) if issue_list.contains(&account) => {
-						issue_list.retain(|x| x.clone() != account);
-						Self::deposit_event(Event::RemovedFromIssueList { account, currency_id });
-						Ok(())
-					},
-					_ => Err(Error::<T>::NotExist),
-				}
-			})?;
-
-			Ok(())
-		}
-
 		#[pallet::call_index(8)]
 		#[pallet::weight(T::WeightInfo::add_to_register_whitelist())]
 		pub fn add_to_register_whitelist(
@@ -464,9 +319,8 @@ pub mod pallet {
 		) -> DispatchResult {
 			T::ControlOrigin::ensure_origin(origin)?;
 
-			let empty_vec: Vec<AccountIdOf<T>> = Vec::new();
 			if RegisterWhiteList::<T>::get(currency_id) == None {
-				RegisterWhiteList::<T>::insert(currency_id, empty_vec);
+				RegisterWhiteList::<T>::insert(currency_id, BoundedVec::default());
 			}
 
 			RegisterWhiteList::<T>::mutate(
@@ -474,7 +328,9 @@ pub mod pallet {
 				|register_whitelist| -> Result<(), Error<T>> {
 					match register_whitelist {
 						Some(register_list) if !register_list.contains(&account) => {
-							register_list.push(account.clone());
+							register_list
+								.try_push(account.clone())
+								.map_err(|_| Error::<T>::ListOverflow)?;
 							Self::deposit_event(Event::AddedToRegisterList {
 								account,
 								currency_id,
@@ -539,4 +395,21 @@ pub mod pallet {
 			Ok(())
 		}
 	}
+
+	impl<T: Config> Pallet<T> {
+		pub fn register_currency_for_cross_in_out(
+			origin: OriginFor<T>,
+			currency_id: CurrencyId,
+		) -> DispatchResult {
+			T::ControlOrigin::ensure_origin(origin)?;
+
+			CrossCurrencyRegistry::<T>::mutate_exists(currency_id, |registration| {
+				if registration.is_none() {
+					*registration = Some(());
+				}
+			});
+
+			Ok(())
+		}
+	}
 }
diff --git a/pallets/cross-in-out/src/migrations/mod.rs b/pallets/cross-in-out/src/migrations/mod.rs
index 504be9301..f5231cb7b 100644
--- a/pallets/cross-in-out/src/migrations/mod.rs
+++ b/pallets/cross-in-out/src/migrations/mod.rs
@@ -18,3 +18,4 @@
 
 /// Version 2.
 pub mod v2;
+pub mod v3;
diff --git a/pallets/cross-in-out/src/migrations/v3.rs b/pallets/cross-in-out/src/migrations/v3.rs
new file mode 100644
index 000000000..b2d44e09a
--- /dev/null
+++ b/pallets/cross-in-out/src/migrations/v3.rs
@@ -0,0 +1,92 @@
+// 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 <https://www.gnu.org/licenses/>.
+
+use crate::*;
+use alloc::vec::Vec;
+use frame_support::traits::OnRuntimeUpgrade;
+#[cfg(feature = "try-runtime")]
+use sp_runtime::TryRuntimeError;
+
+const LOG_TARGET: &str = "cross-in-out::migration";
+
+pub struct MigrateToV2<T>(sp_std::marker::PhantomData<T>);
+impl<T: Config> OnRuntimeUpgrade for MigrateToV2<T> {
+	fn on_runtime_upgrade() -> frame_support::weights::Weight {
+		// Check the storage version
+		let onchain_version = Pallet::<T>::on_chain_storage_version();
+		if onchain_version < 3 {
+			// Transform storage values
+			// We transform the storage values from the old into the new format.
+			log::info!(target: LOG_TARGET, "Start to migrate RegisterWhiteList storage...");
+			RegisterWhiteList::<T>::translate::<Vec<AccountIdOf<T>>, _>(
+				|k: CurrencyId, value: Vec<AccountIdOf<T>>| {
+					log::info!(target: LOG_TARGET, "Migrated to boundedvec for {:?}...", k);
+
+					let target_bounded_vec: BoundedVec<AccountIdOf<T>, T::MaxLengthLimit>;
+
+					if value.len() != 0 {
+						target_bounded_vec = BoundedVec::try_from(value).unwrap();
+					} else {
+						target_bounded_vec =
+							BoundedVec::<AccountIdOf<T>, T::MaxLengthLimit>::default();
+					}
+
+					Some(target_bounded_vec)
+				},
+			);
+
+			// Update the storage version
+			StorageVersion::new(3).put::<Pallet<T>>();
+
+			// Return the consumed weight
+			let count = RegisterWhiteList::<T>::iter().count();
+			Weight::from(T::DbWeight::get().reads_writes(count as u64 + 1, count as u64 + 1))
+		} else {
+			// We don't do anything here.
+			Weight::zero()
+		}
+	}
+
+	#[cfg(feature = "try-runtime")]
+	fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
+		let cnt = RegisterWhiteList::<T>::iter().count();
+		log::info!(target: LOG_TARGET, "RegisterWhiteList pre-migrate storage count: {:?}", cnt);
+		Ok((cnt as u64).encode())
+	}
+
+	#[cfg(feature = "try-runtime")]
+	fn post_upgrade(cnt: Vec<u8>) -> Result<(), TryRuntimeError> {
+		let new_count = RegisterWhiteList::<T>::iter().count();
+
+		let old_count: u64 = Decode::decode(&mut cnt.as_slice())
+			.expect("the state parameter should be something that was generated by pre_upgrade");
+
+		log::info!(
+			target: LOG_TARGET,
+			"RegisterWhiteList post-migrate storage count: {:?}",
+			new_count
+		);
+
+		ensure!(
+			new_count as u64 == old_count,
+			"Post-migration storage count does not match pre-migration count"
+		);
+
+		Ok(())
+	}
+}
diff --git a/pallets/cross-in-out/src/mock.rs b/pallets/cross-in-out/src/mock.rs
index c76374cf3..043bf05f4 100644
--- a/pallets/cross-in-out/src/mock.rs
+++ b/pallets/cross-in-out/src/mock.rs
@@ -161,6 +161,7 @@ impl ExtBuilder {
 			(CHARLIE, BNC, 100),
 			(ALICE, DOT, 100),
 			(ALICE, VDOT, 400),
+			(ALICE, KSM, 100),
 			(BOB, DOT, 100),
 			(BOB, KSM, 100),
 		])
diff --git a/pallets/cross-in-out/src/tests.rs b/pallets/cross-in-out/src/tests.rs
index 0e60781cb..dd549ff6b 100644
--- a/pallets/cross-in-out/src/tests.rs
+++ b/pallets/cross-in-out/src/tests.rs
@@ -33,82 +33,10 @@ fn cross_in_and_cross_out_should_work() {
 			parents: 100,
 			interior: X1(Junction::GeneralKey(WeakBoundedVec::default())),
 		};
-
-		assert_noop!(
-			CrossInOut::cross_in(
-				RuntimeOrigin::signed(ALICE),
-				Box::new(location.clone()),
-				KSM,
-				100,
-				None
-			),
-			Error::<Runtime>::CurrencyNotSupportCrossInAndOut
-		);
-
 		CrossCurrencyRegistry::<Runtime>::insert(KSM, ());
-
-		assert_noop!(
-			CrossInOut::cross_in(
-				RuntimeOrigin::signed(ALICE),
-				Box::new(location.clone()),
-				KSM,
-				100,
-				None
-			),
-			Error::<Runtime>::NoCrossingMinimumSet
-		);
-
-		CrossingMinimumAmount::<Runtime>::insert(KSM, (1000, 1000));
-
-		assert_noop!(
-			CrossInOut::cross_in(
-				RuntimeOrigin::signed(ALICE),
-				Box::new(location.clone()),
-				KSM,
-				100,
-				None
-			),
-			Error::<Runtime>::AmountLowerThanMinimum
-		);
-
 		CrossingMinimumAmount::<Runtime>::insert(KSM, (1, 1));
-
-		assert_noop!(
-			CrossInOut::cross_in(
-				RuntimeOrigin::signed(ALICE),
-				Box::new(location.clone()),
-				KSM,
-				100,
-				None
-			),
-			Error::<Runtime>::NotAllowed
-		);
-
-		let bounded_vector = BoundedVec::try_from(vec![ALICE]).unwrap();
-		IssueWhiteList::<Runtime>::insert(KSM, bounded_vector);
-
-		assert_noop!(
-			CrossInOut::cross_in(
-				RuntimeOrigin::signed(ALICE),
-				Box::new(location.clone()),
-				KSM,
-				100,
-				None
-			),
-			Error::<Runtime>::NoAccountIdMapping
-		);
-
 		AccountToOuterMultilocation::<Runtime>::insert(KSM, ALICE, location.clone());
 		OuterMultilocationToAccount::<Runtime>::insert(KSM, location.clone(), ALICE);
-
-		assert_eq!(Tokens::free_balance(KSM, &ALICE), 0);
-		assert_ok!(CrossInOut::cross_in(
-			RuntimeOrigin::signed(ALICE),
-			Box::new(location),
-			KSM,
-			100,
-			None
-		));
 		assert_eq!(Tokens::free_balance(KSM, &ALICE), 100);
 
 		assert_ok!(CrossInOut::cross_out(RuntimeOrigin::signed(ALICE), KSM, 50));
@@ -116,37 +44,16 @@ fn cross_in_and_cross_out_should_work() {
 	});
 }
 
-#[test]
-fn add_to_and_remove_from_issue_whitelist_should_work() {
-	ExtBuilder::default().one_hundred_for_alice_n_bob().build().execute_with(|| {
-		assert_eq!(IssueWhiteList::<Runtime>::get(KSM), None);
-
-		assert_ok!(CrossInOut::add_to_issue_whitelist(RuntimeOrigin::signed(ALICE), KSM, ALICE));
-		let bounded_vector = BoundedVec::try_from(vec![ALICE]).unwrap();
-		assert_eq!(IssueWhiteList::<Runtime>::get(KSM), Some(bounded_vector));
-
-		assert_noop!(
-			CrossInOut::remove_from_issue_whitelist(RuntimeOrigin::signed(ALICE), KSM, BOB),
-			Error::<Runtime>::NotExist
-		);
-
-		assert_ok!(CrossInOut::remove_from_issue_whitelist(
-			RuntimeOrigin::signed(ALICE),
-			KSM,
-			ALICE
-		));
-		let empty_vec = BoundedVec::default();
-		assert_eq!(IssueWhiteList::<Runtime>::get(KSM), Some(empty_vec));
-	});
-}
-
 #[test]
 fn add_to_and_remove_from_register_whitelist_should_work() {
 	ExtBuilder::default().one_hundred_for_alice_n_bob().build().execute_with(|| {
 		assert_eq!(RegisterWhiteList::<Runtime>::get(KSM), None);
 
 		assert_ok!(CrossInOut::add_to_register_whitelist(RuntimeOrigin::signed(ALICE), KSM, ALICE));
-		assert_eq!(RegisterWhiteList::<Runtime>::get(KSM), Some(vec![ALICE]));
+		assert_eq!(
+			RegisterWhiteList::<Runtime>::get(KSM),
+			Some(BoundedVec::try_from(vec![ALICE]).unwrap())
+		);
 
 		assert_noop!(
 			CrossInOut::remove_from_register_whitelist(RuntimeOrigin::signed(ALICE), KSM, BOB),
@@ -158,7 +65,7 @@ fn add_to_and_remove_from_register_whitelist_should_work() {
 			KSM,
 			ALICE
 		));
-		assert_eq!(RegisterWhiteList::<Runtime>::get(KSM), Some(vec![]));
+		assert_eq!(RegisterWhiteList::<Runtime>::get(KSM), Some(BoundedVec::default()));
 	});
 }
 
@@ -186,7 +93,7 @@ fn register_linked_account_should_work() {
 			Error::<Runtime>::NotAllowed
 		);
 
-		RegisterWhiteList::<Runtime>::insert(KSM, vec![ALICE]);
+		RegisterWhiteList::<Runtime>::insert(KSM, BoundedVec::try_from(vec![ALICE]).unwrap());
 
 		assert_noop!(
 			CrossInOut::register_linked_account(
@@ -222,12 +129,7 @@ fn register_linked_account_should_work() {
 #[test]
 fn register_and_deregister_currency_for_cross_in_out_should_work() {
 	ExtBuilder::default().one_hundred_for_alice_n_bob().build().execute_with(|| {
-		assert_ok!(CrossInOut::register_currency_for_cross_in_out(
-			RuntimeOrigin::signed(ALICE),
-			KSM,
-		));
-
-		assert_eq!(CrossCurrencyRegistry::<Runtime>::get(KSM), Some(()));
+		CrossCurrencyRegistry::<Runtime>::insert(KSM, ());
 
 		assert_ok!(CrossInOut::deregister_currency_for_cross_in_out(
 			RuntimeOrigin::signed(ALICE),
diff --git a/pallets/cross-in-out/src/weights.rs b/pallets/cross-in-out/src/weights.rs
index bb190417d..d75f2deea 100644
--- a/pallets/cross-in-out/src/weights.rs
+++ b/pallets/cross-in-out/src/weights.rs
@@ -53,14 +53,10 @@ use sp_std::marker::PhantomData;
 
 /// Weight functions needed for bifrost_cross_in_out.
 pub trait WeightInfo {
-	fn register_currency_for_cross_in_out() -> Weight;
 	fn deregister_currency_for_cross_in_out() -> Weight;
 	fn set_crossing_minimum_amount() -> Weight;
-	fn add_to_issue_whitelist() -> Weight;
-	fn remove_from_issue_whitelist() -> Weight;
 	fn add_to_register_whitelist() -> Weight;
 	fn remove_from_register_whitelist() -> Weight;
-	fn cross_in() -> Weight;
 	fn register_linked_account() -> Weight;
 	fn cross_out() -> Weight;
 	fn change_outer_linked_account() -> Weight;
@@ -68,17 +64,6 @@ pub trait WeightInfo {
 
 // For backwards compatibility and tests
 impl WeightInfo for () {
-	/// Storage: CrossInOut CrossCurrencyRegistry (r:1 w:1)
-	/// Proof Skipped: CrossInOut CrossCurrencyRegistry (max_values: None, max_size: None, mode: Measured)
-	fn register_currency_for_cross_in_out() -> Weight {
-		// Proof Size summary in bytes:
-		//  Measured:  `76`
-		//  Estimated: `3541`
-		// Minimum execution time: 29_633_000 picoseconds.
-		Weight::from_parts(30_578_000, 3541)
-			.saturating_add(RocksDbWeight::get().reads(1_u64))
-			.saturating_add(RocksDbWeight::get().writes(1_u64))
-	}
 	/// Storage: CrossInOut CrossCurrencyRegistry (r:1 w:1)
 	/// Proof Skipped: CrossInOut CrossCurrencyRegistry (max_values: None, max_size: None, mode: Measured)
 	fn deregister_currency_for_cross_in_out() -> Weight {
@@ -100,28 +85,6 @@ impl WeightInfo for () {
 		Weight::from_parts(24_439_000, 0)
 			.saturating_add(RocksDbWeight::get().writes(1_u64))
 	}
-	/// Storage: CrossInOut IssueWhiteList (r:1 w:1)
-	/// Proof Skipped: CrossInOut IssueWhiteList (max_values: None, max_size: None, mode: Measured)
-	fn add_to_issue_whitelist() -> Weight {
-		// Proof Size summary in bytes:
-		//  Measured:  `76`
-		//  Estimated: `3541`
-		// Minimum execution time: 34_191_000 picoseconds.
-		Weight::from_parts(35_236_000, 3541)
-			.saturating_add(RocksDbWeight::get().reads(1_u64))
-			.saturating_add(RocksDbWeight::get().writes(1_u64))
-	}
-	/// Storage: CrossInOut IssueWhiteList (r:1 w:1)
-	/// Proof Skipped: CrossInOut IssueWhiteList (max_values: None, max_size: None, mode: Measured)
-	fn remove_from_issue_whitelist() -> Weight {
-		// Proof Size summary in bytes:
-		//  Measured:  `154`
-		//  Estimated: `3619`
-		// Minimum execution time: 35_934_000 picoseconds.
-		Weight::from_parts(37_252_000, 3619)
-			.saturating_add(RocksDbWeight::get().reads(1_u64))
-			.saturating_add(RocksDbWeight::get().writes(1_u64))
-	}
 	/// Storage: CrossInOut RegisterWhiteList (r:1 w:1)
 	/// Proof Skipped: CrossInOut RegisterWhiteList (max_values: None, max_size: None, mode: Measured)
 	fn add_to_register_whitelist() -> Weight {
@@ -144,29 +107,6 @@ impl WeightInfo for () {
 			.saturating_add(RocksDbWeight::get().reads(1_u64))
 			.saturating_add(RocksDbWeight::get().writes(1_u64))
 	}
-	/// Storage: CrossInOut CrossCurrencyRegistry (r:1 w:0)
-	/// Proof Skipped: CrossInOut CrossCurrencyRegistry (max_values: None, max_size: None, mode: Measured)
-	/// Storage: CrossInOut CrossingMinimumAmount (r:1 w:0)
-	/// Proof Skipped: CrossInOut CrossingMinimumAmount (max_values: None, max_size: None, mode: Measured)
-	/// Storage: CrossInOut IssueWhiteList (r:1 w:0)
-	/// Proof Skipped: CrossInOut IssueWhiteList (max_values: None, max_size: None, mode: Measured)
-	/// Storage: Tokens Accounts (r:1 w:1)
-	/// Proof: Tokens Accounts (max_values: None, max_size: Some(118), added: 2593, mode: MaxEncodedLen)
-	/// Storage: AssetRegistry CurrencyMetadatas (r:1 w:0)
-	/// Proof Skipped: AssetRegistry CurrencyMetadatas (max_values: None, max_size: None, mode: Measured)
-	/// Storage: Tokens TotalIssuance (r:1 w:1)
-	/// Proof: Tokens TotalIssuance (max_values: None, max_size: Some(38), added: 2513, mode: MaxEncodedLen)
-	/// Storage: System Account (r:1 w:1)
-	/// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen)
-	fn cross_in() -> Weight {
-		// Proof Size summary in bytes:
-		//  Measured:  `1758`
-		//  Estimated: `5223`
-		// Minimum execution time: 146_488_000 picoseconds.
-		Weight::from_parts(150_867_000, 5223)
-			.saturating_add(RocksDbWeight::get().reads(7_u64))
-			.saturating_add(RocksDbWeight::get().writes(3_u64))
-	}
 	/// Storage: CrossInOut RegisterWhiteList (r:1 w:0)
 	/// Proof Skipped: CrossInOut RegisterWhiteList (max_values: None, max_size: None, mode: Measured)
 	/// Storage: CrossInOut CrossCurrencyRegistry (r:1 w:0)
diff --git a/runtime/bifrost-kusama/src/lib.rs b/runtime/bifrost-kusama/src/lib.rs
index b5820a869..5095e5a50 100644
--- a/runtime/bifrost-kusama/src/lib.rs
+++ b/runtime/bifrost-kusama/src/lib.rs
@@ -1932,6 +1932,7 @@ pub mod migrations {
 	pub type Unreleased = (
 		// permanent migration, do not remove
 		pallet_xcm::migration::MigrateToLatestXcmVersion<Runtime>,
+		bifrost_cross_in_out::migrations::v3::MigrateToV2<Runtime>,
 		SystemMakerClearPalletId<Runtime>,
 		frame_support::migrations::RemovePallet<SystemMakerName, RocksDbWeight>,
 	);
diff --git a/runtime/bifrost-kusama/src/weights/bifrost_cross_in_out.rs b/runtime/bifrost-kusama/src/weights/bifrost_cross_in_out.rs
index 870af08ca..eaf91c404 100644
--- a/runtime/bifrost-kusama/src/weights/bifrost_cross_in_out.rs
+++ b/runtime/bifrost-kusama/src/weights/bifrost_cross_in_out.rs
@@ -54,17 +54,6 @@ use sp_std::marker::PhantomData;
 /// Weight functions for bifrost_cross_in_out.
 pub struct BifrostWeight<T>(PhantomData<T>);
 impl<T: frame_system::Config> bifrost_cross_in_out::WeightInfo for BifrostWeight<T> {
-	// Storage: CrossInOut CrossCurrencyRegistry (r:1 w:1)
-	// Proof Skipped: CrossInOut CrossCurrencyRegistry (max_values: None, max_size: None, mode: Measured)
-	fn register_currency_for_cross_in_out() -> Weight {
-		// Proof Size summary in bytes:
-		//  Measured:  `76`
-		//  Estimated: `3541`
-		// Minimum execution time: 30_069 nanoseconds.
-		Weight::from_parts(30_714_000, 3541)
-			.saturating_add(T::DbWeight::get().reads(1))
-			.saturating_add(T::DbWeight::get().writes(1))
-	}
 	// Storage: CrossInOut CrossCurrencyRegistry (r:1 w:1)
 	// Proof Skipped: CrossInOut CrossCurrencyRegistry (max_values: None, max_size: None, mode: Measured)
 	fn deregister_currency_for_cross_in_out() -> Weight {
@@ -86,28 +75,6 @@ impl<T: frame_system::Config> bifrost_cross_in_out::WeightInfo for BifrostWeight
 		Weight::from_parts(25_172_000, 0)
 			.saturating_add(T::DbWeight::get().writes(1))
 	}
-	// Storage: CrossInOut IssueWhiteList (r:1 w:1)
-	// Proof Skipped: CrossInOut IssueWhiteList (max_values: None, max_size: None, mode: Measured)
-	fn add_to_issue_whitelist() -> Weight {
-		// Proof Size summary in bytes:
-		//  Measured:  `76`
-		//  Estimated: `3541`
-		// Minimum execution time: 34_593 nanoseconds.
-		Weight::from_parts(35_760_000, 3541)
-			.saturating_add(T::DbWeight::get().reads(1))
-			.saturating_add(T::DbWeight::get().writes(1))
-	}
-	// Storage: CrossInOut IssueWhiteList (r:1 w:1)
-	// Proof Skipped: CrossInOut IssueWhiteList (max_values: None, max_size: None, mode: Measured)
-	fn remove_from_issue_whitelist() -> Weight {
-		// Proof Size summary in bytes:
-		//  Measured:  `154`
-		//  Estimated: `3619`
-		// Minimum execution time: 35_748 nanoseconds.
-		Weight::from_parts(36_569_000, 3619)
-			.saturating_add(T::DbWeight::get().reads(1))
-			.saturating_add(T::DbWeight::get().writes(1))
-	}
 	// Storage: CrossInOut RegisterWhiteList (r:1 w:1)
 	// Proof Skipped: CrossInOut RegisterWhiteList (max_values: None, max_size: None, mode: Measured)
 	fn add_to_register_whitelist() -> Weight {
@@ -130,29 +97,6 @@ impl<T: frame_system::Config> bifrost_cross_in_out::WeightInfo for BifrostWeight
 			.saturating_add(T::DbWeight::get().reads(1))
 			.saturating_add(T::DbWeight::get().writes(1))
 	}
-	// Storage: CrossInOut CrossCurrencyRegistry (r:1 w:0)
-	// Proof Skipped: CrossInOut CrossCurrencyRegistry (max_values: None, max_size: None, mode: Measured)
-	// Storage: CrossInOut CrossingMinimumAmount (r:1 w:0)
-	// Proof Skipped: CrossInOut CrossingMinimumAmount (max_values: None, max_size: None, mode: Measured)
-	// Storage: CrossInOut IssueWhiteList (r:1 w:0)
-	// Proof Skipped: CrossInOut IssueWhiteList (max_values: None, max_size: None, mode: Measured)
-	// Storage: Tokens Accounts (r:1 w:1)
-	// Proof: Tokens Accounts (max_values: None, max_size: Some(118), added: 2593, mode: MaxEncodedLen)
-	// Storage: AssetRegistry CurrencyMetadatas (r:1 w:0)
-	// Proof Skipped: AssetRegistry CurrencyMetadatas (max_values: None, max_size: None, mode: Measured)
-	// Storage: Tokens TotalIssuance (r:1 w:1)
-	// Proof: Tokens TotalIssuance (max_values: None, max_size: Some(38), added: 2513, mode: MaxEncodedLen)
-	// Storage: System Account (r:1 w:1)
-	// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen)
-	fn cross_in() -> Weight {
-		// Proof Size summary in bytes:
-		//  Measured:  `1758`
-		//  Estimated: `5223`
-		// Minimum execution time: 146_344 nanoseconds.
-		Weight::from_parts(147_835_000, 5223)
-			.saturating_add(T::DbWeight::get().reads(7))
-			.saturating_add(T::DbWeight::get().writes(3))
-	}
 	// Storage: CrossInOut RegisterWhiteList (r:1 w:0)
 	// Proof Skipped: CrossInOut RegisterWhiteList (max_values: None, max_size: None, mode: Measured)
 	// Storage: CrossInOut CrossCurrencyRegistry (r:1 w:0)
diff --git a/runtime/bifrost-polkadot/src/lib.rs b/runtime/bifrost-polkadot/src/lib.rs
index 51238fd02..579a05809 100644
--- a/runtime/bifrost-polkadot/src/lib.rs
+++ b/runtime/bifrost-polkadot/src/lib.rs
@@ -1845,6 +1845,7 @@ pub mod migrations {
 	pub type Unreleased = (
 		// permanent migration, do not remove
 		pallet_xcm::migration::MigrateToLatestXcmVersion<Runtime>,
+		bifrost_cross_in_out::migrations::v3::MigrateToV2<Runtime>,
 		frame_support::migrations::RemovePallet<SystemMakerName, RocksDbWeight>,
 	);
 }
diff --git a/runtime/bifrost-polkadot/src/weights/bifrost_cross_in_out.rs b/runtime/bifrost-polkadot/src/weights/bifrost_cross_in_out.rs
index 870af08ca..eaf91c404 100644
--- a/runtime/bifrost-polkadot/src/weights/bifrost_cross_in_out.rs
+++ b/runtime/bifrost-polkadot/src/weights/bifrost_cross_in_out.rs
@@ -54,17 +54,6 @@ use sp_std::marker::PhantomData;
 /// Weight functions for bifrost_cross_in_out.
 pub struct BifrostWeight<T>(PhantomData<T>);
 impl<T: frame_system::Config> bifrost_cross_in_out::WeightInfo for BifrostWeight<T> {
-	// Storage: CrossInOut CrossCurrencyRegistry (r:1 w:1)
-	// Proof Skipped: CrossInOut CrossCurrencyRegistry (max_values: None, max_size: None, mode: Measured)
-	fn register_currency_for_cross_in_out() -> Weight {
-		// Proof Size summary in bytes:
-		//  Measured:  `76`
-		//  Estimated: `3541`
-		// Minimum execution time: 30_069 nanoseconds.
-		Weight::from_parts(30_714_000, 3541)
-			.saturating_add(T::DbWeight::get().reads(1))
-			.saturating_add(T::DbWeight::get().writes(1))
-	}
 	// Storage: CrossInOut CrossCurrencyRegistry (r:1 w:1)
 	// Proof Skipped: CrossInOut CrossCurrencyRegistry (max_values: None, max_size: None, mode: Measured)
 	fn deregister_currency_for_cross_in_out() -> Weight {
@@ -86,28 +75,6 @@ impl<T: frame_system::Config> bifrost_cross_in_out::WeightInfo for BifrostWeight
 		Weight::from_parts(25_172_000, 0)
 			.saturating_add(T::DbWeight::get().writes(1))
 	}
-	// Storage: CrossInOut IssueWhiteList (r:1 w:1)
-	// Proof Skipped: CrossInOut IssueWhiteList (max_values: None, max_size: None, mode: Measured)
-	fn add_to_issue_whitelist() -> Weight {
-		// Proof Size summary in bytes:
-		//  Measured:  `76`
-		//  Estimated: `3541`
-		// Minimum execution time: 34_593 nanoseconds.
-		Weight::from_parts(35_760_000, 3541)
-			.saturating_add(T::DbWeight::get().reads(1))
-			.saturating_add(T::DbWeight::get().writes(1))
-	}
-	// Storage: CrossInOut IssueWhiteList (r:1 w:1)
-	// Proof Skipped: CrossInOut IssueWhiteList (max_values: None, max_size: None, mode: Measured)
-	fn remove_from_issue_whitelist() -> Weight {
-		// Proof Size summary in bytes:
-		//  Measured:  `154`
-		//  Estimated: `3619`
-		// Minimum execution time: 35_748 nanoseconds.
-		Weight::from_parts(36_569_000, 3619)
-			.saturating_add(T::DbWeight::get().reads(1))
-			.saturating_add(T::DbWeight::get().writes(1))
-	}
 	// Storage: CrossInOut RegisterWhiteList (r:1 w:1)
 	// Proof Skipped: CrossInOut RegisterWhiteList (max_values: None, max_size: None, mode: Measured)
 	fn add_to_register_whitelist() -> Weight {
@@ -130,29 +97,6 @@ impl<T: frame_system::Config> bifrost_cross_in_out::WeightInfo for BifrostWeight
 			.saturating_add(T::DbWeight::get().reads(1))
 			.saturating_add(T::DbWeight::get().writes(1))
 	}
-	// Storage: CrossInOut CrossCurrencyRegistry (r:1 w:0)
-	// Proof Skipped: CrossInOut CrossCurrencyRegistry (max_values: None, max_size: None, mode: Measured)
-	// Storage: CrossInOut CrossingMinimumAmount (r:1 w:0)
-	// Proof Skipped: CrossInOut CrossingMinimumAmount (max_values: None, max_size: None, mode: Measured)
-	// Storage: CrossInOut IssueWhiteList (r:1 w:0)
-	// Proof Skipped: CrossInOut IssueWhiteList (max_values: None, max_size: None, mode: Measured)
-	// Storage: Tokens Accounts (r:1 w:1)
-	// Proof: Tokens Accounts (max_values: None, max_size: Some(118), added: 2593, mode: MaxEncodedLen)
-	// Storage: AssetRegistry CurrencyMetadatas (r:1 w:0)
-	// Proof Skipped: AssetRegistry CurrencyMetadatas (max_values: None, max_size: None, mode: Measured)
-	// Storage: Tokens TotalIssuance (r:1 w:1)
-	// Proof: Tokens TotalIssuance (max_values: None, max_size: Some(38), added: 2513, mode: MaxEncodedLen)
-	// Storage: System Account (r:1 w:1)
-	// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen)
-	fn cross_in() -> Weight {
-		// Proof Size summary in bytes:
-		//  Measured:  `1758`
-		//  Estimated: `5223`
-		// Minimum execution time: 146_344 nanoseconds.
-		Weight::from_parts(147_835_000, 5223)
-			.saturating_add(T::DbWeight::get().reads(7))
-			.saturating_add(T::DbWeight::get().writes(3))
-	}
 	// Storage: CrossInOut RegisterWhiteList (r:1 w:0)
 	// Proof Skipped: CrossInOut RegisterWhiteList (max_values: None, max_size: None, mode: Measured)
 	// Storage: CrossInOut CrossCurrencyRegistry (r:1 w:0)

From 9237c35ec862d744496d84682e077195694614b1 Mon Sep 17 00:00:00 2001
From: yooml <ymlll0508@gmail.com>
Date: Wed, 25 Sep 2024 22:45:41 +0800
Subject: [PATCH 07/31] Update bb bnc (#1436)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* refactor: 💡 for review

* docs: ✏️ add docs

* fix: 🐛 docs

* fix: 🐛 add event && addr rename
---
 pallets/bb-bnc/src/incentive.rs |  68 ++---
 pallets/bb-bnc/src/lib.rs       | 426 +++++++++++++++++++++-----------
 pallets/bb-bnc/src/tests.rs     |  14 +-
 pallets/bb-bnc/src/traits.rs    |  78 +++---
 4 files changed, 367 insertions(+), 219 deletions(-)

diff --git a/pallets/bb-bnc/src/incentive.rs b/pallets/bb-bnc/src/incentive.rs
index 4edfcb1eb..ec082aedd 100644
--- a/pallets/bb-bnc/src/incentive.rs
+++ b/pallets/bb-bnc/src/incentive.rs
@@ -23,12 +23,20 @@ use sp_std::collections::btree_map::BTreeMap;
 
 #[derive(Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo)]
 pub struct IncentiveConfig<CurrencyId, Balance, BlockNumber, AccountId> {
+	/// Reward per block number per currency_id, which will change at notify_reward.
 	pub reward_rate: BTreeMap<CurrencyId, Balance>,
+	/// Each currency_id is rewarded against each TokenType and grows with user actions.
 	pub reward_per_token_stored: BTreeMap<CurrencyId, Balance>,
+	/// Round duration.
 	pub rewards_duration: BlockNumber,
+	/// The time when this round ends.
 	pub period_finish: BlockNumber,
+	/// Last time rewards were updated, any user action will update this field.
 	pub last_update_time: BlockNumber,
+	/// When a round is started, the corresponding value will be transferred from this account to
+	/// the system account.
 	pub incentive_controller: Option<AccountId>,
+	/// When a round is started, the value to be transferred will be obtained from this field.
 	pub last_reward: Vec<(CurrencyId, Balance)>,
 }
 
@@ -103,22 +111,22 @@ impl<T: Config> Pallet<T> {
 	/// Calculates the reward earned by an account from a specific reward pool
 	pub fn earned(
 		pool_id: PoolId,
-		addr: &AccountIdOf<T>,
+		who: &AccountIdOf<T>,
 		share_info: Option<(BalanceOf<T>, BalanceOf<T>)>,
 	) -> Result<BTreeMap<CurrencyIdOf<T>, BalanceOf<T>>, DispatchError> {
 		let reward_per_token = Self::reward_per_token(pool_id)?;
-		let vetoken_balance = Self::balance_of_current_block(addr)?;
-		let mut rewards = if let Some(rewards) = Rewards::<T>::get(addr) {
+		let bbbnc_balance = Self::balance_of_current_block(who)?;
+		let mut rewards = if let Some(rewards) = Rewards::<T>::get(who) {
 			rewards
 		} else {
 			BTreeMap::<CurrencyIdOf<T>, BalanceOf<T>>::default()
 		};
 		reward_per_token.iter().try_for_each(|(currency, reward)| -> DispatchResult {
-			let increment = U256::from(vetoken_balance.saturated_into::<u128>())
+			let increment = U256::from(bbbnc_balance.saturated_into::<u128>())
 				.checked_mul(U256::from(
 					reward
 						.saturating_sub(
-							*UserRewardPerTokenPaid::<T>::get(addr)
+							*UserRewardPerTokenPaid::<T>::get(who)
 								.get(currency)
 								.unwrap_or(&BalanceOf::<T>::zero()),
 						)
@@ -136,7 +144,7 @@ impl<T: Config> Pallet<T> {
 			// and total share.
 			match share_info {
 				Some((share, total_share)) => {
-					let mut pools = UserFarmingPool::<T>::get(addr);
+					let mut pools = UserFarmingPool::<T>::get(who);
 					if share.is_zero() {
 						if let Some(pos) = pools.iter().position(|&x| x == pool_id) {
 							pools.remove(pos);
@@ -144,7 +152,7 @@ impl<T: Config> Pallet<T> {
 					} else {
 						pools.try_push(pool_id).map_err(|_| Error::<T>::UserFarmingPoolOverflow)?;
 					}
-					UserFarmingPool::<T>::insert(addr, pools);
+					UserFarmingPool::<T>::insert(who, pools);
 					let reward = increment
 						.checked_mul(U256::from(share.saturated_into::<u128>()))
 						.ok_or(ArithmeticError::Overflow)?
@@ -182,7 +190,7 @@ impl<T: Config> Pallet<T> {
 	// create_lock/increase_amount/increase_unlock_time/withdraw/get_rewards
 	pub fn update_reward(
 		pool_id: PoolId,
-		addr: Option<&AccountIdOf<T>>,
+		who: Option<&AccountIdOf<T>>,
 		share_info: Option<(BalanceOf<T>, BalanceOf<T>)>,
 	) -> DispatchResult {
 		let reward_per_token_stored = Self::reward_per_token(pool_id)?;
@@ -191,51 +199,51 @@ impl<T: Config> Pallet<T> {
 			item.reward_per_token_stored = reward_per_token_stored.clone();
 			item.last_update_time = Self::last_time_reward_applicable(pool_id);
 		});
-		// If an account address is provided, update the rewards
-		if let Some(address) = addr {
-			let earned = Self::earned(pool_id, address, share_info)?;
+		// If an account is provided, update the rewards
+		if let Some(account) = who {
+			let earned = Self::earned(pool_id, account, share_info)?;
 			// If the account has earned rewards, update the rewards storage
 			if earned != BTreeMap::<CurrencyIdOf<T>, BalanceOf<T>>::default() {
-				Rewards::<T>::insert(address, earned);
+				Rewards::<T>::insert(account, earned);
 			}
-			UserRewardPerTokenPaid::<T>::insert(address, reward_per_token_stored.clone());
+			UserRewardPerTokenPaid::<T>::insert(account, reward_per_token_stored.clone());
 		}
 		Ok(())
 	}
 
 	/// Update reward for all pools
-	pub fn update_reward_all(addr: &AccountIdOf<T>) -> DispatchResult {
-		UserFarmingPool::<T>::get(addr)
+	pub fn update_reward_all(who: &AccountIdOf<T>) -> DispatchResult {
+		UserFarmingPool::<T>::get(who)
 			.iter()
 			.try_for_each(|&pool_id| -> DispatchResult {
-				Self::update_reward(pool_id, Some(addr), None)
+				Self::update_reward(pool_id, Some(who), None)
 			})?;
-		Self::update_reward(VE_MINTING_SYSTEM_POOL_ID, Some(addr), None)?;
+		Self::update_reward(BB_BNC_SYSTEM_POOL_ID, Some(who), None)?;
 		Ok(())
 	}
 
 	///Transfer rewards into an account
 	pub fn get_rewards_inner(
 		pool_id: PoolId,
-		addr: &AccountIdOf<T>,
+		who: &AccountIdOf<T>,
 		share_info: Option<(BalanceOf<T>, BalanceOf<T>)>,
 	) -> DispatchResult {
-		Self::update_reward(pool_id, Some(addr), share_info)?;
-		if Self::balance_of_current_block(addr)? == BalanceOf::<T>::zero() {
+		Self::update_reward(pool_id, Some(who), share_info)?;
+		if Self::balance_of_current_block(who)? == BalanceOf::<T>::zero() {
 			return Ok(());
 		} // Excit earlier if balance of token is zero
-		if let Some(rewards) = Rewards::<T>::get(addr) {
+		if let Some(rewards) = Rewards::<T>::get(who) {
 			rewards.iter().try_for_each(|(currency, &reward)| -> DispatchResult {
 				T::MultiCurrency::transfer(
 					*currency,
 					&T::IncentivePalletId::get().into_account_truncating(),
-					addr,
+					who,
 					reward,
 				)
 			})?;
-			Rewards::<T>::remove(addr);
+			Rewards::<T>::remove(who);
 			Self::deposit_event(Event::Rewarded {
-				addr: addr.to_owned(),
+				who: who.to_owned(),
 				rewards: rewards.into_iter().collect(),
 			});
 		}
@@ -245,11 +253,11 @@ impl<T: Config> Pallet<T> {
 	// Motion
 	pub fn notify_reward_amount(
 		pool_id: PoolId,
-		addr: &Option<AccountIdOf<T>>,
+		who: &Option<AccountIdOf<T>>,
 		rewards: Vec<(CurrencyIdOf<T>, BalanceOf<T>)>,
 	) -> DispatchResult {
-		let who = match addr {
-			Some(addr) => addr,
+		let account = match who {
+			Some(who) => who,
 			None => return Err(Error::<T>::NoController.into()),
 		};
 		Self::update_reward(pool_id, None, None)?;
@@ -257,17 +265,17 @@ impl<T: Config> Pallet<T> {
 		let current_block_number: BlockNumberFor<T> = frame_system::Pallet::<T>::block_number();
 
 		if current_block_number >= conf.period_finish {
-			Self::add_reward(who, &mut conf, &rewards, Zero::zero())?;
+			Self::add_reward(&account, &mut conf, &rewards, Zero::zero())?;
 		} else {
 			let remaining = T::BlockNumberToBalance::convert(
 				conf.period_finish.saturating_sub(current_block_number),
 			);
-			Self::add_reward(who, &mut conf, &rewards, remaining)?;
+			Self::add_reward(&account, &mut conf, &rewards, remaining)?;
 		};
 
 		conf.last_update_time = current_block_number;
 		conf.period_finish = current_block_number.saturating_add(conf.rewards_duration);
-		conf.incentive_controller = Some(who.clone());
+		conf.incentive_controller = Some(account.clone());
 		conf.last_reward = rewards.clone();
 		IncentiveConfigs::<T>::set(pool_id, conf);
 
diff --git a/pallets/bb-bnc/src/lib.rs b/pallets/bb-bnc/src/lib.rs
index 3e0728af3..e88290f02 100644
--- a/pallets/bb-bnc/src/lib.rs
+++ b/pallets/bb-bnc/src/lib.rs
@@ -60,13 +60,14 @@ pub type CurrencyIdOf<T> = <<T as Config>::MultiCurrency as MultiCurrency<
 	<T as frame_system::Config>::AccountId,
 >>::CurrencyId;
 
-const VE_LOCK_ID: LockIdentifier = *b"vebnclck";
-const MARKUP_LOCK_ID: LockIdentifier = *b"vebncmkp";
-const VE_MINTING_SYSTEM_POOL_ID: PoolId = u32::MAX;
+const BB_LOCK_ID: LockIdentifier = *b"bbbnclck";
+const MARKUP_LOCK_ID: LockIdentifier = *b"bbbncmkp";
+const BB_BNC_SYSTEM_POOL_ID: PoolId = u32::MAX;
 #[derive(Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo, Default)]
-pub struct VeConfig<Balance, BlockNumber> {
-	amount: Balance,
+pub struct BbConfig<Balance, BlockNumber> {
+	/// Minimum number of TokenType that users can lock
 	min_mint: Balance,
+	/// Minimum time that users can lock
 	min_block: BlockNumber,
 }
 
@@ -131,6 +132,7 @@ pub mod pallet {
 		#[pallet::constant]
 		type MaxPositions: Get<u32>;
 
+		/// Maximum number of users per refresh.
 		#[pallet::constant]
 		type MarkupRefreshLimit: Get<u32>;
 	}
@@ -138,82 +140,132 @@ pub mod pallet {
 	#[pallet::event]
 	#[pallet::generate_deposit(pub(super) fn deposit_event)]
 	pub enum Event<T: Config> {
-		ConfigSet {
-			config: VeConfig<BalanceOf<T>, BlockNumberFor<T>>,
-		},
+		/// The minimum number of TokenType and minimum time that users can lock has been set.
+		ConfigSet { config: BbConfig<BalanceOf<T>, BlockNumberFor<T>> },
+		/// A successful call of the `create_lock` function.
 		Minted {
-			addr: u128,
+			/// the user who mint
+			who: AccountIdOf<T>,
+			/// the position of this minting
+			position: u128,
+			/// the value of this minting
 			value: BalanceOf<T>,
+			/// total mint value for this user
+			total_value: BalanceOf<T>,
+			/// withdrawable time
 			end: BlockNumberFor<T>,
+			/// current time
 			now: BlockNumberFor<T>,
 		},
+		/// Change in TokenType locked after calling.
 		Supply {
+			/// The balance before the change.
 			supply_before: BalanceOf<T>,
+			/// The balance after the change.
 			supply: BalanceOf<T>,
 		},
+		/// A position was created.
 		LockCreated {
-			addr: AccountIdOf<T>,
+			/// Position owner
+			who: AccountIdOf<T>,
+			/// Position ID
+			position: u128,
+			/// Locked value
 			value: BalanceOf<T>,
+			/// withdrawable time
 			unlock_time: BlockNumberFor<T>,
 		},
+		/// A position was extended.
 		UnlockTimeIncreased {
-			addr: u128,
+			/// Position owner
+			who: AccountIdOf<T>,
+			/// Position ID
+			position: u128,
+			/// New withdrawable time
 			unlock_time: BlockNumberFor<T>,
 		},
+		/// A position was increased.
 		AmountIncreased {
+			/// Position owner
 			who: AccountIdOf<T>,
+			/// Position ID
 			position: u128,
+			/// Increased value, not new locked value
 			value: BalanceOf<T>,
 		},
+		/// A position was withdrawn.
 		Withdrawn {
-			addr: u128,
+			/// Position owner
+			who: AccountIdOf<T>,
+			/// Position ID
+			position: u128,
+			/// Withdrawn value
 			value: BalanceOf<T>,
 		},
+		/// Incentive config set.
 		IncentiveSet {
 			incentive_config:
 				IncentiveConfig<CurrencyIdOf<T>, BalanceOf<T>, BlockNumberFor<T>, AccountIdOf<T>>,
 		},
-		RewardAdded {
-			rewards: Vec<(CurrencyIdOf<T>, BalanceOf<T>)>,
-		},
-		Rewarded {
-			addr: AccountIdOf<T>,
-			rewards: Vec<(CurrencyIdOf<T>, BalanceOf<T>)>,
-		},
-		AllRefreshed {
-			asset_id: CurrencyIdOf<T>,
-		},
-		PartiallyRefreshed {
-			asset_id: CurrencyIdOf<T>,
-		},
-		NotifyRewardFailed {
-			rewards: Vec<(CurrencyIdOf<T>, BalanceOf<T>)>,
+		/// The rewards for this round have been added to the system account.
+		RewardAdded { rewards: Vec<(CurrencyIdOf<T>, BalanceOf<T>)> },
+		/// The user has received the reward.
+		Rewarded { who: AccountIdOf<T>, rewards: Vec<(CurrencyIdOf<T>, BalanceOf<T>)> },
+		/// This currency_id has been refreshed.
+		AllRefreshed { currency_id: CurrencyIdOf<T> },
+		/// This currency_id has been partially refreshed.
+		PartiallyRefreshed { currency_id: CurrencyIdOf<T> },
+		/// Notify reward failed.
+		NotifyRewardFailed { rewards: Vec<(CurrencyIdOf<T>, BalanceOf<T>)> },
+		/// Markup has been deposited.
+		MarkupDeposited {
+			/// The user who deposited
+			who: AccountIdOf<T>,
+			/// The token type of the deposit
+			currency_id: CurrencyIdOf<T>,
+			/// The amount of currency_id to be deposited this time
+			value: BalanceOf<T>,
 		},
+		/// Markup has been withdrawn.
+		MarkupWithdrawn { who: AccountIdOf<T>, currency_id: CurrencyIdOf<T> },
 	}
 
 	#[pallet::error]
 	pub enum Error<T> {
+		/// Not enough balance
 		NotEnoughBalance,
+		/// Block number is expired
 		Expired,
+		/// Below minimum mint
 		BelowMinimumMint,
+		/// Lock does not exist
 		LockNotExist,
+		/// Lock already exists
 		LockExist,
+		/// Arguments error
 		ArgumentsError,
+		/// Exceeds max positions
 		ExceedsMaxPositions,
+		/// No controller
 		NoController,
+		/// User farming pool overflow
 		UserFarmingPoolOverflow,
 	}
 
+	/// Total supply of locked tokens
 	#[pallet::storage]
 	pub type Supply<T: Config> = StorageValue<_, BalanceOf<T>, ValueQuery>;
 
+	/// Configurations
 	#[pallet::storage]
-	pub type VeConfigs<T: Config> =
-		StorageValue<_, VeConfig<BalanceOf<T>, BlockNumberFor<T>>, ValueQuery>;
+	pub type BbConfigs<T: Config> =
+		StorageValue<_, BbConfig<BalanceOf<T>, BlockNumberFor<T>>, ValueQuery>;
 
+	/// Global epoch
 	#[pallet::storage]
 	pub type Epoch<T: Config> = StorageValue<_, U256, ValueQuery>;
 
+	/// Locked tokens. [position => LockedBalance]
 	#[pallet::storage]
 	pub type Locked<T: Config> = StorageMap<
 		_,
@@ -223,15 +275,17 @@ pub mod pallet {
 		ValueQuery,
 	>;
 
+	/// User locked tokens. [who => value]
 	#[pallet::storage]
 	pub type UserLocked<T: Config> =
 		StorageMap<_, Blake2_128Concat, AccountIdOf<T>, BalanceOf<T>, ValueQuery>;
 
-	// Each week has a Point struct stored in PointHistory.
+	/// Each week has a Point struct stored in PointHistory.
 	#[pallet::storage]
 	pub type PointHistory<T: Config> =
 		StorageMap<_, Twox64Concat, U256, Point<BalanceOf<T>, BlockNumberFor<T>>, ValueQuery>;
 
+	/// User point history. [(who, epoch) => Point]
 	#[pallet::storage]
 	pub type UserPointHistory<T: Config> = StorageDoubleMap<
 		_,
@@ -243,14 +297,16 @@ pub mod pallet {
 		ValueQuery,
 	>;
 
+	/// User point epoch. [who => epoch]
 	#[pallet::storage]
 	pub type UserPointEpoch<T: Config> = StorageMap<_, Blake2_128Concat, u128, U256, ValueQuery>;
 
+	/// Slope changes. [block => slope]
 	#[pallet::storage]
 	pub type SlopeChanges<T: Config> =
 		StorageMap<_, Twox64Concat, BlockNumberFor<T>, i128, ValueQuery>;
 
-	// Incentive
+	/// Farming pool incentive configurations.[pool_id => IncentiveConfig]
 	#[pallet::storage]
 	pub type IncentiveConfigs<T: Config> = StorageMap<
 		_,
@@ -260,6 +316,7 @@ pub mod pallet {
 		ValueQuery,
 	>;
 
+	/// User reward per token paid. [who => reward per token]
 	#[pallet::storage]
 	pub type UserRewardPerTokenPaid<T: Config> = StorageMap<
 		_,
@@ -269,14 +326,17 @@ pub mod pallet {
 		ValueQuery,
 	>;
 
+	/// User rewards. [who => rewards]
 	#[pallet::storage]
 	pub type Rewards<T: Config> =
 		StorageMap<_, Blake2_128Concat, AccountIdOf<T>, BTreeMap<CurrencyIdOf<T>, BalanceOf<T>>>;
 
+	/// User markup infos. [who => UserMarkupInfo]
 	#[pallet::storage]
 	pub type UserMarkupInfos<T: Config> =
 		StorageMap<_, Blake2_128Concat, AccountIdOf<T>, UserMarkupInfo>;
 
+	/// Locked tokens for markup. [(token, who) => value]
 	#[pallet::storage]
 	pub type LockedTokens<T: Config> = StorageDoubleMap<
 		_,
@@ -287,17 +347,21 @@ pub mod pallet {
 		LockedToken<BalanceOf<T>, BlockNumberFor<T>>,
 	>;
 
+	/// Total locked tokens for markup. [token => value]
 	#[pallet::storage]
 	pub type TotalLock<T: Config> =
 		StorageMap<_, Twox64Concat, CurrencyIdOf<T>, BalanceOf<T>, ValueQuery>;
 
+	/// Markup coefficient. [token => MarkupCoefficientInfo]
 	#[pallet::storage]
 	pub type MarkupCoefficient<T: Config> =
 		StorageMap<_, Twox64Concat, CurrencyIdOf<T>, MarkupCoefficientInfo<BlockNumberFor<T>>>;
 
+	/// The last position of all.
 	#[pallet::storage]
 	pub type Position<T: Config> = StorageValue<_, u128, ValueQuery>;
 
+	/// Positions owned by the user. [who => positions]
 	#[pallet::storage]
 	pub type UserPositions<T: Config> = StorageMap<
 		_,
@@ -320,10 +384,10 @@ pub mod pallet {
 	#[pallet::hooks]
 	impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
 		fn on_initialize(n: BlockNumberFor<T>) -> Weight {
-			let conf = IncentiveConfigs::<T>::get(VE_MINTING_SYSTEM_POOL_ID);
+			let conf = IncentiveConfigs::<T>::get(BB_BNC_SYSTEM_POOL_ID);
 			if n == conf.period_finish {
 				if let Some(e) = Self::notify_reward_amount(
-					VE_MINTING_SYSTEM_POOL_ID,
+					BB_BNC_SYSTEM_POOL_ID,
 					&conf.incentive_controller,
 					conf.last_reward.clone(),
 				)
@@ -344,28 +408,41 @@ pub mod pallet {
 
 	#[pallet::call]
 	impl<T: Config> Pallet<T> {
+		/// Set configuration.
+		///
+		/// Set the minimum number of tokens and minimum time that users can lock.
+		///
+		/// - `min_mint`: The minimum mint balance
+		/// - `min_block`: The minimum lockup time
 		#[pallet::call_index(0)]
 		#[pallet::weight(T::WeightInfo::set_config())]
 		pub fn set_config(
 			origin: OriginFor<T>,
-			min_mint: Option<BalanceOf<T>>,       // Minimum mint balance
-			min_block: Option<BlockNumberFor<T>>, // Minimum lockup time
+			min_mint: Option<BalanceOf<T>>,
+			min_block: Option<BlockNumberFor<T>>,
 		) -> DispatchResult {
 			T::ControlOrigin::ensure_origin(origin)?;
 
-			let mut ve_config = VeConfigs::<T>::get();
+			let mut bb_config = BbConfigs::<T>::get();
 			if let Some(min_mint) = min_mint {
-				ve_config.min_mint = min_mint;
+				bb_config.min_mint = min_mint;
 			};
 			if let Some(min_block) = min_block {
-				ve_config.min_block = min_block;
+				bb_config.min_block = min_block;
 			};
-			VeConfigs::<T>::set(ve_config.clone());
+			BbConfigs::<T>::set(bb_config.clone());
 
-			Self::deposit_event(Event::ConfigSet { config: ve_config });
+			Self::deposit_event(Event::ConfigSet { config: bb_config });
 			Ok(())
 		}
 
+		/// Create a lock.
+		///
+		/// If the signer already has a position, the position will not be extended. it will be
+		/// created a new position until the maximum number of positions is reached.
+		///
+		/// - `value`: The amount of tokens to lock
+		/// - `unlock_time`: The lockup time
 		#[pallet::call_index(1)]
 		#[pallet::weight(T::WeightInfo::create_lock())]
 		pub fn create_lock(
@@ -377,6 +454,14 @@ pub mod pallet {
 			Self::create_lock_inner(&exchanger, value, unlock_time)
 		}
 
+		/// Increase the lock amount.
+		///
+		/// If the signer does not have the position, it doesn't work and the position will not be
+		/// created. Only the position existed and owned by the signer, the locking amount will be
+		/// increased.
+		///
+		/// - `position`: The lock position
+		/// - `value`: The amount of tokens to increase
 		#[pallet::call_index(2)]
 		#[pallet::weight(T::WeightInfo::increase_amount())]
 		pub fn increase_amount(
@@ -385,12 +470,19 @@ pub mod pallet {
 			value: BalanceOf<T>,
 		) -> DispatchResult {
 			let exchanger = ensure_signed(origin)?;
-			// TODO: ensure postion is owned by exchanger
 			let user_positions = UserPositions::<T>::get(&exchanger);
 			ensure!(user_positions.contains(&position), Error::<T>::LockNotExist);
 			Self::increase_amount_inner(&exchanger, position, value)
 		}
 
+		/// Increase the unlock time.
+		///
+		/// If the signer does not have the position, it doesn't work and the position will not be
+		/// created. Only the position existed and owned by the signer, the locking time will be
+		/// increased.
+		///
+		/// - `position`: The lock position
+		/// - `time`: Additional lock time
 		#[pallet::call_index(3)]
 		#[pallet::weight(T::WeightInfo::increase_unlock_time())]
 		pub fn increase_unlock_time(
@@ -404,6 +496,9 @@ pub mod pallet {
 			Self::increase_unlock_time_inner(&exchanger, position, time)
 		}
 
+		/// Withdraw the locked tokens after unlock time.
+		///
+		/// - `position`: The lock position
 		#[pallet::call_index(4)]
 		#[pallet::weight(T::WeightInfo::withdraw())]
 		pub fn withdraw(origin: OriginFor<T>, position: u128) -> DispatchResult {
@@ -413,6 +508,16 @@ pub mod pallet {
 			Self::withdraw_inner(&exchanger, position)
 		}
 
+		/// Notify rewards.
+		///
+		/// Set the incentive controller and rewards token type for future round. Reward duration
+		/// should be one round interval. It will notify the rewards from incentive controller to
+		/// the system account and start a new round immediately, and the next round will auto start
+		/// at now + rewards_duration.
+		///
+		/// - `incentive_from`: The incentive controller
+		/// - `rewards_duration`: The rewards duration
+		/// - `rewards`: The rewards
 		#[pallet::call_index(5)]
 		#[pallet::weight(T::WeightInfo::notify_rewards())]
 		pub fn notify_rewards(
@@ -423,20 +528,26 @@ pub mod pallet {
 		) -> DispatchResult {
 			T::ControlOrigin::ensure_origin(origin)?;
 			Self::set_incentive(
-				VE_MINTING_SYSTEM_POOL_ID,
+				BB_BNC_SYSTEM_POOL_ID,
 				rewards_duration,
 				Some(incentive_from.clone()),
 			);
-			Self::notify_reward_amount(VE_MINTING_SYSTEM_POOL_ID, &Some(incentive_from), rewards)
+			Self::notify_reward_amount(BB_BNC_SYSTEM_POOL_ID, &Some(incentive_from), rewards)
 		}
 
+		/// Get rewards for the signer.
 		#[pallet::call_index(6)]
 		#[pallet::weight(T::WeightInfo::get_rewards())]
 		pub fn get_rewards(origin: OriginFor<T>) -> DispatchResult {
 			let exchanger = ensure_signed(origin)?;
-			Self::get_rewards_inner(VE_MINTING_SYSTEM_POOL_ID, &exchanger, None)
+			Self::get_rewards_inner(BB_BNC_SYSTEM_POOL_ID, &exchanger, None)
 		}
 
+		/// Fast unlocking, handling fee applies
+		///
+		/// When users want to redeem early regardless of cost, they can use this call.
+		///
+		/// - `position`: The lock position
 		#[pallet::call_index(7)]
 		#[pallet::weight(T::WeightInfo::redeem_unlock())]
 		pub fn redeem_unlock(origin: OriginFor<T>, position: u128) -> DispatchResult {
@@ -444,22 +555,27 @@ pub mod pallet {
 			Self::redeem_unlock_inner(&exchanger, position)
 		}
 
+		/// Set markup configurations.
+		///
+		/// - `currency_id`: The token type
+		/// - `markup`: The markup coefficient
+		/// - `hardcap`: The markup hardcap
 		#[pallet::call_index(8)]
 		#[pallet::weight(T::WeightInfo::set_markup_coefficient())]
 		pub fn set_markup_coefficient(
 			origin: OriginFor<T>,
-			asset_id: CurrencyId, // token类型
-			markup: FixedU128,    // 单位token的加成系数
-			hardcap: FixedU128,   // token对应加成硬顶
+			currency_id: CurrencyId,
+			markup: FixedU128,
+			hardcap: FixedU128,
 		) -> DispatchResult {
 			T::ControlOrigin::ensure_origin(origin)?;
 
-			if !TotalLock::<T>::contains_key(asset_id) {
-				TotalLock::<T>::insert(asset_id, BalanceOf::<T>::zero());
+			if !TotalLock::<T>::contains_key(currency_id) {
+				TotalLock::<T>::insert(currency_id, BalanceOf::<T>::zero());
 			}
 			let current_block_number: BlockNumberFor<T> = frame_system::Pallet::<T>::block_number();
 			MarkupCoefficient::<T>::insert(
-				asset_id,
+				currency_id,
 				MarkupCoefficientInfo {
 					markup_coefficient: markup,
 					hardcap,
@@ -469,33 +585,56 @@ pub mod pallet {
 			Ok(())
 		}
 
+		/// Deposit markup.
+		///
+		/// Deposit the token to the system account for the markup.
+		///
+		/// - `currency_id`: The token type
+		/// - `value`: The amount of tokens to deposit
 		#[pallet::call_index(9)]
 		#[pallet::weight(T::WeightInfo::deposit_markup())]
 		pub fn deposit_markup(
 			origin: OriginFor<T>,
-			asset_id: CurrencyIdOf<T>,
+			currency_id: CurrencyIdOf<T>,
 			value: BalanceOf<T>,
 		) -> DispatchResult {
-			Self::deposit_markup_inner(origin, asset_id, value)
+			let exchanger = ensure_signed(origin)?;
+			Self::deposit_markup_inner(&exchanger, currency_id, value)
 		}
 
+		/// Withdraw markup.
+		///
+		/// Withdraw the token from the system account for the markup.
+		///
+		/// - `currency_id`: The token type
 		#[pallet::call_index(10)]
 		#[pallet::weight(T::WeightInfo::withdraw_markup())]
-		pub fn withdraw_markup(origin: OriginFor<T>, asset_id: CurrencyIdOf<T>) -> DispatchResult {
-			Self::withdraw_markup_inner(origin, asset_id)
+		pub fn withdraw_markup(
+			origin: OriginFor<T>,
+			currency_id: CurrencyIdOf<T>,
+		) -> DispatchResult {
+			let exchanger = ensure_signed(origin)?;
+			Self::withdraw_markup_inner(&exchanger, currency_id)
 		}
 
+		/// Refresh the markup.
+		///
+		/// Any user can call this function to refresh the markup coefficient. The maximum number of
+		/// accounts that can be refreshed in one execution is MarkupRefreshLimit.
+		///
+		/// - `currency_id`: The token type
 		#[pallet::call_index(11)]
 		#[pallet::weight(T::WeightInfo::refresh())]
-		pub fn refresh(origin: OriginFor<T>, asset_id: CurrencyIdOf<T>) -> DispatchResult {
-			Self::refresh_inner(origin, asset_id)
+		pub fn refresh(origin: OriginFor<T>, currency_id: CurrencyIdOf<T>) -> DispatchResult {
+			let _exchanger = ensure_signed(origin)?;
+			Self::refresh_inner(currency_id)
 		}
 	}
 
 	impl<T: Config> Pallet<T> {
 		pub fn _checkpoint(
 			who: &AccountIdOf<T>,
-			addr: u128,
+			position: u128,
 			old_locked: LockedBalance<BalanceOf<T>, BlockNumberFor<T>>,
 			new_locked: LockedBalance<BalanceOf<T>, BlockNumberFor<T>>,
 		) -> DispatchResult {
@@ -652,21 +791,20 @@ pub mod pallet {
 			}
 
 			// Now handle user history
-			let user_epoch = UserPointEpoch::<T>::get(addr)
+			let user_epoch = UserPointEpoch::<T>::get(position)
 				.checked_add(U256::one())
 				.ok_or(ArithmeticError::Overflow)?;
-			UserPointEpoch::<T>::insert(addr, user_epoch);
+			UserPointEpoch::<T>::insert(position, user_epoch);
 			u_new.block = current_block_number;
-			// u_new.amount = Locked::<T>::get(addr).amount;
 			u_new.amount = new_locked.amount;
-			UserPointHistory::<T>::insert(addr, user_epoch, u_new);
+			UserPointHistory::<T>::insert(position, user_epoch, u_new);
 
 			Ok(())
 		}
 
 		pub fn _deposit_for(
 			who: &AccountIdOf<T>,
-			addr: u128,
+			position: u128,
 			value: BalanceOf<T>,
 			unlock_time: BlockNumberFor<T>,
 			locked_balance: LockedBalance<BalanceOf<T>, BlockNumberFor<T>>,
@@ -674,14 +812,15 @@ pub mod pallet {
 			let current_block_number: BlockNumberFor<T> = frame_system::Pallet::<T>::block_number();
 			let mut _locked = locked_balance;
 			let supply_before = Supply::<T>::get();
-			Supply::<T>::set(supply_before.checked_add(value).ok_or(ArithmeticError::Overflow)?);
+			let supply_after = supply_before.checked_add(value).ok_or(ArithmeticError::Overflow)?;
+			Supply::<T>::set(supply_after);
 
 			let old_locked = _locked.clone();
 			_locked.amount = _locked.amount.checked_add(value).ok_or(ArithmeticError::Overflow)?;
 			if unlock_time != Zero::zero() {
 				_locked.end = unlock_time
 			}
-			Locked::<T>::insert(addr, _locked.clone());
+			Locked::<T>::insert(position, _locked.clone());
 
 			let free_balance = T::MultiCurrency::free_balance(T::TokenType::get(), &who);
 			if value != BalanceOf::<T>::zero() {
@@ -694,36 +833,35 @@ pub mod pallet {
 
 			Self::markup_calc(
 				who,
-				addr,
+				position,
 				old_locked,
 				_locked.clone(),
 				UserMarkupInfos::<T>::get(who).as_ref(),
 			)?;
 
 			Self::deposit_event(Event::Minted {
-				addr,
+				who: who.clone(),
+				position,
 				value,
+				total_value: _locked.amount,
 				end: _locked.end,
 				now: current_block_number,
 			});
-			Self::deposit_event(Event::Supply {
-				supply_before,
-				supply: supply_before.checked_add(value).ok_or(ArithmeticError::Overflow)?,
-			});
+			Self::deposit_event(Event::Supply { supply_before, supply: supply_after });
 			Ok(())
 		}
 
-		// Get the current voting power for `addr`
+		// Get the current voting power for `position`
 		pub(crate) fn balance_of_position_current_block(
-			addr: u128,
+			position: u128,
 		) -> Result<BalanceOf<T>, DispatchError> {
 			let current_block_number: BlockNumberFor<T> = frame_system::Pallet::<T>::block_number();
-			let u_epoch = UserPointEpoch::<T>::get(addr);
+			let u_epoch = UserPointEpoch::<T>::get(position);
 			if u_epoch == U256::zero() {
 				return Ok(Zero::zero());
 			} else {
 				let mut last_point: Point<BalanceOf<T>, BlockNumberFor<T>> =
-					UserPointHistory::<T>::get(addr, u_epoch);
+					UserPointHistory::<T>::get(position, u_epoch);
 
 				last_point.bias = last_point
 					.bias
@@ -749,9 +887,9 @@ pub mod pallet {
 			}
 		}
 
-		// Measure voting power of `addr` at block height `block`
+		// Measure voting power of `position` at block height `block`
 		pub(crate) fn balance_of_position_at(
-			addr: u128,
+			position: u128,
 			block: BlockNumberFor<T>,
 		) -> Result<BalanceOf<T>, DispatchError> {
 			let current_block_number: BlockNumberFor<T> = frame_system::Pallet::<T>::block_number();
@@ -759,7 +897,7 @@ pub mod pallet {
 
 			// Binary search
 			let mut _min = U256::zero();
-			let mut _max = UserPointEpoch::<T>::get(addr);
+			let mut _max = UserPointEpoch::<T>::get(position);
 			for _i in 0..128 {
 				if _min >= _max {
 					break;
@@ -772,7 +910,7 @@ pub mod pallet {
 				.checked_div(U256::from(2_u128))
 				.ok_or(ArithmeticError::Overflow)?;
 
-				if UserPointHistory::<T>::get(addr, _mid).block <= block {
+				if UserPointHistory::<T>::get(position, _mid).block <= block {
 					_min = _mid
 				} else {
 					_max = _mid.checked_sub(U256::one()).ok_or(ArithmeticError::Overflow)?
@@ -780,7 +918,7 @@ pub mod pallet {
 			}
 
 			let mut upoint: Point<BalanceOf<T>, BlockNumberFor<T>> =
-				UserPointHistory::<T>::get(addr, _min);
+				UserPointHistory::<T>::get(position, _min);
 			upoint.bias = upoint
 				.bias
 				.checked_sub(
@@ -804,11 +942,11 @@ pub mod pallet {
 		}
 
 		pub(crate) fn balance_of_at(
-			addr: &AccountIdOf<T>,
+			who: &AccountIdOf<T>,
 			block: BlockNumberFor<T>,
 		) -> Result<BalanceOf<T>, DispatchError> {
 			let mut balance = BalanceOf::<T>::zero();
-			UserPositions::<T>::get(addr).into_iter().try_for_each(
+			UserPositions::<T>::get(who).into_iter().try_for_each(
 				|position| -> DispatchResult {
 					balance = balance
 						.checked_add(Self::balance_of_position_at(position, block)?)
@@ -820,10 +958,10 @@ pub mod pallet {
 		}
 
 		pub(crate) fn balance_of_current_block(
-			addr: &AccountIdOf<T>,
+			who: &AccountIdOf<T>,
 		) -> Result<BalanceOf<T>, DispatchError> {
 			let mut balance = BalanceOf::<T>::zero();
-			UserPositions::<T>::get(addr).into_iter().try_for_each(
+			UserPositions::<T>::get(who).into_iter().try_for_each(
 				|position| -> DispatchResult {
 					balance = balance
 						.checked_add(Self::balance_of_position_current_block(position)?)
@@ -835,7 +973,7 @@ pub mod pallet {
 		}
 
 		pub fn markup_calc(
-			addr: &AccountIdOf<T>,
+			who: &AccountIdOf<T>,
 			position: u128,
 			mut old_locked: LockedBalance<BalanceOf<T>, BlockNumberFor<T>>,
 			mut new_locked: LockedBalance<BalanceOf<T>, BlockNumberFor<T>>,
@@ -854,57 +992,59 @@ pub mod pallet {
 					.ok_or(ArithmeticError::Overflow)?;
 			}
 
-			Self::_checkpoint(addr, position, old_locked.clone(), new_locked.clone())?;
+			Self::_checkpoint(who, position, old_locked.clone(), new_locked.clone())?;
 			Ok(())
 		}
 
 		pub fn deposit_markup_inner(
-			origin: OriginFor<T>,
-			asset_id: CurrencyIdOf<T>,
+			who: &AccountIdOf<T>,
+			currency_id: CurrencyIdOf<T>,
 			value: BalanceOf<T>,
 		) -> DispatchResult {
-			let addr = ensure_signed(origin)?;
 			let markup_coefficient =
-				MarkupCoefficient::<T>::get(asset_id).ok_or(Error::<T>::ArgumentsError)?; // Ensure it is the correct token type.
+				MarkupCoefficient::<T>::get(currency_id).ok_or(Error::<T>::ArgumentsError)?; // Ensure it is the correct token type.
 			ensure!(!value.is_zero(), Error::<T>::ArgumentsError);
 
-			TotalLock::<T>::try_mutate(asset_id, |total_lock| -> DispatchResult {
+			TotalLock::<T>::try_mutate(currency_id, |total_lock| -> DispatchResult {
 				*total_lock = total_lock.checked_add(value).ok_or(ArithmeticError::Overflow)?;
 				Ok(())
 			})?;
 
 			let current_block_number: BlockNumberFor<T> = frame_system::Pallet::<T>::block_number();
 
-			let mut user_markup_info = UserMarkupInfos::<T>::get(&addr).unwrap_or_default();
-			let mut locked_token = LockedTokens::<T>::get(asset_id, &addr).unwrap_or(LockedToken {
-				amount: Zero::zero(),
-				markup_coefficient: Zero::zero(),
-				refresh_block: current_block_number,
-			});
+			let mut user_markup_info = UserMarkupInfos::<T>::get(&who).unwrap_or_default();
+			let mut locked_token =
+				LockedTokens::<T>::get(currency_id, &who).unwrap_or(LockedToken {
+					amount: Zero::zero(),
+					markup_coefficient: Zero::zero(),
+					refresh_block: current_block_number,
+				});
 			locked_token.amount = locked_token.amount.saturating_add(value);
 
 			let left: FixedU128 = FixedU128::checked_from_integer(locked_token.amount)
 				.and_then(|x| x.checked_mul(&markup_coefficient.markup_coefficient))
 				.and_then(|x| {
-					x.checked_div(&FixedU128::checked_from_integer(TotalLock::<T>::get(asset_id))?)
+					x.checked_div(&FixedU128::checked_from_integer(TotalLock::<T>::get(
+						currency_id,
+					))?)
 				})
 				.ok_or(ArithmeticError::Overflow)?;
 
-			let total_issuance = T::MultiCurrency::total_issuance(asset_id);
+			let total_issuance = T::MultiCurrency::total_issuance(currency_id);
 			let right: FixedU128 = FixedU128::checked_from_integer(locked_token.amount)
 				.and_then(|x| x.checked_mul(&markup_coefficient.markup_coefficient))
 				.and_then(|x| x.checked_div(&FixedU128::checked_from_integer(total_issuance)?))
 				.ok_or(ArithmeticError::Overflow)?;
 
-			let asset_id_markup_coefficient: FixedU128 =
+			let currency_id_markup_coefficient: FixedU128 =
 				left.checked_add(&right).ok_or(ArithmeticError::Overflow)?;
 			let new_markup_coefficient =
-				match markup_coefficient.hardcap.cmp(&asset_id_markup_coefficient) {
+				match markup_coefficient.hardcap.cmp(&currency_id_markup_coefficient) {
 					Ordering::Less => markup_coefficient.hardcap,
-					Ordering::Equal | Ordering::Greater => asset_id_markup_coefficient,
+					Ordering::Equal | Ordering::Greater => currency_id_markup_coefficient,
 				};
 			Self::update_markup_info(
-				&addr,
+				&who,
 				user_markup_info
 					.markup_coefficient
 					.saturating_sub(locked_token.markup_coefficient)
@@ -914,15 +1054,15 @@ pub mod pallet {
 			locked_token.markup_coefficient = new_markup_coefficient;
 			locked_token.refresh_block = current_block_number;
 
-			T::MultiCurrency::set_lock(MARKUP_LOCK_ID, asset_id, &addr, locked_token.amount)?;
-			LockedTokens::<T>::insert(&asset_id, &addr, locked_token);
-			UserPositions::<T>::get(&addr).into_iter().try_for_each(
+			T::MultiCurrency::set_lock(MARKUP_LOCK_ID, currency_id, &who, locked_token.amount)?;
+			LockedTokens::<T>::insert(&currency_id, &who, locked_token);
+			UserPositions::<T>::get(&who).into_iter().try_for_each(
 				|position| -> DispatchResult {
 					let _locked: LockedBalance<BalanceOf<T>, BlockNumberFor<T>> =
 						Locked::<T>::get(position);
 					ensure!(!_locked.amount.is_zero(), Error::<T>::ArgumentsError);
 					Self::markup_calc(
-						&addr,
+						&who,
 						position,
 						_locked.clone(),
 						_locked,
@@ -932,42 +1072,42 @@ pub mod pallet {
 			)?;
 
 			// Locked cannot be updated because it is markup, not a lock vBNC
+			Self::deposit_event(Event::MarkupDeposited { who: who.clone(), currency_id, value });
 			Ok(())
 		}
 
 		pub fn withdraw_markup_inner(
-			origin: OriginFor<T>,
-			asset_id: CurrencyIdOf<T>,
+			who: &AccountIdOf<T>,
+			currency_id: CurrencyIdOf<T>,
 		) -> DispatchResult {
-			let addr = ensure_signed(origin)?;
-			let _ = MarkupCoefficient::<T>::get(asset_id).ok_or(Error::<T>::ArgumentsError)?; // Ensure it is the correct token type.
+			let _ = MarkupCoefficient::<T>::get(currency_id).ok_or(Error::<T>::ArgumentsError)?; // Ensure it is the correct token type.
 
-			let mut user_markup_info = UserMarkupInfos::<T>::get(&addr).unwrap_or_default();
+			let mut user_markup_info = UserMarkupInfos::<T>::get(&who).unwrap_or_default();
 
 			let locked_token =
-				LockedTokens::<T>::get(&asset_id, &addr).ok_or(Error::<T>::LockNotExist)?;
+				LockedTokens::<T>::get(&currency_id, &who).ok_or(Error::<T>::LockNotExist)?;
 			Self::update_markup_info(
-				&addr,
+				&who,
 				user_markup_info
 					.markup_coefficient
 					.saturating_sub(locked_token.markup_coefficient),
 				&mut user_markup_info,
 			);
-			TotalLock::<T>::try_mutate(asset_id, |total_lock| -> DispatchResult {
+			TotalLock::<T>::try_mutate(currency_id, |total_lock| -> DispatchResult {
 				*total_lock =
 					total_lock.checked_sub(locked_token.amount).ok_or(ArithmeticError::Overflow)?;
 				Ok(())
 			})?;
-			T::MultiCurrency::remove_lock(MARKUP_LOCK_ID, asset_id, &addr)?;
+			T::MultiCurrency::remove_lock(MARKUP_LOCK_ID, currency_id, &who)?;
 
-			LockedTokens::<T>::remove(&asset_id, &addr);
-			UserPositions::<T>::get(&addr).into_iter().try_for_each(
+			LockedTokens::<T>::remove(&currency_id, &who);
+			UserPositions::<T>::get(&who).into_iter().try_for_each(
 				|position| -> DispatchResult {
 					let _locked: LockedBalance<BalanceOf<T>, BlockNumberFor<T>> =
 						Locked::<T>::get(position);
 					ensure!(!_locked.amount.is_zero(), Error::<T>::ArgumentsError); // TODO
 					Self::markup_calc(
-						&addr,
+						&who,
 						position,
 						_locked.clone(),
 						_locked,
@@ -975,21 +1115,21 @@ pub mod pallet {
 					)
 				},
 			)?;
+
+			Self::deposit_event(Event::MarkupWithdrawn { who: who.clone(), currency_id });
 			Ok(())
 		}
 
-		pub fn refresh_inner(origin: OriginFor<T>, asset_id: CurrencyIdOf<T>) -> DispatchResult {
-			let _who = ensure_signed(origin)?;
-
+		pub fn refresh_inner(currency_id: CurrencyIdOf<T>) -> DispatchResult {
 			let markup_coefficient =
-				MarkupCoefficient::<T>::get(asset_id).ok_or(Error::<T>::ArgumentsError)?;
+				MarkupCoefficient::<T>::get(currency_id).ok_or(Error::<T>::ArgumentsError)?;
 			let current_block_number: BlockNumberFor<T> = frame_system::Pallet::<T>::block_number();
 			let limit = T::MarkupRefreshLimit::get();
 			let mut all_refreshed = true;
 			let mut refresh_count = 0;
-			let locked_tokens = LockedTokens::<T>::iter_prefix(&asset_id);
+			let locked_tokens = LockedTokens::<T>::iter_prefix(&currency_id);
 
-			for (addr, mut locked_token) in locked_tokens {
+			for (who, mut locked_token) in locked_tokens {
 				if refresh_count >= limit {
 					all_refreshed = false;
 					break;
@@ -1002,31 +1142,31 @@ pub mod pallet {
 						.and_then(|x| x.checked_mul(&markup_coefficient.markup_coefficient))
 						.and_then(|x| {
 							x.checked_div(&FixedU128::checked_from_integer(TotalLock::<T>::get(
-								asset_id,
+								currency_id,
 							))?)
 						})
 						.ok_or(ArithmeticError::Overflow)?;
 
-					let total_issuance = T::MultiCurrency::total_issuance(asset_id);
+					let total_issuance = T::MultiCurrency::total_issuance(currency_id);
 					let right: FixedU128 = FixedU128::checked_from_integer(locked_token.amount)
 						.and_then(|x| x.checked_mul(&markup_coefficient.markup_coefficient))
 						.and_then(|x| {
 							x.checked_div(&FixedU128::checked_from_integer(total_issuance)?)
 						})
 						.ok_or(ArithmeticError::Overflow)?;
-					let asset_id_markup_coefficient: FixedU128 =
+					let currency_id_markup_coefficient: FixedU128 =
 						left.checked_add(&right).ok_or(ArithmeticError::Overflow)?;
 
 					let mut user_markup_info =
-						UserMarkupInfos::<T>::get(&addr).ok_or(Error::<T>::LockNotExist)?;
+						UserMarkupInfos::<T>::get(&who).ok_or(Error::<T>::LockNotExist)?;
 
 					let new_markup_coefficient =
-						match markup_coefficient.hardcap.cmp(&asset_id_markup_coefficient) {
+						match markup_coefficient.hardcap.cmp(&currency_id_markup_coefficient) {
 							Ordering::Less => markup_coefficient.hardcap,
-							Ordering::Equal | Ordering::Greater => asset_id_markup_coefficient,
+							Ordering::Equal | Ordering::Greater => currency_id_markup_coefficient,
 						};
 					Self::update_markup_info(
-						&addr,
+						&who,
 						user_markup_info
 							.markup_coefficient
 							.saturating_sub(locked_token.markup_coefficient)
@@ -1034,14 +1174,14 @@ pub mod pallet {
 						&mut user_markup_info,
 					);
 					locked_token.markup_coefficient = new_markup_coefficient;
-					LockedTokens::<T>::insert(&asset_id, &addr, locked_token);
-					UserPositions::<T>::get(&addr).into_iter().try_for_each(
+					LockedTokens::<T>::insert(&currency_id, &who, locked_token);
+					UserPositions::<T>::get(&who).into_iter().try_for_each(
 						|position| -> DispatchResult {
 							let _locked: LockedBalance<BalanceOf<T>, BlockNumberFor<T>> =
 								Locked::<T>::get(position);
 							ensure!(!_locked.amount.is_zero(), Error::<T>::ArgumentsError); // TODO
 							Self::markup_calc(
-								&addr,
+								&who,
 								position,
 								_locked.clone(),
 								_locked,
@@ -1055,9 +1195,9 @@ pub mod pallet {
 			}
 
 			if all_refreshed {
-				Self::deposit_event(Event::AllRefreshed { asset_id });
+				Self::deposit_event(Event::AllRefreshed { currency_id });
 			} else {
-				Self::deposit_event(Event::PartiallyRefreshed { asset_id });
+				Self::deposit_event(Event::PartiallyRefreshed { currency_id });
 			}
 			Ok(())
 		}
@@ -1084,7 +1224,8 @@ pub mod pallet {
 			Locked::<T>::insert(position, _locked.clone());
 
 			let supply_before = Supply::<T>::get();
-			Supply::<T>::set(supply_before.saturating_sub(value));
+			let supply_after = supply_before.checked_sub(value).ok_or(ArithmeticError::Overflow)?;
+			Supply::<T>::set(supply_after);
 
 			// BNC should be transferred before checkpoint
 			UserPositions::<T>::mutate(who, |positions| {
@@ -1107,11 +1248,8 @@ pub mod pallet {
 
 			Self::_checkpoint(who, position, old_locked, _locked.clone())?;
 
-			Self::deposit_event(Event::Withdrawn { addr: position, value });
-			Self::deposit_event(Event::Supply {
-				supply_before,
-				supply: supply_before.saturating_sub(value),
-			});
+			Self::deposit_event(Event::Withdrawn { who: who.clone(), position, value });
+			Self::deposit_event(Event::Supply { supply_before, supply: supply_after });
 			Ok(())
 		}
 
@@ -1146,11 +1284,11 @@ pub mod pallet {
 			match new_locked_balance {
 				0 => {
 					// Can not set lock to zero, should remove it.
-					T::MultiCurrency::remove_lock(VE_LOCK_ID, T::TokenType::get(), who)?;
+					T::MultiCurrency::remove_lock(BB_LOCK_ID, T::TokenType::get(), who)?;
 				},
 				_ => {
 					T::MultiCurrency::set_lock(
-						VE_LOCK_ID,
+						BB_LOCK_ID,
 						T::TokenType::get(),
 						who,
 						new_locked_balance,
diff --git a/pallets/bb-bnc/src/tests.rs b/pallets/bb-bnc/src/tests.rs
index 45a80b53f..2948290d3 100644
--- a/pallets/bb-bnc/src/tests.rs
+++ b/pallets/bb-bnc/src/tests.rs
@@ -196,7 +196,7 @@ fn update_reward() {
 		assert_eq!(BbBNC::balance_of(&BOB, None), Ok(25407883680));
 		assert_eq!(BbBNC::balance_of_position_current_block(0), Ok(25407883680));
 		assert_ok!(BbBNC::deposit_for(&BOB, 0, 100_000_000_000));
-		assert_ok!(BbBNC::update_reward(VE_MINTING_SYSTEM_POOL_ID, Some(&BOB), None)); // TODO
+		assert_ok!(BbBNC::update_reward(BB_BNC_SYSTEM_POOL_ID, Some(&BOB), None)); // TODO
 
 		assert_eq!(BbBNC::balance_of(&BOB, None), Ok(50818438500));
 		assert_eq!(BbBNC::balance_of(&BOB, Some(System::block_number())), Ok(50818438500));
@@ -253,7 +253,7 @@ fn notify_reward_amount() {
 		assert_ok!(BbBNC::get_rewards(RuntimeOrigin::signed(BOB)));
 		assert_eq!(Tokens::free_balance(KSM, &BOB), 396819);
 		System::set_block_number(System::block_number() + 7 * 86400 / 12);
-		assert_ok!(BbBNC::get_rewards_inner(VE_MINTING_SYSTEM_POOL_ID, &BOB, None));
+		assert_ok!(BbBNC::get_rewards_inner(BB_BNC_SYSTEM_POOL_ID, &BOB, None));
 		assert_eq!(Tokens::free_balance(KSM, &BOB), 999986398);
 		assert_ok!(BbBNC::notify_rewards(
 			RuntimeOrigin::root(),
@@ -267,14 +267,14 @@ fn notify_reward_amount() {
 			(4 * 365 * 86400 - 7 * 86400) / 12
 		));
 		System::set_block_number(System::block_number() + 1 * 86400 / 12);
-		assert_ok!(BbBNC::get_rewards_inner(VE_MINTING_SYSTEM_POOL_ID, &BOB, None));
+		assert_ok!(BbBNC::get_rewards_inner(BB_BNC_SYSTEM_POOL_ID, &BOB, None));
 		assert_eq!(Tokens::free_balance(KSM, &BOB), 1071241763);
-		assert_ok!(BbBNC::get_rewards_inner(VE_MINTING_SYSTEM_POOL_ID, &CHARLIE, None));
+		assert_ok!(BbBNC::get_rewards_inner(BB_BNC_SYSTEM_POOL_ID, &CHARLIE, None));
 		assert_eq!(Tokens::free_balance(KSM, &CHARLIE), 71599834);
 		System::set_block_number(System::block_number() + 7 * 86400 / 12);
-		assert_ok!(BbBNC::get_rewards_inner(VE_MINTING_SYSTEM_POOL_ID, &CHARLIE, None));
+		assert_ok!(BbBNC::get_rewards_inner(BB_BNC_SYSTEM_POOL_ID, &CHARLIE, None));
 		assert_eq!(Tokens::free_balance(KSM, &CHARLIE), 501203849);
-		assert_ok!(BbBNC::get_rewards_inner(VE_MINTING_SYSTEM_POOL_ID, &BOB, None));
+		assert_ok!(BbBNC::get_rewards_inner(BB_BNC_SYSTEM_POOL_ID, &BOB, None));
 		assert_eq!(Tokens::free_balance(KSM, &BOB), 1498768947);
 	});
 }
@@ -780,7 +780,7 @@ fn refresh_should_work() {
 			UserPointHistory::<Runtime>::get(POSITIONID0, U256::from(2)),
 			Point { bias: 0, slope: 0, block: 0, amount: 0 }
 		);
-		assert_ok!(BbBNC::refresh_inner(RuntimeOrigin::signed(BOB), VBNC));
+		assert_ok!(BbBNC::refresh_inner(VBNC));
 		assert_eq!(
 			UserPointHistory::<Runtime>::get(POSITIONID0, U256::one()),
 			Point { bias: 2796030953200, slope: 1046740, block: 20, amount: 11003333333333 }
diff --git a/pallets/bb-bnc/src/traits.rs b/pallets/bb-bnc/src/traits.rs
index 3c705aa0e..8f6ac48a0 100644
--- a/pallets/bb-bnc/src/traits.rs
+++ b/pallets/bb-bnc/src/traits.rs
@@ -24,7 +24,7 @@ use crate::*;
 pub trait BbBNCInterface<AccountId, CurrencyId, Balance, BlockNumber> {
 	fn deposit_for(_who: &AccountId, position: u128, value: Balance) -> DispatchResult;
 	fn withdraw_inner(who: &AccountId, position: u128) -> DispatchResult;
-	fn balance_of(addr: &AccountId, time: Option<BlockNumber>) -> Result<Balance, DispatchError>;
+	fn balance_of(who: &AccountId, time: Option<BlockNumber>) -> Result<Balance, DispatchError>;
 	fn total_supply(t: BlockNumber) -> Result<Balance, DispatchError>;
 	fn supply_at(
 		point: Point<Balance, BlockNumber>,
@@ -35,13 +35,13 @@ pub trait BbBNCInterface<AccountId, CurrencyId, Balance, BlockNumber> {
 		who: &AccountId,
 		_value: Balance,
 		_unlock_time: BlockNumber,
-	) -> DispatchResult; // Deposit `_value` BNC for `addr` and lock until `_unlock_time`
-	fn increase_amount_inner(who: &AccountId, position: u128, value: Balance) -> DispatchResult; // Deposit `_value` additional BNC for `addr` without modifying the unlock time
+	) -> DispatchResult; // Deposit `_value` BNC for `who` and lock until `_unlock_time`
+	fn increase_amount_inner(who: &AccountId, position: u128, value: Balance) -> DispatchResult; // Deposit `_value` additional BNC for `who` without modifying the unlock time
 	fn increase_unlock_time_inner(
 		who: &AccountId,
 		position: u128,
 		_unlock_time: BlockNumber,
-	) -> DispatchResult; // Extend the unlock time for `addr` to `_unlock_time`
+	) -> DispatchResult; // Extend the unlock time for `who` to `_unlock_time`
 	fn auto_notify_reward(
 		pool_id: PoolId,
 		n: BlockNumber,
@@ -49,12 +49,12 @@ pub trait BbBNCInterface<AccountId, CurrencyId, Balance, BlockNumber> {
 	) -> DispatchResult;
 	fn update_reward(
 		pool_id: PoolId,
-		addr: Option<&AccountId>,
+		who: Option<&AccountId>,
 		share_info: Option<(Balance, Balance)>,
 	) -> DispatchResult;
 	fn get_rewards(
 		pool_id: PoolId,
-		addr: &AccountId,
+		who: &AccountId,
 		share_info: Option<(Balance, Balance)>,
 	) -> DispatchResult;
 	fn set_incentive(
@@ -63,14 +63,14 @@ pub trait BbBNCInterface<AccountId, CurrencyId, Balance, BlockNumber> {
 		controller: Option<AccountId>,
 	);
 	fn add_reward(
-		addr: &AccountId,
+		who: &AccountId,
 		conf: &mut IncentiveConfig<CurrencyId, Balance, BlockNumber, AccountId>,
 		rewards: &Vec<(CurrencyId, Balance)>,
 		remaining: Balance,
 	) -> DispatchResult;
 	fn notify_reward(
 		pool_id: PoolId,
-		addr: &Option<AccountId>,
+		who: &Option<AccountId>,
 		rewards: Vec<(CurrencyId, Balance)>,
 	) -> DispatchResult;
 }
@@ -91,8 +91,8 @@ impl<T: Config> BbBNCInterface<AccountIdOf<T>, CurrencyIdOf<T>, BalanceOf<T>, Bl
 		UserPositions::<T>::insert(who, user_positions);
 		Position::<T>::set(new_position + 1);
 
-		let ve_config = VeConfigs::<T>::get();
-		ensure!(_value >= ve_config.min_mint, Error::<T>::BelowMinimumMint);
+		let bb_config = BbConfigs::<T>::get();
+		ensure!(_value >= bb_config.min_mint, Error::<T>::BelowMinimumMint);
 
 		let current_block_number: BlockNumberFor<T> = frame_system::Pallet::<T>::block_number();
 		let _locked: LockedBalance<BalanceOf<T>, BlockNumberFor<T>> =
@@ -106,7 +106,7 @@ impl<T: Config> BbBNCInterface<AccountIdOf<T>, CurrencyIdOf<T>, BalanceOf<T>, Bl
 			.ok_or(ArithmeticError::Overflow)?;
 
 		ensure!(
-			unlock_time >= ve_config.min_block.saturating_add(current_block_number),
+			unlock_time >= bb_config.min_block.saturating_add(current_block_number),
 			Error::<T>::ArgumentsError
 		);
 		let max_block = T::MaxBlock::get()
@@ -121,7 +121,8 @@ impl<T: Config> BbBNCInterface<AccountIdOf<T>, CurrencyIdOf<T>, BalanceOf<T>, Bl
 
 		Self::_deposit_for(who, new_position, _value, unlock_time, _locked)?;
 		Self::deposit_event(Event::LockCreated {
-			addr: who.to_owned(),
+			who: who.to_owned(),
+			position: new_position,
 			value: _value,
 			unlock_time: _unlock_time,
 		});
@@ -133,7 +134,7 @@ impl<T: Config> BbBNCInterface<AccountIdOf<T>, CurrencyIdOf<T>, BalanceOf<T>, Bl
 		position: u128,
 		_unlock_time: BlockNumberFor<T>,
 	) -> DispatchResult {
-		let ve_config = VeConfigs::<T>::get();
+		let bb_config = BbConfigs::<T>::get();
 		let _locked: LockedBalance<BalanceOf<T>, BlockNumberFor<T>> = Locked::<T>::get(position);
 		let current_block_number: BlockNumberFor<T> = frame_system::Pallet::<T>::block_number();
 
@@ -146,7 +147,7 @@ impl<T: Config> BbBNCInterface<AccountIdOf<T>, CurrencyIdOf<T>, BalanceOf<T>, Bl
 			.ok_or(ArithmeticError::Overflow)?;
 
 		ensure!(
-			unlock_time >= ve_config.min_block.saturating_add(current_block_number),
+			unlock_time >= bb_config.min_block.saturating_add(current_block_number),
 			Error::<T>::ArgumentsError
 		);
 		let max_block = T::MaxBlock::get()
@@ -162,8 +163,9 @@ impl<T: Config> BbBNCInterface<AccountIdOf<T>, CurrencyIdOf<T>, BalanceOf<T>, Bl
 
 		Self::_deposit_for(who, position, BalanceOf::<T>::zero(), unlock_time, _locked)?;
 		Self::deposit_event(Event::UnlockTimeIncreased {
-			addr: position.to_owned(),
-			unlock_time: _unlock_time,
+			who: who.to_owned(),
+			position,
+			unlock_time,
 		});
 		Ok(())
 	}
@@ -173,8 +175,8 @@ impl<T: Config> BbBNCInterface<AccountIdOf<T>, CurrencyIdOf<T>, BalanceOf<T>, Bl
 		position: u128,
 		value: BalanceOf<T>,
 	) -> DispatchResult {
-		let ve_config = VeConfigs::<T>::get();
-		ensure!(value >= ve_config.min_mint, Error::<T>::BelowMinimumMint);
+		let bb_config = BbConfigs::<T>::get();
+		ensure!(value >= bb_config.min_mint, Error::<T>::BelowMinimumMint);
 		let _locked: LockedBalance<BalanceOf<T>, BlockNumberFor<T>> = Locked::<T>::get(position);
 		ensure!(_locked.amount > BalanceOf::<T>::zero(), Error::<T>::LockNotExist); // Need to be executed after create_lock
 		let current_block_number: BlockNumberFor<T> = frame_system::Pallet::<T>::block_number();
@@ -197,12 +199,12 @@ impl<T: Config> BbBNCInterface<AccountIdOf<T>, CurrencyIdOf<T>, BalanceOf<T>, Bl
 	}
 
 	fn balance_of(
-		addr: &AccountIdOf<T>,
+		who: &AccountIdOf<T>,
 		time: Option<BlockNumberFor<T>>,
 	) -> Result<BalanceOf<T>, DispatchError> {
 		match time {
-			Some(_t) => Self::balance_of_at(addr, _t),
-			None => Self::balance_of_current_block(addr),
+			Some(_t) => Self::balance_of_at(who, _t),
+			None => Self::balance_of_current_block(who),
 		}
 	}
 
@@ -294,18 +296,18 @@ impl<T: Config> BbBNCInterface<AccountIdOf<T>, CurrencyIdOf<T>, BalanceOf<T>, Bl
 
 	fn update_reward(
 		pool_id: PoolId,
-		addr: Option<&AccountIdOf<T>>,
+		who: Option<&AccountIdOf<T>>,
 		share_info: Option<(BalanceOf<T>, BalanceOf<T>)>,
 	) -> DispatchResult {
-		Self::update_reward(pool_id, addr, share_info)
+		Self::update_reward(pool_id, who, share_info)
 	}
 
 	fn get_rewards(
 		pool_id: PoolId,
-		addr: &AccountIdOf<T>,
+		who: &AccountIdOf<T>,
 		share_info: Option<(BalanceOf<T>, BalanceOf<T>)>,
 	) -> DispatchResult {
-		Self::get_rewards_inner(pool_id, addr, share_info)
+		Self::get_rewards_inner(pool_id, who, share_info)
 	}
 
 	fn set_incentive(
@@ -326,7 +328,7 @@ impl<T: Config> BbBNCInterface<AccountIdOf<T>, CurrencyIdOf<T>, BalanceOf<T>, Bl
 	}
 
 	fn add_reward(
-		addr: &AccountIdOf<T>,
+		who: &AccountIdOf<T>,
 		conf: &mut IncentiveConfig<
 			CurrencyIdOf<T>,
 			BalanceOf<T>,
@@ -368,7 +370,7 @@ impl<T: Config> BbBNCInterface<AccountIdOf<T>, CurrencyIdOf<T>, BalanceOf<T>, Bl
 				.or_insert(new_reward);
 			T::MultiCurrency::transfer(
 				*currency,
-				addr,
+				who,
 				&T::IncentivePalletId::get().into_account_truncating(),
 				*reward,
 			)
@@ -377,10 +379,10 @@ impl<T: Config> BbBNCInterface<AccountIdOf<T>, CurrencyIdOf<T>, BalanceOf<T>, Bl
 
 	fn notify_reward(
 		pool_id: PoolId,
-		addr: &Option<AccountIdOf<T>>,
+		who: &Option<AccountIdOf<T>>,
 		rewards: Vec<(CurrencyIdOf<T>, BalanceOf<T>)>,
 	) -> DispatchResult {
-		Self::notify_reward_amount(pool_id, addr, rewards)
+		Self::notify_reward_amount(pool_id, who, rewards)
 	}
 }
 
@@ -417,7 +419,7 @@ where
 		Ok(())
 	}
 
-	fn balance_of(_addr: &AccountId, _time: Option<BlockNumber>) -> Result<Balance, DispatchError> {
+	fn balance_of(_who: &AccountId, _time: Option<BlockNumber>) -> Result<Balance, DispatchError> {
 		Ok(Zero::zero())
 	}
 
@@ -446,7 +448,7 @@ where
 
 	fn update_reward(
 		_pool_id: PoolId,
-		_addr: Option<&AccountId>,
+		_who: Option<&AccountId>,
 		_share_info: Option<(Balance, Balance)>,
 	) -> DispatchResult {
 		Ok(())
@@ -454,7 +456,7 @@ where
 
 	fn get_rewards(
 		_pool_id: PoolId,
-		_addr: &AccountId,
+		_who: &AccountId,
 		_share_info: Option<(Balance, Balance)>,
 	) -> DispatchResult {
 		Ok(())
@@ -467,7 +469,7 @@ where
 	) {
 	}
 	fn add_reward(
-		_addr: &AccountId,
+		_who: &AccountId,
 		_conf: &mut IncentiveConfig<CurrencyId, Balance, BlockNumber, AccountId>,
 		_rewards: &Vec<(CurrencyId, Balance)>,
 		_remaining: Balance,
@@ -476,7 +478,7 @@ where
 	}
 	fn notify_reward(
 		_pool_id: PoolId,
-		_addr: &Option<AccountId>,
+		_who: &Option<AccountId>,
 		_rewards: Vec<(CurrencyId, Balance)>,
 	) -> DispatchResult {
 		Ok(())
@@ -492,7 +494,7 @@ pub struct UserMarkupInfo {
 
 #[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, MaxEncodedLen, TypeInfo)]
 pub struct LockedToken<Balance, BlockNumber> {
-	// pub asset_id: CurrencyId,
+	// pub currency_id: CurrencyId,
 	pub amount: Balance,
 	pub markup_coefficient: FixedU128,
 	pub refresh_block: BlockNumber,
@@ -507,7 +509,7 @@ pub struct MarkupCoefficientInfo<BlockNumber> {
 
 pub trait MarkupInfo<AccountId> {
 	fn update_markup_info(
-		addr: &AccountId,
+		who: &AccountId,
 		new_markup_coefficient: FixedU128,
 		user_markup_info: &mut UserMarkupInfo,
 	);
@@ -515,12 +517,12 @@ pub trait MarkupInfo<AccountId> {
 
 impl<T: Config> MarkupInfo<AccountIdOf<T>> for Pallet<T> {
 	fn update_markup_info(
-		addr: &AccountIdOf<T>,
+		who: &AccountIdOf<T>,
 		new_markup_coefficient: FixedU128,
 		user_markup_info: &mut UserMarkupInfo,
 	) {
 		user_markup_info.old_markup_coefficient = user_markup_info.markup_coefficient;
 		user_markup_info.markup_coefficient = new_markup_coefficient;
-		UserMarkupInfos::<T>::insert(addr, user_markup_info);
+		UserMarkupInfos::<T>::insert(who, user_markup_info);
 	}
 }

From 766e60fa47b1845c427fddf2acadea1ac9c0198a Mon Sep 17 00:00:00 2001
From: NingBo Wang <2536935847@qq.com>
Date: Sun, 29 Sep 2024 15:17:11 +0800
Subject: [PATCH 08/31] Optimize slpx pallet (#1444)

---
 Cargo.lock                                 |   2 +
 pallets/slpx/Cargo.toml                    |  17 +-
 pallets/slpx/src/benchmarking.rs           |  30 +-
 pallets/slpx/src/lib.rs                    | 966 ++++++++++++---------
 pallets/slpx/src/migration.rs              |   2 +-
 pallets/slpx/src/mock.rs                   | 333 +------
 pallets/slpx/src/tests.rs                  | 269 +++---
 pallets/slpx/src/types.rs                  |  12 +
 runtime/bifrost-kusama/src/lib.rs          |   4 +-
 runtime/bifrost-polkadot/src/lib.rs        |   4 +-
 runtime/bifrost-polkadot/src/xcm_config.rs |   2 +
 11 files changed, 765 insertions(+), 876 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 8c990f909..dbf222895 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2014,9 +2014,11 @@ dependencies = [
  "orml-xtokens",
  "pallet-balances",
  "pallet-collective",
+ "pallet-staking",
  "pallet-xcm",
  "parity-scale-codec",
  "polkadot-parachain-primitives",
+ "polkadot-primitives",
  "scale-info",
  "serde",
  "sp-core",
diff --git a/pallets/slpx/Cargo.toml b/pallets/slpx/Cargo.toml
index ba5ed8a6b..ff9bf3ee6 100644
--- a/pallets/slpx/Cargo.toml
+++ b/pallets/slpx/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 name = "bifrost-slpx"
 description = "A pallet to manage the execution of XCM messages"
-authors = ["hqwangningbo <2536935847@qq.com>"]
+authors = ["Liebi Technologies <bifrost@liebi.com>"]
 edition = "2021"
 version = "0.8.0"
 
@@ -29,7 +29,6 @@ tiny-keccak = { workspace = true }
 orml-traits = { workspace = true }
 orml-xtokens = { workspace = true }
 zenlink-protocol = { workspace = true }
-
 bifrost-primitives = { workspace = true }
 bifrost-xcm-interface = { workspace = true }
 bifrost-asset-registry = { workspace = true }
@@ -37,6 +36,11 @@ bifrost-stable-pool = { workspace = true }
 bifrost-stable-asset = { workspace = true }
 orml-tokens = { workspace = true }
 log = { workspace = true }
+pallet-xcm  = { workspace = true }
+xcm-executor = { workspace = true }
+xcm-builder = { workspace = true }
+polkadot-primitives = { workspace = true }
+pallet-staking = { workspace = true }
 
 [dev-dependencies]
 hex = { workspace = true }
@@ -46,9 +50,6 @@ bifrost-vtoken-minting = { workspace = true }
 bifrost-slp = { workspace = true }
 cumulus-primitives-core = { workspace = true }
 bifrost-currencies = { workspace = true }
-xcm-executor = { workspace = true }
-xcm-builder = { workspace = true }
-pallet-xcm  = { workspace = true }
 xcm-simulator  = { workspace = true }
 bifrost-runtime-common = { workspace = true }
 pallet-collective = { workspace = true }
@@ -75,10 +76,15 @@ std = [
 	"cumulus-pallet-xcm/std",
 	"sp-core/std",
 	"sp-runtime/std",
+	"pallet-xcm/std",
 	"bifrost-asset-registry/std",
 	"bifrost-stable-pool/std",
 	"bifrost-stable-asset/std",
 	"log/std",
+	"xcm-executor/std",
+	"xcm-builder/std",
+	"polkadot-primitives/std",
+	"pallet-staking/std",
 ]
 runtime-benchmarks = [
 	"frame-benchmarking/runtime-benchmarks",
@@ -87,6 +93,7 @@ runtime-benchmarks = [
 	"pallet-xcm/runtime-benchmarks",
 	"xcm-builder/runtime-benchmarks",
 	"pallet-collective/runtime-benchmarks",
+	"pallet-staking/runtime-benchmarks",
 ]
 try-runtime = ["frame-support/try-runtime"]
 with-bifrost-polkadot-runtime = []
diff --git a/pallets/slpx/src/benchmarking.rs b/pallets/slpx/src/benchmarking.rs
index 1b914af4d..2c77e7f99 100644
--- a/pallets/slpx/src/benchmarking.rs
+++ b/pallets/slpx/src/benchmarking.rs
@@ -19,21 +19,20 @@
 
 use crate::*;
 use bifrost_asset_registry::CurrencyIdToLocations;
-use bifrost_primitives::{CurrencyId, KSM, VKSM};
+use bifrost_primitives::{KSM, VKSM};
 use frame_benchmarking::v2::*;
 use frame_support::{assert_ok, sp_runtime::traits::UniqueSaturatedFrom, BoundedVec};
 use frame_system::RawOrigin;
 
 fn init_whitelist<T: Config + bifrost_asset_registry::Config>() -> (T::AccountId, H160) {
 	let caller: T::AccountId = whitelisted_caller();
-	assert_ok!(Pallet::<T>::add_whitelist(
-		RawOrigin::Root.into(),
+	WhitelistAccountId::<T>::insert(
 		SupportChain::Astar,
-		caller.clone()
-	));
+		BoundedVec::try_from(vec![caller.clone()]).unwrap(),
+	);
 	let addr: [u8; 20] = hex_literal::hex!["3Cd0A705a2DC65e5b1E1205896BaA2be8A07c6e0"].into();
 	let receiver = H160::from(addr);
-	let evm_caller_account_id = Pallet::<T>::h160_to_account_id(receiver);
+	let evm_caller_account_id = Pallet::<T>::h160_to_account_id(&receiver);
 	assert_ok!(<T as Config>::MultiCurrency::deposit(
 		KSM,
 		&evm_caller_account_id,
@@ -52,29 +51,30 @@ fn init_whitelist<T: Config + bifrost_asset_registry::Config>() -> (T::AccountId
 	(caller, receiver)
 }
 
-#[benchmarks(where  T: Config + bifrost_asset_registry::Config + bifrost_stable_pool::Config + bifrost_stable_asset::Config + orml_tokens::Config<CurrencyId = CurrencyId>)]
+#[benchmarks(where  T: Config + bifrost_asset_registry::Config + orml_tokens::Config<CurrencyId = CurrencyId>)]
 mod benchmarks {
 	use super::*;
+	use hex_literal::hex;
 
 	#[benchmark]
 	fn add_whitelist() {
-		let contract: T::AccountId = whitelisted_caller();
+		let addr: [u8; 20] = hex_literal::hex!["3Cd0A705a2DC65e5b1E1205896BaA2be8A07c6e0"].into();
+		let receiver = H160::from(addr);
 
 		#[extrinsic_call]
-		_(RawOrigin::Root, SupportChain::Astar, contract.clone());
-
-		assert_eq!(WhitelistAccountId::<T>::get(SupportChain::Astar).first(), Some(&contract));
+		_(RawOrigin::Root, SupportChain::Astar, receiver);
 	}
 
 	#[benchmark]
 	fn remove_whitelist() {
-		let contract: T::AccountId = whitelisted_caller();
-		let whitelist = BoundedVec::try_from(vec![contract.clone()]).unwrap();
+		let address: [u8; 20] = hex!["c6bf0C5C78686f1D0E2E54b97D6de6e2cEFAe9fD"];
+		let address = H160::from_slice(&address);
 
-		WhitelistAccountId::<T>::insert(SupportChain::Astar, whitelist);
+		let _ =
+			crate::Pallet::<T>::add_whitelist(RawOrigin::Root.into(), SupportChain::Astar, address);
 
 		#[extrinsic_call]
-		_(RawOrigin::Root, SupportChain::Astar, contract.clone());
+		_(RawOrigin::Root, SupportChain::Astar, address);
 
 		assert_eq!(WhitelistAccountId::<T>::get(SupportChain::Astar).first(), None);
 	}
diff --git a/pallets/slpx/src/lib.rs b/pallets/slpx/src/lib.rs
index 37da11083..a51e96c89 100644
--- a/pallets/slpx/src/lib.rs
+++ b/pallets/slpx/src/lib.rs
@@ -24,9 +24,10 @@ use crate::types::{
 };
 use bifrost_asset_registry::AssetMetadata;
 use bifrost_primitives::{
-	currency::{BNC, VFIL},
-	AstarChainId, CurrencyId, CurrencyIdMapping, HydrationChainId, InterlayChainId, MantaChainId,
-	RedeemType, SlpxOperator, TokenInfo, VtokenMintingInterface,
+	currency::{BNC, MOVR, VFIL},
+	AstarChainId, Balance, BifrostKusamaChainId, CurrencyId, CurrencyIdMapping, HydrationChainId,
+	InterlayChainId, MantaChainId, RedeemType, SlpxOperator, TokenInfo, VtokenMintingInterface,
+	GLMR,
 };
 use cumulus_primitives_core::ParaId;
 use ethereum::TransactionAction;
@@ -53,7 +54,8 @@ use sp_runtime::{
 };
 use sp_std::{vec, vec::Vec};
 use xcm::v4::{prelude::*, Location};
-use zenlink_protocol::AssetBalance;
+use xcm_builder::{DescribeAllTerminal, DescribeFamily, HashedDescription};
+use xcm_executor::traits::ConvertLocation;
 
 pub mod migration;
 pub mod types;
@@ -73,15 +75,12 @@ mod benchmarking;
 #[frame_support::pallet]
 pub mod pallet {
 	use super::*;
-	use crate::types::{Order, OrderType};
-	use bifrost_primitives::{currency::MOVR, BifrostKusamaChainId, GLMR};
-	use bifrost_stable_pool::{traits::StablePoolHandler, PoolTokenIndex, StableAssetPoolId};
+	use crate::types::Order;
 	use frame_support::{
 		pallet_prelude::{ValueQuery, *},
 		weights::WeightMeter,
 	};
 	use frame_system::ensure_root;
-	use zenlink_protocol::{AssetId, ExportZenlink};
 
 	const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);
 
@@ -92,11 +91,13 @@ pub mod pallet {
 	#[pallet::config]
 	pub trait Config: frame_system::Config {
 		type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
+		type RuntimeOrigin: From<pallet_xcm::Origin>
+			+ From<<Self as frame_system::Config>::RuntimeOrigin>
+			+ Into<Result<pallet_xcm::Origin, <Self as Config>::RuntimeOrigin>>;
+		type WeightInfo: WeightInfo;
 		type ControlOrigin: EnsureOrigin<<Self as frame_system::Config>::RuntimeOrigin>;
 		type MultiCurrency: MultiCurrency<AccountIdOf<Self>, CurrencyId = CurrencyId>;
 
-		type DexOperator: ExportZenlink<Self::AccountId, AssetId>;
-
 		/// The interface to call VtokenMinting module functions.
 		type VtokenMintingInterface: VtokenMintingInterface<
 			AccountIdOf<Self>,
@@ -104,163 +105,152 @@ pub mod pallet {
 			BalanceOf<Self>,
 		>;
 
-		/// The interface to call StablePool module functions.
-		type StablePoolHandler: StablePoolHandler<
-			Balance = BalanceOf<Self>,
-			AccountId = AccountIdOf<Self>,
-			CurrencyId = CurrencyIdOf<Self>,
-		>;
-
 		/// xtokens xcm transfer interface
 		type XcmTransfer: XcmTransfer<AccountIdOf<Self>, BalanceOf<Self>, CurrencyIdOf<Self>>;
-
-		///
+		/// Send Xcm
 		type XcmSender: SendXcm;
-
 		/// Convert Location to `T::CurrencyId`.
 		type CurrencyIdConvert: CurrencyIdMapping<
 			CurrencyId,
 			xcm::v3::MultiLocation,
 			AssetMetadata<BalanceOf<Self>>,
 		>;
-
 		/// TreasuryAccount
 		#[pallet::constant]
 		type TreasuryAccount: Get<AccountIdOf<Self>>;
-
+		/// ParaId of the parachain
 		#[pallet::constant]
 		type ParachainId: Get<ParaId>;
-
-		type WeightInfo: WeightInfo;
+		/// The maximum number of order is 500
+		#[pallet::constant]
+		type MaxOrderSize: Get<u32>;
 	}
 
 	#[pallet::event]
 	#[pallet::generate_deposit(pub(super) fn deposit_event)]
 	pub enum Event<T: Config> {
+		/// Add the contract account to the whitelist
 		AddWhitelistAccountId {
+			/// The support chain of Slpx
 			support_chain: SupportChain,
+			/// The contract address of the contract
+			contract_address: H160,
+			/// Xcm derivative account id
 			evm_contract_account_id: AccountIdOf<T>,
 		},
+		/// Remove the contract account from the whitelist
 		RemoveWhitelistAccountId {
+			/// The support chain of Slpx
 			support_chain: SupportChain,
+			/// The contract address of the contract
+			contract_address: H160,
+			/// Xcm derivative account id
 			evm_contract_account_id: AccountIdOf<T>,
 		},
-		XcmMint {
-			evm_caller: H160,
-			currency_id: CurrencyIdOf<T>,
-			token_amount: BalanceOf<T>,
-			target_chain: TargetChain<AccountIdOf<T>>,
-		},
-		XcmMintFailed {
-			evm_caller: H160,
-			currency_id: CurrencyIdOf<T>,
-			token_amount: BalanceOf<T>,
-			target_chain: TargetChain<AccountIdOf<T>>,
-		},
-		XcmZenlinkSwap {
-			evm_caller: H160,
-			currency_id_in: CurrencyIdOf<T>,
-			currency_id_out: CurrencyIdOf<T>,
-			currency_id_out_amount: BalanceOf<T>,
-			target_chain: TargetChain<AccountIdOf<T>>,
-		},
-		XcmZenlinkSwapFailed {
-			evm_caller: H160,
-			currency_id_in: CurrencyIdOf<T>,
-			currency_id_out: CurrencyIdOf<T>,
-			currency_id_in_amount: BalanceOf<T>,
-			target_chain: TargetChain<AccountIdOf<T>>,
-		},
-		XcmStablePoolSwap {
-			evm_caller: H160,
-			pool_token_index_in: PoolTokenIndex,
-			pool_token_index_out: PoolTokenIndex,
-			currency_id_out_amount: BalanceOf<T>,
-			target_chain: TargetChain<AccountIdOf<T>>,
-		},
-		XcmStablePoolSwapFailed {
-			evm_caller: H160,
-			pool_token_index_in: PoolTokenIndex,
-			pool_token_index_out: PoolTokenIndex,
-			currency_id_in_amount: BalanceOf<T>,
-			target_chain: TargetChain<AccountIdOf<T>>,
-		},
-		XcmRedeem {
-			evm_caller: H160,
-			vtoken_id: CurrencyIdOf<T>,
-			vtoken_amount: BalanceOf<T>,
-			target_chain: TargetChain<AccountIdOf<T>>,
-		},
-		XcmRedeemFailed {
-			evm_caller: H160,
-			vtoken_id: CurrencyIdOf<T>,
-			vtoken_amount: BalanceOf<T>,
-			target_chain: TargetChain<AccountIdOf<T>>,
-		},
+		/// Set the transfer fee for the currency, only for Moonbeam
 		SetTransferToFee {
+			/// The support chain of Slpx
 			support_chain: SupportChain,
+			/// The transfer fee of the token
 			transfer_to_fee: BalanceOf<T>,
 		},
+		/// Set the execution fee for the order
 		SetExecutionFee {
+			/// The currency id of the token
 			currency_id: CurrencyId,
+			/// The execution fee of the order
 			execution_fee: BalanceOf<T>,
 		},
-		SetCurrencyEthereumCallSwitch {
+		/// Support currency to xcm oracle
+		SupportXcmOracle {
+			/// The currency id of the token
 			currency_id: CurrencyId,
+			/// Whether to support the xcm oracle
 			is_support: bool,
 		},
-		SetEthereumCallConfiguration {
-			xcm_fee: u128,
+		/// Set the xcm oracle configuration
+		SetXcmOracleConfiguration {
+			/// The XCM fee of Sending Xcm
+			xcm_fee: Balance,
+			/// The XCM weight of Sending Xcm
 			xcm_weight: Weight,
+			/// The period of Sending Xcm
 			period: BlockNumberFor<T>,
+			/// The address of XcmOracle
 			contract: H160,
 		},
-		XcmSetTokenAmount {
+		/// Send Xcm message
+		XcmOracle {
+			/// The currency id of the token
 			currency_id: CurrencyId,
-			token_amount: BalanceOf<T>,
-			vcurrency_id: CurrencyId,
-			vtoken_amount: BalanceOf<T>,
+			/// The currency amount of staking
+			staking_currency_amount: BalanceOf<T>,
+			/// The currency id of the vtoken
+			v_currency_id: CurrencyId,
+			/// The currency total supply of vtoken
+			v_currency_total_supply: BalanceOf<T>,
 		},
+		/// Set the currency to support the XCM fee
 		SetCurrencyToSupportXcmFee {
+			/// The currency id of the token
 			currency_id: CurrencyId,
+			/// Whether to support the XCM fee
 			is_support: bool,
 		},
+		/// Set the delay block
 		SetDelayBlock {
+			/// The delay block
 			delay_block: BlockNumberFor<T>,
 		},
+		/// Create order
 		CreateOrder {
 			order: Order<AccountIdOf<T>, CurrencyIdOf<T>, BalanceOf<T>, BlockNumberFor<T>>,
 		},
+		/// Order handled
 		OrderHandled {
 			order: Order<AccountIdOf<T>, CurrencyIdOf<T>, BalanceOf<T>, BlockNumberFor<T>>,
 		},
+		/// Order failed
 		OrderFailed {
 			order: Order<AccountIdOf<T>, CurrencyIdOf<T>, BalanceOf<T>, BlockNumberFor<T>>,
 		},
+		/// Xcm oracle failed
+		XcmOracleFailed { error: DispatchError },
+		/// Withdraw xcm fee
 		InsufficientAssets,
 	}
 
 	#[pallet::error]
+	#[derive(Clone, PartialEq)]
 	pub enum Error<T> {
-		/// Token not found in vtoken minting
-		TokenNotFoundInVtokenMinting,
-		/// Token not found in zenlink
-		TokenNotFoundInZenlink,
 		/// Contract Account already exists in the whitelist
-		AccountIdAlreadyInWhitelist,
+		AccountAlreadyExists,
+		/// Currency already exists in the whitelist
+		CurrencyAlreadyExists,
 		/// Contract Account is not in the whitelist
-		AccountIdNotInWhitelist,
+		AccountNotFound,
+		/// Currency is not in the whitelist
+		CurrencyNotFound,
 		/// The maximum number of whitelist addresses is 10
-		ExceededWhitelistMaxNumber,
+		WhitelistOverflow,
 		/// Execution fee not set
 		NotSetExecutionFee,
 		/// Insufficient balance to execute the fee
 		FreeBalanceTooLow,
-		/// ArgumentsError
-		ArgumentsError,
+		/// The maximum number of order is 500
+		OrderQueueOverflow,
+		/// The maximum number of currency id is 10
+		CurrencyListOverflow,
+		/// Convert vtoken error
 		ErrorConvertVtoken,
+		/// Error encode
+		ErrorEncode,
 		ErrorValidating,
 		ErrorDelivering,
+		ErrorVtokenMiting,
+		ErrorTransferTo,
+		ErrorChargeFee,
+		ErrorArguments,
 		Unsupported,
 	}
 
@@ -284,28 +274,33 @@ pub mod pallet {
 	pub type TransferToFee<T: Config> =
 		StorageMap<_, Blake2_128Concat, SupportChain, BalanceOf<T>, OptionQuery>;
 
+	/// Xcm Oracle configuration
 	#[pallet::storage]
 	pub type XcmEthereumCallConfiguration<T: Config> =
 		StorageValue<_, EthereumCallConfiguration<BlockNumberFor<T>>>;
 
+	/// Currency to support xcm oracle
 	#[pallet::storage]
 	pub type CurrencyIdList<T: Config> =
 		StorageValue<_, BoundedVec<CurrencyId, ConstU32<10>>, ValueQuery>;
 
+	/// Currency to support xcm fee
 	#[pallet::storage]
 	pub type SupportXcmFeeList<T: Config> =
 		StorageValue<_, BoundedVec<CurrencyId, ConstU32<100>>, ValueQuery>;
 
+	/// Order queue
 	#[pallet::storage]
 	pub type OrderQueue<T: Config> = StorageValue<
 		_,
 		BoundedVec<
 			Order<AccountIdOf<T>, CurrencyIdOf<T>, BalanceOf<T>, BlockNumberFor<T>>,
-			ConstU32<1000>,
+			T::MaxOrderSize,
 		>,
 		ValueQuery,
 	>;
 
+	/// Delay block
 	#[pallet::storage]
 	pub type DelayBlock<T: Config> = StorageValue<_, BlockNumberFor<T>, ValueQuery>;
 
@@ -315,7 +310,7 @@ pub mod pallet {
 			let mut weight = Weight::default();
 
 			if WeightMeter::with_limit(limit)
-				.try_consume(T::DbWeight::get().reads_writes(4, 2))
+				.try_consume(T::DbWeight::get().reads_writes(14, 8))
 				.is_err()
 			{
 				return weight;
@@ -323,105 +318,12 @@ pub mod pallet {
 
 			let mut is_handle_xcm_oracle = false;
 
-			let mut currency_list = CurrencyIdList::<T>::get().to_vec();
-			if currency_list.len() < 1 {
-				weight = weight.saturating_add(T::DbWeight::get().reads_writes(1, 0));
-			} else {
-				let configuration = XcmEthereumCallConfiguration::<T>::get();
-				match configuration {
-					Some(mut configuration) => {
-						let currency_id = currency_list[0];
-						let token_amount = T::VtokenMintingInterface::get_token_pool(currency_id);
-						// It's impossible to go wrong.
-						let vcurrency_id = T::VtokenMintingInterface::vtoken_id(currency_id)
-							.expect("Error convert vcurrency_id");
-						let vtoken_amount = T::MultiCurrency::total_issuance(vcurrency_id);
-
-						if configuration.last_block + configuration.period < n {
-							let encoded_call = Self::encode_transact_call(
-								configuration.contract,
-								currency_id,
-								token_amount,
-								vtoken_amount,
-							);
-
-							let result = Self::send_xcm_to_set_token_amount(
-								encoded_call,
-								configuration.xcm_weight,
-								configuration.xcm_fee,
-							);
-
-							if result.is_err() {
-								return weight
-									.saturating_add(T::DbWeight::get().reads_writes(4, 0));
-							}
-							Self::deposit_event(Event::XcmSetTokenAmount {
-								currency_id,
-								token_amount,
-								vcurrency_id,
-								vtoken_amount,
-							});
-
-							let mut target_fee_currency_id = GLMR;
-							if T::ParachainId::get() == Id::from(BifrostKusamaChainId::get()) {
-								target_fee_currency_id = MOVR;
-							}
-
-							// Will not check results and will be sent regardless of the success of
-							// the burning
-							let result = T::MultiCurrency::withdraw(
-								target_fee_currency_id,
-								&T::TreasuryAccount::get(),
-								BalanceOf::<T>::unique_saturated_from(configuration.xcm_fee),
-							);
-							if result.is_err() {
-								Self::deposit_event(Event::InsufficientAssets);
-							}
-
-							configuration.last_block = n;
-							XcmEthereumCallConfiguration::<T>::put(configuration);
-							currency_list.rotate_left(1);
-							CurrencyIdList::<T>::put(BoundedVec::try_from(currency_list).unwrap());
-
-							weight = weight.saturating_add(T::DbWeight::get().reads_writes(4, 2));
-
-							is_handle_xcm_oracle = true;
-						}
-					},
-					None => {
-						weight = weight.saturating_add(T::DbWeight::get().reads_writes(2, 0));
-					},
-				};
+			if let Err(error) = Self::handle_xcm_oracle(n, &mut is_handle_xcm_oracle, &mut weight) {
+				Self::deposit_event(Event::<T>::XcmOracleFailed { error });
 			}
 
 			if !is_handle_xcm_oracle {
-				OrderQueue::<T>::mutate(|order_queue| -> DispatchResult {
-					if let Some(order) = order_queue.get(0) {
-						if n - order.create_block_number >= DelayBlock::<T>::get() {
-							let mut order = order_queue.remove(0);
-							let balance = T::MultiCurrency::free_balance(
-								order.currency_id,
-								&order.derivative_account,
-							);
-							if balance > T::MultiCurrency::minimum_balance(order.currency_id) {
-								order.currency_amount = balance;
-								Self::handle_order(&order)
-									.map_err(|_| Error::<T>::ArgumentsError)?;
-								Self::deposit_event(Event::<T>::OrderHandled {
-									order: order.clone(),
-								});
-								weight =
-									weight.saturating_add(T::DbWeight::get().reads_writes(14, 8));
-							} else {
-								Self::deposit_event(Event::<T>::OrderFailed { order });
-								weight =
-									weight.saturating_add(T::DbWeight::get().reads_writes(4, 1));
-							}
-						};
-					};
-					Ok(())
-				})
-				.ok();
+				let _ = Self::handle_order_queue(n, &mut weight);
 			}
 			weight
 		}
@@ -430,6 +332,11 @@ pub mod pallet {
 	#[pallet::call]
 	impl<T: Config> Pallet<T> {
 		/// vtoken mint and transfer to target chain
+		/// Parameters:
+		/// - `evm_caller`: The caller of the EVM contract
+		/// - `currency_id`: The currency id of the token to be minted
+		/// - `target_chain`: The target chain to transfer the token to
+		/// - `remark`: The remark of the order
 		#[pallet::call_index(0)]
 		#[pallet::weight(<T as Config>::WeightInfo::mint())]
 		pub fn mint(
@@ -439,47 +346,26 @@ pub mod pallet {
 			target_chain: TargetChain<AccountIdOf<T>>,
 			remark: BoundedVec<u8, ConstU32<32>>,
 		) -> DispatchResultWithPostInfo {
-			let (source_chain_caller, derivative_account, bifrost_chain_caller) =
+			let (source_chain_caller, _, bifrost_chain_caller) =
 				Self::ensure_singer_on_whitelist(origin.clone(), evm_caller, &target_chain)?;
 
-			let order = Order {
-				create_block_number: <frame_system::Pallet<T>>::block_number(),
-				order_type: OrderType::Mint,
-				currency_amount: Default::default(),
+			Self::do_create_order(
 				source_chain_caller,
 				bifrost_chain_caller,
-				derivative_account,
 				currency_id,
+				Default::default(),
 				remark,
+				0u32,
 				target_chain,
-				// default to 0
-				channel_id: 0u32,
-			};
-
-			OrderQueue::<T>::mutate(|order_queue| -> DispatchResultWithPostInfo {
-				order_queue.try_push(order.clone()).map_err(|_| Error::<T>::ArgumentsError)?;
-				Self::deposit_event(Event::<T>::CreateOrder { order });
-				Ok(().into())
-			})
-		}
-
-		/// Swap and transfer to target chain
-		#[pallet::call_index(1)]
-		#[pallet::weight(<T as Config>::WeightInfo::zenlink_swap())]
-		pub fn zenlink_swap(
-			origin: OriginFor<T>,
-			_evm_caller: H160,
-			_currency_id_in: CurrencyIdOf<T>,
-			_currency_id_out: CurrencyIdOf<T>,
-			_currency_id_out_min: AssetBalance,
-			_target_chain: TargetChain<AccountIdOf<T>>,
-		) -> DispatchResultWithPostInfo {
-			ensure_signed(origin)?;
-			ensure!(false, Error::<T>::Unsupported);
-			Ok(().into())
+			)
 		}
 
-		/// Redeem
+		/// vtoken redeem and transfer to target chain
+		/// Parameters:
+		/// - `evm_caller`: The caller of the EVM contract
+		/// - `vtoken_id`: The currency id of the vtoken to be redeemed
+		/// - `target_chain`: The target chain to transfer the token to
+		/// - `remark`: The remark of the order
 		#[pallet::call_index(2)]
 		#[pallet::weight(<T as Config>::WeightInfo::redeem())]
 		pub fn redeem(
@@ -489,110 +375,96 @@ pub mod pallet {
 			target_chain: TargetChain<AccountIdOf<T>>,
 		) -> DispatchResultWithPostInfo {
 			let evm_contract_account_id = ensure_signed(origin.clone())?;
-			let (source_chain_caller, derivative_account, bifrost_chain_caller) =
+			let (source_chain_caller, frontier_derivative_account, bifrost_chain_caller) =
 				Self::ensure_singer_on_whitelist(origin, evm_caller, &target_chain)?;
 
 			if vtoken_id == VFIL {
-				let fee_amount = TransferToFee::<T>::get(SupportChain::Moonbeam)
-					.unwrap_or_else(|| Self::get_default_fee(BNC));
+				let fee_amount = Self::get_moonbeam_transfer_to_fee();
 				T::MultiCurrency::transfer(
 					BNC,
 					&evm_contract_account_id,
-					&derivative_account,
+					&frontier_derivative_account,
 					fee_amount,
 				)?;
 			}
 
-			let order = Order {
-				create_block_number: <frame_system::Pallet<T>>::block_number(),
-				order_type: OrderType::Redeem,
-				currency_id: vtoken_id,
-				currency_amount: Default::default(),
-				remark: Default::default(),
+			Self::do_create_order(
 				source_chain_caller,
 				bifrost_chain_caller,
-				derivative_account,
+				vtoken_id,
+				Default::default(),
+				Default::default(),
+				0u32,
 				target_chain,
-				// default to 0
-				channel_id: 0u32,
-			};
-
-			OrderQueue::<T>::mutate(|order_queue| -> DispatchResultWithPostInfo {
-				order_queue.try_push(order.clone()).map_err(|_| Error::<T>::ArgumentsError)?;
-				Self::deposit_event(Event::<T>::CreateOrder { order });
-				Ok(().into())
-			})
-		}
-
-		/// Stable pool swap
-		#[pallet::call_index(3)]
-		#[pallet::weight(<T as Config>::WeightInfo::stable_pool_swap())]
-		pub fn stable_pool_swap(
-			origin: OriginFor<T>,
-			_evm_caller: H160,
-			_pool_id: StableAssetPoolId,
-			_currency_id_in: CurrencyIdOf<T>,
-			_currency_id_out: CurrencyIdOf<T>,
-			_min_dy: BalanceOf<T>,
-			_target_chain: TargetChain<AccountIdOf<T>>,
-		) -> DispatchResult {
-			ensure_signed(origin)?;
-			ensure!(false, Error::<T>::Unsupported);
-			Ok(())
+			)
 		}
 
+		/// Add the contract account to the whitelist
+		/// Parameters:
+		/// - `support_chain`: The support chain of Slpx
+		/// - `contract_address`: The contract address of the contract
 		#[pallet::call_index(4)]
 		#[pallet::weight(<T as Config>::WeightInfo::add_whitelist())]
 		pub fn add_whitelist(
 			origin: OriginFor<T>,
 			support_chain: SupportChain,
-			evm_contract_account_id: T::AccountId,
+			contract_address: H160,
 		) -> DispatchResultWithPostInfo {
 			// Check the validity of origin
 			T::ControlOrigin::ensure_origin(origin)?;
 
-			let mut whitelist_account_ids = WhitelistAccountId::<T>::get(&support_chain);
-
-			ensure!(
-				!whitelist_account_ids.contains(&evm_contract_account_id),
-				Error::<T>::AccountIdAlreadyInWhitelist
-			);
-			whitelist_account_ids
-				.try_push(evm_contract_account_id.clone())
-				.map_err(|_| Error::<T>::ExceededWhitelistMaxNumber)?;
-			WhitelistAccountId::<T>::insert(support_chain, whitelist_account_ids);
-			Self::deposit_event(Event::AddWhitelistAccountId {
+			WhitelistAccountId::<T>::mutate(
 				support_chain,
-				evm_contract_account_id,
-			});
-			Ok(().into())
+				|whitelist| -> DispatchResultWithPostInfo {
+					let account = Self::xcm_derivative_account(support_chain, contract_address)?;
+					ensure!(!whitelist.contains(&account), Error::<T>::AccountAlreadyExists);
+					whitelist
+						.try_push(account.clone())
+						.map_err(|_| Error::<T>::WhitelistOverflow)?;
+					Self::deposit_event(Event::<T>::AddWhitelistAccountId {
+						support_chain,
+						contract_address,
+						evm_contract_account_id: account,
+					});
+					Ok(().into())
+				},
+			)
 		}
 
+		/// Remove the contract account from the whitelist
+		/// Parameters:
+		/// - `support_chain`: The support chain of Slpx
+		/// - `contract_address`: The contract address of the contract
 		#[pallet::call_index(5)]
 		#[pallet::weight(<T as Config>::WeightInfo::remove_whitelist())]
 		pub fn remove_whitelist(
 			origin: OriginFor<T>,
 			support_chain: SupportChain,
-			evm_contract_account_id: T::AccountId,
+			contract_address: H160,
 		) -> DispatchResultWithPostInfo {
 			// Check the validity of origin
 			T::ControlOrigin::ensure_origin(origin)?;
 
-			let mut whitelist_account_ids = WhitelistAccountId::<T>::get(&support_chain);
-
-			ensure!(
-				whitelist_account_ids.contains(&evm_contract_account_id),
-				Error::<T>::AccountIdNotInWhitelist
-			);
-			whitelist_account_ids.retain(|x| *x != evm_contract_account_id);
-			WhitelistAccountId::<T>::insert(support_chain, whitelist_account_ids);
-			Self::deposit_event(Event::RemoveWhitelistAccountId {
+			WhitelistAccountId::<T>::mutate(
 				support_chain,
-				evm_contract_account_id,
-			});
-			Ok(().into())
+				|whitelist| -> DispatchResultWithPostInfo {
+					let account = Self::xcm_derivative_account(support_chain, contract_address)?;
+					ensure!(whitelist.contains(&account), Error::<T>::AccountNotFound);
+					whitelist.retain(|x| *x != account);
+					Self::deposit_event(Event::<T>::RemoveWhitelistAccountId {
+						support_chain,
+						contract_address,
+						evm_contract_account_id: account,
+					});
+					Ok(().into())
+				},
+			)
 		}
 
+		/// Set the execution fee for the currency
+		/// Parameters:
+		/// - `currency_id`: The currency id of the token
+		/// - `execution_fee`: The execution fee of the token
 		#[pallet::call_index(6)]
 		#[pallet::weight(<T as Config>::WeightInfo::set_execution_fee())]
 		pub fn set_execution_fee(
@@ -607,6 +479,10 @@ pub mod pallet {
 			Ok(().into())
 		}
 
+		/// Set the transfer fee for the currency
+		/// Parameters:
+		/// - `support_chain`: The support chain of Slpx
+		/// - `transfer_to_fee`: The transfer fee of the token
 		#[pallet::call_index(7)]
 		#[pallet::weight(<T as Config>::WeightInfo::set_transfer_to_fee())]
 		pub fn set_transfer_to_fee(
@@ -621,9 +497,13 @@ pub mod pallet {
 			Ok(().into())
 		}
 
+		/// Set the currency to support the Ethereum call switch
+		/// Parameters:
+		/// - `currency_id`: The currency id of the token
+		/// - `is_support`: Whether to support the Ethereum call switch
 		#[pallet::call_index(8)]
 		#[pallet::weight(<T as Config>::WeightInfo::set_transfer_to_fee())]
-		pub fn set_currency_ethereum_call_switch(
+		pub fn support_xcm_oracle(
 			origin: OriginFor<T>,
 			currency_id: CurrencyId,
 			is_support: bool,
@@ -634,28 +514,31 @@ pub mod pallet {
 			T::VtokenMintingInterface::vtoken_id(currency_id)
 				.ok_or(Error::<T>::ErrorConvertVtoken)?;
 			let mut currency_list = CurrencyIdList::<T>::get();
-			match is_support {
-				true => {
-					ensure!(!currency_list.contains(&currency_id), Error::<T>::ArgumentsError);
-					currency_list
-						.try_push(currency_id)
-						.map_err(|_| Error::<T>::ExceededWhitelistMaxNumber)?;
-				},
-				false => {
-					ensure!(currency_list.contains(&currency_id), Error::<T>::ArgumentsError);
-					currency_list.retain(|&x| x != currency_id);
-				},
-			};
+			if is_support {
+				ensure!(!currency_list.contains(&currency_id), Error::<T>::CurrencyAlreadyExists);
+				currency_list
+					.try_push(currency_id)
+					.map_err(|_| Error::<T>::CurrencyListOverflow)?;
+			} else {
+				ensure!(currency_list.contains(&currency_id), Error::<T>::CurrencyNotFound);
+				currency_list.retain(|&x| x != currency_id);
+			}
 			CurrencyIdList::<T>::put(currency_list);
-			Self::deposit_event(Event::SetCurrencyEthereumCallSwitch { currency_id, is_support });
+			Self::deposit_event(Event::SupportXcmOracle { currency_id, is_support });
 			Ok(().into())
 		}
 
+		/// Set the Ethereum call configuration
+		/// Parameters:
+		/// - `xcm_fee`: The XCM fee of Sending Xcm
+		/// - `xcm_weight`: The XCM weight of Sending Xcm
+		/// - `period`: The period of Sending Xcm
+		/// - `contract`: The address of XcmOracle
 		#[pallet::call_index(9)]
 		#[pallet::weight(<T as Config>::WeightInfo::set_transfer_to_fee())]
-		pub fn set_ethereum_call_configration(
+		pub fn set_xcm_oracle_configuration(
 			origin: OriginFor<T>,
-			xcm_fee: u128,
+			xcm_fee: Balance,
 			xcm_weight: Weight,
 			period: BlockNumberFor<T>,
 			contract: H160,
@@ -668,7 +551,7 @@ pub mod pallet {
 				last_block: frame_system::Pallet::<T>::block_number(),
 				contract,
 			});
-			Self::deposit_event(Event::SetEthereumCallConfiguration {
+			Self::deposit_event(Event::SetXcmOracleConfiguration {
 				xcm_fee,
 				xcm_weight,
 				period,
@@ -677,6 +560,10 @@ pub mod pallet {
 			Ok(().into())
 		}
 
+		/// Set the currency to support the XCM fee
+		/// Parameters:
+		/// - `currency_id`: The currency id of the token
+		/// - `is_support`: Whether to support the XCM fee
 		#[pallet::call_index(10)]
 		#[pallet::weight(T::DbWeight::get().reads(1) + T::DbWeight::get().writes(1))]
 		pub fn set_currency_support_xcm_fee(
@@ -688,21 +575,23 @@ pub mod pallet {
 			T::ControlOrigin::ensure_origin(origin)?;
 
 			let mut currency_list = SupportXcmFeeList::<T>::get();
-			match is_support {
-				true => {
-					ensure!(!currency_list.contains(&currency_id), Error::<T>::ArgumentsError);
-					currency_list.try_push(currency_id).map_err(|_| Error::<T>::ArgumentsError)?;
-				},
-				false => {
-					ensure!(currency_list.contains(&currency_id), Error::<T>::ArgumentsError);
-					currency_list.retain(|&x| x != currency_id);
-				},
-			};
+			if is_support {
+				ensure!(!currency_list.contains(&currency_id), Error::<T>::CurrencyAlreadyExists);
+				currency_list
+					.try_push(currency_id)
+					.map_err(|_| Error::<T>::CurrencyListOverflow)?;
+			} else {
+				ensure!(currency_list.contains(&currency_id), Error::<T>::CurrencyNotFound);
+				currency_list.retain(|&x| x != currency_id);
+			}
 			SupportXcmFeeList::<T>::put(currency_list);
 			Self::deposit_event(Event::SetCurrencyToSupportXcmFee { currency_id, is_support });
 			Ok(().into())
 		}
 
+		/// Set the delay block, Order will be executed after the delay block.
+		/// Parameters:
+		/// - `delay_block`: The delay block
 		#[pallet::call_index(11)]
 		#[pallet::weight(T::DbWeight::get().reads(1) + T::DbWeight::get().writes(1))]
 		pub fn set_delay_block(
@@ -716,39 +605,44 @@ pub mod pallet {
 			Ok(().into())
 		}
 
+		/// Force add order
+		/// Parameters:
+		/// - `source_chain_caller`: The caller of the source chain
+		/// - `bifrost_chain_caller`: The caller of the bifrost chain
+		/// - `currency_id`: The currency id of the token
+		/// - `target_chain`: The target chain to transfer the token to
+		/// - `remark`: The remark of the order
+		/// - `channel_id`: The channel id of the order
 		#[pallet::call_index(12)]
 		#[pallet::weight(T::DbWeight::get().reads(1) + T::DbWeight::get().writes(1))]
 		pub fn force_add_order(
 			origin: OriginFor<T>,
-			slpx_contract_derivative_account: AccountIdOf<T>,
-			evm_caller: H160,
+			source_chain_caller: OrderCaller<T::AccountId>,
+			bifrost_chain_caller: T::AccountId,
 			currency_id: CurrencyIdOf<T>,
 			target_chain: TargetChain<AccountIdOf<T>>,
 			remark: BoundedVec<u8, ConstU32<32>>,
-			order_type: OrderType,
+			channel_id: u32,
 		) -> DispatchResultWithPostInfo {
 			ensure_root(origin)?;
-			let order = Order {
-				create_block_number: <frame_system::Pallet<T>>::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,
+			Self::do_create_order(
+				source_chain_caller,
+				bifrost_chain_caller,
 				currency_id,
+				Default::default(),
 				remark,
+				channel_id,
 				target_chain,
-				// default to 0
-				channel_id: 0u32,
-			};
-
-			OrderQueue::<T>::mutate(|order_queue| -> DispatchResultWithPostInfo {
-				order_queue.try_push(order.clone()).map_err(|_| Error::<T>::ArgumentsError)?;
-				Self::deposit_event(Event::<T>::CreateOrder { order });
-				Ok(().into())
-			})
+			)
 		}
 
+		/// vtoken mint and transfer to target chain
+		/// Parameters:
+		/// - `evm_caller`: The caller of the EVM contract
+		/// - `currency_id`: The currency id of the token to be minted
+		/// - `target_chain`: The target chain to transfer the token to
+		/// - `remark`: The remark of the order
+		/// - `channel_id`: The channel id of the order
 		#[pallet::call_index(13)]
 		#[pallet::weight(<T as Config>::WeightInfo::mint_with_channel_id())]
 		pub fn mint_with_channel_id(
@@ -759,32 +653,137 @@ pub mod pallet {
 			remark: BoundedVec<u8, ConstU32<32>>,
 			channel_id: u32,
 		) -> DispatchResultWithPostInfo {
-			let (source_chain_caller, derivative_account, bifrost_chain_caller) =
+			let (source_chain_caller, _, bifrost_chain_caller) =
 				Self::ensure_singer_on_whitelist(origin.clone(), evm_caller, &target_chain)?;
 
-			let order = Order {
-				create_block_number: <frame_system::Pallet<T>>::block_number(),
-				order_type: OrderType::Mint,
-				currency_amount: Default::default(),
+			Self::do_create_order(
 				source_chain_caller,
 				bifrost_chain_caller,
-				derivative_account,
 				currency_id,
+				Default::default(),
 				remark,
-				target_chain,
 				channel_id,
-			};
-
-			OrderQueue::<T>::mutate(|order_queue| -> DispatchResultWithPostInfo {
-				order_queue.try_push(order.clone()).map_err(|_| Error::<T>::ArgumentsError)?;
-				Self::deposit_event(Event::<T>::CreateOrder { order });
-				Ok(().into())
-			})
+				target_chain,
+			)
 		}
+
+		// TODO: Substrate user create order
+		// #[pallet::call_index(14)]
+		// #[pallet::weight(<T as Config>::WeightInfo::mint())]
+		// pub fn substrate_create_order(
+		// 	origin: OriginFor<T>,
+		// 	currency_id: CurrencyId,
+		// 	amount: BalanceOf<T>,
+		// 	target_chain: TargetChain<T::AccountId>,
+		// 	remark: BoundedVec<u8, ConstU32<32>>,
+		// 	channel_id: u32,
+		// ) -> DispatchResultWithPostInfo {
+		// 	// let who = ensure_signed(origin)?;
+		// 	let location = ensure_xcm(<T as Config>::RuntimeOrigin::from(origin))?;
+		//
+		// 	let account_id = match location.unpack() {
+		// 		(1, [Parachain(para_id), AccountId32 { network: _, id }]) => {
+		// 			let account_id = T::AccountId::decode(&mut &id[..]).map_err(|_|
+		// Error::<T>::Unsupported)?; 			Ok(account_id)
+		// 		},
+		// 		_ => {
+		// 			Err(Error::<T>::Unsupported)
+		// 		},
+		// 	};
+		// 	Ok(().into())
+		// }
 	}
 }
 
 impl<T: Config> Pallet<T> {
+	/// According to currency_id, return the order type
+	fn order_type(currency_id: CurrencyId) -> Result<OrderType, Error<T>> {
+		match currency_id {
+			CurrencyId::Native(_) | CurrencyId::Token(_) | CurrencyId::Token2(_) =>
+				Ok(OrderType::Mint),
+			CurrencyId::VToken(_) | CurrencyId::VToken2(_) => Ok(OrderType::Redeem),
+			_ => Err(Error::<T>::Unsupported),
+		}
+	}
+
+	/// According to frontier, return the derivative account
+	fn frontier_derivative_account(order_caller: &OrderCaller<T::AccountId>) -> T::AccountId {
+		match order_caller {
+			OrderCaller::Substrate(account_id) => account_id.clone(),
+			OrderCaller::Evm(h160) => Self::h160_to_account_id(h160),
+		}
+	}
+
+	/// According to Xcm, return the account id
+	fn xcm_derivative_account(
+		support_chain: SupportChain,
+		contract_address: H160,
+	) -> Result<T::AccountId, Error<T>> {
+		let location = match support_chain {
+			SupportChain::Astar => {
+				let account_id = Self::h160_to_account_id(&contract_address);
+				let id: [u8; 32] =
+					account_id.encode().try_into().map_err(|_| Error::<T>::ErrorEncode)?;
+				Location::new(
+					1,
+					[Parachain(AstarChainId::get()), AccountId32 { network: None, id }],
+				)
+			},
+			SupportChain::Moonbeam => Location::new(
+				1,
+				[
+					Parachain(T::VtokenMintingInterface::get_moonbeam_parachain_id()),
+					AccountKey20 { network: None, key: contract_address.to_fixed_bytes() },
+				],
+			),
+			_ => {
+				ensure!(false, Error::<T>::Unsupported);
+				Location::default()
+			},
+		};
+		let raw_account =
+			HashedDescription::<[u8; 32], DescribeFamily<DescribeAllTerminal>>::convert_location(
+				&location,
+			)
+			.ok_or(Error::<T>::Unsupported)?;
+		let account =
+			T::AccountId::decode(&mut &raw_account[..]).map_err(|_| Error::<T>::ErrorEncode)?;
+		Ok(account)
+	}
+
+	fn do_create_order(
+		source_chain_caller: OrderCaller<T::AccountId>,
+		bifrost_chain_caller: T::AccountId,
+		currency_id: CurrencyId,
+		currency_amount: BalanceOf<T>,
+		remark: BoundedVec<u8, ConstU32<32>>,
+		channel_id: u32,
+		target_chain: TargetChain<T::AccountId>,
+	) -> DispatchResultWithPostInfo {
+		let order_type = Self::order_type(currency_id)?;
+		let derivative_account = Self::frontier_derivative_account(&source_chain_caller);
+		let order = Order {
+			create_block_number: <frame_system::Pallet<T>>::block_number(),
+			order_type,
+			currency_id,
+			currency_amount,
+			remark,
+			source_chain_caller,
+			bifrost_chain_caller,
+			derivative_account,
+			target_chain,
+			channel_id,
+		};
+
+		OrderQueue::<T>::mutate(|order_queue| -> DispatchResultWithPostInfo {
+			order_queue
+				.try_push(order.clone())
+				.map_err(|_| Error::<T>::OrderQueueOverflow)?;
+			Self::deposit_event(Event::<T>::CreateOrder { order });
+			Ok(().into())
+		})
+	}
+
 	fn send_xcm_to_set_token_amount(
 		call: Vec<u8>,
 		xcm_weight: Weight,
@@ -853,16 +852,16 @@ impl<T: Config> Pallet<T> {
 		currency_id: CurrencyId,
 		token_amount: BalanceOf<T>,
 		vtoken_amount: BalanceOf<T>,
-	) -> Vec<u8> {
+	) -> Result<Vec<u8>, Error<T>> {
 		let ethereum_call = Self::encode_ethereum_call(currency_id, token_amount, vtoken_amount);
 		let transaction = EthereumXcmTransaction::V2(EthereumXcmTransactionV2 {
 			gas_limit: U256::from(MAX_GAS_LIMIT),
 			action: TransactionAction::Call(contract),
 			value: U256::zero(),
-			input: BoundedVec::try_from(ethereum_call).unwrap(),
+			input: BoundedVec::try_from(ethereum_call).map_err(|_| Error::<T>::ErrorEncode)?,
 			access_list: None,
 		});
-		return MoonbeamCall::EthereumXcm(EthereumXcmCall::Transact(transaction)).encode();
+		Ok(MoonbeamCall::EthereumXcm(EthereumXcmCall::Transact(transaction)).encode())
 	}
 
 	/// Check if the signer is in the whitelist
@@ -872,13 +871,6 @@ impl<T: Config> Pallet<T> {
 		target_chain: &TargetChain<AccountIdOf<T>>,
 	) -> Result<(OrderCaller<AccountIdOf<T>>, AccountIdOf<T>, AccountIdOf<T>), DispatchError> {
 		let bifrost_chain_caller = ensure_signed(origin)?;
-		let support_chain = match target_chain {
-			TargetChain::Astar(_) => SupportChain::Astar,
-			TargetChain::Moonbeam(_) => SupportChain::Moonbeam,
-			TargetChain::Hydradx(_) => SupportChain::Hydradx,
-			TargetChain::Interlay(_) => SupportChain::Interlay,
-			TargetChain::Manta(_) => SupportChain::Manta,
-		};
 
 		match target_chain {
 			TargetChain::Hydradx(_) | TargetChain::Manta(_) | TargetChain::Interlay(_) => Ok((
@@ -887,14 +879,15 @@ impl<T: Config> Pallet<T> {
 				bifrost_chain_caller,
 			)),
 			_ => {
-				let whitelist_account_ids = WhitelistAccountId::<T>::get(&support_chain);
+				let whitelist_account_ids =
+					WhitelistAccountId::<T>::get(target_chain.support_chain());
 				ensure!(
 					whitelist_account_ids.contains(&bifrost_chain_caller),
-					Error::<T>::AccountIdNotInWhitelist
+					Error::<T>::AccountNotFound
 				);
 				Ok((
 					OrderCaller::Evm(evm_caller),
-					Self::h160_to_account_id(evm_caller),
+					Self::h160_to_account_id(&evm_caller),
 					bifrost_chain_caller,
 				))
 			},
@@ -929,76 +922,75 @@ impl<T: Config> Pallet<T> {
 		amount: BalanceOf<T>,
 		target_chain: &TargetChain<AccountIdOf<T>>,
 	) -> DispatchResult {
-		match target_chain {
-			TargetChain::Astar(receiver) => {
-				let receiver = Self::h160_to_account_id(*receiver);
-				let dest = Location::new(
-					1,
-					[
-						Parachain(AstarChainId::get()),
-						AccountId32 { network: None, id: receiver.encode().try_into().unwrap() },
-					],
-				);
-
-				T::XcmTransfer::transfer(caller, currency_id, amount, dest, Unlimited)?;
-			},
-			TargetChain::Hydradx(receiver) => {
-				let dest = Location::new(
-					1,
-					[
-						Parachain(HydrationChainId::get()),
-						AccountId32 { network: None, id: receiver.encode().try_into().unwrap() },
-					],
-				);
-
-				T::XcmTransfer::transfer(caller, currency_id, amount, dest, Unlimited)?;
-			},
-			TargetChain::Interlay(receiver) => {
-				let dest = Location::new(
-					1,
-					[
-						Parachain(InterlayChainId::get()),
-						AccountId32 { network: None, id: receiver.encode().try_into().unwrap() },
-					],
-				);
-
-				T::XcmTransfer::transfer(caller, currency_id, amount, dest, Unlimited)?;
-			},
-			TargetChain::Manta(receiver) => {
-				let dest = Location::new(
-					1,
-					[
-						Parachain(MantaChainId::get()),
-						AccountId32 { network: None, id: receiver.encode().try_into().unwrap() },
-					],
-				);
+		let dest = match target_chain {
+			TargetChain::Astar(receiver) => Location::new(
+				1,
+				[
+					Parachain(AstarChainId::get()),
+					AccountId32 {
+						network: None,
+						id: Self::h160_to_account_id(receiver)
+							.encode()
+							.try_into()
+							.map_err(|_| Error::<T>::ErrorEncode)?,
+					},
+				],
+			),
+			TargetChain::Moonbeam(receiver) => Location::new(
+				1,
+				[
+					Parachain(T::VtokenMintingInterface::get_moonbeam_parachain_id()),
+					AccountKey20 { network: None, key: receiver.to_fixed_bytes() },
+				],
+			),
+			TargetChain::Hydradx(receiver) => Location::new(
+				1,
+				[
+					Parachain(HydrationChainId::get()),
+					AccountId32 {
+						network: None,
+						id: receiver.encode().try_into().map_err(|_| Error::<T>::ErrorEncode)?,
+					},
+				],
+			),
+			TargetChain::Interlay(receiver) => Location::new(
+				1,
+				[
+					Parachain(InterlayChainId::get()),
+					AccountId32 {
+						network: None,
+						id: receiver.encode().try_into().map_err(|_| Error::<T>::ErrorEncode)?,
+					},
+				],
+			),
+			TargetChain::Manta(receiver) => Location::new(
+				1,
+				[
+					Parachain(MantaChainId::get()),
+					AccountId32 {
+						network: None,
+						id: receiver.encode().try_into().map_err(|_| Error::<T>::ErrorEncode)?,
+					},
+				],
+			),
+		};
 
+		if let TargetChain::Moonbeam(_) = target_chain {
+			if SupportXcmFeeList::<T>::get().contains(&currency_id) {
 				T::XcmTransfer::transfer(caller, currency_id, amount, dest, Unlimited)?;
-			},
-			TargetChain::Moonbeam(receiver) => {
-				let dest = Location::new(
-					1,
-					[
-						Parachain(T::VtokenMintingInterface::get_moonbeam_parachain_id()),
-						AccountKey20 { network: None, key: receiver.to_fixed_bytes() },
-					],
-				);
-				if SupportXcmFeeList::<T>::get().contains(&currency_id) {
-					T::XcmTransfer::transfer(caller, currency_id, amount, dest, Unlimited)?;
-				} else {
-					let fee_amount = TransferToFee::<T>::get(SupportChain::Moonbeam)
-						.unwrap_or_else(|| Self::get_default_fee(BNC));
-					T::MultiCurrency::transfer(BNC, evm_contract_account_id, &caller, fee_amount)?;
-					let assets = vec![(currency_id, amount), (BNC, fee_amount)];
-
-					T::XcmTransfer::transfer_multicurrencies(caller, assets, 1, dest, Unlimited)?;
-				}
-			},
-		};
+			} else {
+				let fee_amount = Self::get_moonbeam_transfer_to_fee();
+				T::MultiCurrency::transfer(BNC, evm_contract_account_id, &caller, fee_amount)?;
+				let assets = vec![(currency_id, amount), (BNC, fee_amount)];
+				T::XcmTransfer::transfer_multicurrencies(caller, assets, 1, dest, Unlimited)?;
+			}
+		} else {
+			T::XcmTransfer::transfer(caller, currency_id, amount, dest, Unlimited)?;
+		}
 		Ok(())
 	}
 
-	fn h160_to_account_id(address: H160) -> AccountIdOf<T> {
+	fn h160_to_account_id(address: &H160) -> AccountIdOf<T> {
 		let mut data = [0u8; 24];
 		data[0..4].copy_from_slice(b"evm:");
 		data[4..24].copy_from_slice(&address[..]);
@@ -1025,7 +1017,8 @@ impl<T: Config> Pallet<T> {
 		order: &Order<AccountIdOf<T>, CurrencyIdOf<T>, BalanceOf<T>, BlockNumberFor<T>>,
 	) -> DispatchResult {
 		let currency_amount =
-			Self::charge_execution_fee(order.currency_id, &order.derivative_account).unwrap();
+			Self::charge_execution_fee(order.currency_id, &order.derivative_account)
+				.map_err(|_| Error::<T>::ErrorChargeFee)?;
 		match order.order_type {
 			OrderType::Mint => {
 				T::VtokenMintingInterface::mint(
@@ -1035,9 +1028,9 @@ impl<T: Config> Pallet<T> {
 					order.remark.clone(),
 					Some(order.channel_id),
 				)
-				.map_err(|_| Error::<T>::ArgumentsError)?;
-				let vtoken_id = T::VtokenMintingInterface::vtoken_id(order.currency_id)
-					.ok_or(Error::<T>::ArgumentsError)?;
+				.map_err(|_| Error::<T>::ErrorVtokenMiting)?;
+				let vtoken_id =
+					order.currency_id.to_vtoken().map_err(|_| Error::<T>::ErrorConvertVtoken)?;
 				let vtoken_amount =
 					T::MultiCurrency::free_balance(vtoken_id, &order.derivative_account);
 
@@ -1048,12 +1041,12 @@ impl<T: Config> Pallet<T> {
 					vtoken_amount,
 					&order.target_chain,
 				)
-				.map_err(|_| Error::<T>::ArgumentsError)?;
+				.map_err(|_| Error::<T>::ErrorTransferTo)?;
 			},
 			OrderType::Redeem => {
 				let redeem_type = match order.target_chain.clone() {
 					TargetChain::Astar(receiver) => {
-						let receiver = Self::h160_to_account_id(receiver);
+						let receiver = Self::h160_to_account_id(&receiver);
 						RedeemType::Astar(receiver)
 					},
 					TargetChain::Moonbeam(receiver) => RedeemType::Moonbeam(receiver),
@@ -1067,11 +1060,120 @@ impl<T: Config> Pallet<T> {
 					currency_amount,
 					redeem_type,
 				)
-				.map_err(|_| Error::<T>::ArgumentsError)?;
+				.map_err(|_| Error::<T>::ErrorVtokenMiting)?;
 			},
 		};
 		Ok(())
 	}
+
+	#[transactional]
+	pub fn handle_order_queue(
+		current_block_number: BlockNumberFor<T>,
+		weight: &mut Weight,
+	) -> DispatchResult {
+		OrderQueue::<T>::mutate(|order_queue| -> DispatchResult {
+			if order_queue.is_empty() {
+				*weight = weight.saturating_add(T::DbWeight::get().reads_writes(1, 0));
+				return Ok(());
+			};
+
+			if current_block_number - order_queue[0].create_block_number >= DelayBlock::<T>::get() {
+				let mut order = order_queue.remove(0);
+				if order.currency_amount == Default::default() {
+					order.currency_amount = T::MultiCurrency::free_balance(
+						order.currency_id,
+						&order.derivative_account,
+					);
+				}
+				match Self::handle_order(&order) {
+					Ok(_) => {
+						Self::deposit_event(Event::<T>::OrderHandled { order: order.clone() });
+					},
+					Err(_) => {
+						Self::deposit_event(Event::<T>::OrderFailed { order });
+					},
+				};
+				*weight = weight.saturating_add(T::DbWeight::get().reads_writes(12, 8));
+			};
+			*weight = weight.saturating_add(T::DbWeight::get().reads_writes(2, 0));
+			Ok(())
+		})
+	}
+
+	#[transactional]
+	pub fn handle_xcm_oracle(
+		current_block_number: BlockNumberFor<T>,
+		is_handle_xcm_oracle: &mut bool,
+		weight: &mut Weight,
+	) -> DispatchResult {
+		let mut currency_list = CurrencyIdList::<T>::get().to_vec();
+		if currency_list.is_empty() {
+			*weight = weight.saturating_add(T::DbWeight::get().reads_writes(1, 0));
+			return Ok(());
+		};
+
+		let configuration = XcmEthereumCallConfiguration::<T>::get();
+		if let Some(mut config) = configuration {
+			let currency_id = currency_list[0];
+			let staking_currency_amount = T::VtokenMintingInterface::get_token_pool(currency_id);
+			let v_currency_id =
+				currency_id.to_vtoken().map_err(|_| Error::<T>::ErrorConvertVtoken)?;
+			let v_currency_total_supply = T::MultiCurrency::total_issuance(v_currency_id);
+
+			if config.last_block + config.period < current_block_number {
+				let encoded_call = Self::encode_transact_call(
+					config.contract,
+					currency_id,
+					staking_currency_amount,
+					v_currency_total_supply,
+				)
+				.map_err(|_| Error::<T>::ErrorEncode)?;
+
+				Self::send_xcm_to_set_token_amount(encoded_call, config.xcm_weight, config.xcm_fee)
+					.map_err(|_| Error::<T>::ErrorDelivering)?;
+
+				Self::deposit_event(Event::XcmOracle {
+					currency_id,
+					staking_currency_amount,
+					v_currency_id,
+					v_currency_total_supply,
+				});
+
+				let mut target_fee_currency_id = GLMR;
+				if T::ParachainId::get() == Id::from(BifrostKusamaChainId::get()) {
+					target_fee_currency_id = MOVR;
+				}
+
+				// Will not check results and will be sent regardless of the success of
+				// the burning
+				if T::MultiCurrency::withdraw(
+					target_fee_currency_id,
+					&T::TreasuryAccount::get(),
+					BalanceOf::<T>::unique_saturated_from(config.xcm_fee),
+				)
+				.is_err()
+				{
+					Self::deposit_event(Event::InsufficientAssets);
+				}
+
+				config.last_block = current_block_number;
+				XcmEthereumCallConfiguration::<T>::put(config);
+				currency_list.rotate_left(1);
+				CurrencyIdList::<T>::put(
+					BoundedVec::try_from(currency_list).map_err(|_| Error::<T>::ErrorEncode)?,
+				);
+
+				*weight = weight.saturating_add(T::DbWeight::get().reads_writes(4, 2));
+
+				*is_handle_xcm_oracle = true;
+			}
+
+			return Ok(());
+		} else {
+			*weight = weight.saturating_add(T::DbWeight::get().reads_writes(2, 0));
+			return Ok(());
+		}
+	}
 }
 
 // Functions to be called by other pallets.
diff --git a/pallets/slpx/src/migration.rs b/pallets/slpx/src/migration.rs
index a0c5945b2..3fabbbf81 100644
--- a/pallets/slpx/src/migration.rs
+++ b/pallets/slpx/src/migration.rs
@@ -162,7 +162,7 @@ pub fn migrate_to_v1<T: Config>() -> Weight {
 		};
 
 		OrderQueue::<T>::mutate(|order_queue| -> DispatchResultWithPostInfo {
-			order_queue.try_push(order.clone()).map_err(|_| Error::<T>::ArgumentsError)?;
+			order_queue.try_push(order.clone()).map_err(|_| Error::<T>::ErrorArguments)?;
 			Ok(().into())
 		})
 		.expect("BoundedVec should not overflow");
diff --git a/pallets/slpx/src/mock.rs b/pallets/slpx/src/mock.rs
index 13e32baf7..0abbbe43d 100644
--- a/pallets/slpx/src/mock.rs
+++ b/pallets/slpx/src/mock.rs
@@ -19,42 +19,30 @@
 
 use crate as slpx;
 use bifrost_asset_registry::AssetIdMaps;
-use bifrost_primitives::{
-	BifrostEntranceAccount, BifrostExitAccount, BifrostFeeAccount, IncentivePoolAccount,
-	MoonbeamChainId, StableAssetPalletId, ZenlinkPalletId,
-};
 pub use bifrost_primitives::{
-	CurrencyId, CurrencyIdMapping, MockXcmExecutor, SlpxOperator, BNC, KSM,
+	CurrencyId, CurrencyIdMapping, MockXcmExecutor, SlpxOperator, TokenSymbol, BNC, KSM,
 };
-use bifrost_slp::{QueryId, QueryResponseManager};
+use bifrost_primitives::{MockXcmTransfer, MoonbeamChainId, SlpOperator};
 use cumulus_primitives_core::ParaId;
 use frame_support::{
 	construct_runtime, derive_impl, ord_parameter_types,
 	pallet_prelude::*,
 	parameter_types,
 	traits::{Everything, Nothing},
+	PalletId,
 };
 use frame_system::{EnsureRoot, EnsureSignedBy};
-use orml_traits::{
-	location::RelativeReserveProvider, parameter_type_with_key, xcm_transfer::Transferred,
-	MultiCurrency, XcmTransfer,
-};
-use sp_core::ConstU128;
+use hex_literal::hex;
+use orml_traits::parameter_type_with_key;
 use sp_runtime::{
-	traits::{Convert, IdentityLookup, UniqueSaturatedInto},
-	AccountId32, SaturatedConversion,
+	traits::{Convert, IdentityLookup},
+	AccountId32, BuildStorage,
 };
 use sp_std::vec;
 pub use xcm::latest::prelude::*;
-use xcm::{
-	latest::{Junction, Location},
-	opaque::latest::Junction::Parachain,
-};
+use xcm::{latest::Location, opaque::latest::Junction::Parachain};
 use xcm_builder::FrameTransactionalProcessor;
 pub use xcm_builder::{EnsureXcmOrigin, FixedWeightBounds};
-use zenlink_protocol::{
-	AssetBalance, AssetId as ZenlinkAssetId, LocalAssetHandler, PairLpGenerate, ZenlinkMultiAssets,
-};
 
 pub type Balance = u128;
 pub type Amount = i128;
@@ -73,15 +61,10 @@ construct_runtime!(
 	Tokens: orml_tokens,
 	Currencies: bifrost_currencies,
 	AssetRegistry: bifrost_asset_registry,
-	Slp: bifrost_slp,
 	VtokenMinting: bifrost_vtoken_minting,
-	ZenlinkProtocol: zenlink_protocol,
-	XTokens: orml_xtokens,
 	Slpx: slpx,
-	  PolkadotXcm: pallet_xcm,
-	  ParachainInfo: parachain_info,
-	  StableAsset: bifrost_stable_asset,
-	  StablePool: bifrost_stable_pool
+	PolkadotXcm: pallet_xcm,
+	ParachainInfo: parachain_info,
   }
 );
 
@@ -120,7 +103,7 @@ impl pallet_balances::Config for Test {
 }
 
 parameter_types! {
-	pub const GetNativeCurrencyId: CurrencyId = BNC;
+	pub const GetNativeCurrencyId: CurrencyId = CurrencyId::Native(TokenSymbol::BNC);
 }
 
 pub type AdaptedBasicCurrency =
@@ -162,7 +145,11 @@ impl orml_tokens::Config for Test {
 parameter_types! {
 	pub const MaximumUnlockIdOfUser: u32 = 10;
 	pub const MaximumUnlockIdOfTimeUnit: u32 = 50;
+	pub BifrostEntranceAccount: PalletId = PalletId(*b"bf/vtkin");
+	pub BifrostExitAccount: PalletId = PalletId(*b"bf/vtout");
+	pub BifrostFeeAccount: AccountId = hex!["e4da05f08e89bf6c43260d96f26fffcfc7deae5b465da08669a9d008e64c2c63"].into();
 	pub const RelayCurrencyId: CurrencyId = KSM;
+	pub IncentivePoolAccount: PalletId = PalletId(*b"bf/inpoo");
 }
 
 ord_parameter_types! {
@@ -176,6 +163,14 @@ impl SlpxOperator<Balance> for SlpxInterface {
 	}
 }
 
+pub struct MockSlp;
+
+impl<CurrencyId> SlpOperator<CurrencyId> for MockSlp {
+	fn all_delegation_requests_occupied(_: CurrencyId) -> bool {
+		false
+	}
+}
+
 impl bifrost_vtoken_minting::Config for Test {
 	type RuntimeEvent = RuntimeEvent;
 	type MultiCurrency = Currencies;
@@ -189,11 +184,11 @@ impl bifrost_vtoken_minting::Config for Test {
 	type RelayChainToken = RelayCurrencyId;
 	type CurrencyIdConversion = AssetIdMaps<Test>;
 	type CurrencyIdRegister = AssetIdMaps<Test>;
-	type BifrostSlp = Slp;
+	type BifrostSlp = MockSlp;
 	type BifrostSlpx = SlpxInterface;
 	type WeightInfo = ();
 	type OnRedeemSuccess = ();
-	type XcmTransfer = XTokens;
+	type XcmTransfer = MockXcmTransfer;
 	type MoonbeamChainId = MoonbeamChainId;
 	type ChannelCommission = ();
 	type MaxLockRecords = ConstU32<100>;
@@ -201,90 +196,6 @@ impl bifrost_vtoken_minting::Config for Test {
 	type BbBNC = ();
 	type AssetIdMaps = AssetIdMaps<Test>;
 }
-// Below is the implementation of tokens manipulation functions other than native token.
-pub struct LocalAssetAdaptor<Local>(PhantomData<Local>);
-
-impl<Local, AccountId> LocalAssetHandler<AccountId> for LocalAssetAdaptor<Local>
-where
-	Local: MultiCurrency<AccountId, CurrencyId = CurrencyId>,
-{
-	fn local_balance_of(asset_id: ZenlinkAssetId, who: &AccountId) -> AssetBalance {
-		let currency_id: CurrencyId = asset_id.try_into().unwrap();
-		Local::free_balance(currency_id, &who).saturated_into()
-	}
-
-	fn local_total_supply(asset_id: ZenlinkAssetId) -> AssetBalance {
-		let currency_id: CurrencyId = asset_id.try_into().unwrap();
-		Local::total_issuance(currency_id).saturated_into()
-	}
-
-	fn local_is_exists(asset_id: ZenlinkAssetId) -> bool {
-		let rs: Result<CurrencyId, _> = asset_id.try_into();
-		match rs {
-			Ok(_) => true,
-			Err(_) => false,
-		}
-	}
-
-	fn local_transfer(
-		asset_id: ZenlinkAssetId,
-		origin: &AccountId,
-		target: &AccountId,
-		amount: AssetBalance,
-	) -> DispatchResult {
-		let currency_id: CurrencyId = asset_id.try_into().unwrap();
-		Local::transfer(currency_id, &origin, &target, amount.unique_saturated_into())?;
-
-		Ok(())
-	}
-
-	fn local_deposit(
-		asset_id: ZenlinkAssetId,
-		origin: &AccountId,
-		amount: AssetBalance,
-	) -> Result<AssetBalance, DispatchError> {
-		let currency_id: CurrencyId = asset_id.try_into().unwrap();
-		Local::deposit(currency_id, &origin, amount.unique_saturated_into())?;
-		return Ok(amount);
-	}
-
-	fn local_withdraw(
-		asset_id: ZenlinkAssetId,
-		origin: &AccountId,
-		amount: AssetBalance,
-	) -> Result<AssetBalance, DispatchError> {
-		let currency_id: CurrencyId = asset_id.try_into().unwrap();
-		Local::withdraw(currency_id, &origin, amount.unique_saturated_into())?;
-
-		Ok(amount)
-	}
-}
-
-type MultiAssets = ZenlinkMultiAssets<ZenlinkProtocol, Balances, LocalAssetAdaptor<Currencies>>;
-
-parameter_types! {
-	pub const GetExchangeFee: (u32, u32) = (3, 1000);   // 0.3%
-	pub const SelfParaId: u32 = 2001;
-}
-
-impl zenlink_protocol::Config for Test {
-	type RuntimeEvent = RuntimeEvent;
-	type MultiAssetsHandler = MultiAssets;
-	type PalletId = ZenlinkPalletId;
-	type SelfParaId = SelfParaId;
-
-	type TargetChains = ();
-	type WeightInfo = ();
-	type AssetId = ZenlinkAssetId;
-	type LpGenerate = PairLpGenerate<Self>;
-}
-
-pub struct AccountIdToLocation;
-impl Convert<AccountId, Location> for AccountIdToLocation {
-	fn convert(account_id: AccountId) -> Location {
-		Location::from(Junction::AccountId32 { network: None, id: account_id.into() })
-	}
-}
 
 parameter_types! {
 	// One XCM operation is 200_000_000 XcmWeight, cross-chain transfer ~= 2x of transfer = 3_000_000_000
@@ -353,32 +264,10 @@ impl<T: Get<ParaId>> Convert<Location, Option<CurrencyId>> for CurrencyIdConvert
 
 impl parachain_info::Config for Test {}
 
-impl orml_xtokens::Config for Test {
-	type RuntimeEvent = RuntimeEvent;
-	type Balance = Balance;
-	type CurrencyId = CurrencyId;
-	type CurrencyIdConvert = CurrencyIdConvert<ParachainInfo>;
-	type AccountIdToLocation = ();
-	type UniversalLocation = UniversalLocation;
-	type SelfLocation = SelfRelativeLocation;
-	type XcmExecutor = MockXcmExecutor;
-	type Weigher = FixedWeightBounds<UnitWeightCost, RuntimeCall, MaxInstructions>;
-	type BaseXcmWeight = BaseXcmWeight;
-	type MaxAssetsForTransfer = MaxAssetsForTransfer;
-	type MinXcmFee = ParachainMinFee;
-	type LocationsFilter = Everything;
-	type ReserveProvider = RelativeReserveProvider;
-	type RateLimiter = ();
-	type RateLimiterId = ();
-}
-
-ord_parameter_types! {
-	pub const CouncilAccount: AccountId = AccountId::from([1u8; 32]);
-}
 impl bifrost_asset_registry::Config for Test {
 	type RuntimeEvent = RuntimeEvent;
 	type Currency = Balances;
-	type RegisterOrigin = EnsureSignedBy<CouncilAccount, AccountId>;
+	type RegisterOrigin = EnsureRoot<AccountId>;
 	type WeightInfo = ();
 }
 
@@ -389,52 +278,6 @@ impl Get<ParaId> for ParachainId {
 	}
 }
 
-parameter_types! {
-	pub const MaxTypeEntryPerBlock: u32 = 10;
-	pub const MaxRefundPerBlock: u32 = 10;
-	pub const MaxLengthLimit: u32 = 100;
-}
-
-pub struct SubstrateResponseManager;
-impl QueryResponseManager<QueryId, Location, u64, RuntimeCall> for SubstrateResponseManager {
-	fn get_query_response_record(_query_id: QueryId) -> bool {
-		Default::default()
-	}
-	fn create_query_record(
-		_responder: Location,
-		_call_back: Option<RuntimeCall>,
-		_timeout: u64,
-	) -> u64 {
-		Default::default()
-	}
-	fn remove_query_record(_query_id: QueryId) -> bool {
-		Default::default()
-	}
-}
-
-impl bifrost_slp::Config for Test {
-	type RuntimeEvent = RuntimeEvent;
-	type RuntimeOrigin = RuntimeOrigin;
-	type RuntimeCall = RuntimeCall;
-	type MultiCurrency = Currencies;
-	type ControlOrigin = EnsureSignedBy<One, AccountId>;
-	type WeightInfo = ();
-	type VtokenMinting = VtokenMinting;
-	type AccountConverter = ();
-	type ParachainId = ParachainId;
-	type SubstrateResponseManager = SubstrateResponseManager;
-	type MaxTypeEntryPerBlock = MaxTypeEntryPerBlock;
-	type MaxRefundPerBlock = MaxRefundPerBlock;
-	type ParachainStaking = ();
-	type XcmTransfer = XTokens;
-	type MaxLengthLimit = MaxLengthLimit;
-	type XcmWeightAndFeeHandler = ();
-	type ChannelCommission = ();
-	type StablePoolHandler = ();
-	type AssetIdMaps = AssetIdMaps<Test>;
-	type TreasuryAccount = BifrostFeeAccount;
-}
-
 #[cfg(feature = "runtime-benchmarks")]
 parameter_types! {
 	pub ReachableDest: Option<Location> = Some(Parent.into());
@@ -466,133 +309,25 @@ impl pallet_xcm::Config for Test {
 	type RemoteLockConsumerIdentifier = ();
 }
 
-pub struct EnsurePoolAssetId;
-impl bifrost_stable_asset::traits::ValidateAssetId<CurrencyId> for EnsurePoolAssetId {
-	fn validate(_: CurrencyId) -> bool {
-		true
-	}
-}
-
-impl bifrost_stable_asset::Config for Test {
-	type RuntimeEvent = RuntimeEvent;
-	type AssetId = CurrencyId;
-	type Balance = Balance;
-	type Assets = Tokens;
-	type PalletId = StableAssetPalletId;
-	type AtLeast64BitUnsigned = u128;
-	type FeePrecision = ConstU128<10_000_000_000>;
-	type APrecision = ConstU128<100>;
-	type PoolAssetLimit = ConstU32<5>;
-	type SwapExactOverAmount = ConstU128<100>;
-	type WeightInfo = ();
-	type ListingOrigin = EnsureSignedBy<CouncilAccount, AccountId>;
-	type EnsurePoolAssetId = EnsurePoolAssetId;
-}
-
-impl bifrost_stable_pool::Config for Test {
-	type WeightInfo = ();
-	type ControlOrigin = EnsureRoot<AccountId>;
-	type CurrencyId = CurrencyId;
-	type MultiCurrency = Tokens;
-	type StableAsset = StableAsset;
-	type VtokenMinting = VtokenMinting;
-	type CurrencyIdConversion = AssetIdMaps<Test>;
-	type CurrencyIdRegister = AssetIdMaps<Test>;
-}
-
-// Pallet slpx configuration
-parameter_types! {
-	pub const NativeCurrencyId: CurrencyId = BNC;
-}
-
-pub struct XTokensMock;
-
-impl XcmTransfer<AccountId, Balance, CurrencyId> for XTokensMock {
-	fn transfer(
-		who: AccountId,
-		currency_id: CurrencyId,
-		amount: Balance,
-		dest: Location,
-		_dest_weight_limit: WeightLimit,
-	) -> Result<Transferred<AccountId>, DispatchError> {
-		Currencies::withdraw(currency_id, &who, amount).ok();
-		Currencies::deposit(currency_id, &BOB, amount).ok();
-		Ok(Transferred {
-			sender: who,
-			assets: Default::default(),
-			fee: Asset { id: AssetId(Location::new(1, Here)), fun: Fungible(0u128) },
-			dest,
-		})
-	}
-
-	fn transfer_multiasset(
-		_who: AccountId,
-		_asset: Asset,
-		_dest: Location,
-		_dest_weight_limit: WeightLimit,
-	) -> Result<Transferred<AccountId>, DispatchError> {
-		todo!()
-	}
-
-	fn transfer_with_fee(
-		_who: AccountId,
-		_currency_id: CurrencyId,
-		_amount: Balance,
-		_fee: Balance,
-		_dest: Location,
-		_dest_weight_limit: WeightLimit,
-	) -> Result<Transferred<AccountId>, DispatchError> {
-		todo!()
-	}
-
-	fn transfer_multiasset_with_fee(
-		_who: AccountId,
-		_asset: Asset,
-		_fee: Asset,
-		_dest: Location,
-		_dest_weight_limit: WeightLimit,
-	) -> Result<Transferred<AccountId>, DispatchError> {
-		todo!()
-	}
-
-	fn transfer_multicurrencies(
-		_who: AccountId,
-		_currencies: Vec<(CurrencyId, Balance)>,
-		_fee_item: u32,
-		_dest: Location,
-		_dest_weight_limit: WeightLimit,
-	) -> Result<Transferred<AccountId>, DispatchError> {
-		todo!()
-	}
-
-	fn transfer_multiassets(
-		_who: AccountId,
-		_assets: Assets,
-		_fee: Asset,
-		_dest: Location,
-		_dest_weight_limit: WeightLimit,
-	) -> Result<Transferred<AccountId>, DispatchError> {
-		todo!()
-	}
-}
-
 impl slpx::Config for Test {
 	type RuntimeEvent = RuntimeEvent;
+	type RuntimeOrigin = RuntimeOrigin;
 	type ControlOrigin = EnsureRoot<AccountId>;
 	type MultiCurrency = Currencies;
-	type DexOperator = ZenlinkProtocol;
 	type VtokenMintingInterface = VtokenMinting;
-	type StablePoolHandler = StablePool;
-	type XcmTransfer = XTokensMock;
+	type XcmTransfer = MockXcmTransfer;
 	type XcmSender = ();
 	type CurrencyIdConvert = AssetIdMaps<Test>;
 	type TreasuryAccount = BifrostFeeAccount;
 	type ParachainId = ParachainId;
 	type WeightInfo = ();
+	type MaxOrderSize = ConstU32<500>;
 }
 
-#[cfg(feature = "runtime-benchmarks")]
+// Build genesis storage according to the mock runtime.
 pub fn new_test_ext() -> sp_io::TestExternalities {
-	use sp_runtime::BuildStorage;
-	frame_system::GenesisConfig::<Test>::default().build_storage().unwrap().into()
+	let t = frame_system::GenesisConfig::<Test>::default().build_storage().unwrap();
+	let mut ext = sp_io::TestExternalities::new(t);
+	ext.execute_with(|| System::set_block_number(0));
+	ext
 }
diff --git a/pallets/slpx/src/tests.rs b/pallets/slpx/src/tests.rs
index aa58302dc..0f4e8c824 100644
--- a/pallets/slpx/src/tests.rs
+++ b/pallets/slpx/src/tests.rs
@@ -22,22 +22,22 @@ use crate::{
 	types::{EthereumXcmCall, EthereumXcmTransaction, EthereumXcmTransactionV2, MoonbeamCall},
 	*,
 };
-use bifrost_primitives::{TokenSymbol, TryConvertFrom, DOT, VDOT};
+use bifrost_primitives::{TokenSymbol, DOT, VDOT};
 use ethereum::TransactionAction;
-use frame_support::{assert_noop, assert_ok, dispatch::RawOrigin, traits::Hooks};
+use frame_support::{assert_noop, assert_ok, dispatch::RawOrigin, traits::OnIdle};
 use hex_literal::hex;
-use sp_core::{bounded::BoundedVec, ConstU32, U256};
-use sp_io;
+use sp_core::{bounded::BoundedVec, crypto::Ss58Codec, U256};
 use tiny_keccak::Hasher;
-use zenlink_protocol::AssetId;
 
 const EVM_ADDR: [u8; 20] = hex!["573394b77fC17F91E9E67F147A9ECe24d67C5073"];
+const ASTAR_SLPX_ADDR: [u8; 20] = hex!["c6bf0C5C78686f1D0E2E54b97D6de6e2cEFAe9fD"];
+const MOONBEAM_SLPX_ADDR: [u8; 20] = hex!["F1d4797E51a4640a76769A50b57abE7479ADd3d8"];
 
 #[test]
 fn test_account_convert_work() {
-	sp_io::TestExternalities::default().execute_with(|| {
+	new_test_ext().execute_with(|| {
 		let address = H160::from_slice(&EVM_ADDR);
-		let account_id: AccountId = Slpx::h160_to_account_id(address);
+		let account_id: AccountId = Slpx::h160_to_account_id(&address);
 		assert_eq!(
 			account_id,
 			sp_runtime::AccountId32::new(hex!(
@@ -53,57 +53,133 @@ fn test_account_convert_work() {
 }
 
 #[test]
-fn test_whitelist_work() {
-	sp_io::TestExternalities::default().execute_with(|| {
-		assert_ok!(Slpx::add_whitelist(RuntimeOrigin::root(), SupportChain::Astar, ALICE));
-		assert_ok!(Slpx::add_whitelist(RuntimeOrigin::root(), SupportChain::Astar, BOB));
+fn xcm_derivative_account() {
+	new_test_ext().execute_with(|| {
+		let address = H160::from_slice(&ASTAR_SLPX_ADDR);
+		let derivative_account =
+			Slpx::xcm_derivative_account(SupportChain::Astar, address).unwrap();
 		assert_eq!(
-			WhitelistAccountId::<Test>::get(SupportChain::Astar),
-			BoundedVec::<AccountId, ConstU32<10>>::try_from(vec![ALICE, BOB]).unwrap()
+			derivative_account,
+			sp_runtime::AccountId32::from_ss58check(
+				"g96o4GVpsAop1MJiArnmUYtXUjEisfkbfcpsuqmXrS28MEr"
+			)
+			.unwrap()
 		);
-		assert_noop!(
-			Slpx::add_whitelist(RuntimeOrigin::root(), SupportChain::Astar, ALICE),
-			Error::<Test>::AccountIdAlreadyInWhitelist
+
+		let address = H160::from_slice(&MOONBEAM_SLPX_ADDR);
+		let derivative_account =
+			Slpx::xcm_derivative_account(SupportChain::Moonbeam, address).unwrap();
+		assert_eq!(
+			derivative_account,
+			sp_runtime::AccountId32::from_ss58check(
+				"gWEvf2EDMzxR7JHyrEHXf3nqxKLGvHaFbk7HUkJnNPUxDts"
+			)
+			.unwrap()
 		);
-		assert_ok!(Slpx::remove_whitelist(RuntimeOrigin::root(), SupportChain::Astar, ALICE));
+	});
+}
+
+#[test]
+fn add_whitelist() {
+	new_test_ext().execute_with(|| {
+		let astar_slpx_addr = H160::from_slice(&ASTAR_SLPX_ADDR);
+		let moonbeam_slpx_addr = H160::from_slice(&MOONBEAM_SLPX_ADDR);
+		let astar_slpx_account_id = sp_runtime::AccountId32::from_ss58check(
+			"g96o4GVpsAop1MJiArnmUYtXUjEisfkbfcpsuqmXrS28MEr",
+		)
+		.unwrap();
+		let moonbeam_slpx_account_id = sp_runtime::AccountId32::from_ss58check(
+			"gWEvf2EDMzxR7JHyrEHXf3nqxKLGvHaFbk7HUkJnNPUxDts",
+		)
+		.unwrap();
+		assert_ok!(Slpx::add_whitelist(
+			RuntimeOrigin::root(),
+			SupportChain::Astar,
+			astar_slpx_addr
+		));
+		assert_eq!(
+			WhitelistAccountId::<Test>::get(SupportChain::Astar).to_vec(),
+			vec![astar_slpx_account_id]
+		);
+
+		assert_ok!(Slpx::add_whitelist(
+			RuntimeOrigin::root(),
+			SupportChain::Moonbeam,
+			moonbeam_slpx_addr
+		));
 		assert_eq!(
-			WhitelistAccountId::<Test>::get(SupportChain::Astar),
-			BoundedVec::<AccountId, ConstU32<10>>::try_from(vec![BOB]).unwrap()
+			WhitelistAccountId::<Test>::get(SupportChain::Moonbeam).to_vec(),
+			vec![moonbeam_slpx_account_id]
+		);
+	});
+}
+
+#[test]
+fn add_whitelist_account_id_already_in_whitelist() {
+	new_test_ext().execute_with(|| {
+		let astar_slpx_addr = H160::from_slice(&ASTAR_SLPX_ADDR);
+		let astar_slpx_account_id = sp_runtime::AccountId32::from_ss58check(
+			"g96o4GVpsAop1MJiArnmUYtXUjEisfkbfcpsuqmXrS28MEr",
+		)
+		.unwrap();
+		assert_ok!(Slpx::add_whitelist(
+			RuntimeOrigin::root(),
+			SupportChain::Astar,
+			astar_slpx_addr
+		));
+		assert_eq!(
+			WhitelistAccountId::<Test>::get(SupportChain::Astar).to_vec(),
+			vec![astar_slpx_account_id]
 		);
 
-		// Astar && Moonbeam
-		let evm_caller = H160::from_slice(&EVM_ADDR);
-		let target_chain = TargetChain::Astar(evm_caller);
-		let (order_caller, derivative_account, _) =
-			Slpx::ensure_singer_on_whitelist(RuntimeOrigin::signed(BOB), evm_caller, &target_chain)
-				.unwrap();
 		assert_noop!(
-			Slpx::ensure_singer_on_whitelist(
-				RuntimeOrigin::signed(ALICE),
-				evm_caller,
-				&target_chain
-			),
-			Error::<Test>::AccountIdNotInWhitelist
+			Slpx::add_whitelist(RuntimeOrigin::root(), SupportChain::Astar, astar_slpx_addr),
+			Error::<Test>::AccountAlreadyExists
 		);
-		assert_eq!(order_caller, OrderCaller::Evm(evm_caller));
-		assert_eq!(derivative_account, Slpx::h160_to_account_id(evm_caller));
+	});
+}
 
-		// Hydradx No whitelist checking
-		let target_chain = TargetChain::Hydradx(ALICE);
-		let (order_caller, derivative_account, _) = Slpx::ensure_singer_on_whitelist(
-			RuntimeOrigin::signed(ALICE),
-			evm_caller,
-			&target_chain,
+#[test]
+fn remove_whitelist() {
+	new_test_ext().execute_with(|| {
+		let astar_slpx_addr = H160::from_slice(&ASTAR_SLPX_ADDR);
+		let astar_slpx_account_id = sp_runtime::AccountId32::from_ss58check(
+			"g96o4GVpsAop1MJiArnmUYtXUjEisfkbfcpsuqmXrS28MEr",
 		)
 		.unwrap();
-		assert_eq!(order_caller, OrderCaller::Substrate(ALICE));
-		assert_eq!(derivative_account, ALICE);
+		assert_ok!(Slpx::add_whitelist(
+			RuntimeOrigin::root(),
+			SupportChain::Astar,
+			astar_slpx_addr
+		));
+		assert_eq!(
+			WhitelistAccountId::<Test>::get(SupportChain::Astar).to_vec(),
+			vec![astar_slpx_account_id]
+		);
+
+		assert_ok!(Slpx::remove_whitelist(
+			RuntimeOrigin::root(),
+			SupportChain::Astar,
+			astar_slpx_addr
+		));
+		assert_eq!(WhitelistAccountId::<Test>::get(SupportChain::Astar).to_vec(), vec![]);
+	});
+}
+
+#[test]
+fn remove_whitelist_account_id_not_in_whitelist() {
+	new_test_ext().execute_with(|| {
+		let astar_slpx_addr = H160::from_slice(&ASTAR_SLPX_ADDR);
+		assert_noop!(
+			Slpx::remove_whitelist(RuntimeOrigin::root(), SupportChain::Astar, astar_slpx_addr),
+			Error::<Test>::AccountNotFound
+		);
 	});
 }
 
 #[test]
 fn test_execution_fee_work() {
-	sp_io::TestExternalities::default().execute_with(|| {
+	new_test_ext().execute_with(|| {
 		assert_ok!(Currencies::deposit(CurrencyId::Token2(0), &ALICE, 50 * 1_000_000_000));
 
 		assert_ok!(Slpx::set_execution_fee(
@@ -126,67 +202,9 @@ fn test_execution_fee_work() {
 	});
 }
 
-#[test]
-fn test_zenlink() {
-	sp_io::TestExternalities::default().execute_with(|| {
-		assert_ok!(Currencies::deposit(
-			CurrencyId::Native(TokenSymbol::BNC),
-			&ALICE,
-			50 * 1_000_000_000
-		));
-		assert_ok!(Currencies::deposit(
-			CurrencyId::Token(TokenSymbol::KSM),
-			&ALICE,
-			50 * 1_000_000_000
-		));
-
-		let bnc_token: AssetId =
-			AssetId::try_convert_from(CurrencyId::Native(TokenSymbol::BNC), 2001).unwrap();
-		let ksm_token: AssetId =
-			AssetId::try_convert_from(CurrencyId::Token(TokenSymbol::KSM), 2001).unwrap();
-
-		assert_ok!(ZenlinkProtocol::create_pair(
-			RawOrigin::Root.into(),
-			bnc_token,
-			ksm_token,
-			ALICE
-		));
-		assert_ok!(ZenlinkProtocol::add_liquidity(
-			RawOrigin::Signed(ALICE).into(),
-			bnc_token,
-			ksm_token,
-			20u128 * 1_000_000_000,
-			20u128 * 1_000_000_000,
-			0,
-			0,
-			100
-		));
-		assert_eq!(
-			Currencies::free_balance(CurrencyId::Native(TokenSymbol::BNC), &ALICE),
-			30u128 * 1_000_000_000
-		);
-		assert_eq!(
-			Currencies::free_balance(CurrencyId::Token(TokenSymbol::KSM), &ALICE),
-			30u128 * 1_000_000_000
-		);
-
-		let path = vec![bnc_token, ksm_token];
-		let balance = Currencies::free_balance(CurrencyId::Native(TokenSymbol::BNC), &ALICE);
-		let minimum_balance = Currencies::minimum_balance(CurrencyId::Native(TokenSymbol::BNC));
-		assert_ok!(ZenlinkProtocol::swap_exact_assets_for_assets(
-			RawOrigin::Signed(ALICE).into(),
-			balance - minimum_balance,
-			0,
-			path,
-			ALICE,
-			100
-		));
-	});
-}
-
 #[test]
 fn test_get_default_fee() {
-	sp_io::TestExternalities::default().execute_with(|| {
+	new_test_ext().execute_with(|| {
 		assert_eq!(Slpx::get_default_fee(BNC), 10_000_000_000u128);
 		assert_eq!(Slpx::get_default_fee(CurrencyId::Token(TokenSymbol::KSM)), 10_000_000_000u128);
 		assert_eq!(
@@ -203,7 +221,7 @@ fn test_get_default_fee() {
 
 #[test]
 fn test_ed() {
-	sp_io::TestExternalities::default().execute_with(|| {
+	new_test_ext().execute_with(|| {
 		assert_ok!(Currencies::deposit(
 			CurrencyId::Native(TokenSymbol::BNC),
 			&ALICE,
@@ -254,7 +272,7 @@ fn test_selector() {
 
 #[test]
 fn test_ethereum_call() {
-	sp_io::TestExternalities::default().execute_with(|| {
+	new_test_ext().execute_with(|| {
 		// b"setTokenAmount(bytes2,uint256,bytes2,uint256)"
 		assert_eq!("9a41b9240001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007b00000000000000000000000000000000000000000000000000000000000001c8", hex::encode(Slpx::encode_ethereum_call(BNC, 123u128, 456u128)));
 
@@ -269,28 +287,28 @@ fn test_ethereum_call() {
 		});
 		let call = MoonbeamCall::EthereumXcm(EthereumXcmCall::Transact(r));
 		println!("{}", hex::encode(call.encode()));
-		assert_eq!("6d000180fc0a000000000000000000000000000000000000000000000000000000000000ae0daa9bfc50f03ce23d30c796709a58470b5f42000000000000000000000000000000000000000000000000000000000000000091019a41b9240001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007b00000000000000000000000000000000000000000000000000000000000001c800", hex::encode(Slpx::encode_transact_call(H160::from(addr), BNC, 123u128, 456u128)));
+		assert_eq!("6d000180fc0a000000000000000000000000000000000000000000000000000000000000ae0daa9bfc50f03ce23d30c796709a58470b5f42000000000000000000000000000000000000000000000000000000000000000091019a41b9240001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007b00000000000000000000000000000000000000000000000000000000000001c800", hex::encode(Slpx::encode_transact_call(H160::from(addr), BNC, 123u128, 456u128).unwrap()));
 	})
 }
 
 #[test]
 fn test_set_currency_ethereum_call_switch() {
-	sp_io::TestExternalities::default().execute_with(|| {
-		assert_ok!(Slpx::set_currency_ethereum_call_switch(RuntimeOrigin::root(), BNC, true));
+	new_test_ext().execute_with(|| {
+		assert_ok!(Slpx::support_xcm_oracle(RuntimeOrigin::root(), BNC, true));
 		assert_eq!(CurrencyIdList::<Test>::get().to_vec(), vec![BNC]);
 
-		assert_ok!(Slpx::set_currency_ethereum_call_switch(RuntimeOrigin::root(), KSM, true));
+		assert_ok!(Slpx::support_xcm_oracle(RuntimeOrigin::root(), KSM, true));
 		assert_eq!(CurrencyIdList::<Test>::get().to_vec(), vec![BNC, KSM]);
 
-		assert_ok!(Slpx::set_currency_ethereum_call_switch(RuntimeOrigin::root(), BNC, false));
+		assert_ok!(Slpx::support_xcm_oracle(RuntimeOrigin::root(), BNC, false));
 		assert_eq!(CurrencyIdList::<Test>::get().to_vec(), vec![KSM]);
 	})
 }
 
 #[test]
 fn test_set_ethereum_call_configration() {
-	sp_io::TestExternalities::default().execute_with(|| {
-		assert_ok!(Slpx::set_ethereum_call_configration(
+	new_test_ext().execute_with(|| {
+		assert_ok!(Slpx::set_xcm_oracle_configuration(
 			RuntimeOrigin::root(),
 			1_000_000_000_000_000_000u128,
 			Weight::default(),
@@ -309,7 +327,7 @@ fn test_set_ethereum_call_configration() {
 			}
 		);
 
-		assert_ok!(Slpx::set_ethereum_call_configration(
+		assert_ok!(Slpx::set_xcm_oracle_configuration(
 			RuntimeOrigin::root(),
 			1u128,
 			Weight::default(),
@@ -332,7 +350,7 @@ fn test_set_ethereum_call_configration() {
 
 #[test]
 fn test_set_currency_to_support_xcm_fee() {
-	sp_io::TestExternalities::default().execute_with(|| {
+	new_test_ext().execute_with(|| {
 		assert_ok!(Slpx::set_currency_support_xcm_fee(RuntimeOrigin::root(), BNC, true));
 		assert_eq!(SupportXcmFeeList::<Test>::get().to_vec(), vec![BNC]);
 
@@ -346,8 +364,12 @@ fn test_set_currency_to_support_xcm_fee() {
 
 #[test]
 fn test_add_order() {
-	sp_io::TestExternalities::default().execute_with(|| {
-		assert_ok!(Slpx::add_whitelist(RuntimeOrigin::root(), SupportChain::Astar, ALICE));
+	new_test_ext().execute_with(|| {
+		WhitelistAccountId::<Test>::insert(
+			SupportChain::Astar,
+			BoundedVec::try_from(vec![ALICE]).unwrap(),
+		);
+
 		let source_chain_caller = H160::default();
 		assert_ok!(Slpx::mint(
 			RuntimeOrigin::signed(ALICE),
@@ -366,12 +388,12 @@ fn test_add_order() {
 		assert_eq!(OrderQueue::<Test>::get().len(), 2usize);
 		assert_ok!(Slpx::force_add_order(
 			RuntimeOrigin::root(),
+			OrderCaller::Evm(source_chain_caller),
 			ALICE,
-			source_chain_caller,
 			VDOT,
 			TargetChain::Astar(source_chain_caller),
 			BoundedVec::default(),
-			OrderType::Mint
+			0
 		));
 		assert_eq!(OrderQueue::<Test>::get().len(), 3usize);
 
@@ -381,8 +403,12 @@ fn test_add_order() {
 
 #[test]
 fn test_mint_with_channel_id() {
-	sp_io::TestExternalities::default().execute_with(|| {
-		assert_ok!(Slpx::add_whitelist(RuntimeOrigin::root(), SupportChain::Astar, ALICE));
+	new_test_ext().execute_with(|| {
+		WhitelistAccountId::<Test>::insert(
+			SupportChain::Astar,
+			BoundedVec::try_from(vec![ALICE]).unwrap(),
+		);
+
 		let source_chain_caller = H160::default();
 		assert_ok!(Slpx::mint_with_channel_id(
 			RuntimeOrigin::signed(ALICE),
@@ -405,8 +431,11 @@ fn test_mint_with_channel_id() {
 
 #[test]
 fn test_hook() {
-	sp_io::TestExternalities::default().execute_with(|| {
-		assert_ok!(Slpx::add_whitelist(RuntimeOrigin::root(), SupportChain::Astar, ALICE));
+	new_test_ext().execute_with(|| {
+		WhitelistAccountId::<Test>::insert(
+			SupportChain::Astar,
+			BoundedVec::try_from(vec![ALICE]).unwrap(),
+		);
 		let source_chain_caller = H160::default();
 		assert_ok!(Slpx::mint(
 			RuntimeOrigin::signed(ALICE),
diff --git a/pallets/slpx/src/types.rs b/pallets/slpx/src/types.rs
index 5290126d5..e38e0568a 100644
--- a/pallets/slpx/src/types.rs
+++ b/pallets/slpx/src/types.rs
@@ -60,6 +60,18 @@ pub enum TargetChain<AccountId> {
 	Manta(AccountId),
 }
 
+impl<AccountId> TargetChain<AccountId> {
+	pub fn support_chain(self: &TargetChain<AccountId>) -> SupportChain {
+		match self {
+			TargetChain::Astar(_) => SupportChain::Astar,
+			TargetChain::Moonbeam(_) => SupportChain::Moonbeam,
+			TargetChain::Hydradx(_) => SupportChain::Hydradx,
+			TargetChain::Interlay(_) => SupportChain::Interlay,
+			TargetChain::Manta(_) => SupportChain::Manta,
+		}
+	}
+}
+
 #[derive(Clone, Debug, Eq, PartialEq, Encode, Decode, TypeInfo, MaxEncodedLen)]
 pub struct EthereumCallConfiguration<BlockNumber> {
 	/// XCM message execution costs to be consumed
diff --git a/runtime/bifrost-kusama/src/lib.rs b/runtime/bifrost-kusama/src/lib.rs
index 5095e5a50..aa98fd219 100644
--- a/runtime/bifrost-kusama/src/lib.rs
+++ b/runtime/bifrost-kusama/src/lib.rs
@@ -1502,17 +1502,17 @@ impl bifrost_vtoken_minting::Config for Runtime {
 
 impl bifrost_slpx::Config for Runtime {
 	type RuntimeEvent = RuntimeEvent;
+	type RuntimeOrigin = RuntimeOrigin;
 	type ControlOrigin = TechAdminOrCouncil;
 	type MultiCurrency = Currencies;
-	type DexOperator = ZenlinkProtocol;
 	type VtokenMintingInterface = VtokenMinting;
-	type StablePoolHandler = StablePool;
 	type XcmTransfer = XTokens;
 	type XcmSender = XcmRouter;
 	type CurrencyIdConvert = AssetIdMaps<Runtime>;
 	type TreasuryAccount = BifrostTreasuryAccount;
 	type ParachainId = ParachainInfo;
 	type WeightInfo = weights::bifrost_slpx::BifrostWeight<Runtime>;
+	type MaxOrderSize = ConstU32<500>;
 }
 
 pub struct EnsurePoolAssetId;
diff --git a/runtime/bifrost-polkadot/src/lib.rs b/runtime/bifrost-polkadot/src/lib.rs
index 579a05809..409b4b72c 100644
--- a/runtime/bifrost-polkadot/src/lib.rs
+++ b/runtime/bifrost-polkadot/src/lib.rs
@@ -1200,17 +1200,17 @@ impl bifrost_cross_in_out::Config for Runtime {
 
 impl bifrost_slpx::Config for Runtime {
 	type RuntimeEvent = RuntimeEvent;
+	type RuntimeOrigin = RuntimeOrigin;
 	type ControlOrigin = TechAdminOrCouncil;
 	type MultiCurrency = Currencies;
-	type DexOperator = ZenlinkProtocol;
 	type VtokenMintingInterface = VtokenMinting;
-	type StablePoolHandler = StablePool;
 	type XcmTransfer = XTokens;
 	type XcmSender = XcmRouter;
 	type CurrencyIdConvert = AssetIdMaps<Runtime>;
 	type TreasuryAccount = BifrostTreasuryAccount;
 	type ParachainId = ParachainInfo;
 	type WeightInfo = weights::bifrost_slpx::BifrostWeight<Runtime>;
+	type MaxOrderSize = ConstU32<500>;
 }
 
 pub struct EnsurePoolAssetId;
diff --git a/runtime/bifrost-polkadot/src/xcm_config.rs b/runtime/bifrost-polkadot/src/xcm_config.rs
index ede51c1ca..f9577776c 100644
--- a/runtime/bifrost-polkadot/src/xcm_config.rs
+++ b/runtime/bifrost-polkadot/src/xcm_config.rs
@@ -118,6 +118,8 @@ pub type Barrier = TrailingSetTopicAsId<(
 		(
 			// If the message is one that immediately attemps to pay for execution, then allow it.
 			AllowTopLevelPaidExecutionFrom<Everything>,
+			// TODO: Messages coming from system parachains need not pay for execution.
+			// AllowExplicitUnpaidExecutionFrom<Everything>,
 			// Subscriptions for version tracking are OK.
 			AllowSubscriptionsFrom<Everything>,
 		),

From 0aaf2cdd32047d4c4ddbc996a7f46e4f94081728 Mon Sep 17 00:00:00 2001
From: MJLNSN <96321798+MJLNSN@users.noreply.github.com>
Date: Sun, 29 Sep 2024 15:30:06 +0800
Subject: [PATCH 09/31] Moved palletId in runtime to primitives (#1443)

---
 primitives/src/lib.rs                      | 16 ++++++----
 runtime/bifrost-kusama/src/lib.rs          | 34 ++++++----------------
 runtime/bifrost-kusama/src/xcm_config.rs   |  2 +-
 runtime/bifrost-polkadot/src/lib.rs        | 33 ++++++---------------
 runtime/bifrost-polkadot/src/xcm_config.rs |  2 +-
 5 files changed, 31 insertions(+), 56 deletions(-)

diff --git a/primitives/src/lib.rs b/primitives/src/lib.rs
index b711cb02d..6b58e7f04 100644
--- a/primitives/src/lib.rs
+++ b/primitives/src/lib.rs
@@ -161,9 +161,10 @@ pub type TimeStampedPrice = orml_oracle::TimestampedValue<Price, Moment>;
 // Pallet Id
 parameter_types! {
 	pub const BifrostCrowdloanId: PalletId = PalletId(*b"bf/salp#");
-	pub BifrostEntranceAccount: PalletId = PalletId(*b"bf/vtkin");
-	pub BifrostExitAccount: PalletId = PalletId(*b"bf/vtout");
-	pub BifrostVsbondAccount: PalletId = PalletId(*b"bf/salpb");
+	pub const BifrostEntranceAccount: PalletId = PalletId(*b"bf/vtkin");
+	pub const BifrostExitAccount: PalletId = PalletId(*b"bf/vtout");
+	pub const BifrostSalpLiteCrowdloanId: PalletId = PalletId(*b"bf/salpl");
+	pub const BifrostVsbondAccount: PalletId = PalletId(*b"bf/salpb");
 	pub const BuyBackAccount: PalletId = PalletId(*b"bf/bybck");
 	pub const BuybackPalletId: PalletId = PalletId(*b"bf/salpc");
 	pub const CloudsPalletId: PalletId = PalletId(*b"bf/cloud");
@@ -174,17 +175,22 @@ parameter_types! {
 	pub const FarmingRewardIssuerPalletId: PalletId = PalletId(*b"bf/fmrir");
 	pub const FeeSharePalletId: PalletId = PalletId(*b"bf/feesh");
 	pub const FlexibleFeePalletId: PalletId = PalletId(*b"bf/flexi");
-	pub IncentivePoolAccount: PalletId = PalletId(*b"bf/inpoo");
-	pub IncentivePalletId: PalletId = PalletId(*b"bf/bbict");
+	pub const IncentivePoolAccount: PalletId = PalletId(*b"bf/inpoo");
+	pub const IncentivePalletId: PalletId = PalletId(*b"bf/bbict");
 	pub const LendMarketPalletId: PalletId = PalletId(*b"bf/ldmkt");
 	pub const LighteningRedeemPalletId: PalletId = PalletId(*b"lighten#");
 	pub const LiquidityAccount: PalletId = PalletId(*b"bf/liqdt");
+	pub const LiquidityMiningDOTPalletId: PalletId = PalletId(*b"bf/lmdot");
 	pub const LiquidityMiningPalletId: PalletId = PalletId(*b"mining##");
+	pub const MerkleDirtributorPalletId: PalletId = PalletId(*b"bf/mklds");
+	pub const OraclePalletId: PalletId = PalletId(*b"bf/oracl");
 	pub const ParachainStakingPalletId: PalletId = PalletId(*b"bf/stake");
 	pub const SlpEntrancePalletId: PalletId = PalletId(*b"bf/vtkin");
+	pub const SlpExitPalletId: PalletId = PalletId(*b"bf/vtout");
 	pub const StableAssetPalletId: PalletId = PalletId(*b"nuts/sta");
 	pub const SystemMakerPalletId: PalletId = PalletId(*b"bf/sysmk");
 	pub const SystemStakingPalletId: PalletId = PalletId(*b"bf/sysst");
+	pub const TreasuryPalletId: PalletId = PalletId(*b"bf/trsry");
 	pub const VBNCConvertPalletId: PalletId = PalletId(*b"bf/vbncc");
 	pub const VeMintingPalletId: PalletId = PalletId(*b"bf/vemnt");
 	pub const VsbondAuctionPalletId: PalletId = PalletId(*b"bf/vsbnd");
diff --git a/runtime/bifrost-kusama/src/lib.rs b/runtime/bifrost-kusama/src/lib.rs
index aa98fd219..2a71076ee 100644
--- a/runtime/bifrost-kusama/src/lib.rs
+++ b/runtime/bifrost-kusama/src/lib.rs
@@ -30,6 +30,14 @@ use bifrost_slp::{DerivativeAccountProvider, QueryResponseManager};
 use core::convert::TryInto;
 // A few exports that help ease life for downstream crates.
 pub use bifrost_parachain_staking::{InflationInfo, Range};
+use bifrost_primitives::{
+	BifrostCrowdloanId, BifrostVsbondAccount, BuybackPalletId, CommissionPalletId,
+	FarmingBoostPalletId, FarmingGaugeRewardIssuerPalletId, FarmingKeeperPalletId,
+	FarmingRewardIssuerPalletId, FeeSharePalletId, FlexibleFeePalletId, IncentivePoolAccount,
+	LendMarketPalletId, MerkleDirtributorPalletId, OraclePalletId, ParachainStakingPalletId,
+	SlpEntrancePalletId, SlpExitPalletId, SystemMakerPalletId, SystemStakingPalletId,
+	TreasuryPalletId, VBNCConvertPalletId, VsbondAuctionPalletId,
+};
 pub use frame_support::{
 	construct_runtime, match_types, parameter_types,
 	traits::{
@@ -205,35 +213,11 @@ parameter_types! {
 }
 
 parameter_types! {
-	pub const TreasuryPalletId: PalletId = PalletId(*b"bf/trsry");
-	pub const BifrostCrowdloanId: PalletId = PalletId(*b"bf/salp#");
-	pub const BifrostSalpLiteCrowdloanId: PalletId = PalletId(*b"bf/salpl");
 	pub const LiquidityMiningPalletId: PalletId = PalletId(*b"bf/lm###");
-	pub const LiquidityMiningDOTPalletId: PalletId = PalletId(*b"bf/lmdot");
 	pub const LighteningRedeemPalletId: PalletId = PalletId(*b"bf/ltnrd");
-	pub const MerkleDirtributorPalletId: PalletId = PalletId(*b"bf/mklds");
-	pub const VsbondAuctionPalletId: PalletId = PalletId(*b"bf/vsbnd");
-	pub const ParachainStakingPalletId: PalletId = PalletId(*b"bf/stake");
-	pub const BifrostVsbondPalletId: PalletId = PalletId(*b"bf/salpb");
-	pub const SlpEntrancePalletId: PalletId = PalletId(*b"bf/vtkin");
-	pub const SlpExitPalletId: PalletId = PalletId(*b"bf/vtout");
 	pub const StableAmmPalletId: PalletId = PalletId(*b"bf/stamm");
-	pub const FarmingKeeperPalletId: PalletId = PalletId(*b"bf/fmkpr");
-	pub const FarmingRewardIssuerPalletId: PalletId = PalletId(*b"bf/fmrir");
-	pub const SystemStakingPalletId: PalletId = PalletId(*b"bf/sysst");
-	pub const BuybackPalletId: PalletId = PalletId(*b"bf/salpc");
-	pub const SystemMakerPalletId: PalletId = PalletId(*b"bf/sysmk");
-	pub const FeeSharePalletId: PalletId = PalletId(*b"bf/feesh");
 	pub CheckingAccount: AccountId = PolkadotXcm::check_account();
-	pub const FarmingBoostPalletId: PalletId = PalletId(*b"bf/fmbst");
-	pub const LendMarketPalletId: PalletId = PalletId(*b"bf/ldmkt");
-	pub const OraclePalletId: PalletId = PalletId(*b"bf/oracl");
 	pub const StableAssetPalletId: PalletId = PalletId(*b"bf/stabl");
-	pub const CommissionPalletId: PalletId = PalletId(*b"bf/comms");
-	pub IncentivePoolAccount: PalletId = PalletId(*b"bf/inpoo");
-	pub const FarmingGaugeRewardIssuerPalletId: PalletId = PalletId(*b"bf/fmgar");
-	pub const FlexibleFeePalletId: PalletId = PalletId(*b"bf/flexi");
-	pub const VBNCConvertPalletId: PalletId = PalletId(*b"bf/vbncc");
 }
 
 impl frame_system::Config for Runtime {
@@ -1274,7 +1258,7 @@ impl bifrost_vstoken_conversion::Config for Runtime {
 	type RelayCurrencyId = RelayCurrencyId;
 	type TreasuryAccount = BifrostTreasuryAccount;
 	type ControlOrigin = CoreAdminOrCouncil;
-	type VsbondAccount = BifrostVsbondPalletId;
+	type VsbondAccount = BifrostVsbondAccount;
 	type CurrencyIdConversion = AssetIdMaps<Runtime>;
 	type WeightInfo = weights::bifrost_vstoken_conversion::BifrostWeight<Runtime>;
 }
diff --git a/runtime/bifrost-kusama/src/xcm_config.rs b/runtime/bifrost-kusama/src/xcm_config.rs
index 8222f6b28..414600305 100644
--- a/runtime/bifrost-kusama/src/xcm_config.rs
+++ b/runtime/bifrost-kusama/src/xcm_config.rs
@@ -559,7 +559,7 @@ impl Contains<AccountId> for DustRemovalWhitelist {
 		let whitelist: Vec<AccountId> = vec![
 			TreasuryPalletId::get().into_account_truncating(),
 			BifrostCrowdloanId::get().into_account_truncating(),
-			BifrostVsbondPalletId::get().into_account_truncating(),
+			BifrostVsbondAccount::get().into_account_truncating(),
 			SlpEntrancePalletId::get().into_account_truncating(),
 			SlpExitPalletId::get().into_account_truncating(),
 			BuybackPalletId::get().into_account_truncating(),
diff --git a/runtime/bifrost-polkadot/src/lib.rs b/runtime/bifrost-polkadot/src/lib.rs
index 409b4b72c..f63de4618 100644
--- a/runtime/bifrost-polkadot/src/lib.rs
+++ b/runtime/bifrost-polkadot/src/lib.rs
@@ -30,6 +30,14 @@ use bifrost_slp::{DerivativeAccountProvider, QueryResponseManager};
 use core::convert::TryInto;
 use pallet_traits::evm::InspectEvmAccounts;
 // A few exports that help ease life for downstream crates.
+use bifrost_primitives::{
+	BifrostCrowdloanId, BifrostVsbondAccount, BuyBackAccount, BuybackPalletId, CloudsPalletId,
+	CommissionPalletId, FarmingBoostPalletId, FarmingGaugeRewardIssuerPalletId,
+	FarmingKeeperPalletId, FarmingRewardIssuerPalletId, FeeSharePalletId, FlexibleFeePalletId,
+	IncentivePalletId, IncentivePoolAccount, LendMarketPalletId, LiquidityAccount,
+	MerkleDirtributorPalletId, OraclePalletId, SlpEntrancePalletId, SlpExitPalletId,
+	SystemMakerPalletId, SystemStakingPalletId, TreasuryPalletId,
+};
 use cumulus_pallet_parachain_system::{RelayNumberStrictlyIncreases, RelaychainDataProvider};
 pub use frame_support::{
 	construct_runtime, match_types, parameter_types,
@@ -226,31 +234,8 @@ parameter_types! {
 }
 
 parameter_types! {
-	pub const TreasuryPalletId: PalletId = PalletId(*b"bf/trsry");
-	pub const BifrostCrowdloanId: PalletId = PalletId(*b"bf/salp#");
-	pub const MerkleDirtributorPalletId: PalletId = PalletId(*b"bf/mklds");
-	pub const BifrostVsbondPalletId: PalletId = PalletId(*b"bf/salpb");
-	pub const SlpEntrancePalletId: PalletId = PalletId(*b"bf/vtkin");
-	pub const SlpExitPalletId: PalletId = PalletId(*b"bf/vtout");
-	pub const FarmingKeeperPalletId: PalletId = PalletId(*b"bf/fmkpr");
-	pub const FarmingRewardIssuerPalletId: PalletId = PalletId(*b"bf/fmrir");
-	pub const SystemStakingPalletId: PalletId = PalletId(*b"bf/sysst");
-	pub const BuybackPalletId: PalletId = PalletId(*b"bf/salpc");
-	pub const SystemMakerPalletId: PalletId = PalletId(*b"bf/sysmk");
-	pub const FeeSharePalletId: PalletId = PalletId(*b"bf/feesh");
 	pub CheckingAccount: AccountId = PolkadotXcm::check_account();
-	pub const IncentivePalletId: PalletId = PalletId(*b"bf/bbict");
-	pub const FarmingBoostPalletId: PalletId = PalletId(*b"bf/fmbst");
-	pub const LendMarketPalletId: PalletId = PalletId(*b"bf/ldmkt");
-	pub const OraclePalletId: PalletId = PalletId(*b"bf/oracl");
 	pub const StableAssetPalletId: PalletId = PalletId(*b"bf/stabl");
-	pub const CommissionPalletId: PalletId = PalletId(*b"bf/comms");
-	pub const CloudsPalletId: PalletId = PalletId(*b"bf/cloud");
-	pub IncentivePoolAccount: PalletId = PalletId(*b"bf/inpoo");
-	pub const FarmingGaugeRewardIssuerPalletId: PalletId = PalletId(*b"bf/fmgar");
-	pub const BuyBackAccount: PalletId = PalletId(*b"bf/bybck");
-	pub const LiquidityAccount: PalletId = PalletId(*b"bf/liqdt");
-	pub const FlexibleFeePalletId: PalletId = PalletId(*b"bf/flexi");
 }
 
 impl frame_system::Config for Runtime {
@@ -1135,7 +1120,7 @@ impl bifrost_vstoken_conversion::Config for Runtime {
 	type RelayCurrencyId = RelayCurrencyId;
 	type TreasuryAccount = BifrostTreasuryAccount;
 	type ControlOrigin = CoreAdminOrCouncil;
-	type VsbondAccount = BifrostVsbondPalletId;
+	type VsbondAccount = BifrostVsbondAccount;
 	type CurrencyIdConversion = AssetIdMaps<Runtime>;
 	type WeightInfo = weights::bifrost_vstoken_conversion::BifrostWeight<Runtime>;
 }
diff --git a/runtime/bifrost-polkadot/src/xcm_config.rs b/runtime/bifrost-polkadot/src/xcm_config.rs
index f9577776c..69ab3fa92 100644
--- a/runtime/bifrost-polkadot/src/xcm_config.rs
+++ b/runtime/bifrost-polkadot/src/xcm_config.rs
@@ -443,7 +443,7 @@ impl Contains<AccountId> for DustRemovalWhitelist {
 		let whitelist: Vec<AccountId> = vec![
 			TreasuryPalletId::get().into_account_truncating(),
 			BifrostCrowdloanId::get().into_account_truncating(),
-			BifrostVsbondPalletId::get().into_account_truncating(),
+			BifrostVsbondAccount::get().into_account_truncating(),
 			SlpEntrancePalletId::get().into_account_truncating(),
 			SlpExitPalletId::get().into_account_truncating(),
 			BuybackPalletId::get().into_account_truncating(),

From c081548ef504abf3fd7b5329b138547fa62d5c32 Mon Sep 17 00:00:00 2001
From: SunTiebing <87381708+SunTiebing@users.noreply.github.com>
Date: Sun, 29 Sep 2024 16:14:00 +0800
Subject: [PATCH 10/31] Optimize asset registry (#1445)

* optimize asset-registry & remove unused call

* backup asset-registry pallet
---
 pallets/asset-registry/src/benchmarking.rs    |  140 +--
 pallets/asset-registry/src/lib.rs             |  355 +-----
 pallets/asset-registry/src/migrations/mod.rs  |   19 +
 pallets/asset-registry/src/migrations/v0.rs   |  131 +++
 pallets/asset-registry/src/migrations/v1.rs   |  118 ++
 pallets/asset-registry/src/tests.rs           |  208 +---
 pallets/asset-registry/src/weights.rs         |   56 -
 pallets/deprecated/asset-registry/Cargo.toml  |   51 +
 .../asset-registry/src/benchmarking.rs        |  309 +++++
 pallets/deprecated/asset-registry/src/lib.rs  | 1013 +++++++++++++++++
 .../asset-registry/src/migration.rs           |    0
 pallets/deprecated/asset-registry/src/mock.rs |  109 ++
 .../deprecated/asset-registry/src/tests.rs    |  519 +++++++++
 .../deprecated/asset-registry/src/weights.rs  |  190 ++++
 pallets/slpx/src/benchmarking.rs              |    4 +-
 primitives/src/traits.rs                      |   60 -
 .../src/weights/bifrost_asset_registry.rs     |   52 -
 .../src/weights/bifrost_asset_registry.rs     |   52 -
 18 files changed, 2496 insertions(+), 890 deletions(-)
 create mode 100644 pallets/asset-registry/src/migrations/mod.rs
 create mode 100644 pallets/asset-registry/src/migrations/v0.rs
 create mode 100644 pallets/asset-registry/src/migrations/v1.rs
 create mode 100644 pallets/deprecated/asset-registry/Cargo.toml
 create mode 100644 pallets/deprecated/asset-registry/src/benchmarking.rs
 create mode 100644 pallets/deprecated/asset-registry/src/lib.rs
 rename pallets/{ => deprecated}/asset-registry/src/migration.rs (100%)
 create mode 100644 pallets/deprecated/asset-registry/src/mock.rs
 create mode 100644 pallets/deprecated/asset-registry/src/tests.rs
 create mode 100644 pallets/deprecated/asset-registry/src/weights.rs

diff --git a/pallets/asset-registry/src/benchmarking.rs b/pallets/asset-registry/src/benchmarking.rs
index bb7b63b13..5c5555516 100644
--- a/pallets/asset-registry/src/benchmarking.rs
+++ b/pallets/asset-registry/src/benchmarking.rs
@@ -20,82 +20,12 @@
 
 use super::*;
 use crate::Pallet as AssetRegistry;
-use bifrost_primitives::{CurrencyId, TokenSymbol};
+use bifrost_primitives::CurrencyId;
 use frame_benchmarking::{benchmarks, v1::BenchmarkError};
 use frame_support::{assert_ok, traits::UnfilteredDispatchable};
 use sp_runtime::traits::UniqueSaturatedFrom;
 
 benchmarks! {
-	register_native_asset {
-		let origin = T::RegisterOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
-		let versioned_location = VersionedLocation::V4(Location::from([Parachain(1000)]));
-
-	let call = Call::<T>::register_native_asset {
-			currency_id: Token(TokenSymbol::DOT),
-			location: Box::new(versioned_location.clone()),
-			metadata: Box::new(AssetMetadata {
-				name: b"Token Name".to_vec(),
-				symbol: b"TN".to_vec(),
-				decimals: 12,
-				minimal_balance: BalanceOf::<T>::unique_saturated_from(1u128),
-			})
-		};
-	}: {call.dispatch_bypass_filter(origin)?}
-	verify {
-		assert_eq!(
-			AssetMetadatas::<T>::get(AssetIds::NativeAssetId(Token(
-				TokenSymbol::DOT
-			))),
-			Some(AssetMetadata {
-				name: b"Token Name".to_vec(),
-				symbol: b"TN".to_vec(),
-				decimals: 12,
-				minimal_balance: BalanceOf::<T>::unique_saturated_from(1u128),
-			})
-		);
-	}
-
-	update_native_asset {
-		let origin = T::RegisterOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
-		let versioned_location = VersionedLocation::V4(Location::from([Parachain(1000)]));
-
-		assert_ok!(AssetRegistry::<T>::register_native_asset(
-			origin.clone(),
-			Token(TokenSymbol::DOT),
-			Box::new(versioned_location.clone()),
-			Box::new(AssetMetadata {
-				name: b"Token Name".to_vec(),
-				symbol: b"TN".to_vec(),
-				decimals: 12,
-				minimal_balance: BalanceOf::<T>::unique_saturated_from(1u128),
-			})
-		));
-
-	let call = Call::<T>::update_native_asset {
-			currency_id: Token(TokenSymbol::DOT),
-			location: Box::new(versioned_location.clone()),
-			metadata: Box::new(AssetMetadata {
-				name: b"Token Name".to_vec(),
-				symbol: b"TN".to_vec(),
-				decimals: 13,
-				minimal_balance: BalanceOf::<T>::unique_saturated_from(2u128),
-			})
-		};
-	}: {call.dispatch_bypass_filter(origin)?}
-	verify {
-		assert_eq!(
-			AssetMetadatas::<T>::get(AssetIds::NativeAssetId(Token(
-				TokenSymbol::DOT
-			))),
-			Some(AssetMetadata {
-				name: b"Token Name".to_vec(),
-				symbol: b"TN".to_vec(),
-				decimals: 13,
-				minimal_balance: BalanceOf::<T>::unique_saturated_from(2u128),
-			})
-		);
-	}
-
 	register_token_metadata {
 		let origin = T::RegisterOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
 		let metadata = AssetMetadata {
@@ -143,70 +73,6 @@ benchmarks! {
 		)
 	}
 
-	register_vstoken_metadata {
-		let origin = T::RegisterOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
-		let metadata = AssetMetadata {
-			name: b"KSM Native Token".to_vec(),
-			symbol: b"KSM".to_vec(),
-			decimals: 12,
-			minimal_balance: BalanceOf::<T>::unique_saturated_from(0u128),
-		};
-		let v_metadata = AssetMetadata {
-			name: b"Voucher Slot KSM".to_vec(),
-			symbol: b"vsKSM".to_vec(),
-			decimals: 12,
-			minimal_balance: BalanceOf::<T>::unique_saturated_from(0u128),
-		};
-		assert_ok!(AssetRegistry::<T>::register_token_metadata(
-			origin.clone(),
-			Box::new(metadata.clone())
-		));
-
-		let call = Call::<T>::register_vstoken_metadata {
-			token_id: 0
-		};
-	}: {call.dispatch_bypass_filter(origin)?}
-	verify {
-		assert_eq!(
-			CurrencyMetadatas::<T>::get(CurrencyId::VSToken2(0)),
-			Some(v_metadata.clone())
-		)
-	}
-
-	register_vsbond_metadata {
-		let origin = T::RegisterOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
-				let metadata = AssetMetadata {
-			name: b"KSM Native Token".to_vec(),
-			symbol: b"KSM".to_vec(),
-			decimals: 12,
-			minimal_balance: BalanceOf::<T>::unique_saturated_from(0u128),
-		};
-		let name = "vsBOND-KSM-2001-10-20".as_bytes().to_vec();
-		let v_metadata = AssetMetadata {
-			name: name.clone(),
-			symbol: name,
-			decimals: 12,
-			minimal_balance: BalanceOf::<T>::unique_saturated_from(0u128),
-		};
-		assert_ok!(AssetRegistry::<T>::register_token_metadata(
-			origin.clone(),
-			Box::new(metadata.clone())
-		));
-
-		let call = Call::<T>::register_vsbond_metadata {
-			token_id: 0,
-			para_id:2001,
-			first_slot:10,
-			last_slot:20
-		};
-	}: {call.dispatch_bypass_filter(origin)?}
-	verify {
-		assert_eq!(
-			CurrencyMetadatas::<T>::get(CurrencyId::VSBond2(0, 2001, 10, 20)),
-			Some(v_metadata.clone())
-		)
-	}
-
 	register_location {
 		let origin = T::RegisterOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
 		let metadata = AssetMetadata {
@@ -217,7 +83,7 @@ benchmarks! {
 		};
 	let versioned_location = VersionedLocation::V4(Location::new(1, [Parachain(2001)]));
 
-		let location: xcm::v3::Location = versioned_location.clone().try_into().unwrap();
+		let location: xcm::v4::Location = versioned_location.clone().try_into().unwrap();
 
 		assert_ok!(AssetRegistry::<T>::register_token_metadata(
 			origin.clone(),
@@ -232,7 +98,7 @@ benchmarks! {
 	}: {call.dispatch_bypass_filter(origin)?}
 	verify {
 		assert_eq!(
-			LocationToCurrencyIds::<T>::get(location),
+			LocationToCurrencyIds::<T>::get(location.clone()),
 			Some(Token2(0))
 		);
 		assert_eq!(
diff --git a/pallets/asset-registry/src/lib.rs b/pallets/asset-registry/src/lib.rs
index c35d14481..edf1ca0e4 100644
--- a/pallets/asset-registry/src/lib.rs
+++ b/pallets/asset-registry/src/lib.rs
@@ -51,7 +51,7 @@ use xcm::{
 use xcm_builder::TakeRevenue;
 use xcm_executor::{traits::WeightTrader, AssetsInHolding};
 
-pub mod migration;
+pub mod migrations;
 mod mock;
 mod tests;
 pub mod weights;
@@ -66,6 +66,14 @@ pub use weights::WeightInfo;
 pub type BalanceOf<T> =
 	<<T as Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance;
 
+#[derive(Clone, Eq, PartialEq, RuntimeDebug, Encode, Decode, TypeInfo)]
+pub struct AssetMetadata<Balance> {
+	pub name: Vec<u8>,
+	pub symbol: Vec<u8>,
+	pub decimals: u8,
+	pub minimal_balance: Balance,
+}
+
 #[frame_support::pallet]
 pub mod pallet {
 	use super::*;
@@ -85,14 +93,6 @@ pub mod pallet {
 		type WeightInfo: WeightInfo;
 	}
 
-	#[derive(Clone, Eq, PartialEq, RuntimeDebug, Encode, Decode, TypeInfo)]
-	pub struct AssetMetadata<Balance> {
-		pub name: Vec<u8>,
-		pub symbol: Vec<u8>,
-		pub decimals: u8,
-		pub minimal_balance: Balance,
-	}
-
 	#[pallet::error]
 	pub enum Error<T> {
 		/// The given location could not be used (e.g. because it cannot be expressed in the
@@ -142,14 +142,14 @@ pub mod pallet {
 	/// CurrencyIdToLocations: map CurrencyId => Option<Location>
 	#[pallet::storage]
 	pub type CurrencyIdToLocations<T: Config> =
-		StorageMap<_, Twox64Concat, CurrencyId, xcm::v3::Location, OptionQuery>;
+		StorageMap<_, Twox64Concat, CurrencyId, Location, OptionQuery>;
 
 	/// The storages for CurrencyIds.
 	///
 	/// LocationToCurrencyIds: map Location => Option<CurrencyId>
 	#[pallet::storage]
 	pub type LocationToCurrencyIds<T: Config> =
-		StorageMap<_, Twox64Concat, xcm::v3::Location, CurrencyId, OptionQuery>;
+		StorageMap<_, Twox64Concat, Location, CurrencyId, OptionQuery>;
 
 	#[pallet::storage]
 	pub type CurrencyIdToWeights<T: Config> =
@@ -213,30 +213,6 @@ pub mod pallet {
 				Pallet::<T>::do_register_metadata(*currency_id, &metadata).expect("Token register");
 			}
 
-			for (currency, para_id, first_slot, last_slot) in self.vsbond.iter() {
-				match currency {
-					Token(symbol) | Native(symbol) => {
-						AssetIdMaps::<T>::register_vsbond_metadata(
-							*symbol,
-							*para_id,
-							*first_slot,
-							*last_slot,
-						)
-						.expect("VSBond register");
-					},
-					Token2(token_id) => {
-						AssetIdMaps::<T>::register_vsbond2_metadata(
-							*token_id,
-							*para_id,
-							*first_slot,
-							*last_slot,
-						)
-						.expect("VToken register");
-					},
-					_ => (),
-				}
-			}
-
 			for &currency in self.vcurrency.iter() {
 				match currency {
 					CurrencyId::VToken(symbol) => {
@@ -247,68 +223,21 @@ pub mod pallet {
 						AssetIdMaps::<T>::register_vtoken2_metadata(token_id)
 							.expect("VToken register");
 					},
-					CurrencyId::VSToken(symbol) => {
-						AssetIdMaps::<T>::register_vstoken_metadata(symbol)
-							.expect("VSToken register");
-					},
-					CurrencyId::VSToken2(token_id) => {
-						AssetIdMaps::<T>::register_vstoken2_metadata(token_id)
-							.expect("VSToken register");
-					},
 					_ => (),
 				}
 			}
 		}
 	}
 
+	const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);
+
 	#[pallet::pallet]
 	#[pallet::without_storage_info]
+	#[pallet::storage_version(STORAGE_VERSION)]
 	pub struct Pallet<T>(_);
 
 	#[pallet::call]
 	impl<T: Config> Pallet<T> {
-		#[pallet::call_index(0)]
-		#[pallet::weight(T::WeightInfo::register_native_asset())]
-		pub fn register_native_asset(
-			origin: OriginFor<T>,
-			currency_id: CurrencyId,
-			location: Box<VersionedLocation>,
-			metadata: Box<AssetMetadata<BalanceOf<T>>>,
-		) -> DispatchResult {
-			T::RegisterOrigin::ensure_origin(origin)?;
-
-			let location: Location =
-				(*location).try_into().map_err(|()| Error::<T>::BadLocation)?;
-			Self::do_register_native_asset(currency_id, &location, &metadata)?;
-
-			Self::deposit_event(Event::<T>::AssetRegistered {
-				asset_id: AssetIds::NativeAssetId(currency_id),
-				metadata: *metadata,
-			});
-			Ok(())
-		}
-
-		#[pallet::call_index(1)]
-		#[pallet::weight(T::WeightInfo::update_native_asset())]
-		pub fn update_native_asset(
-			origin: OriginFor<T>,
-			currency_id: CurrencyId,
-			location: Box<VersionedLocation>,
-			metadata: Box<AssetMetadata<BalanceOf<T>>>,
-		) -> DispatchResult {
-			T::RegisterOrigin::ensure_origin(origin)?;
-
-			let location: Location =
-				(*location).try_into().map_err(|()| Error::<T>::BadLocation)?;
-			Self::do_update_native_asset(currency_id, &location, &metadata)?;
-
-			Self::deposit_event(Event::<T>::AssetUpdated {
-				asset_id: AssetIds::NativeAssetId(currency_id),
-				metadata: *metadata,
-			});
-			Ok(())
-		}
-
 		#[pallet::call_index(2)]
 		#[pallet::weight(T::WeightInfo::register_token_metadata())]
 		pub fn register_token_metadata(
@@ -339,55 +268,6 @@ pub mod pallet {
 			}
 		}
 
-		#[pallet::call_index(4)]
-		#[pallet::weight(T::WeightInfo::register_vstoken_metadata())]
-		pub fn register_vstoken_metadata(
-			origin: OriginFor<T>,
-			token_id: TokenId,
-		) -> DispatchResult {
-			T::RegisterOrigin::ensure_origin(origin)?;
-
-			if let Some(token_metadata) = CurrencyMetadatas::<T>::get(CurrencyId::Token2(token_id))
-			{
-				let vstoken_metadata = Self::convert_to_vstoken_metadata(token_metadata);
-				Self::do_register_metadata(CurrencyId::VSToken2(token_id), &vstoken_metadata)?;
-
-				return Ok(());
-			} else {
-				return Err(Error::<T>::CurrencyIdNotExists)?;
-			}
-		}
-
-		#[pallet::call_index(5)]
-		#[pallet::weight(T::WeightInfo::register_vsbond_metadata())]
-		pub fn register_vsbond_metadata(
-			origin: OriginFor<T>,
-			token_id: TokenId,
-			para_id: ParaId,
-			first_slot: LeasePeriod,
-			last_slot: LeasePeriod,
-		) -> DispatchResult {
-			T::RegisterOrigin::ensure_origin(origin)?;
-
-			if let Some(token_metadata) = CurrencyMetadatas::<T>::get(CurrencyId::Token2(token_id))
-			{
-				let vsbond_metadata = Self::convert_to_vsbond_metadata(
-					token_metadata,
-					para_id,
-					first_slot,
-					last_slot,
-				);
-				Self::do_register_metadata(
-					CurrencyId::VSBond2(token_id, para_id, first_slot, last_slot),
-					&vsbond_metadata,
-				)?;
-
-				return Ok(());
-			} else {
-				return Err(Error::<T>::CurrencyIdNotExists)?;
-			}
-		}
-
 		#[pallet::call_index(6)]
 		#[pallet::weight(T::WeightInfo::register_location())]
 		pub fn register_location(
@@ -419,16 +299,16 @@ pub mod pallet {
 			let location: Location =
 				(*location).try_into().map_err(|()| Error::<T>::BadLocation)?;
 
-			let v3_location = xcm::v3::Location::try_from(location.clone())
-				.map_err(|()| Error::<T>::BadLocation)?;
+			let v4_location =
+				Location::try_from(location.clone()).map_err(|_| Error::<T>::BadLocation)?;
 
 			ensure!(
 				CurrencyMetadatas::<T>::get(currency_id).is_some(),
 				Error::<T>::CurrencyIdNotExists
 			);
 
-			LocationToCurrencyIds::<T>::insert(v3_location, currency_id);
-			CurrencyIdToLocations::<T>::insert(currency_id, v3_location);
+			LocationToCurrencyIds::<T>::insert(v4_location.clone(), currency_id);
+			CurrencyIdToLocations::<T>::insert(currency_id, v4_location);
 			CurrencyIdToWeights::<T>::insert(currency_id, weight);
 
 			Pallet::<T>::deposit_event(Event::<T>::LocationSet { currency_id, location, weight });
@@ -484,31 +364,6 @@ impl<T: Config> Pallet<T> {
 		})
 	}
 
-	pub fn do_register_native_asset(
-		currency_id: CurrencyId,
-		location: &Location,
-		metadata: &AssetMetadata<BalanceOf<T>>,
-	) -> DispatchResult {
-		let v3_location =
-			xcm::v3::Location::try_from(location.clone()).map_err(|()| Error::<T>::BadLocation)?;
-
-		ensure!(LocationToCurrencyIds::<T>::get(v3_location).is_none(), Error::<T>::AssetIdExisted);
-		ensure!(
-			CurrencyIdToLocations::<T>::get(currency_id).is_none(),
-			Error::<T>::LocationExisted
-		);
-		ensure!(
-			AssetMetadatas::<T>::get(AssetIds::NativeAssetId(currency_id)).is_none(),
-			Error::<T>::AssetIdExisted
-		);
-
-		LocationToCurrencyIds::<T>::insert(v3_location, currency_id);
-		CurrencyIdToLocations::<T>::insert(currency_id, v3_location);
-		AssetMetadatas::<T>::insert(AssetIds::NativeAssetId(currency_id), metadata);
-
-		Ok(())
-	}
-
 	pub fn convert_to_vtoken_metadata(
 		token_metadata: AssetMetadata<BalanceOf<T>>,
 	) -> AssetMetadata<BalanceOf<T>> {
@@ -519,34 +374,6 @@ impl<T: Config> Pallet<T> {
 		AssetMetadata { name, symbol, ..token_metadata }
 	}
 
-	pub fn convert_to_vstoken_metadata(
-		token_metadata: AssetMetadata<BalanceOf<T>>,
-	) -> AssetMetadata<BalanceOf<T>> {
-		let mut name = "Voucher Slot ".as_bytes().to_vec();
-		name.extend_from_slice(&token_metadata.symbol);
-		let mut symbol = "vs".as_bytes().to_vec();
-		symbol.extend_from_slice(&token_metadata.symbol);
-		AssetMetadata { name, symbol, ..token_metadata }
-	}
-
-	pub fn convert_to_vsbond_metadata(
-		token_metadata: AssetMetadata<BalanceOf<T>>,
-		para_id: ParaId,
-		first_slot: LeasePeriod,
-		last_slot: LeasePeriod,
-	) -> AssetMetadata<BalanceOf<T>> {
-		let name = scale_info::prelude::format!(
-			"vsBOND-{}-{}-{}-{}",
-			core::str::from_utf8(&token_metadata.symbol).unwrap_or(""),
-			para_id,
-			first_slot,
-			last_slot
-		)
-		.as_bytes()
-		.to_vec();
-		AssetMetadata { name: name.clone(), symbol: name, ..token_metadata }
-	}
-
 	pub fn do_register_metadata(
 		currency_id: CurrencyId,
 		metadata: &AssetMetadata<BalanceOf<T>>,
@@ -564,15 +391,15 @@ impl<T: Config> Pallet<T> {
 	}
 
 	pub fn do_register_location(currency_id: CurrencyId, location: &Location) -> DispatchResult {
-		let v3_location =
-			xcm::v3::Location::try_from(location.clone()).map_err(|()| Error::<T>::BadLocation)?;
+		let v4_location =
+			Location::try_from(location.clone()).map_err(|_| Error::<T>::BadLocation)?;
 
 		ensure!(
 			CurrencyMetadatas::<T>::get(currency_id).is_some(),
 			Error::<T>::CurrencyIdNotExists
 		);
 		ensure!(
-			LocationToCurrencyIds::<T>::get(v3_location).is_none(),
+			LocationToCurrencyIds::<T>::get(v4_location.clone()).is_none(),
 			Error::<T>::CurrencyIdExisted
 		);
 		ensure!(
@@ -580,8 +407,8 @@ impl<T: Config> Pallet<T> {
 			Error::<T>::LocationExisted
 		);
 
-		LocationToCurrencyIds::<T>::insert(v3_location, currency_id);
-		CurrencyIdToLocations::<T>::insert(currency_id, v3_location);
+		LocationToCurrencyIds::<T>::insert(v4_location.clone(), currency_id);
+		CurrencyIdToLocations::<T>::insert(currency_id, v4_location);
 
 		Ok(())
 	}
@@ -596,34 +423,6 @@ impl<T: Config> Pallet<T> {
 
 		Ok(())
 	}
-
-	fn do_update_native_asset(
-		currency_id: CurrencyId,
-		location: &Location,
-		metadata: &AssetMetadata<BalanceOf<T>>,
-	) -> DispatchResult {
-		let v3_location =
-			xcm::v3::Location::try_from(location.clone()).map_err(|()| Error::<T>::BadLocation)?;
-
-		ensure!(
-			LocationToCurrencyIds::<T>::get(v3_location).is_some(),
-			Error::<T>::AssetIdNotExists
-		);
-		ensure!(
-			CurrencyIdToLocations::<T>::get(currency_id).is_some(),
-			Error::<T>::LocationExisted
-		);
-		ensure!(
-			AssetMetadatas::<T>::get(AssetIds::NativeAssetId(currency_id)).is_some(),
-			Error::<T>::AssetIdNotExists
-		);
-
-		LocationToCurrencyIds::<T>::insert(v3_location, currency_id);
-		CurrencyIdToLocations::<T>::insert(currency_id, v3_location);
-		AssetMetadatas::<T>::insert(AssetIds::NativeAssetId(currency_id), metadata);
-
-		Ok(())
-	}
 }
 
 pub struct AssetIdMaps<T>(sp_std::marker::PhantomData<T>);
@@ -648,8 +447,8 @@ impl<T: Config> CurrencyIdMapping<CurrencyId, MultiLocation, AssetMetadata<Balan
 	}
 
 	fn get_currency_id(multi_location: Location) -> Option<CurrencyId> {
-		let v3_location = xcm::v3::Location::try_from(multi_location).ok()?;
-		LocationToCurrencyIds::<T>::get(v3_location)
+		let v4_location = Location::try_from(multi_location).ok()?;
+		LocationToCurrencyIds::<T>::get(v4_location)
 	}
 }
 
@@ -752,55 +551,6 @@ impl<T: Config> CurrencyIdRegister<CurrencyId> for AssetIdMaps<T> {
 		}
 	}
 
-	fn register_vstoken_metadata(token_symbol: TokenSymbol) -> sp_runtime::DispatchResult {
-		if let Some(token_metadata) = CurrencyMetadatas::<T>::get(CurrencyId::Token(token_symbol)) {
-			let vstoken_metadata = Pallet::<T>::convert_to_vstoken_metadata(token_metadata);
-			Pallet::<T>::do_register_metadata(
-				CurrencyId::VSToken(token_symbol),
-				&vstoken_metadata,
-			)?;
-
-			return Ok(());
-		} else {
-			return Err(Error::<T>::CurrencyIdNotExists.into());
-		}
-	}
-
-	fn register_vsbond_metadata(
-		token_symbol: TokenSymbol,
-		para_id: ParaId,
-		first_slot: LeasePeriod,
-		last_slot: LeasePeriod,
-	) -> sp_runtime::DispatchResult {
-		let option_token_metadata =
-			if CurrencyMetadatas::<T>::contains_key(CurrencyId::Token(token_symbol)) {
-				CurrencyMetadatas::<T>::get(CurrencyId::Token(token_symbol))
-			} else if token_symbol == TokenSymbol::BNC &&
-				CurrencyMetadatas::<T>::contains_key(CurrencyId::Native(token_symbol))
-			{
-				CurrencyMetadatas::<T>::get(CurrencyId::Native(token_symbol))
-			} else {
-				None
-			};
-
-		if let Some(token_metadata) = option_token_metadata {
-			let vsbond_metadata = Pallet::<T>::convert_to_vsbond_metadata(
-				token_metadata,
-				para_id,
-				first_slot,
-				last_slot,
-			);
-			Pallet::<T>::do_register_metadata(
-				CurrencyId::VSBond(token_symbol, para_id, first_slot, last_slot),
-				&vsbond_metadata,
-			)?;
-
-			return Ok(());
-		} else {
-			return Err(Error::<T>::CurrencyIdNotExists.into());
-		}
-	}
-
 	fn check_token2_registered(token_id: TokenId) -> bool {
 		CurrencyMetadatas::<T>::get(CurrencyId::Token2(token_id)).is_some()
 	}
@@ -809,20 +559,6 @@ impl<T: Config> CurrencyIdRegister<CurrencyId> for AssetIdMaps<T> {
 		CurrencyMetadatas::<T>::get(CurrencyId::VToken2(token_id)).is_some()
 	}
 
-	fn check_vstoken2_registered(token_id: TokenId) -> bool {
-		CurrencyMetadatas::<T>::get(CurrencyId::VSToken2(token_id)).is_some()
-	}
-
-	fn check_vsbond2_registered(
-		token_id: TokenId,
-		para_id: ParaId,
-		first_slot: LeasePeriod,
-		last_slot: LeasePeriod,
-	) -> bool {
-		CurrencyMetadatas::<T>::get(CurrencyId::VSBond2(token_id, para_id, first_slot, last_slot))
-			.is_some()
-	}
-
 	fn register_vtoken2_metadata(token_id: TokenId) -> DispatchResult {
 		if let Some(token_metadata) = CurrencyMetadatas::<T>::get(CurrencyId::Token2(token_id)) {
 			let vtoken_metadata = Pallet::<T>::convert_to_vtoken_metadata(token_metadata);
@@ -834,41 +570,6 @@ impl<T: Config> CurrencyIdRegister<CurrencyId> for AssetIdMaps<T> {
 		}
 	}
 
-	fn register_vstoken2_metadata(token_id: TokenId) -> DispatchResult {
-		if let Some(token_metadata) = CurrencyMetadatas::<T>::get(CurrencyId::Token2(token_id)) {
-			let vstoken_metadata = Pallet::<T>::convert_to_vstoken_metadata(token_metadata);
-			Pallet::<T>::do_register_metadata(CurrencyId::VSToken2(token_id), &vstoken_metadata)?;
-
-			return Ok(());
-		} else {
-			return Err(Error::<T>::CurrencyIdNotExists.into());
-		}
-	}
-
-	fn register_vsbond2_metadata(
-		token_id: TokenId,
-		para_id: ParaId,
-		first_slot: LeasePeriod,
-		last_slot: LeasePeriod,
-	) -> DispatchResult {
-		if let Some(token_metadata) = CurrencyMetadatas::<T>::get(CurrencyId::Token2(token_id)) {
-			let vsbond_metadata = Pallet::<T>::convert_to_vsbond_metadata(
-				token_metadata,
-				para_id,
-				first_slot,
-				last_slot,
-			);
-			Pallet::<T>::do_register_metadata(
-				CurrencyId::VSBond2(token_id, para_id, first_slot, last_slot),
-				&vsbond_metadata,
-			)?;
-
-			return Ok(());
-		} else {
-			return Err(Error::<T>::CurrencyIdNotExists.into());
-		}
-	}
-
 	fn register_blp_metadata(pool_id: PoolId, decimals: u8) -> DispatchResult {
 		let name = scale_info::prelude::format!("Bifrost Stable Pool Token {}", pool_id)
 			.as_bytes()
@@ -931,10 +632,10 @@ where
 		let AssetId(ref location) = asset_id.clone();
 		log::debug!(target: "asset-registry::weight", "buy_weight location: {:?}", location);
 
-		let v3_location =
-			xcm::v3::Location::try_from(location.clone()).map_err(|_| XcmError::InvalidLocation)?;
+		let v4_location =
+			Location::try_from(location.clone()).map_err(|_| XcmError::InvalidLocation)?;
 
-		if let Some(currency_id) = LocationToCurrencyIds::<T>::get(v3_location) {
+		if let Some(currency_id) = LocationToCurrencyIds::<T>::get(v4_location) {
 			if let Some(currency_metadatas) = CurrencyMetadatas::<T>::get(currency_id) {
 				// The integration tests can ensure the ed is non-zero.
 				let ed_ratio = FixedU128::saturating_from_rational(
diff --git a/pallets/asset-registry/src/migrations/mod.rs b/pallets/asset-registry/src/migrations/mod.rs
new file mode 100644
index 000000000..306e9e560
--- /dev/null
+++ b/pallets/asset-registry/src/migrations/mod.rs
@@ -0,0 +1,19 @@
+// 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 <https://www.gnu.org/licenses/>.
+pub mod v0;
+pub mod v1;
diff --git a/pallets/asset-registry/src/migrations/v0.rs b/pallets/asset-registry/src/migrations/v0.rs
new file mode 100644
index 000000000..e194e5eef
--- /dev/null
+++ b/pallets/asset-registry/src/migrations/v0.rs
@@ -0,0 +1,131 @@
+// 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 <https://www.gnu.org/licenses/>.
+
+use crate::*;
+use bifrost_primitives::{CurrencyId, BNC};
+use frame_support::traits::{Get, OnRuntimeUpgrade};
+#[cfg(feature = "try-runtime")]
+use sp_runtime::TryRuntimeError;
+use xcm::opaque::v3::Junctions::X1;
+
+const LOG_TARGET: &str = "asset-registry::migration";
+
+pub fn update_blp_metadata<T: Config>(pool_count: u32) -> Weight {
+	for pool_id in 0..pool_count {
+		if let Some(old_metadata) = CurrencyMetadatas::<T>::get(CurrencyId::BLP(pool_id)) {
+			let name = scale_info::prelude::format!("Bifrost Stable Pool Token {}", pool_id)
+				.as_bytes()
+				.to_vec();
+			let symbol = scale_info::prelude::format!("BLP{}", pool_id).as_bytes().to_vec();
+			CurrencyMetadatas::<T>::insert(
+				CurrencyId::BLP(pool_id),
+				&AssetMetadata { name, symbol, ..old_metadata },
+			)
+		}
+	}
+
+	T::DbWeight::get().reads(pool_count.into()) + T::DbWeight::get().writes(pool_count.into())
+}
+
+const BNC_LOCATION: xcm::v3::Location = xcm::v3::Location {
+	parents: 0,
+	interior: X1(xcm::v3::Junction::GeneralKey {
+		length: 2,
+		data: [
+			0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+			0, 0, 0,
+		],
+	}),
+};
+
+pub struct InsertBNCMetadata<T>(PhantomData<T>);
+impl<T: Config> OnRuntimeUpgrade for InsertBNCMetadata<T> {
+	fn on_runtime_upgrade() -> Weight {
+		log::info!(target: LOG_TARGET, "Start to insert BNC Metadata...");
+		CurrencyMetadatas::<T>::insert(
+			BNC,
+			&AssetMetadata {
+				name: b"Bifrost Native Token".to_vec(),
+				symbol: b"BNC".to_vec(),
+				decimals: 12,
+				minimal_balance: BalanceOf::<T>::unique_saturated_from(10_000_000_000u128),
+			},
+		);
+
+		match Location::try_from(BNC_LOCATION) {
+			Ok(location) => {
+				CurrencyIdToLocations::<T>::insert(BNC, location.clone());
+				LocationToCurrencyIds::<T>::insert(location, BNC);
+
+				Weight::from(T::DbWeight::get().reads_writes(3 as u64 + 1, 3 as u64 + 1))
+			},
+			Err(_) => {
+				log::error!(target: LOG_TARGET, "Conversion failed from BNC_LOCATION to v4_bnc_location.");
+				Weight::from(T::DbWeight::get().reads_writes(1 as u64 + 1, 1 as u64 + 1))
+			},
+		}
+	}
+
+	#[cfg(feature = "try-runtime")]
+	fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
+		let bnc_location = Location::try_from(BNC_LOCATION).unwrap();
+		assert!(LocationToCurrencyIds::<T>::get(bnc_location).is_none());
+
+		Ok(sp_std::vec![])
+	}
+
+	#[cfg(feature = "try-runtime")]
+	fn post_upgrade(_cnt: Vec<u8>) -> Result<(), TryRuntimeError> {
+		let metadata = CurrencyMetadatas::<T>::get(BNC);
+		assert_eq!(
+			metadata,
+			Some(AssetMetadata {
+				name: b"Bifrost Native Token".to_vec(),
+				symbol: b"BNC".to_vec(),
+				decimals: 12,
+				minimal_balance: BalanceOf::<T>::unique_saturated_from(10_000_000_000u128),
+			})
+		);
+		log::info!(
+			target: LOG_TARGET,
+			"InsertBNCMetadata post-migrate storage: {:?}",
+			metadata
+		);
+
+		let bnc_location = Location::try_from(BNC_LOCATION).unwrap();
+
+		let location = CurrencyIdToLocations::<T>::get(BNC);
+		assert_eq!(location, Some(bnc_location.clone()));
+
+		log::info!(
+			target: LOG_TARGET,
+			"InsertBNCMetadata post-migrate storage: {:?}",
+			location
+		);
+
+		let currency = LocationToCurrencyIds::<T>::get(bnc_location);
+		assert_eq!(currency, Some(BNC));
+		log::info!(
+			target: LOG_TARGET,
+			"InsertBNCMetadata post-migrate storage: {:?}",
+			currency
+		);
+
+		Ok(())
+	}
+}
diff --git a/pallets/asset-registry/src/migrations/v1.rs b/pallets/asset-registry/src/migrations/v1.rs
new file mode 100644
index 000000000..99a7481a2
--- /dev/null
+++ b/pallets/asset-registry/src/migrations/v1.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 <https://www.gnu.org/licenses/>.
+
+use crate::*;
+use frame_support::traits::OnRuntimeUpgrade;
+#[cfg(feature = "try-runtime")]
+use sp_runtime::TryRuntimeError;
+
+const LOG_TARGET: &str = "asset-registry::migration";
+
+pub struct MigrateToV1<T>(sp_std::marker::PhantomData<T>);
+impl<T: Config> OnRuntimeUpgrade for MigrateToV1<T> {
+	fn on_runtime_upgrade() -> frame_support::weights::Weight {
+		// Check the storage version
+		let onchain_version = Pallet::<T>::on_chain_storage_version();
+		// Transform storage values
+		// We transform the storage values from the old into the new format.
+		if onchain_version < 1 {
+			let mut count = 0;
+
+			log::info!(target: LOG_TARGET, "Start to migrate RegisterWhiteList storage...");
+			CurrencyIdToLocations::<T>::translate::<xcm::v3::Location, _>(
+				|k: CurrencyId, value: xcm::v3::Location| {
+					log::info!(target: LOG_TARGET, "CurrencyIdToLocations Migrated to xcm::v4::Location for {:?}...", k);
+					let v4_location = xcm::v4::Location::try_from(value).unwrap();
+
+					count += 1;
+					Some(v4_location)
+				},
+			);
+
+			log::info!(target: LOG_TARGET, "Start to migrate LocationToCurrencyIds storage...");
+			let migrated_items: Vec<_> = LocationToCurrencyIds::<T>::drain()
+				.map(|(v3_location, value)| {
+					log::info!(target: LOG_TARGET, "LocationToCurrencyIds Migrated to xcm::v4::Location for {:?}...", value);
+					let v4_location = xcm::v4::Location::try_from(v3_location).unwrap();
+
+					count += 1;
+					(v4_location, value)
+				})
+				.collect();
+			for (v4_location, value) in migrated_items {
+				LocationToCurrencyIds::<T>::insert(v4_location, value);
+			}
+
+			// Update the storage version
+			StorageVersion::new(1).put::<Pallet<T>>();
+
+			// Return the consumed weight
+			Weight::from(T::DbWeight::get().reads_writes(count as u64 + 1, count as u64 + 1))
+		} else {
+			// We don't do anything here.
+			Weight::zero()
+		}
+	}
+
+	#[cfg(feature = "try-runtime")]
+	fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
+		let currency_id_to_locations_count = CurrencyIdToLocations::<T>::iter().count();
+		log::info!(target: LOG_TARGET, "CurrencyIdToLocations pre-migrate storage count: {:?}", currency_id_to_locations_count);
+
+		let location_to_currency_ids_count = LocationToCurrencyIds::<T>::iter().count();
+		log::info!(target: LOG_TARGET, "LocationToCurrencyIds pre-migrate storage count: {:?}", location_to_currency_ids_count);
+
+		let combined_data =
+			(currency_id_to_locations_count as u64, location_to_currency_ids_count as u64);
+
+		Ok(combined_data.encode())
+	}
+
+	#[cfg(feature = "try-runtime")]
+	fn post_upgrade(cnt: Vec<u8>) -> Result<(), TryRuntimeError> {
+		let (old_currency_id_to_locations_count, old_location_to_currency_ids_count): (u64, u64) =
+			Decode::decode(&mut cnt.as_slice()).expect(
+				"the state parameter should be something that was generated by pre_upgrade",
+			);
+
+		let new_currency_id_to_locations_count = CurrencyIdToLocations::<T>::iter().count();
+		log::info!(
+			target: LOG_TARGET,
+			"CurrencyIdToLocations post-migrate storage count: {:?}",
+			new_currency_id_to_locations_count
+		);
+
+		let new_location_to_currency_ids_count = LocationToCurrencyIds::<T>::iter().count();
+		log::info!(
+			target: LOG_TARGET,
+			"LocationToCurrencyIds post-migrate storage count: {:?}",
+			new_location_to_currency_ids_count
+		);
+
+		ensure!(
+			new_currency_id_to_locations_count as u64 == old_currency_id_to_locations_count,
+			"Post-migration CurrencyIdToLocations count does not match pre-migration count"
+		);
+		ensure!(
+			new_location_to_currency_ids_count as u64 == old_location_to_currency_ids_count,
+			"Post-migration LocationToCurrencyIds count does not match pre-migration count"
+		);
+
+		Ok(())
+	}
+}
diff --git a/pallets/asset-registry/src/tests.rs b/pallets/asset-registry/src/tests.rs
index 470a22438..f16a42416 100644
--- a/pallets/asset-registry/src/tests.rs
+++ b/pallets/asset-registry/src/tests.rs
@@ -21,7 +21,6 @@
 #![cfg(test)]
 
 use super::*;
-use bifrost_primitives::TokenSymbol;
 use frame_support::{assert_noop, assert_ok};
 use mock::{
 	AssetRegistry, CouncilAccount, ExtBuilder, Runtime, RuntimeEvent, RuntimeOrigin, System,
@@ -36,125 +35,6 @@ fn versioned_multi_location_convert_work() {
 	});
 }
 
-#[test]
-fn register_native_asset_works() {
-	ExtBuilder::default().build().execute_with(|| {
-		let versioned_location = VersionedLocation::V4(Location::from([Parachain(1000)]));
-
-		assert_ok!(AssetRegistry::register_native_asset(
-			RuntimeOrigin::signed(CouncilAccount::get()),
-			Token(TokenSymbol::DOT),
-			Box::new(versioned_location.clone()),
-			Box::new(AssetMetadata {
-				name: b"Token Name".to_vec(),
-				symbol: b"TN".to_vec(),
-				decimals: 12,
-				minimal_balance: 1,
-			})
-		));
-		System::assert_last_event(RuntimeEvent::AssetRegistry(Event::AssetRegistered {
-			asset_id: AssetIds::NativeAssetId(Token(TokenSymbol::DOT)),
-			metadata: AssetMetadata {
-				name: b"Token Name".to_vec(),
-				symbol: b"TN".to_vec(),
-				decimals: 12,
-				minimal_balance: 1,
-			},
-		}));
-
-		assert_eq!(
-			AssetMetadatas::<Runtime>::get(AssetIds::NativeAssetId(Token(TokenSymbol::DOT))),
-			Some(AssetMetadata {
-				name: b"Token Name".to_vec(),
-				symbol: b"TN".to_vec(),
-				decimals: 12,
-				minimal_balance: 1,
-			})
-		);
-		// Can't duplicate
-		assert_noop!(
-			AssetRegistry::register_native_asset(
-				RuntimeOrigin::signed(CouncilAccount::get()),
-				Token(TokenSymbol::DOT),
-				Box::new(versioned_location),
-				Box::new(AssetMetadata {
-					name: b"Token Name".to_vec(),
-					symbol: b"TN".to_vec(),
-					decimals: 12,
-					minimal_balance: 1,
-				})
-			),
-			Error::<Runtime>::AssetIdExisted
-		);
-	});
-}
-
-#[test]
-fn update_native_asset_works() {
-	let versioned_location = VersionedLocation::V4(Location::from([Parachain(1000)]));
-
-	ExtBuilder::default().build().execute_with(|| {
-		assert_noop!(
-			AssetRegistry::update_native_asset(
-				RuntimeOrigin::signed(CouncilAccount::get()),
-				Token(TokenSymbol::DOT),
-				Box::new(versioned_location.clone()),
-				Box::new(AssetMetadata {
-					name: b"New Token Name".to_vec(),
-					symbol: b"NTN".to_vec(),
-					decimals: 13,
-					minimal_balance: 2,
-				})
-			),
-			Error::<Runtime>::AssetIdNotExists
-		);
-
-		assert_ok!(AssetRegistry::register_native_asset(
-			RuntimeOrigin::signed(CouncilAccount::get()),
-			Token(TokenSymbol::DOT),
-			Box::new(versioned_location.clone()),
-			Box::new(AssetMetadata {
-				name: b"Token Name".to_vec(),
-				symbol: b"TN".to_vec(),
-				decimals: 12,
-				minimal_balance: 1,
-			})
-		));
-
-		assert_ok!(AssetRegistry::update_native_asset(
-			RuntimeOrigin::signed(CouncilAccount::get()),
-			Token(TokenSymbol::DOT),
-			Box::new(versioned_location.clone()),
-			Box::new(AssetMetadata {
-				name: b"New Token Name".to_vec(),
-				symbol: b"NTN".to_vec(),
-				decimals: 13,
-				minimal_balance: 2,
-			})
-		));
-
-		System::assert_last_event(RuntimeEvent::AssetRegistry(Event::AssetUpdated {
-			asset_id: AssetIds::NativeAssetId(Token(TokenSymbol::DOT)),
-			metadata: AssetMetadata {
-				name: b"New Token Name".to_vec(),
-				symbol: b"NTN".to_vec(),
-				decimals: 13,
-				minimal_balance: 2,
-			},
-		}));
-
-		assert_eq!(
-			AssetMetadatas::<Runtime>::get(AssetIds::NativeAssetId(Token(TokenSymbol::DOT))),
-			Some(AssetMetadata {
-				name: b"New Token Name".to_vec(),
-				symbol: b"NTN".to_vec(),
-				decimals: 13,
-				minimal_balance: 2,
-			})
-		);
-	});
-}
-
 #[test]
 fn register_token_metadata_should_work() {
 	ExtBuilder::default().build().execute_with(|| {
@@ -214,86 +94,6 @@ fn register_vtoken_metadata_should_work() {
 	})
 }
 
-#[test]
-fn register_vstoken_metadata_should_work() {
-	ExtBuilder::default().build().execute_with(|| {
-		let metadata = AssetMetadata {
-			name: b"KSM Native Token".to_vec(),
-			symbol: b"KSM".to_vec(),
-			decimals: 12,
-			minimal_balance: 0,
-		};
-		let v_metadata = AssetMetadata {
-			name: b"Voucher Slot KSM".to_vec(),
-			symbol: b"vsKSM".to_vec(),
-			decimals: 12,
-			minimal_balance: 0,
-		};
-		assert_noop!(
-			AssetRegistry::register_vtoken_metadata(
-				RuntimeOrigin::signed(CouncilAccount::get()),
-				1
-			),
-			Error::<Runtime>::CurrencyIdNotExists
-		);
-
-		assert_ok!(AssetRegistry::register_token_metadata(
-			RuntimeOrigin::signed(CouncilAccount::get()),
-			Box::new(metadata.clone())
-		));
-
-		assert_ok!(AssetRegistry::register_vstoken_metadata(
-			RuntimeOrigin::signed(CouncilAccount::get()),
-			0
-		));
-
-		assert_eq!(
-			CurrencyMetadatas::<Runtime>::get(CurrencyId::VSToken2(0)),
-			Some(v_metadata.clone())
-		)
-	})
-}
-
-#[test]
-fn register_vsbond_metadata_should_work() {
-	ExtBuilder::default().build().execute_with(|| {
-		let metadata = AssetMetadata {
-			name: b"KSM Native Token".to_vec(),
-			symbol: b"KSM".to_vec(),
-			decimals: 12,
-			minimal_balance: 0,
-		};
-		let name = "vsBOND-KSM-2001-10-20".as_bytes().to_vec();
-		let v_metadata =
-			AssetMetadata { name: name.clone(), symbol: name, decimals: 12, minimal_balance: 0 };
-		assert_noop!(
-			AssetRegistry::register_vtoken_metadata(
-				RuntimeOrigin::signed(CouncilAccount::get()),
-				1
-			),
-			Error::<Runtime>::CurrencyIdNotExists
-		);
-
-		assert_ok!(AssetRegistry::register_token_metadata(
-			RuntimeOrigin::signed(CouncilAccount::get()),
-			Box::new(metadata.clone())
-		));
-
-		assert_ok!(AssetRegistry::register_vsbond_metadata(
-			RuntimeOrigin::signed(CouncilAccount::get()),
-			0,
-			2001,
-			10,
-			20
-		));
-
-		assert_eq!(
-			CurrencyMetadatas::<Runtime>::get(CurrencyId::VSBond2(0, 2001, 10, 20)),
-			Some(v_metadata.clone())
-		)
-	})
-}
-
 #[test]
 fn register_multilocation_should_work() {
 	ExtBuilder::default().build().execute_with(|| {
@@ -305,7 +105,7 @@ fn register_multilocation_should_work() {
 		};
 
 		let versioned_location = VersionedLocation::V4(Location::new(1, [Parachain(2001)]));
-		let location: xcm::v3::Location = versioned_location.clone().try_into().unwrap();
+		let location: Location = versioned_location.clone().try_into().unwrap();
 
 		assert_noop!(
 			AssetRegistry::register_location(
@@ -339,7 +139,7 @@ fn register_multilocation_should_work() {
 			Error::<Runtime>::CurrencyIdExisted
 		);
 
-		assert_eq!(LocationToCurrencyIds::<Runtime>::get(location), Some(Token2(0)));
+		assert_eq!(LocationToCurrencyIds::<Runtime>::get(location.clone()), Some(Token2(0)));
 		assert_eq!(CurrencyIdToLocations::<Runtime>::get(Token2(0)), Some(location));
 		assert_eq!(
 			CurrencyIdToWeights::<Runtime>::get(Token2(0)),
@@ -358,7 +158,7 @@ fn force_set_multilocation_should_work() {
 			minimal_balance: 0,
 		};
 		let versioned_location = VersionedLocation::V4(Location::new(1, [Parachain(2001)]));
-		let location: xcm::v3::Location = versioned_location.clone().try_into().unwrap();
+		let location: Location = versioned_location.clone().try_into().unwrap();
 
 		assert_noop!(
 			AssetRegistry::force_set_location(
@@ -389,7 +189,7 @@ fn force_set_multilocation_should_work() {
 			Weight::from_parts(2000_000_000, 0)
 		));
 
-		assert_eq!(LocationToCurrencyIds::<Runtime>::get(location), Some(Token2(0)));
+		assert_eq!(LocationToCurrencyIds::<Runtime>::get(location.clone()), Some(Token2(0)));
 		assert_eq!(CurrencyIdToLocations::<Runtime>::get(Token2(0)), Some(location));
 		assert_eq!(
 			CurrencyIdToWeights::<Runtime>::get(Token2(0)),
diff --git a/pallets/asset-registry/src/weights.rs b/pallets/asset-registry/src/weights.rs
index 162c6fad6..b16619e2e 100644
--- a/pallets/asset-registry/src/weights.rs
+++ b/pallets/asset-registry/src/weights.rs
@@ -53,12 +53,8 @@ use sp_std::marker::PhantomData;
 
 /// Weight functions needed for bifrost_asset_registry.
 pub trait WeightInfo {
-	fn register_native_asset() -> Weight;
-	fn update_native_asset() -> Weight;
 	fn register_token_metadata() -> Weight;
 	fn register_vtoken_metadata() -> Weight;
-	fn register_vstoken_metadata() -> Weight;
-	fn register_vsbond_metadata() -> Weight;
 	fn register_location() -> Weight;
 	fn force_set_location() -> Weight;
 	fn update_currency_metadata() -> Weight;
@@ -66,36 +62,6 @@ pub trait WeightInfo {
 
 // For backwards compatibility and tests
 impl WeightInfo for () {
-	/// Storage: AssetRegistry LocationToCurrencyIds (r:1 w:1)
-	/// Proof Skipped: AssetRegistry LocationToCurrencyIds (max_values: None, max_size: None, mode: Measured)
-	/// Storage: AssetRegistry CurrencyIdToLocations (r:1 w:1)
-	/// Proof Skipped: AssetRegistry CurrencyIdToLocations (max_values: None, max_size: None, mode: Measured)
-	/// Storage: AssetRegistry AssetMetadatas (r:1 w:1)
-	/// Proof Skipped: AssetRegistry AssetMetadatas (max_values: None, max_size: None, mode: Measured)
-	fn register_native_asset() -> Weight {
-		// Proof Size summary in bytes:
-		//  Measured:  `118`
-		//  Estimated: `3583`
-		// Minimum execution time: 52_056_000 picoseconds.
-		Weight::from_parts(53_012_000, 3583)
-			.saturating_add(RocksDbWeight::get().reads(3_u64))
-			.saturating_add(RocksDbWeight::get().writes(3_u64))
-	}
-	/// Storage: AssetRegistry LocationToCurrencyIds (r:1 w:1)
-	/// Proof Skipped: AssetRegistry LocationToCurrencyIds (max_values: None, max_size: None, mode: Measured)
-	/// Storage: AssetRegistry CurrencyIdToLocations (r:1 w:1)
-	/// Proof Skipped: AssetRegistry CurrencyIdToLocations (max_values: None, max_size: None, mode: Measured)
-	/// Storage: AssetRegistry AssetMetadatas (r:1 w:1)
-	/// Proof Skipped: AssetRegistry AssetMetadatas (max_values: None, max_size: None, mode: Measured)
-	fn update_native_asset() -> Weight {
-		// Proof Size summary in bytes:
-		//  Measured:  `250`
-		//  Estimated: `3715`
-		// Minimum execution time: 59_891_000 picoseconds.
-		Weight::from_parts(60_869_000, 3715)
-			.saturating_add(RocksDbWeight::get().reads(3_u64))
-			.saturating_add(RocksDbWeight::get().writes(3_u64))
-	}
 	/// Storage: AssetRegistry NextTokenId (r:1 w:1)
 	/// Proof Skipped: AssetRegistry NextTokenId (max_values: Some(1), max_size: None, mode: Measured)
 	/// Storage: AssetRegistry CurrencyMetadatas (r:1 w:1)
@@ -120,28 +86,6 @@ impl WeightInfo for () {
 			.saturating_add(RocksDbWeight::get().reads(2_u64))
 			.saturating_add(RocksDbWeight::get().writes(1_u64))
 	}
-	/// Storage: AssetRegistry CurrencyMetadatas (r:2 w:1)
-	/// Proof Skipped: AssetRegistry CurrencyMetadatas (max_values: None, max_size: None, mode: Measured)
-	fn register_vstoken_metadata() -> Weight {
-		// Proof Size summary in bytes:
-		//  Measured:  `705`
-		//  Estimated: `6645`
-		// Minimum execution time: 52_491_000 picoseconds.
-		Weight::from_parts(53_682_000, 6645)
-			.saturating_add(RocksDbWeight::get().reads(2_u64))
-			.saturating_add(RocksDbWeight::get().writes(1_u64))
-	}
-	/// Storage: AssetRegistry CurrencyMetadatas (r:2 w:1)
-	/// Proof Skipped: AssetRegistry CurrencyMetadatas (max_values: None, max_size: None, mode: Measured)
-	fn register_vsbond_metadata() -> Weight {
-		// Proof Size summary in bytes:
-		//  Measured:  `763`
-		//  Estimated: `6703`
-		// Minimum execution time: 55_589_000 picoseconds.
-		Weight::from_parts(56_804_000, 6703)
-			.saturating_add(RocksDbWeight::get().reads(2_u64))
-			.saturating_add(RocksDbWeight::get().writes(1_u64))
-	}
 	/// Storage: AssetRegistry CurrencyMetadatas (r:1 w:0)
 	/// Proof Skipped: AssetRegistry CurrencyMetadatas (max_values: None, max_size: None, mode: Measured)
 	/// Storage: AssetRegistry LocationToCurrencyIds (r:1 w:1)
diff --git a/pallets/deprecated/asset-registry/Cargo.toml b/pallets/deprecated/asset-registry/Cargo.toml
new file mode 100644
index 000000000..c6e22cd68
--- /dev/null
+++ b/pallets/deprecated/asset-registry/Cargo.toml
@@ -0,0 +1,51 @@
+[package]
+name = "bifrost-asset-registry"
+version = "0.8.0"
+authors = ["Edwin Wang <lark930@gmail.com>"]
+edition = "2021"
+
+[dependencies]
+log = { workspace = true }
+serde = { workspace = true }
+scale-info = { workspace = true, features = ["derive"] }
+parity-scale-codec = { workspace = true, features = ["derive"] }
+sp-runtime = { workspace = true }
+sp-std = { workspace = true }
+frame-support = { workspace = true }
+frame-system = { workspace = true }
+frame-benchmarking = { workspace = true, optional = true }
+bifrost-primitives = { workspace = true }
+
+xcm = { workspace = true }
+xcm-builder = { workspace = true }
+xcm-executor = { workspace = true }
+
+[dev-dependencies]
+sp-io = { workspace = true }
+pallet-balances = { workspace = true }
+
+[features]
+default = ["std"]
+std = [
+	"serde/std",
+	"log/std",
+	"parity-scale-codec/std",
+	"scale-info/std",
+	"sp-runtime/std",
+	"sp-std/std",
+	"frame-support/std",
+	"frame-system/std",
+	"frame-benchmarking?/std",
+	"bifrost-primitives/std",
+	"xcm/std",
+	"xcm-builder/std",
+	"xcm-executor/std",
+]
+try-runtime = ["frame-support/try-runtime"]
+
+runtime-benchmarks = [
+	"frame-benchmarking",
+	"frame-support/runtime-benchmarks",
+	"frame-system/runtime-benchmarks",
+	"xcm-builder/runtime-benchmarks",
+]
diff --git a/pallets/deprecated/asset-registry/src/benchmarking.rs b/pallets/deprecated/asset-registry/src/benchmarking.rs
new file mode 100644
index 000000000..bb7b63b13
--- /dev/null
+++ b/pallets/deprecated/asset-registry/src/benchmarking.rs
@@ -0,0 +1,309 @@
+// 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 <https://www.gnu.org/licenses/>.
+
+#![cfg(feature = "runtime-benchmarks")]
+
+use super::*;
+use crate::Pallet as AssetRegistry;
+use bifrost_primitives::{CurrencyId, TokenSymbol};
+use frame_benchmarking::{benchmarks, v1::BenchmarkError};
+use frame_support::{assert_ok, traits::UnfilteredDispatchable};
+use sp_runtime::traits::UniqueSaturatedFrom;
+
+benchmarks! {
+	register_native_asset {
+		let origin = T::RegisterOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
+		let versioned_location = VersionedLocation::V4(Location::from([Parachain(1000)]));
+
+	let call = Call::<T>::register_native_asset {
+			currency_id: Token(TokenSymbol::DOT),
+			location: Box::new(versioned_location.clone()),
+			metadata: Box::new(AssetMetadata {
+				name: b"Token Name".to_vec(),
+				symbol: b"TN".to_vec(),
+				decimals: 12,
+				minimal_balance: BalanceOf::<T>::unique_saturated_from(1u128),
+			})
+		};
+	}: {call.dispatch_bypass_filter(origin)?}
+	verify {
+		assert_eq!(
+			AssetMetadatas::<T>::get(AssetIds::NativeAssetId(Token(
+				TokenSymbol::DOT
+			))),
+			Some(AssetMetadata {
+				name: b"Token Name".to_vec(),
+				symbol: b"TN".to_vec(),
+				decimals: 12,
+				minimal_balance: BalanceOf::<T>::unique_saturated_from(1u128),
+			})
+		);
+	}
+
+	update_native_asset {
+		let origin = T::RegisterOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
+		let versioned_location = VersionedLocation::V4(Location::from([Parachain(1000)]));
+
+		assert_ok!(AssetRegistry::<T>::register_native_asset(
+			origin.clone(),
+			Token(TokenSymbol::DOT),
+			Box::new(versioned_location.clone()),
+			Box::new(AssetMetadata {
+				name: b"Token Name".to_vec(),
+				symbol: b"TN".to_vec(),
+				decimals: 12,
+				minimal_balance: BalanceOf::<T>::unique_saturated_from(1u128),
+			})
+		));
+
+	let call = Call::<T>::update_native_asset {
+			currency_id: Token(TokenSymbol::DOT),
+			location: Box::new(versioned_location.clone()),
+			metadata: Box::new(AssetMetadata {
+				name: b"Token Name".to_vec(),
+				symbol: b"TN".to_vec(),
+				decimals: 13,
+				minimal_balance: BalanceOf::<T>::unique_saturated_from(2u128),
+			})
+		};
+	}: {call.dispatch_bypass_filter(origin)?}
+	verify {
+		assert_eq!(
+			AssetMetadatas::<T>::get(AssetIds::NativeAssetId(Token(
+				TokenSymbol::DOT
+			))),
+			Some(AssetMetadata {
+				name: b"Token Name".to_vec(),
+				symbol: b"TN".to_vec(),
+				decimals: 13,
+				minimal_balance: BalanceOf::<T>::unique_saturated_from(2u128),
+			})
+		);
+	}
+
+	register_token_metadata {
+		let origin = T::RegisterOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
+		let metadata = AssetMetadata {
+			name: b"Bifrost Native Coin".to_vec(),
+			symbol: b"BNC".to_vec(),
+			decimals: 12,
+			minimal_balance: BalanceOf::<T>::unique_saturated_from(0u128),
+		};
+
+		let call = Call::<T>::register_token_metadata {
+			metadata: Box::new(metadata.clone())
+		};
+	}: {call.dispatch_bypass_filter(origin)?}
+	verify {
+		assert_eq!(CurrencyMetadatas::<T>::get(Token2(0)), Some(metadata.clone()))
+	}
+
+	register_vtoken_metadata {
+		let origin = T::RegisterOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
+		let metadata = AssetMetadata {
+			name: b"Bifrost Native Coin".to_vec(),
+			symbol: b"BNC".to_vec(),
+			decimals: 12,
+			minimal_balance: BalanceOf::<T>::unique_saturated_from(0u128),
+		};
+		let v_metadata = AssetMetadata {
+			name: b"Voucher BNC".to_vec(),
+			symbol: b"vBNC".to_vec(),
+			decimals: 12,
+			minimal_balance: BalanceOf::<T>::unique_saturated_from(0u128),
+		};
+		assert_ok!(AssetRegistry::<T>::register_token_metadata(
+			origin.clone(),
+			Box::new(metadata.clone())
+		));
+
+		let call = Call::<T>::register_vtoken_metadata {
+			token_id: 0
+		};
+	}: {call.dispatch_bypass_filter(origin)?}
+	verify {
+		assert_eq!(
+			CurrencyMetadatas::<T>::get(CurrencyId::VToken2(0)),
+			Some(v_metadata.clone())
+		)
+	}
+
+	register_vstoken_metadata {
+		let origin = T::RegisterOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
+		let metadata = AssetMetadata {
+			name: b"KSM Native Token".to_vec(),
+			symbol: b"KSM".to_vec(),
+			decimals: 12,
+			minimal_balance: BalanceOf::<T>::unique_saturated_from(0u128),
+		};
+		let v_metadata = AssetMetadata {
+			name: b"Voucher Slot KSM".to_vec(),
+			symbol: b"vsKSM".to_vec(),
+			decimals: 12,
+			minimal_balance: BalanceOf::<T>::unique_saturated_from(0u128),
+		};
+		assert_ok!(AssetRegistry::<T>::register_token_metadata(
+			origin.clone(),
+			Box::new(metadata.clone())
+		));
+
+		let call = Call::<T>::register_vstoken_metadata {
+			token_id: 0
+		};
+	}: {call.dispatch_bypass_filter(origin)?}
+	verify {
+		assert_eq!(
+			CurrencyMetadatas::<T>::get(CurrencyId::VSToken2(0)),
+			Some(v_metadata.clone())
+		)
+	}
+
+	register_vsbond_metadata {
+		let origin = T::RegisterOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
+				let metadata = AssetMetadata {
+			name: b"KSM Native Token".to_vec(),
+			symbol: b"KSM".to_vec(),
+			decimals: 12,
+			minimal_balance: BalanceOf::<T>::unique_saturated_from(0u128),
+		};
+		let name = "vsBOND-KSM-2001-10-20".as_bytes().to_vec();
+		let v_metadata = AssetMetadata {
+			name: name.clone(),
+			symbol: name,
+			decimals: 12,
+			minimal_balance: BalanceOf::<T>::unique_saturated_from(0u128),
+		};
+		assert_ok!(AssetRegistry::<T>::register_token_metadata(
+			origin.clone(),
+			Box::new(metadata.clone())
+		));
+
+		let call = Call::<T>::register_vsbond_metadata {
+			token_id: 0,
+			para_id:2001,
+			first_slot:10,
+			last_slot:20
+		};
+	}: {call.dispatch_bypass_filter(origin)?}
+	verify {
+		assert_eq!(
+			CurrencyMetadatas::<T>::get(CurrencyId::VSBond2(0, 2001, 10, 20)),
+			Some(v_metadata.clone())
+		)
+	}
+
+	register_location {
+		let origin = T::RegisterOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
+		let metadata = AssetMetadata {
+			name: b"Bifrost Native Coin".to_vec(),
+			symbol: b"BNC".to_vec(),
+			decimals: 12,
+			minimal_balance: BalanceOf::<T>::unique_saturated_from(0u128),
+		};
+	let versioned_location = VersionedLocation::V4(Location::new(1, [Parachain(2001)]));
+
+		let location: xcm::v3::Location = versioned_location.clone().try_into().unwrap();
+
+		assert_ok!(AssetRegistry::<T>::register_token_metadata(
+			origin.clone(),
+			Box::new(metadata.clone())
+		));
+
+		let call = Call::<T>::register_location {
+			currency_id: Token2(0),
+			location:Box::new(versioned_location.clone()),
+			weight:Weight::from_parts(2000_000_000, u64::MAX),
+		};
+	}: {call.dispatch_bypass_filter(origin)?}
+	verify {
+		assert_eq!(
+			LocationToCurrencyIds::<T>::get(location),
+			Some(Token2(0))
+		);
+		assert_eq!(
+			CurrencyIdToLocations::<T>::get(Token2(0)),
+			Some(location)
+		);
+		assert_eq!(CurrencyIdToWeights::<T>::get(Token2(0)), Some(Weight::from_parts(2000_000_000, u64::MAX)));
+	}
+
+	force_set_location {
+		let origin = T::RegisterOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
+		let metadata = AssetMetadata {
+			name: b"Bifrost Native Coin".to_vec(),
+			symbol: b"BNC".to_vec(),
+			decimals: 12,
+			minimal_balance: BalanceOf::<T>::unique_saturated_from(0u128),
+		};
+		let versioned_location = VersionedLocation::V4(Location::new(1, [Parachain(2001)]));
+
+		let location: xcm::v3::Location = versioned_location.clone().try_into().unwrap();
+
+		assert_ok!(AssetRegistry::<T>::register_token_metadata(
+			origin.clone(),
+			Box::new(metadata.clone())
+		));
+
+		let call = Call::<T>::force_set_location {
+			currency_id: Token2(0),
+			location:Box::new(versioned_location.clone()),
+			weight:Weight::from_parts(2000_000_000, u64::MAX),
+		};
+	}: {call.dispatch_bypass_filter(origin)?}
+
+	update_currency_metadata {
+		let origin = T::RegisterOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
+
+		assert_ok!(AssetRegistry::<T>::register_token_metadata(
+			origin.clone(),
+			Box::new(AssetMetadata {
+				name: b"Old Token Name".to_vec(),
+				symbol: b"OTN".to_vec(),
+				decimals: 10,
+				minimal_balance: BalanceOf::<T>::unique_saturated_from(1u128),
+			})
+		));
+
+		let call = Call::<T>::update_currency_metadata {
+			currency_id: CurrencyId::Token2(0),
+			asset_name: Some(b"Token Name".to_vec()),
+			asset_symbol: Some(b"TN".to_vec()),
+			asset_decimals : Some(12),
+			asset_minimal_balance : Some(BalanceOf::<T>::unique_saturated_from(1000u128)),
+		};
+
+	}: {call.dispatch_bypass_filter(origin)?}
+	verify {
+		assert_eq!(
+			CurrencyMetadatas::<T>::get(CurrencyId::Token2(0)),
+			Some(AssetMetadata {
+				name: b"Token Name".to_vec(),
+				symbol: b"TN".to_vec(),
+				decimals: 12,
+				minimal_balance: BalanceOf::<T>::unique_saturated_from(1000u128),
+			})
+		);
+	}
+
+	impl_benchmark_test_suite!(
+	AssetRegistry,
+	crate::mock::ExtBuilder::default().build(),
+	crate::mock::Runtime
+);
+
+}
diff --git a/pallets/deprecated/asset-registry/src/lib.rs b/pallets/deprecated/asset-registry/src/lib.rs
new file mode 100644
index 000000000..c35d14481
--- /dev/null
+++ b/pallets/deprecated/asset-registry/src/lib.rs
@@ -0,0 +1,1013 @@
+// 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 <https://www.gnu.org/licenses/>.
+
+//! # Asset Registry Module
+//!
+//! Local and foreign assets management. The foreign assets can be updated without runtime upgrade.
+
+#![cfg_attr(not(feature = "std"), no_std)]
+
+pub use bifrost_primitives::{
+	AssetIds, CurrencyId,
+	CurrencyId::{Native, Token, Token2},
+	CurrencyIdConversion, CurrencyIdMapping, CurrencyIdRegister, ForeignAssetId, LeasePeriod,
+	ParaId, PoolId, TokenId, TokenInfo, TokenSymbol,
+};
+use frame_support::{
+	dispatch::DispatchResult,
+	ensure,
+	pallet_prelude::*,
+	traits::{Currency, EnsureOrigin},
+	weights::{constants::WEIGHT_REF_TIME_PER_SECOND, Weight},
+};
+use frame_system::pallet_prelude::*;
+use scale_info::{prelude::string::String, TypeInfo};
+use sp_runtime::{
+	traits::{One, UniqueSaturatedFrom},
+	ArithmeticError, FixedPointNumber, FixedU128, RuntimeDebug,
+};
+use sp_std::{boxed::Box, vec::Vec};
+use xcm::{
+	opaque::lts::XcmContext,
+	v3::MultiLocation,
+	v4::{prelude::*, Asset, Location},
+	VersionedLocation,
+};
+use xcm_builder::TakeRevenue;
+use xcm_executor::{traits::WeightTrader, AssetsInHolding};
+
+pub mod migration;
+mod mock;
+mod tests;
+pub mod weights;
+
+#[cfg(feature = "runtime-benchmarks")]
+mod benchmarking;
+
+pub use pallet::*;
+pub use weights::WeightInfo;
+
+/// Type alias for currency balance.
+pub type BalanceOf<T> =
+	<<T as Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance;
+
+#[frame_support::pallet]
+pub mod pallet {
+	use super::*;
+
+	#[pallet::config]
+	pub trait Config: frame_system::Config {
+		/// The overarching event type.
+		type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
+
+		/// Currency type for withdraw and balance storage.
+		type Currency: Currency<Self::AccountId>;
+
+		/// Required origin for registering asset.
+		type RegisterOrigin: EnsureOrigin<Self::RuntimeOrigin>;
+
+		/// Weight information for the extrinsics in this module.
+		type WeightInfo: WeightInfo;
+	}
+
+	#[derive(Clone, Eq, PartialEq, RuntimeDebug, Encode, Decode, TypeInfo)]
+	pub struct AssetMetadata<Balance> {
+		pub name: Vec<u8>,
+		pub symbol: Vec<u8>,
+		pub decimals: u8,
+		pub minimal_balance: Balance,
+	}
+
+	#[pallet::error]
+	pub enum Error<T> {
+		/// The given location could not be used (e.g. because it cannot be expressed in the
+		/// desired version of XCM).
+		BadLocation,
+		/// Location existed
+		LocationExisted,
+		/// AssetId not exists
+		AssetIdNotExists,
+		/// AssetId exists
+		AssetIdExisted,
+		/// CurrencyId not exists
+		CurrencyIdNotExists,
+		/// CurrencyId exists
+		CurrencyIdExisted,
+	}
+
+	#[pallet::event]
+	#[pallet::generate_deposit(pub(super) fn deposit_event)]
+	pub enum Event<T: Config> {
+		/// The asset registered.
+		AssetRegistered { asset_id: AssetIds, metadata: AssetMetadata<BalanceOf<T>> },
+		/// The asset updated.
+		AssetUpdated { asset_id: AssetIds, metadata: AssetMetadata<BalanceOf<T>> },
+		/// The CurrencyId registered.
+		CurrencyIdRegistered { currency_id: CurrencyId, metadata: AssetMetadata<BalanceOf<T>> },
+		/// Location Force set.
+		LocationSet { currency_id: CurrencyId, location: Location, weight: Weight },
+		/// The CurrencyId updated.
+		CurrencyIdUpdated { currency_id: CurrencyId, metadata: AssetMetadata<BalanceOf<T>> },
+	}
+
+	/// Next available Foreign AssetId ID.
+	///
+	/// NextForeignAssetId: ForeignAssetId
+	#[pallet::storage]
+	pub type NextForeignAssetId<T: Config> = StorageValue<_, ForeignAssetId, ValueQuery>;
+
+	/// Next available TokenId ID.
+	///
+	/// NextTokenId: TokenId
+	#[pallet::storage]
+	pub type NextTokenId<T: Config> = StorageValue<_, TokenId, ValueQuery>;
+
+	/// The storages for Locations.
+	///
+	/// CurrencyIdToLocations: map CurrencyId => Option<Location>
+	#[pallet::storage]
+	pub type CurrencyIdToLocations<T: Config> =
+		StorageMap<_, Twox64Concat, CurrencyId, xcm::v3::Location, OptionQuery>;
+
+	/// The storages for CurrencyIds.
+	///
+	/// LocationToCurrencyIds: map Location => Option<CurrencyId>
+	#[pallet::storage]
+	pub type LocationToCurrencyIds<T: Config> =
+		StorageMap<_, Twox64Concat, xcm::v3::Location, CurrencyId, OptionQuery>;
+
+	#[pallet::storage]
+	pub type CurrencyIdToWeights<T: Config> =
+		StorageMap<_, Twox64Concat, CurrencyId, Weight, OptionQuery>;
+
+	/// The storages for AssetMetadatas.
+	///
+	/// AssetMetadatas: map AssetIds => Option<AssetMetadata>
+	#[pallet::storage]
+	pub type AssetMetadatas<T: Config> =
+		StorageMap<_, Twox64Concat, AssetIds, AssetMetadata<BalanceOf<T>>, OptionQuery>;
+
+	/// The storages for AssetMetadata.
+	///
+	/// CurrencyMetadatas: map CurrencyId => Option<AssetMetadata>
+	#[pallet::storage]
+	pub type CurrencyMetadatas<T: Config> =
+		StorageMap<_, Twox64Concat, CurrencyId, AssetMetadata<BalanceOf<T>>, OptionQuery>;
+
+	#[pallet::genesis_config]
+	#[derive(frame_support::DefaultNoBound)]
+	pub struct GenesisConfig<T: Config> {
+		pub currency: Vec<(CurrencyId, BalanceOf<T>, Option<(String, String, u8)>)>,
+		pub vcurrency: Vec<CurrencyId>,
+		pub vsbond: Vec<(CurrencyId, u32, u32, u32)>,
+		pub phantom: PhantomData<T>,
+	}
+
+	#[pallet::genesis_build]
+	impl<T: Config> BuildGenesisConfig for GenesisConfig<T> {
+		fn build(&self) {
+			for (currency_id, metadata) in
+				self.currency.iter().map(|(currency_id, minimal_balance, metadata)| {
+					(
+						currency_id,
+						match &metadata {
+							None => AssetMetadata {
+								name: currency_id
+									.name()
+									.map(|s| s.as_bytes().to_vec())
+									.unwrap_or_default(),
+								symbol: currency_id
+									.symbol()
+									.map(|s| s.as_bytes().to_vec())
+									.unwrap_or_default(),
+								decimals: currency_id.decimals().unwrap_or_default(),
+								minimal_balance: *minimal_balance,
+							},
+							Some(metadata) => AssetMetadata {
+								name: metadata.0.as_bytes().to_vec(),
+								symbol: metadata.1.as_bytes().to_vec(),
+								decimals: metadata.2,
+								minimal_balance: *minimal_balance,
+							},
+						},
+					)
+				}) {
+				if let CurrencyId::Token2(_token_id) = *currency_id {
+					Pallet::<T>::get_next_token_id().expect("Token register");
+				}
+				Pallet::<T>::do_register_metadata(*currency_id, &metadata).expect("Token register");
+			}
+
+			for (currency, para_id, first_slot, last_slot) in self.vsbond.iter() {
+				match currency {
+					Token(symbol) | Native(symbol) => {
+						AssetIdMaps::<T>::register_vsbond_metadata(
+							*symbol,
+							*para_id,
+							*first_slot,
+							*last_slot,
+						)
+						.expect("VSBond register");
+					},
+					Token2(token_id) => {
+						AssetIdMaps::<T>::register_vsbond2_metadata(
+							*token_id,
+							*para_id,
+							*first_slot,
+							*last_slot,
+						)
+						.expect("VToken register");
+					},
+					_ => (),
+				}
+			}
+
+			for &currency in self.vcurrency.iter() {
+				match currency {
+					CurrencyId::VToken(symbol) => {
+						AssetIdMaps::<T>::register_vtoken_metadata(symbol)
+							.expect("VToken register");
+					},
+					CurrencyId::VToken2(token_id) => {
+						AssetIdMaps::<T>::register_vtoken2_metadata(token_id)
+							.expect("VToken register");
+					},
+					CurrencyId::VSToken(symbol) => {
+						AssetIdMaps::<T>::register_vstoken_metadata(symbol)
+							.expect("VSToken register");
+					},
+					CurrencyId::VSToken2(token_id) => {
+						AssetIdMaps::<T>::register_vstoken2_metadata(token_id)
+							.expect("VSToken register");
+					},
+					_ => (),
+				}
+			}
+		}
+	}
+
+	#[pallet::pallet]
+	#[pallet::without_storage_info]
+	pub struct Pallet<T>(_);
+
+	#[pallet::call]
+	impl<T: Config> Pallet<T> {
+		#[pallet::call_index(0)]
+		#[pallet::weight(T::WeightInfo::register_native_asset())]
+		pub fn register_native_asset(
+			origin: OriginFor<T>,
+			currency_id: CurrencyId,
+			location: Box<VersionedLocation>,
+			metadata: Box<AssetMetadata<BalanceOf<T>>>,
+		) -> DispatchResult {
+			T::RegisterOrigin::ensure_origin(origin)?;
+
+			let location: Location =
+				(*location).try_into().map_err(|()| Error::<T>::BadLocation)?;
+			Self::do_register_native_asset(currency_id, &location, &metadata)?;
+
+			Self::deposit_event(Event::<T>::AssetRegistered {
+				asset_id: AssetIds::NativeAssetId(currency_id),
+				metadata: *metadata,
+			});
+			Ok(())
+		}
+
+		#[pallet::call_index(1)]
+		#[pallet::weight(T::WeightInfo::update_native_asset())]
+		pub fn update_native_asset(
+			origin: OriginFor<T>,
+			currency_id: CurrencyId,
+			location: Box<VersionedLocation>,
+			metadata: Box<AssetMetadata<BalanceOf<T>>>,
+		) -> DispatchResult {
+			T::RegisterOrigin::ensure_origin(origin)?;
+
+			let location: Location =
+				(*location).try_into().map_err(|()| Error::<T>::BadLocation)?;
+			Self::do_update_native_asset(currency_id, &location, &metadata)?;
+
+			Self::deposit_event(Event::<T>::AssetUpdated {
+				asset_id: AssetIds::NativeAssetId(currency_id),
+				metadata: *metadata,
+			});
+			Ok(())
+		}
+
+		#[pallet::call_index(2)]
+		#[pallet::weight(T::WeightInfo::register_token_metadata())]
+		pub fn register_token_metadata(
+			origin: OriginFor<T>,
+			metadata: Box<AssetMetadata<BalanceOf<T>>>,
+		) -> DispatchResult {
+			T::RegisterOrigin::ensure_origin(origin)?;
+
+			let token_id = Self::get_next_token_id()?;
+			let currency_id = Token2(token_id);
+			Self::do_register_metadata(currency_id, &metadata)?;
+
+			Ok(())
+		}
+
+		#[pallet::call_index(3)]
+		#[pallet::weight(T::WeightInfo::register_vtoken_metadata())]
+		pub fn register_vtoken_metadata(origin: OriginFor<T>, token_id: TokenId) -> DispatchResult {
+			T::RegisterOrigin::ensure_origin(origin)?;
+
+			if let Some(token_metadata) = CurrencyMetadatas::<T>::get(Token2(token_id)) {
+				let vtoken_metadata = Self::convert_to_vtoken_metadata(token_metadata);
+				Self::do_register_metadata(CurrencyId::VToken2(token_id), &vtoken_metadata)?;
+
+				return Ok(());
+			} else {
+				return Err(Error::<T>::CurrencyIdNotExists)?;
+			}
+		}
+
+		#[pallet::call_index(4)]
+		#[pallet::weight(T::WeightInfo::register_vstoken_metadata())]
+		pub fn register_vstoken_metadata(
+			origin: OriginFor<T>,
+			token_id: TokenId,
+		) -> DispatchResult {
+			T::RegisterOrigin::ensure_origin(origin)?;
+
+			if let Some(token_metadata) = CurrencyMetadatas::<T>::get(CurrencyId::Token2(token_id))
+			{
+				let vstoken_metadata = Self::convert_to_vstoken_metadata(token_metadata);
+				Self::do_register_metadata(CurrencyId::VSToken2(token_id), &vstoken_metadata)?;
+
+				return Ok(());
+			} else {
+				return Err(Error::<T>::CurrencyIdNotExists)?;
+			}
+		}
+
+		#[pallet::call_index(5)]
+		#[pallet::weight(T::WeightInfo::register_vsbond_metadata())]
+		pub fn register_vsbond_metadata(
+			origin: OriginFor<T>,
+			token_id: TokenId,
+			para_id: ParaId,
+			first_slot: LeasePeriod,
+			last_slot: LeasePeriod,
+		) -> DispatchResult {
+			T::RegisterOrigin::ensure_origin(origin)?;
+
+			if let Some(token_metadata) = CurrencyMetadatas::<T>::get(CurrencyId::Token2(token_id))
+			{
+				let vsbond_metadata = Self::convert_to_vsbond_metadata(
+					token_metadata,
+					para_id,
+					first_slot,
+					last_slot,
+				);
+				Self::do_register_metadata(
+					CurrencyId::VSBond2(token_id, para_id, first_slot, last_slot),
+					&vsbond_metadata,
+				)?;
+
+				return Ok(());
+			} else {
+				return Err(Error::<T>::CurrencyIdNotExists)?;
+			}
+		}
+
+		#[pallet::call_index(6)]
+		#[pallet::weight(T::WeightInfo::register_location())]
+		pub fn register_location(
+			origin: OriginFor<T>,
+			currency_id: CurrencyId,
+			location: Box<VersionedLocation>,
+			weight: Weight,
+		) -> DispatchResult {
+			T::RegisterOrigin::ensure_origin(origin)?;
+
+			let location: Location =
+				(*location).try_into().map_err(|()| Error::<T>::BadLocation)?;
+			Self::do_register_location(currency_id, &location)?;
+			Self::do_register_weight(currency_id, weight)?;
+
+			Ok(())
+		}
+
+		#[pallet::call_index(7)]
+		#[pallet::weight(T::WeightInfo::force_set_location())]
+		pub fn force_set_location(
+			origin: OriginFor<T>,
+			currency_id: CurrencyId,
+			location: Box<VersionedLocation>,
+			weight: Weight,
+		) -> DispatchResult {
+			T::RegisterOrigin::ensure_origin(origin)?;
+
+			let location: Location =
+				(*location).try_into().map_err(|()| Error::<T>::BadLocation)?;
+
+			let v3_location = xcm::v3::Location::try_from(location.clone())
+				.map_err(|()| Error::<T>::BadLocation)?;
+
+			ensure!(
+				CurrencyMetadatas::<T>::get(currency_id).is_some(),
+				Error::<T>::CurrencyIdNotExists
+			);
+
+			LocationToCurrencyIds::<T>::insert(v3_location, currency_id);
+			CurrencyIdToLocations::<T>::insert(currency_id, v3_location);
+			CurrencyIdToWeights::<T>::insert(currency_id, weight);
+
+			Pallet::<T>::deposit_event(Event::<T>::LocationSet { currency_id, location, weight });
+
+			Ok(())
+		}
+
+		#[pallet::call_index(8)]
+		#[pallet::weight(T::WeightInfo::update_currency_metadata())]
+		pub fn update_currency_metadata(
+			origin: OriginFor<T>,
+			currency_id: CurrencyId,
+			asset_name: Option<Vec<u8>>,
+			asset_symbol: Option<Vec<u8>>,
+			asset_decimals: Option<u8>,
+			asset_minimal_balance: Option<BalanceOf<T>>,
+		) -> DispatchResult {
+			T::RegisterOrigin::ensure_origin(origin)?;
+
+			// Check if the currency metadata exists
+			let mut metadata =
+				CurrencyMetadatas::<T>::get(currency_id).ok_or(Error::<T>::CurrencyIdNotExists)?;
+
+			// Update the metadata fields based on the provided options
+			if let Some(name) = asset_name {
+				metadata.name = name;
+			}
+			if let Some(symbol) = asset_symbol {
+				metadata.symbol = symbol;
+			}
+			if let Some(decimals) = asset_decimals {
+				metadata.decimals = decimals;
+			}
+			if let Some(minimal_balance) = asset_minimal_balance {
+				metadata.minimal_balance = minimal_balance;
+			}
+
+			// Store the updated metadata
+			CurrencyMetadatas::<T>::insert(currency_id, metadata.clone());
+			Self::deposit_event(Event::<T>::CurrencyIdUpdated { currency_id, metadata });
+
+			Ok(())
+		}
+	}
+}
+
+impl<T: Config> Pallet<T> {
+	pub fn get_next_token_id() -> Result<TokenId, DispatchError> {
+		NextTokenId::<T>::try_mutate(|current| -> Result<TokenId, DispatchError> {
+			let id = *current;
+			*current = current.checked_add(One::one()).ok_or(ArithmeticError::Overflow)?;
+			Ok(id)
+		})
+	}
+
+	pub fn do_register_native_asset(
+		currency_id: CurrencyId,
+		location: &Location,
+		metadata: &AssetMetadata<BalanceOf<T>>,
+	) -> DispatchResult {
+		let v3_location =
+			xcm::v3::Location::try_from(location.clone()).map_err(|()| Error::<T>::BadLocation)?;
+
+		ensure!(LocationToCurrencyIds::<T>::get(v3_location).is_none(), Error::<T>::AssetIdExisted);
+		ensure!(
+			CurrencyIdToLocations::<T>::get(currency_id).is_none(),
+			Error::<T>::LocationExisted
+		);
+		ensure!(
+			AssetMetadatas::<T>::get(AssetIds::NativeAssetId(currency_id)).is_none(),
+			Error::<T>::AssetIdExisted
+		);
+
+		LocationToCurrencyIds::<T>::insert(v3_location, currency_id);
+		CurrencyIdToLocations::<T>::insert(currency_id, v3_location);
+		AssetMetadatas::<T>::insert(AssetIds::NativeAssetId(currency_id), metadata);
+
+		Ok(())
+	}
+
+	pub fn convert_to_vtoken_metadata(
+		token_metadata: AssetMetadata<BalanceOf<T>>,
+	) -> AssetMetadata<BalanceOf<T>> {
+		let mut name = "Voucher ".as_bytes().to_vec();
+		name.extend_from_slice(&token_metadata.symbol);
+		let mut symbol = "v".as_bytes().to_vec();
+		symbol.extend_from_slice(&token_metadata.symbol);
+		AssetMetadata { name, symbol, ..token_metadata }
+	}
+
+	pub fn convert_to_vstoken_metadata(
+		token_metadata: AssetMetadata<BalanceOf<T>>,
+	) -> AssetMetadata<BalanceOf<T>> {
+		let mut name = "Voucher Slot ".as_bytes().to_vec();
+		name.extend_from_slice(&token_metadata.symbol);
+		let mut symbol = "vs".as_bytes().to_vec();
+		symbol.extend_from_slice(&token_metadata.symbol);
+		AssetMetadata { name, symbol, ..token_metadata }
+	}
+
+	pub fn convert_to_vsbond_metadata(
+		token_metadata: AssetMetadata<BalanceOf<T>>,
+		para_id: ParaId,
+		first_slot: LeasePeriod,
+		last_slot: LeasePeriod,
+	) -> AssetMetadata<BalanceOf<T>> {
+		let name = scale_info::prelude::format!(
+			"vsBOND-{}-{}-{}-{}",
+			core::str::from_utf8(&token_metadata.symbol).unwrap_or(""),
+			para_id,
+			first_slot,
+			last_slot
+		)
+		.as_bytes()
+		.to_vec();
+		AssetMetadata { name: name.clone(), symbol: name, ..token_metadata }
+	}
+
+	pub fn do_register_metadata(
+		currency_id: CurrencyId,
+		metadata: &AssetMetadata<BalanceOf<T>>,
+	) -> DispatchResult {
+		ensure!(CurrencyMetadatas::<T>::get(currency_id).is_none(), Error::<T>::CurrencyIdExisted);
+
+		CurrencyMetadatas::<T>::insert(currency_id, metadata.clone());
+
+		Pallet::<T>::deposit_event(Event::<T>::CurrencyIdRegistered {
+			currency_id,
+			metadata: metadata.clone(),
+		});
+
+		Ok(())
+	}
+
+	pub fn do_register_location(currency_id: CurrencyId, location: &Location) -> DispatchResult {
+		let v3_location =
+			xcm::v3::Location::try_from(location.clone()).map_err(|()| Error::<T>::BadLocation)?;
+
+		ensure!(
+			CurrencyMetadatas::<T>::get(currency_id).is_some(),
+			Error::<T>::CurrencyIdNotExists
+		);
+		ensure!(
+			LocationToCurrencyIds::<T>::get(v3_location).is_none(),
+			Error::<T>::CurrencyIdExisted
+		);
+		ensure!(
+			CurrencyIdToLocations::<T>::get(currency_id).is_none(),
+			Error::<T>::LocationExisted
+		);
+
+		LocationToCurrencyIds::<T>::insert(v3_location, currency_id);
+		CurrencyIdToLocations::<T>::insert(currency_id, v3_location);
+
+		Ok(())
+	}
+
+	pub fn do_register_weight(currency_id: CurrencyId, weight: Weight) -> DispatchResult {
+		ensure!(
+			CurrencyMetadatas::<T>::get(currency_id).is_some(),
+			Error::<T>::CurrencyIdNotExists
+		);
+
+		CurrencyIdToWeights::<T>::insert(currency_id, weight);
+
+		Ok(())
+	}
+
+	fn do_update_native_asset(
+		currency_id: CurrencyId,
+		location: &Location,
+		metadata: &AssetMetadata<BalanceOf<T>>,
+	) -> DispatchResult {
+		let v3_location =
+			xcm::v3::Location::try_from(location.clone()).map_err(|()| Error::<T>::BadLocation)?;
+
+		ensure!(
+			LocationToCurrencyIds::<T>::get(v3_location).is_some(),
+			Error::<T>::AssetIdNotExists
+		);
+		ensure!(
+			CurrencyIdToLocations::<T>::get(currency_id).is_some(),
+			Error::<T>::LocationExisted
+		);
+		ensure!(
+			AssetMetadatas::<T>::get(AssetIds::NativeAssetId(currency_id)).is_some(),
+			Error::<T>::AssetIdNotExists
+		);
+
+		LocationToCurrencyIds::<T>::insert(v3_location, currency_id);
+		CurrencyIdToLocations::<T>::insert(currency_id, v3_location);
+		AssetMetadatas::<T>::insert(AssetIds::NativeAssetId(currency_id), metadata);
+
+		Ok(())
+	}
+}
+
+pub struct AssetIdMaps<T>(sp_std::marker::PhantomData<T>);
+
+impl<T: Config> CurrencyIdMapping<CurrencyId, MultiLocation, AssetMetadata<BalanceOf<T>>>
+	for AssetIdMaps<T>
+{
+	fn get_asset_metadata(asset_ids: AssetIds) -> Option<AssetMetadata<BalanceOf<T>>> {
+		AssetMetadatas::<T>::get(asset_ids)
+	}
+
+	fn get_currency_metadata(currency_id: CurrencyId) -> Option<AssetMetadata<BalanceOf<T>>> {
+		CurrencyMetadatas::<T>::get(currency_id)
+	}
+
+	fn get_all_currency() -> Vec<CurrencyId> {
+		CurrencyMetadatas::<T>::iter_keys().collect()
+	}
+
+	fn get_location(currency_id: CurrencyId) -> Option<Location> {
+		CurrencyIdToLocations::<T>::get(currency_id).map(|location| location.try_into().ok())?
+	}
+
+	fn get_currency_id(multi_location: Location) -> Option<CurrencyId> {
+		let v3_location = xcm::v3::Location::try_from(multi_location).ok()?;
+		LocationToCurrencyIds::<T>::get(v3_location)
+	}
+}
+
+impl<T: Config> CurrencyIdConversion<CurrencyId> for AssetIdMaps<T> {
+	fn convert_to_token(currency_id: CurrencyId) -> Result<CurrencyId, ()> {
+		match currency_id {
+			CurrencyId::VSBond(TokenSymbol::BNC, 2001, 13, 20) =>
+				Ok(CurrencyId::Token(TokenSymbol::KSM)),
+			CurrencyId::VToken(TokenSymbol::BNC) => Ok(CurrencyId::Native(TokenSymbol::BNC)),
+			CurrencyId::VToken(token_symbol) |
+			CurrencyId::VSToken(token_symbol) |
+			CurrencyId::VSBond(token_symbol, ..) => Ok(CurrencyId::Token(token_symbol)),
+			CurrencyId::VToken2(token_id) |
+			CurrencyId::VSToken2(token_id) |
+			CurrencyId::VSBond2(token_id, ..) => Ok(CurrencyId::Token2(token_id)),
+			_ => Err(()),
+		}
+	}
+
+	fn convert_to_vtoken(currency_id: CurrencyId) -> Result<CurrencyId, ()> {
+		match currency_id {
+			CurrencyId::Token(token_symbol) | CurrencyId::Native(token_symbol) =>
+				Ok(CurrencyId::VToken(token_symbol)),
+			CurrencyId::Token2(token_id) => Ok(CurrencyId::VToken2(token_id)),
+			_ => Err(()),
+		}
+	}
+
+	fn convert_to_vstoken(currency_id: CurrencyId) -> Result<CurrencyId, ()> {
+		match currency_id {
+			CurrencyId::Token(token_symbol) => Ok(CurrencyId::VSToken(token_symbol)),
+			CurrencyId::Token2(token_id) => Ok(CurrencyId::VSToken2(token_id)),
+			_ => Err(()),
+		}
+	}
+
+	fn convert_to_vsbond(
+		currency_id: CurrencyId,
+		index: ParaId,
+		first_slot: LeasePeriod,
+		last_slot: LeasePeriod,
+	) -> Result<CurrencyId, ()> {
+		match currency_id {
+			CurrencyId::Token(token_symbol) => {
+				let mut vs_bond = CurrencyId::VSBond(token_symbol, index, first_slot, last_slot);
+				if vs_bond == CurrencyId::VSBond(TokenSymbol::KSM, 2001, 13, 20) {
+					// fix vsBOND::BNC
+					vs_bond = CurrencyId::VSBond(TokenSymbol::BNC, 2001, 13, 20);
+				}
+				Ok(vs_bond)
+			},
+			CurrencyId::Token2(token_id) =>
+				Ok(CurrencyId::VSBond2(token_id, index, first_slot, last_slot)),
+			_ => Err(()),
+		}
+	}
+}
+
+impl<T: Config> CurrencyIdRegister<CurrencyId> for AssetIdMaps<T> {
+	fn check_token_registered(token_symbol: TokenSymbol) -> bool {
+		CurrencyMetadatas::<T>::get(CurrencyId::Token(token_symbol)).is_some()
+	}
+
+	fn check_vtoken_registered(token_symbol: TokenSymbol) -> bool {
+		CurrencyMetadatas::<T>::get(CurrencyId::VToken(token_symbol)).is_some()
+	}
+
+	fn check_vstoken_registered(token_symbol: TokenSymbol) -> bool {
+		CurrencyMetadatas::<T>::get(CurrencyId::VSToken(token_symbol)).is_some()
+	}
+
+	fn check_vsbond_registered(
+		token_symbol: TokenSymbol,
+		para_id: ParaId,
+		first_slot: LeasePeriod,
+		last_slot: LeasePeriod,
+	) -> bool {
+		CurrencyMetadatas::<T>::get(CurrencyId::VSBond(
+			token_symbol,
+			para_id,
+			first_slot,
+			last_slot,
+		))
+		.is_some()
+	}
+
+	fn register_vtoken_metadata(token_symbol: TokenSymbol) -> sp_runtime::DispatchResult {
+		if let Some(token_metadata) = CurrencyMetadatas::<T>::get(CurrencyId::Token(token_symbol)) {
+			let vtoken_metadata = Pallet::<T>::convert_to_vtoken_metadata(token_metadata);
+			Pallet::<T>::do_register_metadata(CurrencyId::VToken(token_symbol), &vtoken_metadata)?;
+			return Ok(());
+		} else if let Some(token_metadata) =
+			CurrencyMetadatas::<T>::get(CurrencyId::Native(token_symbol))
+		{
+			let vtoken_metadata = Pallet::<T>::convert_to_vtoken_metadata(token_metadata);
+			Pallet::<T>::do_register_metadata(CurrencyId::VToken(token_symbol), &vtoken_metadata)?;
+			return Ok(());
+		} else {
+			return Err(Error::<T>::CurrencyIdNotExists.into());
+		}
+	}
+
+	fn register_vstoken_metadata(token_symbol: TokenSymbol) -> sp_runtime::DispatchResult {
+		if let Some(token_metadata) = CurrencyMetadatas::<T>::get(CurrencyId::Token(token_symbol)) {
+			let vstoken_metadata = Pallet::<T>::convert_to_vstoken_metadata(token_metadata);
+			Pallet::<T>::do_register_metadata(
+				CurrencyId::VSToken(token_symbol),
+				&vstoken_metadata,
+			)?;
+
+			return Ok(());
+		} else {
+			return Err(Error::<T>::CurrencyIdNotExists.into());
+		}
+	}
+
+	fn register_vsbond_metadata(
+		token_symbol: TokenSymbol,
+		para_id: ParaId,
+		first_slot: LeasePeriod,
+		last_slot: LeasePeriod,
+	) -> sp_runtime::DispatchResult {
+		let option_token_metadata =
+			if CurrencyMetadatas::<T>::contains_key(CurrencyId::Token(token_symbol)) {
+				CurrencyMetadatas::<T>::get(CurrencyId::Token(token_symbol))
+			} else if token_symbol == TokenSymbol::BNC &&
+				CurrencyMetadatas::<T>::contains_key(CurrencyId::Native(token_symbol))
+			{
+				CurrencyMetadatas::<T>::get(CurrencyId::Native(token_symbol))
+			} else {
+				None
+			};
+
+		if let Some(token_metadata) = option_token_metadata {
+			let vsbond_metadata = Pallet::<T>::convert_to_vsbond_metadata(
+				token_metadata,
+				para_id,
+				first_slot,
+				last_slot,
+			);
+			Pallet::<T>::do_register_metadata(
+				CurrencyId::VSBond(token_symbol, para_id, first_slot, last_slot),
+				&vsbond_metadata,
+			)?;
+
+			return Ok(());
+		} else {
+			return Err(Error::<T>::CurrencyIdNotExists.into());
+		}
+	}
+
+	fn check_token2_registered(token_id: TokenId) -> bool {
+		CurrencyMetadatas::<T>::get(CurrencyId::Token2(token_id)).is_some()
+	}
+
+	fn check_vtoken2_registered(token_id: TokenId) -> bool {
+		CurrencyMetadatas::<T>::get(CurrencyId::VToken2(token_id)).is_some()
+	}
+
+	fn check_vstoken2_registered(token_id: TokenId) -> bool {
+		CurrencyMetadatas::<T>::get(CurrencyId::VSToken2(token_id)).is_some()
+	}
+
+	fn check_vsbond2_registered(
+		token_id: TokenId,
+		para_id: ParaId,
+		first_slot: LeasePeriod,
+		last_slot: LeasePeriod,
+	) -> bool {
+		CurrencyMetadatas::<T>::get(CurrencyId::VSBond2(token_id, para_id, first_slot, last_slot))
+			.is_some()
+	}
+
+	fn register_vtoken2_metadata(token_id: TokenId) -> DispatchResult {
+		if let Some(token_metadata) = CurrencyMetadatas::<T>::get(CurrencyId::Token2(token_id)) {
+			let vtoken_metadata = Pallet::<T>::convert_to_vtoken_metadata(token_metadata);
+			Pallet::<T>::do_register_metadata(CurrencyId::VToken2(token_id), &vtoken_metadata)?;
+
+			return Ok(());
+		} else {
+			return Err(Error::<T>::CurrencyIdNotExists.into());
+		}
+	}
+
+	fn register_vstoken2_metadata(token_id: TokenId) -> DispatchResult {
+		if let Some(token_metadata) = CurrencyMetadatas::<T>::get(CurrencyId::Token2(token_id)) {
+			let vstoken_metadata = Pallet::<T>::convert_to_vstoken_metadata(token_metadata);
+			Pallet::<T>::do_register_metadata(CurrencyId::VSToken2(token_id), &vstoken_metadata)?;
+
+			return Ok(());
+		} else {
+			return Err(Error::<T>::CurrencyIdNotExists.into());
+		}
+	}
+
+	fn register_vsbond2_metadata(
+		token_id: TokenId,
+		para_id: ParaId,
+		first_slot: LeasePeriod,
+		last_slot: LeasePeriod,
+	) -> DispatchResult {
+		if let Some(token_metadata) = CurrencyMetadatas::<T>::get(CurrencyId::Token2(token_id)) {
+			let vsbond_metadata = Pallet::<T>::convert_to_vsbond_metadata(
+				token_metadata,
+				para_id,
+				first_slot,
+				last_slot,
+			);
+			Pallet::<T>::do_register_metadata(
+				CurrencyId::VSBond2(token_id, para_id, first_slot, last_slot),
+				&vsbond_metadata,
+			)?;
+
+			return Ok(());
+		} else {
+			return Err(Error::<T>::CurrencyIdNotExists.into());
+		}
+	}
+
+	fn register_blp_metadata(pool_id: PoolId, decimals: u8) -> DispatchResult {
+		let name = scale_info::prelude::format!("Bifrost Stable Pool Token {}", pool_id)
+			.as_bytes()
+			.to_vec();
+		let symbol = scale_info::prelude::format!("BLP{}", pool_id).as_bytes().to_vec();
+		Pallet::<T>::do_register_metadata(
+			CurrencyId::BLP(pool_id),
+			&AssetMetadata {
+				name,
+				symbol,
+				decimals,
+				minimal_balance: BalanceOf::<T>::unique_saturated_from(1_000_000u128),
+			},
+		)
+	}
+}
+
+/// Simple fee calculator that requires payment in a single fungible at a fixed rate.
+///
+/// The constant `FixedRate` type parameter should be the concrete fungible ID and the amount of it
+/// required for one second of weight.
+pub struct FixedRateOfAsset<T, FixedRate: Get<u128>, R: TakeRevenue> {
+	weight: u64,
+	amount: u128,
+	ed_ratio: FixedU128,
+	location: Option<Location>,
+	_marker: PhantomData<(T, FixedRate, R)>,
+}
+
+impl<T: Config, FixedRate: Get<u128>, R: TakeRevenue> WeightTrader
+	for FixedRateOfAsset<T, FixedRate, R>
+where
+	BalanceOf<T>: Into<u128>,
+{
+	fn new() -> Self {
+		Self {
+			weight: 0,
+			amount: 0,
+			ed_ratio: Default::default(),
+			location: None,
+			_marker: PhantomData,
+		}
+	}
+
+	fn buy_weight(
+		&mut self,
+		weight: Weight,
+		payment: AssetsInHolding,
+		_context: &XcmContext,
+	) -> Result<AssetsInHolding, XcmError> {
+		log::trace!(target: "asset-registry::weight", "buy_weight weight: {:?}, payment: {:?}", weight, payment);
+
+		// only support first fungible assets now.
+		let asset_id = payment
+			.fungible
+			.iter()
+			.next()
+			.map_or(Err(XcmError::TooExpensive), |v| Ok(v.0))?;
+
+		let AssetId(ref location) = asset_id.clone();
+		log::debug!(target: "asset-registry::weight", "buy_weight location: {:?}", location);
+
+		let v3_location =
+			xcm::v3::Location::try_from(location.clone()).map_err(|_| XcmError::InvalidLocation)?;
+
+		if let Some(currency_id) = LocationToCurrencyIds::<T>::get(v3_location) {
+			if let Some(currency_metadatas) = CurrencyMetadatas::<T>::get(currency_id) {
+				// The integration tests can ensure the ed is non-zero.
+				let ed_ratio = FixedU128::saturating_from_rational(
+					currency_metadatas.minimal_balance.into(),
+					T::Currency::minimum_balance().into(),
+				);
+				// The WEIGHT_REF_TIME_PER_SECOND is non-zero.
+				let weight_ratio = FixedU128::saturating_from_rational(
+					weight.ref_time(),
+					WEIGHT_REF_TIME_PER_SECOND,
+				);
+				let amount =
+					ed_ratio.saturating_mul_int(weight_ratio.saturating_mul_int(FixedRate::get()));
+
+				let required = Asset { id: asset_id.clone(), fun: Fungible(amount) };
+
+				log::trace!(
+					target: "asset-registry::weight", "buy_weight payment: {:?}, required: {:?}, fixed_rate: {:?}, ed_ratio: {:?}, weight_ratio: {:?}",
+					payment, required, FixedRate::get(), ed_ratio, weight_ratio
+				);
+				let unused =
+					payment.clone().checked_sub(required).map_err(|_| XcmError::TooExpensive)?;
+				self.weight = self.weight.saturating_add(weight.ref_time());
+				self.amount = self.amount.saturating_add(amount);
+				self.ed_ratio = ed_ratio;
+				self.location = Some(location.clone());
+				return Ok(unused);
+			}
+		};
+
+		log::trace!(target: "asset-registry::weight", "no concrete fungible asset");
+		Err(XcmError::TooExpensive)
+	}
+
+	fn refund_weight(&mut self, weight: Weight, _context: &XcmContext) -> Option<Asset> {
+		log::trace!(
+			target: "asset-registry::weight", "refund_weight weight: {:?}, weight: {:?}, amount: {:?}, ed_ratio: {:?}, location: {:?}",
+			weight, self.weight, self.amount, self.ed_ratio, self.location
+		);
+		let weight = weight.min(Weight::from_parts(self.weight, 0));
+		let weight_ratio =
+			FixedU128::saturating_from_rational(weight.ref_time(), WEIGHT_REF_TIME_PER_SECOND);
+		let amount = self
+			.ed_ratio
+			.saturating_mul_int(weight_ratio.saturating_mul_int(FixedRate::get()));
+
+		self.weight = self.weight.saturating_sub(weight.ref_time());
+		self.amount = self.amount.saturating_sub(amount);
+
+		log::trace!(target: "asset-registry::weight", "refund_weight amount: {:?}", amount);
+		if amount > 0 && self.location.is_some() {
+			Some(Asset {
+				fun: Fungible(amount),
+				id: AssetId(
+					self.location.clone().expect("checked is non-empty; qed").try_into().unwrap(),
+				),
+			})
+		} else {
+			None
+		}
+	}
+}
+
+impl<T, FixedRate: Get<u128>, R: TakeRevenue> Drop for FixedRateOfAsset<T, FixedRate, R> {
+	fn drop(&mut self) {
+		log::trace!(target: "asset-registry::weight", "take revenue, weight: {:?}, amount: {:?}, location: {:?}", self.weight, self.amount, self.location);
+		if self.amount > 0 && self.location.is_some() {
+			R::take_revenue(Asset {
+				fun: Fungible(self.amount),
+				id: AssetId(
+					self.location.clone().expect("checked is non-empty; qed").try_into().unwrap(),
+				),
+			});
+		}
+	}
+}
diff --git a/pallets/asset-registry/src/migration.rs b/pallets/deprecated/asset-registry/src/migration.rs
similarity index 100%
rename from pallets/asset-registry/src/migration.rs
rename to pallets/deprecated/asset-registry/src/migration.rs
diff --git a/pallets/deprecated/asset-registry/src/mock.rs b/pallets/deprecated/asset-registry/src/mock.rs
new file mode 100644
index 000000000..a948e290c
--- /dev/null
+++ b/pallets/deprecated/asset-registry/src/mock.rs
@@ -0,0 +1,109 @@
+// 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 <https://www.gnu.org/licenses/>.
+
+//! Mocks for asset registry module.
+
+#![cfg(test)]
+
+use bifrost_primitives::{AccountId, Balance};
+use frame_support::{
+	construct_runtime, derive_impl, ord_parameter_types, pallet_prelude::ConstU32, parameter_types,
+};
+use frame_system::EnsureSignedBy;
+use sp_runtime::BuildStorage;
+
+use crate as asset_registry;
+
+parameter_types!(
+	pub const BlockHashCount: u32 = 250;
+);
+
+#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)]
+impl frame_system::Config for Runtime {
+	type AccountId = AccountId;
+	type AccountData = pallet_balances::AccountData<Balance>;
+	type Block = Block;
+	type Lookup = sp_runtime::traits::IdentityLookup<Self::AccountId>;
+}
+
+parameter_types! {
+	pub const ExistentialDeposit: u64 = 1;
+	pub const MaxReserves: u32 = 50;
+}
+
+impl pallet_balances::Config for Runtime {
+	type Balance = Balance;
+	type DustRemoval = ();
+	type RuntimeEvent = RuntimeEvent;
+	type ExistentialDeposit = ExistentialDeposit;
+	type AccountStore = System;
+	type MaxLocks = ();
+	type MaxReserves = MaxReserves;
+	type ReserveIdentifier = [u8; 8];
+	type WeightInfo = ();
+	type RuntimeHoldReason = RuntimeHoldReason;
+	type RuntimeFreezeReason = RuntimeFreezeReason;
+	type FreezeIdentifier = ();
+	type MaxFreezes = ConstU32<0>;
+}
+
+ord_parameter_types! {
+	pub const CouncilAccount: AccountId = AccountId::from([1u8; 32]);
+}
+impl asset_registry::Config for Runtime {
+	type RuntimeEvent = RuntimeEvent;
+	type Currency = Balances;
+	type RegisterOrigin = EnsureSignedBy<CouncilAccount, AccountId>;
+	type WeightInfo = ();
+}
+
+type Block = frame_system::mocking::MockBlock<Runtime>;
+
+construct_runtime!(
+	pub enum Runtime {
+		System: frame_system,
+		Balances: pallet_balances,
+		AssetRegistry: asset_registry,
+	}
+);
+
+pub struct ExtBuilder {
+	balances: Vec<(AccountId, Balance)>,
+}
+
+impl Default for ExtBuilder {
+	fn default() -> Self {
+		Self { balances: vec![] }
+	}
+}
+
+impl ExtBuilder {
+	pub fn build(self) -> sp_io::TestExternalities {
+		let mut t = frame_system::GenesisConfig::<Runtime>::default().build_storage().unwrap();
+
+		pallet_balances::GenesisConfig::<Runtime> {
+			balances: self.balances.into_iter().collect::<Vec<_>>(),
+		}
+		.assimilate_storage(&mut t)
+		.unwrap();
+
+		let mut ext = sp_io::TestExternalities::new(t);
+		ext.execute_with(|| System::set_block_number(1));
+		ext
+	}
+}
diff --git a/pallets/deprecated/asset-registry/src/tests.rs b/pallets/deprecated/asset-registry/src/tests.rs
new file mode 100644
index 000000000..470a22438
--- /dev/null
+++ b/pallets/deprecated/asset-registry/src/tests.rs
@@ -0,0 +1,519 @@
+// 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 <https://www.gnu.org/licenses/>.
+
+//! Unit tests for asset registry module.
+
+#![cfg(test)]
+
+use super::*;
+use bifrost_primitives::TokenSymbol;
+use frame_support::{assert_noop, assert_ok};
+use mock::{
+	AssetRegistry, CouncilAccount, ExtBuilder, Runtime, RuntimeEvent, RuntimeOrigin, System,
+};
+
+#[test]
+fn versioned_multi_location_convert_work() {
+	ExtBuilder::default().build().execute_with(|| {
+		let versioned_location = VersionedLocation::V4(Location::from([Parachain(1000)]));
+		let location: Location = versioned_location.try_into().unwrap();
+		assert_eq!(location, Location::new(0, [Parachain(1000)]));
+	});
+}
+
+#[test]
+fn register_native_asset_works() {
+	ExtBuilder::default().build().execute_with(|| {
+		let versioned_location = VersionedLocation::V4(Location::from([Parachain(1000)]));
+
+		assert_ok!(AssetRegistry::register_native_asset(
+			RuntimeOrigin::signed(CouncilAccount::get()),
+			Token(TokenSymbol::DOT),
+			Box::new(versioned_location.clone()),
+			Box::new(AssetMetadata {
+				name: b"Token Name".to_vec(),
+				symbol: b"TN".to_vec(),
+				decimals: 12,
+				minimal_balance: 1,
+			})
+		));
+		System::assert_last_event(RuntimeEvent::AssetRegistry(Event::AssetRegistered {
+			asset_id: AssetIds::NativeAssetId(Token(TokenSymbol::DOT)),
+			metadata: AssetMetadata {
+				name: b"Token Name".to_vec(),
+				symbol: b"TN".to_vec(),
+				decimals: 12,
+				minimal_balance: 1,
+			},
+		}));
+
+		assert_eq!(
+			AssetMetadatas::<Runtime>::get(AssetIds::NativeAssetId(Token(TokenSymbol::DOT))),
+			Some(AssetMetadata {
+				name: b"Token Name".to_vec(),
+				symbol: b"TN".to_vec(),
+				decimals: 12,
+				minimal_balance: 1,
+			})
+		);
+		// Can't duplicate
+		assert_noop!(
+			AssetRegistry::register_native_asset(
+				RuntimeOrigin::signed(CouncilAccount::get()),
+				Token(TokenSymbol::DOT),
+				Box::new(versioned_location),
+				Box::new(AssetMetadata {
+					name: b"Token Name".to_vec(),
+					symbol: b"TN".to_vec(),
+					decimals: 12,
+					minimal_balance: 1,
+				})
+			),
+			Error::<Runtime>::AssetIdExisted
+		);
+	});
+}
+
+#[test]
+fn update_native_asset_works() {
+	let versioned_location = VersionedLocation::V4(Location::from([Parachain(1000)]));
+
+	ExtBuilder::default().build().execute_with(|| {
+		assert_noop!(
+			AssetRegistry::update_native_asset(
+				RuntimeOrigin::signed(CouncilAccount::get()),
+				Token(TokenSymbol::DOT),
+				Box::new(versioned_location.clone()),
+				Box::new(AssetMetadata {
+					name: b"New Token Name".to_vec(),
+					symbol: b"NTN".to_vec(),
+					decimals: 13,
+					minimal_balance: 2,
+				})
+			),
+			Error::<Runtime>::AssetIdNotExists
+		);
+
+		assert_ok!(AssetRegistry::register_native_asset(
+			RuntimeOrigin::signed(CouncilAccount::get()),
+			Token(TokenSymbol::DOT),
+			Box::new(versioned_location.clone()),
+			Box::new(AssetMetadata {
+				name: b"Token Name".to_vec(),
+				symbol: b"TN".to_vec(),
+				decimals: 12,
+				minimal_balance: 1,
+			})
+		));
+
+		assert_ok!(AssetRegistry::update_native_asset(
+			RuntimeOrigin::signed(CouncilAccount::get()),
+			Token(TokenSymbol::DOT),
+			Box::new(versioned_location.clone()),
+			Box::new(AssetMetadata {
+				name: b"New Token Name".to_vec(),
+				symbol: b"NTN".to_vec(),
+				decimals: 13,
+				minimal_balance: 2,
+			})
+		));
+
+		System::assert_last_event(RuntimeEvent::AssetRegistry(Event::AssetUpdated {
+			asset_id: AssetIds::NativeAssetId(Token(TokenSymbol::DOT)),
+			metadata: AssetMetadata {
+				name: b"New Token Name".to_vec(),
+				symbol: b"NTN".to_vec(),
+				decimals: 13,
+				minimal_balance: 2,
+			},
+		}));
+
+		assert_eq!(
+			AssetMetadatas::<Runtime>::get(AssetIds::NativeAssetId(Token(TokenSymbol::DOT))),
+			Some(AssetMetadata {
+				name: b"New Token Name".to_vec(),
+				symbol: b"NTN".to_vec(),
+				decimals: 13,
+				minimal_balance: 2,
+			})
+		);
+	});
+}
+
+#[test]
+fn register_token_metadata_should_work() {
+	ExtBuilder::default().build().execute_with(|| {
+		let metadata = AssetMetadata {
+			name: b"Bifrost Native Coin".to_vec(),
+			symbol: b"BNC".to_vec(),
+			decimals: 12,
+			minimal_balance: 0,
+		};
+
+		assert_ok!(AssetRegistry::register_token_metadata(
+			RuntimeOrigin::signed(CouncilAccount::get()),
+			Box::new(metadata.clone())
+		));
+
+		assert_eq!(CurrencyMetadatas::<Runtime>::get(Token2(0)), Some(metadata.clone()))
+	})
+}
+
+#[test]
+fn register_vtoken_metadata_should_work() {
+	ExtBuilder::default().build().execute_with(|| {
+		let metadata = AssetMetadata {
+			name: b"Bifrost Native Coin".to_vec(),
+			symbol: b"BNC".to_vec(),
+			decimals: 12,
+			minimal_balance: 0,
+		};
+		let v_metadata = AssetMetadata {
+			name: b"Voucher BNC".to_vec(),
+			symbol: b"vBNC".to_vec(),
+			decimals: 12,
+			minimal_balance: 0,
+		};
+		assert_noop!(
+			AssetRegistry::register_vtoken_metadata(
+				RuntimeOrigin::signed(CouncilAccount::get()),
+				1
+			),
+			Error::<Runtime>::CurrencyIdNotExists
+		);
+
+		assert_ok!(AssetRegistry::register_token_metadata(
+			RuntimeOrigin::signed(CouncilAccount::get()),
+			Box::new(metadata.clone())
+		));
+
+		assert_ok!(AssetRegistry::register_vtoken_metadata(
+			RuntimeOrigin::signed(CouncilAccount::get()),
+			0
+		));
+
+		assert_eq!(
+			CurrencyMetadatas::<Runtime>::get(CurrencyId::VToken2(0)),
+			Some(v_metadata.clone())
+		)
+	})
+}
+
+#[test]
+fn register_vstoken_metadata_should_work() {
+	ExtBuilder::default().build().execute_with(|| {
+		let metadata = AssetMetadata {
+			name: b"KSM Native Token".to_vec(),
+			symbol: b"KSM".to_vec(),
+			decimals: 12,
+			minimal_balance: 0,
+		};
+		let v_metadata = AssetMetadata {
+			name: b"Voucher Slot KSM".to_vec(),
+			symbol: b"vsKSM".to_vec(),
+			decimals: 12,
+			minimal_balance: 0,
+		};
+		assert_noop!(
+			AssetRegistry::register_vtoken_metadata(
+				RuntimeOrigin::signed(CouncilAccount::get()),
+				1
+			),
+			Error::<Runtime>::CurrencyIdNotExists
+		);
+
+		assert_ok!(AssetRegistry::register_token_metadata(
+			RuntimeOrigin::signed(CouncilAccount::get()),
+			Box::new(metadata.clone())
+		));
+
+		assert_ok!(AssetRegistry::register_vstoken_metadata(
+			RuntimeOrigin::signed(CouncilAccount::get()),
+			0
+		));
+
+		assert_eq!(
+			CurrencyMetadatas::<Runtime>::get(CurrencyId::VSToken2(0)),
+			Some(v_metadata.clone())
+		)
+	})
+}
+
+#[test]
+fn register_vsbond_metadata_should_work() {
+	ExtBuilder::default().build().execute_with(|| {
+		let metadata = AssetMetadata {
+			name: b"KSM Native Token".to_vec(),
+			symbol: b"KSM".to_vec(),
+			decimals: 12,
+			minimal_balance: 0,
+		};
+		let name = "vsBOND-KSM-2001-10-20".as_bytes().to_vec();
+		let v_metadata =
+			AssetMetadata { name: name.clone(), symbol: name, decimals: 12, minimal_balance: 0 };
+		assert_noop!(
+			AssetRegistry::register_vtoken_metadata(
+				RuntimeOrigin::signed(CouncilAccount::get()),
+				1
+			),
+			Error::<Runtime>::CurrencyIdNotExists
+		);
+
+		assert_ok!(AssetRegistry::register_token_metadata(
+			RuntimeOrigin::signed(CouncilAccount::get()),
+			Box::new(metadata.clone())
+		));
+
+		assert_ok!(AssetRegistry::register_vsbond_metadata(
+			RuntimeOrigin::signed(CouncilAccount::get()),
+			0,
+			2001,
+			10,
+			20
+		));
+
+		assert_eq!(
+			CurrencyMetadatas::<Runtime>::get(CurrencyId::VSBond2(0, 2001, 10, 20)),
+			Some(v_metadata.clone())
+		)
+	})
+}
+
+#[test]
+fn register_multilocation_should_work() {
+	ExtBuilder::default().build().execute_with(|| {
+		let metadata = AssetMetadata {
+			name: b"Bifrost Native Coin".to_vec(),
+			symbol: b"BNC".to_vec(),
+			decimals: 12,
+			minimal_balance: 0,
+		};
+
+		let versioned_location = VersionedLocation::V4(Location::new(1, [Parachain(2001)]));
+		let location: xcm::v3::Location = versioned_location.clone().try_into().unwrap();
+
+		assert_noop!(
+			AssetRegistry::register_location(
+				RuntimeOrigin::signed(CouncilAccount::get()),
+				Token2(0),
+				Box::new(versioned_location.clone()),
+				Weight::from_parts(2000_000_000, 0)
+			),
+			Error::<Runtime>::CurrencyIdNotExists
+		);
+
+		assert_ok!(AssetRegistry::register_token_metadata(
+			RuntimeOrigin::signed(CouncilAccount::get()),
+			Box::new(metadata.clone())
+		));
+
+		assert_ok!(AssetRegistry::register_location(
+			RuntimeOrigin::signed(CouncilAccount::get()),
+			Token2(0),
+			Box::new(versioned_location.clone()),
+			Weight::from_parts(2000_000_000, 0)
+		));
+
+		assert_noop!(
+			AssetRegistry::register_location(
+				RuntimeOrigin::signed(CouncilAccount::get()),
+				Token2(0),
+				Box::new(versioned_location.clone()),
+				Weight::from_parts(2000_000_000, 0)
+			),
+			Error::<Runtime>::CurrencyIdExisted
+		);
+
+		assert_eq!(LocationToCurrencyIds::<Runtime>::get(location), Some(Token2(0)));
+		assert_eq!(CurrencyIdToLocations::<Runtime>::get(Token2(0)), Some(location));
+		assert_eq!(
+			CurrencyIdToWeights::<Runtime>::get(Token2(0)),
+			Some(Weight::from_parts(2000_000_000, 0))
+		);
+	})
+}
+
+#[test]
+fn force_set_multilocation_should_work() {
+	ExtBuilder::default().build().execute_with(|| {
+		let metadata = AssetMetadata {
+			name: b"Bifrost Native Coin".to_vec(),
+			symbol: b"BNC".to_vec(),
+			decimals: 12,
+			minimal_balance: 0,
+		};
+		let versioned_location = VersionedLocation::V4(Location::new(1, [Parachain(2001)]));
+		let location: xcm::v3::Location = versioned_location.clone().try_into().unwrap();
+
+		assert_noop!(
+			AssetRegistry::force_set_location(
+				RuntimeOrigin::signed(CouncilAccount::get()),
+				Token2(0),
+				Box::new(versioned_location.clone()),
+				Weight::from_parts(2000_000_000, 0)
+			),
+			Error::<Runtime>::CurrencyIdNotExists
+		);
+
+		assert_ok!(AssetRegistry::register_token_metadata(
+			RuntimeOrigin::signed(CouncilAccount::get()),
+			Box::new(metadata.clone())
+		));
+
+		assert_ok!(AssetRegistry::force_set_location(
+			RuntimeOrigin::signed(CouncilAccount::get()),
+			Token2(0),
+			Box::new(versioned_location.clone()),
+			Weight::from_parts(2000_000_000, 0)
+		));
+
+		assert_ok!(AssetRegistry::force_set_location(
+			RuntimeOrigin::signed(CouncilAccount::get()),
+			Token2(0),
+			Box::new(versioned_location.clone()),
+			Weight::from_parts(2000_000_000, 0)
+		));
+
+		assert_eq!(LocationToCurrencyIds::<Runtime>::get(location), Some(Token2(0)));
+		assert_eq!(CurrencyIdToLocations::<Runtime>::get(Token2(0)), Some(location));
+		assert_eq!(
+			CurrencyIdToWeights::<Runtime>::get(Token2(0)),
+			Some(Weight::from_parts(2000_000_000, 0))
+		);
+	})
+}
+
+#[test]
+fn update_currency_metadata_should_work() {
+	ExtBuilder::default().build().execute_with(|| {
+		let caller = CouncilAccount::get();
+		let currency_id = CurrencyId::Token2(0);
+		let name = b"Updated Name".to_vec();
+		let symbol = b"UN".to_vec();
+		let decimals: u8 = 10;
+		let minimal_balance = 1000u32.into();
+
+		// Pre-insert a currency_metadata to update
+		CurrencyMetadatas::<Runtime>::insert(
+			currency_id,
+			AssetMetadata {
+				name: b"Old Name".to_vec(),
+				symbol: b"ON".to_vec(),
+				decimals: 8,
+				minimal_balance: 1u32.into(),
+			},
+		);
+
+		// Ensure the origin has the required permissions
+		let origin = RuntimeOrigin::signed(caller);
+		assert_ok!(AssetRegistry::update_currency_metadata(
+			origin,
+			currency_id,
+			Some(name.clone()),
+			Some(symbol.clone()),
+			Some(decimals),
+			Some(minimal_balance)
+		));
+
+		System::assert_last_event(RuntimeEvent::AssetRegistry(crate::Event::CurrencyIdUpdated {
+			currency_id,
+			metadata: AssetMetadata {
+				name: name.clone(),
+				symbol: symbol.clone(),
+				decimals,
+				minimal_balance,
+			},
+		}));
+
+		// Verify the updated metadata
+		let updated_metadata = CurrencyMetadatas::<Runtime>::get(currency_id).unwrap();
+		assert_eq!(updated_metadata.name, name);
+		assert_eq!(updated_metadata.symbol, symbol);
+		assert_eq!(updated_metadata.decimals, decimals);
+		assert_eq!(updated_metadata.minimal_balance, minimal_balance);
+	})
+}
+
+#[test]
+fn update_currency_metadata_should_work_no_change() {
+	ExtBuilder::default().build().execute_with(|| {
+		let caller = CouncilAccount::get();
+		let currency_id = CurrencyId::Token2(0);
+		let name = None;
+		let symbol = None;
+		let decimals = None;
+		let minimal_balance = None;
+
+		let old_metadata = AssetMetadata {
+			name: b"Old Name".to_vec(),
+			symbol: b"ON".to_vec(),
+			decimals: 8,
+			minimal_balance: 1u32.into(),
+		};
+
+		// Pre-insert a currency_metadata to update
+		CurrencyMetadatas::<Runtime>::insert(currency_id, old_metadata.clone());
+
+		// Ensure the origin has the required permissions
+		let origin = RuntimeOrigin::signed(caller);
+		assert_ok!(AssetRegistry::update_currency_metadata(
+			origin,
+			currency_id,
+			name,
+			symbol,
+			decimals,
+			minimal_balance
+		));
+
+		// Verify the event
+		System::assert_last_event(RuntimeEvent::AssetRegistry(crate::Event::CurrencyIdUpdated {
+			currency_id,
+			metadata: old_metadata.clone(),
+		}));
+
+		// Verify the updated metadata
+		let updated_metadata = CurrencyMetadatas::<Runtime>::get(currency_id).unwrap();
+		assert_eq!(updated_metadata, old_metadata);
+	});
+}
+
+#[test]
+fn update_currency_metadata_nonexistent_currency_id() {
+	ExtBuilder::default().build().execute_with(|| {
+		let caller = CouncilAccount::get();
+		let currency_id = CurrencyId::Token2(1); // Non-existent currency ID
+		let name = Some(b"Updated Name".to_vec());
+		let symbol = Some(b"UN".to_vec());
+		let decimals = Some(10);
+		let minimal_balance = Some(1000u32.into());
+
+		// Ensure the origin has the required permissions
+		let origin = RuntimeOrigin::signed(caller);
+		assert_noop!(
+			AssetRegistry::update_currency_metadata(
+				origin,
+				currency_id,
+				name,
+				symbol,
+				decimals,
+				minimal_balance
+			),
+			Error::<Runtime>::CurrencyIdNotExists
+		);
+	});
+}
diff --git a/pallets/deprecated/asset-registry/src/weights.rs b/pallets/deprecated/asset-registry/src/weights.rs
new file mode 100644
index 000000000..162c6fad6
--- /dev/null
+++ b/pallets/deprecated/asset-registry/src/weights.rs
@@ -0,0 +1,190 @@
+// 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 <https://www.gnu.org/licenses/>.
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! Autogenerated weights for bifrost_asset_registry
+//!
+//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
+//! DATE: 2023-09-14, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! HOSTNAME: `bifrost-jenkins`, CPU: `Intel(R) Xeon(R) CPU E5-26xx v4`
+//! WASM-EXECUTION: Compiled, CHAIN: Some("bifrost-kusama-local"), DB CACHE: 1024
+
+// Executed Command:
+// target/release/bifrost
+// benchmark
+// pallet
+// --chain=bifrost-kusama-local
+// --steps=50
+// --repeat=20
+// --pallet=bifrost_asset_registry
+// --extrinsic=*
+// --execution=wasm
+// --wasm-execution=compiled
+// --heap-pages=4096
+// --output=./pallets/asset-registry/src/weights.rs
+// --template=./weight-template/pallet-weight-template.hbs
+
+#![cfg_attr(rustfmt, rustfmt_skip)]
+#![allow(unused_parens)]
+#![allow(unused_imports)]
+
+use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
+use sp_std::marker::PhantomData;
+
+/// Weight functions needed for bifrost_asset_registry.
+pub trait WeightInfo {
+	fn register_native_asset() -> Weight;
+	fn update_native_asset() -> Weight;
+	fn register_token_metadata() -> Weight;
+	fn register_vtoken_metadata() -> Weight;
+	fn register_vstoken_metadata() -> Weight;
+	fn register_vsbond_metadata() -> Weight;
+	fn register_location() -> Weight;
+	fn force_set_location() -> Weight;
+	fn update_currency_metadata() -> Weight;
+}
+
+// For backwards compatibility and tests
+impl WeightInfo for () {
+	/// Storage: AssetRegistry LocationToCurrencyIds (r:1 w:1)
+	/// Proof Skipped: AssetRegistry LocationToCurrencyIds (max_values: None, max_size: None, mode: Measured)
+	/// Storage: AssetRegistry CurrencyIdToLocations (r:1 w:1)
+	/// Proof Skipped: AssetRegistry CurrencyIdToLocations (max_values: None, max_size: None, mode: Measured)
+	/// Storage: AssetRegistry AssetMetadatas (r:1 w:1)
+	/// Proof Skipped: AssetRegistry AssetMetadatas (max_values: None, max_size: None, mode: Measured)
+	fn register_native_asset() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `118`
+		//  Estimated: `3583`
+		// Minimum execution time: 52_056_000 picoseconds.
+		Weight::from_parts(53_012_000, 3583)
+			.saturating_add(RocksDbWeight::get().reads(3_u64))
+			.saturating_add(RocksDbWeight::get().writes(3_u64))
+	}
+	/// Storage: AssetRegistry LocationToCurrencyIds (r:1 w:1)
+	/// Proof Skipped: AssetRegistry LocationToCurrencyIds (max_values: None, max_size: None, mode: Measured)
+	/// Storage: AssetRegistry CurrencyIdToLocations (r:1 w:1)
+	/// Proof Skipped: AssetRegistry CurrencyIdToLocations (max_values: None, max_size: None, mode: Measured)
+	/// Storage: AssetRegistry AssetMetadatas (r:1 w:1)
+	/// Proof Skipped: AssetRegistry AssetMetadatas (max_values: None, max_size: None, mode: Measured)
+	fn update_native_asset() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `250`
+		//  Estimated: `3715`
+		// Minimum execution time: 59_891_000 picoseconds.
+		Weight::from_parts(60_869_000, 3715)
+			.saturating_add(RocksDbWeight::get().reads(3_u64))
+			.saturating_add(RocksDbWeight::get().writes(3_u64))
+	}
+	/// Storage: AssetRegistry NextTokenId (r:1 w:1)
+	/// Proof Skipped: AssetRegistry NextTokenId (max_values: Some(1), max_size: None, mode: Measured)
+	/// Storage: AssetRegistry CurrencyMetadatas (r:1 w:1)
+	/// Proof Skipped: AssetRegistry CurrencyMetadatas (max_values: None, max_size: None, mode: Measured)
+	fn register_token_metadata() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `607`
+		//  Estimated: `4072`
+		// Minimum execution time: 46_860_000 picoseconds.
+		Weight::from_parts(48_151_000, 4072)
+			.saturating_add(RocksDbWeight::get().reads(2_u64))
+			.saturating_add(RocksDbWeight::get().writes(2_u64))
+	}
+	/// Storage: AssetRegistry CurrencyMetadatas (r:2 w:1)
+	/// Proof Skipped: AssetRegistry CurrencyMetadatas (max_values: None, max_size: None, mode: Measured)
+	fn register_vtoken_metadata() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `779`
+		//  Estimated: `6719`
+		// Minimum execution time: 53_699_000 picoseconds.
+		Weight::from_parts(54_646_000, 6719)
+			.saturating_add(RocksDbWeight::get().reads(2_u64))
+			.saturating_add(RocksDbWeight::get().writes(1_u64))
+	}
+	/// Storage: AssetRegistry CurrencyMetadatas (r:2 w:1)
+	/// Proof Skipped: AssetRegistry CurrencyMetadatas (max_values: None, max_size: None, mode: Measured)
+	fn register_vstoken_metadata() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `705`
+		//  Estimated: `6645`
+		// Minimum execution time: 52_491_000 picoseconds.
+		Weight::from_parts(53_682_000, 6645)
+			.saturating_add(RocksDbWeight::get().reads(2_u64))
+			.saturating_add(RocksDbWeight::get().writes(1_u64))
+	}
+	/// Storage: AssetRegistry CurrencyMetadatas (r:2 w:1)
+	/// Proof Skipped: AssetRegistry CurrencyMetadatas (max_values: None, max_size: None, mode: Measured)
+	fn register_vsbond_metadata() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `763`
+		//  Estimated: `6703`
+		// Minimum execution time: 55_589_000 picoseconds.
+		Weight::from_parts(56_804_000, 6703)
+			.saturating_add(RocksDbWeight::get().reads(2_u64))
+			.saturating_add(RocksDbWeight::get().writes(1_u64))
+	}
+	/// Storage: AssetRegistry CurrencyMetadatas (r:1 w:0)
+	/// Proof Skipped: AssetRegistry CurrencyMetadatas (max_values: None, max_size: None, mode: Measured)
+	/// Storage: AssetRegistry LocationToCurrencyIds (r:1 w:1)
+	/// Proof Skipped: AssetRegistry LocationToCurrencyIds (max_values: None, max_size: None, mode: Measured)
+	/// Storage: AssetRegistry CurrencyIdToLocations (r:1 w:1)
+	/// Proof Skipped: AssetRegistry CurrencyIdToLocations (max_values: None, max_size: None, mode: Measured)
+	/// Storage: AssetRegistry CurrencyIdToWeights (r:0 w:1)
+	/// Proof Skipped: AssetRegistry CurrencyIdToWeights (max_values: None, max_size: None, mode: Measured)
+	fn register_location() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `683`
+		//  Estimated: `4148`
+		// Minimum execution time: 45_469_000 picoseconds.
+		Weight::from_parts(48_623_000, 4148)
+			.saturating_add(RocksDbWeight::get().reads(3_u64))
+			.saturating_add(RocksDbWeight::get().writes(3_u64))
+	}
+	/// Storage: AssetRegistry CurrencyMetadatas (r:1 w:0)
+	/// Proof Skipped: AssetRegistry CurrencyMetadatas (max_values: None, max_size: None, mode: Measured)
+	/// Storage: AssetRegistry LocationToCurrencyIds (r:0 w:1)
+	/// Proof Skipped: AssetRegistry LocationToCurrencyIds (max_values: None, max_size: None, mode: Measured)
+	/// Storage: AssetRegistry CurrencyIdToWeights (r:0 w:1)
+	/// Proof Skipped: AssetRegistry CurrencyIdToWeights (max_values: None, max_size: None, mode: Measured)
+	/// Storage: AssetRegistry CurrencyIdToLocations (r:0 w:1)
+	/// Proof Skipped: AssetRegistry CurrencyIdToLocations (max_values: None, max_size: None, mode: Measured)
+	fn force_set_location() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `683`
+		//  Estimated: `4148`
+		// Minimum execution time: 52_878_000 picoseconds.
+		Weight::from_parts(55_012_000, 4148)
+			.saturating_add(RocksDbWeight::get().reads(1_u64))
+			.saturating_add(RocksDbWeight::get().writes(3_u64))
+	}
+	/// Storage: `AssetRegistry::CurrencyMetadatas` (r:1 w:1)
+	/// Proof: `AssetRegistry::CurrencyMetadatas` (`max_values`: None, `max_size`: None, mode: `Measured`)
+	fn update_currency_metadata() -> Weight {
+		// Proof Size summary in bytes:
+		//  Measured:  `409`
+		//  Estimated: `3874`
+		// Minimum execution time: 12_000_000 picoseconds.
+		Weight::from_parts(13_000_000, 3874)
+			.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 2c77e7f99..8a43cd007 100644
--- a/pallets/slpx/src/benchmarking.rs
+++ b/pallets/slpx/src/benchmarking.rs
@@ -45,8 +45,8 @@ fn init_whitelist<T: Config + bifrost_asset_registry::Config>() -> (T::AccountId
 		BalanceOf::<T>::unique_saturated_from(100_000_000_000_000u128),
 	));
 
-	CurrencyIdToLocations::<T>::insert(KSM, xcm::v3::Location::default());
-	CurrencyIdToLocations::<T>::insert(VKSM, xcm::v3::Location::default());
+	CurrencyIdToLocations::<T>::insert(KSM, xcm::v4::Location::default());
+	CurrencyIdToLocations::<T>::insert(VKSM, xcm::v4::Location::default());
 
 	(caller, receiver)
 }
diff --git a/primitives/src/traits.rs b/primitives/src/traits.rs
index a3423ec73..c6cf28de0 100644
--- a/primitives/src/traits.rs
+++ b/primitives/src/traits.rs
@@ -186,30 +186,9 @@ pub trait CurrencyIdRegister<CurrencyId> {
 		last_slot: crate::LeasePeriod,
 	) -> bool;
 	fn register_vtoken_metadata(token_symbol: TokenSymbol) -> DispatchResult;
-	fn register_vstoken_metadata(token_symbol: TokenSymbol) -> DispatchResult;
-	fn register_vsbond_metadata(
-		token_symbol: TokenSymbol,
-		para_id: crate::ParaId,
-		first_slot: crate::LeasePeriod,
-		last_slot: crate::LeasePeriod,
-	) -> DispatchResult;
 	fn check_token2_registered(token_id: TokenId) -> bool;
 	fn check_vtoken2_registered(token_id: TokenId) -> bool;
-	fn check_vstoken2_registered(token_id: TokenId) -> bool;
-	fn check_vsbond2_registered(
-		token_id: TokenId,
-		para_id: crate::ParaId,
-		first_slot: crate::LeasePeriod,
-		last_slot: crate::LeasePeriod,
-	) -> bool;
 	fn register_vtoken2_metadata(token_id: TokenId) -> DispatchResult;
-	fn register_vstoken2_metadata(token_id: TokenId) -> DispatchResult;
-	fn register_vsbond2_metadata(
-		token_id: TokenId,
-		para_id: crate::ParaId,
-		first_slot: crate::LeasePeriod,
-		last_slot: crate::LeasePeriod,
-	) -> DispatchResult;
 	fn register_blp_metadata(pool_id: PoolId, decimals: u8) -> DispatchResult;
 }
 
@@ -239,19 +218,6 @@ impl<CurrencyId> CurrencyIdRegister<CurrencyId> for () {
 		Ok(())
 	}
 
-	fn register_vstoken_metadata(_token_symbol: TokenSymbol) -> DispatchResult {
-		Ok(())
-	}
-
-	fn register_vsbond_metadata(
-		_token_symbol: TokenSymbol,
-		_para_id: ParaId,
-		_first_slot: LeasePeriod,
-		_last_slot: LeasePeriod,
-	) -> DispatchResult {
-		Ok(())
-	}
-
 	fn check_token2_registered(_token_id: TokenId) -> bool {
 		false
 	}
@@ -260,36 +226,10 @@ impl<CurrencyId> CurrencyIdRegister<CurrencyId> for () {
 		false
 	}
 
-	fn check_vstoken2_registered(_token_id: TokenId) -> bool {
-		false
-	}
-
-	fn check_vsbond2_registered(
-		_token_id: TokenId,
-		_para_id: ParaId,
-		_first_slot: LeasePeriod,
-		_last_slot: LeasePeriod,
-	) -> bool {
-		false
-	}
-
 	fn register_vtoken2_metadata(_token_id: TokenId) -> DispatchResult {
 		Ok(())
 	}
 
-	fn register_vstoken2_metadata(_token_id: TokenId) -> DispatchResult {
-		Ok(())
-	}
-
-	fn register_vsbond2_metadata(
-		_token_id: TokenId,
-		_para_id: ParaId,
-		_first_slot: LeasePeriod,
-		_last_slot: LeasePeriod,
-	) -> DispatchResult {
-		Ok(())
-	}
-
 	fn register_blp_metadata(_pool_id: PoolId, _decimals: u8) -> DispatchResult {
 		Ok(())
 	}
diff --git a/runtime/bifrost-kusama/src/weights/bifrost_asset_registry.rs b/runtime/bifrost-kusama/src/weights/bifrost_asset_registry.rs
index 927135cec..cbc3b0ac0 100644
--- a/runtime/bifrost-kusama/src/weights/bifrost_asset_registry.rs
+++ b/runtime/bifrost-kusama/src/weights/bifrost_asset_registry.rs
@@ -54,36 +54,6 @@ use sp_std::marker::PhantomData;
 /// Weight functions for bifrost_asset_registry.
 pub struct BifrostWeight<T>(PhantomData<T>);
 impl<T: frame_system::Config> bifrost_asset_registry::WeightInfo for BifrostWeight<T> {
-	// Storage: AssetRegistry LocationToCurrencyIds (r:1 w:1)
-	// Proof Skipped: AssetRegistry LocationToCurrencyIds (max_values: None, max_size: None, mode: Measured)
-	// Storage: AssetRegistry CurrencyIdToLocations (r:1 w:1)
-	// Proof Skipped: AssetRegistry CurrencyIdToLocations (max_values: None, max_size: None, mode: Measured)
-	// Storage: AssetRegistry AssetMetadatas (r:1 w:1)
-	// Proof Skipped: AssetRegistry AssetMetadatas (max_values: None, max_size: None, mode: Measured)
-	fn register_native_asset() -> Weight {
-		// Proof Size summary in bytes:
-		//  Measured:  `118`
-		//  Estimated: `3583`
-		// Minimum execution time: 49_553 nanoseconds.
-		Weight::from_parts(50_599_000, 3583)
-			.saturating_add(T::DbWeight::get().reads(3))
-			.saturating_add(T::DbWeight::get().writes(3))
-	}
-	// Storage: AssetRegistry LocationToCurrencyIds (r:1 w:1)
-	// Proof Skipped: AssetRegistry LocationToCurrencyIds (max_values: None, max_size: None, mode: Measured)
-	// Storage: AssetRegistry CurrencyIdToLocations (r:1 w:1)
-	// Proof Skipped: AssetRegistry CurrencyIdToLocations (max_values: None, max_size: None, mode: Measured)
-	// Storage: AssetRegistry AssetMetadatas (r:1 w:1)
-	// Proof Skipped: AssetRegistry AssetMetadatas (max_values: None, max_size: None, mode: Measured)
-	fn update_native_asset() -> Weight {
-		// Proof Size summary in bytes:
-		//  Measured:  `250`
-		//  Estimated: `3715`
-		// Minimum execution time: 56_917 nanoseconds.
-		Weight::from_parts(57_419_000, 3715)
-			.saturating_add(T::DbWeight::get().reads(3))
-			.saturating_add(T::DbWeight::get().writes(3))
-	}
 	// Storage: AssetRegistry NextTokenId (r:1 w:1)
 	// Proof Skipped: AssetRegistry NextTokenId (max_values: Some(1), max_size: None, mode: Measured)
 	// Storage: AssetRegistry CurrencyMetadatas (r:1 w:1)
@@ -108,28 +78,6 @@ impl<T: frame_system::Config> bifrost_asset_registry::WeightInfo for BifrostWeig
 			.saturating_add(T::DbWeight::get().reads(2))
 			.saturating_add(T::DbWeight::get().writes(1))
 	}
-	// Storage: AssetRegistry CurrencyMetadatas (r:2 w:1)
-	// Proof Skipped: AssetRegistry CurrencyMetadatas (max_values: None, max_size: None, mode: Measured)
-	fn register_vstoken_metadata() -> Weight {
-		// Proof Size summary in bytes:
-		//  Measured:  `705`
-		//  Estimated: `6645`
-		// Minimum execution time: 49_492 nanoseconds.
-		Weight::from_parts(50_943_000, 6645)
-			.saturating_add(T::DbWeight::get().reads(2))
-			.saturating_add(T::DbWeight::get().writes(1))
-	}
-	// Storage: AssetRegistry CurrencyMetadatas (r:2 w:1)
-	// Proof Skipped: AssetRegistry CurrencyMetadatas (max_values: None, max_size: None, mode: Measured)
-	fn register_vsbond_metadata() -> Weight {
-		// Proof Size summary in bytes:
-		//  Measured:  `763`
-		//  Estimated: `6703`
-		// Minimum execution time: 52_709 nanoseconds.
-		Weight::from_parts(54_285_000, 6703)
-			.saturating_add(T::DbWeight::get().reads(2))
-			.saturating_add(T::DbWeight::get().writes(1))
-	}
 	// Storage: AssetRegistry CurrencyMetadatas (r:1 w:0)
 	// Proof Skipped: AssetRegistry CurrencyMetadatas (max_values: None, max_size: None, mode: Measured)
 	// Storage: AssetRegistry LocationToCurrencyIds (r:1 w:1)
diff --git a/runtime/bifrost-polkadot/src/weights/bifrost_asset_registry.rs b/runtime/bifrost-polkadot/src/weights/bifrost_asset_registry.rs
index 927135cec..cbc3b0ac0 100644
--- a/runtime/bifrost-polkadot/src/weights/bifrost_asset_registry.rs
+++ b/runtime/bifrost-polkadot/src/weights/bifrost_asset_registry.rs
@@ -54,36 +54,6 @@ use sp_std::marker::PhantomData;
 /// Weight functions for bifrost_asset_registry.
 pub struct BifrostWeight<T>(PhantomData<T>);
 impl<T: frame_system::Config> bifrost_asset_registry::WeightInfo for BifrostWeight<T> {
-	// Storage: AssetRegistry LocationToCurrencyIds (r:1 w:1)
-	// Proof Skipped: AssetRegistry LocationToCurrencyIds (max_values: None, max_size: None, mode: Measured)
-	// Storage: AssetRegistry CurrencyIdToLocations (r:1 w:1)
-	// Proof Skipped: AssetRegistry CurrencyIdToLocations (max_values: None, max_size: None, mode: Measured)
-	// Storage: AssetRegistry AssetMetadatas (r:1 w:1)
-	// Proof Skipped: AssetRegistry AssetMetadatas (max_values: None, max_size: None, mode: Measured)
-	fn register_native_asset() -> Weight {
-		// Proof Size summary in bytes:
-		//  Measured:  `118`
-		//  Estimated: `3583`
-		// Minimum execution time: 49_553 nanoseconds.
-		Weight::from_parts(50_599_000, 3583)
-			.saturating_add(T::DbWeight::get().reads(3))
-			.saturating_add(T::DbWeight::get().writes(3))
-	}
-	// Storage: AssetRegistry LocationToCurrencyIds (r:1 w:1)
-	// Proof Skipped: AssetRegistry LocationToCurrencyIds (max_values: None, max_size: None, mode: Measured)
-	// Storage: AssetRegistry CurrencyIdToLocations (r:1 w:1)
-	// Proof Skipped: AssetRegistry CurrencyIdToLocations (max_values: None, max_size: None, mode: Measured)
-	// Storage: AssetRegistry AssetMetadatas (r:1 w:1)
-	// Proof Skipped: AssetRegistry AssetMetadatas (max_values: None, max_size: None, mode: Measured)
-	fn update_native_asset() -> Weight {
-		// Proof Size summary in bytes:
-		//  Measured:  `250`
-		//  Estimated: `3715`
-		// Minimum execution time: 56_917 nanoseconds.
-		Weight::from_parts(57_419_000, 3715)
-			.saturating_add(T::DbWeight::get().reads(3))
-			.saturating_add(T::DbWeight::get().writes(3))
-	}
 	// Storage: AssetRegistry NextTokenId (r:1 w:1)
 	// Proof Skipped: AssetRegistry NextTokenId (max_values: Some(1), max_size: None, mode: Measured)
 	// Storage: AssetRegistry CurrencyMetadatas (r:1 w:1)
@@ -108,28 +78,6 @@ impl<T: frame_system::Config> bifrost_asset_registry::WeightInfo for BifrostWeig
 			.saturating_add(T::DbWeight::get().reads(2))
 			.saturating_add(T::DbWeight::get().writes(1))
 	}
-	// Storage: AssetRegistry CurrencyMetadatas (r:2 w:1)
-	// Proof Skipped: AssetRegistry CurrencyMetadatas (max_values: None, max_size: None, mode: Measured)
-	fn register_vstoken_metadata() -> Weight {
-		// Proof Size summary in bytes:
-		//  Measured:  `705`
-		//  Estimated: `6645`
-		// Minimum execution time: 49_492 nanoseconds.
-		Weight::from_parts(50_943_000, 6645)
-			.saturating_add(T::DbWeight::get().reads(2))
-			.saturating_add(T::DbWeight::get().writes(1))
-	}
-	// Storage: AssetRegistry CurrencyMetadatas (r:2 w:1)
-	// Proof Skipped: AssetRegistry CurrencyMetadatas (max_values: None, max_size: None, mode: Measured)
-	fn register_vsbond_metadata() -> Weight {
-		// Proof Size summary in bytes:
-		//  Measured:  `763`
-		//  Estimated: `6703`
-		// Minimum execution time: 52_709 nanoseconds.
-		Weight::from_parts(54_285_000, 6703)
-			.saturating_add(T::DbWeight::get().reads(2))
-			.saturating_add(T::DbWeight::get().writes(1))
-	}
 	// Storage: AssetRegistry CurrencyMetadatas (r:1 w:0)
 	// Proof Skipped: AssetRegistry CurrencyMetadatas (max_values: None, max_size: None, mode: Measured)
 	// Storage: AssetRegistry LocationToCurrencyIds (r:1 w:1)

From f372dfd70fce3f425553eeb6f28e07fd2f5b86fb Mon Sep 17 00:00:00 2001
From: MJLNSN <96321798+MJLNSN@users.noreply.github.com>
Date: Sun, 29 Sep 2024 21:29:44 +0800
Subject: [PATCH 11/31] Removed getters in farming (#1446)

---
 pallets/farming/src/boost.rs | 18 +++++++-------
 pallets/farming/src/lib.rs   | 47 +++++++++++++-----------------------
 pallets/farming/src/tests.rs | 24 +++++++++---------
 3 files changed, 38 insertions(+), 51 deletions(-)

diff --git a/pallets/farming/src/boost.rs b/pallets/farming/src/boost.rs
index a31e28966..50ada6193 100644
--- a/pallets/farming/src/boost.rs
+++ b/pallets/farming/src/boost.rs
@@ -43,10 +43,10 @@ impl<T: Config> BoostInterface<AccountIdOf<T>, CurrencyIdOf<T>, BalanceOf<T>, Bl
 	for Pallet<T>
 {
 	fn refresh_vebnc_farming(who: &AccountIdOf<T>) -> DispatchResult {
-		let mut boost_pool_info = Self::boost_pool_infos();
+		let mut boost_pool_info = BoostPoolInfos::<T>::get();
 		let new_vote_amount = T::BbBNC::balance_of(who, None)?;
 
-		if let Some(mut user_boost_info) = Self::user_boost_infos(who) {
+		if let Some(mut user_boost_info) = UserBoostInfos::<T>::get(who) {
 			// If the user's last voting block height is greater than or equal to the block height
 			// at the beginning of this round, refresh.
 			if user_boost_info.last_vote >= boost_pool_info.start_round {
@@ -89,7 +89,7 @@ impl<T: Config> Pallet<T> {
 	// the next round.
 	pub(crate) fn start_boost_round_inner(round_length: BlockNumberFor<T>) -> DispatchResult {
 		ensure!(round_length != Zero::zero(), Error::<T>::RoundLengthNotSet);
-		let mut boost_pool_info = Self::boost_pool_infos();
+		let mut boost_pool_info = BoostPoolInfos::<T>::get();
 		ensure!(boost_pool_info.end_round == Zero::zero(), Error::<T>::RoundNotOver);
 
 		// Update whitelist
@@ -118,7 +118,7 @@ impl<T: Config> Pallet<T> {
 	// Clear boost_basic_rewards and boost_pool_info.end_round to eliminate the influence of boost
 	// in hook
 	pub(crate) fn end_boost_round_inner() {
-		let mut boost_pool_info = Self::boost_pool_infos();
+		let mut boost_pool_info = BoostPoolInfos::<T>::get();
 		let _ = BoostBasicRewards::<T>::clear(u32::max_value(), None);
 		Self::deposit_event(Event::RoundEnd {
 			total_votes: boost_pool_info.total_votes,
@@ -132,7 +132,7 @@ impl<T: Config> Pallet<T> {
 
 	// Only used in hook
 	pub(crate) fn auto_start_boost_round() {
-		let mut boost_pool_info = Self::boost_pool_infos();
+		let mut boost_pool_info = BoostPoolInfos::<T>::get();
 		let whitelist_iter = BoostWhitelist::<T>::iter_keys();
 		// Update whitelist
 		if BoostNextRoundWhitelist::<T>::iter().count() != 0 {
@@ -164,7 +164,7 @@ impl<T: Config> Pallet<T> {
 		boost_pool_info: &BoostPoolInfo<BalanceOf<T>, BlockNumberFor<T>>,
 	) -> DispatchResult {
 		BoostVotingPools::<T>::iter()
-			.filter_map(|(pid, value)| match Self::pool_infos(pid) {
+			.filter_map(|(pid, value)| match PoolInfos::<T>::get(pid) {
 				Some(pool_info) => Some((pid, value, pool_info)),
 				None => None,
 			})
@@ -201,9 +201,9 @@ impl<T: Config> Pallet<T> {
 		vote_list: Vec<(PoolId, Percent)>,
 	) -> DispatchResult {
 		let current_block_number = frame_system::Pallet::<T>::block_number();
-		let mut boost_pool_info = Self::boost_pool_infos();
+		let mut boost_pool_info = BoostPoolInfos::<T>::get();
 
-		if let Some(user_boost_info) = Self::user_boost_infos(who) {
+		if let Some(user_boost_info) = UserBoostInfos::<T>::get(who) {
 			// If the user's last voting block height is greater than or equal to the block height
 			// at the beginning of this round, subtract.
 			if user_boost_info.last_vote >= boost_pool_info.start_round {
@@ -230,7 +230,7 @@ impl<T: Config> Pallet<T> {
 		let new_vote_amount = T::BbBNC::balance_of(who, None)?;
 		let mut percent_check = Percent::from_percent(0);
 		vote_list.iter().try_for_each(|(pid, proportion)| -> DispatchResult {
-			ensure!(Self::boost_whitelist(pid) != None, Error::<T>::NotInWhitelist);
+			ensure!(BoostWhitelist::<T>::get(pid) != None, Error::<T>::NotInWhitelist);
 			let increace = *proportion * new_vote_amount;
 			percent_check =
 				percent_check.checked_add(proportion).ok_or(Error::<T>::PercentOverflow)?;
diff --git a/pallets/farming/src/lib.rs b/pallets/farming/src/lib.rs
index 16d71fa2b..73d4badfd 100644
--- a/pallets/farming/src/lib.rs
+++ b/pallets/farming/src/lib.rs
@@ -236,22 +236,18 @@ pub mod pallet {
 	}
 
 	#[pallet::storage]
-	#[pallet::getter(fn pool_next_id)]
 	pub type PoolNextId<T: Config> = StorageValue<_, PoolId, ValueQuery>;
 
 	#[pallet::storage]
-	#[pallet::getter(fn gauge_pool_next_id)]
 	pub type GaugePoolNextId<T: Config> = StorageValue<_, PoolId, ValueQuery>;
 
 	#[pallet::storage]
-	#[pallet::getter(fn retire_limit)]
 	pub type RetireLimit<T: Config> = StorageValue<_, u32, ValueQuery>;
 
 	/// Record reward pool info.
 	///
 	/// map PoolId => PoolInfo
 	#[pallet::storage]
-	#[pallet::getter(fn pool_infos)]
 	pub type PoolInfos<T: Config> = StorageMap<
 		_,
 		Twox64Concat,
@@ -263,7 +259,6 @@ pub mod pallet {
 	///
 	/// map PoolId => GaugePoolInfo
 	#[pallet::storage]
-	#[pallet::getter(fn gauge_pool_infos)]
 	pub type GaugePoolInfos<T: Config> = StorageMap<
 		_,
 		Twox64Concat,
@@ -272,7 +267,6 @@ pub mod pallet {
 	>;
 
 	#[pallet::storage]
-	#[pallet::getter(fn gauge_infos)]
 	pub type GaugeInfos<T: Config> = StorageDoubleMap<
 		_,
 		Twox64Concat,
@@ -287,7 +281,6 @@ pub mod pallet {
 	///
 	/// double_map (PoolId, AccountId) => ShareInfo
 	#[pallet::storage]
-	#[pallet::getter(fn shares_and_withdrawn_rewards)]
 	pub type SharesAndWithdrawnRewards<T: Config> = StorageDoubleMap<
 		_,
 		Twox64Concat,
@@ -298,29 +291,23 @@ pub mod pallet {
 	>;
 
 	#[pallet::storage]
-	#[pallet::getter(fn boost_pool_infos)]
 	pub type BoostPoolInfos<T: Config> =
 		StorageValue<_, BoostPoolInfo<BalanceOf<T>, BlockNumberFor<T>>, ValueQuery>;
 
 	#[pallet::storage]
-	#[pallet::getter(fn user_boost_infos)]
 	pub type UserBoostInfos<T: Config> =
 		StorageMap<_, Blake2_128Concat, T::AccountId, UserBoostInfo<T>>;
 
 	#[pallet::storage]
-	#[pallet::getter(fn boost_whitelist)]
 	pub type BoostWhitelist<T: Config> = StorageMap<_, Twox64Concat, PoolId, ()>;
 
 	#[pallet::storage]
-	#[pallet::getter(fn boost_next_round_whitelist)]
 	pub type BoostNextRoundWhitelist<T: Config> = StorageMap<_, Twox64Concat, PoolId, ()>;
 
 	#[pallet::storage]
-	#[pallet::getter(fn boost_voting_pools)]
 	pub type BoostVotingPools<T: Config> = StorageMap<_, Twox64Concat, PoolId, BalanceOf<T>>;
 
 	#[pallet::storage]
-	#[pallet::getter(fn boost_basic_rewards)]
 	pub type BoostBasicRewards<T: Config> =
 		StorageDoubleMap<_, Twox64Concat, PoolId, Twox64Concat, CurrencyIdOf<T>, BalanceOf<T>>;
 
@@ -332,7 +319,7 @@ pub mod pallet {
 					pool_info.basic_rewards.clone().iter_mut().for_each(
 						|(reward_currency_id, reward_amount)| {
 							if let Some(boost_basic_reward) =
-								Self::boost_basic_rewards(pid, reward_currency_id)
+								BoostBasicRewards::<T>::get(pid, reward_currency_id)
 							{
 								*reward_amount = reward_amount.saturating_add(boost_basic_reward);
 							}
@@ -369,7 +356,7 @@ pub mod pallet {
 				}
 			});
 
-			if n == Self::boost_pool_infos().end_round {
+			if n == BoostPoolInfos::<T>::get().end_round {
 				Self::end_boost_round_inner();
 				Self::auto_start_boost_round();
 			}
@@ -399,7 +386,7 @@ pub mod pallet {
 		) -> DispatchResult {
 			T::ControlOrigin::ensure_origin(origin)?;
 
-			let pid = Self::pool_next_id();
+			let pid = PoolNextId::<T>::get();
 			let keeper = T::Keeper::get().into_sub_account_truncating(pid);
 			let reward_issuer = T::RewardIssuer::get().into_sub_account_truncating(pid);
 			let basic_token = *tokens_proportion.get(0).ok_or(Error::<T>::NotNullable)?;
@@ -449,7 +436,7 @@ pub mod pallet {
 		) -> DispatchResult {
 			let exchanger = ensure_signed(origin)?;
 
-			let mut pool_info = Self::pool_infos(&pid).ok_or(Error::<T>::PoolDoesNotExist)?;
+			let mut pool_info = PoolInfos::<T>::get(&pid).ok_or(Error::<T>::PoolDoesNotExist)?;
 
 			match if_gauge {
 				true => {
@@ -500,7 +487,7 @@ pub mod pallet {
 			// Check origin
 			let exchanger = ensure_signed(origin)?;
 
-			let mut pool_info = Self::pool_infos(&pid).ok_or(Error::<T>::PoolDoesNotExist)?;
+			let mut pool_info = PoolInfos::<T>::get(&pid).ok_or(Error::<T>::PoolDoesNotExist)?;
 			ensure!(
 				pool_info.state == PoolState::Ongoing || pool_info.state == PoolState::Charged,
 				Error::<T>::InvalidPoolState
@@ -543,14 +530,14 @@ pub mod pallet {
 			// Check origin
 			let exchanger = ensure_signed(origin)?;
 
-			let pool_info = Self::pool_infos(&pid).ok_or(Error::<T>::PoolDoesNotExist)?;
+			let pool_info = PoolInfos::<T>::get(&pid).ok_or(Error::<T>::PoolDoesNotExist)?;
 			ensure!(
 				pool_info.state == PoolState::Ongoing ||
 					pool_info.state == PoolState::Charged ||
 					pool_info.state == PoolState::Dead,
 				Error::<T>::InvalidPoolState
 			);
-			let share_info = Self::shares_and_withdrawn_rewards(&pid, &exchanger)
+			let share_info = SharesAndWithdrawnRewards::<T>::get(&pid, &exchanger)
 				.ok_or(Error::<T>::ShareInfoNotExists)?;
 			ensure!(
 				share_info.withdraw_list.len() < pool_info.withdraw_limit_count.into(),
@@ -570,14 +557,14 @@ pub mod pallet {
 			// Check origin
 			let exchanger = ensure_signed(origin)?;
 
-			let pool_info = Self::pool_infos(&pid).ok_or(Error::<T>::PoolDoesNotExist)?;
+			let pool_info = PoolInfos::<T>::get(&pid).ok_or(Error::<T>::PoolDoesNotExist)?;
 			ensure!(
 				pool_info.state == PoolState::Ongoing || pool_info.state == PoolState::Dead,
 				Error::<T>::InvalidPoolState
 			);
 
 			let current_block_number: BlockNumberFor<T> = frame_system::Pallet::<T>::block_number();
-			let share_info = Self::shares_and_withdrawn_rewards(&pid, &exchanger)
+			let share_info = SharesAndWithdrawnRewards::<T>::get(&pid, &exchanger)
 				.ok_or(Error::<T>::ShareInfoNotExists)?;
 			ensure!(
 				share_info.claim_last_block.saturating_add(pool_info.claim_limit_time) <=
@@ -598,7 +585,7 @@ pub mod pallet {
 			// Check origin
 			let exchanger = ensure_signed(origin)?;
 
-			let pool_info = Self::pool_infos(&pid).ok_or(Error::<T>::PoolDoesNotExist)?;
+			let pool_info = PoolInfos::<T>::get(&pid).ok_or(Error::<T>::PoolDoesNotExist)?;
 			Self::process_withdraw_list(&exchanger, pid, &pool_info, false)?;
 
 			Self::deposit_event(Event::WithdrawClaimed { who: exchanger, pid });
@@ -610,7 +597,7 @@ pub mod pallet {
 		pub fn force_retire_pool(origin: OriginFor<T>, pid: PoolId) -> DispatchResult {
 			T::ControlOrigin::ensure_origin(origin)?;
 
-			let mut pool_info = Self::pool_infos(&pid).ok_or(Error::<T>::PoolDoesNotExist)?;
+			let mut pool_info = PoolInfos::<T>::get(&pid).ok_or(Error::<T>::PoolDoesNotExist)?;
 			ensure!(pool_info.state == PoolState::Dead, Error::<T>::InvalidPoolState);
 			let withdraw_limit_time = BlockNumberFor::<T>::default();
 			let retire_limit = RetireLimit::<T>::get();
@@ -629,7 +616,7 @@ pub mod pallet {
 			if all_retired {
 				if let Some(ref gid) = pool_info.gauge {
 					let mut gauge_pool_info =
-						Self::gauge_pool_infos(gid).ok_or(Error::<T>::GaugePoolNotExist)?;
+						GaugePoolInfos::<T>::get(gid).ok_or(Error::<T>::GaugePoolNotExist)?;
 					gauge_pool_info.gauge_state = GaugeState::Unbond;
 					GaugePoolInfos::<T>::insert(&gid, gauge_pool_info);
 				}
@@ -661,7 +648,7 @@ pub mod pallet {
 		pub fn close_pool(origin: OriginFor<T>, pid: PoolId) -> DispatchResult {
 			T::ControlOrigin::ensure_origin(origin)?;
 
-			let mut pool_info = Self::pool_infos(&pid).ok_or(Error::<T>::PoolDoesNotExist)?;
+			let mut pool_info = PoolInfos::<T>::get(&pid).ok_or(Error::<T>::PoolDoesNotExist)?;
 			ensure!(pool_info.state == PoolState::Ongoing, Error::<T>::InvalidPoolState);
 			pool_info.state = PoolState::Dead;
 			PoolInfos::<T>::insert(&pid, pool_info);
@@ -685,7 +672,7 @@ pub mod pallet {
 		) -> DispatchResult {
 			T::ControlOrigin::ensure_origin(origin)?;
 
-			let mut pool_info = Self::pool_infos(&pid).ok_or(Error::<T>::PoolDoesNotExist)?;
+			let mut pool_info = PoolInfos::<T>::get(&pid).ok_or(Error::<T>::PoolDoesNotExist)?;
 			ensure!(pool_info.state == PoolState::Retired, Error::<T>::InvalidPoolState);
 			if let Some(basic_rewards) = basic_rewards {
 				let basic_rewards_map: BTreeMap<CurrencyIdOf<T>, BalanceOf<T>> =
@@ -728,7 +715,7 @@ pub mod pallet {
 		pub fn kill_pool(origin: OriginFor<T>, pid: PoolId) -> DispatchResult {
 			T::ControlOrigin::ensure_origin(origin)?;
 
-			let pool_info = Self::pool_infos(&pid).ok_or(Error::<T>::PoolDoesNotExist)?;
+			let pool_info = PoolInfos::<T>::get(&pid).ok_or(Error::<T>::PoolDoesNotExist)?;
 			ensure!(
 				pool_info.state == PoolState::Retired || pool_info.state == PoolState::UnCharged,
 				Error::<T>::InvalidPoolState
@@ -754,7 +741,7 @@ pub mod pallet {
 		) -> DispatchResult {
 			T::ControlOrigin::ensure_origin(origin)?;
 
-			let mut pool_info = Self::pool_infos(&pid).ok_or(Error::<T>::PoolDoesNotExist)?;
+			let mut pool_info = PoolInfos::<T>::get(&pid).ok_or(Error::<T>::PoolDoesNotExist)?;
 			ensure!(
 				pool_info.state == PoolState::Retired ||
 					pool_info.state == PoolState::Ongoing ||
@@ -922,7 +909,7 @@ pub mod pallet {
 
 impl<T: Config> FarmingInfo<BalanceOf<T>, CurrencyIdOf<T>> for Pallet<T> {
 	fn get_token_shares(pool_id: PoolId, currency_id: CurrencyIdOf<T>) -> BalanceOf<T> {
-		if let Some(pool_info) = Self::pool_infos(&pool_id) {
+		if let Some(pool_info) = PoolInfos::<T>::get(&pool_id) {
 			if let Some(token_proportion_value) = pool_info.tokens_proportion.get(&currency_id) {
 				let native_amount =
 					pool_info.basic_token.1.saturating_reciprocal_mul(pool_info.total_shares);
diff --git a/pallets/farming/src/tests.rs b/pallets/farming/src/tests.rs
index a114c4467..7c6a9e765 100644
--- a/pallets/farming/src/tests.rs
+++ b/pallets/farming/src/tests.rs
@@ -28,7 +28,7 @@ use frame_support::{assert_err, assert_ok};
 fn claim() {
 	ExtBuilder::default().one_hundred_for_alice_n_bob().build().execute_with(|| {
 		let (pid, _tokens) = init_no_gauge();
-		// assert_eq!(Farming::shares_and_withdrawn_rewards(pid, &ALICE), ShareInfo::default());
+		// assert_eq!(SharesAndWithdrawnRewards::<Runtime>::get(pid, &ALICE), ShareInfo::default());
 		assert_ok!(Farming::set_retire_limit(RuntimeOrigin::signed(ALICE), 10));
 		assert_err!(
 			Farming::claim(RuntimeOrigin::signed(ALICE), pid),
@@ -85,7 +85,7 @@ fn deposit() {
 			gauge_last_block: 0,
 			gauge_state: GaugeState::Bonded,
 		};
-		assert_eq!(Farming::gauge_pool_infos(0), Some(gauge_pool_info2));
+		assert_eq!(GaugePoolInfos::<Runtime>::get(0), Some(gauge_pool_info2));
 		Farming::on_initialize(0);
 		Farming::on_initialize(0);
 		System::set_block_number(System::block_number() + 1000);
@@ -118,7 +118,7 @@ fn withdraw() {
 		assert_ok!(Farming::withdraw_claim(RuntimeOrigin::signed(ALICE), pid));
 		assert_eq!(Tokens::free_balance(KSM, &ALICE), 4166);
 		assert_ok!(Farming::claim(RuntimeOrigin::signed(ALICE), pid));
-		assert_eq!(Farming::shares_and_withdrawn_rewards(pid, &ALICE), None);
+		assert_eq!(SharesAndWithdrawnRewards::<Runtime>::get(pid, &ALICE), None);
 		assert_eq!(Tokens::free_balance(KSM, &ALICE), 4166);
 		let ed = <Runtime as Config>::MultiCurrency::minimum_balance(KSM);
 		assert_eq!(Tokens::free_balance(KSM, &TREASURY_ACCOUNT), ed);
@@ -130,7 +130,7 @@ fn gauge() {
 	ExtBuilder::default().one_hundred_for_alice_n_bob().build().execute_with(|| {
 		let (pid, tokens) = init_gauge();
 		assert_eq!(Tokens::free_balance(KSM, &ALICE), 2000);
-		if let Some(gauge_pool_infos) = Farming::gauge_pool_infos(0) {
+		if let Some(gauge_pool_infos) = GaugePoolInfos::<Runtime>::get(0) {
 			assert_eq!(
 				gauge_pool_infos.rewards,
 				BTreeMap::<
@@ -170,7 +170,7 @@ fn gauge_withdraw() {
 	ExtBuilder::default().one_hundred_for_alice_n_bob().build().execute_with(|| {
 		let (pid, _tokens) = init_gauge();
 		assert_eq!(Tokens::free_balance(KSM, &ALICE), 2000);
-		if let Some(gauge_pool_infos) = Farming::gauge_pool_infos(0) {
+		if let Some(gauge_pool_infos) = GaugePoolInfos::<Runtime>::get(0) {
 			assert_eq!(gauge_pool_infos.gauge_amount, 0)
 		};
 		Farming::on_initialize(0);
@@ -181,7 +181,7 @@ fn gauge_withdraw() {
 		System::set_block_number(System::block_number() + 1000);
 		assert_ok!(Farming::gauge_withdraw(RuntimeOrigin::signed(ALICE), pid));
 		assert_eq!(Tokens::free_balance(KSM, &ALICE), 21017);
-		if let Some(gauge_pool_infos) = Farming::gauge_pool_infos(0) {
+		if let Some(gauge_pool_infos) = GaugePoolInfos::<Runtime>::get(0) {
 			assert_eq!(gauge_pool_infos.gauge_amount, 0)
 		};
 	})
@@ -202,7 +202,7 @@ fn retire() {
 		System::set_block_number(System::block_number() + 1000);
 		assert_ok!(Farming::force_retire_pool(RuntimeOrigin::signed(ALICE), pid));
 		assert_eq!(Tokens::free_balance(KSM, &ALICE), 3000);
-		assert_eq!(Farming::shares_and_withdrawn_rewards(pid, &ALICE), None);
+		assert_eq!(SharesAndWithdrawnRewards::<Runtime>::get(pid, &ALICE), None);
 	})
 }
 
@@ -255,8 +255,8 @@ fn reset() {
 			claim_limit_time: Default::default(),
 			withdraw_limit_count: 5,
 		};
-		assert_eq!(Farming::pool_infos(0), Some(pool_infos));
-		assert_eq!(Farming::gauge_pool_infos(1), None);
+		assert_eq!(PoolInfos::<Runtime>::get(0), Some(pool_infos));
+		assert_eq!(GaugePoolInfos::<Runtime>::get(1), None);
 		assert_eq!(Tokens::free_balance(KSM, &ALICE), 4018);
 		let charge_rewards = vec![(KSM, 300000)];
 		assert_ok!(Farming::charge(RuntimeOrigin::signed(BOB), pid, charge_rewards, false));
@@ -377,7 +377,7 @@ fn create_farming_pool() {
 			6,
 			5
 		));
-		if let Some(pool_infos) = Farming::pool_infos(0) {
+		if let Some(pool_infos) = PoolInfos::<Runtime>::get(0) {
 			assert_eq!(pool_infos.state, PoolState::UnCharged)
 		};
 		assert_ok!(Farming::kill_pool(RuntimeOrigin::signed(ALICE), 0));
@@ -385,7 +385,7 @@ fn create_farming_pool() {
 		let pid = 1;
 		let charge_rewards = vec![(KSM, 300000)];
 		assert_ok!(Farming::charge(RuntimeOrigin::signed(BOB), pid, charge_rewards, false));
-		if let Some(pool_infos) = Farming::pool_infos(0) {
+		if let Some(pool_infos) = PoolInfos::<Runtime>::get(0) {
 			assert_eq!(pool_infos.total_shares, 0);
 			assert_eq!(pool_infos.min_deposit_to_start, 2);
 			assert_eq!(pool_infos.state, PoolState::Charged)
@@ -398,7 +398,7 @@ fn create_farming_pool() {
 		assert_ok!(Farming::deposit(RuntimeOrigin::signed(ALICE), pid, tokens, Some((100, 100))));
 		Farming::on_initialize(System::block_number() + 3);
 		Farming::on_initialize(0);
-		if let Some(pool_infos) = Farming::pool_infos(0) {
+		if let Some(pool_infos) = PoolInfos::<Runtime>::get(0) {
 			assert_eq!(pool_infos.total_shares, 1000);
 			assert_eq!(pool_infos.min_deposit_to_start, 2);
 			assert_eq!(pool_infos.state, PoolState::Ongoing)

From 72b00f4e4e1fef61db8ab5cce4d8036ed89b8bfd Mon Sep 17 00:00:00 2001
From: MJLNSN <96321798+MJLNSN@users.noreply.github.com>
Date: Mon, 30 Sep 2024 11:40:58 +0800
Subject: [PATCH 12/31] Removed getters in vesting. (#1447)

* Removed getters in vesting

* updated

* updated
---
 pallets/vesting/src/lib.rs   | 29 ++++++------
 pallets/vesting/src/tests.rs | 89 +++++++++++++++++++-----------------
 2 files changed, 59 insertions(+), 59 deletions(-)

diff --git a/pallets/vesting/src/lib.rs b/pallets/vesting/src/lib.rs
index cc2d4001d..c70f2754a 100644
--- a/pallets/vesting/src/lib.rs
+++ b/pallets/vesting/src/lib.rs
@@ -198,18 +198,15 @@ pub mod pallet {
 
 	/// Start at
 	#[pallet::storage]
-	#[pallet::getter(fn vesting_start_at)]
 	pub(super) type VestingStartAt<T: Config> = StorageValue<_, BlockNumberFor<T>>;
 
 	/// Cliff vesting
 	#[pallet::storage]
-	#[pallet::getter(fn cliffs)]
 	pub(super) type Cliff<T: Config> =
 		StorageMap<_, Blake2_128Concat, T::AccountId, BlockNumberFor<T>>;
 
 	/// Information regarding the vesting of a given account.
 	#[pallet::storage]
-	#[pallet::getter(fn vesting)]
 	pub type Vesting<T: Config> = StorageMap<
 		_,
 		Blake2_128Concat,
@@ -425,7 +422,7 @@ pub mod pallet {
 			let target = T::Lookup::lookup(target)?;
 			let index = index as usize;
 			Self::do_vest(target.clone())?;
-			let schedules = Self::vesting(&target).ok_or(Error::<T>::NotVesting)?;
+			let schedules = Vesting::<T>::get(&target).ok_or(Error::<T>::NotVesting)?;
 			ensure!(schedules.len() > index, Error::<T>::ScheduleIndexOutOfBounds);
 			ensure!(schedules[index].per_block() != per_block, Error::<T>::SamePerBlock);
 
@@ -509,7 +506,7 @@ pub mod pallet {
 			let schedule1_index = schedule1_index as usize;
 			let schedule2_index = schedule2_index as usize;
 
-			let schedules = Self::vesting(&who).ok_or(Error::<T>::NotVesting)?;
+			let schedules = Vesting::<T>::get(&who).ok_or(Error::<T>::NotVesting)?;
 			let merge_action =
 				VestingAction::Merge { index1: schedule1_index, index2: schedule2_index };
 
@@ -542,9 +539,9 @@ impl<T: Config> Pallet<T> {
 		schedule2: VestingInfo<BalanceOf<T>, BlockNumberFor<T>>,
 	) -> Option<VestingInfo<BalanceOf<T>, BlockNumberFor<T>>> {
 		let schedule1_start_at =
-			Self::vesting_start_at().map(|st| st.saturating_add(schedule1.starting_block()));
+			VestingStartAt::<T>::get().map(|st| st.saturating_add(schedule1.starting_block()));
 		let schedule2_start_at =
-			Self::vesting_start_at().map(|st| st.saturating_add(schedule2.starting_block()));
+			VestingStartAt::<T>::get().map(|st| st.saturating_add(schedule2.starting_block()));
 		let schedule1_ending_block = schedule1.ending_block_as_balance::<T::BlockNumberToBalance>();
 		let schedule2_ending_block = schedule2.ending_block_as_balance::<T::BlockNumberToBalance>();
 		let now_as_balance = T::BlockNumberToBalance::convert(now);
@@ -650,8 +647,8 @@ impl<T: Config> Pallet<T> {
 		let filtered_schedules = action
 			.pick_schedules::<T>(schedules)
 			.filter(|schedule| {
-				let start_at =
-					Self::vesting_start_at().map(|st| st.saturating_add(schedule.starting_block()));
+				let start_at = VestingStartAt::<T>::get()
+					.map(|st| st.saturating_add(schedule.starting_block()));
 				let locked_now = schedule.locked_at::<T::BlockNumberToBalance>(now, start_at);
 				let keep = !locked_now.is_zero();
 				if keep {
@@ -700,7 +697,7 @@ impl<T: Config> Pallet<T> {
 
 	/// Unlock any vested funds of `who`.
 	fn do_vest(who: T::AccountId) -> DispatchResult {
-		let schedules = Self::vesting(&who).ok_or(Error::<T>::NotVesting)?;
+		let schedules = Vesting::<T>::get(&who).ok_or(Error::<T>::NotVesting)?;
 
 		let (schedules, locked_now) =
 			Self::exec_action(schedules.to_vec(), VestingAction::Passive)?;
@@ -736,7 +733,7 @@ impl<T: Config> Pallet<T> {
 					// 1) need to add it to the accounts vesting schedule collection,
 					schedules.push(new_schedule);
 					// (we use `locked_at` in case this is a schedule that started in the past)
-					let start_at = Self::vesting_start_at()
+					let start_at = VestingStartAt::<T>::get()
 						.map(|st| st.saturating_add(new_schedule.starting_block()));
 					let new_schedule_locked =
 						new_schedule.locked_at::<T::BlockNumberToBalance>(now, start_at);
@@ -767,11 +764,11 @@ where
 
 	/// Get the amount that is currently being vested and cannot be transferred out of this account.
 	fn vesting_balance(who: &T::AccountId) -> Option<BalanceOf<T>> {
-		if let Some(v) = Self::vesting(who) {
+		if let Some(v) = Vesting::<T>::get(who) {
 			let now = <frame_system::Pallet<T>>::block_number();
 			let total_locked_now = v.iter().fold(Zero::zero(), |total, schedule| {
-				let start_at =
-					Self::vesting_start_at().map(|st| st.saturating_add(schedule.starting_block()));
+				let start_at = VestingStartAt::<T>::get()
+					.map(|st| st.saturating_add(schedule.starting_block()));
 				schedule
 					.locked_at::<T::BlockNumberToBalance>(now, start_at)
 					.saturating_add(total)
@@ -810,7 +807,7 @@ where
 			return Err(Error::<T>::InvalidScheduleParams.into());
 		};
 
-		let mut schedules = Self::vesting(who).unwrap_or_default();
+		let mut schedules = Vesting::<T>::get(who).unwrap_or_default();
 
 		// NOTE: we must push the new schedule so that `exec_action`
 		// will give the correct new locked amount.
@@ -848,7 +845,7 @@ where
 
 	/// Remove a vesting schedule for a given account.
 	fn remove_vesting_schedule(who: &T::AccountId, schedule_index: u32) -> DispatchResult {
-		let schedules = Self::vesting(who).ok_or(Error::<T>::NotVesting)?;
+		let schedules = Vesting::<T>::get(who).ok_or(Error::<T>::NotVesting)?;
 		let remove_action = VestingAction::Remove { index: schedule_index as usize };
 
 		let (schedules, locked_now) = Self::exec_action(schedules.to_vec(), remove_action)?;
diff --git a/pallets/vesting/src/tests.rs b/pallets/vesting/src/tests.rs
index 29aad6a74..ce02da117 100644
--- a/pallets/vesting/src/tests.rs
+++ b/pallets/vesting/src/tests.rs
@@ -21,7 +21,10 @@ use frame_system::RawOrigin;
 use sp_runtime::{traits::Identity, TokenError};
 
 use super::{Vesting as VestingStorage, *};
-use crate::mock::{Balances, ExtBuilder, System, Test, Vesting};
+use crate::{
+	mock::{Balances, ExtBuilder, System, Test, Vesting},
+	Vesting as vesting,
+};
 
 const ED: u64 = 1000;
 
@@ -71,9 +74,9 @@ fn check_vesting_status() {
 			CHAR_PER_BLOCK,   // Vesting over 20 blocks
 			10u64,
 		);
-		assert_eq!(Vesting::vesting(&ALICE).unwrap().to_vec(), vec![user1_vesting_schedule]);
-		assert_eq!(Vesting::vesting(&BOB).unwrap().to_vec(), vec![user2_vesting_schedule]);
-		assert_eq!(Vesting::vesting(&CHAR).unwrap().to_vec(), vec![user3_vesting_schedule]);
+		assert_eq!(vesting::<Test>::get(&ALICE).unwrap().to_vec(), vec![user1_vesting_schedule]);
+		assert_eq!(vesting::<Test>::get(&BOB).unwrap().to_vec(), vec![user2_vesting_schedule]);
+		assert_eq!(vesting::<Test>::get(&CHAR).unwrap().to_vec(), vec![user3_vesting_schedule]);
 	});
 }
 
@@ -160,7 +163,7 @@ fn vested_transfer_should_work() {
 			user1_vesting_schedule_2
 		));
 		assert_eq!(
-			Vesting::vesting(&ALICE).unwrap().to_vec(),
+			vesting::<Test>::get(&ALICE).unwrap().to_vec(),
 			vec![user1_vesting_schedule_1, user1_vesting_schedule_2]
 		);
 	})
@@ -208,7 +211,7 @@ fn do_vest_with_cliff_should_work() {
 		//set start_at to 0
 		assert_ok!(Vesting::init_vesting_start_at(RawOrigin::Root.into(), 0));
 		assert_ok!(Vesting::force_set_cliff(RawOrigin::Root.into(), ALICE, 4));
-		assert_eq!(Vesting::cliffs(ALICE), Some(4));
+		assert_eq!(Cliff::<Test>::get(ALICE), Some(4));
 
 		//set block to 4
 		System::set_block_number(4);
@@ -283,7 +286,7 @@ fn set_vesting_per_block_should_work() {
 
 		//check result start_at 10 > now 5 => 10 start_at
 		let user_vesting_schedule_1 = VestingInfo::new(20000, 100, 10);
-		assert_eq!(Vesting::vesting(&BOB).unwrap().to_vec(), vec![user_vesting_schedule_1]);
+		assert_eq!(vesting::<Test>::get(&BOB).unwrap().to_vec(), vec![user_vesting_schedule_1]);
 
 		//set block to 15
 		System::set_block_number(15);
@@ -298,7 +301,7 @@ fn set_vesting_per_block_should_work() {
 		//old_start_at = old_start_block 10 + absolute_start 0
 		//remained_vesting = 20000 - 5 * 100
 		let user_vesting_schedule_2 = VestingInfo::new(20000 - 5 * 100, 10, 15);
-		assert_eq!(Vesting::vesting(&BOB).unwrap().to_vec(), vec![user_vesting_schedule_2]);
+		assert_eq!(vesting::<Test>::get(&BOB).unwrap().to_vec(), vec![user_vesting_schedule_2]);
 		let bob_locked_2 = Balances::locks(BOB).to_vec()[0].amount;
 		assert_eq!(bob_locked_1 - 5 * 100, bob_locked_2);
 	})
@@ -323,7 +326,7 @@ fn set_vesting_per_block_with_start_at_should_work() {
 
 		//check result old_start_at 12 > now 5 => 10 start_at
 		let user_vesting_schedule_1 = VestingInfo::new(20000, 100, 10);
-		assert_eq!(Vesting::vesting(&BOB).unwrap().to_vec(), vec![user_vesting_schedule_1]);
+		assert_eq!(vesting::<Test>::get(&BOB).unwrap().to_vec(), vec![user_vesting_schedule_1]);
 
 		//set block to 15
 		System::set_block_number(15);
@@ -338,7 +341,7 @@ fn set_vesting_per_block_with_start_at_should_work() {
 		//old_start_at 12 < now 15 => now 15 - absolute_start 2 = 13
 		//remained_vesting = 20000 - 3 * 100
 		let user_vesting_schedule_2 = VestingInfo::new(20000 - 3 * 100, 10, 13);
-		assert_eq!(Vesting::vesting(&BOB).unwrap().to_vec(), vec![user_vesting_schedule_2]);
+		assert_eq!(vesting::<Test>::get(&BOB).unwrap().to_vec(), vec![user_vesting_schedule_2]);
 		let bob_locked_2 = Balances::locks(BOB).to_vec()[0].amount;
 		assert_eq!(bob_locked_1 - 3 * 100, bob_locked_2);
 	})
@@ -365,7 +368,7 @@ fn repeatedly_set_vesting_per_block_should_work() {
 			user_vesting_schedule_3
 		));
 		assert_eq!(
-			Vesting::vesting(&BOB).unwrap().to_vec(),
+			vesting::<Test>::get(&BOB).unwrap().to_vec(),
 			vec![user_vesting_schedule_1, user_vesting_schedule_2, user_vesting_schedule_3]
 		);
 
@@ -388,7 +391,7 @@ fn repeatedly_set_vesting_per_block_should_work() {
 		//check result old_start_at 12 > now 5 => 12 start_at
 		let new_user_vesting_schedule_1 = VestingInfo::new(10000, 100, 12);
 		assert_eq!(
-			Vesting::vesting(&BOB).unwrap().to_vec(),
+			vesting::<Test>::get(&BOB).unwrap().to_vec(),
 			vec![user_vesting_schedule_1, new_user_vesting_schedule_1, user_vesting_schedule_3]
 		);
 
@@ -406,7 +409,7 @@ fn repeatedly_set_vesting_per_block_should_work() {
 		//remained_vesting = 20000 - 3 * 1000
 		let new_user_vesting_schedule_2 = VestingInfo::new(20000 - 3 * 1000, 10, 13);
 		assert_eq!(
-			Vesting::vesting(&BOB).unwrap().to_vec(),
+			vesting::<Test>::get(&BOB).unwrap().to_vec(),
 			vec![new_user_vesting_schedule_2, new_user_vesting_schedule_1, user_vesting_schedule_3]
 		);
 
@@ -445,7 +448,7 @@ fn merge_schedules_has_not_started_should_work() {
 			user_vesting_schedule_2
 		));
 		assert_eq!(
-			Vesting::vesting(&BOB).unwrap().to_vec(),
+			vesting::<Test>::get(&BOB).unwrap().to_vec(),
 			vec![user_vesting_schedule_1, user_vesting_schedule_2]
 		);
 
@@ -460,7 +463,7 @@ fn merge_schedules_has_not_started_should_work() {
 		assert_ok!(Vesting::merge_schedules(RawOrigin::Signed(BOB).into(), 0, 1));
 
 		assert_eq!(
-			Vesting::vesting(&BOB).unwrap().to_vec(),
+			vesting::<Test>::get(&BOB).unwrap().to_vec(),
 			vec![VestingInfo::new(BOB_INIT_LOCKED * 2, 2000, 12)]
 		);
 		assert_eq!(40000, Balances::locks(BOB).to_vec()[0].amount);
@@ -482,7 +485,7 @@ fn merge_ongoing_schedules_should_work() {
 			user_vesting_schedule_2
 		));
 		assert_eq!(
-			Vesting::vesting(&BOB).unwrap().to_vec(),
+			vesting::<Test>::get(&BOB).unwrap().to_vec(),
 			vec![user_vesting_schedule_1, user_vesting_schedule_2]
 		);
 
@@ -497,7 +500,7 @@ fn merge_ongoing_schedules_should_work() {
 		assert_ok!(Vesting::merge_schedules(RawOrigin::Signed(BOB).into(), 0, 1));
 
 		assert_eq!(
-			Vesting::vesting(&BOB).unwrap().to_vec(),
+			vesting::<Test>::get(&BOB).unwrap().to_vec(),
 			vec![VestingInfo::new(BOB_INIT_LOCKED, 1000, 40)]
 		);
 		assert_eq!(12000, Balances::locks(BOB).to_vec()[0].amount);
@@ -519,7 +522,7 @@ fn merge_finished_schedules_should_work() {
 			user_vesting_schedule_2
 		));
 		assert_eq!(
-			Vesting::vesting(&BOB).unwrap().to_vec(),
+			vesting::<Test>::get(&BOB).unwrap().to_vec(),
 			vec![user_vesting_schedule_1, user_vesting_schedule_2]
 		);
 
@@ -530,7 +533,7 @@ fn merge_finished_schedules_should_work() {
 		//None
 		assert_ok!(Vesting::merge_schedules(RawOrigin::Signed(BOB).into(), 0, 1));
 
-		assert_eq!(Vesting::vesting(&BOB), None);
+		assert_eq!(vesting::<Test>::get(&BOB), None);
 		assert_eq!(0, Balances::locks(BOB).to_vec().len());
 	})
 }
@@ -544,12 +547,12 @@ fn merge_schedules_that_have_not_started() {
 			ED, // Vest over 20 blocks.
 			10,
 		);
-		assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]);
+		assert_eq!(vesting::<Test>::get(&2).unwrap(), vec![sched0]);
 		assert_eq!(Balances::usable_balance(&2), 0);
 
 		// Add a schedule that is identical to the one that already exists.
 		assert_ok!(Vesting::vested_transfer(Some(4).into(), 2, sched0));
-		assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched0]);
+		assert_eq!(vesting::<Test>::get(&2).unwrap(), vec![sched0, sched0]);
 		assert_eq!(Balances::usable_balance(&2), 0);
 		assert_ok!(Vesting::merge_schedules(Some(2).into(), 0, 1));
 
@@ -560,7 +563,7 @@ fn merge_schedules_that_have_not_started() {
 			sched0.per_block() * 2,
 			10, // Starts at the block the schedules are merged/
 		);
-		assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched1]);
+		assert_eq!(vesting::<Test>::get(&2).unwrap(), vec![sched1]);
 
 		assert_eq!(Balances::usable_balance(&2), 0);
 	});
@@ -577,7 +580,7 @@ fn merge_ongoing_schedules() {
 			ED, // Vest over 20 blocks.
 			10,
 		);
-		assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]);
+		assert_eq!(vesting::<Test>::get(&2).unwrap(), vec![sched0]);
 
 		let sched1 = VestingInfo::new(
 			ED * 10,
@@ -585,10 +588,10 @@ fn merge_ongoing_schedules() {
 			sched0.starting_block() + 5, // Start at block 15.
 		);
 		assert_ok!(Vesting::vested_transfer(Some(4).into(), 2, sched1));
-		assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched1]);
+		assert_eq!(vesting::<Test>::get(&2).unwrap(), vec![sched0, sched1]);
 
 		// assert_ok!(Vesting::merge_schedules(Some(2).into(), 0, 1));
-		// assert_eq!(Vesting::vesting(&2).unwrap(), vec![]);
+		// assert_eq!(vesting::<Test>::get(&2).unwrap(), vec![]);
 
 		// Got to half way through the second schedule where both schedules are actively vesting.
 		let cur_block = 20;
@@ -620,7 +623,7 @@ fn merge_ongoing_schedules() {
 		let sched2_per_block = sched2_locked / sched2_duration;
 
 		let sched2 = VestingInfo::new(sched2_locked, sched2_per_block, cur_block);
-		assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched2]);
+		assert_eq!(vesting::<Test>::get(&2).unwrap(), vec![sched2]);
 
 		// And just to double check, we assert the new merged schedule we be cleaned up as expected.
 		System::set_block_number(30);
@@ -663,7 +666,7 @@ fn merging_shifts_other_schedules_index() {
 		);
 
 		// Account 3 starts out with no schedules,
-		assert_eq!(Vesting::vesting(&3), None);
+		assert_eq!(vesting::<Test>::get(&3), None);
 		// and some usable balance.
 		let usable_balance = Balances::usable_balance(&3);
 		assert_eq!(usable_balance, 30 * ED);
@@ -677,7 +680,7 @@ fn merging_shifts_other_schedules_index() {
 		assert_ok!(Vesting::vested_transfer(Some(4).into(), 3, sched2));
 
 		// With no schedules vested or merged they are in the order they are created
-		assert_eq!(Vesting::vesting(&3).unwrap(), vec![sched0, sched1, sched2]);
+		assert_eq!(vesting::<Test>::get(&3).unwrap(), vec![sched0, sched1, sched2]);
 		// and the usable balance has not changed.
 		assert_eq!(usable_balance, Balances::usable_balance(&3));
 
@@ -698,7 +701,7 @@ fn merging_shifts_other_schedules_index() {
 		let sched3 = VestingInfo::new(sched3_locked, sched3_per_block, sched3_start);
 
 		// The not touched schedule moves left and the new merged schedule is appended.
-		assert_eq!(Vesting::vesting(&3).unwrap(), vec![sched1, sched3]);
+		assert_eq!(vesting::<Test>::get(&3).unwrap(), vec![sched1, sched3]);
 		// The usable balance hasn't changed since none of the schedules have started.
 		assert_eq!(Balances::usable_balance(&3), usable_balance);
 	});
@@ -716,7 +719,7 @@ fn merge_ongoing_and_yet_to_be_started_schedules() {
 			ED, // Vesting over 20 blocks
 			10,
 		);
-		assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]);
+		assert_eq!(vesting::<Test>::get(&2).unwrap(), vec![sched0]);
 
 		// Fast forward to half way through the life of sched1.
 		let mut cur_block =
@@ -769,7 +772,7 @@ fn merge_ongoing_and_yet_to_be_started_schedules() {
 		let sched2_per_block = sched2_locked / sched2_duration;
 
 		let sched2 = VestingInfo::new(sched2_locked, sched2_per_block, sched2_start);
-		assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched2]);
+		assert_eq!(vesting::<Test>::get(&2).unwrap(), vec![sched2]);
 	});
 }
 
@@ -785,7 +788,7 @@ fn merge_finished_and_ongoing_schedules() {
 			ED, // Vesting over 20 blocks.
 			10,
 		);
-		assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]);
+		assert_eq!(vesting::<Test>::get(&2).unwrap(), vec![sched0]);
 
 		let sched1 = VestingInfo::new(
 			ED * 40,
@@ -804,7 +807,7 @@ fn merge_finished_and_ongoing_schedules() {
 		assert_ok!(Vesting::vested_transfer(Some(3).into(), 2, sched2));
 
 		// The schedules are in expected order prior to merging.
-		assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched1, sched2]);
+		assert_eq!(vesting::<Test>::get(&2).unwrap(), vec![sched0, sched1, sched2]);
 
 		// Fast forward to sched0's end block.
 		let cur_block = sched0.ending_block_as_balance::<Identity>();
@@ -819,7 +822,7 @@ fn merge_finished_and_ongoing_schedules() {
 		// sched2 is now the first, since sched0 & sched1 get filtered out while "merging".
 		// sched1 gets treated like the new merged schedule by getting pushed onto back
 		// of the vesting schedules vec. Note: sched0 finished at the current block.
-		assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched2, sched1]);
+		assert_eq!(vesting::<Test>::get(&2).unwrap(), vec![sched2, sched1]);
 
 		// sched0 has finished, so its funds are fully unlocked.
 		let sched0_unlocked_now = sched0.locked();
@@ -850,7 +853,7 @@ fn merge_finishing_schedules_does_not_create_a_new_one() {
 			ED, // 20 block duration.
 			10,
 		);
-		assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]);
+		assert_eq!(vesting::<Test>::get(&2).unwrap(), vec![sched0]);
 
 		// Create sched1 and transfer it to account 2.
 		let sched1 = VestingInfo::new(
@@ -859,7 +862,7 @@ fn merge_finishing_schedules_does_not_create_a_new_one() {
 			10,
 		);
 		assert_ok!(Vesting::vested_transfer(Some(3).into(), 2, sched1));
-		assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched1]);
+		assert_eq!(vesting::<Test>::get(&2).unwrap(), vec![sched0, sched1]);
 
 		let all_scheds_end = sched0
 			.ending_block_as_balance::<Identity>()
@@ -893,7 +896,7 @@ fn merge_finished_and_yet_to_be_started_schedules() {
 			ED, // 20 block duration.
 			10, // Ends at block 30
 		);
-		assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]);
+		assert_eq!(vesting::<Test>::get(&2).unwrap(), vec![sched0]);
 
 		let sched1 = VestingInfo::new(
 			ED * 30,
@@ -901,7 +904,7 @@ fn merge_finished_and_yet_to_be_started_schedules() {
 			35,
 		);
 		assert_ok!(Vesting::vested_transfer(Some(13).into(), 2, sched1));
-		assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched1]);
+		assert_eq!(vesting::<Test>::get(&2).unwrap(), vec![sched0, sched1]);
 
 		let sched2 = VestingInfo::new(
 			ED * 40,
@@ -910,7 +913,7 @@ fn merge_finished_and_yet_to_be_started_schedules() {
 		);
 		// Add a 3rd schedule to demonstrate how sched1 shifts.
 		assert_ok!(Vesting::vested_transfer(Some(13).into(), 2, sched2));
-		assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched1, sched2]);
+		assert_eq!(vesting::<Test>::get(&2).unwrap(), vec![sched0, sched1, sched2]);
 
 		System::set_block_number(30);
 
@@ -925,7 +928,7 @@ fn merge_finished_and_yet_to_be_started_schedules() {
 
 		// sched0 is removed since it finished, and sched1 is removed and then pushed on the back
 		// because it is treated as the merged schedule
-		assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched2, sched1]);
+		assert_eq!(vesting::<Test>::get(&2).unwrap(), vec![sched2, sched1]);
 
 		// The usable balance is updated because merging fully unlocked sched0.
 		assert_eq!(Balances::usable_balance(&2), sched0.locked());
@@ -941,7 +944,7 @@ fn merge_schedules_throws_proper_errors() {
 			ED, // 20 block duration.
 			10,
 		);
-		assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]);
+		assert_eq!(vesting::<Test>::get(&2).unwrap(), vec![sched0]);
 
 		// Account 2 only has 1 vesting schedule.
 		assert_noop!(
@@ -950,12 +953,12 @@ fn merge_schedules_throws_proper_errors() {
 		);
 
 		// Account 4 has 0 vesting schedules.
-		assert_eq!(Vesting::vesting(&4), None);
+		assert_eq!(vesting::<Test>::get(&4), None);
 		assert_noop!(Vesting::merge_schedules(Some(4).into(), 0, 1), Error::<Test>::NotVesting);
 
 		// There are enough schedules to merge but an index is non-existent.
 		Vesting::vested_transfer(Some(3).into(), 2, sched0).unwrap();
-		assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched0]);
+		assert_eq!(vesting::<Test>::get(&2).unwrap(), vec![sched0, sched0]);
 		assert_noop!(
 			Vesting::merge_schedules(Some(2).into(), 0, 2),
 			Error::<Test>::ScheduleIndexOutOfBounds

From c97cdc22e58ee201948bd11929d0fba638aeef5d Mon Sep 17 00:00:00 2001
From: SunTiebing <87381708+SunTiebing@users.noreply.github.com>
Date: Mon, 30 Sep 2024 15:20:17 +0800
Subject: [PATCH 13/31] Feat/vtoken voting vbnc (#1442)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* Bifrost v0.12.0

* remove old migrations

* Fix vtokenVoting.removeDelegatorVote (#1288)

* add PollClass type

* add the calss parameter to the remove_delegator_vote method

* Add metadata hash (#1299)

* feat: 🎸 add buy-back

* Bifrost v0.10.001

* feat: 🎸 benchmark

* SLPx mint support commission id (#1261)

* Add vtoken exchange rate rpc (#1260)

* fix: 🐛 add event (#1263)

* add update_currency_metadata function (#1259)

* add update_currency_metadata function

* fix: 🐛 correct update_currency_metadata weight

* add the use of Vec (#1264)

* Add vtoken exchange rate rpc

* add the use of Vec

* Upgrade to Polkadot-SDK v1.7.0 (#1262)

* Bifrost v0.10.0

* fix: 🐛 clippy

* Fix chain spec (#1243)

* Upgrade to polkadot-v1.7.0

---------

Co-authored-by: SunTiebing <1045060705@qq.com>
Co-authored-by: Edwin Wang <lark930@gmail.com>

* Fix compile

* feat: 🎸 add metadata-hash-extension (#1265)

* feat: 🎸 add metadata-hash-extension

* Fix compile (#1266)

* Fix/fix vtoken voting unlock (#1267)

* update the exchange rate of vtokenminting of vtokenvoting test

* Resolve the frozen anomaly when unlocking

* Revert "feat: 🎸 add metadata-hash-extension (#1265)" (#1268)

This reverts commit 489fc9c6adeae44d23edf449e74fde3d6aa40bc3.

* rename the version number to 0.11.0

* Slp supports XCMv4 and reconstruct integration tests (#1272)

* Fix compile

* Reconstruct integration tests and slp supports XCMv4

* Fix slp construct_xcm_message

* Feat/slpx mint add commission (#1273)

* SLPx mint support commission id

* remove the channel_id parameter from the mint method

* add mint_with_channel_id method

* perform data migration for OrderQueue storage

* slpx: set the default value of channel_id to 0

* resolve conflicts

* change the location of the old data structure during storage migration

* Feat/add vtoken exchange rate rpc (#1274)

* Add vtoken exchange rate rpc

* add the use of Vec

* supplement the RPC logic && fix bugs

* adjust the RPC exchange rate precision to three decimal places

* fix clippy

* fix bug: storage migration anomaly (#1276)

* SLPx mint support commission id

* remove the channel_id parameter from the mint method

* add mint_with_channel_id method

* perform data migration for OrderQueue storage

* slpx: set the default value of channel_id to 0

* resolve conflicts

* change the location of the old data structure during storage migration

* fix bug: storage migration anomaly

* Slp removes refund (#1275)

* Slp removes refund

* Fix clippy

* Feat/add vtoken exchange rate rpc (#1277)

* Add vtoken exchange rate rpc

* add the use of Vec

* supplement the RPC logic && fix bugs

* adjust the RPC exchange rate precision to three decimal places

* fix clippy

* supplement omissions: adjust the RPC exchange rate precision to three decimal places

* Remove dmp queue (#1279)

* fix: 🐛 CheckMetadataHash to false

* fix: 🐛 update sp-api

* refactor: 💡 fmt

* fix: 🐛 add metadata-hash

* fix: 🐛 add feature metadata-hash

* fix: 🐛 rm metadata-hash feature

---------

Co-authored-by: SunTiebing <1045060705@qq.com>
Co-authored-by: SunTiebing <87381708+SunTiebing@users.noreply.github.com>
Co-authored-by: NingBo Wang <2536935847@qq.com>
Co-authored-by: Edwin Wang <lark930@gmail.com>

* refactor: 💡 update MaxTurnout and whitelisted_caller track (#1304)

* Allow to receive and send Ethereum assets (#1305)

* feat: 🎸 add buy-back

* Bifrost v0.10.001

* feat: 🎸 benchmark

* SLPx mint support commission id (#1261)

* Add vtoken exchange rate rpc (#1260)

* fix: 🐛 add event (#1263)

* add update_currency_metadata function (#1259)

* add update_currency_metadata function

* fix: 🐛 correct update_currency_metadata weight

* add the use of Vec (#1264)

* Add vtoken exchange rate rpc

* add the use of Vec

* Upgrade to Polkadot-SDK v1.7.0 (#1262)

* Bifrost v0.10.0

* fix: 🐛 clippy

* Fix chain spec (#1243)

* Upgrade to polkadot-v1.7.0

---------

Co-authored-by: SunTiebing <1045060705@qq.com>
Co-authored-by: Edwin Wang <lark930@gmail.com>

* feat: 🎸 add metadata-hash-extension (#1265)

* Fix compile (#1266)

* Fix/fix vtoken voting unlock (#1267)

* update the exchange rate of vtokenminting of vtokenvoting test

* Resolve the frozen anomaly when unlocking

* Revert "feat: 🎸 add metadata-hash-extension (#1265)" (#1268)

This reverts commit 489fc9c6adeae44d23edf449e74fde3d6aa40bc3.

* rename the version number to 0.11.0

* Slp supports XCMv4 and reconstruct integration tests (#1272)

* Fix compile

* Reconstruct integration tests and slp supports XCMv4

* Fix slp construct_xcm_message

* Feat/slpx mint add commission (#1273)

* SLPx mint support commission id

* remove the channel_id parameter from the mint method

* add mint_with_channel_id method

* perform data migration for OrderQueue storage

* slpx: set the default value of channel_id to 0

* resolve conflicts

* change the location of the old data structure during storage migration

* Feat/add vtoken exchange rate rpc (#1274)

* Add vtoken exchange rate rpc

* add the use of Vec

* supplement the RPC logic && fix bugs

* adjust the RPC exchange rate precision to three decimal places

* fix clippy

* fix bug: storage migration anomaly (#1276)

* SLPx mint support commission id

* remove the channel_id parameter from the mint method

* add mint_with_channel_id method

* perform data migration for OrderQueue storage

* slpx: set the default value of channel_id to 0

* resolve conflicts

* change the location of the old data structure during storage migration

* fix bug: storage migration anomaly

* Slp removes refund (#1275)

* Slp removes refund

* Fix clippy

* Allow to receive and send Ethereum assets

* Add constants

---------

Co-authored-by: yooml <ymlll0508@gmail.com>
Co-authored-by: SunTiebing <1045060705@qq.com>
Co-authored-by: SunTiebing <87381708+SunTiebing@users.noreply.github.com>
Co-authored-by: Edwin Wang <lark930@gmail.com>

* Disable supplement_fee_reserve (#1306)

* Remove call_switchgear and add tx_pause (#1308)

* Remove call_switchgear and add tx_pause

* Fix clippy

* Optimize flexible fee (#1307)

* Optimize flexible fee

* Fix bug

* Fix bug

* Add PalletId

* Add error handle

* feat: 🎸 add market-bond

* fix: 🐛 test-all

* fix: 🐛 try-runtime

* Add the channel_id field to the Minted event

* Upgrade to polkadot-v1.13.0 (#1312)

* Upgrade to polkadot-v1.13.0

* remove the warning

* Fix dep issues

* Upgrade to polkadot-v1.13.0

* supplement and upgrade the code

* Upgrade the new parts from v0.12.0

* Fix dep issues

* format Cargo.toml

* Modify the AddOrigin type of the fellowship in bifrost-polkadot

* Cancel the cross-in-out migration.

* fix clippy

---------

Co-authored-by: hqwangningbo <2536935847@qq.com>

* Use github dependencies (#1314)

* Fix flexible_fee TransferTo (#1315)

* Refactor code structure: extract the vote operation from the relaychain.

* Refactor code structure: extract the remove_vote operation from the relaychain.

* Move the XCM-related methods into the relaychain_agent.

* Move the call.rs into the relaychain_agent.

* vtokenvoting functionality supports vBNC

* Bifrost v0.13.0

* Remove getter in buy-back. (#1354)

* Bifrost v0.12.0

* remove old migrations

* Fix vtokenVoting.removeDelegatorVote (#1288)

* add PollClass type

* add the calss parameter to the remove_delegator_vote method

* Add metadata hash (#1299)

* feat: 🎸 add buy-back

* Bifrost v0.10.001

* feat: 🎸 benchmark

* SLPx mint support commission id (#1261)

* Add vtoken exchange rate rpc (#1260)

* fix: 🐛 add event (#1263)

* add update_currency_metadata function (#1259)

* add update_currency_metadata function

* fix: 🐛 correct update_currency_metadata weight

* add the use of Vec (#1264)

* Add vtoken exchange rate rpc

* add the use of Vec

* Upgrade to Polkadot-SDK v1.7.0 (#1262)

* Bifrost v0.10.0

* fix: 🐛 clippy

* Fix chain spec (#1243)

* Upgrade to polkadot-v1.7.0

---------

Co-authored-by: SunTiebing <1045060705@qq.com>
Co-authored-by: Edwin Wang <lark930@gmail.com>

* Fix compile

* feat: 🎸 add metadata-hash-extension (#1265)

* feat: 🎸 add metadata-hash-extension

* Fix compile (#1266)

* Fix/fix vtoken voting unlock (#1267)

* update the exchange rate of vtokenminting of vtokenvoting test

* Resolve the frozen anomaly when unlocking

* Revert "feat: 🎸 add metadata-hash-extension (#1265)" (#1268)

This reverts commit 489fc9c6adeae44d23edf449e74fde3d6aa40bc3.

* rename the version number to 0.11.0

* Slp supports XCMv4 and reconstruct integration tests (#1272)

* Fix compile

* Reconstruct integration tests and slp supports XCMv4

* Fix slp construct_xcm_message

* Feat/slpx mint add commission (#1273)

* SLPx mint support commission id

* remove the channel_id parameter from the mint method

* add mint_with_channel_id method

* perform data migration for OrderQueue storage

* slpx: set the default value of channel_id to 0

* resolve conflicts

* change the location of the old data structure during storage migration

* Feat/add vtoken exchange rate rpc (#1274)

* Add vtoken exchange rate rpc

* add the use of Vec

* supplement the RPC logic && fix bugs

* adjust the RPC exchange rate precision to three decimal places

* fix clippy

* fix bug: storage migration anomaly (#1276)

* SLPx mint support commission id

* remove the channel_id parameter from the mint method

* add mint_with_channel_id method

* perform data migration for OrderQueue storage

* slpx: set the default value of channel_id to 0

* resolve conflicts

* change the location of the old data structure during storage migration

* fix bug: storage migration anomaly

* Slp removes refund (#1275)

* Slp removes refund

* Fix clippy

* Feat/add vtoken exchange rate rpc (#1277)

* Add vtoken exchange rate rpc

* add the use of Vec

* supplement the RPC logic && fix bugs

* adjust the RPC exchange rate precision to three decimal places

* fix clippy

* supplement omissions: adjust the RPC exchange rate precision to three decimal places

* Remove dmp queue (#1279)

* fix: 🐛 CheckMetadataHash to false

* fix: 🐛 update sp-api

* refactor: 💡 fmt

* fix: 🐛 add metadata-hash

* fix: 🐛 add feature metadata-hash

* fix: 🐛 rm metadata-hash feature

---------

Co-authored-by: SunTiebing <1045060705@qq.com>
Co-authored-by: SunTiebing <87381708+SunTiebing@users.noreply.github.com>
Co-authored-by: NingBo Wang <2536935847@qq.com>
Co-authored-by: Edwin Wang <lark930@gmail.com>

* refactor: 💡 update MaxTurnout and whitelisted_caller track (#1304)

* Allow to receive and send Ethereum assets (#1305)

* feat: 🎸 add buy-back

* Bifrost v0.10.001

* feat: 🎸 benchmark

* SLPx mint support commission id (#1261)

* Add vtoken exchange rate rpc (#1260)

* fix: 🐛 add event (#1263)

* add update_currency_metadata function (#1259)

* add update_currency_metadata function

* fix: 🐛 correct update_currency_metadata weight

* add the use of Vec (#1264)

* Add vtoken exchange rate rpc

* add the use of Vec

* Upgrade to Polkadot-SDK v1.7.0 (#1262)

* Bifrost v0.10.0

* fix: 🐛 clippy

* Fix chain spec (#1243)

* Upgrade to polkadot-v1.7.0

---------

Co-authored-by: SunTiebing <1045060705@qq.com>
Co-authored-by: Edwin Wang <lark930@gmail.com>

* feat: 🎸 add metadata-hash-extension (#1265)

* Fix compile (#1266)

* Fix/fix vtoken voting unlock (#1267)

* update the exchange rate of vtokenminting of vtokenvoting test

* Resolve the frozen anomaly when unlocking

* Revert "feat: 🎸 add metadata-hash-extension (#1265)" (#1268)

This reverts commit 489fc9c6adeae44d23edf449e74fde3d6aa40bc3.

* rename the version number to 0.11.0

* Slp supports XCMv4 and reconstruct integration tests (#1272)

* Fix compile

* Reconstruct integration tests and slp supports XCMv4

* Fix slp construct_xcm_message

* Feat/slpx mint add commission (#1273)

* SLPx mint support commission id

* remove the channel_id parameter from the mint method

* add mint_with_channel_id method

* perform data migration for OrderQueue storage

* slpx: set the default value of channel_id to 0

* resolve conflicts

* change the location of the old data structure during storage migration

* Feat/add vtoken exchange rate rpc (#1274)

* Add vtoken exchange rate rpc

* add the use of Vec

* supplement the RPC logic && fix bugs

* adjust the RPC exchange rate precision to three decimal places

* fix clippy

* fix bug: storage migration anomaly (#1276)

* SLPx mint support commission id

* remove the channel_id parameter from the mint method

* add mint_with_channel_id method

* perform data migration for OrderQueue storage

* slpx: set the default value of channel_id to 0

* resolve conflicts

* change the location of the old data structure during storage migration

* fix bug: storage migration anomaly

* Slp removes refund (#1275)

* Slp removes refund

* Fix clippy

* Allow to receive and send Ethereum assets

* Add constants

---------

Co-authored-by: yooml <ymlll0508@gmail.com>
Co-authored-by: SunTiebing <1045060705@qq.com>
Co-authored-by: SunTiebing <87381708+SunTiebing@users.noreply.github.com>
Co-authored-by: Edwin Wang <lark930@gmail.com>

* Disable supplement_fee_reserve (#1306)

* Remove call_switchgear and add tx_pause (#1308)

* Remove call_switchgear and add tx_pause

* Fix clippy

* Optimize flexible fee (#1307)

* Optimize flexible fee

* Fix bug

* Fix bug

* Add PalletId

* Add error handle

* feat: 🎸 add market-bond

* fix: 🐛 test-all

* fix: 🐛 try-runtime

* Add the channel_id field to the Minted event

* Upgrade to polkadot-v1.13.0 (#1312)

* Upgrade to polkadot-v1.13.0

* remove the warning

* Fix dep issues

* Upgrade to polkadot-v1.13.0

* supplement and upgrade the code

* Upgrade the new parts from v0.12.0

* Fix dep issues

* format Cargo.toml

* Modify the AddOrigin type of the fellowship in bifrost-polkadot

* Cancel the cross-in-out migration.

* fix clippy

---------

Co-authored-by: hqwangningbo <2536935847@qq.com>

* Use github dependencies (#1314)

* Fix flexible_fee TransferTo (#1315)

* Fix generate_genesis_state (#1317)

* Optimize oracle (#1318)

* refactor: 💡 optimize orml-oracle

* fix: 🐛 MinimumTimestampInterval

* style: 💄 rename to MaximumValueInterval

* Add some tests for ve-minting

* Add some tests for ve-minting

* Integrate evm (#1319)

* Update dep

* Ingrate EVM

* Fix deps

* Add precompiles.rs

* Remove pallet-hotfix-sufficients

* Add pallet-evm-accounts

* Evm precompiles

* EVM integration

* Fix compile

* Fix rpc

* Fix `encode_evm_address` and `decode_evm_address`

* Fix evm precompile multicurrency

* Implementing Erc20Mapping using xc-20 standard

* Compatible with BNC Decimal

* Increase min_gas_price

* feat: enable dev mode with manual seal & fix pending block problem

* Add copyright and fix some bugs

* Change native token to WETH

* Support evm flexible fee

* Add inner_swap_exact_assets_for_assets to evm withdraw fee

* Remove swap

* EVM migration from bifrost kusama to bifrost polkadot

* Fix erc20 precompile

* Use OraclePrice

* Fix some errors

* feat: add prices genesis config & optimize dev mode code

* Fix conflicts

* Fix some errors

* Fix clippy

* Format Cargo.toml

* Remove unused code

* Fix clippy

* Fix some errors

* Fix erc20 precompile

---------

Co-authored-by: Edwin Wang <lark930@gmail.com>
Co-authored-by: Damian.lu <wsteth@outlook.com>

* Fix try-runtime (#1323)

* Fix manual seal

* Fix manual seal (#1324)

* fix: 🐛 fellowship collective data (#1325)

* fix: add parachain mock inherent data provider

* Fix ethereum transfer fee (#1328)

* Add evm genesis migration (#1338)

* Bifrost v0.12.0 (#1286)

* Bifrost v0.12.0

* remove old migrations

* Fix vtokenVoting.removeDelegatorVote (#1288)

* add PollClass type

* add the calss parameter to the remove_delegator_vote method

* Add metadata hash (#1299)

* feat: 🎸 add buy-back

* Bifrost v0.10.001

* feat: 🎸 benchmark

* SLPx mint support commission id (#1261)

* Add vtoken exchange rate rpc (#1260)

* fix: 🐛 add event (#1263)

* add update_currency_metadata function (#1259)

* add update_currency_metadata function

* fix: 🐛 correct update_currency_metadata weight

* add the use of Vec (#1264)

* Add vtoken exchange rate rpc

* add the use of Vec

* Upgrade to Polkadot-SDK v1.7.0 (#1262)

* Bifrost v0.10.0

* fix: 🐛 clippy

* Fix chain spec (#1243)

* Upgrade to polkadot-v1.7.0

---------

Co-authored-by: SunTiebing <1045060705@qq.com>
Co-authored-by: Edwin Wang <lark930@gmail.com>

* Fix compile

* feat: 🎸 add metadata-hash-extension (#1265)

* feat: 🎸 add metadata-hash-extension

* Fix compile (#1266)

* Fix/fix vtoken voting unlock (#1267)

* update the exchange rate of vtokenminting of vtokenvoting test

* Resolve the frozen anomaly when unlocking

* Revert "feat: 🎸 add metadata-hash-extension (#1265)" (#1268)

This reverts commit 489fc9c6adeae44d23edf449e74fde3d6aa40bc3.

* rename the version number to 0.11.0

* Slp supports XCMv4 and reconstruct integration tests (#1272)

* Fix compile

* Reconstruct integration tests and slp supports XCMv4

* Fix slp construct_xcm_message

* Feat/slpx mint add commission (#1273)

* SLPx mint support commission id

* remove the channel_id parameter from the mint method

* add mint_with_channel_id method

* perform data migration for OrderQueue storage

* slpx: set the default value of channel_id to 0

* resolve conflicts

* change the location of the old data structure during storage migration

* Feat/add vtoken exchange rate rpc (#1274)

* Add vtoken exchange rate rpc

* add the use of Vec

* supplement the RPC logic && fix bugs

* adjust the RPC exchange rate precision to three decimal places

* fix clippy

* fix bug: storage migration anomaly (#1276)

* SLPx mint support commission id

* remove the channel_id parameter from the mint method

* add mint_with_channel_id method

* perform data migration for OrderQueue storage

* slpx: set the default value of channel_id to 0

* resolve conflicts

* change the location of the old data structure during storage migration

* fix bug: storage migration anomaly

* Slp removes refund (#1275)

* Slp removes refund

* Fix clippy

* Feat/add vtoken exchange rate rpc (#1277)

* Add vtoken exchange rate rpc

* add the use of Vec

* supplement the RPC logic && fix bugs

* adjust the RPC exchange rate precision to three decimal places

* fix clippy

* supplement omissions: adjust the RPC exchange rate precision to three decimal places

* Remove dmp queue (#1279)

* fix: 🐛 CheckMetadataHash to false

* fix: 🐛 update sp-api

* refactor: 💡 fmt

* fix: 🐛 add metadata-hash

* fix: 🐛 add feature metadata-hash

* fix: 🐛 rm metadata-hash feature

---------

Co-authored-by: SunTiebing <1045060705@qq.com>
Co-authored-by: SunTiebing <87381708+SunTiebing@users.noreply.github.com>
Co-authored-by: NingBo Wang <2536935847@qq.com>
Co-authored-by: Edwin Wang <lark930@gmail.com>

* refactor: 💡 update MaxTurnout and whitelisted_caller track (#1304)

* Allow to receive and send Ethereum assets (#1305)

* feat: 🎸 add buy-back

* Bifrost v0.10.001

* feat: 🎸 benchmark

* SLPx mint support commission id (#1261)

* Add vtoken exchange rate rpc (#1260)

* fix: 🐛 add event (#1263)

* add update_currency_metadata function (#1259)

* add update_currency_metadata function

* fix: 🐛 correct update_currency_metadata weight

* add the use of Vec (#1264)

* Add vtoken exchange rate rpc

* add the use of Vec

* Upgrade to Polkadot-SDK v1.7.0 (#1262)

* Bifrost v0.10.0

* fix: 🐛 clippy

* Fix chain spec (#1243)

* Upgrade to polkadot-v1.7.0

---------

Co-authored-by: SunTiebing <1045060705@qq.com>
Co-authored-by: Edwin Wang <lark930@gmail.com>

* feat: 🎸 add metadata-hash-extension (#1265)

* Fix compile (#1266)

* Fix/fix vtoken voting unlock (#1267)

* update the exchange rate of vtokenminting of vtokenvoting test

* Resolve the frozen anomaly when unlocking

* Revert "feat: 🎸 add metadata-hash-extension (#1265)" (#1268)

This reverts commit 489fc9c6adeae44d23edf449e74fde3d6aa40bc3.

* rename the version number to 0.11.0

* Slp supports XCMv4 and reconstruct integration tests (#1272)

* Fix compile

* Reconstruct integration tests and slp supports XCMv4

* Fix slp construct_xcm_message

* Feat/slpx mint add commission (#1273)

* SLPx mint support commission id

* remove the channel_id parameter from the mint method

* add mint_with_channel_id method

* perform data migration for OrderQueue storage

* slpx: set the default value of channel_id to 0

* resolve conflicts

* change the location of the old data structure during storage migration

* Feat/add vtoken exchange rate rpc (#1274)

* Add vtoken exchange rate rpc

* add the use of Vec

* supplement the RPC logic && fix bugs

* adjust the RPC exchange rate precision to three decimal places

* fix clippy

* fix bug: storage migration anomaly (#1276)

* SLPx mint support commission id

* remove the channel_id parameter from the mint method

* add mint_with_channel_id method

* perform data migration for OrderQueue storage

* slpx: set the default value of channel_id to 0

* resolve conflicts

* change the location of the old data structure during storage migration

* fix bug: storage migration anomaly

* Slp removes refund (#1275)

* Slp removes refund

* Fix clippy

* Allow to receive and send Ethereum assets

* Add constants

---------

Co-authored-by: yooml <ymlll0508@gmail.com>
Co-authored-by: SunTiebing <1045060705@qq.com>
Co-authored-by: SunTiebing <87381708+SunTiebing@users.noreply.github.com>
Co-authored-by: Edwin Wang <lark930@gmail.com>

* Disable supplement_fee_reserve (#1306)

* Remove call_switchgear and add tx_pause (#1308)

* Remove call_switchgear and add tx_pause

* Fix clippy

* Optimize flexible fee (#1307)

* Optimize flexible fee

* Fix bug

* Fix bug

* Add PalletId

* Add error handle

* feat: 🎸 add market-bond

* fix: 🐛 test-all

* fix: 🐛 try-runtime

* Add the channel_id field to the Minted event

* Upgrade to polkadot-v1.13.0 (#1312)

* Upgrade to polkadot-v1.13.0

* remove the warning

* Fix dep issues

* Upgrade to polkadot-v1.13.0

* supplement and upgrade the code

* Upgrade the new parts from v0.12.0

* Fix dep issues

* format Cargo.toml

* Modify the AddOrigin type of the fellowship in bifrost-polkadot

* Cancel the cross-in-out migration.

* fix clippy

---------

Co-authored-by: hqwangningbo <2536935847@qq.com>

* Use github dependencies (#1314)

* Fix flexible_fee TransferTo (#1315)

* Fix generate_genesis_state (#1317)

* Optimize oracle (#1318)

* refactor: 💡 optimize orml-oracle

* fix: 🐛 MinimumTimestampInterval

* style: 💄 rename to MaximumValueInterval

* Add some tests for ve-minting

* Add some tests for ve-minting

* Integrate evm (#1319)

* Update dep

* Ingrate EVM

* Fix deps

* Add precompiles.rs

* Remove pallet-hotfix-sufficients

* Add pallet-evm-accounts

* Evm precompiles

* EVM integration

* Fix compile

* Fix rpc

* Fix `encode_evm_address` and `decode_evm_address`

* Fix evm precompile multicurrency

* Implementing Erc20Mapping using xc-20 standard

* Compatible with BNC Decimal

* Increase min_gas_price

* feat: enable dev mode with manual seal & fix pending block problem

* Add copyright and fix some bugs

* Change native token to WETH

* Support evm flexible fee

* Add inner_swap_exact_assets_for_assets to evm withdraw fee

* Remove swap

* EVM migration from bifrost kusama to bifrost polkadot

* Fix erc20 precompile

* Use OraclePrice

* Fix some errors

* feat: add prices genesis config & optimize dev mode code

* Fix conflicts

* Fix some errors

* Fix clippy

* Format Cargo.toml

* Remove unused code

* Fix clippy

* Fix some errors

* Fix erc20 precompile

---------

Co-authored-by: Edwin Wang <lark930@gmail.com>
Co-authored-by: Damian.lu <wsteth@outlook.com>

* Fix try-runtime (#1323)

* Fix manual seal

* Fix manual seal (#1324)

* fix: 🐛 fellowship collective data (#1325)

* fix: add parachain mock inherent data provider

* Fix ethereum transfer fee (#1328)

---------

Co-authored-by: Edwin Wang <lark930@gmail.com>
Co-authored-by: yooml <ymlll0508@gmail.com>
Co-authored-by: NingBo Wang <2536935847@qq.com>
Co-authored-by: Gemma <neversaynever333@outlook.com>
Co-authored-by: Damian.lu <wsteth@outlook.com>

* Add evm genesis storage

* [skip ci] Add evmSince

---------

Co-authored-by: SunTiebing <87381708+SunTiebing@users.noreply.github.com>
Co-authored-by: Edwin Wang <lark930@gmail.com>
Co-authored-by: yooml <ymlll0508@gmail.com>
Co-authored-by: Gemma <neversaynever333@outlook.com>
Co-authored-by: Damian.lu <wsteth@outlook.com>

* Bump version to 0.12.1

* Update Cargo.lock

* Fix migration (#1341)

* Bifrost v0.12.0 (#1286)

* Bifrost v0.12.0

* remove old migrations

* Fix vtokenVoting.removeDelegatorVote (#1288)

* add PollClass type

* add the calss parameter to the remove_delegator_vote method

* Add metadata hash (#1299)

* feat: 🎸 add buy-back

* Bifrost v0.10.001

* feat: 🎸 benchmark

* SLPx mint support commission id (#1261)

* Add vtoken exchange rate rpc (#1260)

* fix: 🐛 add event (#1263)

* add update_currency_metadata function (#1259)

* add update_currency_metadata function

* fix: 🐛 correct update_currency_metadata weight

* add the use of Vec (#1264)

* Add vtoken exchange rate rpc

* add the use of Vec

* Upgrade to Polkadot-SDK v1.7.0 (#1262)

* Bifrost v0.10.0

* fix: 🐛 clippy

* Fix chain spec (#1243)

* Upgrade to polkadot-v1.7.0

---------

Co-authored-by: SunTiebing <1045060705@qq.com>
Co-authored-by: Edwin Wang <lark930@gmail.com>

* Fix compile

* feat: 🎸 add metadata-hash-extension (#1265)

* feat: 🎸 add metadata-hash-extension

* Fix compile (#1266)

* Fix/fix vtoken voting unlock (#1267)

* update the exchange rate of vtokenminting of vtokenvoting test

* Resolve the frozen anomaly when unlocking

* Revert "feat: 🎸 add metadata-hash-extension (#1265)" (#1268)

This reverts commit 489fc9c6adeae44d23edf449e74fde3d6aa40bc3.

* rename the version number to 0.11.0

* Slp supports XCMv4 and reconstruct integration tests (#1272)

* Fix compile

* Reconstruct integration tests and slp supports XCMv4

* Fix slp construct_xcm_message

* Feat/slpx mint add commission (#1273)

* SLPx mint support commission id

* remove the channel_id parameter from the mint method

* add mint_with_channel_id method

* perform data migration for OrderQueue storage

* slpx: set the default value of channel_id to 0

* resolve conflicts

* change the location of the old data structure during storage migration

* Feat/add vtoken exchange rate rpc (#1274)

* Add vtoken exchange rate rpc

* add the use of Vec

* supplement the RPC logic && fix bugs

* adjust the RPC exchange rate precision to three decimal places

* fix clippy

* fix bug: storage migration anomaly (#1276)

* SLPx mint support commission id

* remove the channel_id parameter from the mint method

* add mint_with_channel_id method

* perform data migration for OrderQueue storage

* slpx: set the default value of channel_id to 0

* resolve conflicts

* change the location of the old data structure during storage migration

* fix bug: storage migration anomaly

* Slp removes refund (#1275)

* Slp removes refund

* Fix clippy

* Feat/add vtoken exchange rate rpc (#1277)

* Add vtoken exchange rate rpc

* add the use of Vec

* supplement the RPC logic && fix bugs

* adjust the RPC exchange rate precision to three decimal places

* fix clippy

* supplement omissions: adjust the RPC exchange rate precision to three decimal places

* Remove dmp queue (#1279)

* fix: 🐛 CheckMetadataHash to false

* fix: 🐛 update sp-api

* refactor: 💡 fmt

* fix: 🐛 add metadata-hash

* fix: 🐛 add feature metadata-hash

* fix: 🐛 rm metadata-hash feature

---------

Co-authored-by: SunTiebing <1045060705@qq.com>
Co-authored-by: SunTiebing <87381708+SunTiebing@users.noreply.github.com>
Co-authored-by: NingBo Wang <2536935847@qq.com>
Co-authored-by: Edwin Wang <lark930@gmail.com>

* refactor: 💡 update MaxTurnout and whitelisted_caller track (#1304)

* Allow to receive and send Ethereum assets (#1305)

* feat: 🎸 add buy-back

* Bifrost v0.10.001

* feat: 🎸 benchmark

* SLPx mint support commission id (#1261)

* Add vtoken exchange rate rpc (#1260)

* fix: 🐛 add event (#1263)

* add update_currency_metadata function (#1259)

* add update_currency_metadata function

* fix: 🐛 correct update_currency_metadata weight

* add the use of Vec (#1264)

* Add vtoken exchange rate rpc

* add the use of Vec

* Upgrade to Polkadot-SDK v1.7.0 (#1262)

* Bifrost v0.10.0

* fix: 🐛 clippy

* Fix chain spec (#1243)

* Upgrade to polkadot-v1.7.0

---------

Co-authored-by: SunTiebing <1045060705@qq.com>
Co-authored-by: Edwin Wang <lark930@gmail.com>

* feat: 🎸 add metadata-hash-extension (#1265)

* Fix compile (#1266)

* Fix/fix vtoken voting unlock (#1267)

* update the exchange rate of vtokenminting of vtokenvoting test

* Resolve the frozen anomaly when unlocking

* Revert "feat: 🎸 add metadata-hash-extension (#1265)" (#1268)

This reverts commit 489fc9c6adeae44d23edf449e74fde3d6aa40bc3.

* rename the version number to 0.11.0

* Slp supports XCMv4 and reconstruct integration tests (#1272)

* Fix compile

* Reconstruct integration tests and slp supports XCMv4

* Fix slp construct_xcm_message

* Feat/slpx mint add commission (#1273)

* SLPx mint support commission id

* remove the channel_id parameter from the mint method

* add mint_with_channel_id method

* perform data migration for OrderQueue storage

* slpx: set the default value of channel_id to 0

* resolve conflicts

* change the location of the old data structure during storage migration

* Feat/add vtoken exchange rate rpc (#1274)

* Add vtoken exchange rate rpc

* add the use of Vec

* supplement the RPC logic && fix bugs

* adjust the RPC exchange rate precision to three decimal places

* fix clippy

* fix bug: storage migration anomaly (#1276)

* SLPx mint support commission id

* remove the channel_id parameter from the mint method

* add mint_with_channel_id method

* perform data migration for OrderQueue storage

* slpx: set the default value of channel_id to 0

* resolve conflicts

* change the location of the old data structure during storage migration

* fix bug: storage migration anomaly

* Slp removes refund (#1275)

* Slp removes refund

* Fix clippy

* Allow to receive and send Ethereum assets

* Add constants

---------

Co-authored-by: yooml <ymlll0508@gmail.com>
Co-authored-by: SunTiebing <1045060705@qq.com>
Co-authored-by: SunTiebing <87381708+SunTiebing@users.noreply.github.com>
Co-authored-by: Edwin Wang <lark930@gmail.com>

* Disable supplement_fee_reserve (#1306)

* Remove call_switchgear and add tx_pause (#1308)

* Remove call_switchgear and add tx_pause

* Fix clippy

* Optimize flexible fee (#1307)

* Optimize flexible fee

* Fix bug

* Fix bug

* Add PalletId

* Add error handle

* feat: 🎸 add market-bond

* fix: 🐛 test-all

* fix: 🐛 try-runtime

* Add the channel_id field to the Minted event

* Upgrade to polkadot-v1.13.0 (#1312)

* Upgrade to polkadot-v1.13.0

* remove the warning

* Fix dep issues

* Upgrade to polkadot-v1.13.0

* supplement and upgrade the code

* Upgrade the new parts from v0.12.0

* Fix dep issues

* format Cargo.toml

* Modify the AddOrigin type of the fellowship in bifrost-polkadot

* Cancel the cross-in-out migration.

* fix clippy

---------

Co-authored-by: hqwangningbo <2536935847@qq.com>

* Use github dependencies (#1314)

* Fix flexible_fee TransferTo (#1315)

* Fix generate_genesis_state (#1317)

* Optimize oracle (#1318)

* refactor: 💡 optimize orml-oracle

* fix: 🐛 MinimumTimestampInterval

* style: 💄 rename to MaximumValueInterval

* Add some tests for ve-minting

* Add some tests for ve-minting

* Integrate evm (#1319)

* Update dep

* Ingrate EVM

* Fix deps

* Add precompiles.rs

* Remove pallet-hotfix-sufficients

* Add pallet-evm-accounts

* Evm precompiles

* EVM integration

* Fix compile

* Fix rpc

* Fix `encode_evm_address` and `decode_evm_address`

* Fix evm precompile multicurrency

* Implementing Erc20Mapping using xc-20 standard

* Compatible with BNC Decimal

* Increase min_gas_price

* feat: enable dev mode with manual seal & fix pending block problem

* Add copyright and fix some bugs

* Change native token to WETH

* Support evm flexible fee

* Add inner_swap_exact_assets_for_assets to evm withdraw fee

* Remove swap

* EVM migration from bifrost kusama to bifrost polkadot

* Fix erc20 precompile

* Use OraclePrice

* Fix some errors

* feat: add prices genesis config & optimize dev mode code

* Fix conflicts

* Fix some errors

* Fix clippy

* Format Cargo.toml

* Remove unused code

* Fix clippy

* Fix some errors

* Fix erc20 precompile

---------

Co-authored-by: Edwin Wang <lark930@gmail.com>
Co-authored-by: Damian.lu <wsteth@outlook.com>

* Fix try-runtime (#1323)

* Fix manual seal

* Fix manual seal (#1324)

* fix: 🐛 fellowship collective data (#1325)

* fix: add parachain mock inherent data provider

* Fix ethereum transfer fee (#1328)

---------

Co-authored-by: Edwin Wang <lark930@gmail.com>
Co-authored-by: yooml <ymlll0508@gmail.com>
Co-authored-by: NingBo Wang <2536935847@qq.com>
Co-authored-by: Gemma <neversaynever333@outlook.com>
Co-authored-by: Damian.lu <wsteth@outlook.com>

* Add evm genesis storage

* [skip ci] Add evmSince

* Fix migration

* Fix migration

* Remove unused code

---------

Co-authored-by: SunTiebing <87381708+SunTiebing@users.noreply.github.com>
Co-authored-by: Edwin Wang <lark930@gmail.com>
Co-authored-by: yooml <ymlll0508@gmail.com>
Co-authored-by: Gemma <neversaynever333@outlook.com>
Co-authored-by: Damian.lu <wsteth@outlook.com>

* Remove getter in buy-back

---------

Co-authored-by: SunTiebing <1045060705@qq.com>
Co-authored-by: SunTiebing <87381708+SunTiebing@users.noreply.github.com>
Co-authored-by: Edwin Wang <lark930@gmail.com>
Co-authored-by: yooml <ymlll0508@gmail.com>
Co-authored-by: NingBo Wang <2536935847@qq.com>
Co-authored-by: Damian.lu <wsteth@outlook.com>

* Remove getters in xcm-interface (#1352)

* Remove getters in salp. (#1351)

* Remove getter in evm-accounts (#1350)

* Remove getters in slp (#1353)

* Remove getters in slpx (#1360)

* Remove getters in vstoken-conversion. (#1362)

* Remove getters in vtoken-minting. (#1363)

* Remove getter in system-maker. (#1364)

* Remove getter in fee-share (#1365)

* Remove getters in prices (#1367)

* Remove getters in lend-market (#1366)

* Remove getters in ve-minting (#1368)

* Optimize clippy (#1369)

* Deprecated unused pallets (#1383)

* Review format (#1386)

* style: 💄 format

* style: 💄 check-all

* fix: 🐛 bench

* Update buy back (#1387)

* style: 💄 format

* style: 💄 check-all

* fix: 🐛 bench

* feat: 🎸 add destruction_ratio

* fix: 🐛 benchmark

* EVM flexible fee logic optimization (#1370)

* EVM flexible fee logic optimization

* Add comments

* Add support for handling different currency precisions & included error handling.

* Adjust the gas_fee parameter in the get_balance_in_currency method to an exact value

* fix clippy

* add test code of flexiable-fee pallet

* Update fee share (#1395)

* feat: 🎸 add usd_cumulation

* feat: 🎸 bench

* fix: 🐛 fmt

* docs: ✏️ add note

* Feat/change evm address convert rule (#1396)

* Change EVM Address convert rule

* Change EVM Address convert rule

* Remove the unused function:is_evm_account & rename truncated_account_id function to convert_account_id

* fix clippy

* refactor: 💡 move to TechAdmin (#1398)

* refactor: 💡 transfer to BuyBackAccount (#1399)

* Fix mint_with_channel_id weights (#1400)

* Recoverd imgs of banner and logo (#1401)

* feat: 🎸 add fn set_swap_out_min (#1389)

* feat: 🎸 add fn set_swap_out_min

* fix: 🐛 fmt

* fix: 🐛 fmt

* fix: 🐛 error

* feat: 🎸 add bais

* fix: 🐛 add test

* fix: 🐛 rename field bias

* Optimize the `channel-commission` code. (#1390)

* Optimize the `channel-commission` code.

* Replace the insert method with the mutate method

* Added a result check for the clear_prefix method

* Supplement the test code of `channel-commission`.

* Handling Error cases in hooks.

* Optimize the handling of the `check_removed_all` method.

* Remove getters in cross-in-out (#1402)

* Removed getters in channel-commission. (#1404)

* Removed getters in flexible-fee. (#1405)

* Removed getters in channel-commission.

* Removed getters in flexible-fee.

* Removed getters in parachain-staking. (#1406)

* Removed getters in channel-commission.

* Removed getters in flexible-fee.

* Removed getterd in parachain-staking.

* Update buy back (#1407)

* fix: 🐛 add field last_buyback_cycle for accurate judgment

* style: 💄 fmt

* Update ve minting (#1408)

* refactor: 💡 transfer to BuyBackAccount

* feat: 🎸 add auto notify_reward

* Optimize vtokenvoting pallet.

* Use the call.dispatch method to support vBNC in vTokenVoting.

* Use the call.dispatch method to support vBNC in vTokenVoting.

* adjust mock file

* Change the way the vtoken-voting pallet interacts with other runtime pallets to a decoding-based approach.

* Plump vtokenvoting supports vbnc

* optimize test

* optimize reviewed code

* Add vtoken-voting Kusama tests to the test-all command.

---------

Co-authored-by: Edwin Wang <lark930@gmail.com>
Co-authored-by: yooml <ymlll0508@gmail.com>
Co-authored-by: NingBo Wang <2536935847@qq.com>
Co-authored-by: MJLNSN <96321798+MJLNSN@users.noreply.github.com>
Co-authored-by: Damian.lu <wsteth@outlook.com>
---
 Makefile                                      |    5 +-
 pallets/slp/src/lib.rs                        |   15 +-
 pallets/vtoken-minting/src/lib.rs             |    2 +-
 .../src/agents/bifrost_agent/agent.rs         |  150 ++
 .../src/agents/bifrost_agent/call.rs          |   73 +
 .../src/agents/bifrost_agent/mod.rs           |   22 +
 pallets/vtoken-voting/src/agents/mod.rs       |   23 +
 .../src/agents/relaychain_agent/agent.rs      |  120 ++
 .../src/{ => agents/relaychain_agent}/call.rs |   35 +-
 .../src/agents/relaychain_agent/mod.rs        |   22 +
 pallets/vtoken-voting/src/lib.rs              |  584 +++---
 pallets/vtoken-voting/src/mock.rs             |  149 +-
 pallets/vtoken-voting/src/tests.rs            | 1379 ---------------
 .../vtoken-voting/src/tests/common_test.rs    | 1564 +++++++++++++++++
 pallets/vtoken-voting/src/tests/mod.rs        |   23 +
 pallets/vtoken-voting/src/tests/vbnc_test.rs  |  841 +++++++++
 pallets/vtoken-voting/src/traits.rs           |  142 ++
 pallets/vtoken-voting/src/vote.rs             |    4 +-
 primitives/src/traits.rs                      |    4 +-
 runtime/bifrost-kusama/src/lib.rs             |    1 +
 runtime/bifrost-polkadot/src/lib.rs           |    1 +
 21 files changed, 3526 insertions(+), 1633 deletions(-)
 create mode 100644 pallets/vtoken-voting/src/agents/bifrost_agent/agent.rs
 create mode 100644 pallets/vtoken-voting/src/agents/bifrost_agent/call.rs
 create mode 100644 pallets/vtoken-voting/src/agents/bifrost_agent/mod.rs
 create mode 100644 pallets/vtoken-voting/src/agents/mod.rs
 create mode 100644 pallets/vtoken-voting/src/agents/relaychain_agent/agent.rs
 rename pallets/vtoken-voting/src/{ => agents/relaychain_agent}/call.rs (78%)
 create mode 100644 pallets/vtoken-voting/src/agents/relaychain_agent/mod.rs
 delete mode 100644 pallets/vtoken-voting/src/tests.rs
 create mode 100644 pallets/vtoken-voting/src/tests/common_test.rs
 create mode 100644 pallets/vtoken-voting/src/tests/mod.rs
 create mode 100644 pallets/vtoken-voting/src/tests/vbnc_test.rs
 create mode 100644 pallets/vtoken-voting/src/traits.rs

diff --git a/Makefile b/Makefile
index 121749f9c..e72e6af14 100644
--- a/Makefile
+++ b/Makefile
@@ -30,7 +30,7 @@ check-all: format
 	SKIP_WASM_BUILD= cargo check -p bifrost-cli --locked --features "with-all-runtime,runtime-benchmarks,try-runtime"
 
 .PHONY: test-all # cargo test all
-test-all: test-runtimes test-benchmarks
+test-all: test-runtimes test-benchmarks test-vtoken-voting-kusama
 
 .PHONY: test-runtimes
 test-runtimes:
@@ -40,6 +40,9 @@ test-runtimes:
 test-benchmarks:
 	SKIP_WASM_BUILD= cargo test benchmarking  --features="with-bifrost-runtime, runtime-benchmarks, polkadot"
 
+test-vtoken-voting-kusama:
+	SKIP_WASM_BUILD= cargo test -p bifrost-vtoken-voting --features="kusama, runtime-benchmarks"
+
 .PHONY: clean # cargo clean
 clean:
 	cargo clean
diff --git a/pallets/slp/src/lib.rs b/pallets/slp/src/lib.rs
index d4a5fd67a..4ca0f422a 100644
--- a/pallets/slp/src/lib.rs
+++ b/pallets/slp/src/lib.rs
@@ -2254,7 +2254,8 @@ pub mod pallet {
 pub struct DerivativeAccountProvider<T, F>(PhantomData<(T, F)>);
 
 impl<T: Config, F: Contains<CurrencyIdOf<T>>>
-	DerivativeAccountHandler<CurrencyIdOf<T>, BalanceOf<T>> for DerivativeAccountProvider<T, F>
+	DerivativeAccountHandler<CurrencyIdOf<T>, BalanceOf<T>, AccountIdOf<T>>
+	for DerivativeAccountProvider<T, F>
 {
 	fn check_derivative_index_exists(
 		token: CurrencyIdOf<T>,
@@ -2270,6 +2271,18 @@ impl<T: Config, F: Contains<CurrencyIdOf<T>>>
 		DelegatorsIndex2Multilocation::<T>::get(token, derivative_index)
 	}
 
+	fn get_account_id(
+		token: CurrencyIdOf<T>,
+		derivative_index: DerivativeIndex,
+	) -> Option<AccountIdOf<T>> {
+		Self::get_multilocation(token, derivative_index).and_then(|location| {
+			location.interior.last().and_then(|interior| match interior {
+				AccountId32 { id, .. } => T::AccountId::decode(&mut &id[..]).ok(),
+				_ => None,
+			})
+		})
+	}
+
 	fn get_stake_info(
 		token: CurrencyIdOf<T>,
 		derivative_index: DerivativeIndex,
diff --git a/pallets/vtoken-minting/src/lib.rs b/pallets/vtoken-minting/src/lib.rs
index 687ee5475..b145c2de7 100644
--- a/pallets/vtoken-minting/src/lib.rs
+++ b/pallets/vtoken-minting/src/lib.rs
@@ -2182,7 +2182,7 @@ impl<T: Config> VTokenSupplyProvider<CurrencyIdOf<T>, BalanceOf<T>> for Pallet<T
 	}
 
 	fn get_token_supply(token: CurrencyIdOf<T>) -> Option<BalanceOf<T>> {
-		if CurrencyId::is_token(&token) {
+		if CurrencyId::is_token(&token) | CurrencyId::is_native(&token) {
 			Some(TokenPool::<T>::get(token))
 		} else {
 			None
diff --git a/pallets/vtoken-voting/src/agents/bifrost_agent/agent.rs b/pallets/vtoken-voting/src/agents/bifrost_agent/agent.rs
new file mode 100644
index 000000000..24c250a24
--- /dev/null
+++ b/pallets/vtoken-voting/src/agents/bifrost_agent/agent.rs
@@ -0,0 +1,150 @@
+// 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 <https://www.gnu.org/licenses/>.
+
+use crate::*;
+use bifrost_primitives::{CurrencyId, DerivativeIndex};
+use frame_support::pallet_prelude::*;
+use xcm::v4::Location;
+
+use crate::{agents::bifrost_agent::BifrostCall, pallet::Error, traits::*};
+
+/// VotingAgent implementation for Bifrost
+pub struct BifrostAgent<T: Config> {
+	vtoken: CurrencyIdOf<T>,
+	location: Location,
+}
+
+impl<T: Config> BifrostAgent<T> {
+	// Only polkadot networks are supported.
+	pub fn new(vtoken: CurrencyId) -> Result<Self, Error<T>> {
+		if cfg!(feature = "polkadot") {
+			let location = Pallet::<T>::convert_vtoken_to_dest_location(vtoken)?;
+			Ok(Self { vtoken, location })
+		} else {
+			Err(Error::<T>::VTokenNotSupport)
+		}
+	}
+}
+
+impl<T: Config> VotingAgent<T> for BifrostAgent<T> {
+	fn vtoken(&self) -> CurrencyIdOf<T> {
+		self.vtoken
+	}
+
+	fn location(&self) -> Location {
+		self.location.clone()
+	}
+
+	fn delegate_vote(
+		&self,
+		who: AccountIdOf<T>,
+		vtoken: CurrencyIdOf<T>,
+		poll_index: PollIndex,
+		_submitted: bool,
+		new_delegator_votes: Vec<(DerivativeIndex, AccountVote<BalanceOf<T>>)>,
+		maybe_old_vote: Option<(AccountVote<BalanceOf<T>>, BalanceOf<T>)>,
+	) -> DispatchResult {
+		// Get the derivative index from the first delegator vote.
+		let derivative_index = new_delegator_votes[0].0;
+		let call_encode =
+			self.vote_call_encode(new_delegator_votes, poll_index, derivative_index)?;
+		let vote_call: <T as frame_system::Config>::RuntimeCall =
+			<T as frame_system::Config>::RuntimeCall::decode(&mut &*call_encode)
+				.map_err(|_| Error::<T>::CallDecodeFailed)?;
+
+		let token = CurrencyId::to_token(&vtoken).map_err(|_| Error::<T>::NoData)?;
+		let delegator: AccountIdOf<T> =
+			T::DerivativeAccount::get_account_id(token, derivative_index)
+				.ok_or(Error::<T>::NoData)?;
+		let origin = RawOrigin::Signed(delegator).into();
+		let success = vote_call.dispatch(origin).is_ok();
+		Pallet::<T>::handle_vote_result(
+			success,
+			who,
+			vtoken,
+			poll_index,
+			maybe_old_vote,
+			derivative_index,
+		)?;
+
+		if success {
+			Ok(())
+		} else {
+			Err(Error::<T>::InvalidCallDispatch.into())
+		}
+	}
+
+	fn vote_call_encode(
+		&self,
+		new_delegator_votes: Vec<(DerivativeIndex, AccountVote<BalanceOf<T>>)>,
+		poll_index: PollIndex,
+		_derivative_index: DerivativeIndex,
+	) -> Result<Vec<u8>, Error<T>> {
+		let vote_calls = new_delegator_votes
+			.iter()
+			.map(|(_derivative_index, vote)| {
+				<BifrostCall<T> as ConvictionVotingCall<T>>::vote(poll_index, *vote)
+			})
+			.collect::<Vec<_>>();
+		let vote_call = if vote_calls.len() == 1 {
+			vote_calls.into_iter().nth(0).ok_or(Error::<T>::NoData)?
+		} else {
+			ensure!(false, Error::<T>::NoPermissionYet);
+			<BifrostCall<T> as UtilityCall<BifrostCall<T>>>::batch_all(vote_calls)
+		};
+
+		Ok(vote_call.encode())
+	}
+
+	fn delegate_remove_delegator_vote(
+		&self,
+		vtoken: CurrencyIdOf<T>,
+		poll_index: PollIndex,
+		class: PollClass,
+		derivative_index: DerivativeIndex,
+	) -> DispatchResult {
+		let call_encode =
+			self.remove_delegator_vote_call_encode(class, poll_index, derivative_index)?;
+		let call = <T as frame_system::Config>::RuntimeCall::decode(&mut &*call_encode)
+			.map_err(|_| Error::<T>::CallDecodeFailed)?;
+
+		let token = CurrencyId::to_token(&vtoken).map_err(|_| Error::<T>::NoData)?;
+		let delegator: AccountIdOf<T> =
+			T::DerivativeAccount::get_account_id(token, derivative_index)
+				.ok_or(Error::<T>::NoData)?;
+		let origin = RawOrigin::Signed(delegator).into();
+		let success = call.dispatch(origin).is_ok();
+
+		if success {
+			Pallet::<T>::handle_remove_delegator_vote_success(vtoken, poll_index);
+			Ok(())
+		} else {
+			Err(Error::<T>::InvalidCallDispatch.into())
+		}
+	}
+
+	fn remove_delegator_vote_call_encode(
+		&self,
+		class: PollClass,
+		poll_index: PollIndex,
+		_derivative_index: DerivativeIndex,
+	) -> Result<Vec<u8>, Error<T>> {
+		Ok(<BifrostCall<T> as ConvictionVotingCall<T>>::remove_vote(Some(class), poll_index)
+			.encode())
+	}
+}
diff --git a/pallets/vtoken-voting/src/agents/bifrost_agent/call.rs b/pallets/vtoken-voting/src/agents/bifrost_agent/call.rs
new file mode 100644
index 000000000..ee89348e3
--- /dev/null
+++ b/pallets/vtoken-voting/src/agents/bifrost_agent/call.rs
@@ -0,0 +1,73 @@
+// 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 <https://www.gnu.org/licenses/>.
+
+use crate::{traits::*, *};
+use parity_scale_codec::{Decode, Encode};
+use sp_runtime::{traits::StaticLookup, RuntimeDebug};
+
+pub(in crate::agents::bifrost_agent) use bifrost::*;
+
+pub(in crate::agents::bifrost_agent) mod bifrost {
+	use crate::agents::bifrost_agent::call::*;
+
+	#[derive(Encode, Decode, RuntimeDebug)]
+	pub(in crate::agents::bifrost_agent) enum BifrostCall<T: Config> {
+		#[codec(index = 36)]
+		ConvictionVoting(ConvictionVoting<T>),
+		#[codec(index = 50)]
+		Utility(Utility<Self>),
+	}
+}
+
+#[derive(Encode, Decode, RuntimeDebug, Clone)]
+pub(in crate::agents::bifrost_agent) enum ConvictionVoting<T: Config> {
+	#[codec(index = 0)]
+	Vote(#[codec(compact)] PollIndex, AccountVote<BalanceOf<T>>),
+	#[codec(index = 3)]
+	Unlock(PollClass, <T::Lookup as StaticLookup>::Source),
+	#[codec(index = 4)]
+	RemoveVote(Option<PollClass>, PollIndex),
+}
+
+impl<T: Config> ConvictionVotingCall<T> for BifrostCall<T> {
+	fn vote(poll_index: PollIndex, vote: AccountVote<BalanceOf<T>>) -> Self {
+		Self::ConvictionVoting(ConvictionVoting::Vote(poll_index, vote))
+	}
+
+	fn remove_vote(class: Option<PollClass>, poll_index: PollIndex) -> Self {
+		Self::ConvictionVoting(ConvictionVoting::RemoveVote(class, poll_index))
+	}
+}
+
+#[derive(Encode, Decode, RuntimeDebug, Clone)]
+pub(in crate::agents::bifrost_agent) enum Utility<Call> {
+	#[codec(index = 1)]
+	AsDerivative(DerivativeIndex, Box<Call>),
+	#[codec(index = 2)]
+	BatchAll(Vec<Call>),
+}
+
+impl<T: Config> UtilityCall<BifrostCall<T>> for BifrostCall<T> {
+	fn as_derivative(derivative_index: DerivativeIndex, call: Self) -> Self {
+		Self::Utility(Utility::AsDerivative(derivative_index, Box::new(call)))
+	}
+
+	fn batch_all(calls: Vec<Self>) -> Self {
+		Self::Utility(Utility::BatchAll(calls))
+	}
+}
diff --git a/pallets/vtoken-voting/src/agents/bifrost_agent/mod.rs b/pallets/vtoken-voting/src/agents/bifrost_agent/mod.rs
new file mode 100644
index 000000000..533ae6ef3
--- /dev/null
+++ b/pallets/vtoken-voting/src/agents/bifrost_agent/mod.rs
@@ -0,0 +1,22 @@
+// 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 <https://www.gnu.org/licenses/>.
+pub mod agent;
+mod call;
+
+pub use agent::*;
+pub(in crate::agents::bifrost_agent) use call::*;
diff --git a/pallets/vtoken-voting/src/agents/mod.rs b/pallets/vtoken-voting/src/agents/mod.rs
new file mode 100644
index 000000000..b89becf7d
--- /dev/null
+++ b/pallets/vtoken-voting/src/agents/mod.rs
@@ -0,0 +1,23 @@
+// 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 <https://www.gnu.org/licenses/>.
+
+mod bifrost_agent;
+mod relaychain_agent;
+
+pub use bifrost_agent::*;
+pub use relaychain_agent::*;
diff --git a/pallets/vtoken-voting/src/agents/relaychain_agent/agent.rs b/pallets/vtoken-voting/src/agents/relaychain_agent/agent.rs
new file mode 100644
index 000000000..73e2a9b2e
--- /dev/null
+++ b/pallets/vtoken-voting/src/agents/relaychain_agent/agent.rs
@@ -0,0 +1,120 @@
+// 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 <https://www.gnu.org/licenses/>.
+
+use crate::*;
+use bifrost_primitives::{CurrencyId, DerivativeIndex};
+use frame_support::{ensure, pallet_prelude::*};
+use xcm::v4::Location;
+
+use crate::{agents::relaychain_agent::call::*, pallet::Error, traits::*};
+
+/// VotingAgent implementation for relay chain
+pub struct RelaychainAgent<T: Config> {
+	vtoken: CurrencyIdOf<T>,
+	location: Location,
+}
+impl<T: Config> RelaychainAgent<T> {
+	pub fn new(vtoken: CurrencyId) -> Result<Self, Error<T>> {
+		let location = Pallet::<T>::convert_vtoken_to_dest_location(vtoken)?;
+		Ok(Self { vtoken, location })
+	}
+}
+
+impl<T: Config> VotingAgent<T> for RelaychainAgent<T> {
+	fn vtoken(&self) -> CurrencyIdOf<T> {
+		self.vtoken
+	}
+
+	fn location(&self) -> Location {
+		self.location.clone()
+	}
+	fn delegate_vote(
+		&self,
+		who: AccountIdOf<T>,
+		vtoken: CurrencyIdOf<T>,
+		poll_index: PollIndex,
+		submitted: bool,
+		new_delegator_votes: Vec<(DerivativeIndex, AccountVote<BalanceOf<T>>)>,
+		maybe_old_vote: Option<(AccountVote<BalanceOf<T>>, BalanceOf<T>)>,
+	) -> DispatchResult {
+		Pallet::<T>::send_xcm_vote_message(
+			who,
+			vtoken,
+			poll_index,
+			submitted,
+			new_delegator_votes,
+			maybe_old_vote,
+		)
+	}
+
+	fn vote_call_encode(
+		&self,
+		new_delegator_votes: Vec<(DerivativeIndex, AccountVote<BalanceOf<T>>)>,
+		poll_index: PollIndex,
+		derivative_index: DerivativeIndex,
+	) -> Result<Vec<u8>, Error<T>> {
+		let vote_calls = new_delegator_votes
+			.iter()
+			.map(|(_derivative_index, vote)| {
+				<RelayCall<T> as ConvictionVotingCall<T>>::vote(poll_index, *vote)
+			})
+			.collect::<Vec<_>>();
+		let vote_call = if vote_calls.len() == 1 {
+			vote_calls.into_iter().nth(0).ok_or(Error::<T>::NoData)?
+		} else {
+			ensure!(false, Error::<T>::NoPermissionYet);
+			<RelayCall<T> as UtilityCall<RelayCall<T>>>::batch_all(vote_calls)
+		};
+
+		let encode_call =
+			<RelayCall<T> as UtilityCall<RelayCall<T>>>::as_derivative(derivative_index, vote_call)
+				.encode();
+
+		Ok(encode_call)
+	}
+
+	fn delegate_remove_delegator_vote(
+		&self,
+		vtoken: CurrencyIdOf<T>,
+		poll_index: PollIndex,
+		class: PollClass,
+		derivative_index: DerivativeIndex,
+	) -> DispatchResult {
+		Pallet::<T>::send_xcm_remove_delegator_vote_message(
+			vtoken,
+			poll_index,
+			class,
+			derivative_index,
+		)
+	}
+
+	fn remove_delegator_vote_call_encode(
+		&self,
+		class: PollClass,
+		poll_index: PollIndex,
+		derivative_index: DerivativeIndex,
+	) -> Result<Vec<u8>, Error<T>> {
+		let remove_vote_call =
+			<RelayCall<T> as ConvictionVotingCall<T>>::remove_vote(Some(class), poll_index);
+		Ok(<RelayCall<T> as UtilityCall<RelayCall<T>>>::as_derivative(
+			derivative_index,
+			remove_vote_call,
+		)
+		.encode())
+	}
+}
diff --git a/pallets/vtoken-voting/src/call.rs b/pallets/vtoken-voting/src/agents/relaychain_agent/call.rs
similarity index 78%
rename from pallets/vtoken-voting/src/call.rs
rename to pallets/vtoken-voting/src/agents/relaychain_agent/call.rs
index 956d2a15a..8fb6ce1f1 100644
--- a/pallets/vtoken-voting/src/call.rs
+++ b/pallets/vtoken-voting/src/agents/relaychain_agent/call.rs
@@ -19,23 +19,22 @@
 #![allow(ambiguous_glob_reexports)]
 #![allow(unused_imports)]
 
-use crate::{AccountVote, BalanceOf, Config, DerivativeIndex, PollClass, PollIndex};
+use crate::{traits::*, *};
 use parity_scale_codec::{Decode, Encode};
 use sp_runtime::{traits::StaticLookup, RuntimeDebug};
-use sp_std::prelude::*;
 
 #[cfg(feature = "kusama")]
-pub use kusama::*;
+pub(in crate::agents::relaychain_agent) use kusama::*;
 
 #[cfg(feature = "polkadot")]
-pub use polkadot::*;
+pub(in crate::agents::relaychain_agent) use polkadot::*;
 
 #[cfg(feature = "kusama")]
-mod kusama {
-	use crate::*;
+pub(in crate::agents::relaychain_agent) mod kusama {
+	use crate::agents::relaychain_agent::call::*;
 
 	#[derive(Encode, Decode, RuntimeDebug)]
-	pub enum RelayCall<T: Config> {
+	pub(in crate::agents::relaychain_agent) enum RelayCall<T: Config> {
 		#[codec(index = 20)]
 		ConvictionVoting(ConvictionVoting<T>),
 		#[codec(index = 24)]
@@ -44,11 +43,11 @@ mod kusama {
 }
 
 #[cfg(feature = "polkadot")]
-mod polkadot {
-	use crate::*;
+pub(in crate::agents::relaychain_agent) mod polkadot {
+	use crate::agents::relaychain_agent::call::*;
 
 	#[derive(Encode, Decode, RuntimeDebug)]
-	pub enum RelayCall<T: Config> {
+	pub(in crate::agents::relaychain_agent) enum RelayCall<T: Config> {
 		#[codec(index = 20)]
 		ConvictionVoting(ConvictionVoting<T>),
 		#[codec(index = 26)]
@@ -57,7 +56,7 @@ mod polkadot {
 }
 
 #[derive(Encode, Decode, RuntimeDebug, Clone)]
-pub enum ConvictionVoting<T: Config> {
+pub(in crate::agents::relaychain_agent) enum ConvictionVoting<T: Config> {
 	#[codec(index = 0)]
 	Vote(#[codec(compact)] PollIndex, AccountVote<BalanceOf<T>>),
 	#[codec(index = 3)]
@@ -66,12 +65,6 @@ pub enum ConvictionVoting<T: Config> {
 	RemoveVote(Option<PollClass>, PollIndex),
 }
 
-pub trait ConvictionVotingCall<T: Config> {
-	fn vote(poll_index: PollIndex, vote: AccountVote<BalanceOf<T>>) -> Self;
-
-	fn remove_vote(class: Option<PollClass>, poll_index: PollIndex) -> Self;
-}
-
 impl<T: Config> ConvictionVotingCall<T> for RelayCall<T> {
 	fn vote(poll_index: PollIndex, vote: AccountVote<BalanceOf<T>>) -> Self {
 		Self::ConvictionVoting(ConvictionVoting::Vote(poll_index, vote))
@@ -83,19 +76,13 @@ impl<T: Config> ConvictionVotingCall<T> for RelayCall<T> {
 }
 
 #[derive(Encode, Decode, RuntimeDebug, Clone)]
-pub enum Utility<Call> {
+pub(in crate::agents::relaychain_agent) enum Utility<Call> {
 	#[codec(index = 1)]
 	AsDerivative(DerivativeIndex, Box<Call>),
 	#[codec(index = 2)]
 	BatchAll(Vec<Call>),
 }
 
-pub trait UtilityCall<Call> {
-	fn as_derivative(derivative_index: DerivativeIndex, call: Call) -> Call;
-
-	fn batch_all(calls: Vec<Call>) -> Call;
-}
-
 impl<T: Config> UtilityCall<RelayCall<T>> for RelayCall<T> {
 	fn as_derivative(derivative_index: DerivativeIndex, call: Self) -> Self {
 		Self::Utility(Utility::AsDerivative(derivative_index, Box::new(call)))
diff --git a/pallets/vtoken-voting/src/agents/relaychain_agent/mod.rs b/pallets/vtoken-voting/src/agents/relaychain_agent/mod.rs
new file mode 100644
index 000000000..321c37045
--- /dev/null
+++ b/pallets/vtoken-voting/src/agents/relaychain_agent/mod.rs
@@ -0,0 +1,22 @@
+// 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 <https://www.gnu.org/licenses/>.
+
+pub mod agent;
+mod call;
+
+pub use agent::*;
diff --git a/pallets/vtoken-voting/src/lib.rs b/pallets/vtoken-voting/src/lib.rs
index 5d99397b8..95d4bd80b 100644
--- a/pallets/vtoken-voting/src/lib.rs
+++ b/pallets/vtoken-voting/src/lib.rs
@@ -27,41 +27,48 @@ mod mock;
 #[cfg(test)]
 mod tests;
 
-mod call;
+mod agents;
 mod vote;
 
 // pub mod migration;
+pub mod traits;
 pub mod weights;
 
-use crate::vote::{Casting, Tally, Voting};
-pub use crate::{
-	call::*,
-	vote::{AccountVote, PollStatus, ReferendumInfo, ReferendumStatus, VoteRole},
+pub use crate::vote::{AccountVote, PollStatus, ReferendumInfo, ReferendumStatus, VoteRole};
+use crate::{
+	agents::{BifrostAgent, RelaychainAgent},
+	traits::VotingAgent,
+	vote::{Casting, Tally, Voting},
 };
 use bifrost_primitives::{
-	currency::{VDOT, VKSM},
+	currency::{BNC, DOT, KSM, VBNC, VDOT, VKSM},
 	traits::{DerivativeAccountHandler, VTokenSupplyProvider, XcmDestWeightAndFeeHandler},
 	CurrencyId, DerivativeIndex, XcmOperationType,
 };
 use cumulus_primitives_core::{ParaId, QueryId, Response};
 use frame_support::{
-	dispatch::GetDispatchInfo,
+	dispatch::{GetDispatchInfo, PostDispatchInfo},
 	pallet_prelude::*,
 	traits::{Get, LockIdentifier},
 };
-use frame_system::pallet_prelude::{BlockNumberFor, *};
+use frame_system::{
+	pallet_prelude::{BlockNumberFor, *},
+	RawOrigin,
+};
 use orml_traits::{MultiCurrency, MultiLockableCurrency};
 pub use pallet::*;
+pub use pallet_conviction_voting::AccountVote as ConvictionVotingAccountVote;
 use pallet_conviction_voting::{Conviction, UnvoteScope, Vote};
 use sp_runtime::{
 	traits::{
-		BlockNumberProvider, Bounded, CheckedDiv, CheckedMul, Saturating, UniqueSaturatedInto, Zero,
+		BlockNumberProvider, Bounded, CheckedDiv, CheckedMul, Dispatchable, Saturating,
+		UniqueSaturatedInto, Zero,
 	},
 	ArithmeticError, Perbill,
 };
-use sp_std::prelude::*;
+use sp_std::{boxed::Box, vec::Vec};
 pub use weights::WeightInfo;
-use xcm::v4::{prelude::*, Weight as XcmWeight};
+use xcm::v4::{prelude::*, Location, Weight as XcmWeight};
 
 const CONVICTION_VOTING_ID: LockIdentifier = *b"vtvoting";
 
@@ -82,9 +89,12 @@ type VotingOf<T> =
 
 pub type ReferendumInfoOf<T> = ReferendumInfo<BlockNumberFor<T>, TallyOf<T>>;
 
+type VotingAgentBoxType<T> = Box<dyn VotingAgent<T>>;
+
 #[frame_support::pallet]
 pub mod pallet {
 	use super::*;
+	use frame_support::traits::CallerTrait;
 
 	/// The current storage version.
 	const STORAGE_VERSION: StorageVersion = StorageVersion::new(3);
@@ -102,7 +112,11 @@ pub mod pallet {
 
 		type RuntimeCall: IsType<<Self as pallet_xcm::Config>::RuntimeCall>
 			+ From<Call<Self>>
-			+ GetDispatchInfo;
+			+ GetDispatchInfo
+			+ Dispatchable<
+				RuntimeOrigin = <Self as Config>::RuntimeOrigin,
+				PostInfo = PostDispatchInfo,
+			> + Parameter;
 
 		type MultiCurrency: MultiLockableCurrency<AccountIdOf<Self>, CurrencyId = CurrencyId>;
 
@@ -110,12 +124,16 @@ pub mod pallet {
 
 		type ResponseOrigin: EnsureOrigin<
 			<Self as frame_system::Config>::RuntimeOrigin,
-			Success = xcm::v4::Location,
+			Success = Location,
 		>;
 
 		type XcmDestWeightAndFee: XcmDestWeightAndFeeHandler<CurrencyIdOf<Self>, BalanceOf<Self>>;
 
-		type DerivativeAccount: DerivativeAccountHandler<CurrencyIdOf<Self>, BalanceOf<Self>>;
+		type DerivativeAccount: DerivativeAccountHandler<
+			CurrencyIdOf<Self>,
+			BalanceOf<Self>,
+			AccountIdOf<Self>,
+		>;
 
 		type RelaychainBlockNumberProvider: BlockNumberProvider<BlockNumber = BlockNumberFor<Self>>;
 
@@ -136,11 +154,20 @@ pub mod pallet {
 
 		/// Weight information for extrinsics in this pallet.
 		type WeightInfo: WeightInfo;
+
+		type PalletsOrigin: CallerTrait<Self::AccountId>;
 	}
 
 	#[pallet::event]
 	#[pallet::generate_deposit(pub(super) fn deposit_event)]
 	pub enum Event<T: Config> {
+		/// A vote has been cast.
+		///
+		/// - `who`: The account that cast the vote.
+		/// - `vtoken`: The token used for voting.
+		/// - `poll_index`: The index of the poll being voted on.
+		/// - `token_vote`: The vote cast using the token.
+		/// - `delegator_vote`: The vote cast by a delegator.
 		Voted {
 			who: AccountIdOf<T>,
 			vtoken: CurrencyIdOf<T>,
@@ -148,61 +175,101 @@ pub mod pallet {
 			token_vote: AccountVote<BalanceOf<T>>,
 			delegator_vote: AccountVote<BalanceOf<T>>,
 		},
-		Unlocked {
-			who: AccountIdOf<T>,
-			vtoken: CurrencyIdOf<T>,
-			poll_index: PollIndex,
-		},
+
+		/// A user's vote has been unlocked, allowing them to retrieve their tokens.
+		///
+		/// - `who`: The account whose tokens are unlocked.
+		/// - `vtoken`: The token that was locked during voting.
+		/// - `poll_index`: The index of the poll associated with the unlocking.
+		Unlocked { who: AccountIdOf<T>, vtoken: CurrencyIdOf<T>, poll_index: PollIndex },
+
+		/// A delegator's vote has been removed.
+		///
+		/// - `who`: The account that dispatched remove_delegator_vote.
+		/// - `vtoken`: The token associated with the delegator's vote.
+		/// - `derivative_index`: The index of the derivative.
 		DelegatorVoteRemoved {
 			who: AccountIdOf<T>,
 			vtoken: CurrencyIdOf<T>,
 			derivative_index: DerivativeIndex,
 		},
-		DelegatorAdded {
-			vtoken: CurrencyIdOf<T>,
-			derivative_index: DerivativeIndex,
-		},
+
+		/// A delegator has been added.
+		///
+		/// - `vtoken`: The token associated with the delegator.
+		/// - `derivative_index`: The index of the derivative being added for the delegator.
+		DelegatorAdded { vtoken: CurrencyIdOf<T>, derivative_index: DerivativeIndex },
+
+		/// A new referendum information has been created.
+		///
+		/// - `vtoken`: The token associated with the referendum.
+		/// - `poll_index`: The index of the poll.
+		/// - `info`: The referendum information (details about the poll).
 		ReferendumInfoCreated {
 			vtoken: CurrencyIdOf<T>,
 			poll_index: PollIndex,
 			info: ReferendumInfoOf<T>,
 		},
+
+		/// Referendum information has been updated.
+		///
+		/// - `vtoken`: The token associated with the referendum.
+		/// - `poll_index`: The index of the poll.
+		/// - `info`: The updated referendum information.
 		ReferendumInfoSet {
 			vtoken: CurrencyIdOf<T>,
 			poll_index: PollIndex,
 			info: ReferendumInfoOf<T>,
 		},
-		VoteLockingPeriodSet {
-			vtoken: CurrencyIdOf<T>,
-			locking_period: BlockNumberFor<T>,
-		},
-		UndecidingTimeoutSet {
-			vtoken: CurrencyIdOf<T>,
-			undeciding_timeout: BlockNumberFor<T>,
-		},
-		ReferendumKilled {
-			vtoken: CurrencyIdOf<T>,
-			poll_index: PollIndex,
-		},
-		VoteNotified {
-			vtoken: CurrencyIdOf<T>,
-			poll_index: PollIndex,
-			success: bool,
-		},
+
+		/// The vote locking period has been set.
+		///
+		/// - `vtoken`: The token for which the locking period is being set.
+		/// - `locking_period`: The period for which votes will be locked (in block numbers).
+		VoteLockingPeriodSet { vtoken: CurrencyIdOf<T>, locking_period: BlockNumberFor<T> },
+
+		/// The undeciding timeout period has been set.
+		///
+		/// - `vtoken`: The token associated with the timeout.
+		/// - `undeciding_timeout`: The period of time before a poll is considered undecided.
+		UndecidingTimeoutSet { vtoken: CurrencyIdOf<T>, undeciding_timeout: BlockNumberFor<T> },
+
+		/// A referendum has been killed (cancelled or ended).
+		///
+		/// - `vtoken`: The token associated with the referendum.
+		/// - `poll_index`: The index of the poll being killed.
+		ReferendumKilled { vtoken: CurrencyIdOf<T>, poll_index: PollIndex },
+
+		/// A notification about the result of a vote has been sent.
+		///
+		/// - `vtoken`: The token associated with the poll.
+		/// - `poll_index`: The index of the poll.
+		/// - `success`: Whether the notification was successful or not.
+		VoteNotified { vtoken: CurrencyIdOf<T>, poll_index: PollIndex, success: bool },
+
+		/// A notification about the removal of a delegator's vote has been sent.
+		///
+		/// - `vtoken`: The token associated with the poll.
+		/// - `poll_index`: The index of the poll.
+		/// - `success`: Whether the notification was successful or not.
 		DelegatorVoteRemovedNotified {
 			vtoken: CurrencyIdOf<T>,
 			poll_index: PollIndex,
 			success: bool,
 		},
-		ResponseReceived {
-			responder: xcm::v4::Location,
-			query_id: QueryId,
-			response: Response,
-		},
-		VoteCapRatioSet {
-			vtoken: CurrencyIdOf<T>,
-			vote_cap_ratio: Perbill,
-		},
+
+		/// A response has been received from a specific location.
+		///
+		/// - `responder`: The location that sent the response.
+		/// - `query_id`: The ID of the query that was responded to.
+		/// - `response`: The content of the response.
+		ResponseReceived { responder: Location, query_id: QueryId, response: Response },
+
+		/// The vote cap ratio has been set.
+		///
+		/// - `vtoken`: The token associated with the cap.
+		/// - `vote_cap_ratio`: The maximum allowed ratio for the vote.
+		VoteCapRatioSet { vtoken: CurrencyIdOf<T>, vote_cap_ratio: Perbill },
 	}
 
 	#[pallet::error]
@@ -247,6 +314,8 @@ pub mod pallet {
 		InvalidConviction,
 		/// The given value is out of range.
 		OutOfRange,
+		InvalidCallDispatch,
+		CallDecodeFailed,
 	}
 
 	/// Information concerning any given referendum.
@@ -366,20 +435,25 @@ pub mod pallet {
 	#[pallet::genesis_config]
 	#[derive(frame_support::DefaultNoBound)]
 	pub struct GenesisConfig<T: Config> {
-		pub delegators: (CurrencyIdOf<T>, Vec<DerivativeIndex>),
+		pub delegators: Vec<(CurrencyIdOf<T>, Vec<DerivativeIndex>)>,
 		pub undeciding_timeouts: Vec<(CurrencyIdOf<T>, BlockNumberFor<T>)>,
-		pub vote_cap_ratio: (CurrencyIdOf<T>, Perbill),
+		pub vote_cap_ratio: Vec<(CurrencyIdOf<T>, Perbill)>,
 	}
 
 	#[pallet::genesis_build]
 	impl<T: Config> BuildGenesisConfig for GenesisConfig<T> {
 		fn build(&self) {
-			let (vtoken, delegators) = &self.delegators;
-			Delegators::<T>::insert(vtoken, BoundedVec::truncate_from(delegators.clone()));
+			self.delegators.iter().for_each(|(vtoken, delegators)| {
+				Delegators::<T>::insert(vtoken, BoundedVec::truncate_from(delegators.clone()));
+			});
+
 			self.undeciding_timeouts.iter().for_each(|(vtoken, undeciding_timeout)| {
 				UndecidingTimeout::<T>::insert(vtoken, undeciding_timeout);
 			});
-			VoteCapRatio::<T>::insert(self.vote_cap_ratio.0, self.vote_cap_ratio.1);
+
+			self.vote_cap_ratio.iter().for_each(|(vtoken, cap_ratio)| {
+				VoteCapRatio::<T>::insert(vtoken, cap_ratio);
+			});
 		}
 	}
 
@@ -435,7 +509,7 @@ pub mod pallet {
 		pub fn vote(
 			origin: OriginFor<T>,
 			vtoken: CurrencyIdOf<T>,
-			#[pallet::compact] poll_index: PollIndex,
+			poll_index: PollIndex,
 			vtoken_vote: AccountVote<BalanceOf<T>>,
 		) -> DispatchResult {
 			let who = ensure_signed(origin)?;
@@ -479,42 +553,14 @@ pub mod pallet {
 				Ok(())
 			})?;
 
-			// send XCM message
-			let vote_calls = new_delegator_votes
-				.iter()
-				.map(|(_derivative_index, vote)| {
-					<RelayCall<T> as ConvictionVotingCall<T>>::vote(poll_index, *vote)
-				})
-				.collect::<Vec<_>>();
-			let vote_call = if vote_calls.len() == 1 {
-				vote_calls.into_iter().nth(0).ok_or(Error::<T>::NoData)?
-			} else {
-				ensure!(false, Error::<T>::NoPermissionYet);
-				<RelayCall<T> as UtilityCall<RelayCall<T>>>::batch_all(vote_calls)
-			};
-			let notify_call = Call::<T>::notify_vote { query_id: 0, response: Default::default() };
-			let (weight, extra_fee) = T::XcmDestWeightAndFee::get_operation_weight_and_fee(
-				CurrencyId::to_token(&vtoken).map_err(|_| Error::<T>::NoData)?,
-				XcmOperationType::Vote,
-			)
-			.ok_or(Error::<T>::NoData)?;
-
-			let derivative_index = new_delegator_votes[0].0;
-			Self::send_xcm_with_notify(
-				derivative_index,
-				vote_call,
-				notify_call,
-				weight,
-				extra_fee,
-				|query_id| {
-					if !submitted {
-						PendingReferendumInfo::<T>::insert(query_id, (vtoken, poll_index));
-					}
-					PendingVotingInfo::<T>::insert(
-						query_id,
-						(vtoken, poll_index, derivative_index, who.clone(), maybe_old_vote),
-					)
-				},
+			let voting_agent = Self::get_voting_agent(&vtoken)?;
+			voting_agent.delegate_vote(
+				who.clone(),
+				vtoken,
+				poll_index,
+				submitted,
+				new_delegator_votes.clone(),
+				maybe_old_vote,
 			)?;
 
 			Self::deposit_event(Event::<T>::Voted {
@@ -567,29 +613,12 @@ pub mod pallet {
 			ensure!(DelegatorVotes::<T>::get(vtoken, poll_index).len() > 0, Error::<T>::NoData);
 			Self::ensure_referendum_expired(vtoken, poll_index)?;
 
-			let notify_call = Call::<T>::notify_remove_delegator_vote {
-				query_id: 0,
-				response: Default::default(),
-			};
-			let remove_vote_call =
-				<RelayCall<T> as ConvictionVotingCall<T>>::remove_vote(Some(class), poll_index);
-			let (weight, extra_fee) = T::XcmDestWeightAndFee::get_operation_weight_and_fee(
-				CurrencyId::to_token(&vtoken).map_err(|_| Error::<T>::NoData)?,
-				XcmOperationType::RemoveVote,
-			)
-			.ok_or(Error::<T>::NoData)?;
-			Self::send_xcm_with_notify(
+			let voting_agent = Self::get_voting_agent(&vtoken)?;
+			voting_agent.delegate_remove_delegator_vote(
+				vtoken,
+				poll_index,
+				class,
 				derivative_index,
-				remove_vote_call,
-				notify_call,
-				weight,
-				extra_fee,
-				|query_id| {
-					PendingRemoveDelegatorVote::<T>::insert(
-						query_id,
-						(vtoken, poll_index, derivative_index),
-					);
-				},
 			)?;
 
 			Self::deposit_event(Event::<T>::DelegatorVoteRemoved { who, vtoken, derivative_index });
@@ -710,33 +739,15 @@ pub mod pallet {
 			if let Some((vtoken, poll_index, derivative_index, who, maybe_old_vote)) =
 				PendingVotingInfo::<T>::get(query_id)
 			{
-				if !success {
-					// rollback vote
-					let _ = PendingDelegatorVotes::<T>::clear(u32::MAX, None);
-					Self::try_remove_vote(&who, vtoken, poll_index, UnvoteScope::Any)?;
-					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)?;
-					}
-				} else {
-					if !VoteDelegatorFor::<T>::contains_key((&who, vtoken, poll_index)) {
-						VoteDelegatorFor::<T>::insert((&who, vtoken, poll_index), derivative_index);
-					}
-					DelegatorVotes::<T>::remove(vtoken, poll_index);
-					DelegatorVotes::<T>::try_mutate(
-						vtoken,
-						poll_index,
-						|item| -> DispatchResult {
-							for (derivative_index, vote) in
-								PendingDelegatorVotes::<T>::take(vtoken, poll_index).iter()
-							{
-								item.try_push((*derivative_index, *vote))
-									.map_err(|_| Error::<T>::TooMany)?;
-							}
-							Ok(())
-						},
-					)?;
-				}
+				Self::handle_vote_result(
+					success,
+					who,
+					vtoken,
+					poll_index,
+					maybe_old_vote,
+					derivative_index,
+				)?;
+
 				PendingVotingInfo::<T>::remove(query_id);
 				Self::deposit_event(Event::<T>::VoteNotified { vtoken, poll_index, success });
 			}
@@ -797,7 +808,7 @@ pub mod pallet {
 			{
 				let success = Response::DispatchResult(MaybeErrorCode::Success) == response;
 				if success {
-					DelegatorVotes::<T>::remove(vtoken, poll_index);
+					Self::handle_remove_delegator_vote_success(vtoken, poll_index);
 				}
 				PendingRemoveDelegatorVote::<T>::remove(query_id);
 				Self::deposit_event(Event::<T>::DelegatorVoteRemovedNotified {
@@ -828,6 +839,201 @@ pub mod pallet {
 	}
 
 	impl<T: Config> Pallet<T> {
+		pub(crate) fn handle_remove_delegator_vote_success(
+			vtoken: CurrencyIdOf<T>,
+			poll_index: PollIndex,
+		) {
+			DelegatorVotes::<T>::remove(vtoken, poll_index);
+		}
+
+		pub(crate) fn handle_vote_result(
+			success: bool,
+			who: AccountIdOf<T>,
+			vtoken: CurrencyIdOf<T>,
+			poll_index: PollIndex,
+			maybe_old_vote: Option<(AccountVote<BalanceOf<T>>, BalanceOf<T>)>,
+			derivative_index: DerivativeIndex,
+		) -> DispatchResult {
+			if !success {
+				// rollback vote
+				let _ = PendingDelegatorVotes::<T>::clear(u32::MAX, None);
+				Self::try_remove_vote(&who, vtoken, poll_index, UnvoteScope::Any)?;
+				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)?;
+				}
+			} else {
+				if !VoteDelegatorFor::<T>::contains_key((&who, vtoken, poll_index)) {
+					VoteDelegatorFor::<T>::insert((&who, vtoken, poll_index), derivative_index);
+				}
+				DelegatorVotes::<T>::remove(vtoken, poll_index);
+				DelegatorVotes::<T>::try_mutate(vtoken, poll_index, |item| -> DispatchResult {
+					for (derivative_index, vote) in
+						PendingDelegatorVotes::<T>::take(vtoken, poll_index).iter()
+					{
+						item.try_push((*derivative_index, *vote))
+							.map_err(|_| Error::<T>::TooMany)?;
+					}
+					Ok(())
+				})?;
+			}
+
+			Ok(())
+		}
+
+		pub(crate) fn send_xcm_vote_message(
+			who: AccountIdOf<T>,
+			vtoken: CurrencyIdOf<T>,
+			poll_index: PollIndex,
+			submitted: bool,
+			new_delegator_votes: Vec<(DerivativeIndex, AccountVote<BalanceOf<T>>)>,
+			maybe_old_vote: Option<(AccountVote<BalanceOf<T>>, BalanceOf<T>)>,
+		) -> DispatchResult {
+			let notify_call = Call::<T>::notify_vote { query_id: 0, response: Default::default() };
+			let (weight, extra_fee) = T::XcmDestWeightAndFee::get_operation_weight_and_fee(
+				CurrencyId::to_token(&vtoken).map_err(|_| Error::<T>::NoData)?,
+				XcmOperationType::Vote,
+			)
+			.ok_or(Error::<T>::NoData)?;
+
+			let derivative_index = new_delegator_votes[0].0;
+
+			let voting_agent = Self::get_voting_agent(&vtoken)?;
+			let encode_call = voting_agent.vote_call_encode(
+				new_delegator_votes.clone(),
+				poll_index,
+				derivative_index,
+			)?;
+
+			Self::send_xcm_with_notify(
+				voting_agent.location(),
+				encode_call,
+				notify_call,
+				weight,
+				extra_fee,
+				|query_id| {
+					if !submitted {
+						PendingReferendumInfo::<T>::insert(query_id, (vtoken, poll_index));
+					}
+					PendingVotingInfo::<T>::insert(
+						query_id,
+						(vtoken, poll_index, derivative_index, who.clone(), maybe_old_vote),
+					)
+				},
+			)?;
+
+			Ok(())
+		}
+
+		pub(crate) fn send_xcm_remove_delegator_vote_message(
+			vtoken: CurrencyIdOf<T>,
+			poll_index: PollIndex,
+			class: PollClass,
+			derivative_index: DerivativeIndex,
+		) -> DispatchResult {
+			let voting_agent = Self::get_voting_agent(&vtoken)?;
+			let encode_call = voting_agent.remove_delegator_vote_call_encode(
+				class,
+				poll_index,
+				derivative_index,
+			)?;
+			let notify_call = Call::<T>::notify_remove_delegator_vote {
+				query_id: 0,
+				response: Default::default(),
+			};
+
+			let (weight, extra_fee) = T::XcmDestWeightAndFee::get_operation_weight_and_fee(
+				CurrencyId::to_token(&vtoken).map_err(|_| Error::<T>::NoData)?,
+				XcmOperationType::RemoveVote,
+			)
+			.ok_or(Error::<T>::NoData)?;
+
+			Self::send_xcm_with_notify(
+				voting_agent.location(),
+				encode_call,
+				notify_call,
+				weight,
+				extra_fee,
+				|query_id| {
+					PendingRemoveDelegatorVote::<T>::insert(
+						query_id,
+						(vtoken, poll_index, derivative_index),
+					);
+				},
+			)?;
+
+			Ok(())
+		}
+
+		pub(crate) fn send_xcm_with_notify(
+			responder_location: Location,
+			encode_call: Vec<u8>,
+			notify_call: Call<T>,
+			transact_weight: XcmWeight,
+			extra_fee: BalanceOf<T>,
+			f: impl FnOnce(QueryId) -> (),
+		) -> DispatchResult {
+			let now = frame_system::Pallet::<T>::block_number();
+			let timeout = now.saturating_add(T::QueryTimeout::get());
+			let notify_runtime_call = <T as Config>::RuntimeCall::from(notify_call);
+			let notify_call_weight = notify_runtime_call.get_dispatch_info().weight;
+			let query_id = pallet_xcm::Pallet::<T>::new_notify_query(
+				responder_location.clone(),
+				notify_runtime_call,
+				timeout,
+				xcm::v4::Junctions::Here,
+			);
+			f(query_id);
+
+			let xcm_message = Self::construct_xcm_message(
+				encode_call,
+				extra_fee,
+				transact_weight,
+				notify_call_weight,
+				query_id,
+			)?;
+
+			xcm::v4::send_xcm::<T::XcmRouter>(responder_location, xcm_message)
+				.map_err(|_| Error::<T>::XcmFailure)?;
+
+			Ok(())
+		}
+
+		pub(crate) fn construct_xcm_message(
+			call: Vec<u8>,
+			extra_fee: BalanceOf<T>,
+			transact_weight: XcmWeight,
+			notify_call_weight: XcmWeight,
+			query_id: QueryId,
+		) -> Result<Xcm<()>, Error<T>> {
+			let para_id = T::ParachainId::get().into();
+			let asset = Asset {
+				id: AssetId(Location::here()),
+				fun: Fungible(UniqueSaturatedInto::<u128>::unique_saturated_into(extra_fee)),
+			};
+			let xcm_message = sp_std::vec![
+				WithdrawAsset(asset.clone().into()),
+				BuyExecution { fees: asset, weight_limit: Unlimited },
+				Transact {
+					origin_kind: OriginKind::SovereignAccount,
+					require_weight_at_most: transact_weight,
+					call: call.into(),
+				},
+				ReportTransactStatus(QueryResponseInfo {
+					destination: Location::from(Parachain(para_id)),
+					query_id,
+					max_weight: notify_call_weight,
+				}),
+				RefundSurplus,
+				DepositAsset {
+					assets: All.into(),
+					beneficiary: Location::new(0, [Parachain(para_id)]),
+				},
+			];
+
+			Ok(Xcm(xcm_message))
+		}
+
 		fn try_vote(
 			who: &AccountIdOf<T>,
 			vtoken: CurrencyIdOf<T>,
@@ -1004,79 +1210,8 @@ pub mod pallet {
 			}
 		}
 
-		fn send_xcm_with_notify(
-			derivative_index: DerivativeIndex,
-			call: RelayCall<T>,
-			notify_call: Call<T>,
-			transact_weight: XcmWeight,
-			extra_fee: BalanceOf<T>,
-			f: impl FnOnce(QueryId) -> (),
-		) -> DispatchResult {
-			let responder = xcm::v4::Location::parent();
-			let now = frame_system::Pallet::<T>::block_number();
-			let timeout = now.saturating_add(T::QueryTimeout::get());
-			let notify_runtime_call = <T as Config>::RuntimeCall::from(notify_call);
-			let notify_call_weight = notify_runtime_call.get_dispatch_info().weight;
-			let query_id = pallet_xcm::Pallet::<T>::new_notify_query(
-				responder,
-				notify_runtime_call,
-				timeout,
-				xcm::v4::Junctions::Here,
-			);
-			f(query_id);
-
-			let xcm_message = Self::construct_xcm_message(
-				<RelayCall<T> as UtilityCall<RelayCall<T>>>::as_derivative(derivative_index, call)
-					.encode(),
-				extra_fee,
-				transact_weight,
-				notify_call_weight,
-				query_id,
-			)?;
-
-			xcm::v4::send_xcm::<T::XcmRouter>(Parent.into(), xcm_message)
-				.map_err(|_e| Error::<T>::XcmFailure)?;
-
-			Ok(())
-		}
-
-		fn construct_xcm_message(
-			call: Vec<u8>,
-			extra_fee: BalanceOf<T>,
-			transact_weight: XcmWeight,
-			notify_call_weight: XcmWeight,
-			query_id: QueryId,
-		) -> Result<Xcm<()>, Error<T>> {
-			let para_id = T::ParachainId::get().into();
-			let asset = Asset {
-				id: AssetId(Location::here()),
-				fun: Fungible(UniqueSaturatedInto::<u128>::unique_saturated_into(extra_fee)),
-			};
-			let xcm_message = sp_std::vec![
-				WithdrawAsset(asset.clone().into()),
-				BuyExecution { fees: asset, weight_limit: Unlimited },
-				Transact {
-					origin_kind: OriginKind::SovereignAccount,
-					require_weight_at_most: transact_weight,
-					call: call.into(),
-				},
-				ReportTransactStatus(QueryResponseInfo {
-					destination: Location::from(Parachain(para_id)),
-					query_id,
-					max_weight: notify_call_weight,
-				}),
-				RefundSurplus,
-				DepositAsset {
-					assets: All.into(),
-					beneficiary: Location::new(0, [Parachain(para_id)]),
-				},
-			];
-
-			Ok(Xcm(xcm_message))
-		}
-
 		fn ensure_vtoken(vtoken: &CurrencyIdOf<T>) -> Result<(), DispatchError> {
-			ensure!([VKSM, VDOT].contains(vtoken), Error::<T>::VTokenNotSupport);
+			ensure!([VKSM, VDOT, VBNC].contains(vtoken), Error::<T>::VTokenNotSupport);
 			Ok(())
 		}
 
@@ -1156,7 +1291,7 @@ pub mod pallet {
 
 		fn ensure_xcm_response_or_governance(
 			origin: OriginFor<T>,
-		) -> Result<xcm::v4::Location, DispatchError> {
+		) -> Result<Location, DispatchError> {
 			let responder = T::ResponseOrigin::ensure_origin(origin.clone()).or_else(|_| {
 				T::ControlOrigin::ensure_origin(origin).map(|_| xcm::v4::Junctions::Here.into())
 			})?;
@@ -1293,5 +1428,26 @@ pub mod pallet {
 
 			Ok(delegator_votes)
 		}
+
+		pub(crate) fn get_voting_agent(
+			currency_id: &CurrencyIdOf<T>,
+		) -> Result<VotingAgentBoxType<T>, Error<T>> {
+			match *currency_id {
+				VKSM | VDOT => Ok(Box::new(RelaychainAgent::<T>::new(*currency_id)?)),
+				VBNC => Ok(Box::new(BifrostAgent::<T>::new(*currency_id)?)),
+				_ => Err(Error::<T>::VTokenNotSupport),
+			}
+		}
+
+		pub(crate) fn convert_vtoken_to_dest_location(
+			vtoken: CurrencyId,
+		) -> Result<Location, Error<T>> {
+			let token = CurrencyId::to_token(&vtoken).map_err(|_| Error::<T>::NoData)?;
+			match token {
+				KSM | DOT => Ok(Location::parent()),
+				BNC => Ok(Location::new(1, [Parachain(T::ParachainId::get().into())])),
+				_ => Err(Error::<T>::VTokenNotSupport),
+			}
+		}
 	}
 }
diff --git a/pallets/vtoken-voting/src/mock.rs b/pallets/vtoken-voting/src/mock.rs
index 16a6adfc6..397c7f9a9 100644
--- a/pallets/vtoken-voting/src/mock.rs
+++ b/pallets/vtoken-voting/src/mock.rs
@@ -21,24 +21,26 @@
 use crate as vtoken_voting;
 use crate::{BalanceOf, DerivativeAccountHandler, DerivativeIndex, DispatchResult};
 use bifrost_primitives::{
-	currency::{KSM, VBNC, VKSM},
+	currency::{DOT, KSM, VBNC, VDOT, VKSM},
 	traits::XcmDestWeightAndFeeHandler,
 	CurrencyId, MockXcmRouter, VTokenSupplyProvider, XcmOperationType, BNC,
 };
 use cumulus_primitives_core::ParaId;
 use frame_support::{
 	derive_impl, ord_parameter_types,
-	pallet_prelude::Weight,
+	pallet_prelude::{DispatchError, Weight},
 	parameter_types,
-	traits::{Everything, Get, Nothing},
+	traits::{ConstU64, Everything, Get, Nothing, PollStatus, Polling, VoteTally},
 	weights::RuntimeDbWeight,
 };
 use frame_system::EnsureRoot;
+use pallet_conviction_voting::{Tally, TallyOf};
 use pallet_xcm::EnsureResponse;
 use sp_runtime::{
 	traits::{BlockNumberProvider, ConstU32, IdentityLookup},
 	BuildStorage, Perbill,
 };
+use std::collections::BTreeMap;
 use xcm::{prelude::*, v3::MultiLocation};
 use xcm_builder::{FixedWeightBounds, FrameTransactionalProcessor};
 use xcm_executor::XcmExecutor;
@@ -63,6 +65,7 @@ frame_support::construct_runtime!(
 		Currencies: bifrost_currencies,
 		PolkadotXcm: pallet_xcm,
 		VtokenVoting: vtoken_voting,
+		ConvictionVoting: pallet_conviction_voting = 36,
 	}
 );
 
@@ -103,7 +106,7 @@ impl pallet_balances::Config for Runtime {
 	type DustRemoval = ();
 	type RuntimeEvent = RuntimeEvent;
 	type ExistentialDeposit = ExistentialDeposit;
-	type MaxLocks = ();
+	type MaxLocks = ConstU32<100>;
 	type MaxReserves = ();
 	type ReserveIdentifier = [u8; 8];
 	type WeightInfo = ();
@@ -113,10 +116,107 @@ impl pallet_balances::Config for Runtime {
 	type MaxFreezes = ConstU32<0>;
 }
 
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub enum TestPollState {
+	Ongoing(TallyOf<Runtime>, u8),
+	Completed(u64, bool),
+}
+use TestPollState::*;
+
+parameter_types! {
+	pub static Polls: BTreeMap<u8, TestPollState> = (0u8..=255)
+		.map(|i| (i, Ongoing(Tally::from_parts(0, 0, 0), 0)))
+		.collect();
+}
+
+pub struct TestPolls;
+impl Polling<TallyOf<Runtime>> for TestPolls {
+	type Index = u8;
+	type Votes = u128;
+	type Moment = u64;
+	type Class = u8;
+	fn classes() -> Vec<u8> {
+		vec![0, 1, 2]
+	}
+	fn as_ongoing(index: u8) -> Option<(TallyOf<Runtime>, Self::Class)> {
+		Polls::get().remove(&index).and_then(|x| {
+			if let TestPollState::Ongoing(t, c) = x {
+				Some((t, c))
+			} else {
+				None
+			}
+		})
+	}
+	fn access_poll<R>(
+		index: Self::Index,
+		f: impl FnOnce(PollStatus<&mut TallyOf<Runtime>, u64, u8>) -> R,
+	) -> R {
+		let mut polls = Polls::get();
+		let entry = polls.get_mut(&index);
+		let r = match entry {
+			Some(Ongoing(ref mut tally_mut_ref, class)) =>
+				f(PollStatus::Ongoing(tally_mut_ref, *class)),
+			Some(Completed(when, succeeded)) => f(PollStatus::Completed(*when, *succeeded)),
+			None => f(PollStatus::None),
+		};
+		Polls::set(polls);
+		r
+	}
+	fn try_access_poll<R>(
+		index: Self::Index,
+		f: impl FnOnce(PollStatus<&mut TallyOf<Runtime>, u64, u8>) -> Result<R, DispatchError>,
+	) -> Result<R, DispatchError> {
+		let mut polls = Polls::get();
+		let entry = polls.get_mut(&index);
+		let r = match entry {
+			Some(Ongoing(ref mut tally_mut_ref, class)) =>
+				f(PollStatus::Ongoing(tally_mut_ref, *class)),
+			Some(Completed(when, succeeded)) => f(PollStatus::Completed(*when, *succeeded)),
+			None => f(PollStatus::None),
+		}?;
+		Polls::set(polls);
+		Ok(r)
+	}
+
+	#[cfg(feature = "runtime-benchmarks")]
+	fn create_ongoing(class: Self::Class) -> Result<Self::Index, ()> {
+		let mut polls = Polls::get();
+		let i = polls.keys().rev().next().map_or(0, |x| x + 1);
+		polls.insert(i, Ongoing(Tally::new(0), class));
+		Polls::set(polls);
+		Ok(i)
+	}
+
+	#[cfg(feature = "runtime-benchmarks")]
+	fn end_ongoing(index: Self::Index, approved: bool) -> Result<(), ()> {
+		let mut polls = Polls::get();
+		match polls.get(&index) {
+			Some(Ongoing(..)) => {},
+			_ => return Err(()),
+		}
+		let now = frame_system::Pallet::<Runtime>::block_number();
+		polls.insert(index, Completed(now, approved));
+		Polls::set(polls);
+		Ok(())
+	}
+}
+
+impl pallet_conviction_voting::Config for Runtime {
+	type WeightInfo = ();
+	type RuntimeEvent = RuntimeEvent;
+	type Currency = Balances;
+	type VoteLockingPeriod = ConstU64<3>;
+	type MaxVotes = ConstU32<512>;
+	type MaxTurnout = frame_support::traits::TotalIssuanceOf<Balances, Self::AccountId>;
+	type Polls = TestPolls;
+}
+
 orml_traits::parameter_type_with_key! {
 	pub ExistentialDeposits: |currency_id: CurrencyId| -> Balance {
 		match currency_id {
+			&DOT => 0,
 			&KSM => 0,
+			&VDOT => 0,
 			&VBNC => 0,
 			&VKSM => 0,
 			_ => 0,
@@ -239,7 +339,7 @@ impl XcmDestWeightAndFeeHandler<CurrencyId, BalanceOf<Runtime>> for XcmDestWeigh
 }
 
 pub struct DerivativeAccount;
-impl DerivativeAccountHandler<CurrencyId, Balance> for DerivativeAccount {
+impl DerivativeAccountHandler<CurrencyId, Balance, AccountId> for DerivativeAccount {
 	fn check_derivative_index_exists(
 		_token: CurrencyId,
 		_derivative_index: DerivativeIndex,
@@ -254,6 +354,10 @@ impl DerivativeAccountHandler<CurrencyId, Balance> for DerivativeAccount {
 		Some(xcm::v3::Parent.into())
 	}
 
+	fn get_account_id(_token: CurrencyId, _derivative_index: DerivativeIndex) -> Option<AccountId> {
+		Some(CHARLIE)
+	}
+
 	fn get_stake_info(
 		token: CurrencyId,
 		derivative_index: DerivativeIndex,
@@ -337,26 +441,51 @@ impl vtoken_voting::Config for Runtime {
 	type QueryTimeout = QueryTimeout;
 	type ReferendumCheckInterval = ReferendumCheckInterval;
 	type WeightInfo = ();
+	type PalletsOrigin = OriginCaller;
 }
 
 pub fn new_test_ext() -> sp_io::TestExternalities {
 	let mut t = frame_system::GenesisConfig::<Runtime>::default().build_storage().unwrap();
 	pallet_balances::GenesisConfig::<Runtime> {
-		balances: vec![(ALICE, 10), (BOB, 20), (CHARLIE, 30)],
+		balances: vec![(ALICE, 10), (BOB, 20), (CHARLIE, 3000)],
 	}
 	.assimilate_storage(&mut t)
 	.unwrap();
 
 	orml_tokens::GenesisConfig::<Runtime> {
-		balances: vec![(1, VKSM, 10), (2, VKSM, 20), (3, VKSM, 30), (4, VKSM, 40), (5, VKSM, 50)],
+		balances: vec![
+			(1, VKSM, 10),
+			(2, VKSM, 20),
+			(3, VKSM, 30),
+			(4, VKSM, 40),
+			(5, VKSM, 50),
+			(1, VDOT, 10),
+			(2, VDOT, 20),
+			(3, VDOT, 30),
+			(4, VDOT, 40),
+			(5, VDOT, 50),
+			(1, VBNC, 10),
+			(2, VBNC, 20),
+			(3, VBNC, 30),
+			(4, VBNC, 40),
+			(5, VBNC, 50),
+		],
 	}
 	.assimilate_storage(&mut t)
 	.unwrap();
 
 	vtoken_voting::GenesisConfig::<Runtime> {
-		delegators: (VKSM, vec![0, 1, 2, 3, 4, 5, 10, 11, 15, 20, 21]),
-		undeciding_timeouts: vec![(VKSM, 100)],
-		vote_cap_ratio: (VKSM, Perbill::from_percent(10)),
+		delegators: vec![
+			(VKSM, vec![0, 1, 2, 3, 4, 5, 10, 11, 15, 20, 21]),
+			(VDOT, vec![0, 1, 2, 3, 4, 5, 10, 11, 15, 20, 21]),
+			(VBNC, vec![0, 1, 2, 3, 4, 5, 10, 11, 15, 20, 21]),
+		],
+		undeciding_timeouts: vec![(VDOT, 100), (VKSM, 100), (VBNC, 100)],
+		vote_cap_ratio: vec![
+			(VDOT, Perbill::from_percent(10)),
+			(VKSM, Perbill::from_percent(10)),
+			(VBNC, Perbill::from_percent(10)),
+		],
 	}
 	.assimilate_storage(&mut t)
 	.unwrap();
diff --git a/pallets/vtoken-voting/src/tests.rs b/pallets/vtoken-voting/src/tests.rs
deleted file mode 100644
index de56e74e0..000000000
--- a/pallets/vtoken-voting/src/tests.rs
+++ /dev/null
@@ -1,1379 +0,0 @@
-// 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 <https://www.gnu.org/licenses/>.
-
-// Ensure we're `no_std` when compiling for Wasm.
-
-use super::*;
-use crate::mock::*;
-use bifrost_primitives::currency::{VBNC, VKSM};
-use frame_support::{
-	assert_noop, assert_ok,
-	traits::{
-		fungibles::Inspect,
-		tokens::{Fortitude::Polite, Preservation::Expendable},
-	},
-	weights::RuntimeDbWeight,
-};
-use pallet_conviction_voting::Vote;
-use pallet_xcm::Origin as XcmOrigin;
-
-fn aye(amount: Balance, conviction: u8) -> AccountVote<Balance> {
-	let vote = Vote { aye: true, conviction: conviction.try_into().unwrap() };
-	AccountVote::Standard { vote, balance: amount }
-}
-
-fn nay(amount: Balance, conviction: u8) -> AccountVote<Balance> {
-	let vote = Vote { aye: false, conviction: conviction.try_into().unwrap() };
-	AccountVote::Standard { vote, balance: amount }
-}
-
-fn tally(vtoken: CurrencyId, poll_index: u32) -> TallyOf<Runtime> {
-	VtokenVoting::ensure_referendum_ongoing(vtoken, poll_index)
-		.expect("No poll")
-		.tally
-}
-
-fn usable_balance(vtoken: CurrencyId, who: &AccountId) -> Balance {
-	Tokens::reducible_balance(vtoken, who, Expendable, Polite)
-}
-
-fn origin_response() -> RuntimeOrigin {
-	XcmOrigin::Response(Parent.into()).into()
-}
-
-fn response_success() -> Response {
-	Response::DispatchResult(MaybeErrorCode::Success)
-}
-
-fn response_fail() -> Response {
-	Response::DispatchResult(MaybeErrorCode::Error(BoundedVec::try_from(vec![0u8, 1u8]).unwrap()))
-}
-
-#[test]
-fn basic_voting_works() {
-	new_test_ext().execute_with(|| {
-		let poll_index = 3;
-		let vtoken = VKSM;
-
-		assert_ok!(VtokenVoting::vote(RuntimeOrigin::signed(ALICE), vtoken, poll_index, aye(2, 5)));
-		assert_eq!(tally(vtoken, poll_index), Tally::from_parts(20, 0, 4));
-		System::assert_last_event(RuntimeEvent::VtokenVoting(Event::Voted {
-			who: ALICE,
-			vtoken,
-			poll_index,
-			token_vote: aye(4, 5),
-			delegator_vote: aye(200, 0),
-		}));
-		assert_ok!(VtokenVoting::notify_vote(origin_response(), 0, response_success()));
-
-		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));
-		assert_eq!(usable_balance(vtoken, &ALICE), 10);
-	});
-}
-
-#[test]
-fn voting_balance_gets_locked() {
-	new_test_ext().execute_with(|| {
-		let poll_index = 3;
-		let vtoken = VKSM;
-
-		assert_ok!(VtokenVoting::vote(
-			RuntimeOrigin::signed(ALICE),
-			vtoken,
-			poll_index,
-			nay(10, 0)
-		));
-		assert_eq!(tally(vtoken, poll_index), Tally::from_parts(0, 2, 0));
-		assert_ok!(VtokenVoting::notify_vote(origin_response(), 0, response_success()));
-		assert_eq!(usable_balance(vtoken, &ALICE), 0);
-
-		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));
-		assert_eq!(usable_balance(vtoken, &ALICE), 10);
-	});
-}
-
-#[test]
-fn successful_but_zero_conviction_vote_balance_can_be_unlocked() {
-	new_test_ext().execute_with(|| {
-		let poll_index = 3;
-		let vtoken = VKSM;
-
-		assert_ok!(VtokenVoting::vote(RuntimeOrigin::signed(ALICE), vtoken, poll_index, aye(1, 1)));
-		assert_eq!(usable_balance(vtoken, &ALICE), 9);
-		assert_ok!(VtokenVoting::notify_vote(origin_response(), 0, response_success()));
-		assert_ok!(VtokenVoting::vote(RuntimeOrigin::signed(ALICE), vtoken, poll_index, aye(3, 1)));
-		assert_eq!(usable_balance(vtoken, &ALICE), 7);
-		assert_ok!(VtokenVoting::notify_vote(origin_response(), 1, response_success()));
-
-		assert_ok!(VtokenVoting::vote(RuntimeOrigin::signed(BOB), vtoken, poll_index, nay(20, 0)));
-		assert_eq!(usable_balance(vtoken, &BOB), 0);
-		assert_ok!(VtokenVoting::notify_vote(origin_response(), 2, response_success()));
-
-		assert_ok!(VtokenVoting::set_vote_locking_period(RuntimeOrigin::root(), vtoken, 10));
-		assert_ok!(VtokenVoting::set_referendum_status(
-			RuntimeOrigin::root(),
-			vtoken,
-			poll_index,
-			ReferendumInfoOf::<Runtime>::Completed(3),
-		));
-
-		assert_ok!(VtokenVoting::unlock(RuntimeOrigin::signed(BOB), vtoken, poll_index));
-		assert_eq!(usable_balance(vtoken, &BOB), 20);
-
-		RelaychainDataProvider::set_block_number(13);
-		assert_ok!(VtokenVoting::unlock(RuntimeOrigin::signed(ALICE), vtoken, poll_index));
-		assert_eq!(usable_balance(vtoken, &ALICE), 10);
-	});
-}
-
-#[test]
-fn unsuccessful_conviction_vote_balance_can_be_unlocked() {
-	new_test_ext().execute_with(|| {
-		let poll_index = 3;
-		let vtoken = VKSM;
-		let locking_period = 10;
-		assert_ok!(VtokenVoting::set_vote_locking_period(
-			RuntimeOrigin::root(),
-			vtoken,
-			locking_period,
-		));
-
-		assert_ok!(VtokenVoting::vote(RuntimeOrigin::signed(ALICE), vtoken, poll_index, aye(1, 1)));
-		assert_ok!(VtokenVoting::notify_vote(origin_response(), 0, response_success()));
-		assert_ok!(VtokenVoting::vote(RuntimeOrigin::signed(BOB), vtoken, poll_index, nay(20, 0)));
-		assert_ok!(VtokenVoting::notify_vote(origin_response(), 1, response_success()));
-
-		assert_ok!(VtokenVoting::set_referendum_status(
-			RuntimeOrigin::root(),
-			vtoken,
-			poll_index,
-			ReferendumInfoOf::<Runtime>::Completed(3),
-		));
-		RelaychainDataProvider::set_block_number(13);
-		assert_ok!(VtokenVoting::try_remove_vote(&ALICE, vtoken, poll_index, UnvoteScope::Any));
-		assert_ok!(VtokenVoting::update_lock(&ALICE, vtoken));
-		assert_eq!(usable_balance(vtoken, &ALICE), 10);
-	});
-}
-
-#[test]
-fn ensure_balance_after_unlock() {
-	new_test_ext().execute_with(|| {
-		let poll_index = 3;
-		let poll_index_2 = 4;
-		let vtoken = VKSM;
-		let locking_period = 10;
-		assert_ok!(VtokenVoting::set_vote_locking_period(
-			RuntimeOrigin::root(),
-			vtoken,
-			locking_period,
-		));
-
-		assert_ok!(VtokenVoting::vote(
-			RuntimeOrigin::signed(ALICE),
-			vtoken,
-			poll_index,
-			aye(10, 1)
-		));
-		assert_ok!(VtokenVoting::notify_vote(origin_response(), 0, response_success()));
-		assert_ok!(VtokenVoting::vote(
-			RuntimeOrigin::signed(ALICE),
-			vtoken,
-			poll_index_2,
-			aye(10, 5)
-		));
-		assert_ok!(VtokenVoting::notify_vote(origin_response(), 1, response_success()));
-
-		assert_ok!(VtokenVoting::set_referendum_status(
-			RuntimeOrigin::root(),
-			vtoken,
-			poll_index,
-			ReferendumInfoOf::<Runtime>::Completed(3),
-		));
-		RelaychainDataProvider::set_block_number(13);
-		assert_ok!(VtokenVoting::unlock(RuntimeOrigin::signed(ALICE), vtoken, poll_index));
-		assert_eq!(usable_balance(vtoken, &ALICE), 0);
-		assert_eq!(Tokens::accounts(&ALICE, vtoken).frozen, 10);
-		assert_eq!(VotingFor::<Runtime>::get(&ALICE).locked_balance(), 10);
-	});
-}
-
-#[test]
-fn ensure_comprehensive_balance_after_unlock() {
-	new_test_ext().execute_with(|| {
-		let poll_index = 3;
-		let poll_index_2 = 4;
-		let poll_index_3 = 5;
-		let vtoken = VKSM;
-		let locking_period = 10;
-		assert_ok!(VtokenVoting::set_vote_locking_period(
-			RuntimeOrigin::root(),
-			vtoken,
-			locking_period,
-		));
-
-		assert_ok!(VtokenVoting::vote(RuntimeOrigin::signed(ALICE), vtoken, poll_index, aye(2, 1)));
-		assert_ok!(VtokenVoting::notify_vote(origin_response(), 0, response_success()));
-		assert_ok!(VtokenVoting::vote(
-			RuntimeOrigin::signed(ALICE),
-			vtoken,
-			poll_index_2,
-			aye(1, 5)
-		));
-		assert_ok!(VtokenVoting::notify_vote(origin_response(), 1, response_success()));
-		assert_ok!(VtokenVoting::vote(
-			RuntimeOrigin::signed(ALICE),
-			vtoken,
-			poll_index_3,
-			aye(2, 5)
-		));
-		assert_ok!(VtokenVoting::notify_vote(origin_response(), 2, response_success()));
-
-		assert_ok!(VtokenVoting::set_referendum_status(
-			RuntimeOrigin::root(),
-			vtoken,
-			poll_index,
-			ReferendumInfoOf::<Runtime>::Completed(3),
-		));
-		RelaychainDataProvider::set_block_number(13);
-		assert_ok!(VtokenVoting::unlock(RuntimeOrigin::signed(ALICE), vtoken, poll_index));
-		assert_eq!(usable_balance(vtoken, &ALICE), 8);
-		assert_eq!(Tokens::accounts(&ALICE, vtoken).frozen, 2);
-		assert_eq!(VotingFor::<Runtime>::get(&ALICE).locked_balance(), 2);
-
-		assert_ok!(VtokenVoting::vote(
-			RuntimeOrigin::signed(ALICE),
-			vtoken,
-			poll_index_2,
-			aye(10, 5)
-		));
-		assert_ok!(VtokenVoting::notify_vote(origin_response(), 3, response_success()));
-
-		assert_eq!(usable_balance(vtoken, &ALICE), 0);
-		assert_eq!(Tokens::accounts(&ALICE, vtoken).frozen, 10);
-		assert_eq!(VotingFor::<Runtime>::get(&ALICE).locked_balance(), 10);
-	});
-}
-
-#[test]
-fn successful_conviction_vote_balance_stays_locked_for_correct_time() {
-	new_test_ext().execute_with(|| {
-		let poll_index = 3;
-		let vtoken = VKSM;
-		let locking_period = 10;
-		assert_ok!(VtokenVoting::set_vote_locking_period(
-			RuntimeOrigin::root(),
-			vtoken,
-			locking_period,
-		));
-		for i in 1..=5 {
-			assert_ok!(VtokenVoting::vote(
-				RuntimeOrigin::signed(i),
-				vtoken,
-				poll_index,
-				aye(10, i as u8)
-			));
-			assert_ok!(VtokenVoting::notify_vote(origin_response(), i - 1, response_success()));
-		}
-		assert_ok!(VtokenVoting::set_referendum_status(
-			RuntimeOrigin::root(),
-			vtoken,
-			poll_index,
-			ReferendumInfoOf::<Runtime>::Completed(3),
-		));
-		RelaychainDataProvider::set_block_number(163);
-		for i in 1..=5 {
-			assert_ok!(VtokenVoting::try_remove_vote(&i, vtoken, poll_index, UnvoteScope::Any));
-		}
-		for i in 1..=5 {
-			assert_ok!(VtokenVoting::update_lock(&i, vtoken));
-			assert_eq!(usable_balance(vtoken, &i), 10 * i as u128);
-		}
-	});
-}
-
-#[test]
-fn lock_amalgamation_valid_with_multiple_removed_votes() {
-	new_test_ext().execute_with(|| {
-		let vtoken = VKSM;
-		let response = response_success();
-
-		assert_ok!(VtokenVoting::vote(RuntimeOrigin::signed(ALICE), vtoken, 0, aye(5, 1)));
-		assert_ok!(VtokenVoting::notify_vote(origin_response(), 0, response.clone()));
-		assert_eq!(
-			ClassLocksFor::<Runtime>::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::<Runtime>::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::<Runtime>::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::<Runtime>::get(&ALICE),
-			BoundedVec::<(CurrencyId, u128), ConstU32<256>>::try_from(vec![(vtoken, 10),]).unwrap()
-		);
-
-		assert_ok!(VtokenVoting::set_referendum_status(
-			RuntimeOrigin::root(),
-			vtoken,
-			0,
-			ReferendumInfoOf::<Runtime>::Completed(1),
-		));
-		assert_ok!(VtokenVoting::set_referendum_status(
-			RuntimeOrigin::root(),
-			vtoken,
-			1,
-			ReferendumInfoOf::<Runtime>::Completed(1),
-		));
-		assert_ok!(VtokenVoting::set_referendum_status(
-			RuntimeOrigin::root(),
-			vtoken,
-			2,
-			ReferendumInfoOf::<Runtime>::Completed(1),
-		));
-
-		let locking_period = 10;
-		assert_ok!(VtokenVoting::set_vote_locking_period(
-			RuntimeOrigin::root(),
-			vtoken,
-			locking_period,
-		));
-		assert_eq!(VoteLockingPeriod::<Runtime>::get(vtoken), Some(10));
-
-		assert_eq!(
-			ClassLocksFor::<Runtime>::get(&ALICE),
-			BoundedVec::<(CurrencyId, u128), ConstU32<256>>::try_from(vec![(vtoken, 10),]).unwrap()
-		);
-
-		RelaychainDataProvider::set_block_number(10);
-		assert_noop!(
-			VtokenVoting::unlock(RuntimeOrigin::signed(ALICE), vtoken, 0),
-			Error::<Runtime>::NoPermissionYet
-		);
-		assert_eq!(VotingFor::<Runtime>::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::<Runtime>::get(&ALICE).locked_balance(), 10);
-		assert_eq!(usable_balance(vtoken, &ALICE), 0);
-		assert_eq!(
-			ClassLocksFor::<Runtime>::get(&ALICE),
-			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), 0);
-		assert_eq!(
-			ClassLocksFor::<Runtime>::get(&ALICE),
-			BoundedVec::<(CurrencyId, u128), ConstU32<256>>::try_from(vec![(vtoken, 10)]).unwrap()
-		);
-
-		RelaychainDataProvider::set_block_number(21);
-		assert_ok!(VtokenVoting::unlock(RuntimeOrigin::signed(ALICE), vtoken, 2));
-		assert_eq!(usable_balance(vtoken, &ALICE), 10);
-		assert_eq!(
-			ClassLocksFor::<Runtime>::get(&ALICE),
-			BoundedVec::<(CurrencyId, u128), ConstU32<256>>::try_from(vec![]).unwrap()
-		);
-	});
-}
-
-#[test]
-fn removed_votes_when_referendum_killed() {
-	new_test_ext().execute_with(|| {
-		let vtoken = VKSM;
-		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_ok!(VtokenVoting::notify_vote(origin_response(), 1, response.clone()));
-		assert_ok!(VtokenVoting::notify_vote(origin_response(), 2, response.clone()));
-
-		assert_ok!(VtokenVoting::set_referendum_status(
-			RuntimeOrigin::root(),
-			vtoken,
-			0,
-			ReferendumInfoOf::<Runtime>::Completed(1),
-		));
-		assert_ok!(VtokenVoting::set_referendum_status(
-			RuntimeOrigin::root(),
-			vtoken,
-			1,
-			ReferendumInfoOf::<Runtime>::Completed(1),
-		));
-		assert_ok!(VtokenVoting::set_referendum_status(
-			RuntimeOrigin::root(),
-			vtoken,
-			2,
-			ReferendumInfoOf::<Runtime>::Completed(1),
-		));
-
-		assert_ok!(VtokenVoting::kill_referendum(RuntimeOrigin::root(), vtoken, 0));
-		assert_ok!(VtokenVoting::kill_referendum(RuntimeOrigin::root(), vtoken, 1));
-		assert_ok!(VtokenVoting::kill_referendum(RuntimeOrigin::root(), vtoken, 2));
-
-		assert_eq!(
-			ClassLocksFor::<Runtime>::get(&ALICE),
-			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::<Runtime>::get(&ALICE),
-			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::<Runtime>::get(&ALICE),
-			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::<Runtime>::get(&ALICE),
-			BoundedVec::<(CurrencyId, u128), ConstU32<256>>::try_from(vec![]).unwrap()
-		);
-	});
-}
-
-#[test]
-fn errors_with_vote_works() {
-	new_test_ext().execute_with(|| {
-		let vtoken = VKSM;
-
-		assert_noop!(
-			VtokenVoting::vote(RuntimeOrigin::signed(1), VBNC, 0, aye(10, 0)),
-			Error::<Runtime>::VTokenNotSupport
-		);
-		assert_noop!(
-			VtokenVoting::vote(RuntimeOrigin::signed(1), vtoken, 3, aye(11, 0)),
-			Error::<Runtime>::InsufficientFunds
-		);
-
-		for poll_index in 0..256 {
-			assert_ok!(VtokenVoting::vote(
-				RuntimeOrigin::signed(1),
-				vtoken,
-				poll_index,
-				aye(10, 0)
-			));
-		}
-		assert_noop!(
-			VtokenVoting::vote(RuntimeOrigin::signed(1), vtoken, 256, aye(10, 0)),
-			Error::<Runtime>::MaxVotesReached
-		);
-	});
-}
-
-#[test]
-fn kill_referendum_works() {
-	new_test_ext().execute_with(|| {
-		let vtoken = VKSM;
-		let poll_index = 3;
-
-		assert_ok!(VtokenVoting::vote(RuntimeOrigin::signed(ALICE), vtoken, poll_index, aye(5, 1)));
-		assert_ok!(VtokenVoting::set_referendum_status(
-			RuntimeOrigin::root(),
-			vtoken,
-			poll_index,
-			ReferendumInfoOf::<Runtime>::Completed(1),
-		));
-		assert_ok!(VtokenVoting::kill_referendum(RuntimeOrigin::root(), vtoken, poll_index));
-		System::assert_last_event(RuntimeEvent::VtokenVoting(Event::ReferendumKilled {
-			vtoken,
-			poll_index,
-		}));
-	});
-}
-
-#[test]
-fn kill_referendum_with_origin_signed_fails() {
-	new_test_ext().execute_with(|| {
-		let vtoken = VKSM;
-		let poll_index = 3;
-
-		assert_ok!(VtokenVoting::vote(RuntimeOrigin::signed(ALICE), vtoken, poll_index, aye(5, 1)));
-		assert_ok!(VtokenVoting::set_referendum_status(
-			RuntimeOrigin::root(),
-			vtoken,
-			poll_index,
-			ReferendumInfoOf::<Runtime>::Completed(1),
-		));
-		assert_noop!(
-			VtokenVoting::kill_referendum(RuntimeOrigin::signed(ALICE), vtoken, poll_index),
-			DispatchError::BadOrigin
-		);
-	});
-}
-
-#[test]
-fn add_delegator_works() {
-	new_test_ext().execute_with(|| {
-		let vtoken = VKSM;
-		let derivative_index: DerivativeIndex = 100;
-
-		assert_ok!(VtokenVoting::add_delegator(RuntimeOrigin::root(), vtoken, derivative_index,));
-
-		System::assert_last_event(RuntimeEvent::VtokenVoting(Event::DelegatorAdded {
-			vtoken,
-			derivative_index,
-		}));
-	});
-}
-
-#[test]
-fn set_referendum_status_works() {
-	new_test_ext().execute_with(|| {
-		let poll_index = 3;
-		let vtoken = VKSM;
-		let info = ReferendumInfo::Completed(3);
-
-		assert_ok!(VtokenVoting::vote(RuntimeOrigin::signed(ALICE), vtoken, poll_index, aye(2, 5)));
-		assert_ok!(VtokenVoting::set_referendum_status(
-			RuntimeOrigin::root(),
-			vtoken,
-			poll_index,
-			info.clone(),
-		));
-
-		System::assert_last_event(RuntimeEvent::VtokenVoting(Event::ReferendumInfoSet {
-			vtoken,
-			poll_index,
-			info,
-		}));
-	});
-}
-
-#[test]
-fn set_referendum_status_without_vote_should_fail() {
-	new_test_ext().execute_with(|| {
-		let poll_index = 3;
-		let vtoken = VKSM;
-		let info = ReferendumInfo::Completed(3);
-
-		assert_noop!(
-			VtokenVoting::set_referendum_status(
-				RuntimeOrigin::root(),
-				vtoken,
-				poll_index,
-				info.clone(),
-			),
-			Error::<Runtime>::NoData
-		);
-	});
-}
-
-#[test]
-fn set_referendum_status_with_origin_signed_should_fail() {
-	new_test_ext().execute_with(|| {
-		let poll_index = 3;
-		let vtoken = VKSM;
-		let info = ReferendumInfo::Completed(3);
-
-		assert_noop!(
-			VtokenVoting::set_referendum_status(
-				RuntimeOrigin::signed(ALICE),
-				vtoken,
-				poll_index,
-				info.clone(),
-			),
-			DispatchError::BadOrigin
-		);
-	});
-}
-
-#[test]
-fn set_vote_locking_period_works() {
-	new_test_ext().execute_with(|| {
-		let vtoken = VKSM;
-		let locking_period = 100;
-
-		assert_ok!(VtokenVoting::set_vote_locking_period(
-			RuntimeOrigin::root(),
-			vtoken,
-			locking_period,
-		));
-
-		System::assert_last_event(RuntimeEvent::VtokenVoting(Event::VoteLockingPeriodSet {
-			vtoken,
-			locking_period,
-		}));
-	});
-}
-
-#[test]
-fn set_vote_locking_period_with_origin_signed_should_fail() {
-	new_test_ext().execute_with(|| {
-		let vtoken = VKSM;
-		let locking_period = 100;
-
-		assert_noop!(
-			VtokenVoting::set_vote_locking_period(
-				RuntimeOrigin::signed(ALICE),
-				vtoken,
-				locking_period,
-			),
-			DispatchError::BadOrigin
-		);
-	});
-}
-
-#[test]
-fn set_undeciding_timeout_works() {
-	new_test_ext().execute_with(|| {
-		let vtoken = VKSM;
-		let undeciding_timeout = 100;
-
-		assert_ok!(VtokenVoting::set_undeciding_timeout(
-			RuntimeOrigin::root(),
-			vtoken,
-			undeciding_timeout,
-		));
-
-		System::assert_last_event(RuntimeEvent::VtokenVoting(Event::UndecidingTimeoutSet {
-			vtoken,
-			undeciding_timeout,
-		}));
-	});
-}
-
-#[test]
-fn set_undeciding_timeout_with_origin_signed_should_fail() {
-	new_test_ext().execute_with(|| {
-		let vtoken = VKSM;
-		let undeciding_timeout = 100;
-
-		assert_noop!(
-			VtokenVoting::set_undeciding_timeout(
-				RuntimeOrigin::signed(ALICE),
-				vtoken,
-				undeciding_timeout,
-			),
-			DispatchError::BadOrigin
-		);
-	});
-}
-
-#[test]
-fn notify_vote_success_works() {
-	new_test_ext().execute_with(|| {
-		let poll_index = 3;
-		let vtoken = VKSM;
-		let query_id = 0;
-		let response = response_success();
-		let derivative_index = 0;
-
-		assert_ok!(VtokenVoting::vote(RuntimeOrigin::signed(ALICE), vtoken, poll_index, aye(2, 5)));
-		assert_eq!(
-			ReferendumInfoFor::<Runtime>::get(vtoken, poll_index),
-			Some(ReferendumInfo::Ongoing(ReferendumStatus {
-				submitted: None,
-				tally: TallyOf::<Runtime>::from_parts(20, 0, 4),
-			}))
-		);
-		assert_eq!(
-			PendingDelegatorVotes::<Runtime>::get(vtoken, poll_index),
-			BoundedVec::<(DerivativeIndex, AccountVote<Balance>), ConstU32<100>>::try_from(vec![(
-				derivative_index,
-				aye(200, 0)
-			)])
-			.unwrap()
-		);
-		assert_eq!(DelegatorVotes::<Runtime>::get(vtoken, poll_index).len(), 0);
-		assert_eq!(tally(vtoken, poll_index), Tally::from_parts(20, 0, 4));
-		System::assert_last_event(RuntimeEvent::VtokenVoting(Event::Voted {
-			who: ALICE,
-			vtoken,
-			poll_index,
-			token_vote: aye(4, 5),
-			delegator_vote: aye(200, 0),
-		}));
-
-		assert_ok!(VtokenVoting::notify_vote(origin_response(), query_id, response.clone()));
-		assert_eq!(
-			ReferendumInfoFor::<Runtime>::get(vtoken, poll_index),
-			Some(ReferendumInfo::Ongoing(ReferendumStatus {
-				submitted: Some(1),
-				tally: TallyOf::<Runtime>::from_parts(20, 0, 4),
-			}))
-		);
-		assert_eq!(PendingDelegatorVotes::<Runtime>::get(vtoken, poll_index).len(), 0);
-		assert_eq!(
-			DelegatorVotes::<Runtime>::get(vtoken, poll_index),
-			BoundedVec::<(DerivativeIndex, AccountVote<Balance>), ConstU32<100>>::try_from(vec![(
-				derivative_index,
-				aye(200, 0)
-			)])
-			.unwrap()
-		);
-		System::assert_has_event(RuntimeEvent::VtokenVoting(Event::VoteNotified {
-			vtoken,
-			poll_index,
-			success: true,
-		}));
-		System::assert_has_event(RuntimeEvent::VtokenVoting(Event::ReferendumInfoCreated {
-			vtoken,
-			poll_index,
-			info: ReferendumInfo::Ongoing(ReferendumStatus {
-				submitted: Some(1),
-				tally: TallyOf::<Runtime>::from_parts(20, 0, 4),
-			}),
-		}));
-		System::assert_last_event(RuntimeEvent::VtokenVoting(Event::ResponseReceived {
-			responder: Parent.into(),
-			query_id,
-			response,
-		}));
-	});
-}
-
-#[test]
-fn notify_vote_success_max_works() {
-	new_test_ext().execute_with(|| {
-		let vtoken = VKSM;
-
-		for poll_index in 0..256 {
-			RelaychainDataProvider::set_block_number(1);
-
-			assert_ok!(VtokenVoting::vote(
-				RuntimeOrigin::signed(ALICE),
-				vtoken,
-				poll_index,
-				aye(2, 5)
-			));
-			assert_ok!(VtokenVoting::notify_vote(
-				origin_response(),
-				poll_index as QueryId,
-				response_success()
-			));
-
-			RelaychainDataProvider::set_block_number(
-				1 + UndecidingTimeout::<Runtime>::get(vtoken).unwrap(),
-			);
-			VtokenVoting::on_idle(Zero::zero(), Weight::MAX);
-		}
-	});
-}
-
-#[test]
-fn notify_vote_success_exceed_max_fail() {
-	new_test_ext().execute_with(|| {
-		let vtoken = VKSM;
-
-		for poll_index in 0..50 {
-			assert_ok!(VtokenVoting::vote(
-				RuntimeOrigin::signed(ALICE),
-				vtoken,
-				poll_index,
-				aye(2, 5)
-			));
-			assert_ok!(VtokenVoting::notify_vote(
-				origin_response(),
-				poll_index as QueryId,
-				response_success()
-			));
-		}
-		let poll_index = 50;
-		assert_ok!(VtokenVoting::vote(RuntimeOrigin::signed(ALICE), vtoken, poll_index, aye(2, 5)));
-		assert_noop!(
-			VtokenVoting::notify_vote(origin_response(), poll_index as QueryId, response_success()),
-			Error::<Runtime>::TooMany
-		);
-	});
-}
-
-#[test]
-fn notify_vote_fail_works() {
-	new_test_ext().execute_with(|| {
-		let poll_index = 3;
-		let vtoken = VKSM;
-		let query_id = 0;
-		let response = response_fail();
-		let derivative_index = 0;
-
-		assert_ok!(VtokenVoting::vote(RuntimeOrigin::signed(ALICE), vtoken, poll_index, aye(2, 5)));
-		assert_eq!(
-			ReferendumInfoFor::<Runtime>::get(vtoken, poll_index),
-			Some(ReferendumInfo::Ongoing(ReferendumStatus {
-				submitted: None,
-				tally: TallyOf::<Runtime>::from_parts(20, 0, 4),
-			}))
-		);
-		assert_eq!(DelegatorVotes::<Runtime>::get(vtoken, poll_index).len(), 0);
-		assert_eq!(
-			PendingDelegatorVotes::<Runtime>::get(vtoken, poll_index),
-			BoundedVec::<(DerivativeIndex, AccountVote<Balance>), ConstU32<100>>::try_from(vec![(
-				derivative_index,
-				aye(200, 0)
-			)])
-			.unwrap()
-		);
-		assert_eq!(tally(vtoken, poll_index), Tally::from_parts(20, 0, 4));
-		System::assert_last_event(RuntimeEvent::VtokenVoting(Event::Voted {
-			who: ALICE,
-			vtoken,
-			poll_index,
-			token_vote: aye(4, 5),
-			delegator_vote: aye(200, 0),
-		}));
-
-		assert_ok!(VtokenVoting::notify_vote(origin_response(), query_id, response.clone()));
-		assert_eq!(ReferendumInfoFor::<Runtime>::get(vtoken, poll_index), None);
-		assert_eq!(DelegatorVotes::<Runtime>::get(vtoken, poll_index).len(), 0);
-		assert_eq!(PendingDelegatorVotes::<Runtime>::get(vtoken, poll_index).len(), 0);
-		System::assert_last_event(RuntimeEvent::VtokenVoting(Event::ResponseReceived {
-			responder: Parent.into(),
-			query_id,
-			response,
-		}));
-	});
-}
-
-#[test]
-fn notify_vote_with_no_data_works() {
-	new_test_ext().execute_with(|| {
-		let query_id = 0;
-		let response = response_success();
-
-		assert_ok!(VtokenVoting::notify_vote(origin_response(), query_id, response.clone()));
-		System::assert_last_event(RuntimeEvent::VtokenVoting(Event::ResponseReceived {
-			responder: Parent.into(),
-			query_id,
-			response,
-		}));
-	});
-}
-
-#[test]
-fn notify_remove_delegator_vote_success_works() {
-	new_test_ext().execute_with(|| {
-		let class = 0;
-		let poll_index = 3;
-		let vtoken = VKSM;
-		let mut query_id = 0;
-		let derivative_index = 0;
-		let response = response_success();
-
-		assert_ok!(VtokenVoting::vote(RuntimeOrigin::signed(ALICE), vtoken, poll_index, aye(2, 5)));
-		assert_eq!(DelegatorVotes::<Runtime>::get(vtoken, poll_index).len(), 0);
-		assert_eq!(
-			PendingDelegatorVotes::<Runtime>::get(vtoken, poll_index),
-			BoundedVec::<(DerivativeIndex, AccountVote<Balance>), ConstU32<100>>::try_from(vec![(
-				derivative_index,
-				aye(200, 0)
-			)])
-			.unwrap()
-		);
-		assert_eq!(tally(vtoken, poll_index), Tally::from_parts(20, 0, 4));
-		System::assert_last_event(RuntimeEvent::VtokenVoting(Event::Voted {
-			who: ALICE,
-			vtoken,
-			poll_index,
-			token_vote: aye(4, 5),
-			delegator_vote: aye(200, 0),
-		}));
-		assert_ok!(VtokenVoting::notify_vote(origin_response(), query_id, response.clone()));
-		assert_eq!(
-			DelegatorVotes::<Runtime>::get(vtoken, poll_index),
-			BoundedVec::<(DerivativeIndex, AccountVote<Balance>), ConstU32<100>>::try_from(vec![(
-				derivative_index,
-				aye(200, 0)
-			)])
-			.unwrap()
-		);
-		assert_eq!(PendingDelegatorVotes::<Runtime>::get(vtoken, poll_index).len(), 0);
-
-		assert_ok!(VtokenVoting::set_referendum_status(
-			RuntimeOrigin::root(),
-			vtoken,
-			poll_index,
-			ReferendumInfoOf::<Runtime>::Completed(3),
-		));
-		assert_ok!(VtokenVoting::set_vote_locking_period(RuntimeOrigin::root(), vtoken, 10));
-
-		RelaychainDataProvider::set_block_number(3);
-		assert_ok!(VtokenVoting::remove_delegator_vote(
-			RuntimeOrigin::signed(ALICE),
-			vtoken,
-			class,
-			poll_index,
-			derivative_index,
-		));
-		assert_eq!(DelegatorVotes::<Runtime>::get(vtoken, poll_index).len(), 1);
-
-		query_id = 1;
-		assert_ok!(VtokenVoting::notify_remove_delegator_vote(
-			origin_response(),
-			query_id,
-			response.clone()
-		));
-		assert_eq!(DelegatorVotes::<Runtime>::get(vtoken, poll_index).len(), 0);
-		System::assert_has_event(RuntimeEvent::VtokenVoting(Event::DelegatorVoteRemovedNotified {
-			vtoken,
-			poll_index,
-			success: true,
-		}));
-		System::assert_last_event(RuntimeEvent::VtokenVoting(Event::ResponseReceived {
-			responder: Parent.into(),
-			query_id,
-			response,
-		}));
-	});
-}
-
-#[test]
-fn notify_remove_delegator_vote_fail_works() {
-	new_test_ext().execute_with(|| {
-		let class = 0;
-		let poll_index = 3;
-		let vtoken = VKSM;
-		let mut query_id = 0;
-		let derivative_index = 0;
-		let response = response_fail();
-
-		assert_ok!(VtokenVoting::vote(RuntimeOrigin::signed(ALICE), vtoken, poll_index, aye(2, 5)));
-		assert_eq!(DelegatorVotes::<Runtime>::get(vtoken, poll_index).len(), 0);
-		assert_eq!(
-			PendingDelegatorVotes::<Runtime>::get(vtoken, poll_index),
-			BoundedVec::<(DerivativeIndex, AccountVote<Balance>), ConstU32<100>>::try_from(vec![(
-				derivative_index,
-				aye(200, 0)
-			)])
-			.unwrap()
-		);
-		assert_eq!(tally(vtoken, poll_index), Tally::from_parts(20, 0, 4));
-		System::assert_last_event(RuntimeEvent::VtokenVoting(Event::Voted {
-			who: ALICE,
-			vtoken,
-			poll_index,
-			token_vote: aye(4, 5),
-			delegator_vote: aye(200, 0),
-		}));
-		assert_ok!(VtokenVoting::notify_vote(origin_response(), query_id, response_success()));
-		assert_eq!(
-			DelegatorVotes::<Runtime>::get(vtoken, poll_index),
-			BoundedVec::<(DerivativeIndex, AccountVote<Balance>), ConstU32<100>>::try_from(vec![(
-				derivative_index,
-				aye(200, 0)
-			)])
-			.unwrap()
-		);
-		assert_eq!(PendingDelegatorVotes::<Runtime>::get(vtoken, poll_index).len(), 0);
-
-		assert_ok!(VtokenVoting::set_referendum_status(
-			RuntimeOrigin::root(),
-			vtoken,
-			poll_index,
-			ReferendumInfoOf::<Runtime>::Completed(3),
-		));
-		assert_ok!(VtokenVoting::set_vote_locking_period(RuntimeOrigin::root(), vtoken, 10));
-
-		RelaychainDataProvider::set_block_number(3);
-		assert_ok!(VtokenVoting::remove_delegator_vote(
-			RuntimeOrigin::signed(ALICE),
-			vtoken,
-			class,
-			poll_index,
-			derivative_index,
-		));
-		assert_eq!(DelegatorVotes::<Runtime>::get(vtoken, poll_index).len(), 1);
-
-		query_id = 1;
-		assert_ok!(VtokenVoting::notify_remove_delegator_vote(
-			origin_response(),
-			query_id,
-			response.clone()
-		));
-		assert_eq!(DelegatorVotes::<Runtime>::get(vtoken, poll_index).len(), 1);
-		System::assert_last_event(RuntimeEvent::VtokenVoting(Event::ResponseReceived {
-			responder: Parent.into(),
-			query_id,
-			response,
-		}));
-	});
-}
-
-#[test]
-fn notify_remove_delegator_vote_with_no_data_works() {
-	new_test_ext().execute_with(|| {
-		let query_id = 0;
-		let response = response_success();
-
-		assert_ok!(VtokenVoting::notify_remove_delegator_vote(
-			origin_response(),
-			query_id,
-			response.clone(),
-		));
-		System::assert_last_event(RuntimeEvent::VtokenVoting(Event::ResponseReceived {
-			responder: Parent.into(),
-			query_id,
-			response,
-		}));
-	});
-}
-
-#[test]
-fn on_idle_works() {
-	new_test_ext().execute_with(|| {
-		let vtoken = VKSM;
-		for (index, poll_index) in (0..50).collect::<Vec<_>>().iter().enumerate() {
-			let relay_block_number = index as BlockNumber;
-			let query_id = index as QueryId;
-			RelaychainDataProvider::set_block_number(relay_block_number);
-			assert_ok!(VtokenVoting::vote(
-				RuntimeOrigin::signed(ALICE),
-				vtoken,
-				*poll_index,
-				aye(2, 5)
-			));
-			assert_ok!(VtokenVoting::notify_vote(
-				origin_response(),
-				query_id as QueryId,
-				response_success()
-			));
-		}
-
-		let count = 30;
-		RelaychainDataProvider::set_block_number(
-			count + UndecidingTimeout::<Runtime>::get(vtoken).unwrap(),
-		);
-		let db_weight = RuntimeDbWeight { read: 1, write: 1 };
-		let weight =
-			db_weight.reads(3) + db_weight.reads_writes(1, 2) * count + db_weight.writes(2) * count;
-		let used_weight = VtokenVoting::on_idle(Zero::zero(), weight);
-		assert_eq!(used_weight, Weight::from_parts(0, 0));
-
-		let mut actual_count = 0;
-		for poll_index in 0..50 {
-			let relay_block_number = poll_index as BlockNumber;
-			if ReferendumTimeout::<Runtime>::get(
-				relay_block_number + UndecidingTimeout::<Runtime>::get(vtoken).unwrap(),
-			)
-			.is_empty()
-			{
-				actual_count += 1;
-			}
-		}
-		assert_eq!(actual_count, 31);
-	});
-}
-
-#[test]
-fn set_vote_cap_ratio_works() {
-	new_test_ext().execute_with(|| {
-		let vtoken = VKSM;
-
-		assert_ok!(VtokenVoting::set_vote_cap_ratio(
-			RuntimeOrigin::root(),
-			vtoken,
-			Perbill::from_percent(0)
-		));
-		assert_eq!(VoteCapRatio::<Runtime>::get(vtoken), Perbill::from_percent(0));
-
-		assert_ok!(VtokenVoting::set_vote_cap_ratio(
-			RuntimeOrigin::root(),
-			vtoken,
-			Perbill::from_percent(10)
-		));
-		assert_eq!(VoteCapRatio::<Runtime>::get(vtoken), Perbill::from_percent(10));
-
-		assert_ok!(VtokenVoting::set_vote_cap_ratio(
-			RuntimeOrigin::root(),
-			vtoken,
-			Perbill::from_percent(100)
-		));
-		assert_eq!(VoteCapRatio::<Runtime>::get(vtoken), Perbill::from_percent(100));
-	});
-}
-
-#[test]
-fn vote_cap_works() {
-	new_test_ext().execute_with(|| {
-		let vtoken = VKSM;
-		assert_eq!(VtokenVoting::vote_cap(vtoken), Ok((u64::MAX / 10) as Balance));
-	});
-}
-
-#[test]
-fn vote_to_capital_works() {
-	new_test_ext().execute_with(|| {
-		assert_eq!(VtokenVoting::vote_to_capital(Conviction::None, 300), 3000);
-		assert_eq!(VtokenVoting::vote_to_capital(Conviction::Locked1x, 300), 300);
-		assert_eq!(VtokenVoting::vote_to_capital(Conviction::Locked2x, 300), 150);
-		assert_eq!(VtokenVoting::vote_to_capital(Conviction::Locked3x, 300), 100);
-		assert_eq!(VtokenVoting::vote_to_capital(Conviction::Locked4x, 300), 75);
-		assert_eq!(VtokenVoting::vote_to_capital(Conviction::Locked5x, 300), 60);
-		assert_eq!(VtokenVoting::vote_to_capital(Conviction::Locked6x, 300), 50);
-	});
-}
-
-#[test]
-fn compute_delegator_total_vote_works() {
-	new_test_ext().execute_with(|| {
-		let vtoken = VKSM;
-		assert_eq!(VtokenVoting::compute_delegator_total_vote(vtoken, aye(10, 0)), Ok(aye(10, 0)));
-		assert_eq!(VtokenVoting::compute_delegator_total_vote(vtoken, aye(2, 1)), Ok(aye(20, 0)));
-		assert_eq!(VtokenVoting::compute_delegator_total_vote(vtoken, aye(2, 2)), Ok(aye(40, 0)));
-		assert_eq!(VtokenVoting::compute_delegator_total_vote(vtoken, aye(2, 3)), Ok(aye(60, 0)));
-		assert_eq!(VtokenVoting::compute_delegator_total_vote(vtoken, aye(2, 4)), Ok(aye(80, 0)));
-		assert_eq!(VtokenVoting::compute_delegator_total_vote(vtoken, aye(2, 5)), Ok(aye(100, 0)));
-		assert_eq!(VtokenVoting::compute_delegator_total_vote(vtoken, aye(2, 6)), Ok(aye(120, 0)));
-
-		assert_eq!(VtokenVoting::compute_delegator_total_vote(vtoken, nay(10, 0)), Ok(nay(10, 0)));
-		assert_eq!(VtokenVoting::compute_delegator_total_vote(vtoken, nay(2, 1)), Ok(nay(20, 0)));
-		assert_eq!(VtokenVoting::compute_delegator_total_vote(vtoken, nay(2, 2)), Ok(nay(40, 0)));
-		assert_eq!(VtokenVoting::compute_delegator_total_vote(vtoken, nay(2, 3)), Ok(nay(60, 0)));
-		assert_eq!(VtokenVoting::compute_delegator_total_vote(vtoken, nay(2, 4)), Ok(nay(80, 0)));
-		assert_eq!(VtokenVoting::compute_delegator_total_vote(vtoken, nay(2, 5)), Ok(nay(100, 0)));
-		assert_eq!(VtokenVoting::compute_delegator_total_vote(vtoken, nay(2, 6)), Ok(nay(120, 0)));
-
-		SimpleVTokenSupplyProvider::set_token_supply(10_000_000);
-		assert_eq!(VtokenVoting::vote_cap(vtoken), Ok(1_000_000));
-		assert_eq!(
-			VtokenVoting::compute_delegator_total_vote(vtoken, aye(1_000_000, 0)),
-			Ok(aye(1_000_000, 0))
-		);
-		for i in 1..=6_u8 {
-			assert_eq!(
-				VtokenVoting::compute_delegator_total_vote(
-					vtoken,
-					aye(10_000_000 * i as Balance, 0)
-				),
-				Ok(aye(1_000_000, i))
-			);
-		}
-
-		assert_eq!(
-			VtokenVoting::compute_delegator_total_vote(vtoken, aye(100_000, 1)),
-			Ok(aye(1_000_000, 0))
-		);
-		for i in 1..=6_u8 {
-			assert_eq!(
-				VtokenVoting::compute_delegator_total_vote(
-					vtoken,
-					aye(1_000_000 * i as Balance, 1)
-				),
-				Ok(aye(1_000_000, i))
-			);
-		}
-		assert_noop!(
-			VtokenVoting::compute_delegator_total_vote(vtoken, aye(6_000_006, 1)),
-			Error::<Runtime>::InsufficientFunds
-		);
-
-		assert_eq!(
-			VtokenVoting::compute_delegator_total_vote(vtoken, aye(50_000, 2)),
-			Ok(aye(1_000_000, 0))
-		);
-		for i in 1..=6_u8 {
-			assert_eq!(
-				VtokenVoting::compute_delegator_total_vote(vtoken, aye(500_000 * i as Balance, 2)),
-				Ok(aye(1_000_000, i))
-			);
-		}
-		assert_noop!(
-			VtokenVoting::compute_delegator_total_vote(vtoken, aye(3_000_003, 2)),
-			Error::<Runtime>::InsufficientFunds
-		);
-
-		assert_eq!(
-			VtokenVoting::compute_delegator_total_vote(vtoken, aye(33_333, 3)),
-			Ok(aye(999_990, 0))
-		);
-		for i in 1..=6_u8 {
-			assert_eq!(
-				VtokenVoting::compute_delegator_total_vote(vtoken, aye(333_333 * i as Balance, 3)),
-				Ok(aye(999_999, i))
-			);
-		}
-		assert_noop!(
-			VtokenVoting::compute_delegator_total_vote(vtoken, aye(2_000_002, 3)),
-			Error::<Runtime>::InsufficientFunds
-		);
-
-		assert_eq!(
-			VtokenVoting::compute_delegator_total_vote(vtoken, aye(25_000, 4)),
-			Ok(aye(1_000_000, 0))
-		);
-		for i in 1..=6_u8 {
-			assert_eq!(
-				VtokenVoting::compute_delegator_total_vote(vtoken, aye(250_000 * i as Balance, 4)),
-				Ok(aye(1_000_000, i))
-			);
-		}
-		assert_noop!(
-			VtokenVoting::compute_delegator_total_vote(vtoken, aye(1_500_002, 4)),
-			Error::<Runtime>::InsufficientFunds
-		);
-
-		assert_eq!(
-			VtokenVoting::compute_delegator_total_vote(vtoken, aye(20_000, 5)),
-			Ok(aye(1_000_000, 0))
-		);
-		for i in 1..=6_u8 {
-			assert_eq!(
-				VtokenVoting::compute_delegator_total_vote(vtoken, aye(200_000 * i as Balance, 5)),
-				Ok(aye(1_000_000, i))
-			);
-		}
-		assert_noop!(
-			VtokenVoting::compute_delegator_total_vote(vtoken, aye(1_200_002, 5)),
-			Error::<Runtime>::InsufficientFunds
-		);
-
-		assert_eq!(
-			VtokenVoting::compute_delegator_total_vote(vtoken, aye(16_666, 6)),
-			Ok(aye(999_960, 0))
-		);
-		for i in 1..=6_u8 {
-			assert_eq!(
-				VtokenVoting::compute_delegator_total_vote(vtoken, aye(166_666 * i as Balance, 6)),
-				Ok(aye(999_996, i))
-			);
-		}
-		assert_noop!(
-			VtokenVoting::compute_delegator_total_vote(vtoken, aye(1_000_001, 6)),
-			Error::<Runtime>::InsufficientFunds
-		);
-	});
-}
-
-#[test]
-fn compute_delegator_total_vote_with_low_value_will_loss() {
-	new_test_ext().execute_with(|| {
-		let vtoken = VKSM;
-		assert_eq!(VtokenVoting::compute_delegator_total_vote(vtoken, aye(9, 0)), Ok(aye(0, 0)));
-		assert_eq!(VtokenVoting::compute_delegator_total_vote(vtoken, nay(9, 0)), Ok(nay(0, 0)));
-	});
-}
-
-#[test]
-fn allocate_delegator_votes_works() {
-	new_test_ext().execute_with(|| {
-		let vtoken = VKSM;
-		let poll_index = 3;
-
-		for conviction in 0..=6 {
-			let vote = aye(5e9 as Balance, conviction);
-			let delegator_votes = VtokenVoting::allocate_delegator_votes(vtoken, poll_index, vote);
-			assert_eq!(
-				delegator_votes,
-				Ok(vec![(0, aye(4294967295, conviction)), (1, aye(705032705, conviction))])
-			);
-			assert_eq!(
-				delegator_votes.unwrap().into_iter().map(|(_derivative_index, vote)| vote).fold(
-					aye(0, conviction),
-					|mut acc, vote| {
-						let _ = acc.checked_add(vote);
-						acc
-					},
-				),
-				vote
-			);
-		}
-
-		for conviction in 0..=6 {
-			let vote = aye(3e10 as Balance, conviction);
-			let delegator_votes = VtokenVoting::allocate_delegator_votes(vtoken, poll_index, vote);
-			assert_eq!(
-				delegator_votes,
-				Ok(vec![
-					(0, aye(4294967295, conviction)),
-					(1, aye(4294967295, conviction)),
-					(2, aye(4294967295, conviction)),
-					(3, aye(4294967295, conviction)),
-					(4, aye(4294967295, conviction)),
-					(5, aye(4294967295, conviction)),
-					(10, aye(4230196230, conviction))
-				])
-			);
-			assert_eq!(
-				delegator_votes.unwrap().into_iter().map(|(_derivative_index, vote)| vote).fold(
-					aye(0, conviction),
-					|mut acc, vote| {
-						let _ = acc.checked_add(vote);
-						acc
-					},
-				),
-				vote
-			);
-		}
-	});
-}
-
-#[test]
-fn tally_convert_works() {
-	assert_eq!(
-		TallyOf::<Runtime>::from_parts(10, 9, 0).account_vote(Conviction::Locked1x),
-		aye(1, 1)
-	);
-	assert_eq!(
-		TallyOf::<Runtime>::from_parts(10, 11, 0).account_vote(Conviction::Locked1x),
-		nay(1, 1)
-	);
-	assert_eq!(
-		TallyOf::<Runtime>::from_parts(10, 10, 0).account_vote(Conviction::Locked1x),
-		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/tests/common_test.rs b/pallets/vtoken-voting/src/tests/common_test.rs
new file mode 100644
index 000000000..721d4aebd
--- /dev/null
+++ b/pallets/vtoken-voting/src/tests/common_test.rs
@@ -0,0 +1,1564 @@
+// 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 <https://www.gnu.org/licenses/>.
+
+// Ensure we're `no_std` when compiling for Wasm.
+use crate::{mock::*, *};
+use bifrost_primitives::currency::VPHA;
+use frame_support::{
+	assert_noop, assert_ok,
+	traits::{
+		fungibles::Inspect,
+		tokens::{Fortitude::Polite, Preservation::Expendable},
+	},
+	weights::RuntimeDbWeight,
+};
+use pallet_xcm::Origin as XcmOrigin;
+
+const TOKENS: &[CurrencyId] = if cfg!(feature = "polkadot") {
+	&[VDOT]
+} else if cfg!(feature = "kusama") {
+	&[VKSM]
+} else {
+	&[]
+};
+
+fn aye(amount: Balance, conviction: u8) -> AccountVote<Balance> {
+	let vote = Vote { aye: true, conviction: conviction.try_into().unwrap() };
+	AccountVote::Standard { vote, balance: amount }
+}
+
+fn nay(amount: Balance, conviction: u8) -> AccountVote<Balance> {
+	let vote = Vote { aye: false, conviction: conviction.try_into().unwrap() };
+	AccountVote::Standard { vote, balance: amount }
+}
+
+fn tally(vtoken: CurrencyId, poll_index: u32) -> TallyOf<Runtime> {
+	VtokenVoting::ensure_referendum_ongoing(vtoken, poll_index)
+		.expect("No poll")
+		.tally
+}
+
+fn usable_balance(vtoken: CurrencyId, who: &AccountId) -> Balance {
+	Tokens::reducible_balance(vtoken, who, Expendable, Polite)
+}
+
+fn origin_response() -> RuntimeOrigin {
+	XcmOrigin::Response(Parent.into()).into()
+}
+
+fn response_success() -> Response {
+	Response::DispatchResult(MaybeErrorCode::Success)
+}
+
+fn response_fail() -> Response {
+	Response::DispatchResult(MaybeErrorCode::Error(BoundedVec::try_from(vec![0u8, 1u8]).unwrap()))
+}
+
+#[test]
+fn basic_voting_works() {
+	for &vtoken in TOKENS {
+		new_test_ext().execute_with(|| {
+			let poll_index = 3;
+
+			assert_ok!(VtokenVoting::vote(
+				RuntimeOrigin::signed(ALICE),
+				vtoken,
+				poll_index,
+				aye(2, 5)
+			));
+			assert_eq!(tally(vtoken, poll_index), Tally::from_parts(20, 0, 4));
+			System::assert_last_event(RuntimeEvent::VtokenVoting(Event::Voted {
+				who: ALICE,
+				vtoken,
+				poll_index,
+				token_vote: aye(4, 5),
+				delegator_vote: aye(200, 0),
+			}));
+			assert_ok!(VtokenVoting::notify_vote(origin_response(), 0, response_success()));
+
+			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));
+			assert_eq!(usable_balance(vtoken, &ALICE), 10);
+		});
+	}
+}
+
+#[test]
+fn voting_balance_gets_locked() {
+	for &vtoken in TOKENS {
+		new_test_ext().execute_with(|| {
+			let poll_index = 3;
+
+			assert_ok!(VtokenVoting::vote(
+				RuntimeOrigin::signed(ALICE),
+				vtoken,
+				poll_index,
+				nay(10, 0)
+			));
+			assert_eq!(tally(vtoken, poll_index), Tally::from_parts(0, 2, 0));
+			assert_ok!(VtokenVoting::notify_vote(origin_response(), 0, response_success()));
+			assert_eq!(usable_balance(vtoken, &ALICE), 0);
+
+			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));
+			assert_eq!(usable_balance(vtoken, &ALICE), 10);
+		});
+	}
+}
+
+#[test]
+fn successful_but_zero_conviction_vote_balance_can_be_unlocked() {
+	for &vtoken in TOKENS {
+		new_test_ext().execute_with(|| {
+			let poll_index = 3;
+
+			assert_ok!(VtokenVoting::vote(
+				RuntimeOrigin::signed(ALICE),
+				vtoken,
+				poll_index,
+				aye(1, 1)
+			));
+			assert_eq!(usable_balance(vtoken, &ALICE), 9);
+			assert_ok!(VtokenVoting::notify_vote(origin_response(), 0, response_success()));
+			assert_ok!(VtokenVoting::vote(
+				RuntimeOrigin::signed(ALICE),
+				vtoken,
+				poll_index,
+				aye(3, 1)
+			));
+			assert_eq!(usable_balance(vtoken, &ALICE), 7);
+			assert_ok!(VtokenVoting::notify_vote(origin_response(), 1, response_success()));
+
+			assert_ok!(VtokenVoting::vote(
+				RuntimeOrigin::signed(BOB),
+				vtoken,
+				poll_index,
+				nay(20, 0)
+			));
+			assert_eq!(usable_balance(vtoken, &BOB), 0);
+			assert_ok!(VtokenVoting::notify_vote(origin_response(), 2, response_success()));
+
+			assert_ok!(VtokenVoting::set_vote_locking_period(RuntimeOrigin::root(), vtoken, 10));
+			assert_ok!(VtokenVoting::set_referendum_status(
+				RuntimeOrigin::root(),
+				vtoken,
+				poll_index,
+				ReferendumInfoOf::<Runtime>::Completed(3),
+			));
+
+			assert_ok!(VtokenVoting::unlock(RuntimeOrigin::signed(BOB), vtoken, poll_index));
+			assert_eq!(usable_balance(vtoken, &BOB), 20);
+
+			RelaychainDataProvider::set_block_number(13);
+			assert_ok!(VtokenVoting::unlock(RuntimeOrigin::signed(ALICE), vtoken, poll_index));
+			assert_eq!(usable_balance(vtoken, &ALICE), 10);
+		});
+	}
+}
+
+#[test]
+fn unsuccessful_conviction_vote_balance_can_be_unlocked() {
+	for &vtoken in TOKENS {
+		new_test_ext().execute_with(|| {
+			let poll_index = 3;
+			let locking_period = 10;
+			assert_ok!(VtokenVoting::set_vote_locking_period(
+				RuntimeOrigin::root(),
+				vtoken,
+				locking_period,
+			));
+
+			assert_ok!(VtokenVoting::vote(
+				RuntimeOrigin::signed(ALICE),
+				vtoken,
+				poll_index,
+				aye(1, 1)
+			));
+			assert_ok!(VtokenVoting::notify_vote(origin_response(), 0, response_success()));
+			assert_ok!(VtokenVoting::vote(
+				RuntimeOrigin::signed(BOB),
+				vtoken,
+				poll_index,
+				nay(20, 0)
+			));
+			assert_ok!(VtokenVoting::notify_vote(origin_response(), 1, response_success()));
+
+			assert_ok!(VtokenVoting::set_referendum_status(
+				RuntimeOrigin::root(),
+				vtoken,
+				poll_index,
+				ReferendumInfoOf::<Runtime>::Completed(3),
+			));
+			RelaychainDataProvider::set_block_number(13);
+			assert_ok!(VtokenVoting::try_remove_vote(&ALICE, vtoken, poll_index, UnvoteScope::Any));
+			assert_ok!(VtokenVoting::update_lock(&ALICE, vtoken));
+			assert_eq!(usable_balance(vtoken, &ALICE), 10);
+		});
+	}
+}
+
+#[test]
+fn ensure_balance_after_unlock() {
+	for &vtoken in TOKENS {
+		new_test_ext().execute_with(|| {
+			let poll_index = 3;
+			let poll_index_2 = 4;
+			let locking_period = 10;
+			assert_ok!(VtokenVoting::set_vote_locking_period(
+				RuntimeOrigin::root(),
+				vtoken,
+				locking_period,
+			));
+
+			assert_ok!(VtokenVoting::vote(
+				RuntimeOrigin::signed(ALICE),
+				vtoken,
+				poll_index,
+				aye(10, 1)
+			));
+			assert_ok!(VtokenVoting::notify_vote(origin_response(), 0, response_success()));
+			assert_ok!(VtokenVoting::vote(
+				RuntimeOrigin::signed(ALICE),
+				vtoken,
+				poll_index_2,
+				aye(10, 5)
+			));
+			assert_ok!(VtokenVoting::notify_vote(origin_response(), 1, response_success()));
+
+			assert_ok!(VtokenVoting::set_referendum_status(
+				RuntimeOrigin::root(),
+				vtoken,
+				poll_index,
+				ReferendumInfoOf::<Runtime>::Completed(3),
+			));
+			RelaychainDataProvider::set_block_number(13);
+			assert_ok!(VtokenVoting::unlock(RuntimeOrigin::signed(ALICE), vtoken, poll_index));
+			assert_eq!(usable_balance(vtoken, &ALICE), 0);
+			assert_eq!(Tokens::accounts(&ALICE, vtoken).frozen, 10);
+			assert_eq!(VotingFor::<Runtime>::get(&ALICE).locked_balance(), 10);
+		});
+	}
+}
+
+#[test]
+fn ensure_comprehensive_balance_after_unlock() {
+	for &vtoken in TOKENS {
+		new_test_ext().execute_with(|| {
+			let poll_index = 3;
+			let poll_index_2 = 4;
+			let poll_index_3 = 5;
+			let locking_period = 10;
+			assert_ok!(VtokenVoting::set_vote_locking_period(
+				RuntimeOrigin::root(),
+				vtoken,
+				locking_period,
+			));
+
+			assert_ok!(VtokenVoting::vote(
+				RuntimeOrigin::signed(ALICE),
+				vtoken,
+				poll_index,
+				aye(2, 1)
+			));
+			assert_ok!(VtokenVoting::notify_vote(origin_response(), 0, response_success()));
+			assert_ok!(VtokenVoting::vote(
+				RuntimeOrigin::signed(ALICE),
+				vtoken,
+				poll_index_2,
+				aye(1, 5)
+			));
+			assert_ok!(VtokenVoting::notify_vote(origin_response(), 1, response_success()));
+			assert_ok!(VtokenVoting::vote(
+				RuntimeOrigin::signed(ALICE),
+				vtoken,
+				poll_index_3,
+				aye(2, 5)
+			));
+			assert_ok!(VtokenVoting::notify_vote(origin_response(), 2, response_success()));
+
+			assert_ok!(VtokenVoting::set_referendum_status(
+				RuntimeOrigin::root(),
+				vtoken,
+				poll_index,
+				ReferendumInfoOf::<Runtime>::Completed(3),
+			));
+			RelaychainDataProvider::set_block_number(13);
+			assert_ok!(VtokenVoting::unlock(RuntimeOrigin::signed(ALICE), vtoken, poll_index));
+			assert_eq!(usable_balance(vtoken, &ALICE), 8);
+			assert_eq!(Tokens::accounts(&ALICE, vtoken).frozen, 2);
+			assert_eq!(VotingFor::<Runtime>::get(&ALICE).locked_balance(), 2);
+
+			assert_ok!(VtokenVoting::vote(
+				RuntimeOrigin::signed(ALICE),
+				vtoken,
+				poll_index_2,
+				aye(10, 5)
+			));
+			assert_ok!(VtokenVoting::notify_vote(origin_response(), 3, response_success()));
+
+			assert_eq!(usable_balance(vtoken, &ALICE), 0);
+			assert_eq!(Tokens::accounts(&ALICE, vtoken).frozen, 10);
+			assert_eq!(VotingFor::<Runtime>::get(&ALICE).locked_balance(), 10);
+		});
+	}
+}
+
+#[test]
+fn successful_conviction_vote_balance_stays_locked_for_correct_time() {
+	for &vtoken in TOKENS {
+		new_test_ext().execute_with(|| {
+			let poll_index = 3;
+			let locking_period = 10;
+			assert_ok!(VtokenVoting::set_vote_locking_period(
+				RuntimeOrigin::root(),
+				vtoken,
+				locking_period,
+			));
+			for i in 1..=5 {
+				assert_ok!(VtokenVoting::vote(
+					RuntimeOrigin::signed(i),
+					vtoken,
+					poll_index,
+					aye(10, i as u8)
+				));
+				assert_ok!(VtokenVoting::notify_vote(origin_response(), i - 1, response_success()));
+			}
+			assert_ok!(VtokenVoting::set_referendum_status(
+				RuntimeOrigin::root(),
+				vtoken,
+				poll_index,
+				ReferendumInfoOf::<Runtime>::Completed(3),
+			));
+			RelaychainDataProvider::set_block_number(163);
+			for i in 1..=5 {
+				assert_ok!(VtokenVoting::try_remove_vote(&i, vtoken, poll_index, UnvoteScope::Any));
+			}
+			for i in 1..=5 {
+				assert_ok!(VtokenVoting::update_lock(&i, vtoken));
+				assert_eq!(usable_balance(vtoken, &i), 10 * i as u128);
+			}
+		});
+	}
+}
+
+#[test]
+fn lock_amalgamation_valid_with_multiple_removed_votes() {
+	for &vtoken in TOKENS {
+		new_test_ext().execute_with(|| {
+			let response = response_success();
+
+			assert_ok!(VtokenVoting::vote(RuntimeOrigin::signed(ALICE), vtoken, 0, aye(5, 1)));
+			assert_ok!(VtokenVoting::notify_vote(origin_response(), 0, response.clone()));
+			assert_eq!(
+				ClassLocksFor::<Runtime>::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::<Runtime>::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::<Runtime>::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::<Runtime>::get(&ALICE),
+				BoundedVec::<(CurrencyId, u128), ConstU32<256>>::try_from(vec![(vtoken, 10),])
+					.unwrap()
+			);
+
+			assert_ok!(VtokenVoting::set_referendum_status(
+				RuntimeOrigin::root(),
+				vtoken,
+				0,
+				ReferendumInfoOf::<Runtime>::Completed(1),
+			));
+			assert_ok!(VtokenVoting::set_referendum_status(
+				RuntimeOrigin::root(),
+				vtoken,
+				1,
+				ReferendumInfoOf::<Runtime>::Completed(1),
+			));
+			assert_ok!(VtokenVoting::set_referendum_status(
+				RuntimeOrigin::root(),
+				vtoken,
+				2,
+				ReferendumInfoOf::<Runtime>::Completed(1),
+			));
+
+			let locking_period = 10;
+			assert_ok!(VtokenVoting::set_vote_locking_period(
+				RuntimeOrigin::root(),
+				vtoken,
+				locking_period,
+			));
+			assert_eq!(VoteLockingPeriod::<Runtime>::get(vtoken), Some(10));
+
+			assert_eq!(
+				ClassLocksFor::<Runtime>::get(&ALICE),
+				BoundedVec::<(CurrencyId, u128), ConstU32<256>>::try_from(vec![(vtoken, 10),])
+					.unwrap()
+			);
+
+			RelaychainDataProvider::set_block_number(10);
+			assert_noop!(
+				VtokenVoting::unlock(RuntimeOrigin::signed(ALICE), vtoken, 0),
+				Error::<Runtime>::NoPermissionYet
+			);
+			assert_eq!(VotingFor::<Runtime>::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::<Runtime>::get(&ALICE).locked_balance(), 10);
+			assert_eq!(usable_balance(vtoken, &ALICE), 0);
+			assert_eq!(
+				ClassLocksFor::<Runtime>::get(&ALICE),
+				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), 0);
+			assert_eq!(
+				ClassLocksFor::<Runtime>::get(&ALICE),
+				BoundedVec::<(CurrencyId, u128), ConstU32<256>>::try_from(vec![(vtoken, 10)])
+					.unwrap()
+			);
+
+			RelaychainDataProvider::set_block_number(21);
+			assert_ok!(VtokenVoting::unlock(RuntimeOrigin::signed(ALICE), vtoken, 2));
+			assert_eq!(usable_balance(vtoken, &ALICE), 10);
+			assert_eq!(
+				ClassLocksFor::<Runtime>::get(&ALICE),
+				BoundedVec::<(CurrencyId, u128), ConstU32<256>>::try_from(vec![]).unwrap()
+			);
+		});
+	}
+}
+
+#[test]
+fn removed_votes_when_referendum_killed() {
+	for &vtoken in TOKENS {
+		new_test_ext().execute_with(|| {
+			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_ok!(VtokenVoting::notify_vote(origin_response(), 1, response.clone()));
+			assert_ok!(VtokenVoting::notify_vote(origin_response(), 2, response.clone()));
+
+			assert_ok!(VtokenVoting::set_referendum_status(
+				RuntimeOrigin::root(),
+				vtoken,
+				0,
+				ReferendumInfoOf::<Runtime>::Completed(1),
+			));
+			assert_ok!(VtokenVoting::set_referendum_status(
+				RuntimeOrigin::root(),
+				vtoken,
+				1,
+				ReferendumInfoOf::<Runtime>::Completed(1),
+			));
+			assert_ok!(VtokenVoting::set_referendum_status(
+				RuntimeOrigin::root(),
+				vtoken,
+				2,
+				ReferendumInfoOf::<Runtime>::Completed(1),
+			));
+
+			assert_ok!(VtokenVoting::kill_referendum(RuntimeOrigin::root(), vtoken, 0));
+			assert_ok!(VtokenVoting::kill_referendum(RuntimeOrigin::root(), vtoken, 1));
+			assert_ok!(VtokenVoting::kill_referendum(RuntimeOrigin::root(), vtoken, 2));
+
+			assert_eq!(
+				ClassLocksFor::<Runtime>::get(&ALICE),
+				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::<Runtime>::get(&ALICE),
+				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::<Runtime>::get(&ALICE),
+				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::<Runtime>::get(&ALICE),
+				BoundedVec::<(CurrencyId, u128), ConstU32<256>>::try_from(vec![]).unwrap()
+			);
+		});
+	}
+}
+
+#[test]
+fn errors_with_vote_works() {
+	for &vtoken in TOKENS {
+		new_test_ext().execute_with(|| {
+			assert_noop!(
+				VtokenVoting::vote(RuntimeOrigin::signed(1), VPHA, 0, aye(10, 0)),
+				Error::<Runtime>::VTokenNotSupport
+			);
+			assert_noop!(
+				VtokenVoting::vote(RuntimeOrigin::signed(1), vtoken, 3, aye(11, 0)),
+				Error::<Runtime>::InsufficientFunds
+			);
+
+			for poll_index in 0..256 {
+				assert_ok!(VtokenVoting::vote(
+					RuntimeOrigin::signed(1),
+					vtoken,
+					poll_index,
+					aye(10, 0)
+				));
+			}
+			assert_noop!(
+				VtokenVoting::vote(RuntimeOrigin::signed(1), vtoken, 256, aye(10, 0)),
+				Error::<Runtime>::MaxVotesReached
+			);
+		});
+	}
+}
+
+#[test]
+fn kill_referendum_works() {
+	for &vtoken in TOKENS {
+		new_test_ext().execute_with(|| {
+			let poll_index = 3;
+
+			assert_ok!(VtokenVoting::vote(
+				RuntimeOrigin::signed(ALICE),
+				vtoken,
+				poll_index,
+				aye(5, 1)
+			));
+			assert_ok!(VtokenVoting::set_referendum_status(
+				RuntimeOrigin::root(),
+				vtoken,
+				poll_index,
+				ReferendumInfoOf::<Runtime>::Completed(1),
+			));
+			assert_ok!(VtokenVoting::kill_referendum(RuntimeOrigin::root(), vtoken, poll_index));
+			System::assert_last_event(RuntimeEvent::VtokenVoting(Event::ReferendumKilled {
+				vtoken,
+				poll_index,
+			}));
+		});
+	}
+}
+
+#[test]
+fn kill_referendum_with_origin_signed_fails() {
+	for &vtoken in TOKENS {
+		new_test_ext().execute_with(|| {
+			let poll_index = 3;
+
+			assert_ok!(VtokenVoting::vote(
+				RuntimeOrigin::signed(ALICE),
+				vtoken,
+				poll_index,
+				aye(5, 1)
+			));
+			assert_ok!(VtokenVoting::set_referendum_status(
+				RuntimeOrigin::root(),
+				vtoken,
+				poll_index,
+				ReferendumInfoOf::<Runtime>::Completed(1),
+			));
+			assert_noop!(
+				VtokenVoting::kill_referendum(RuntimeOrigin::signed(ALICE), vtoken, poll_index),
+				DispatchError::BadOrigin
+			);
+		});
+	}
+}
+
+#[test]
+fn add_delegator_works() {
+	for &vtoken in TOKENS {
+		new_test_ext().execute_with(|| {
+			let derivative_index: DerivativeIndex = 100;
+
+			assert_ok!(VtokenVoting::add_delegator(
+				RuntimeOrigin::root(),
+				vtoken,
+				derivative_index,
+			));
+
+			System::assert_last_event(RuntimeEvent::VtokenVoting(Event::DelegatorAdded {
+				vtoken,
+				derivative_index,
+			}));
+		});
+	}
+}
+
+#[test]
+fn set_referendum_status_works() {
+	for &vtoken in TOKENS {
+		new_test_ext().execute_with(|| {
+			let poll_index = 3;
+			let info = ReferendumInfo::Completed(3);
+
+			assert_ok!(VtokenVoting::vote(
+				RuntimeOrigin::signed(ALICE),
+				vtoken,
+				poll_index,
+				aye(2, 5)
+			));
+			assert_ok!(VtokenVoting::set_referendum_status(
+				RuntimeOrigin::root(),
+				vtoken,
+				poll_index,
+				info.clone(),
+			));
+
+			System::assert_last_event(RuntimeEvent::VtokenVoting(Event::ReferendumInfoSet {
+				vtoken,
+				poll_index,
+				info,
+			}));
+		});
+	}
+}
+
+#[test]
+fn set_referendum_status_without_vote_should_fail() {
+	for &vtoken in TOKENS {
+		new_test_ext().execute_with(|| {
+			let poll_index = 3;
+			let info = ReferendumInfo::Completed(3);
+
+			assert_noop!(
+				VtokenVoting::set_referendum_status(
+					RuntimeOrigin::root(),
+					vtoken,
+					poll_index,
+					info.clone(),
+				),
+				Error::<Runtime>::NoData
+			);
+		});
+	}
+}
+
+#[test]
+fn set_referendum_status_with_origin_signed_should_fail() {
+	for &vtoken in TOKENS {
+		new_test_ext().execute_with(|| {
+			let poll_index = 3;
+			let info = ReferendumInfo::Completed(3);
+
+			assert_noop!(
+				VtokenVoting::set_referendum_status(
+					RuntimeOrigin::signed(ALICE),
+					vtoken,
+					poll_index,
+					info.clone(),
+				),
+				DispatchError::BadOrigin
+			);
+		});
+	}
+}
+
+#[test]
+fn set_vote_locking_period_works() {
+	for &vtoken in TOKENS {
+		new_test_ext().execute_with(|| {
+			let locking_period = 100;
+
+			assert_ok!(VtokenVoting::set_vote_locking_period(
+				RuntimeOrigin::root(),
+				vtoken,
+				locking_period,
+			));
+
+			System::assert_last_event(RuntimeEvent::VtokenVoting(Event::VoteLockingPeriodSet {
+				vtoken,
+				locking_period,
+			}));
+		});
+	}
+}
+
+#[test]
+fn set_vote_locking_period_with_origin_signed_should_fail() {
+	for &vtoken in TOKENS {
+		new_test_ext().execute_with(|| {
+			let locking_period = 100;
+
+			assert_noop!(
+				VtokenVoting::set_vote_locking_period(
+					RuntimeOrigin::signed(ALICE),
+					vtoken,
+					locking_period,
+				),
+				DispatchError::BadOrigin
+			);
+		});
+	}
+}
+
+#[test]
+fn set_undeciding_timeout_works() {
+	for &vtoken in TOKENS {
+		new_test_ext().execute_with(|| {
+			let undeciding_timeout = 100;
+
+			assert_ok!(VtokenVoting::set_undeciding_timeout(
+				RuntimeOrigin::root(),
+				vtoken,
+				undeciding_timeout,
+			));
+
+			System::assert_last_event(RuntimeEvent::VtokenVoting(Event::UndecidingTimeoutSet {
+				vtoken,
+				undeciding_timeout,
+			}));
+		});
+	}
+}
+
+#[test]
+fn set_undeciding_timeout_with_origin_signed_should_fail() {
+	for &vtoken in TOKENS {
+		new_test_ext().execute_with(|| {
+			let undeciding_timeout = 100;
+
+			assert_noop!(
+				VtokenVoting::set_undeciding_timeout(
+					RuntimeOrigin::signed(ALICE),
+					vtoken,
+					undeciding_timeout,
+				),
+				DispatchError::BadOrigin
+			);
+		});
+	}
+}
+
+#[test]
+fn notify_vote_success_works() {
+	for &vtoken in TOKENS {
+		new_test_ext().execute_with(|| {
+			let poll_index = 3;
+			let query_id = 0;
+			let response = response_success();
+			let derivative_index = 0;
+
+			assert_ok!(VtokenVoting::vote(
+				RuntimeOrigin::signed(ALICE),
+				vtoken,
+				poll_index,
+				aye(2, 5)
+			));
+			assert_eq!(
+				ReferendumInfoFor::<Runtime>::get(vtoken, poll_index),
+				Some(ReferendumInfo::Ongoing(ReferendumStatus {
+					submitted: None,
+					tally: TallyOf::<Runtime>::from_parts(20, 0, 4),
+				}))
+			);
+			assert_eq!(
+				PendingDelegatorVotes::<Runtime>::get(vtoken, poll_index),
+				BoundedVec::<(DerivativeIndex, AccountVote<Balance>), ConstU32<100>>::try_from(
+					vec![(derivative_index, aye(200, 0))]
+				)
+				.unwrap()
+			);
+			assert_eq!(DelegatorVotes::<Runtime>::get(vtoken, poll_index).len(), 0);
+			assert_eq!(tally(vtoken, poll_index), Tally::from_parts(20, 0, 4));
+			System::assert_last_event(RuntimeEvent::VtokenVoting(Event::Voted {
+				who: ALICE,
+				vtoken,
+				poll_index,
+				token_vote: aye(4, 5),
+				delegator_vote: aye(200, 0),
+			}));
+
+			assert_ok!(VtokenVoting::notify_vote(origin_response(), query_id, response.clone()));
+			assert_eq!(
+				ReferendumInfoFor::<Runtime>::get(vtoken, poll_index),
+				Some(ReferendumInfo::Ongoing(ReferendumStatus {
+					submitted: Some(1),
+					tally: TallyOf::<Runtime>::from_parts(20, 0, 4),
+				}))
+			);
+			assert_eq!(PendingDelegatorVotes::<Runtime>::get(vtoken, poll_index).len(), 0);
+			assert_eq!(
+				DelegatorVotes::<Runtime>::get(vtoken, poll_index),
+				BoundedVec::<(DerivativeIndex, AccountVote<Balance>), ConstU32<100>>::try_from(
+					vec![(derivative_index, aye(200, 0))]
+				)
+				.unwrap()
+			);
+			System::assert_has_event(RuntimeEvent::VtokenVoting(Event::VoteNotified {
+				vtoken,
+				poll_index,
+				success: true,
+			}));
+			System::assert_has_event(RuntimeEvent::VtokenVoting(Event::ReferendumInfoCreated {
+				vtoken,
+				poll_index,
+				info: ReferendumInfo::Ongoing(ReferendumStatus {
+					submitted: Some(1),
+					tally: TallyOf::<Runtime>::from_parts(20, 0, 4),
+				}),
+			}));
+			System::assert_last_event(RuntimeEvent::VtokenVoting(Event::ResponseReceived {
+				responder: Parent.into(),
+				query_id,
+				response,
+			}));
+		});
+	}
+}
+
+#[test]
+fn notify_vote_success_max_works() {
+	for &vtoken in TOKENS {
+		new_test_ext().execute_with(|| {
+			for poll_index in 0..256 {
+				RelaychainDataProvider::set_block_number(1);
+
+				assert_ok!(VtokenVoting::vote(
+					RuntimeOrigin::signed(ALICE),
+					vtoken,
+					poll_index,
+					aye(2, 5)
+				));
+				assert_ok!(VtokenVoting::notify_vote(
+					origin_response(),
+					poll_index as QueryId,
+					response_success()
+				));
+
+				RelaychainDataProvider::set_block_number(
+					1 + UndecidingTimeout::<Runtime>::get(vtoken).unwrap(),
+				);
+				VtokenVoting::on_idle(Zero::zero(), Weight::MAX);
+			}
+		});
+	}
+}
+
+#[test]
+fn notify_vote_success_exceed_max_fail() {
+	for &vtoken in TOKENS {
+		new_test_ext().execute_with(|| {
+			for poll_index in 0..50 {
+				assert_ok!(VtokenVoting::vote(
+					RuntimeOrigin::signed(ALICE),
+					vtoken,
+					poll_index,
+					aye(2, 5)
+				));
+				assert_ok!(VtokenVoting::notify_vote(
+					origin_response(),
+					poll_index as QueryId,
+					response_success()
+				));
+			}
+			let poll_index = 50;
+			assert_ok!(VtokenVoting::vote(
+				RuntimeOrigin::signed(ALICE),
+				vtoken,
+				poll_index,
+				aye(2, 5)
+			));
+			assert_noop!(
+				VtokenVoting::notify_vote(
+					origin_response(),
+					poll_index as QueryId,
+					response_success()
+				),
+				Error::<Runtime>::TooMany
+			);
+		});
+	}
+}
+
+#[test]
+fn notify_vote_fail_works() {
+	for &vtoken in TOKENS {
+		new_test_ext().execute_with(|| {
+			let poll_index = 3;
+			let query_id = 0;
+			let response = response_fail();
+			let derivative_index = 0;
+
+			assert_ok!(VtokenVoting::vote(
+				RuntimeOrigin::signed(ALICE),
+				vtoken,
+				poll_index,
+				aye(2, 5)
+			));
+			assert_eq!(
+				ReferendumInfoFor::<Runtime>::get(vtoken, poll_index),
+				Some(ReferendumInfo::Ongoing(ReferendumStatus {
+					submitted: None,
+					tally: TallyOf::<Runtime>::from_parts(20, 0, 4),
+				}))
+			);
+			assert_eq!(DelegatorVotes::<Runtime>::get(vtoken, poll_index).len(), 0);
+			assert_eq!(
+				PendingDelegatorVotes::<Runtime>::get(vtoken, poll_index),
+				BoundedVec::<(DerivativeIndex, AccountVote<Balance>), ConstU32<100>>::try_from(
+					vec![(derivative_index, aye(200, 0))]
+				)
+				.unwrap()
+			);
+			assert_eq!(tally(vtoken, poll_index), Tally::from_parts(20, 0, 4));
+			System::assert_last_event(RuntimeEvent::VtokenVoting(Event::Voted {
+				who: ALICE,
+				vtoken,
+				poll_index,
+				token_vote: aye(4, 5),
+				delegator_vote: aye(200, 0),
+			}));
+
+			assert_ok!(VtokenVoting::notify_vote(origin_response(), query_id, response.clone()));
+			assert_eq!(ReferendumInfoFor::<Runtime>::get(vtoken, poll_index), None);
+			assert_eq!(DelegatorVotes::<Runtime>::get(vtoken, poll_index).len(), 0);
+			assert_eq!(PendingDelegatorVotes::<Runtime>::get(vtoken, poll_index).len(), 0);
+			System::assert_last_event(RuntimeEvent::VtokenVoting(Event::ResponseReceived {
+				responder: Parent.into(),
+				query_id,
+				response,
+			}));
+		});
+	}
+}
+
+#[test]
+fn notify_vote_with_no_data_works() {
+	new_test_ext().execute_with(|| {
+		let query_id = 0;
+		let response = response_success();
+
+		assert_ok!(VtokenVoting::notify_vote(origin_response(), query_id, response.clone()));
+		System::assert_last_event(RuntimeEvent::VtokenVoting(Event::ResponseReceived {
+			responder: Parent.into(),
+			query_id,
+			response,
+		}));
+	});
+}
+
+#[test]
+fn notify_remove_delegator_vote_success_works() {
+	for &vtoken in TOKENS {
+		new_test_ext().execute_with(|| {
+			let class = 0;
+			let poll_index = 3;
+			let mut query_id = 0;
+			let derivative_index = 0;
+			let response = response_success();
+
+			assert_ok!(VtokenVoting::vote(
+				RuntimeOrigin::signed(ALICE),
+				vtoken,
+				poll_index,
+				aye(2, 5)
+			));
+			assert_eq!(DelegatorVotes::<Runtime>::get(vtoken, poll_index).len(), 0);
+			assert_eq!(
+				PendingDelegatorVotes::<Runtime>::get(vtoken, poll_index),
+				BoundedVec::<(DerivativeIndex, AccountVote<Balance>), ConstU32<100>>::try_from(
+					vec![(derivative_index, aye(200, 0))]
+				)
+				.unwrap()
+			);
+			assert_eq!(tally(vtoken, poll_index), Tally::from_parts(20, 0, 4));
+			System::assert_last_event(RuntimeEvent::VtokenVoting(Event::Voted {
+				who: ALICE,
+				vtoken,
+				poll_index,
+				token_vote: aye(4, 5),
+				delegator_vote: aye(200, 0),
+			}));
+			assert_ok!(VtokenVoting::notify_vote(origin_response(), query_id, response.clone()));
+			assert_eq!(
+				DelegatorVotes::<Runtime>::get(vtoken, poll_index),
+				BoundedVec::<(DerivativeIndex, AccountVote<Balance>), ConstU32<100>>::try_from(
+					vec![(derivative_index, aye(200, 0))]
+				)
+				.unwrap()
+			);
+			assert_eq!(PendingDelegatorVotes::<Runtime>::get(vtoken, poll_index).len(), 0);
+
+			assert_ok!(VtokenVoting::set_referendum_status(
+				RuntimeOrigin::root(),
+				vtoken,
+				poll_index,
+				ReferendumInfoOf::<Runtime>::Completed(3),
+			));
+			assert_ok!(VtokenVoting::set_vote_locking_period(RuntimeOrigin::root(), vtoken, 10));
+
+			RelaychainDataProvider::set_block_number(3);
+			assert_ok!(VtokenVoting::remove_delegator_vote(
+				RuntimeOrigin::signed(ALICE),
+				vtoken,
+				class,
+				poll_index,
+				derivative_index,
+			));
+			assert_eq!(DelegatorVotes::<Runtime>::get(vtoken, poll_index).len(), 1);
+
+			query_id = 1;
+			assert_ok!(VtokenVoting::notify_remove_delegator_vote(
+				origin_response(),
+				query_id,
+				response.clone()
+			));
+			assert_eq!(DelegatorVotes::<Runtime>::get(vtoken, poll_index).len(), 0);
+			System::assert_has_event(RuntimeEvent::VtokenVoting(
+				Event::DelegatorVoteRemovedNotified { vtoken, poll_index, success: true },
+			));
+			System::assert_last_event(RuntimeEvent::VtokenVoting(Event::ResponseReceived {
+				responder: Parent.into(),
+				query_id,
+				response,
+			}));
+		});
+	}
+}
+
+#[test]
+fn notify_remove_delegator_vote_fail_works() {
+	for &vtoken in TOKENS {
+		new_test_ext().execute_with(|| {
+			let class = 0;
+			let poll_index = 3;
+			let mut query_id = 0;
+			let derivative_index = 0;
+			let response = response_fail();
+
+			assert_ok!(VtokenVoting::vote(
+				RuntimeOrigin::signed(ALICE),
+				vtoken,
+				poll_index,
+				aye(2, 5)
+			));
+			assert_eq!(DelegatorVotes::<Runtime>::get(vtoken, poll_index).len(), 0);
+			assert_eq!(
+				PendingDelegatorVotes::<Runtime>::get(vtoken, poll_index),
+				BoundedVec::<(DerivativeIndex, AccountVote<Balance>), ConstU32<100>>::try_from(
+					vec![(derivative_index, aye(200, 0))]
+				)
+				.unwrap()
+			);
+			assert_eq!(tally(vtoken, poll_index), Tally::from_parts(20, 0, 4));
+			System::assert_last_event(RuntimeEvent::VtokenVoting(Event::Voted {
+				who: ALICE,
+				vtoken,
+				poll_index,
+				token_vote: aye(4, 5),
+				delegator_vote: aye(200, 0),
+			}));
+			assert_ok!(VtokenVoting::notify_vote(origin_response(), query_id, response_success()));
+			assert_eq!(
+				DelegatorVotes::<Runtime>::get(vtoken, poll_index),
+				BoundedVec::<(DerivativeIndex, AccountVote<Balance>), ConstU32<100>>::try_from(
+					vec![(derivative_index, aye(200, 0))]
+				)
+				.unwrap()
+			);
+			assert_eq!(PendingDelegatorVotes::<Runtime>::get(vtoken, poll_index).len(), 0);
+
+			assert_ok!(VtokenVoting::set_referendum_status(
+				RuntimeOrigin::root(),
+				vtoken,
+				poll_index,
+				ReferendumInfoOf::<Runtime>::Completed(3),
+			));
+			assert_ok!(VtokenVoting::set_vote_locking_period(RuntimeOrigin::root(), vtoken, 10));
+
+			RelaychainDataProvider::set_block_number(3);
+			assert_ok!(VtokenVoting::remove_delegator_vote(
+				RuntimeOrigin::signed(ALICE),
+				vtoken,
+				class,
+				poll_index,
+				derivative_index,
+			));
+			assert_eq!(DelegatorVotes::<Runtime>::get(vtoken, poll_index).len(), 1);
+
+			query_id = 1;
+			assert_ok!(VtokenVoting::notify_remove_delegator_vote(
+				origin_response(),
+				query_id,
+				response.clone()
+			));
+			assert_eq!(DelegatorVotes::<Runtime>::get(vtoken, poll_index).len(), 1);
+			System::assert_last_event(RuntimeEvent::VtokenVoting(Event::ResponseReceived {
+				responder: Parent.into(),
+				query_id,
+				response,
+			}));
+		});
+	}
+}
+
+#[test]
+fn notify_remove_delegator_vote_with_no_data_works() {
+	new_test_ext().execute_with(|| {
+		let query_id = 0;
+		let response = response_success();
+
+		assert_ok!(VtokenVoting::notify_remove_delegator_vote(
+			origin_response(),
+			query_id,
+			response.clone(),
+		));
+		System::assert_last_event(RuntimeEvent::VtokenVoting(Event::ResponseReceived {
+			responder: Parent.into(),
+			query_id,
+			response,
+		}));
+	});
+}
+
+#[test]
+fn on_idle_works() {
+	for &vtoken in TOKENS {
+		new_test_ext().execute_with(|| {
+			for (index, poll_index) in (0..50).collect::<Vec<_>>().iter().enumerate() {
+				let relay_block_number = index as BlockNumber;
+				let query_id = index as QueryId;
+				RelaychainDataProvider::set_block_number(relay_block_number);
+				assert_ok!(VtokenVoting::vote(
+					RuntimeOrigin::signed(ALICE),
+					vtoken,
+					*poll_index,
+					aye(2, 5)
+				));
+				assert_ok!(VtokenVoting::notify_vote(
+					origin_response(),
+					query_id as QueryId,
+					response_success()
+				));
+			}
+
+			let count = 30;
+			RelaychainDataProvider::set_block_number(
+				count + UndecidingTimeout::<Runtime>::get(vtoken).unwrap(),
+			);
+			let db_weight = RuntimeDbWeight { read: 1, write: 1 };
+			let weight = db_weight.reads(3) +
+				db_weight.reads_writes(1, 2) * count +
+				db_weight.writes(2) * count;
+			let used_weight = VtokenVoting::on_idle(Zero::zero(), weight);
+			assert_eq!(used_weight, Weight::from_parts(0, 0));
+
+			let mut actual_count = 0;
+			for poll_index in 0..50 {
+				let relay_block_number = poll_index as BlockNumber;
+				if ReferendumTimeout::<Runtime>::get(
+					relay_block_number + UndecidingTimeout::<Runtime>::get(vtoken).unwrap(),
+				)
+				.is_empty()
+				{
+					actual_count += 1;
+				}
+			}
+			assert_eq!(actual_count, 31);
+		});
+	}
+}
+
+#[test]
+fn set_vote_cap_ratio_works() {
+	for &vtoken in TOKENS {
+		new_test_ext().execute_with(|| {
+			assert_ok!(VtokenVoting::set_vote_cap_ratio(
+				RuntimeOrigin::root(),
+				vtoken,
+				Perbill::from_percent(0)
+			));
+			assert_eq!(VoteCapRatio::<Runtime>::get(vtoken), Perbill::from_percent(0));
+
+			assert_ok!(VtokenVoting::set_vote_cap_ratio(
+				RuntimeOrigin::root(),
+				vtoken,
+				Perbill::from_percent(10)
+			));
+			assert_eq!(VoteCapRatio::<Runtime>::get(vtoken), Perbill::from_percent(10));
+
+			assert_ok!(VtokenVoting::set_vote_cap_ratio(
+				RuntimeOrigin::root(),
+				vtoken,
+				Perbill::from_percent(100)
+			));
+			assert_eq!(VoteCapRatio::<Runtime>::get(vtoken), Perbill::from_percent(100));
+		});
+	}
+}
+
+#[test]
+fn vote_cap_works() {
+	for &vtoken in TOKENS {
+		new_test_ext().execute_with(|| {
+			assert_eq!(VtokenVoting::vote_cap(vtoken), Ok((u64::MAX / 10) as Balance));
+		});
+	}
+}
+
+#[test]
+fn vote_to_capital_works() {
+	new_test_ext().execute_with(|| {
+		assert_eq!(VtokenVoting::vote_to_capital(Conviction::None, 300), 3000);
+		assert_eq!(VtokenVoting::vote_to_capital(Conviction::Locked1x, 300), 300);
+		assert_eq!(VtokenVoting::vote_to_capital(Conviction::Locked2x, 300), 150);
+		assert_eq!(VtokenVoting::vote_to_capital(Conviction::Locked3x, 300), 100);
+		assert_eq!(VtokenVoting::vote_to_capital(Conviction::Locked4x, 300), 75);
+		assert_eq!(VtokenVoting::vote_to_capital(Conviction::Locked5x, 300), 60);
+		assert_eq!(VtokenVoting::vote_to_capital(Conviction::Locked6x, 300), 50);
+	});
+}
+
+#[test]
+fn compute_delegator_total_vote_works() {
+	for &vtoken in TOKENS {
+		new_test_ext().execute_with(|| {
+			assert_eq!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, aye(10, 0)),
+				Ok(aye(10, 0))
+			);
+			assert_eq!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, aye(2, 1)),
+				Ok(aye(20, 0))
+			);
+			assert_eq!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, aye(2, 2)),
+				Ok(aye(40, 0))
+			);
+			assert_eq!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, aye(2, 3)),
+				Ok(aye(60, 0))
+			);
+			assert_eq!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, aye(2, 4)),
+				Ok(aye(80, 0))
+			);
+			assert_eq!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, aye(2, 5)),
+				Ok(aye(100, 0))
+			);
+			assert_eq!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, aye(2, 6)),
+				Ok(aye(120, 0))
+			);
+
+			assert_eq!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, nay(10, 0)),
+				Ok(nay(10, 0))
+			);
+			assert_eq!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, nay(2, 1)),
+				Ok(nay(20, 0))
+			);
+			assert_eq!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, nay(2, 2)),
+				Ok(nay(40, 0))
+			);
+			assert_eq!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, nay(2, 3)),
+				Ok(nay(60, 0))
+			);
+			assert_eq!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, nay(2, 4)),
+				Ok(nay(80, 0))
+			);
+			assert_eq!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, nay(2, 5)),
+				Ok(nay(100, 0))
+			);
+			assert_eq!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, nay(2, 6)),
+				Ok(nay(120, 0))
+			);
+
+			SimpleVTokenSupplyProvider::set_token_supply(10_000_000);
+			assert_eq!(VtokenVoting::vote_cap(vtoken), Ok(1_000_000));
+			assert_eq!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, aye(1_000_000, 0)),
+				Ok(aye(1_000_000, 0))
+			);
+			for i in 1..=6_u8 {
+				assert_eq!(
+					VtokenVoting::compute_delegator_total_vote(
+						vtoken,
+						aye(10_000_000 * i as Balance, 0)
+					),
+					Ok(aye(1_000_000, i))
+				);
+			}
+
+			assert_eq!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, aye(100_000, 1)),
+				Ok(aye(1_000_000, 0))
+			);
+			for i in 1..=6_u8 {
+				assert_eq!(
+					VtokenVoting::compute_delegator_total_vote(
+						vtoken,
+						aye(1_000_000 * i as Balance, 1)
+					),
+					Ok(aye(1_000_000, i))
+				);
+			}
+			assert_noop!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, aye(6_000_006, 1)),
+				Error::<Runtime>::InsufficientFunds
+			);
+
+			assert_eq!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, aye(50_000, 2)),
+				Ok(aye(1_000_000, 0))
+			);
+			for i in 1..=6_u8 {
+				assert_eq!(
+					VtokenVoting::compute_delegator_total_vote(
+						vtoken,
+						aye(500_000 * i as Balance, 2)
+					),
+					Ok(aye(1_000_000, i))
+				);
+			}
+			assert_noop!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, aye(3_000_003, 2)),
+				Error::<Runtime>::InsufficientFunds
+			);
+
+			assert_eq!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, aye(33_333, 3)),
+				Ok(aye(999_990, 0))
+			);
+			for i in 1..=6_u8 {
+				assert_eq!(
+					VtokenVoting::compute_delegator_total_vote(
+						vtoken,
+						aye(333_333 * i as Balance, 3)
+					),
+					Ok(aye(999_999, i))
+				);
+			}
+			assert_noop!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, aye(2_000_002, 3)),
+				Error::<Runtime>::InsufficientFunds
+			);
+
+			assert_eq!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, aye(25_000, 4)),
+				Ok(aye(1_000_000, 0))
+			);
+			for i in 1..=6_u8 {
+				assert_eq!(
+					VtokenVoting::compute_delegator_total_vote(
+						vtoken,
+						aye(250_000 * i as Balance, 4)
+					),
+					Ok(aye(1_000_000, i))
+				);
+			}
+			assert_noop!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, aye(1_500_002, 4)),
+				Error::<Runtime>::InsufficientFunds
+			);
+
+			assert_eq!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, aye(20_000, 5)),
+				Ok(aye(1_000_000, 0))
+			);
+			for i in 1..=6_u8 {
+				assert_eq!(
+					VtokenVoting::compute_delegator_total_vote(
+						vtoken,
+						aye(200_000 * i as Balance, 5)
+					),
+					Ok(aye(1_000_000, i))
+				);
+			}
+			assert_noop!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, aye(1_200_002, 5)),
+				Error::<Runtime>::InsufficientFunds
+			);
+
+			assert_eq!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, aye(16_666, 6)),
+				Ok(aye(999_960, 0))
+			);
+			for i in 1..=6_u8 {
+				assert_eq!(
+					VtokenVoting::compute_delegator_total_vote(
+						vtoken,
+						aye(166_666 * i as Balance, 6)
+					),
+					Ok(aye(999_996, i))
+				);
+			}
+			assert_noop!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, aye(1_000_001, 6)),
+				Error::<Runtime>::InsufficientFunds
+			);
+		});
+	}
+}
+
+#[test]
+fn compute_delegator_total_vote_with_low_value_will_loss() {
+	for &vtoken in TOKENS {
+		new_test_ext().execute_with(|| {
+			assert_eq!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, aye(9, 0)),
+				Ok(aye(0, 0))
+			);
+			assert_eq!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, nay(9, 0)),
+				Ok(nay(0, 0))
+			);
+		});
+	}
+}
+
+#[test]
+fn allocate_delegator_votes_works() {
+	for &vtoken in TOKENS {
+		new_test_ext().execute_with(|| {
+			let poll_index = 3;
+
+			for conviction in 0..=6 {
+				let vote = aye(5e9 as Balance, conviction);
+				let delegator_votes =
+					VtokenVoting::allocate_delegator_votes(vtoken, poll_index, vote);
+				assert_eq!(
+					delegator_votes,
+					Ok(vec![(0, aye(4294967295, conviction)), (1, aye(705032705, conviction))])
+				);
+				assert_eq!(
+					delegator_votes
+						.unwrap()
+						.into_iter()
+						.map(|(_derivative_index, vote)| vote)
+						.fold(aye(0, conviction), |mut acc, vote| {
+							let _ = acc.checked_add(vote);
+							acc
+						},),
+					vote
+				);
+			}
+
+			for conviction in 0..=6 {
+				let vote = aye(3e10 as Balance, conviction);
+				let delegator_votes =
+					VtokenVoting::allocate_delegator_votes(vtoken, poll_index, vote);
+				assert_eq!(
+					delegator_votes,
+					Ok(vec![
+						(0, aye(4294967295, conviction)),
+						(1, aye(4294967295, conviction)),
+						(2, aye(4294967295, conviction)),
+						(3, aye(4294967295, conviction)),
+						(4, aye(4294967295, conviction)),
+						(5, aye(4294967295, conviction)),
+						(10, aye(4230196230, conviction))
+					])
+				);
+				assert_eq!(
+					delegator_votes
+						.unwrap()
+						.into_iter()
+						.map(|(_derivative_index, vote)| vote)
+						.fold(aye(0, conviction), |mut acc, vote| {
+							let _ = acc.checked_add(vote);
+							acc
+						},),
+					vote
+				);
+			}
+		});
+	}
+}
+
+#[test]
+fn tally_convert_works() {
+	assert_eq!(
+		TallyOf::<Runtime>::from_parts(10, 9, 0).account_vote(Conviction::Locked1x),
+		aye(1, 1)
+	);
+	assert_eq!(
+		TallyOf::<Runtime>::from_parts(10, 11, 0).account_vote(Conviction::Locked1x),
+		nay(1, 1)
+	);
+	assert_eq!(
+		TallyOf::<Runtime>::from_parts(10, 10, 0).account_vote(Conviction::Locked1x),
+		aye(0, 1)
+	);
+}
+
+#[test]
+fn set_lock_works() {
+	for &vtoken in TOKENS {
+		new_test_ext().execute_with(|| {
+			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/tests/mod.rs b/pallets/vtoken-voting/src/tests/mod.rs
new file mode 100644
index 000000000..955f282ad
--- /dev/null
+++ b/pallets/vtoken-voting/src/tests/mod.rs
@@ -0,0 +1,23 @@
+// 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 <https://www.gnu.org/licenses/>.
+
+#[cfg(test)]
+mod common_test;
+
+#[cfg(test)]
+mod vbnc_test;
diff --git a/pallets/vtoken-voting/src/tests/vbnc_test.rs b/pallets/vtoken-voting/src/tests/vbnc_test.rs
new file mode 100644
index 000000000..ebf45665e
--- /dev/null
+++ b/pallets/vtoken-voting/src/tests/vbnc_test.rs
@@ -0,0 +1,841 @@
+// 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 <https://www.gnu.org/licenses/>.
+
+// Ensure we're `no_std` when compiling for Wasm.
+use crate::{mock::*, *};
+use bifrost_primitives::currency::VPHA;
+use frame_support::{
+	assert_noop, assert_ok,
+	traits::{
+		fungibles::Inspect,
+		tokens::{Fortitude::Polite, Preservation::Expendable},
+	},
+};
+
+const TOKENS: &[CurrencyId] = if cfg!(feature = "polkadot") { &[VBNC] } else { &[] };
+
+fn aye(amount: Balance, conviction: u8) -> AccountVote<Balance> {
+	let vote = Vote { aye: true, conviction: conviction.try_into().unwrap() };
+	AccountVote::Standard { vote, balance: amount }
+}
+
+fn nay(amount: Balance, conviction: u8) -> AccountVote<Balance> {
+	let vote = Vote { aye: false, conviction: conviction.try_into().unwrap() };
+	AccountVote::Standard { vote, balance: amount }
+}
+
+fn tally(vtoken: CurrencyId, poll_index: u32) -> TallyOf<Runtime> {
+	VtokenVoting::ensure_referendum_ongoing(vtoken, poll_index)
+		.expect("No poll")
+		.tally
+}
+
+fn usable_balance(vtoken: CurrencyId, who: &AccountId) -> Balance {
+	Tokens::reducible_balance(vtoken, who, Expendable, Polite)
+}
+
+#[test]
+fn basic_voting_works() {
+	for &vtoken in TOKENS {
+		new_test_ext().execute_with(|| {
+			let poll_index = 3;
+
+			assert_ok!(VtokenVoting::vote(
+				RuntimeOrigin::signed(ALICE),
+				vtoken,
+				poll_index,
+				aye(2, 5)
+			));
+			assert_eq!(tally(vtoken, poll_index), Tally::from_parts(20, 0, 4));
+			System::assert_last_event(RuntimeEvent::VtokenVoting(Event::Voted {
+				who: ALICE,
+				vtoken,
+				poll_index,
+				token_vote: aye(4, 5),
+				delegator_vote: aye(200, 0),
+			}));
+
+			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));
+			assert_eq!(usable_balance(vtoken, &ALICE), 10);
+		});
+	}
+}
+
+#[test]
+fn voting_balance_gets_locked() {
+	for &vtoken in TOKENS {
+		new_test_ext().execute_with(|| {
+			let poll_index = 3;
+
+			assert_ok!(VtokenVoting::vote(
+				RuntimeOrigin::signed(ALICE),
+				vtoken,
+				poll_index,
+				nay(10, 0)
+			));
+			assert_eq!(tally(vtoken, poll_index), Tally::from_parts(0, 2, 0));
+			assert_eq!(usable_balance(vtoken, &ALICE), 0);
+
+			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));
+			assert_eq!(usable_balance(vtoken, &ALICE), 10);
+		});
+	}
+}
+
+#[test]
+fn successful_but_zero_conviction_vote_balance_can_be_unlocked() {
+	for &vtoken in TOKENS {
+		new_test_ext().execute_with(|| {
+			let poll_index = 3;
+
+			assert_ok!(VtokenVoting::vote(
+				RuntimeOrigin::signed(ALICE),
+				vtoken,
+				poll_index,
+				aye(1, 1)
+			));
+			assert_eq!(usable_balance(vtoken, &ALICE), 9);
+			assert_ok!(VtokenVoting::vote(
+				RuntimeOrigin::signed(ALICE),
+				vtoken,
+				poll_index,
+				aye(3, 1)
+			));
+			assert_eq!(usable_balance(vtoken, &ALICE), 7);
+
+			assert_ok!(VtokenVoting::vote(
+				RuntimeOrigin::signed(BOB),
+				vtoken,
+				poll_index,
+				nay(20, 0)
+			));
+			assert_eq!(usable_balance(vtoken, &BOB), 0);
+
+			assert_ok!(VtokenVoting::set_vote_locking_period(RuntimeOrigin::root(), vtoken, 10));
+			assert_ok!(VtokenVoting::set_referendum_status(
+				RuntimeOrigin::root(),
+				vtoken,
+				poll_index,
+				ReferendumInfoOf::<Runtime>::Completed(3),
+			));
+
+			assert_ok!(VtokenVoting::unlock(RuntimeOrigin::signed(BOB), vtoken, poll_index));
+			assert_eq!(usable_balance(vtoken, &BOB), 20);
+
+			RelaychainDataProvider::set_block_number(13);
+			assert_ok!(VtokenVoting::unlock(RuntimeOrigin::signed(ALICE), vtoken, poll_index));
+			assert_eq!(usable_balance(vtoken, &ALICE), 10);
+		});
+	}
+}
+
+#[test]
+fn unsuccessful_conviction_vote_balance_can_be_unlocked() {
+	for &vtoken in TOKENS {
+		new_test_ext().execute_with(|| {
+			let poll_index = 3;
+			let locking_period = 10;
+			assert_ok!(VtokenVoting::set_vote_locking_period(
+				RuntimeOrigin::root(),
+				vtoken,
+				locking_period,
+			));
+
+			assert_ok!(VtokenVoting::vote(
+				RuntimeOrigin::signed(ALICE),
+				vtoken,
+				poll_index,
+				aye(1, 1)
+			));
+			assert_ok!(VtokenVoting::vote(
+				RuntimeOrigin::signed(BOB),
+				vtoken,
+				poll_index,
+				nay(20, 0)
+			));
+
+			assert_ok!(VtokenVoting::set_referendum_status(
+				RuntimeOrigin::root(),
+				vtoken,
+				poll_index,
+				ReferendumInfoOf::<Runtime>::Completed(3),
+			));
+			RelaychainDataProvider::set_block_number(13);
+			assert_ok!(VtokenVoting::try_remove_vote(&ALICE, vtoken, poll_index, UnvoteScope::Any));
+			assert_ok!(VtokenVoting::update_lock(&ALICE, vtoken));
+			assert_eq!(usable_balance(vtoken, &ALICE), 10);
+		});
+	}
+}
+
+#[test]
+fn ensure_balance_after_unlock() {
+	for &vtoken in TOKENS {
+		new_test_ext().execute_with(|| {
+			let poll_index = 3;
+			let poll_index_2 = 4;
+			let locking_period = 10;
+			assert_ok!(VtokenVoting::set_vote_locking_period(
+				RuntimeOrigin::root(),
+				vtoken,
+				locking_period,
+			));
+
+			assert_ok!(VtokenVoting::vote(
+				RuntimeOrigin::signed(ALICE),
+				vtoken,
+				poll_index,
+				aye(10, 1)
+			));
+			assert_ok!(VtokenVoting::vote(
+				RuntimeOrigin::signed(ALICE),
+				vtoken,
+				poll_index_2,
+				aye(10, 5)
+			));
+
+			assert_ok!(VtokenVoting::set_referendum_status(
+				RuntimeOrigin::root(),
+				vtoken,
+				poll_index,
+				ReferendumInfoOf::<Runtime>::Completed(3),
+			));
+			RelaychainDataProvider::set_block_number(13);
+			assert_ok!(VtokenVoting::unlock(RuntimeOrigin::signed(ALICE), vtoken, poll_index));
+			assert_eq!(usable_balance(vtoken, &ALICE), 0);
+			assert_eq!(Tokens::accounts(&ALICE, vtoken).frozen, 10);
+			assert_eq!(VotingFor::<Runtime>::get(&ALICE).locked_balance(), 10);
+		});
+	}
+}
+
+#[test]
+fn ensure_comprehensive_balance_after_unlock() {
+	for &vtoken in TOKENS {
+		new_test_ext().execute_with(|| {
+			let poll_index = 3;
+			let poll_index_2 = 4;
+			let poll_index_3 = 5;
+			let locking_period = 10;
+			assert_ok!(VtokenVoting::set_vote_locking_period(
+				RuntimeOrigin::root(),
+				vtoken,
+				locking_period,
+			));
+
+			assert_ok!(VtokenVoting::vote(
+				RuntimeOrigin::signed(ALICE),
+				vtoken,
+				poll_index,
+				aye(2, 1)
+			));
+			assert_ok!(VtokenVoting::vote(
+				RuntimeOrigin::signed(ALICE),
+				vtoken,
+				poll_index_2,
+				aye(1, 5)
+			));
+			assert_ok!(VtokenVoting::vote(
+				RuntimeOrigin::signed(ALICE),
+				vtoken,
+				poll_index_3,
+				aye(2, 5)
+			));
+
+			assert_ok!(VtokenVoting::set_referendum_status(
+				RuntimeOrigin::root(),
+				vtoken,
+				poll_index,
+				ReferendumInfoOf::<Runtime>::Completed(3),
+			));
+			RelaychainDataProvider::set_block_number(13);
+			assert_ok!(VtokenVoting::unlock(RuntimeOrigin::signed(ALICE), vtoken, poll_index));
+			assert_eq!(usable_balance(vtoken, &ALICE), 8);
+			assert_eq!(Tokens::accounts(&ALICE, vtoken).frozen, 2);
+			assert_eq!(VotingFor::<Runtime>::get(&ALICE).locked_balance(), 2);
+
+			assert_ok!(VtokenVoting::vote(
+				RuntimeOrigin::signed(ALICE),
+				vtoken,
+				poll_index_2,
+				aye(10, 5)
+			));
+
+			assert_eq!(usable_balance(vtoken, &ALICE), 0);
+			assert_eq!(Tokens::accounts(&ALICE, vtoken).frozen, 10);
+			assert_eq!(VotingFor::<Runtime>::get(&ALICE).locked_balance(), 10);
+		});
+	}
+}
+
+#[test]
+fn successful_conviction_vote_balance_stays_locked_for_correct_time() {
+	for &vtoken in TOKENS {
+		new_test_ext().execute_with(|| {
+			let poll_index = 3;
+			let locking_period = 10;
+			assert_ok!(VtokenVoting::set_vote_locking_period(
+				RuntimeOrigin::root(),
+				vtoken,
+				locking_period,
+			));
+			for i in 1..=5 {
+				assert_ok!(VtokenVoting::vote(
+					RuntimeOrigin::signed(i),
+					vtoken,
+					poll_index,
+					aye(10, i as u8)
+				));
+			}
+			assert_ok!(VtokenVoting::set_referendum_status(
+				RuntimeOrigin::root(),
+				vtoken,
+				poll_index,
+				ReferendumInfoOf::<Runtime>::Completed(3),
+			));
+			RelaychainDataProvider::set_block_number(163);
+			for i in 1..=5 {
+				assert_ok!(VtokenVoting::try_remove_vote(&i, vtoken, poll_index, UnvoteScope::Any));
+			}
+			for i in 1..=5 {
+				assert_ok!(VtokenVoting::update_lock(&i, vtoken));
+				assert_eq!(usable_balance(vtoken, &i), 10 * i as u128);
+			}
+		});
+	}
+}
+
+#[test]
+fn lock_amalgamation_valid_with_multiple_removed_votes() {
+	for &vtoken in TOKENS {
+		new_test_ext().execute_with(|| {
+			assert_ok!(VtokenVoting::vote(RuntimeOrigin::signed(ALICE), vtoken, 0, aye(5, 1)));
+			assert_eq!(
+				ClassLocksFor::<Runtime>::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_eq!(
+				ClassLocksFor::<Runtime>::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_eq!(
+				ClassLocksFor::<Runtime>::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_eq!(
+				ClassLocksFor::<Runtime>::get(&ALICE),
+				BoundedVec::<(CurrencyId, u128), ConstU32<256>>::try_from(vec![(vtoken, 10),])
+					.unwrap()
+			);
+
+			assert_ok!(VtokenVoting::set_referendum_status(
+				RuntimeOrigin::root(),
+				vtoken,
+				0,
+				ReferendumInfoOf::<Runtime>::Completed(1),
+			));
+			assert_ok!(VtokenVoting::set_referendum_status(
+				RuntimeOrigin::root(),
+				vtoken,
+				1,
+				ReferendumInfoOf::<Runtime>::Completed(1),
+			));
+			assert_ok!(VtokenVoting::set_referendum_status(
+				RuntimeOrigin::root(),
+				vtoken,
+				2,
+				ReferendumInfoOf::<Runtime>::Completed(1),
+			));
+
+			let locking_period = 10;
+			assert_ok!(VtokenVoting::set_vote_locking_period(
+				RuntimeOrigin::root(),
+				vtoken,
+				locking_period,
+			));
+			assert_eq!(VoteLockingPeriod::<Runtime>::get(vtoken), Some(10));
+
+			assert_eq!(
+				ClassLocksFor::<Runtime>::get(&ALICE),
+				BoundedVec::<(CurrencyId, u128), ConstU32<256>>::try_from(vec![(vtoken, 10),])
+					.unwrap()
+			);
+
+			RelaychainDataProvider::set_block_number(10);
+			assert_noop!(
+				VtokenVoting::unlock(RuntimeOrigin::signed(ALICE), vtoken, 0),
+				Error::<Runtime>::NoPermissionYet
+			);
+			assert_eq!(VotingFor::<Runtime>::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::<Runtime>::get(&ALICE).locked_balance(), 10);
+			assert_eq!(usable_balance(vtoken, &ALICE), 0);
+			assert_eq!(
+				ClassLocksFor::<Runtime>::get(&ALICE),
+				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), 0);
+			assert_eq!(
+				ClassLocksFor::<Runtime>::get(&ALICE),
+				BoundedVec::<(CurrencyId, u128), ConstU32<256>>::try_from(vec![(vtoken, 10)])
+					.unwrap()
+			);
+
+			RelaychainDataProvider::set_block_number(21);
+			assert_ok!(VtokenVoting::unlock(RuntimeOrigin::signed(ALICE), vtoken, 2));
+			assert_eq!(usable_balance(vtoken, &ALICE), 10);
+			assert_eq!(
+				ClassLocksFor::<Runtime>::get(&ALICE),
+				BoundedVec::<(CurrencyId, u128), ConstU32<256>>::try_from(vec![]).unwrap()
+			);
+		});
+	}
+}
+
+#[test]
+fn removed_votes_when_referendum_killed() {
+	for &vtoken in TOKENS {
+		new_test_ext().execute_with(|| {
+			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::set_referendum_status(
+				RuntimeOrigin::root(),
+				vtoken,
+				0,
+				ReferendumInfoOf::<Runtime>::Completed(1),
+			));
+			assert_ok!(VtokenVoting::set_referendum_status(
+				RuntimeOrigin::root(),
+				vtoken,
+				1,
+				ReferendumInfoOf::<Runtime>::Completed(1),
+			));
+			assert_ok!(VtokenVoting::set_referendum_status(
+				RuntimeOrigin::root(),
+				vtoken,
+				2,
+				ReferendumInfoOf::<Runtime>::Completed(1),
+			));
+
+			assert_ok!(VtokenVoting::kill_referendum(RuntimeOrigin::root(), vtoken, 0));
+			assert_ok!(VtokenVoting::kill_referendum(RuntimeOrigin::root(), vtoken, 1));
+			assert_ok!(VtokenVoting::kill_referendum(RuntimeOrigin::root(), vtoken, 2));
+
+			assert_eq!(
+				ClassLocksFor::<Runtime>::get(&ALICE),
+				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::<Runtime>::get(&ALICE),
+				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::<Runtime>::get(&ALICE),
+				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::<Runtime>::get(&ALICE),
+				BoundedVec::<(CurrencyId, u128), ConstU32<256>>::try_from(vec![]).unwrap()
+			);
+		});
+	}
+}
+
+#[test]
+fn errors_with_vote_works() {
+	for &vtoken in TOKENS {
+		new_test_ext().execute_with(|| {
+			assert_noop!(
+				VtokenVoting::vote(RuntimeOrigin::signed(1), VPHA, 0, aye(10, 0)),
+				Error::<Runtime>::VTokenNotSupport
+			);
+			assert_noop!(
+				VtokenVoting::vote(RuntimeOrigin::signed(1), vtoken, 3, aye(11, 0)),
+				Error::<Runtime>::InsufficientFunds
+			);
+
+			for poll_index in 0..256 {
+				assert_ok!(VtokenVoting::vote(
+					RuntimeOrigin::signed(1),
+					vtoken,
+					poll_index,
+					aye(10, 0)
+				));
+			}
+			assert_noop!(
+				VtokenVoting::vote(RuntimeOrigin::signed(1), vtoken, 256, aye(10, 0)),
+				Error::<Runtime>::MaxVotesReached
+			);
+		});
+	}
+}
+
+#[test]
+fn kill_referendum_works() {
+	for &vtoken in TOKENS {
+		new_test_ext().execute_with(|| {
+			let poll_index = 3;
+
+			assert_ok!(VtokenVoting::vote(
+				RuntimeOrigin::signed(ALICE),
+				vtoken,
+				poll_index,
+				aye(5, 1)
+			));
+			assert_ok!(VtokenVoting::set_referendum_status(
+				RuntimeOrigin::root(),
+				vtoken,
+				poll_index,
+				ReferendumInfoOf::<Runtime>::Completed(1),
+			));
+			assert_ok!(VtokenVoting::kill_referendum(RuntimeOrigin::root(), vtoken, poll_index));
+			System::assert_last_event(RuntimeEvent::VtokenVoting(Event::ReferendumKilled {
+				vtoken,
+				poll_index,
+			}));
+		});
+	}
+}
+
+#[test]
+fn kill_referendum_with_origin_signed_fails() {
+	for &vtoken in TOKENS {
+		new_test_ext().execute_with(|| {
+			let poll_index = 3;
+
+			assert_ok!(VtokenVoting::vote(
+				RuntimeOrigin::signed(ALICE),
+				vtoken,
+				poll_index,
+				aye(5, 1)
+			));
+			assert_ok!(VtokenVoting::set_referendum_status(
+				RuntimeOrigin::root(),
+				vtoken,
+				poll_index,
+				ReferendumInfoOf::<Runtime>::Completed(1),
+			));
+			assert_noop!(
+				VtokenVoting::kill_referendum(RuntimeOrigin::signed(ALICE), vtoken, poll_index),
+				DispatchError::BadOrigin
+			);
+		});
+	}
+}
+
+#[test]
+fn compute_delegator_total_vote_works() {
+	for &vtoken in TOKENS {
+		new_test_ext().execute_with(|| {
+			assert_eq!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, aye(10, 0)),
+				Ok(aye(10, 0))
+			);
+			assert_eq!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, aye(2, 1)),
+				Ok(aye(20, 0))
+			);
+			assert_eq!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, aye(2, 2)),
+				Ok(aye(40, 0))
+			);
+			assert_eq!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, aye(2, 3)),
+				Ok(aye(60, 0))
+			);
+			assert_eq!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, aye(2, 4)),
+				Ok(aye(80, 0))
+			);
+			assert_eq!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, aye(2, 5)),
+				Ok(aye(100, 0))
+			);
+			assert_eq!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, aye(2, 6)),
+				Ok(aye(120, 0))
+			);
+
+			assert_eq!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, nay(10, 0)),
+				Ok(nay(10, 0))
+			);
+			assert_eq!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, nay(2, 1)),
+				Ok(nay(20, 0))
+			);
+			assert_eq!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, nay(2, 2)),
+				Ok(nay(40, 0))
+			);
+			assert_eq!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, nay(2, 3)),
+				Ok(nay(60, 0))
+			);
+			assert_eq!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, nay(2, 4)),
+				Ok(nay(80, 0))
+			);
+			assert_eq!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, nay(2, 5)),
+				Ok(nay(100, 0))
+			);
+			assert_eq!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, nay(2, 6)),
+				Ok(nay(120, 0))
+			);
+
+			SimpleVTokenSupplyProvider::set_token_supply(10_000_000);
+			assert_eq!(VtokenVoting::vote_cap(vtoken), Ok(1_000_000));
+			assert_eq!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, aye(1_000_000, 0)),
+				Ok(aye(1_000_000, 0))
+			);
+			for i in 1..=6_u8 {
+				assert_eq!(
+					VtokenVoting::compute_delegator_total_vote(
+						vtoken,
+						aye(10_000_000 * i as Balance, 0)
+					),
+					Ok(aye(1_000_000, i))
+				);
+			}
+
+			assert_eq!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, aye(100_000, 1)),
+				Ok(aye(1_000_000, 0))
+			);
+			for i in 1..=6_u8 {
+				assert_eq!(
+					VtokenVoting::compute_delegator_total_vote(
+						vtoken,
+						aye(1_000_000 * i as Balance, 1)
+					),
+					Ok(aye(1_000_000, i))
+				);
+			}
+			assert_noop!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, aye(6_000_006, 1)),
+				Error::<Runtime>::InsufficientFunds
+			);
+
+			assert_eq!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, aye(50_000, 2)),
+				Ok(aye(1_000_000, 0))
+			);
+			for i in 1..=6_u8 {
+				assert_eq!(
+					VtokenVoting::compute_delegator_total_vote(
+						vtoken,
+						aye(500_000 * i as Balance, 2)
+					),
+					Ok(aye(1_000_000, i))
+				);
+			}
+			assert_noop!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, aye(3_000_003, 2)),
+				Error::<Runtime>::InsufficientFunds
+			);
+
+			assert_eq!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, aye(33_333, 3)),
+				Ok(aye(999_990, 0))
+			);
+			for i in 1..=6_u8 {
+				assert_eq!(
+					VtokenVoting::compute_delegator_total_vote(
+						vtoken,
+						aye(333_333 * i as Balance, 3)
+					),
+					Ok(aye(999_999, i))
+				);
+			}
+			assert_noop!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, aye(2_000_002, 3)),
+				Error::<Runtime>::InsufficientFunds
+			);
+
+			assert_eq!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, aye(25_000, 4)),
+				Ok(aye(1_000_000, 0))
+			);
+			for i in 1..=6_u8 {
+				assert_eq!(
+					VtokenVoting::compute_delegator_total_vote(
+						vtoken,
+						aye(250_000 * i as Balance, 4)
+					),
+					Ok(aye(1_000_000, i))
+				);
+			}
+			assert_noop!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, aye(1_500_002, 4)),
+				Error::<Runtime>::InsufficientFunds
+			);
+
+			assert_eq!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, aye(20_000, 5)),
+				Ok(aye(1_000_000, 0))
+			);
+			for i in 1..=6_u8 {
+				assert_eq!(
+					VtokenVoting::compute_delegator_total_vote(
+						vtoken,
+						aye(200_000 * i as Balance, 5)
+					),
+					Ok(aye(1_000_000, i))
+				);
+			}
+			assert_noop!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, aye(1_200_002, 5)),
+				Error::<Runtime>::InsufficientFunds
+			);
+
+			assert_eq!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, aye(16_666, 6)),
+				Ok(aye(999_960, 0))
+			);
+			for i in 1..=6_u8 {
+				assert_eq!(
+					VtokenVoting::compute_delegator_total_vote(
+						vtoken,
+						aye(166_666 * i as Balance, 6)
+					),
+					Ok(aye(999_996, i))
+				);
+			}
+			assert_noop!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, aye(1_000_001, 6)),
+				Error::<Runtime>::InsufficientFunds
+			);
+		});
+	}
+}
+
+#[test]
+fn compute_delegator_total_vote_with_low_value_will_loss() {
+	for &vtoken in TOKENS {
+		new_test_ext().execute_with(|| {
+			assert_eq!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, aye(9, 0)),
+				Ok(aye(0, 0))
+			);
+			assert_eq!(
+				VtokenVoting::compute_delegator_total_vote(vtoken, nay(9, 0)),
+				Ok(nay(0, 0))
+			);
+		});
+	}
+}
+
+#[test]
+fn allocate_delegator_votes_works() {
+	for &vtoken in TOKENS {
+		new_test_ext().execute_with(|| {
+			let poll_index = 3;
+
+			for conviction in 0..=6 {
+				let vote = aye(5e9 as Balance, conviction);
+				let delegator_votes =
+					VtokenVoting::allocate_delegator_votes(vtoken, poll_index, vote);
+				assert_eq!(
+					delegator_votes,
+					Ok(vec![(0, aye(4294967295, conviction)), (1, aye(705032705, conviction))])
+				);
+				assert_eq!(
+					delegator_votes
+						.unwrap()
+						.into_iter()
+						.map(|(_derivative_index, vote)| vote)
+						.fold(aye(0, conviction), |mut acc, vote| {
+							let _ = acc.checked_add(vote);
+							acc
+						},),
+					vote
+				);
+			}
+
+			for conviction in 0..=6 {
+				let vote = aye(3e10 as Balance, conviction);
+				let delegator_votes =
+					VtokenVoting::allocate_delegator_votes(vtoken, poll_index, vote);
+				assert_eq!(
+					delegator_votes,
+					Ok(vec![
+						(0, aye(4294967295, conviction)),
+						(1, aye(4294967295, conviction)),
+						(2, aye(4294967295, conviction)),
+						(3, aye(4294967295, conviction)),
+						(4, aye(4294967295, conviction)),
+						(5, aye(4294967295, conviction)),
+						(10, aye(4230196230, conviction))
+					])
+				);
+				assert_eq!(
+					delegator_votes
+						.unwrap()
+						.into_iter()
+						.map(|(_derivative_index, vote)| vote)
+						.fold(aye(0, conviction), |mut acc, vote| {
+							let _ = acc.checked_add(vote);
+							acc
+						},),
+					vote
+				);
+			}
+		});
+	}
+}
diff --git a/pallets/vtoken-voting/src/traits.rs b/pallets/vtoken-voting/src/traits.rs
new file mode 100644
index 000000000..30fe18202
--- /dev/null
+++ b/pallets/vtoken-voting/src/traits.rs
@@ -0,0 +1,142 @@
+// 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 <https://www.gnu.org/licenses/>.
+
+use crate::{AccountVote, PollClass, PollIndex, *};
+use bifrost_primitives::DerivativeIndex;
+use sp_std::vec::Vec;
+
+/// Abstraction over a voting agent for a certain parachain.
+///
+/// This trait defines the operations a voting agent should implement for handling votes and
+/// delegator-related actions within a certain parachain's voting system.
+pub trait VotingAgent<T: Config> {
+	/// Retrieves the voting token (`vtoken`) associated with the agent.
+	///
+	/// This function should return the currency ID representing the token used for voting.
+	fn vtoken(&self) -> CurrencyIdOf<T>;
+
+	/// Retrieves the location of the agent.
+	///
+	/// This function returns the location associated with the agent, which could be used to
+	/// identify the origin or context within the parachain system.
+	fn location(&self) -> Location;
+
+	/// Delegate a vote on behalf of a user.
+	///
+	/// - `who`: The account for which the vote is being delegated.
+	/// - `vtoken`: The token used for voting.
+	/// - `poll_index`: The index of the poll on which the vote is being cast.
+	/// - `submitted`: A flag indicating whether the vote was already submitted.
+	/// - `new_delegator_votes`: A vector of delegator votes, represented by the index of the
+	///   derivative and the account's vote.
+	/// - `maybe_old_vote`: An optional tuple representing the old vote and its associated balance,
+	///   in case an old vote exists.
+	///
+	/// This function handles the delegation of votes for the specified account and updates the
+	/// voting state accordingly. It returns a `DispatchResult` to indicate success or failure.
+	fn delegate_vote(
+		&self,
+		who: AccountIdOf<T>,
+		vtoken: CurrencyIdOf<T>,
+		poll_index: PollIndex,
+		submitted: bool,
+		new_delegator_votes: Vec<(DerivativeIndex, AccountVote<BalanceOf<T>>)>,
+		maybe_old_vote: Option<(AccountVote<BalanceOf<T>>, BalanceOf<T>)>,
+	) -> DispatchResult;
+
+	/// Encode the call data for voting.
+	///
+	/// - `new_delegator_votes`: A vector of new delegator votes to be encoded.
+	/// - `poll_index`: The index of the poll.
+	/// - `derivative_index`: The index of the derivative (delegator) involved in the voting
+	///   process.
+	///
+	/// This function encodes the call for a vote delegation action, returning the byte-encoded
+	/// representation of the call data. In case of errors during encoding, an `Error<T>` is
+	/// returned.
+	fn vote_call_encode(
+		&self,
+		new_delegator_votes: Vec<(DerivativeIndex, AccountVote<BalanceOf<T>>)>,
+		poll_index: PollIndex,
+		derivative_index: DerivativeIndex,
+	) -> Result<Vec<u8>, Error<T>>;
+
+	/// Remove a delegator's vote.
+	///
+	/// - `vtoken`: The token associated with the vote.
+	/// - `poll_index`: The index of the poll from which the vote is being removed.
+	/// - `class`: The class/type of the poll.
+	/// - `derivative_index`: The index of the delegator's derivative whose vote is being removed.
+	///
+	/// This function handles the removal of a delegator's vote for the specified poll and class,
+	/// returning a `DispatchResult` to indicate success or failure.
+	fn delegate_remove_delegator_vote(
+		&self,
+		vtoken: CurrencyIdOf<T>,
+		poll_index: PollIndex,
+		class: PollClass,
+		derivative_index: DerivativeIndex,
+	) -> DispatchResult;
+
+	/// Encode the call data for removing a delegator's vote.
+	///
+	/// - `class`: The class/type of the poll.
+	/// - `poll_index`: The index of the poll from which the vote is being removed.
+	/// - `derivative_index`: The index of the delegator's derivative involved in the vote removal.
+	///
+	/// This function encodes the call for removing a delegator's vote, returning the byte-encoded
+	/// representation of the call data. In case of errors during encoding, an `Error<T>` is
+	/// returned.
+	fn remove_delegator_vote_call_encode(
+		&self,
+		class: PollClass,
+		poll_index: PollIndex,
+		derivative_index: DerivativeIndex,
+	) -> Result<Vec<u8>, Error<T>>;
+}
+
+/// Trait defining calls related to conviction voting mechanisms.
+pub trait ConvictionVotingCall<T: Config> {
+	/// Casts a vote in a poll.
+	///
+	/// - `poll_index`: The index of the poll where the vote is being cast.
+	/// - `vote`: The vote being cast, which includes the voter's balance and conviction.
+	fn vote(poll_index: PollIndex, vote: AccountVote<BalanceOf<T>>) -> Self;
+
+	/// Removes a vote from a poll.
+	///
+	/// - `class`: Optionally specify the class of the poll (if applicable).
+	/// - `poll_index`: The index of the poll from which the vote is being removed.
+	fn remove_vote(class: Option<PollClass>, poll_index: PollIndex) -> Self;
+}
+
+/// Trait defining utility calls for handling batch or derivative actions.
+pub trait UtilityCall<Call> {
+	/// Executes a call as a derivative of another account.
+	///
+	/// - `derivative_index`: The index representing a specific derivative account (usually for
+	///   staking or delegation purposes).
+	/// - `call`: The call that will be executed by the derivative account.
+	fn as_derivative(derivative_index: DerivativeIndex, call: Call) -> Call;
+
+	/// Executes a batch of calls where all must succeed or none will be executed.
+	///
+	/// - `calls`: A vector of calls that will be executed in batch. If any call fails, none of the
+	///   calls will be applied.
+	fn batch_all(calls: Vec<Call>) -> Call;
+}
diff --git a/pallets/vtoken-voting/src/vote.rs b/pallets/vtoken-voting/src/vote.rs
index a9a9b1b86..f34984d7c 100644
--- a/pallets/vtoken-voting/src/vote.rs
+++ b/pallets/vtoken-voting/src/vote.rs
@@ -357,8 +357,8 @@ where
 #[derive(Encode, Decode, Clone, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
 #[scale_info(skip_type_params(MaxVotes))]
 #[codec(mel_bound(
-Balance: MaxEncodedLen, AccountId: MaxEncodedLen, BlockNumber: MaxEncodedLen,
-PollIndex: MaxEncodedLen,
+	Balance: MaxEncodedLen, AccountId: MaxEncodedLen, BlockNumber: MaxEncodedLen,
+	PollIndex: MaxEncodedLen,
 ))]
 pub enum Voting<Balance, AccountId, BlockNumber, PollIndex, MaxVotes>
 where
diff --git a/primitives/src/traits.rs b/primitives/src/traits.rs
index c6cf28de0..1d9f630bc 100644
--- a/primitives/src/traits.rs
+++ b/primitives/src/traits.rs
@@ -387,7 +387,7 @@ where
 	}
 }
 
-pub trait DerivativeAccountHandler<CurrencyId, Balance> {
+pub trait DerivativeAccountHandler<CurrencyId, Balance, AccountId> {
 	fn check_derivative_index_exists(token: CurrencyId, derivative_index: DerivativeIndex) -> bool;
 
 	fn get_multilocation(
@@ -395,6 +395,8 @@ pub trait DerivativeAccountHandler<CurrencyId, Balance> {
 		derivative_index: DerivativeIndex,
 	) -> Option<xcm::v3::MultiLocation>;
 
+	fn get_account_id(token: CurrencyId, derivative_index: DerivativeIndex) -> Option<AccountId>;
+
 	fn get_stake_info(
 		token: CurrencyId,
 		derivative_index: DerivativeIndex,
diff --git a/runtime/bifrost-kusama/src/lib.rs b/runtime/bifrost-kusama/src/lib.rs
index 2a71076ee..19d700739 100644
--- a/runtime/bifrost-kusama/src/lib.rs
+++ b/runtime/bifrost-kusama/src/lib.rs
@@ -1349,6 +1349,7 @@ impl bifrost_vtoken_voting::Config for Runtime {
 	type QueryTimeout = QueryTimeout;
 	type ReferendumCheckInterval = ReferendumCheckInterval;
 	type WeightInfo = weights::bifrost_vtoken_voting::BifrostWeight<Runtime>;
+	type PalletsOrigin = OriginCaller;
 }
 
 // Bifrost modules end
diff --git a/runtime/bifrost-polkadot/src/lib.rs b/runtime/bifrost-polkadot/src/lib.rs
index f63de4618..ee97874bf 100644
--- a/runtime/bifrost-polkadot/src/lib.rs
+++ b/runtime/bifrost-polkadot/src/lib.rs
@@ -1261,6 +1261,7 @@ impl bifrost_vtoken_voting::Config for Runtime {
 	type QueryTimeout = QueryTimeout;
 	type ReferendumCheckInterval = ReferendumCheckInterval;
 	type WeightInfo = weights::bifrost_vtoken_voting::BifrostWeight<Runtime>;
+	type PalletsOrigin = OriginCaller;
 }
 
 // Bifrost modules end

From 8ba3c31882b77437dce2e3f1adec898ddbb23fec Mon Sep 17 00:00:00 2001
From: NingBo Wang <2536935847@qq.com>
Date: Tue, 8 Oct 2024 13:42:32 +0800
Subject: [PATCH 14/31] Fix try-runtime (#1451)

---
 pallets/asset-registry/src/migrations/v1.rs | 17 ++++++++++++++---
 pallets/flexible-fee/src/lib.rs             |  4 ++++
 runtime/bifrost-kusama/src/lib.rs           |  1 +
 runtime/bifrost-polkadot/src/lib.rs         |  1 +
 4 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/pallets/asset-registry/src/migrations/v1.rs b/pallets/asset-registry/src/migrations/v1.rs
index 99a7481a2..b74b62711 100644
--- a/pallets/asset-registry/src/migrations/v1.rs
+++ b/pallets/asset-registry/src/migrations/v1.rs
@@ -27,10 +27,11 @@ pub struct MigrateToV1<T>(sp_std::marker::PhantomData<T>);
 impl<T: Config> OnRuntimeUpgrade for MigrateToV1<T> {
 	fn on_runtime_upgrade() -> frame_support::weights::Weight {
 		// Check the storage version
-		let onchain_version = Pallet::<T>::on_chain_storage_version();
+		let in_code_version = Pallet::<T>::in_code_storage_version();
+		let on_chain_version = Pallet::<T>::on_chain_storage_version();
 		// Transform storage values
 		// We transform the storage values from the old into the new format.
-		if onchain_version < 1 {
+		if on_chain_version == 0 && in_code_version == 1 {
 			let mut count = 0;
 
 			log::info!(target: LOG_TARGET, "Start to migrate RegisterWhiteList storage...");
@@ -59,7 +60,7 @@ impl<T: Config> OnRuntimeUpgrade for MigrateToV1<T> {
 			}
 
 			// Update the storage version
-			StorageVersion::new(1).put::<Pallet<T>>();
+			in_code_version.put::<Pallet<T>>();
 
 			// Return the consumed weight
 			Weight::from(T::DbWeight::get().reads_writes(count as u64 + 1, count as u64 + 1))
@@ -71,6 +72,8 @@ impl<T: Config> OnRuntimeUpgrade for MigrateToV1<T> {
 
 	#[cfg(feature = "try-runtime")]
 	fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
+		ensure!(Pallet::<T>::on_chain_storage_version() == 0, "must upgrade linearly");
+		ensure!(Pallet::<T>::in_code_storage_version() == 1, "must upgrade linearly");
 		let currency_id_to_locations_count = CurrencyIdToLocations::<T>::iter().count();
 		log::info!(target: LOG_TARGET, "CurrencyIdToLocations pre-migrate storage count: {:?}", currency_id_to_locations_count);
 
@@ -85,6 +88,14 @@ impl<T: Config> OnRuntimeUpgrade for MigrateToV1<T> {
 
 	#[cfg(feature = "try-runtime")]
 	fn post_upgrade(cnt: Vec<u8>) -> Result<(), TryRuntimeError> {
+		let in_code_version = Pallet::<T>::in_code_storage_version();
+		let on_chain_version = Pallet::<T>::on_chain_storage_version();
+		ensure!(in_code_version == 1, "must_upgrade");
+		ensure!(
+			in_code_version == on_chain_version,
+			"after migration, the in_code_version and on_chain_version should be the same"
+		);
+
 		let (old_currency_id_to_locations_count, old_location_to_currency_ids_count): (u64, u64) =
 			Decode::decode(&mut cnt.as_slice()).expect(
 				"the state parameter should be something that was generated by pre_upgrade",
diff --git a/pallets/flexible-fee/src/lib.rs b/pallets/flexible-fee/src/lib.rs
index 2b585be1f..48a065209 100644
--- a/pallets/flexible-fee/src/lib.rs
+++ b/pallets/flexible-fee/src/lib.rs
@@ -158,6 +158,9 @@ pub mod pallet {
 		},
 	}
 
+	/// The current storage version, we set to 2 our new version.
+	const STORAGE_VERSION: StorageVersion = StorageVersion::new(2);
+
 	/// Universal fee currency order list for all users
 	#[pallet::storage]
 	pub type UniversalFeeCurrencyOrderList<T: Config> =
@@ -180,6 +183,7 @@ pub mod pallet {
 	>;
 
 	#[pallet::pallet]
+	#[pallet::storage_version(STORAGE_VERSION)]
 	pub struct Pallet<T>(_);
 
 	#[pallet::error]
diff --git a/runtime/bifrost-kusama/src/lib.rs b/runtime/bifrost-kusama/src/lib.rs
index 19d700739..47a399465 100644
--- a/runtime/bifrost-kusama/src/lib.rs
+++ b/runtime/bifrost-kusama/src/lib.rs
@@ -1918,6 +1918,7 @@ pub mod migrations {
 		// permanent migration, do not remove
 		pallet_xcm::migration::MigrateToLatestXcmVersion<Runtime>,
 		bifrost_cross_in_out::migrations::v3::MigrateToV2<Runtime>,
+		bifrost_asset_registry::migrations::v1::MigrateToV1<Runtime>,
 		SystemMakerClearPalletId<Runtime>,
 		frame_support::migrations::RemovePallet<SystemMakerName, RocksDbWeight>,
 	);
diff --git a/runtime/bifrost-polkadot/src/lib.rs b/runtime/bifrost-polkadot/src/lib.rs
index ee97874bf..fcbc36dbc 100644
--- a/runtime/bifrost-polkadot/src/lib.rs
+++ b/runtime/bifrost-polkadot/src/lib.rs
@@ -1832,6 +1832,7 @@ pub mod migrations {
 		// permanent migration, do not remove
 		pallet_xcm::migration::MigrateToLatestXcmVersion<Runtime>,
 		bifrost_cross_in_out::migrations::v3::MigrateToV2<Runtime>,
+		bifrost_asset_registry::migrations::v1::MigrateToV1<Runtime>,
 		frame_support::migrations::RemovePallet<SystemMakerName, RocksDbWeight>,
 	);
 }

From 81f5c6dc5200a34012b517220ea1eeaf4af9008f Mon Sep 17 00:00:00 2001
From: NingBo Wang <2536935847@qq.com>
Date: Thu, 10 Oct 2024 23:09:42 +0800
Subject: [PATCH 15/31] Slpx add evm create (#1454)

* Fix try-runtime

* Slpx add evm create order
---
 pallets/slp/src/tests/phala_tests.rs |  37 +++++++++
 pallets/slpx/src/lib.rs              | 118 +++++++++++++++++++++++----
 pallets/slpx/src/migration.rs        |  95 ++++++++++++++++++++-
 pallets/slpx/src/tests.rs            |   2 +-
 pallets/slpx/src/types.rs            |   2 +
 primitives/src/xcm.rs                |   7 ++
 runtime/bifrost-kusama/src/lib.rs    |   1 +
 runtime/bifrost-polkadot/src/lib.rs  |   1 +
 8 files changed, 246 insertions(+), 17 deletions(-)

diff --git a/pallets/slp/src/tests/phala_tests.rs b/pallets/slp/src/tests/phala_tests.rs
index f5a930017..1f8589918 100644
--- a/pallets/slp/src/tests/phala_tests.rs
+++ b/pallets/slp/src/tests/phala_tests.rs
@@ -28,6 +28,7 @@ use crate::{
 use bifrost_primitives::currency::{PHA, VPHA};
 use frame_support::{assert_noop, assert_ok, PalletId};
 use polkadot_parachain_primitives::primitives::Sibling;
+use sp_core::crypto::Ss58Codec;
 use sp_runtime::traits::AccountIdConversion;
 
 // parents 0 means vault, parents 1 means stake_pool
@@ -1460,3 +1461,39 @@ fn phala_convert_asset_works() {
 		);
 	});
 }
+
+#[test]
+fn generate_derivative_account() {
+	ExtBuilder::default().build().execute_with(|| {
+		// PublicKey: 0x70617261d1070000000000000000000000000000000000000000000000000000
+		// AccountId(42): 5Ec4AhPV91i9yNuiWuNunPf6AQCYDhFTTA4G5QCbtqYApH9E
+		let sovereign_account = <ParaId as AccountIdConversion<AccountId>>::into_account_truncating(
+			&ParaId::from(2001),
+		);
+		println!("sovereign_account: {:?}", sovereign_account);
+		// PublicKey: 0x5a53736d8e96f1c007cf0d630acf5209b20611617af23ce924c8e25328eb5d28
+		// AccountId(42): 5E78xTBiaN3nAGYtcNnqTJQJqYAkSDGggKqaDfpNsKyPpbcb
+		let sovereign_account_derivative_0 =
+			Utility::derivative_account_id(sovereign_account.clone(), 0);
+		assert_eq!(
+			sovereign_account_derivative_0,
+			AccountId::from_ss58check("5E78xTBiaN3nAGYtcNnqTJQJqYAkSDGggKqaDfpNsKyPpbcb").unwrap()
+		);
+		// PublicKey: 0xf1c5ca0368e7a567945a59aaea92b9be1e0794fe5e077d017462b7ce8fc1ed7c
+		// AccountId(42): 5HXi9pzWnTQzk7VKzY6VQn92KfWCcA5NbSm53uKHrYU1VsjP
+		let sovereign_account_derivative_1 =
+			Utility::derivative_account_id(sovereign_account.clone(), 1);
+		assert_eq!(
+			sovereign_account_derivative_1,
+			AccountId::from_ss58check("5HXi9pzWnTQzk7VKzY6VQn92KfWCcA5NbSm53uKHrYU1VsjP").unwrap()
+		);
+		// PublicKey: 0x1e365411cfd0b0f78466be433a2ec5f7d545c5e28cb2e9a31ce97d4a28447dfc
+		// AccountId(42): 5CkKS3YMx64TguUYrMERc5Bn6Mn2aKMUkcozUFREQDgHS3Tv
+		let sovereign_account_derivative_2 =
+			Utility::derivative_account_id(sovereign_account.clone(), 2);
+		assert_eq!(
+			sovereign_account_derivative_2,
+			AccountId::from_ss58check("5CkKS3YMx64TguUYrMERc5Bn6Mn2aKMUkcozUFREQDgHS3Tv").unwrap()
+		);
+	})
+}
diff --git a/pallets/slpx/src/lib.rs b/pallets/slpx/src/lib.rs
index a51e96c89..407832e2a 100644
--- a/pallets/slpx/src/lib.rs
+++ b/pallets/slpx/src/lib.rs
@@ -25,9 +25,9 @@ use crate::types::{
 use bifrost_asset_registry::AssetMetadata;
 use bifrost_primitives::{
 	currency::{BNC, MOVR, VFIL},
-	AstarChainId, Balance, BifrostKusamaChainId, CurrencyId, CurrencyIdMapping, HydrationChainId,
-	InterlayChainId, MantaChainId, RedeemType, SlpxOperator, TokenInfo, VtokenMintingInterface,
-	GLMR,
+	AstarChainId, AstarEvmChainId, Balance, BifrostKusamaChainId, CurrencyId, CurrencyIdMapping,
+	HydrationChainId, InterlayChainId, MantaChainId, MoonbeamEvmChainId, MoonriverEvmChainId,
+	RedeemType, SlpxOperator, TokenInfo, VtokenMintingInterface, GLMR,
 };
 use cumulus_primitives_core::ParaId;
 use ethereum::TransactionAction;
@@ -82,7 +82,7 @@ pub mod pallet {
 	};
 	use frame_system::ensure_root;
 
-	const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);
+	const STORAGE_VERSION: StorageVersion = StorageVersion::new(2);
 
 	#[pallet::pallet]
 	#[pallet::storage_version(STORAGE_VERSION)]
@@ -351,6 +351,8 @@ pub mod pallet {
 
 			Self::do_create_order(
 				source_chain_caller,
+				Default::default(),
+				None,
 				bifrost_chain_caller,
 				currency_id,
 				Default::default(),
@@ -390,6 +392,8 @@ pub mod pallet {
 
 			Self::do_create_order(
 				source_chain_caller,
+				Default::default(),
+				None,
 				bifrost_chain_caller,
 				vtoken_id,
 				Default::default(),
@@ -627,6 +631,8 @@ pub mod pallet {
 			ensure_root(origin)?;
 			Self::do_create_order(
 				source_chain_caller,
+				Default::default(),
+				None,
 				bifrost_chain_caller,
 				currency_id,
 				Default::default(),
@@ -658,6 +664,8 @@ pub mod pallet {
 
 			Self::do_create_order(
 				source_chain_caller,
+				Default::default(),
+				None,
 				bifrost_chain_caller,
 				currency_id,
 				Default::default(),
@@ -667,6 +675,54 @@ pub mod pallet {
 			)
 		}
 
+		/// EVM create order
+		/// Parameters:
+		/// - `source_chain_caller`: The caller of the source chain
+		/// - `source_chain_id`: The source chain id
+		/// - `source_chain_block_number`: The source chain block number
+		/// - `currency_id`: The currency id of the token
+		/// - `currency_amount`: The currency amount of the token
+		/// - `send_to`: The target chain to transfer the token to
+		/// - `remark`: The remark of the order
+		/// - `channel_id`: The channel id of the order
+		#[pallet::call_index(14)]
+		#[pallet::weight(<T as Config>::WeightInfo::mint())]
+		pub fn evm_create_order(
+			origin: OriginFor<T>,
+			source_chain_caller: H160,
+			source_chain_id: u64,
+			source_chain_block_number: u128,
+			currency_id: CurrencyId,
+			currency_amount: BalanceOf<T>,
+			send_to: TargetChain<T::AccountId>,
+			remark: BoundedVec<u8, ConstU32<32>>,
+			channel_id: u32,
+		) -> DispatchResultWithPostInfo {
+			let bifrost_chain_caller = ensure_signed(origin)?;
+
+			let support_chain =
+				Self::match_source_chain_id(source_chain_id).ok_or(Error::<T>::Unsupported)?;
+
+			ensure!(
+				WhitelistAccountId::<T>::get(support_chain).contains(&bifrost_chain_caller),
+				Error::<T>::AccountNotFound
+			);
+
+			let source_chain_caller = OrderCaller::Evm(source_chain_caller);
+
+			Self::do_create_order(
+				source_chain_caller,
+				source_chain_id,
+				Some(source_chain_block_number),
+				bifrost_chain_caller,
+				currency_id,
+				currency_amount,
+				remark,
+				channel_id,
+				send_to,
+			)
+		}
+
 		// TODO: Substrate user create order
 		// #[pallet::call_index(14)]
 		// #[pallet::weight(<T as Config>::WeightInfo::mint())]
@@ -696,6 +752,18 @@ pub mod pallet {
 }
 
 impl<T: Config> Pallet<T> {
+	fn match_source_chain_id(source_chain_id: u64) -> Option<SupportChain> {
+		if source_chain_id == AstarEvmChainId::get() {
+			Some(SupportChain::Astar)
+		} else if source_chain_id == MoonriverEvmChainId::get() ||
+			source_chain_id == MoonbeamEvmChainId::get()
+		{
+			Some(SupportChain::Moonbeam)
+		} else {
+			None
+		}
+	}
+
 	/// According to currency_id, return the order type
 	fn order_type(currency_id: CurrencyId) -> Result<OrderType, Error<T>> {
 		match currency_id {
@@ -753,6 +821,8 @@ impl<T: Config> Pallet<T> {
 
 	fn do_create_order(
 		source_chain_caller: OrderCaller<T::AccountId>,
+		source_chain_id: u64,
+		source_chain_block_number: Option<u128>,
 		bifrost_chain_caller: T::AccountId,
 		currency_id: CurrencyId,
 		currency_amount: BalanceOf<T>,
@@ -769,6 +839,8 @@ impl<T: Config> Pallet<T> {
 			currency_amount,
 			remark,
 			source_chain_caller,
+			source_chain_id,
+			source_chain_block_number,
 			bifrost_chain_caller,
 			derivative_account,
 			target_chain,
@@ -897,9 +969,9 @@ impl<T: Config> Pallet<T> {
 	/// Charge an execution fee
 	fn charge_execution_fee(
 		currency_id: CurrencyIdOf<T>,
+		currency_amount: BalanceOf<T>,
 		evm_caller_account_id: &AccountIdOf<T>,
 	) -> Result<BalanceOf<T>, DispatchError> {
-		let free_balance = T::MultiCurrency::free_balance(currency_id, evm_caller_account_id);
 		let execution_fee = ExecutionFee::<T>::get(currency_id)
 			.unwrap_or_else(|| Self::get_default_fee(currency_id));
 
@@ -910,8 +982,9 @@ impl<T: Config> Pallet<T> {
 			execution_fee,
 		)?;
 
-		let balance_exclude_fee =
-			free_balance.checked_sub(&execution_fee).ok_or(Error::<T>::FreeBalanceTooLow)?;
+		let balance_exclude_fee = currency_amount
+			.checked_sub(&execution_fee)
+			.ok_or(Error::<T>::FreeBalanceTooLow)?;
 		Ok(balance_exclude_fee)
 	}
 
@@ -1016,11 +1089,24 @@ impl<T: Config> Pallet<T> {
 	pub fn handle_order(
 		order: &Order<AccountIdOf<T>, CurrencyIdOf<T>, BalanceOf<T>, BlockNumberFor<T>>,
 	) -> DispatchResult {
-		let currency_amount =
-			Self::charge_execution_fee(order.currency_id, &order.derivative_account)
-				.map_err(|_| Error::<T>::ErrorChargeFee)?;
+		let currency_amount = Self::charge_execution_fee(
+			order.currency_id,
+			order.currency_amount,
+			&order.derivative_account,
+		)
+		.map_err(|_| Error::<T>::ErrorChargeFee)?;
 		match order.order_type {
 			OrderType::Mint => {
+				let vtoken_id =
+					order.currency_id.to_vtoken().map_err(|_| Error::<T>::ErrorConvertVtoken)?;
+
+				let vtoken_amount = T::VtokenMintingInterface::token_to_vtoken(
+					order.currency_id,
+					vtoken_id,
+					currency_amount,
+				)
+				.map_err(|_| Error::<T>::ErrorVtokenMiting)?;
+
 				T::VtokenMintingInterface::mint(
 					order.derivative_account.clone(),
 					order.currency_id,
@@ -1029,10 +1115,6 @@ impl<T: Config> Pallet<T> {
 					Some(order.channel_id),
 				)
 				.map_err(|_| Error::<T>::ErrorVtokenMiting)?;
-				let vtoken_id =
-					order.currency_id.to_vtoken().map_err(|_| Error::<T>::ErrorConvertVtoken)?;
-				let vtoken_amount =
-					T::MultiCurrency::free_balance(vtoken_id, &order.derivative_account);
 
 				Self::transfer_to(
 					order.derivative_account.clone(),
@@ -1079,11 +1161,19 @@ impl<T: Config> Pallet<T> {
 
 			if current_block_number - order_queue[0].create_block_number >= DelayBlock::<T>::get() {
 				let mut order = order_queue.remove(0);
+				// For compatibility with older versions
 				if order.currency_amount == Default::default() {
 					order.currency_amount = T::MultiCurrency::free_balance(
 						order.currency_id,
 						&order.derivative_account,
 					);
+				} else {
+					// Ensure that the currency amount is not greater than the free balance
+					let free_balance = T::MultiCurrency::free_balance(
+						order.currency_id,
+						&order.derivative_account,
+					);
+					order.currency_amount = order.currency_amount.min(free_balance);
 				}
 				match Self::handle_order(&order) {
 					Ok(_) => {
diff --git a/pallets/slpx/src/migration.rs b/pallets/slpx/src/migration.rs
index 3fabbbf81..e2c38cee2 100644
--- a/pallets/slpx/src/migration.rs
+++ b/pallets/slpx/src/migration.rs
@@ -106,10 +106,34 @@ mod v0 {
 }
 
 pub mod v1 {
-	use frame_support::pallet_prelude::StorageVersion;
+	use frame_support::pallet_prelude::{StorageVersion, ValueQuery};
 
 	use super::*;
 
+	#[derive(Encode, Decode, Clone)]
+	pub struct Order<AccountId, CurrencyId, Balance, BlockNumber> {
+		pub source_chain_caller: OrderCaller<AccountId>,
+		pub bifrost_chain_caller: AccountId,
+		pub derivative_account: AccountId,
+		pub create_block_number: BlockNumber,
+		pub currency_id: CurrencyId,
+		pub currency_amount: Balance,
+		pub order_type: OrderType,
+		pub remark: BoundedVec<u8, ConstU32<32>>,
+		pub target_chain: TargetChain<AccountId>,
+		pub channel_id: u32,
+	}
+
+	#[storage_alias]
+	pub(super) type OrderQueue<T: Config> = StorageValue<
+		Pallet<T>,
+		BoundedVec<
+			Order<AccountIdOf<T>, CurrencyIdOf<T>, BalanceOf<T>, BlockNumberFor<T>>,
+			ConstU32<1000>,
+		>,
+		ValueQuery,
+	>;
+
 	pub struct MigrateToV1<T>(sp_std::marker::PhantomData<T>);
 	impl<T: Config> OnRuntimeUpgrade for MigrateToV1<T> {
 		fn on_runtime_upgrade() -> Weight {
@@ -142,12 +166,47 @@ pub mod v1 {
 	}
 }
 
+pub mod v2 {
+	use super::*;
+	use frame_support::traits::GetStorageVersion;
+
+	pub struct MigrateToV2<T>(sp_std::marker::PhantomData<T>);
+	impl<T: Config> OnRuntimeUpgrade for MigrateToV2<T> {
+		fn on_runtime_upgrade() -> Weight {
+			let on_chain_storage_version = Pallet::<T>::on_chain_storage_version();
+			let in_code_storage_version = Pallet::<T>::in_code_storage_version();
+			if on_chain_storage_version == 1 && in_code_storage_version == 2 {
+				let weight_consumed = migrate_to_v2::<T>();
+				log::info!("Migrating slpx storage to v2");
+				in_code_storage_version.put::<Pallet<T>>();
+				weight_consumed.saturating_add(T::DbWeight::get().writes(1))
+			} else {
+				log::warn!("slpx migration should be removed.");
+				T::DbWeight::get().reads(1)
+			}
+		}
+
+		#[cfg(feature = "try-runtime")]
+		fn post_upgrade(_: Vec<u8>) -> Result<(), sp_runtime::DispatchError> {
+			ensure!(
+				Pallet::<T>::on_chain_storage_version() == 2,
+				"on_chain_storage_version should be 2"
+			);
+			ensure!(
+				Pallet::<T>::in_code_storage_version() == 2,
+				"in_code_storage_version should be 2"
+			);
+			Ok(())
+		}
+	}
+}
+
 pub fn migrate_to_v1<T: Config>() -> Weight {
 	let mut weight: Weight = Weight::zero();
 
 	let old_orders = v0::OrderQueue::<T>::get();
 	for old_order in old_orders.into_iter() {
-		let order = Order {
+		let order = v1::Order {
 			source_chain_caller: old_order.source_chain_caller,
 			bifrost_chain_caller: old_order.bifrost_chain_caller,
 			derivative_account: old_order.derivative_account,
@@ -161,6 +220,38 @@ pub fn migrate_to_v1<T: Config>() -> Weight {
 			channel_id: 0u32,
 		};
 
+		v1::OrderQueue::<T>::mutate(|order_queue| -> DispatchResultWithPostInfo {
+			order_queue.try_push(order.clone()).map_err(|_| Error::<T>::ErrorArguments)?;
+			Ok(().into())
+		})
+		.expect("BoundedVec should not overflow");
+
+		weight = weight.saturating_add(T::DbWeight::get().writes(1));
+	}
+
+	weight
+}
+
+pub fn migrate_to_v2<T: Config>() -> Weight {
+	let mut weight: Weight = Weight::zero();
+
+	let old_order_queue = v1::OrderQueue::<T>::take();
+	for old_order in old_order_queue.into_iter() {
+		let order = Order {
+			source_chain_caller: old_order.source_chain_caller,
+			source_chain_id: 0,
+			source_chain_block_number: None,
+			bifrost_chain_caller: old_order.bifrost_chain_caller,
+			derivative_account: old_order.derivative_account,
+			create_block_number: old_order.create_block_number,
+			currency_id: old_order.currency_id,
+			currency_amount: old_order.currency_amount,
+			order_type: old_order.order_type,
+			remark: old_order.remark,
+			target_chain: old_order.target_chain,
+			channel_id: old_order.channel_id,
+		};
+
 		OrderQueue::<T>::mutate(|order_queue| -> DispatchResultWithPostInfo {
 			order_queue.try_push(order.clone()).map_err(|_| Error::<T>::ErrorArguments)?;
 			Ok(().into())
diff --git a/pallets/slpx/src/tests.rs b/pallets/slpx/src/tests.rs
index 0f4e8c824..762d56562 100644
--- a/pallets/slpx/src/tests.rs
+++ b/pallets/slpx/src/tests.rs
@@ -190,7 +190,7 @@ fn test_execution_fee_work() {
 		assert_eq!(ExecutionFee::<Test>::get(CurrencyId::Token2(0)), Some(10 * 1_000_000_000));
 
 		let balance_exclude_fee =
-			Slpx::charge_execution_fee(CurrencyId::Token2(0), &ALICE).unwrap();
+			Slpx::charge_execution_fee(CurrencyId::Token2(0), 50 * 1_000_000_000, &ALICE).unwrap();
 		assert_eq!(balance_exclude_fee, 40 * 1_000_000_000);
 
 		assert_ok!(Slpx::set_transfer_to_fee(
diff --git a/pallets/slpx/src/types.rs b/pallets/slpx/src/types.rs
index e38e0568a..082ffa3b3 100644
--- a/pallets/slpx/src/types.rs
+++ b/pallets/slpx/src/types.rs
@@ -134,6 +134,8 @@ pub enum OrderType {
 #[derive(Encode, Decode, Clone, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
 pub struct Order<AccountId, CurrencyId, Balance, BlockNumber> {
 	pub source_chain_caller: OrderCaller<AccountId>,
+	pub source_chain_id: u64,
+	pub source_chain_block_number: Option<u128>,
 	pub bifrost_chain_caller: AccountId,
 	pub derivative_account: AccountId,
 	pub create_block_number: BlockNumber,
diff --git a/primitives/src/xcm.rs b/primitives/src/xcm.rs
index b6d59929c..efcb265a8 100644
--- a/primitives/src/xcm.rs
+++ b/primitives/src/xcm.rs
@@ -43,7 +43,14 @@ parameter_types! {
 	pub const MoonriverChainId: u32 = 2023;
 	pub const PhalaChainId: u32 = 2035;
 	pub const KaruraChainId: u32 = 2000;
+}
+
+// Evm chain id
+parameter_types! {
 	pub const EthereumChainId: u64 = 1;
+	pub const MoonriverEvmChainId: u64 = 1285;
+	pub const MoonbeamEvmChainId: u64 = 1284;
+	pub const AstarEvmChainId: u64 = 592;
 }
 
 // Location
diff --git a/runtime/bifrost-kusama/src/lib.rs b/runtime/bifrost-kusama/src/lib.rs
index 47a399465..01276e4dd 100644
--- a/runtime/bifrost-kusama/src/lib.rs
+++ b/runtime/bifrost-kusama/src/lib.rs
@@ -1919,6 +1919,7 @@ pub mod migrations {
 		pallet_xcm::migration::MigrateToLatestXcmVersion<Runtime>,
 		bifrost_cross_in_out::migrations::v3::MigrateToV2<Runtime>,
 		bifrost_asset_registry::migrations::v1::MigrateToV1<Runtime>,
+		bifrost_slpx::migration::v2::MigrateToV2<Runtime>,
 		SystemMakerClearPalletId<Runtime>,
 		frame_support::migrations::RemovePallet<SystemMakerName, RocksDbWeight>,
 	);
diff --git a/runtime/bifrost-polkadot/src/lib.rs b/runtime/bifrost-polkadot/src/lib.rs
index fcbc36dbc..9bded4470 100644
--- a/runtime/bifrost-polkadot/src/lib.rs
+++ b/runtime/bifrost-polkadot/src/lib.rs
@@ -1833,6 +1833,7 @@ pub mod migrations {
 		pallet_xcm::migration::MigrateToLatestXcmVersion<Runtime>,
 		bifrost_cross_in_out::migrations::v3::MigrateToV2<Runtime>,
 		bifrost_asset_registry::migrations::v1::MigrateToV1<Runtime>,
+		bifrost_slpx::migration::v2::MigrateToV2<Runtime>,
 		frame_support::migrations::RemovePallet<SystemMakerName, RocksDbWeight>,
 	);
 }

From b1542d22219896979b98a66716f61570f18ca78f Mon Sep 17 00:00:00 2001
From: yooml <ymlll0508@gmail.com>
Date: Thu, 10 Oct 2024 23:13:08 +0800
Subject: [PATCH 16/31] Update farming (#1455)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* fix: 🐛 for review

* fix: 🐛 for review
---
 pallets/farming/src/benchmarking.rs |  12 +--
 pallets/farming/src/lib.rs          | 133 ++++++++++++++++++++++++++--
 pallets/farming/src/rewards.rs      |   6 +-
 pallets/farming/src/tests.rs        |  26 +++---
 pallets/system-staking/src/tests.rs |   2 +-
 5 files changed, 151 insertions(+), 28 deletions(-)

diff --git a/pallets/farming/src/benchmarking.rs b/pallets/farming/src/benchmarking.rs
index fe5e4504a..c743e1dd3 100644
--- a/pallets/farming/src/benchmarking.rs
+++ b/pallets/farming/src/benchmarking.rs
@@ -65,7 +65,7 @@ benchmarks! {
 		));
 		let charge_rewards = vec![(default_currency_id,BalanceOf::<T>::unique_saturated_from(300000u128))];
 		assert_ok!(Farming::<T>::charge(RawOrigin::Signed(caller.clone()).into(), 0, charge_rewards, false));
-	}: _(RawOrigin::Signed(caller.clone()), 0, token_amount, None)
+	}: _(RawOrigin::Signed(caller.clone()), 0, token_amount)
 
 	withdraw {
 		let caller: T::AccountId = whitelisted_caller();
@@ -87,7 +87,7 @@ benchmarks! {
 		));
 		let charge_rewards = vec![(default_currency_id,BalanceOf::<T>::unique_saturated_from(300000u128))];
 		assert_ok!(Farming::<T>::charge(RawOrigin::Signed(caller.clone()).into(), 0, charge_rewards, false));
-		assert_ok!(Farming::<T>::deposit(RawOrigin::Signed(caller.clone()).into(), 0, token_amount, None));
+		assert_ok!(Farming::<T>::deposit(RawOrigin::Signed(caller.clone()).into(), 0, token_amount));
 	}: _(RawOrigin::Signed(caller.clone()), 0, None)
 
 	claim {
@@ -110,7 +110,7 @@ benchmarks! {
 		));
 		let charge_rewards = vec![(default_currency_id,BalanceOf::<T>::unique_saturated_from(300000u128))];
 		assert_ok!(Farming::<T>::charge(RawOrigin::Signed(caller.clone()).into(), 0, charge_rewards, false));
-		assert_ok!(Farming::<T>::deposit(RawOrigin::Signed(caller.clone()).into(), 0, token_amount, None));
+		assert_ok!(Farming::<T>::deposit(RawOrigin::Signed(caller.clone()).into(), 0, token_amount));
 		System::<T>::set_block_number(System::<T>::block_number() + BlockNumberFor::<T>::from(10u32));
 		Farming::<T>::on_initialize(BlockNumberFor::<T>::from(0u32));
 	}: _(RawOrigin::Signed(caller.clone()), 0)
@@ -135,7 +135,7 @@ benchmarks! {
 		));
 		let charge_rewards = vec![(default_currency_id,BalanceOf::<T>::unique_saturated_from(300000u128))];
 		assert_ok!(Farming::<T>::charge(RawOrigin::Signed(caller.clone()).into(), 0, charge_rewards, false));
-		assert_ok!(Farming::<T>::deposit(RawOrigin::Signed(caller.clone()).into(), 0, token_amount, Some((BalanceOf::<T>::unique_saturated_from(100u128), BlockNumberFor::<T>::from(100u32)))));
+		assert_ok!(Farming::<T>::deposit(RawOrigin::Signed(caller.clone()).into(), 0, token_amount));
 		// System::<T>::set_block_number(System::<T>::block_number() + BlockNumberFor::<T>::from(10u32));
 	}: _(RawOrigin::Signed(caller.clone()), 0)
 
@@ -159,7 +159,7 @@ benchmarks! {
 		));
 		let charge_rewards = vec![(default_currency_id,BalanceOf::<T>::unique_saturated_from(300000u128))];
 		assert_ok!(Farming::<T>::charge(RawOrigin::Signed(caller.clone()).into(), 0, charge_rewards, false));
-		assert_ok!(Farming::<T>::deposit(RawOrigin::Signed(caller.clone()).into(), 0, token_amount, None));
+		assert_ok!(Farming::<T>::deposit(RawOrigin::Signed(caller.clone()).into(), 0, token_amount));
 	}: _(RawOrigin::Signed(caller.clone()), 0)
 
 	reset_pool {
@@ -335,7 +335,7 @@ benchmarks! {
 		));
 		let charge_rewards = vec![(default_currency_id,BalanceOf::<T>::unique_saturated_from(300000u128))];
 		assert_ok!(Farming::<T>::charge(RawOrigin::Signed(caller.clone()).into(), 0, charge_rewards, false));
-		assert_ok!(Farming::<T>::deposit(RawOrigin::Signed(caller.clone()).into(), 0, token_amount, Some((BalanceOf::<T>::unique_saturated_from(100u128), BlockNumberFor::<T>::from(100u32)))));
+		assert_ok!(Farming::<T>::deposit(RawOrigin::Signed(caller.clone()).into(), 0, token_amount));
 		assert_ok!(Farming::<T>::set_retire_limit(RawOrigin::Root.into(), 10));
 	}: _(RawOrigin::Root, 0)
 
diff --git a/pallets/farming/src/lib.rs b/pallets/farming/src/lib.rs
index 73d4badfd..b86a75ea7 100644
--- a/pallets/farming/src/lib.rs
+++ b/pallets/farming/src/lib.rs
@@ -153,7 +153,6 @@ pub mod pallet {
 			who: AccountIdOf<T>,
 			pid: PoolId,
 			add_value: BalanceOf<T>,
-			gauge_info: Option<(BalanceOf<T>, BlockNumberFor<T>)>,
 		},
 		Withdrawn {
 			who: AccountIdOf<T>,
@@ -211,28 +210,46 @@ pub mod pallet {
 
 	#[pallet::error]
 	pub enum Error<T> {
+		/// The field tokens_proportion cannot be empty.
 		NotNullable,
+		/// The pool does not exist.
 		PoolDoesNotExist,
+		/// The gauge pool does not exist.
 		GaugePoolNotExist,
+		/// The gauge info does not exist.
 		GaugeInfoNotExist,
+		/// The pool is not in the correct state.
 		InvalidPoolState,
-		LastGaugeNotClaim,
 		/// claim_limit_time exceeded
 		CanNotClaim,
 		/// gauge pool max_block exceeded
 		GaugeMaxBlockOverflow,
 		/// withdraw_limit_time exceeded
 		WithdrawLimitCountExceeded,
+		/// User's personal share info does not exist
 		ShareInfoNotExists,
+		/// The current block height needs to be greater than the field after_block_to_start in
+		/// order to execute deposit.
 		CanNotDeposit,
+		/// Whitelist cannot be empty
 		WhitelistEmpty,
+		/// When starting a round, the field end_round needs to be 0 to indicate that the previous
+		/// round has ended.
 		RoundNotOver,
+		/// The round length needs to be set when starting a round
 		RoundLengthNotSet,
+		/// Whitelist maximum limit exceeded
 		WhitelistLimitExceeded,
+		/// No one voted for this pool.
 		NobodyVoting,
+		/// The pool is not in the whitelist
 		NotInWhitelist,
+		/// The total voting percentage of users cannot exceed 100%.
 		PercentOverflow,
+		/// The pool cannot be cleaned completely
 		PoolNotCleared,
+		/// Invalid remove amount
+		InvalidRemoveAmount,
 	}
 
 	#[pallet::storage]
@@ -371,6 +388,20 @@ pub mod pallet {
 		BlockNumberFor<T>: AtLeast32BitUnsigned + Copy,
 		BalanceOf<T>: AtLeast32BitUnsigned + Copy,
 	{
+		/// Create a farming pool.
+		///
+		/// The state of the pool will be set to `Ongoing` if the current block number is greater
+		/// than or equal to the field `after_block_to_start` or the total shares of the pool is
+		/// greater than or equal to the field `min_deposit_to_start`.
+		///
+		/// - `tokens_proportion`: The proportion of each token in the pool.
+		/// - `basic_rewards`: The basic reward of each token in the pool.
+		/// - `gauge_init`: The initial gauge pool info.
+		/// - `min_deposit_to_start`: The minimum deposit to start the pool.
+		/// - `after_block_to_start`: The block number to start the pool.
+		/// - `withdraw_limit_time`: The block number to limit the withdraw.
+		/// - `claim_limit_time`: The block number to limit the claim.
+		/// - `withdraw_limit_count`: The count to limit the withdraw.
 		#[pallet::call_index(0)]
 		#[pallet::weight(T::WeightInfo::create_farming_pool())]
 		pub fn create_farming_pool(
@@ -426,6 +457,15 @@ pub mod pallet {
 			Ok(())
 		}
 
+		/// Charge the pool.
+		///
+		/// Transfer the rewards from the exchanger to the pool. It will charge the rewards to the
+		/// gauge pool if the `if_gauge` is true, otherwise it will charge the rewards to the
+		/// farming pool.
+		///
+		/// - `pid`: The pool id.
+		/// - `rewards`: The rewards to charge.
+		/// - `if_gauge`: If the rewards are for the gauge pool.
 		#[pallet::call_index(1)]
 		#[pallet::weight(T::WeightInfo::charge())]
 		pub fn charge(
@@ -476,13 +516,20 @@ pub mod pallet {
 			Ok(())
 		}
 
+		/// Deposit the pool.
+		///
+		/// Mint the share to the exchanger and transfer the tokens to the pool. The state of the
+		/// pool should be `Ongoing` or `Charged`. The current block number should be greater than
+		/// or equal to the field `after_block_to_start` if the state of the pool is `Charged`.
+		///
+		/// - `pid`: The pool id.
+		/// - `add_value`: The value to deposit.
 		#[pallet::call_index(2)]
 		#[pallet::weight(T::WeightInfo::deposit())]
 		pub fn deposit(
 			origin: OriginFor<T>,
 			pid: PoolId,
 			add_value: BalanceOf<T>,
-			gauge_info: Option<(BalanceOf<T>, BlockNumberFor<T>)>,
 		) -> DispatchResult {
 			// Check origin
 			let exchanger = ensure_signed(origin)?;
@@ -516,10 +563,19 @@ pub mod pallet {
 			Self::add_share(&exchanger, pid, &mut pool_info, add_value);
 			Self::update_reward(&exchanger, pid)?;
 
-			Self::deposit_event(Event::Deposited { who: exchanger, pid, add_value, gauge_info });
+			Self::deposit_event(Event::Deposited { who: exchanger, pid, add_value });
 			Ok(())
 		}
 
+		/// Withdraw from the pool.
+		///
+		/// The state of the pool should be `Ongoing`, `Charged` or `Dead`.
+		/// User's withdraw limit count should be less than the field `withdraw_limit_count`.
+		/// It will remove the share from the user, but not transfer the tokens to the user
+		/// immediately.
+		///
+		/// - `pid`: The pool id.
+		/// - `remove_value`: The value to withdraw.
 		#[pallet::call_index(3)]
 		#[pallet::weight(T::WeightInfo::withdraw())]
 		pub fn withdraw(
@@ -551,6 +607,13 @@ pub mod pallet {
 			Ok(())
 		}
 
+		/// Claim the rewards from the pool.
+		///
+		/// The state of the pool should be `Ongoing` or `Dead`.
+		/// The user should not claim the rewards within the field `claim_limit_time`.
+		/// It will claim the rewards to the user, and transfer the tokens to the user immediately.
+		///
+		/// - `pid`: The pool id.
 		#[pallet::call_index(4)]
 		#[pallet::weight(T::WeightInfo::claim())]
 		pub fn claim(origin: OriginFor<T>, pid: PoolId) -> DispatchResult {
@@ -579,6 +642,11 @@ pub mod pallet {
 			Ok(())
 		}
 
+		/// Withdraw the claim from the pool.
+		///
+		/// It will immediately transfer the withdrawable tokens to the user.
+		///
+		/// - `pid`: The pool id.
 		#[pallet::call_index(5)]
 		#[pallet::weight(T::WeightInfo::withdraw_claim())]
 		pub fn withdraw_claim(origin: OriginFor<T>, pid: PoolId) -> DispatchResult {
@@ -592,6 +660,12 @@ pub mod pallet {
 			Ok(())
 		}
 
+		/// Force retire the pool.
+		///
+		/// The state of the pool should be `Dead`.
+		/// It will retire the pool and transfer the withdrawable tokens to the users.
+		///
+		/// - `pid`: The pool id.
 		#[pallet::call_index(6)]
 		#[pallet::weight(T::WeightInfo::force_retire_pool())]
 		pub fn force_retire_pool(origin: OriginFor<T>, pid: PoolId) -> DispatchResult {
@@ -630,6 +704,9 @@ pub mod pallet {
 			Ok(())
 		}
 
+		/// Set the retire limit.
+		///
+		/// - `limit`: The retire limit.
 		#[pallet::call_index(7)]
 		#[pallet::weight(T::WeightInfo::set_retire_limit())]
 		pub fn set_retire_limit(origin: OriginFor<T>, limit: u32) -> DispatchResult {
@@ -643,6 +720,11 @@ pub mod pallet {
 			Ok(())
 		}
 
+		/// Close the pool.
+		///
+		/// Change the state of the pool to `Dead` before retiring the pool.
+		///
+		/// - `pid`: The pool id.
 		#[pallet::call_index(8)]
 		#[pallet::weight(T::WeightInfo::close_pool())]
 		pub fn close_pool(origin: OriginFor<T>, pid: PoolId) -> DispatchResult {
@@ -657,6 +739,16 @@ pub mod pallet {
 			Ok(())
 		}
 
+		/// Reuse retired pools
+		///
+		/// - `pid`: The pool id.
+		/// - `basic_rewards`: The basic reward of each token in the pool.
+		/// - `min_deposit_to_start`: The minimum deposit to start the pool.
+		/// - `after_block_to_start`: The block number to start the pool.
+		/// - `withdraw_limit_time`: The block number to limit the withdraw.
+		/// - `claim_limit_time`: The block number to limit the claim.
+		/// - `withdraw_limit_count`: The count to limit the withdraw.
+		/// - `gauge_init`: The initial gauge pool info.
 		#[pallet::call_index(9)]
 		#[pallet::weight(T::WeightInfo::reset_pool())]
 		pub fn reset_pool(
@@ -710,6 +802,9 @@ pub mod pallet {
 			Ok(())
 		}
 
+		/// Kill the pool after retired.
+		///
+		/// - `pid`: The pool id.
 		#[pallet::call_index(10)]
 		#[pallet::weight(T::WeightInfo::kill_pool())]
 		pub fn kill_pool(origin: OriginFor<T>, pid: PoolId) -> DispatchResult {
@@ -728,6 +823,7 @@ pub mod pallet {
 			Ok(())
 		}
 
+		/// Edit the pool at the state of `Retired`, `Ongoing`, `Charged` or `UnCharged`.
 		#[pallet::call_index(11)]
 		#[pallet::weight(T::WeightInfo::edit_pool())]
 		pub fn edit_pool(
@@ -782,6 +878,9 @@ pub mod pallet {
 			Ok(())
 		}
 
+		/// Withdraw the rewards from the gauge pool.
+		///
+		/// - `gid`: The gauge pool id.
 		#[pallet::call_index(12)]
 		#[pallet::weight(T::WeightInfo::gauge_withdraw())]
 		pub fn gauge_withdraw(origin: OriginFor<T>, gid: PoolId) -> DispatchResult {
@@ -797,6 +896,11 @@ pub mod pallet {
 			Ok(())
 		}
 
+		/// Force claim the rewards from the gauge pool.
+		///
+		/// Control origin can force claim the rewards from the gauge pool to the users.
+		///
+		/// - `gid`: The gauge pool id.
 		#[pallet::call_index(13)]
 		#[pallet::weight(T::WeightInfo::force_gauge_claim())]
 		pub fn force_gauge_claim(origin: OriginFor<T>, gid: PoolId) -> DispatchResult {
@@ -829,7 +933,9 @@ pub mod pallet {
 			Ok(())
 		}
 
-		// Add whitelist and take effect immediately
+		/// Add whitelist and take effect immediately
+		///
+		/// - `whitelist`: The whitelist to add
 		#[pallet::call_index(14)]
 		#[pallet::weight(T::WeightInfo::add_boost_pool_whitelist())]
 		pub fn add_boost_pool_whitelist(
@@ -843,7 +949,9 @@ pub mod pallet {
 			Ok(())
 		}
 
-		// Whitelist for next round in effect
+		/// Whitelist for next round in effect
+		///
+		/// - `whitelist`: The whitelist for the next round
 		#[pallet::call_index(15)]
 		#[pallet::weight(T::WeightInfo::set_next_round_whitelist())]
 		pub fn set_next_round_whitelist(
@@ -851,13 +959,17 @@ pub mod pallet {
 			whitelist: Vec<PoolId>,
 		) -> DispatchResult {
 			T::ControlOrigin::ensure_origin(origin)?;
-			let _ = BoostNextRoundWhitelist::<T>::clear(u32::max_value(), None);
+			let res = BoostNextRoundWhitelist::<T>::clear(u32::max_value(), None);
+			ensure!(res.maybe_cursor.is_none(), Error::<T>::PoolNotCleared);
 			whitelist.iter().for_each(|pid| {
 				BoostNextRoundWhitelist::<T>::insert(pid, ());
 			});
 			Ok(())
 		}
 
+		/// Vote for the pool
+		///
+		/// - `vote_list`: The vote list for the pool
 		#[pallet::call_index(16)]
 		#[pallet::weight(T::WeightInfo::claim())]
 		pub fn vote(origin: OriginFor<T>, vote_list: Vec<(PoolId, Percent)>) -> DispatchResult {
@@ -867,6 +979,9 @@ pub mod pallet {
 			Ok(())
 		}
 
+		/// Start the boost round
+		///
+		/// - `round_length`: The length of the round
 		#[pallet::call_index(17)]
 		#[pallet::weight(T::WeightInfo::claim())]
 		pub fn start_boost_round(
@@ -878,6 +993,7 @@ pub mod pallet {
 			Ok(())
 		}
 
+		/// Force end of boost round
 		#[pallet::call_index(18)]
 		#[pallet::weight(T::WeightInfo::claim())]
 		pub fn end_boost_round(origin: OriginFor<T>) -> DispatchResult {
@@ -886,6 +1002,9 @@ pub mod pallet {
 			Ok(())
 		}
 
+		/// Charge the boost rewards to the FarmingBoost account
+		///
+		/// - `rewards`: The rewards to charge
 		#[pallet::call_index(19)]
 		#[pallet::weight(T::WeightInfo::claim())]
 		pub fn charge_boost(
diff --git a/pallets/farming/src/rewards.rs b/pallets/farming/src/rewards.rs
index a284fa85d..7fb23d95c 100644
--- a/pallets/farming/src/rewards.rs
+++ b/pallets/farming/src/rewards.rs
@@ -228,7 +228,11 @@ impl<T: Config> Pallet<T> {
 			if let Some(mut share_info) = share_info_old.take() {
 				let remove_amount;
 				if let Some(remove_amount_input) = remove_amount_input {
-					remove_amount = remove_amount_input.min(share_info.share);
+					ensure!(
+						remove_amount_input <= share_info.share,
+						Error::<T>::InvalidRemoveAmount
+					);
+					remove_amount = remove_amount_input;
 				} else {
 					remove_amount = share_info.share;
 				}
diff --git a/pallets/farming/src/tests.rs b/pallets/farming/src/tests.rs
index 7c6a9e765..3afbc3987 100644
--- a/pallets/farming/src/tests.rs
+++ b/pallets/farming/src/tests.rs
@@ -60,9 +60,9 @@ fn deposit() {
 	ExtBuilder::default().one_hundred_for_alice_n_bob().build().execute_with(|| {
 		let (pid, tokens) = init_gauge();
 		System::set_block_number(System::block_number() + 1);
-		assert_ok!(Farming::deposit(RuntimeOrigin::signed(ALICE), pid, tokens, Some((100, 100))));
+		assert_ok!(Farming::deposit(RuntimeOrigin::signed(ALICE), pid, tokens));
 		System::set_block_number(System::block_number() + 1);
-		assert_ok!(Farming::deposit(RuntimeOrigin::signed(ALICE), pid, 0, Some((100, 100))));
+		assert_ok!(Farming::deposit(RuntimeOrigin::signed(ALICE), pid, 0));
 		assert_eq!(Tokens::free_balance(KSM, &ALICE), 1000);
 		let keeper: AccountId = <Runtime as Config>::Keeper::get().into_sub_account_truncating(pid);
 		let reward_issuer: AccountId =
@@ -109,7 +109,7 @@ fn withdraw() {
 		assert_ok!(Farming::claim(RuntimeOrigin::signed(ALICE), pid));
 		assert_eq!(Tokens::free_balance(KSM, &ALICE), 3000);
 		System::set_block_number(System::block_number() + 100);
-		assert_ok!(Farming::deposit(RuntimeOrigin::signed(BOB), pid, tokens, None));
+		assert_ok!(Farming::deposit(RuntimeOrigin::signed(BOB), pid, tokens));
 		Farming::on_initialize(0);
 		assert_ok!(Farming::claim(RuntimeOrigin::signed(ALICE), pid));
 		assert_eq!(Tokens::free_balance(KSM, &ALICE), 3966);
@@ -146,18 +146,18 @@ fn gauge() {
 		assert_eq!(Tokens::free_balance(KSM, &ALICE), 3018);
 		Farming::on_initialize(0);
 		System::set_block_number(System::block_number() + 10);
-		assert_ok!(Farming::deposit(RuntimeOrigin::signed(ALICE), pid, tokens, Some((100, 100))));
+		assert_ok!(Farming::deposit(RuntimeOrigin::signed(ALICE), pid, tokens));
 		assert_eq!(Tokens::free_balance(KSM, &ALICE), 2018);
 		System::set_block_number(System::block_number() + 20);
 		assert_ok!(Farming::claim(RuntimeOrigin::signed(ALICE), pid));
 		assert_eq!(Tokens::free_balance(KSM, &ALICE), 3586);
-		assert_ok!(Farming::deposit(RuntimeOrigin::signed(BOB), pid, 10, None));
+		assert_ok!(Farming::deposit(RuntimeOrigin::signed(BOB), pid, 10));
 		assert_eq!(Tokens::free_balance(KSM, &BOB), 9699990);
 		System::set_block_number(System::block_number() + 200);
 		assert_ok!(Farming::claim(RuntimeOrigin::signed(ALICE), pid));
 		assert_eq!(Tokens::free_balance(KSM, &ALICE), 7366);
 		assert_eq!(Tokens::free_balance(KSM, &BOB), 9699990);
-		assert_ok!(Farming::deposit(RuntimeOrigin::signed(BOB), pid, 0, Some((100, 100))));
+		assert_ok!(Farming::deposit(RuntimeOrigin::signed(BOB), pid, 0));
 		System::set_block_number(System::block_number() + 200);
 		assert_ok!(Farming::set_retire_limit(RuntimeOrigin::signed(ALICE), 10));
 		assert_ok!(Farming::force_gauge_claim(RuntimeOrigin::signed(ALICE), pid));
@@ -193,9 +193,9 @@ fn retire() {
 		let (pid, tokens) = init_no_gauge();
 		Farming::on_initialize(0);
 		System::set_block_number(System::block_number() + 1);
-		assert_ok!(Farming::deposit(RuntimeOrigin::signed(ALICE), pid, tokens, None));
+		assert_ok!(Farming::deposit(RuntimeOrigin::signed(ALICE), pid, tokens));
 		System::set_block_number(System::block_number() + 1);
-		assert_ok!(Farming::deposit(RuntimeOrigin::signed(ALICE), pid, 0, None));
+		assert_ok!(Farming::deposit(RuntimeOrigin::signed(ALICE), pid, 0));
 		assert_eq!(Tokens::free_balance(KSM, &ALICE), 1000);
 		assert_ok!(Farming::close_pool(RuntimeOrigin::signed(ALICE), pid));
 		assert_ok!(Farming::set_retire_limit(RuntimeOrigin::signed(ALICE), 10));
@@ -260,7 +260,7 @@ fn reset() {
 		assert_eq!(Tokens::free_balance(KSM, &ALICE), 4018);
 		let charge_rewards = vec![(KSM, 300000)];
 		assert_ok!(Farming::charge(RuntimeOrigin::signed(BOB), pid, charge_rewards, false));
-		assert_ok!(Farming::deposit(RuntimeOrigin::signed(ALICE), pid, 1, Some((100, 100))));
+		assert_ok!(Farming::deposit(RuntimeOrigin::signed(ALICE), pid, 1));
 		assert_eq!(Tokens::free_balance(KSM, &ALICE), 4017);
 		Farming::on_initialize(0);
 		System::set_block_number(System::block_number() + 20);
@@ -292,7 +292,7 @@ fn init_gauge() -> (PoolId, BalanceOf<Runtime>) {
 	let pid = 0;
 	let charge_rewards = vec![(KSM, 300000)];
 	assert_ok!(Farming::charge(RuntimeOrigin::signed(BOB), pid, charge_rewards, false));
-	assert_ok!(Farming::deposit(RuntimeOrigin::signed(ALICE), pid, tokens, Some((100, 100))));
+	assert_ok!(Farming::deposit(RuntimeOrigin::signed(ALICE), pid, tokens));
 	assert_ok!(BbBNC::set_config(RuntimeOrigin::signed(ALICE), Some(0), Some(7 * 86400 / 12)));
 	assert_ok!(BbBNC::notify_reward_amount(pid, &Some(CHARLIE), gauge_basic_rewards.clone()));
 	assert_ok!(BbBNC::create_lock_inner(
@@ -325,7 +325,7 @@ fn init_no_gauge() -> (PoolId, BalanceOf<Runtime>) {
 	let pid = 0;
 	let charge_rewards = vec![(KSM, 100000)];
 	assert_ok!(Farming::charge(RuntimeOrigin::signed(BOB), pid, charge_rewards, false));
-	assert_ok!(Farming::deposit(RuntimeOrigin::signed(ALICE), pid, tokens, None));
+	assert_ok!(Farming::deposit(RuntimeOrigin::signed(ALICE), pid, tokens));
 	(pid, tokens)
 }
 
@@ -391,11 +391,11 @@ fn create_farming_pool() {
 			assert_eq!(pool_infos.state, PoolState::Charged)
 		};
 		assert_err!(
-			Farming::deposit(RuntimeOrigin::signed(ALICE), pid, tokens, Some((100, 100))),
+			Farming::deposit(RuntimeOrigin::signed(ALICE), pid, tokens),
 			Error::<Runtime>::CanNotDeposit
 		);
 		System::set_block_number(System::block_number() + 3);
-		assert_ok!(Farming::deposit(RuntimeOrigin::signed(ALICE), pid, tokens, Some((100, 100))));
+		assert_ok!(Farming::deposit(RuntimeOrigin::signed(ALICE), pid, tokens));
 		Farming::on_initialize(System::block_number() + 3);
 		Farming::on_initialize(0);
 		if let Some(pool_infos) = PoolInfos::<Runtime>::get(0) {
diff --git a/pallets/system-staking/src/tests.rs b/pallets/system-staking/src/tests.rs
index d97ec5aae..75544e3ba 100644
--- a/pallets/system-staking/src/tests.rs
+++ b/pallets/system-staking/src/tests.rs
@@ -246,7 +246,7 @@ fn init_farming_no_gauge() -> (PoolId, BalanceOf<Runtime>) {
 	let pid = 0;
 	let charge_rewards = vec![(KSM, 100000)];
 	assert_ok!(Farming::charge(RuntimeOrigin::signed(BOB), pid, charge_rewards, false));
-	assert_ok!(Farming::deposit(RuntimeOrigin::signed(ALICE), pid, tokens, None));
+	assert_ok!(Farming::deposit(RuntimeOrigin::signed(ALICE), pid, tokens));
 	(pid, tokens)
 }
 

From 8d19729320d21d06804bf06e5ea733153ac9a99b Mon Sep 17 00:00:00 2001
From: SunTiebing <87381708+SunTiebing@users.noreply.github.com>
Date: Fri, 11 Oct 2024 15:08:08 +0800
Subject: [PATCH 17/31] Remove vsbond auction pallet (#1456)

* Backup vsbond-auction pallet

* remove unnecessary call method of vsbond-auction

* remove vsbond-auction pallet

* fix clippy

* Optimize migration code
---
 Cargo.lock                                    |  21 --
 Cargo.toml                                    |   2 -
 .../vsbond-auction/Cargo.toml                 |   0
 .../vsbond-auction/src/benchmarking.rs        |   0
 .../vsbond-auction/src/lib.rs                 |   0
 .../vsbond-auction/src/migration.rs           |   0
 .../vsbond-auction/src/mock.rs                |   0
 .../vsbond-auction/src/tests.rs               |   0
 .../vsbond-auction/src/weights.rs             |   0
 primitives/src/lib.rs                         |   1 +
 runtime/bifrost-kusama/Cargo.toml             |   4 -
 runtime/bifrost-kusama/src/lib.rs             |  23 +-
 runtime/bifrost-kusama/src/migration.rs       | 325 +++++++++++++++++-
 .../src/weights/bifrost_vsbond_auction.rs     | 150 --------
 runtime/bifrost-kusama/src/weights/mod.rs     |   1 -
 runtime/bifrost-kusama/src/xcm_config.rs      |   7 -
 16 files changed, 329 insertions(+), 205 deletions(-)
 rename pallets/{ => deprecated}/vsbond-auction/Cargo.toml (100%)
 rename pallets/{ => deprecated}/vsbond-auction/src/benchmarking.rs (100%)
 rename pallets/{ => deprecated}/vsbond-auction/src/lib.rs (100%)
 rename pallets/{ => deprecated}/vsbond-auction/src/migration.rs (100%)
 rename pallets/{ => deprecated}/vsbond-auction/src/mock.rs (100%)
 rename pallets/{ => deprecated}/vsbond-auction/src/tests.rs (100%)
 rename pallets/{ => deprecated}/vsbond-auction/src/weights.rs (100%)
 delete mode 100644 runtime/bifrost-kusama/src/weights/bifrost_vsbond_auction.rs

diff --git a/Cargo.lock b/Cargo.lock
index 0eecd8dd6..3af063867 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1333,7 +1333,6 @@ dependencies = [
  "bifrost-token-issuer",
  "bifrost-vbnc-convert",
  "bifrost-vesting",
- "bifrost-vsbond-auction",
  "bifrost-vstoken-conversion",
  "bifrost-vtoken-minting",
  "bifrost-vtoken-minting-rpc-runtime-api",
@@ -2240,26 +2239,6 @@ dependencies = [
  "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?branch=release-polkadot-v1.13.0)",
 ]
 
-[[package]]
-name = "bifrost-vsbond-auction"
-version = "0.8.0"
-dependencies = [
- "bifrost-primitives",
- "frame-benchmarking",
- "frame-support",
- "frame-system",
- "log",
- "orml-tokens",
- "orml-traits",
- "parity-scale-codec",
- "scale-info",
- "sp-arithmetic",
- "sp-core",
- "sp-io",
- "sp-runtime",
- "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?branch=release-polkadot-v1.13.0)",
-]
-
 [[package]]
 name = "bifrost-vstoken-conversion"
 version = "0.8.0"
diff --git a/Cargo.toml b/Cargo.toml
index 7a72f45b8..dbe0830a0 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -14,7 +14,6 @@ members = [
 	"pallets/salp",
 	"pallets/token-issuer",
 	"pallets/vesting",
-	"pallets/vsbond-auction",
 	"pallets/cross-in-out",
 	"pallets/evm-accounts",
 	"pallets/xcm-interface",
@@ -92,7 +91,6 @@ bifrost-vbnc-convert                   = { path = "pallets/vbnc-convert", defaul
 bb-bnc                                 = { path = "pallets/bb-bnc", default-features = false }
 bb-bnc-rpc-runtime-api                 = { path = "pallets/bb-bnc/rpc/runtime-api", default-features = false }
 bifrost-vesting                        = { path = "pallets/vesting", default-features = false }
-bifrost-vsbond-auction                 = { path = "pallets/vsbond-auction", default-features = false }
 bifrost-vstoken-conversion             = { path = "pallets/vstoken-conversion", default-features = false }
 bifrost-vtoken-minting                 = { path = "pallets/vtoken-minting", default-features = false }
 bifrost-vtoken-minting-rpc-runtime-api = { path = "pallets/vtoken-minting/rpc/runtime-api", default-features = false }
diff --git a/pallets/vsbond-auction/Cargo.toml b/pallets/deprecated/vsbond-auction/Cargo.toml
similarity index 100%
rename from pallets/vsbond-auction/Cargo.toml
rename to pallets/deprecated/vsbond-auction/Cargo.toml
diff --git a/pallets/vsbond-auction/src/benchmarking.rs b/pallets/deprecated/vsbond-auction/src/benchmarking.rs
similarity index 100%
rename from pallets/vsbond-auction/src/benchmarking.rs
rename to pallets/deprecated/vsbond-auction/src/benchmarking.rs
diff --git a/pallets/vsbond-auction/src/lib.rs b/pallets/deprecated/vsbond-auction/src/lib.rs
similarity index 100%
rename from pallets/vsbond-auction/src/lib.rs
rename to pallets/deprecated/vsbond-auction/src/lib.rs
diff --git a/pallets/vsbond-auction/src/migration.rs b/pallets/deprecated/vsbond-auction/src/migration.rs
similarity index 100%
rename from pallets/vsbond-auction/src/migration.rs
rename to pallets/deprecated/vsbond-auction/src/migration.rs
diff --git a/pallets/vsbond-auction/src/mock.rs b/pallets/deprecated/vsbond-auction/src/mock.rs
similarity index 100%
rename from pallets/vsbond-auction/src/mock.rs
rename to pallets/deprecated/vsbond-auction/src/mock.rs
diff --git a/pallets/vsbond-auction/src/tests.rs b/pallets/deprecated/vsbond-auction/src/tests.rs
similarity index 100%
rename from pallets/vsbond-auction/src/tests.rs
rename to pallets/deprecated/vsbond-auction/src/tests.rs
diff --git a/pallets/vsbond-auction/src/weights.rs b/pallets/deprecated/vsbond-auction/src/weights.rs
similarity index 100%
rename from pallets/vsbond-auction/src/weights.rs
rename to pallets/deprecated/vsbond-auction/src/weights.rs
diff --git a/primitives/src/lib.rs b/primitives/src/lib.rs
index 6b58e7f04..b114b3912 100644
--- a/primitives/src/lib.rs
+++ b/primitives/src/lib.rs
@@ -193,6 +193,7 @@ parameter_types! {
 	pub const TreasuryPalletId: PalletId = PalletId(*b"bf/trsry");
 	pub const VBNCConvertPalletId: PalletId = PalletId(*b"bf/vbncc");
 	pub const VeMintingPalletId: PalletId = PalletId(*b"bf/vemnt");
+	// unused after vsbond_auction pallet removed
 	pub const VsbondAuctionPalletId: PalletId = PalletId(*b"bf/vsbnd");
 	pub const ZenlinkPalletId: PalletId = PalletId(*b"/zenlink");
 }
diff --git a/runtime/bifrost-kusama/Cargo.toml b/runtime/bifrost-kusama/Cargo.toml
index 2d123a6fa..20bca7d5d 100644
--- a/runtime/bifrost-kusama/Cargo.toml
+++ b/runtime/bifrost-kusama/Cargo.toml
@@ -134,7 +134,6 @@ bifrost-system-maker = { workspace = true }
 bifrost-system-staking = { workspace = true }
 bifrost-token-issuer = { workspace = true }
 bifrost-vesting = { workspace = true }
-bifrost-vsbond-auction = { workspace = true }
 bifrost-vstoken-conversion = { workspace = true }
 bifrost-vtoken-minting = { workspace = true }
 bifrost-vtoken-voting = { workspace = true, features = [ "kusama" ] }
@@ -260,7 +259,6 @@ std = [
 	"bifrost-system-staking/std",
 	"bifrost-token-issuer/std",
 	"bifrost-vesting/std",
-	"bifrost-vsbond-auction/std",
 	"bifrost-vstoken-conversion/std",
 	"bifrost-vtoken-minting/std",
 	"bifrost-vtoken-voting/std",
@@ -306,7 +304,6 @@ runtime-benchmarks = [
 	"xcm-builder/runtime-benchmarks",
 	"bifrost-flexible-fee/runtime-benchmarks",
 	"bifrost-salp/runtime-benchmarks",
-	"bifrost-vsbond-auction/runtime-benchmarks",
 	"bifrost-token-issuer/runtime-benchmarks",
 	"bifrost-vtoken-minting/runtime-benchmarks",
 	"bifrost-farming/runtime-benchmarks",
@@ -380,7 +377,6 @@ try-runtime = [
 	"bifrost-flexible-fee/try-runtime",
 	"bifrost-salp/try-runtime",
 	"bifrost-token-issuer/try-runtime",
-	"bifrost-vsbond-auction/try-runtime",
 	"bifrost-asset-registry/try-runtime",
 	"bifrost-vtoken-minting/try-runtime",
 	"bifrost-slp/try-runtime",
diff --git a/runtime/bifrost-kusama/src/lib.rs b/runtime/bifrost-kusama/src/lib.rs
index 01276e4dd..b25e34213 100644
--- a/runtime/bifrost-kusama/src/lib.rs
+++ b/runtime/bifrost-kusama/src/lib.rs
@@ -36,7 +36,7 @@ use bifrost_primitives::{
 	FarmingRewardIssuerPalletId, FeeSharePalletId, FlexibleFeePalletId, IncentivePoolAccount,
 	LendMarketPalletId, MerkleDirtributorPalletId, OraclePalletId, ParachainStakingPalletId,
 	SlpEntrancePalletId, SlpExitPalletId, SystemMakerPalletId, SystemStakingPalletId,
-	TreasuryPalletId, VBNCConvertPalletId, VsbondAuctionPalletId,
+	TreasuryPalletId, VBNCConvertPalletId,
 };
 pub use frame_support::{
 	construct_runtime, match_types, parameter_types,
@@ -1159,18 +1159,6 @@ parameter_types! {
 	pub const MinimumSupply: Balance = 0;
 }
 
-impl bifrost_vsbond_auction::Config for Runtime {
-	type RuntimeEvent = RuntimeEvent;
-	type InvoicingCurrency = RelayCurrencyId;
-	type MaximumOrderInTrade = MaximumOrderInTrade;
-	type MinimumAmount = MinimumSupply;
-	type MultiCurrency = Currencies;
-	type WeightInfo = weights::bifrost_vsbond_auction::BifrostWeight<Runtime>;
-	type PalletId = VsbondAuctionPalletId;
-	type TreasuryAccount = BifrostTreasuryAccount;
-	type ControlOrigin = TechAdminOrCouncil;
-}
-
 impl bifrost_token_issuer::Config for Runtime {
 	type RuntimeEvent = RuntimeEvent;
 	type MultiCurrency = Currencies;
@@ -1828,7 +1816,6 @@ construct_runtime! {
 		FlexibleFee: bifrost_flexible_fee = 100,
 		Salp: bifrost_salp = 105,
 		TokenIssuer: bifrost_token_issuer = 109,
-		VSBondAuction: bifrost_vsbond_auction = 113,
 		AssetRegistry: bifrost_asset_registry = 114,
 		VtokenMinting: bifrost_vtoken_minting = 115,
 		Slp: bifrost_slp = 116,
@@ -1905,13 +1892,16 @@ pub type Migrations = migrations::Unreleased;
 
 parameter_types! {
 	pub const SystemMakerName: &'static str = "SystemMaker";
+	pub const VSBondAuctionName: &'static str = "VSBondAuction";
 }
 
 /// The runtime migrations per release.
 pub mod migrations {
 	#![allow(unused_imports)]
 	use super::*;
-	use migration::system_maker::SystemMakerClearPalletId;
+	use migration::{
+		system_maker::SystemMakerClearPalletId, vsbond_auction::VSBondAuctionClearPalletId,
+	};
 
 	/// Unreleased migrations. Add new ones here:
 	pub type Unreleased = (
@@ -1921,7 +1911,9 @@ pub mod migrations {
 		bifrost_asset_registry::migrations::v1::MigrateToV1<Runtime>,
 		bifrost_slpx::migration::v2::MigrateToV2<Runtime>,
 		SystemMakerClearPalletId<Runtime>,
+		VSBondAuctionClearPalletId<Runtime>,
 		frame_support::migrations::RemovePallet<SystemMakerName, RocksDbWeight>,
+		frame_support::migrations::RemovePallet<VSBondAuctionName, RocksDbWeight>,
 	);
 }
 
@@ -1952,7 +1944,6 @@ mod benches {
 		[bifrost_stable_pool, StablePool]
 		[bifrost_system_staking, SystemStaking]
 		[bifrost_token_issuer, TokenIssuer]
-		[bifrost_vsbond_auction, VSBondAuction]
 		[bifrost_vstoken_conversion, VstokenConversion]
 		[bifrost_vtoken_minting, VtokenMinting]
 		[bifrost_vtoken_voting, VtokenVoting]
diff --git a/runtime/bifrost-kusama/src/migration.rs b/runtime/bifrost-kusama/src/migration.rs
index c6209c79c..487a48617 100644
--- a/runtime/bifrost-kusama/src/migration.rs
+++ b/runtime/bifrost-kusama/src/migration.rs
@@ -382,13 +382,13 @@ pub mod system_maker {
 		fn pre_upgrade() -> Result<sp_std::prelude::Vec<u8>, sp_runtime::DispatchError> {
 			#[allow(unused_imports)]
 			use frame_support::PalletId;
-			log::info!("Bifrost `pre_upgrade`...");
+			log::info!("Bifrost SystemMakerClearPalletId `pre_upgrade`...");
 
 			Ok(vec![])
 		}
 
 		fn on_runtime_upgrade() -> Weight {
-			log::info!("Bifrost `on_runtime_upgrade`...");
+			log::info!("Bifrost SystemMakerClearPalletId `on_runtime_upgrade`...");
 
 			let account_id = SystemMakerPalletId::get().into_account_truncating();
 			let ksm_balance = T::MultiCurrency::free_balance(KSM, &account_id);
@@ -410,14 +410,14 @@ pub mod system_maker {
 			log::info!("KSM balance: {:?}", ksm_balance);
 			log::info!("VKSM balance: {:?}", vksm_balance);
 
-			log::info!("Bifrost `on_runtime_upgrade finished`");
+			log::info!("Bifrost SystemMakerClearPalletId `on_runtime_upgrade finished`");
 
 			Weight::from(T::DbWeight::get().reads_writes(1, 1))
 		}
 
 		#[cfg(feature = "try-runtime")]
 		fn post_upgrade(_: sp_std::prelude::Vec<u8>) -> Result<(), sp_runtime::DispatchError> {
-			log::info!("Bifrost `post_upgrade`...");
+			log::info!("Bifrost SystemMakerClearPalletId `post_upgrade`...");
 			let account_id = SystemMakerPalletId::get().into_account_truncating();
 			let ksm_balance = T::MultiCurrency::free_balance(KSM, &account_id);
 			assert_eq!(ksm_balance, Zero::zero());
@@ -428,3 +428,320 @@ pub mod system_maker {
 		}
 	}
 }
+
+pub mod vsbond_auction {
+	use super::*;
+	pub use bifrost_primitives::currency::{BNC, KSM};
+	use bifrost_primitives::VsbondAuctionPalletId;
+	use frame_support::{pallet_prelude::PhantomData, traits::OnRuntimeUpgrade};
+	use sp_core::Get;
+
+	pub struct VSBondAuctionClearPalletId<T>(PhantomData<T>);
+	impl<T: bifrost_vtoken_minting::Config> OnRuntimeUpgrade for VSBondAuctionClearPalletId<T> {
+		#[cfg(feature = "try-runtime")]
+		fn pre_upgrade() -> Result<sp_std::prelude::Vec<u8>, sp_runtime::DispatchError> {
+			log::info!("Bifrost VSBondAuctionClearPalletId `pre_upgrade`...");
+
+			Ok(vec![])
+		}
+
+		fn on_runtime_upgrade() -> Weight {
+			log::info!("Bifrost VSBondAuctionClearPalletId `on_runtime_upgrade`...");
+
+			let account_id = VsbondAuctionPalletId::get().into_account_truncating();
+			let mut count: u64 = 0;
+
+			let bnc_balance = T::MultiCurrency::free_balance(BNC, &account_id);
+			if !bnc_balance.is_zero() {
+				match T::MultiCurrency::transfer(
+					BNC,
+					&account_id,
+					&TreasuryPalletId::get().into_account_truncating(),
+					bnc_balance,
+				) {
+					Ok(_) => {
+						count += 1;
+						log::info!("Transfer successful: {:?} of BNC transferred", bnc_balance);
+					},
+					Err(e) => {
+						log::error!("Failed to transfer {:?} of BNC: {:?}", bnc_balance, e);
+					},
+				}
+			} else {
+				log::info!("No transfer needed for BNC as the balance is 0");
+			}
+
+			let ksm_balance = T::MultiCurrency::free_balance(KSM, &account_id);
+			if !ksm_balance.is_zero() {
+				match T::MultiCurrency::transfer(
+					KSM,
+					&account_id,
+					&TreasuryPalletId::get().into_account_truncating(),
+					ksm_balance,
+				) {
+					Ok(_) => {
+						count += 1;
+						log::info!("Transfer successful: {:?} of KSM transferred", ksm_balance);
+					},
+					Err(e) => {
+						log::error!("Failed to transfer {:?} of KSM: {:?}", ksm_balance, e);
+					},
+				}
+			} else {
+				log::info!("No transfer needed for KSM as the balance is 0");
+			}
+
+			let vs_bond_1 = CurrencyId::VSBond(TokenSymbol::KSM, 2092, 15, 22);
+			let vs_bond_1_balance = T::MultiCurrency::free_balance(vs_bond_1, &account_id);
+			if !vs_bond_1_balance.is_zero() {
+				match T::MultiCurrency::transfer(
+					vs_bond_1,
+					&account_id,
+					&TreasuryPalletId::get().into_account_truncating(),
+					vs_bond_1_balance,
+				) {
+					Ok(_) => {
+						count += 1;
+						log::info!(
+							"Transfer successful: {:?} of VSBond(TokenSymbol::KSM, 2092, 15, 22); transferred",
+							vs_bond_1_balance
+						);
+					},
+					Err(e) => {
+						log::error!(
+							"Failed to transfer {:?} of VSBond(TokenSymbol::KSM, 2092, 15, 22);: {:?}",
+							vs_bond_1_balance,
+							e
+						);
+					},
+				}
+			} else {
+				log::info!("No transfer needed for VSBond(TokenSymbol::KSM, 2092, 15, 22) as the balance is 0");
+			}
+
+			let vs_bond_2 = CurrencyId::VSBond(TokenSymbol::KSM, 2096, 17, 24);
+			let vs_bond_2_balance = T::MultiCurrency::free_balance(vs_bond_2, &account_id);
+			if !vs_bond_2_balance.is_zero() {
+				match T::MultiCurrency::transfer(
+					vs_bond_2,
+					&account_id,
+					&TreasuryPalletId::get().into_account_truncating(),
+					vs_bond_2_balance,
+				) {
+					Ok(_) => {
+						count += 1;
+						log::info!(
+							"Transfer successful: {:?} of VSBond(TokenSymbol::KSM, 2096, 17, 24) transferred",
+							vs_bond_2_balance
+						);
+					},
+					Err(e) => {
+						log::error!(
+							"Failed to transfer {:?} of VSBond(TokenSymbol::KSM, 2096, 17, 24): {:?}",
+							vs_bond_2_balance,
+							e
+						);
+					},
+				}
+			} else {
+				log::info!("No transfer needed for VSBond(TokenSymbol::KSM, 2096, 17, 24) as the balance is 0");
+			}
+
+			let vs_bond_3 = CurrencyId::VSBond(TokenSymbol::KSM, 2100, 18, 25);
+			let vs_bond_3_balance = T::MultiCurrency::free_balance(vs_bond_3, &account_id);
+			if !vs_bond_3_balance.is_zero() {
+				match T::MultiCurrency::transfer(
+					vs_bond_3,
+					&account_id,
+					&TreasuryPalletId::get().into_account_truncating(),
+					vs_bond_3_balance,
+				) {
+					Ok(_) => {
+						count += 1;
+						log::info!(
+							"Transfer successful: {:?} of VSBond(TokenSymbol::KSM, 2100, 18, 25) transferred",
+							vs_bond_3_balance
+						);
+					},
+					Err(e) => {
+						log::error!(
+							"Failed to transfer {:?} of VSBond(TokenSymbol::KSM, 2100, 18, 25): {:?}",
+							vs_bond_3_balance,
+							e
+						);
+					},
+				}
+			} else {
+				log::info!("No transfer needed for VSBond(TokenSymbol::KSM, 2100, 18, 25) as the balance is 0");
+			}
+
+			let vs_bond_4 = CurrencyId::VSBond(TokenSymbol::KSM, 2125, 23, 30);
+			let vs_bond_4_balance = T::MultiCurrency::free_balance(vs_bond_4, &account_id);
+			if !vs_bond_4_balance.is_zero() {
+				match T::MultiCurrency::transfer(
+					vs_bond_4,
+					&account_id,
+					&TreasuryPalletId::get().into_account_truncating(),
+					vs_bond_4_balance,
+				) {
+					Ok(_) => {
+						count += 1;
+						log::info!(
+							"Transfer successful: {:?} of VSBond(TokenSymbol::KSM, 2125, 23, 30) transferred",
+							vs_bond_4_balance
+						);
+					},
+					Err(e) => {
+						log::error!(
+							"Failed to transfer {:?} of VSBond(TokenSymbol::KSM, 2125, 23, 30): {:?}",
+							vs_bond_4_balance,
+							e
+						);
+					},
+				}
+			} else {
+				log::info!("No transfer needed for VSBond(TokenSymbol::KSM, 2125, 23, 30) as the balance is 0");
+			}
+
+			let vs_bond_5 = CurrencyId::VSBond(TokenSymbol::KSM, 2114, 20, 27);
+			let vs_bond_5_balance = T::MultiCurrency::free_balance(vs_bond_5, &account_id);
+			if !vs_bond_5_balance.is_zero() {
+				match T::MultiCurrency::transfer(
+					vs_bond_5,
+					&account_id,
+					&TreasuryPalletId::get().into_account_truncating(),
+					vs_bond_5_balance,
+				) {
+					Ok(_) => {
+						count += 1;
+						log::info!(
+							"Transfer successful: {:?} of VSBond(TokenSymbol::KSM, 2114, 20, 27) transferred",
+							vs_bond_5_balance
+						);
+					},
+					Err(e) => {
+						log::error!(
+							"Failed to transfer {:?} of VSBond(TokenSymbol::KSM, 2114, 20, 27): {:?}",
+							vs_bond_5_balance,
+							e
+						);
+					},
+				}
+			} else {
+				log::info!("No transfer needed for VSBond(TokenSymbol::KSM, 2114, 20, 27) as the balance is 0");
+			}
+
+			let vs_bond_6 = CurrencyId::VSBond(TokenSymbol::KSM, 2118, 22, 29);
+			let vs_bond_6_balance = T::MultiCurrency::free_balance(vs_bond_6, &account_id);
+			if !vs_bond_6_balance.is_zero() {
+				match T::MultiCurrency::transfer(
+					vs_bond_6,
+					&account_id,
+					&TreasuryPalletId::get().into_account_truncating(),
+					vs_bond_6_balance,
+				) {
+					Ok(_) => {
+						count += 1;
+						log::info!(
+							"Transfer successful: {:?} of VSBond(TokenSymbol::KSM, 2118, 22, 29) transferred",
+							vs_bond_6_balance
+						);
+					},
+					Err(e) => {
+						log::error!(
+							"Failed to transfer {:?} of VSBond(TokenSymbol::KSM, 2118, 22, 29): {:?}",
+							vs_bond_6_balance,
+							e
+						);
+					},
+				}
+			} else {
+				log::info!("No transfer needed for VSBond(TokenSymbol::KSM, 2118, 22, 29) as the balance is 0");
+			}
+
+			let vs_bond_7 = CurrencyId::VSBond(TokenSymbol::BNC, 2001, 13, 20);
+			let vs_bond_7_balance = T::MultiCurrency::free_balance(vs_bond_7, &account_id);
+			if !vs_bond_7_balance.is_zero() {
+				match T::MultiCurrency::transfer(
+					vs_bond_7,
+					&account_id,
+					&TreasuryPalletId::get().into_account_truncating(),
+					vs_bond_7_balance,
+				) {
+					Ok(_) => {
+						count += 1;
+						log::info!(
+							"Transfer successful: {:?} of VSBond(TokenSymbol::BNC, 2001, 13, 20) transferred",
+							vs_bond_7_balance
+						);
+					},
+					Err(e) => {
+						log::error!(
+							"Failed to transfer {:?} of VSBond(TokenSymbol::BNC, 2001, 13, 20): {:?}",
+							vs_bond_7_balance,
+							e
+						);
+					},
+				}
+			} else {
+				log::info!("No transfer needed for VSBond(TokenSymbol::BNC, 2001, 13, 20) as the balance is 0");
+			}
+
+			log::info!("BNC balance: {:?}", bnc_balance);
+			log::info!("KSM balance: {:?}", ksm_balance);
+			log::info!("vs_bond_1_balance balance: {:?}", vs_bond_1_balance);
+			log::info!("vs_bond_2_balance balance: {:?}", vs_bond_2_balance);
+			log::info!("vs_bond_3_balance balance: {:?}", vs_bond_3_balance);
+			log::info!("vs_bond_4_balance balance: {:?}", vs_bond_4_balance);
+			log::info!("vs_bond_5_balance balance: {:?}", vs_bond_5_balance);
+			log::info!("vs_bond_6_balance balance: {:?}", vs_bond_6_balance);
+			log::info!("vs_bond_7_balance balance: {:?}", vs_bond_7_balance);
+
+			log::info!("Bifrost VSBondAuctionClearPalletId `on_runtime_upgrade finished`");
+
+			Weight::from(T::DbWeight::get().reads_writes(count + 1, 10))
+		}
+
+		#[cfg(feature = "try-runtime")]
+		fn post_upgrade(_: sp_std::prelude::Vec<u8>) -> Result<(), sp_runtime::DispatchError> {
+			log::info!("Bifrost VSBondAuctionClearPalletId `post_upgrade`...");
+			let account_id = VsbondAuctionPalletId::get().into_account_truncating();
+
+			let bnc_balance = T::MultiCurrency::free_balance(BNC, &account_id);
+			assert_eq!(bnc_balance, Zero::zero());
+
+			let ksm_balance = T::MultiCurrency::free_balance(KSM, &account_id);
+			assert_eq!(ksm_balance, Zero::zero());
+
+			let vs_bond_1 = CurrencyId::VSBond(TokenSymbol::KSM, 2092, 15, 22);
+			let vs_bond_1_balance = T::MultiCurrency::free_balance(vs_bond_1, &account_id);
+			assert_eq!(vs_bond_1_balance, Zero::zero());
+
+			let vs_bond_2 = CurrencyId::VSBond(TokenSymbol::KSM, 2096, 17, 24);
+			let vs_bond_2_balance = T::MultiCurrency::free_balance(vs_bond_2, &account_id);
+			assert_eq!(vs_bond_2_balance, Zero::zero());
+
+			let vs_bond_3 = CurrencyId::VSBond(TokenSymbol::KSM, 2100, 18, 25);
+			let vs_bond_3_balance = T::MultiCurrency::free_balance(vs_bond_3, &account_id);
+			assert_eq!(vs_bond_3_balance, Zero::zero());
+
+			let vs_bond_4 = CurrencyId::VSBond(TokenSymbol::KSM, 2125, 23, 30);
+			let vs_bond_4_balance = T::MultiCurrency::free_balance(vs_bond_4, &account_id);
+			assert_eq!(vs_bond_4_balance, Zero::zero());
+
+			let vs_bond_5 = CurrencyId::VSBond(TokenSymbol::KSM, 2114, 20, 27);
+			let vs_bond_5_balance = T::MultiCurrency::free_balance(vs_bond_5, &account_id);
+			assert_eq!(vs_bond_5_balance, Zero::zero());
+
+			let vs_bond_6 = CurrencyId::VSBond(TokenSymbol::KSM, 2118, 22, 29);
+			let vs_bond_6_balance = T::MultiCurrency::free_balance(vs_bond_6, &account_id);
+			assert_eq!(vs_bond_6_balance, Zero::zero());
+
+			let vs_bond_7 = CurrencyId::VSBond(TokenSymbol::BNC, 2001, 13, 20);
+			let vs_bond_7_balance = T::MultiCurrency::free_balance(vs_bond_7, &account_id);
+			assert_eq!(vs_bond_7_balance, Zero::zero());
+
+			Ok(())
+		}
+	}
+}
diff --git a/runtime/bifrost-kusama/src/weights/bifrost_vsbond_auction.rs b/runtime/bifrost-kusama/src/weights/bifrost_vsbond_auction.rs
deleted file mode 100644
index b74cd417a..000000000
--- a/runtime/bifrost-kusama/src/weights/bifrost_vsbond_auction.rs
+++ /dev/null
@@ -1,150 +0,0 @@
-// 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 <https://www.gnu.org/licenses/>.
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-//! Autogenerated weights for bifrost_vsbond_auction
-//!
-//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
-//! DATE: 2023-09-14, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]`
-//! HOSTNAME: `bifrost-jenkins`, CPU: `Intel(R) Xeon(R) CPU E5-26xx v4`
-//! WASM-EXECUTION: Compiled, CHAIN: Some("bifrost-kusama-local"), DB CACHE: 1024
-
-// Executed Command:
-// target/release/bifrost
-// benchmark
-// pallet
-// --chain=bifrost-kusama-local
-// --steps=50
-// --repeat=20
-// --pallet=bifrost_vsbond_auction
-// --extrinsic=*
-// --execution=wasm
-// --wasm-execution=compiled
-// --heap-pages=4096
-// --output=./runtime/bifrost-kusama/src/weights/bifrost_vsbond_auction.rs
-// --template=./weight-template/runtime-weight-template.hbs
-
-#![cfg_attr(rustfmt, rustfmt_skip)]
-#![allow(unused_parens)]
-#![allow(unused_imports)]
-
-use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
-use sp_std::marker::PhantomData;
-
-/// Weight functions for bifrost_vsbond_auction.
-pub struct BifrostWeight<T>(PhantomData<T>);
-impl<T: frame_system::Config> bifrost_vsbond_auction::WeightInfo for BifrostWeight<T> {
-	// Storage: VSBondAuction TransactionFee (r:1 w:0)
-	// Proof Skipped: VSBondAuction TransactionFee (max_values: Some(1), max_size: None, mode: Measured)
-	// Storage: Tokens Accounts (r:2 w:2)
-	// Proof: Tokens Accounts (max_values: None, max_size: Some(118), added: 2593, mode: MaxEncodedLen)
-	// Storage: VSBondAuction UserOrderIds (r:1 w:1)
-	// Proof Skipped: VSBondAuction UserOrderIds (max_values: None, max_size: None, mode: Measured)
-	// Storage: VSBondAuction NextOrderId (r:1 w:1)
-	// Proof Skipped: VSBondAuction NextOrderId (max_values: Some(1), max_size: None, mode: Measured)
-	// Storage: AssetRegistry CurrencyMetadatas (r:1 w:0)
-	// Proof Skipped: AssetRegistry CurrencyMetadatas (max_values: None, max_size: None, mode: Measured)
-	// Storage: System Account (r:1 w:1)
-	// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen)
-	// Storage: VSBondAuction TotalOrderInfos (r:0 w:1)
-	// Proof Skipped: VSBondAuction TotalOrderInfos (max_values: None, max_size: None, mode: Measured)
-	fn create_order() -> Weight {
-		// Proof Size summary in bytes:
-		//  Measured:  `1789`
-		//  Estimated: `6176`
-		// Minimum execution time: 175_259 nanoseconds.
-		Weight::from_parts(177_403_000, 6176)
-			.saturating_add(T::DbWeight::get().reads(7))
-			.saturating_add(T::DbWeight::get().writes(6))
-	}
-	// Storage: VSBondAuction TotalOrderInfos (r:1 w:1)
-	// Proof Skipped: VSBondAuction TotalOrderInfos (max_values: None, max_size: None, mode: Measured)
-	// Storage: AssetRegistry CurrencyMetadatas (r:1 w:0)
-	// Proof Skipped: AssetRegistry CurrencyMetadatas (max_values: None, max_size: None, mode: Measured)
-	// Storage: Tokens Accounts (r:2 w:2)
-	// Proof: Tokens Accounts (max_values: None, max_size: Some(118), added: 2593, mode: MaxEncodedLen)
-	// Storage: System Account (r:1 w:1)
-	// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen)
-	// Storage: VSBondAuction UserOrderIds (r:1 w:1)
-	// Proof Skipped: VSBondAuction UserOrderIds (max_values: None, max_size: None, mode: Measured)
-	fn revoke_order() -> Weight {
-		// Proof Size summary in bytes:
-		//  Measured:  `2023`
-		//  Estimated: `6176`
-		// Minimum execution time: 161_381 nanoseconds.
-		Weight::from_parts(162_871_000, 6176)
-			.saturating_add(T::DbWeight::get().reads(6))
-			.saturating_add(T::DbWeight::get().writes(5))
-	}
-	// Storage: VSBondAuction TotalOrderInfos (r:1 w:1)
-	// Proof Skipped: VSBondAuction TotalOrderInfos (max_values: None, max_size: None, mode: Measured)
-	// Storage: VSBondAuction TransactionFee (r:1 w:0)
-	// Proof Skipped: VSBondAuction TransactionFee (max_values: Some(1), max_size: None, mode: Measured)
-	// Storage: Tokens Accounts (r:4 w:4)
-	// Proof: Tokens Accounts (max_values: None, max_size: Some(118), added: 2593, mode: MaxEncodedLen)
-	// Storage: AssetRegistry CurrencyMetadatas (r:1 w:0)
-	// Proof Skipped: AssetRegistry CurrencyMetadatas (max_values: None, max_size: None, mode: Measured)
-	// Storage: System Account (r:1 w:1)
-	// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen)
-	// Storage: VSBondAuction UserOrderIds (r:1 w:1)
-	// Proof Skipped: VSBondAuction UserOrderIds (max_values: None, max_size: None, mode: Measured)
-	fn clinch_order() -> Weight {
-		// Proof Size summary in bytes:
-		//  Measured:  `2383`
-		//  Estimated: `11362`
-		// Minimum execution time: 236_772 nanoseconds.
-		Weight::from_parts(238_487_000, 11362)
-			.saturating_add(T::DbWeight::get().reads(9))
-			.saturating_add(T::DbWeight::get().writes(7))
-	}
-	// Storage: VSBondAuction TotalOrderInfos (r:1 w:1)
-	// Proof Skipped: VSBondAuction TotalOrderInfos (max_values: None, max_size: None, mode: Measured)
-	// Storage: VSBondAuction TransactionFee (r:1 w:0)
-	// Proof Skipped: VSBondAuction TransactionFee (max_values: Some(1), max_size: None, mode: Measured)
-	// Storage: Tokens Accounts (r:4 w:4)
-	// Proof: Tokens Accounts (max_values: None, max_size: Some(118), added: 2593, mode: MaxEncodedLen)
-	// Storage: AssetRegistry CurrencyMetadatas (r:1 w:0)
-	// Proof Skipped: AssetRegistry CurrencyMetadatas (max_values: None, max_size: None, mode: Measured)
-	// Storage: System Account (r:1 w:0)
-	// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen)
-	fn partial_clinch_order() -> Weight {
-		// Proof Size summary in bytes:
-		//  Measured:  `2291`
-		//  Estimated: `11362`
-		// Minimum execution time: 206_572 nanoseconds.
-		Weight::from_parts(214_687_000, 11362)
-			.saturating_add(T::DbWeight::get().reads(8))
-			.saturating_add(T::DbWeight::get().writes(5))
-	}
-	// Storage: VSBondAuction TransactionFee (r:1 w:1)
-	// Proof Skipped: VSBondAuction TransactionFee (max_values: Some(1), max_size: None, mode: Measured)
-	fn set_buy_and_sell_transaction_fee_rate() -> Weight {
-		// Proof Size summary in bytes:
-		//  Measured:  `4`
-		//  Estimated: `1489`
-		// Minimum execution time: 26_870 nanoseconds.
-		Weight::from_parts(27_527_000, 1489)
-			.saturating_add(T::DbWeight::get().reads(1))
-			.saturating_add(T::DbWeight::get().writes(1))
-	}
-}
diff --git a/runtime/bifrost-kusama/src/weights/mod.rs b/runtime/bifrost-kusama/src/weights/mod.rs
index 5de22ec76..c69a7e8be 100644
--- a/runtime/bifrost-kusama/src/weights/mod.rs
+++ b/runtime/bifrost-kusama/src/weights/mod.rs
@@ -36,7 +36,6 @@ pub mod bifrost_system_staking;
 pub mod bifrost_token_issuer;
 pub mod bifrost_vbnc_convert;
 pub mod bifrost_vesting;
-pub mod bifrost_vsbond_auction;
 pub mod bifrost_vstoken_conversion;
 pub mod bifrost_vtoken_minting;
 pub mod bifrost_vtoken_voting;
diff --git a/runtime/bifrost-kusama/src/xcm_config.rs b/runtime/bifrost-kusama/src/xcm_config.rs
index 414600305..90b13211a 100644
--- a/runtime/bifrost-kusama/src/xcm_config.rs
+++ b/runtime/bifrost-kusama/src/xcm_config.rs
@@ -352,12 +352,6 @@ impl Contains<RuntimeCall> for SafeCallFilter {
 			RuntimeCall::Salp(
 				bifrost_salp::Call::redeem { .. }
 			) |
-			RuntimeCall::VSBondAuction(
-				bifrost_vsbond_auction::Call::clinch_order { .. } |
-				bifrost_vsbond_auction::Call::create_order { .. } |
-				bifrost_vsbond_auction::Call::partial_clinch_order { .. } |
-				bifrost_vsbond_auction::Call::revoke_order { .. }
-			) |
 			RuntimeCall::VstokenConversion(
 				bifrost_vstoken_conversion::Call::vsbond_convert_to_vstoken { .. } |
 				bifrost_vstoken_conversion::Call::vstoken_convert_to_vsbond { .. }
@@ -566,7 +560,6 @@ impl Contains<AccountId> for DustRemovalWhitelist {
 			SystemMakerPalletId::get().into_account_truncating(),
 			ZenklinkFeeAccount::get(),
 			CommissionPalletId::get().into_account_truncating(),
-			VsbondAuctionPalletId::get().into_account_truncating(),
 			ParachainStakingPalletId::get().into_account_truncating(),
 			SystemStakingPalletId::get().into_account_truncating(),
 			VBNCConvertPalletId::get().into_account_truncating(),

From 9ac8443649519d3bc16db805bd4031221649cda1 Mon Sep 17 00:00:00 2001
From: SunTiebing <87381708+SunTiebing@users.noreply.github.com>
Date: Fri, 11 Oct 2024 17:40:47 +0800
Subject: [PATCH 18/31] This version of vtoken_voting does not support VBNC.
 (#1459)

---
 pallets/vtoken-voting/src/lib.rs       | 2 +-
 pallets/vtoken-voting/src/tests/mod.rs | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/pallets/vtoken-voting/src/lib.rs b/pallets/vtoken-voting/src/lib.rs
index 95d4bd80b..a8452f646 100644
--- a/pallets/vtoken-voting/src/lib.rs
+++ b/pallets/vtoken-voting/src/lib.rs
@@ -1211,7 +1211,7 @@ pub mod pallet {
 		}
 
 		fn ensure_vtoken(vtoken: &CurrencyIdOf<T>) -> Result<(), DispatchError> {
-			ensure!([VKSM, VDOT, VBNC].contains(vtoken), Error::<T>::VTokenNotSupport);
+			ensure!([VKSM, VDOT].contains(vtoken), Error::<T>::VTokenNotSupport);
 			Ok(())
 		}
 
diff --git a/pallets/vtoken-voting/src/tests/mod.rs b/pallets/vtoken-voting/src/tests/mod.rs
index 955f282ad..aa137efcd 100644
--- a/pallets/vtoken-voting/src/tests/mod.rs
+++ b/pallets/vtoken-voting/src/tests/mod.rs
@@ -19,5 +19,5 @@
 #[cfg(test)]
 mod common_test;
 
-#[cfg(test)]
-mod vbnc_test;
+// #[cfg(test)]
+// mod vbnc_test;

From c62e8169ab074b42afe48b4096bbc42e8df3bbc7 Mon Sep 17 00:00:00 2001
From: NingBo Wang <2536935847@qq.com>
Date: Sun, 13 Oct 2024 00:06:23 +0800
Subject: [PATCH 19/31] Update parachain staking (#1460)

* Fix staking collator snapshot to use total counted instead of total exposure(1719)

* deprecate delegator leave in favor of batch schedule revoke(1760)

* move Default config associated types to GenesisConfig(1798)

* Fix overflow for large round numbers(1817)

* Fix clippy
---
 node/service/src/chain_spec/bifrost_kusama.rs | 17 ++--
 pallets/buy-back/src/lib.rs                   |  4 +-
 pallets/parachain-staking/Cargo.toml          |  1 +
 pallets/parachain-staking/src/inflation.rs    | 26 ++++--
 pallets/parachain-staking/src/lib.rs          | 83 ++++++++++++-------
 pallets/parachain-staking/src/migrations.rs   | 12 ++-
 pallets/parachain-staking/src/mock.rs         |  6 +-
 pallets/parachain-staking/src/tests.rs        | 64 +++++++-------
 pallets/parachain-staking/src/types.rs        |  5 ++
 pallets/slp/src/mocks/mock.rs                 |  9 +-
 pallets/slp/src/mocks/mock_kusama.rs          |  9 +-
 runtime/bifrost-kusama/src/lib.rs             |  9 --
 12 files changed, 138 insertions(+), 107 deletions(-)

diff --git a/node/service/src/chain_spec/bifrost_kusama.rs b/node/service/src/chain_spec/bifrost_kusama.rs
index ba38b8ab7..4a307e7ea 100644
--- a/node/service/src/chain_spec/bifrost_kusama.rs
+++ b/node/service/src/chain_spec/bifrost_kusama.rs
@@ -18,13 +18,13 @@
 
 use crate::chain_spec::{get_account_id_from_seed, get_from_seed, RelayExtensions};
 use bifrost_kusama_runtime::{
-	constants::currency::DOLLARS, AccountId, Balance, BalancesConfig, BlockNumber,
-	DefaultBlocksPerRound, InflationInfo, Range, SS58Prefix, VestingConfig,
+	constants::currency::DOLLARS, AccountId, Balance, BalancesConfig, BlockNumber, InflationInfo,
+	Range, SS58Prefix, VestingConfig,
 };
 use bifrost_primitives::{
 	BifrostKusamaChainId, CurrencyId, CurrencyId::*, TokenInfo, TokenSymbol::*,
 };
-use bifrost_runtime_common::AuraId;
+use bifrost_runtime_common::{constants::time::HOURS, AuraId};
 use cumulus_primitives_core::ParaId;
 use frame_benchmarking::{account, whitelisted_caller};
 use hex_literal::hex;
@@ -33,7 +33,7 @@ use sc_service::ChainType;
 use serde::de::DeserializeOwned;
 use serde_json as json;
 use sp_core::{crypto::UncheckedInto, sr25519};
-use sp_runtime::{traits::Zero, Perbill};
+use sp_runtime::{traits::Zero, Perbill, Percent};
 use std::{
 	collections::BTreeMap,
 	fs::{read_dir, File},
@@ -50,6 +50,10 @@ pub fn ENDOWMENT() -> u128 {
 	1_000_000 * DOLLARS
 }
 
+const COLLATOR_COMMISSION: Perbill = Perbill::from_percent(10);
+const PARACHAIN_BOND_RESERVE_PERCENT: Percent = Percent::from_percent(0);
+const BLOCKS_PER_ROUND: u32 = 2 * HOURS;
+
 pub fn inflation_config() -> InflationInfo<Balance> {
 	fn to_round_inflation(annual: Range<Perbill>) -> Range<Perbill> {
 		use bifrost_parachain_staking::inflation::{
@@ -58,7 +62,7 @@ pub fn inflation_config() -> InflationInfo<Balance> {
 		perbill_annual_to_perbill_round(
 			annual,
 			// rounds per year
-			BLOCKS_PER_YEAR / DefaultBlocksPerRound::get(),
+			BLOCKS_PER_YEAR / BLOCKS_PER_ROUND,
 		)
 	}
 	let annual = Range {
@@ -171,6 +175,9 @@ pub fn bifrost_genesis(
 				.collect::<Vec<_>>(),
 			"delegations": delegations,
 			"inflationConfig": inflation_config(),
+			"collatorCommission": COLLATOR_COMMISSION,
+			"parachainBondReservePercent": PARACHAIN_BOND_RESERVE_PERCENT,
+			"blocksPerRound": BLOCKS_PER_ROUND,
 		},
 	})
 }
diff --git a/pallets/buy-back/src/lib.rs b/pallets/buy-back/src/lib.rs
index b3ea80623..f6668d663 100644
--- a/pallets/buy-back/src/lib.rs
+++ b/pallets/buy-back/src/lib.rs
@@ -270,6 +270,7 @@ pub mod pallet {
 							n.saturating_sub(info.last_buyback_cycle)
 								.saturated_into::<u32>()
 								.saturating_sub(One::one()) =>
+					{
 						if let Some(swap_out_min) = SwapOutMin::<T>::get(currency_id) {
 							if let Some(e) =
 								Self::buy_back(&buyback_address, currency_id, &info, swap_out_min)
@@ -295,7 +296,8 @@ pub mod pallet {
 							info.last_buyback = n;
 							Infos::<T>::insert(currency_id, info);
 							SwapOutMin::<T>::remove(currency_id);
-						},
+						}
+					},
 					_ => (),
 				}
 			}
diff --git a/pallets/parachain-staking/Cargo.toml b/pallets/parachain-staking/Cargo.toml
index c9a7d34b9..04aa346cd 100644
--- a/pallets/parachain-staking/Cargo.toml
+++ b/pallets/parachain-staking/Cargo.toml
@@ -46,6 +46,7 @@ std = [
 	"pallet-authorship/std",
 	"pallet-session/std",
 	"log/std",
+	"bifrost-primitives/std",
 ]
 runtime-benchmarks = ["frame-benchmarking"]
 try-runtime = ["frame-support/try-runtime"]
diff --git a/pallets/parachain-staking/src/inflation.rs b/pallets/parachain-staking/src/inflation.rs
index 53c2a465a..a01314375 100644
--- a/pallets/parachain-staking/src/inflation.rs
+++ b/pallets/parachain-staking/src/inflation.rs
@@ -20,10 +20,7 @@ use parity_scale_codec::{Decode, Encode, MaxEncodedLen};
 use scale_info::TypeInfo;
 use serde::{Deserialize, Serialize};
 use sp_runtime::{PerThing, Perbill, RuntimeDebug};
-use substrate_fixed::{
-	transcendental::pow as floatpow,
-	types::{I32F32, I64F64},
-};
+use substrate_fixed::{transcendental::pow as floatpow, types::I64F64};
 
 use crate::{
 	pallet::{BalanceOf, Config},
@@ -76,10 +73,10 @@ pub fn perbill_annual_to_perbill_round(
 	annual: Range<Perbill>,
 	rounds_per_year: u32,
 ) -> Range<Perbill> {
-	let exponent = I32F32::from_num(1) / I32F32::from_num(rounds_per_year);
+	let exponent = I64F64::from_num(1) / I64F64::from_num(rounds_per_year);
 	let annual_to_round = |annual: Perbill| -> Perbill {
-		let x = I32F32::from_num(annual.deconstruct()) / I32F32::from_num(Perbill::ACCURACY);
-		let y: I64F64 = floatpow(I32F32::from_num(1) + x, exponent)
+		let x = I64F64::from_num(annual.deconstruct()) / I64F64::from_num(Perbill::ACCURACY);
+		let y: I64F64 = floatpow(I64F64::from_num(1) + x, exponent)
 			.expect("Cannot overflow since rounds_per_year is u32 so worst case 0; QED");
 		Perbill::from_parts(
 			((y - I64F64::from_num(1)) * I64F64::from_num(Perbill::ACCURACY))
@@ -208,4 +205,19 @@ mod tests {
 			mock_round_issuance_range(10_000_000, mock_annual_to_round(schedule, 8766))
 		);
 	}
+
+	#[test]
+	fn inflation_does_not_panic_at_round_number_limit() {
+		let schedule = Range {
+			min: Perbill::from_percent(100),
+			ideal: Perbill::from_percent(100),
+			max: Perbill::from_percent(100),
+		};
+		mock_round_issuance_range(u32::MAX.into(), mock_annual_to_round(schedule, u32::MAX));
+		mock_round_issuance_range(u64::MAX.into(), mock_annual_to_round(schedule, u32::MAX));
+		mock_round_issuance_range(u128::MAX.into(), mock_annual_to_round(schedule, u32::MAX));
+		mock_round_issuance_range(u32::MAX.into(), mock_annual_to_round(schedule, 1));
+		mock_round_issuance_range(u64::MAX.into(), mock_annual_to_round(schedule, 1));
+		mock_round_issuance_range(u128::MAX.into(), mock_annual_to_round(schedule, 1));
+	}
 }
diff --git a/pallets/parachain-staking/src/lib.rs b/pallets/parachain-staking/src/lib.rs
index 3504f24f7..41a0e3cc0 100755
--- a/pallets/parachain-staking/src/lib.rs
+++ b/pallets/parachain-staking/src/lib.rs
@@ -131,9 +131,6 @@ pub mod pallet {
 		/// Minimum number of blocks per round
 		#[pallet::constant]
 		type MinBlocksPerRound: Get<u32>;
-		/// Default number of blocks per round at genesis
-		#[pallet::constant]
-		type DefaultBlocksPerRound: Get<u32>;
 		/// Number of rounds that candidates remain bonded before exit request is executable
 		#[pallet::constant]
 		type LeaveCandidatesDelay: Get<RoundIndex>;
@@ -164,12 +161,6 @@ pub mod pallet {
 		/// Maximum delegations per delegator
 		#[pallet::constant]
 		type MaxDelegationsPerDelegator: Get<u32>;
-		/// Default commission due to collators, is `CollatorCommission` storage value in genesis
-		#[pallet::constant]
-		type DefaultCollatorCommission: Get<Perbill>;
-		/// Default percent of inflation set aside for parachain bond account
-		#[pallet::constant]
-		type DefaultParachainBondReservePercent: Get<Percent>;
 		/// Minimum stake required for any candidate to be in `SelectedCandidates` for the round
 		#[pallet::constant]
 		type MinCollatorStk: Get<BalanceOf<Self>>;
@@ -591,18 +582,41 @@ pub mod pallet {
 	>;
 
 	#[pallet::genesis_config]
-	#[derive(frame_support::DefaultNoBound)]
 	pub struct GenesisConfig<T: Config> {
+		/// Initialize balance and register all as collators: `(collator AccountId, balance
+		/// Amount)`
 		pub candidates: Vec<(AccountIdOf<T>, BalanceOf<T>)>,
-		/// Vec of tuples of the format (delegator AccountId, collator AccountId, delegation
-		/// Amount)
+		/// Initialize balance and make delegations:
+		/// `(delegator AccountId, collator AccountId, delegation Amount, auto-compounding
+		/// Percent)`
 		pub delegations: Vec<(AccountIdOf<T>, AccountIdOf<T>, BalanceOf<T>)>,
+		/// Inflation configuration
 		pub inflation_config: InflationInfo<BalanceOf<T>>,
+		/// Default fixed percent a collator takes off the top of due rewards
+		pub collator_commission: Perbill,
+		/// Default percent of inflation set aside for parachain bond every round
+		pub parachain_bond_reserve_percent: Percent,
+		/// Default number of blocks in a round
+		pub blocks_per_round: u32,
+	}
+
+	impl<T: Config> Default for GenesisConfig<T> {
+		fn default() -> Self {
+			Self {
+				candidates: vec![],
+				delegations: vec![],
+				inflation_config: Default::default(),
+				collator_commission: Default::default(),
+				parachain_bond_reserve_percent: Default::default(),
+				blocks_per_round: 1u32,
+			}
+		}
 	}
 
 	#[pallet::genesis_build]
 	impl<T: Config> BuildGenesisConfig for GenesisConfig<T> {
 		fn build(&self) {
+			assert!(self.blocks_per_round > 0, "Blocks per round must be > 0");
 			<InflationConfig<T>>::put(self.inflation_config.clone());
 			let mut candidate_count = 0u32;
 			// Initialize the candidates
@@ -656,7 +670,7 @@ pub mod pallet {
 				}
 			}
 			// Set collator commission to default config
-			<CollatorCommission<T>>::put(T::DefaultCollatorCommission::get());
+			<CollatorCommission<T>>::put(self.collator_commission);
 			// Set parachain bond config to default config
 			<ParachainBondInfo<T>>::put(ParachainBondConfig {
 				// must be set soon; if not => due inflation will be sent to collators/delegators
@@ -664,7 +678,7 @@ pub mod pallet {
 					&mut sp_runtime::traits::TrailingZeroInput::zeroes(),
 				)
 				.expect("infinite length input; no invalid inputs for type; qed"),
-				percent: T::DefaultParachainBondReservePercent::get(),
+				percent: self.parachain_bond_reserve_percent,
 				payment_in_round: T::PaymentInRound::get(),
 			});
 			// Set total selected candidates to minimum config
@@ -673,7 +687,7 @@ pub mod pallet {
 			let (v_count, _, total_staked) = <Pallet<T>>::select_top_candidates(1u32);
 			// Start Round 1 at Block 0
 			let round: RoundInfo<BlockNumberFor<T>> =
-				RoundInfo::new(1u32, 0u32.into(), T::DefaultBlocksPerRound::get());
+				RoundInfo::new(1u32, 0u32.into(), self.blocks_per_round);
 			<Round<T>>::put(round);
 			// Snapshot total stake
 			<Staked<T>>::insert(1u32, <Total<T>>::get());
@@ -1134,18 +1148,21 @@ pub mod pallet {
 			)
 		}
 
-		#[pallet::call_index(18)]
-		#[pallet::weight(<T as Config>::WeightInfo::schedule_leave_delegators())]
+		/// DEPRECATED use batch util with schedule_revoke_delegation for all delegations
 		/// Request to leave the set of delegators. If successful, the caller is scheduled to be
 		/// allowed to exit via a [DelegationAction::Revoke] towards all existing delegations.
 		/// Success forbids future delegation requests until the request is invoked or cancelled.
+		#[pallet::call_index(18)]
+		#[pallet::weight(<T as Config>::WeightInfo::schedule_leave_delegators())]
 		pub fn schedule_leave_delegators(origin: OriginFor<T>) -> DispatchResultWithPostInfo {
 			let delegator = ensure_signed(origin)?;
 			Self::delegator_schedule_revoke_all(delegator)
 		}
+
+		/// DEPRECATED use batch util with execute_delegation_request for all delegations
+		/// Execute the right to exit the set of delegators and revoke all ongoing delegations.
 		#[pallet::call_index(19)]
 		#[pallet::weight(<T as Config>::WeightInfo::execute_leave_delegators(*delegation_count))]
-		/// Execute the right to exit the set of delegators and revoke all ongoing delegations.
 		pub fn execute_leave_delegators(
 			origin: OriginFor<T>,
 			delegator: AccountIdOf<T>,
@@ -1154,10 +1171,12 @@ pub mod pallet {
 			ensure_signed(origin)?;
 			Self::delegator_execute_scheduled_revoke_all(delegator, delegation_count)
 		}
-		#[pallet::call_index(20)]
-		#[pallet::weight(<T as Config>::WeightInfo::cancel_leave_delegators())]
+
+		/// DEPRECATED use batch util with cancel_delegation_request for all delegations
 		/// Cancel a pending request to exit the set of delegators. Success clears the pending exit
 		/// request (thereby resetting the delay upon another `leave_delegators` call).
+		#[pallet::call_index(20)]
+		#[pallet::weight(<T as Config>::WeightInfo::cancel_leave_delegators())]
 		pub fn cancel_leave_delegators(origin: OriginFor<T>) -> DispatchResultWithPostInfo {
 			let delegator = ensure_signed(origin)?;
 			Self::delegator_cancel_scheduled_revoke_all(delegator)
@@ -1710,19 +1729,21 @@ pub mod pallet {
 				collator_count = collator_count.saturating_add(1u32);
 				delegation_count = delegation_count.saturating_add(state.delegation_count);
 				total = total.saturating_add(state.total_counted);
-				let snapshot_total = state.total_counted;
-				let top_rewardable_delegations = Self::get_rewardable_delegators(account);
+
+				let CountedDelegations { uncounted_stake, rewardable_delegations } =
+					Self::get_rewardable_delegators(&account);
+				let total_counted = state.total_counted.saturating_sub(uncounted_stake);
 
 				let snapshot = CollatorSnapshot {
 					bond: state.bond,
-					delegations: top_rewardable_delegations,
-					total: state.total_counted,
+					delegations: rewardable_delegations,
+					total: total_counted,
 				};
 				<AtStake<T>>::insert(now, account, snapshot);
 				Self::deposit_event(Event::CollatorChosen {
 					round: now,
 					collator_account: account.clone(),
-					total_exposed_amount: snapshot_total,
+					total_exposed_amount: state.total_counted,
 				});
 			}
 			// insert canonical collator set
@@ -1739,15 +1760,14 @@ pub mod pallet {
 		/// - else, do nothing
 		///
 		/// The intended bond amounts will be used while calculating rewards.
-		fn get_rewardable_delegators(
-			collator: &AccountIdOf<T>,
-		) -> Vec<Bond<AccountIdOf<T>, BalanceOf<T>>> {
+		fn get_rewardable_delegators(collator: &AccountIdOf<T>) -> CountedDelegations<T> {
 			let requests = <DelegationScheduledRequests<T>>::get(collator)
 				.into_iter()
 				.map(|x| (x.delegator, x.action))
 				.collect::<BTreeMap<_, _>>();
 
-			<TopDelegations<T>>::get(collator)
+			let mut uncounted_stake = BalanceOf::<T>::zero();
+			let rewardable_delegations = <TopDelegations<T>>::get(collator)
 				.expect("all members of CandidateQ must be candidates")
 				.delegations
 				.into_iter()
@@ -1760,6 +1780,7 @@ pub mod pallet {
 								revoke request",
 								bond.owner
 							);
+							uncounted_stake = uncounted_stake.saturating_add(bond.amount);
 							BalanceOf::<T>::zero()
 						},
 						Some(DelegationAction::Decrease(amount)) => {
@@ -1768,13 +1789,15 @@ pub mod pallet {
 								decrease request",
 								bond.owner
 							);
+							uncounted_stake = uncounted_stake.saturating_add(*amount);
 							bond.amount.saturating_sub(*amount)
 						},
 					};
 
 					bond
 				})
-				.collect()
+				.collect();
+			CountedDelegations { uncounted_stake, rewardable_delegations }
 		}
 
 		/// Temporary JIT migration of a single delegator's reserve -> lock. This will query
diff --git a/pallets/parachain-staking/src/migrations.rs b/pallets/parachain-staking/src/migrations.rs
index 21d43b070..4fbfb1bd9 100644
--- a/pallets/parachain-staking/src/migrations.rs
+++ b/pallets/parachain-staking/src/migrations.rs
@@ -36,7 +36,7 @@ use frame_system::pallet_prelude::BlockNumberFor;
 use scale_info::prelude::string::String;
 use sp_runtime::{
 	traits::{AccountIdConversion, Saturating, Zero},
-	Perbill, TryRuntimeError,
+	Perbill, Percent, TryRuntimeError,
 };
 use sp_std::{convert::TryInto, vec::Vec};
 
@@ -53,6 +53,10 @@ use crate::{
 	RoundInfo, Staked, TopDelegations, TotalSelected,
 };
 
+const COLLATOR_COMMISSION: Perbill = Perbill::from_percent(10);
+const PARACHAIN_BOND_RESERVE_PERCENT: Percent = Percent::from_percent(0);
+const BLOCKS_PER_ROUND: u32 = 2 * 300;
+
 /// Migration to purge staking storage bloat for `Points` and `AtStake` storage items
 pub struct InitGenesisMigration<T>(PhantomData<T>);
 impl<T: Config> OnRuntimeUpgrade for InitGenesisMigration<T> {
@@ -97,12 +101,12 @@ impl<T: Config> OnRuntimeUpgrade for InitGenesisMigration<T> {
 			}
 		}
 		// Set collator commission to default config
-		<CollatorCommission<T>>::put(T::DefaultCollatorCommission::get());
+		<CollatorCommission<T>>::put(COLLATOR_COMMISSION);
 		// Set parachain bond config to default config
 		<ParachainBondInfo<T>>::put(ParachainBondConfig {
 			// must be set soon; if not => due inflation will be sent to collators/delegators
 			account: T::PalletId::get().into_account_truncating(),
-			percent: T::DefaultParachainBondReservePercent::get(),
+			percent: PARACHAIN_BOND_RESERVE_PERCENT,
 			payment_in_round: T::PaymentInRound::get(),
 		});
 		// Set total selected candidates to minimum config
@@ -111,7 +115,7 @@ impl<T: Config> OnRuntimeUpgrade for InitGenesisMigration<T> {
 		<Pallet<T>>::select_top_candidates(1u32);
 		// Start Round 1 at Block 0
 		let round: RoundInfo<BlockNumberFor<T>> =
-			RoundInfo::new(1u32, 0u32.into(), T::DefaultBlocksPerRound::get());
+			RoundInfo::new(1u32, 0u32.into(), BLOCKS_PER_ROUND);
 		<Round<T>>::put(round);
 		// Snapshot total stake
 		<Staked<T>>::insert(1u32, <Total<T>>::get());
diff --git a/pallets/parachain-staking/src/mock.rs b/pallets/parachain-staking/src/mock.rs
index 45acfb13b..72235e155 100644
--- a/pallets/parachain-staking/src/mock.rs
+++ b/pallets/parachain-staking/src/mock.rs
@@ -106,7 +106,6 @@ impl Config for Test {
 	type Currency = Balances;
 	type MonetaryGovernanceOrigin = frame_system::EnsureRoot<AccountId>;
 	type MinBlocksPerRound = MinBlocksPerRound;
-	type DefaultBlocksPerRound = DefaultBlocksPerRound;
 	type LeaveCandidatesDelay = LeaveCandidatesDelay;
 	type CandidateBondLessDelay = CandidateBondLessDelay;
 	type LeaveDelegatorsDelay = LeaveDelegatorsDelay;
@@ -117,8 +116,6 @@ impl Config for Test {
 	type MaxTopDelegationsPerCandidate = MaxTopDelegationsPerCandidate;
 	type MaxBottomDelegationsPerCandidate = MaxBottomDelegationsPerCandidate;
 	type MaxDelegationsPerDelegator = MaxDelegationsPerDelegator;
-	type DefaultCollatorCommission = DefaultCollatorCommission;
-	type DefaultParachainBondReservePercent = DefaultParachainBondReservePercent;
 	type MinCollatorStk = MinCollatorStk;
 	type MinCandidateStk = MinCollatorStk;
 	type MinDelegatorStk = MinDelegatorStk;
@@ -206,6 +203,9 @@ impl ExtBuilder {
 			candidates: self.collators,
 			delegations: self.delegations,
 			inflation_config: self.inflation,
+			collator_commission: DefaultCollatorCommission::get(),
+			parachain_bond_reserve_percent: DefaultParachainBondReservePercent::get(),
+			blocks_per_round: DefaultBlocksPerRound::get(),
 		}
 		.assimilate_storage(&mut t)
 		.expect("Parachain Staking's storage can be assimilated");
diff --git a/pallets/parachain-staking/src/tests.rs b/pallets/parachain-staking/src/tests.rs
index 0ed9682ff..c7b5ff82f 100644
--- a/pallets/parachain-staking/src/tests.rs
+++ b/pallets/parachain-staking/src/tests.rs
@@ -3490,9 +3490,9 @@ fn parachain_bond_inflation_reserve_matches_config() {
 					selected_collators_number: 5,
 					total_balance: 130,
 				},
-				Event::Rewarded { account: 1, rewards: 24 },
-				Event::Rewarded { account: 7, rewards: 6 },
-				Event::Rewarded { account: 10, rewards: 6 },
+				Event::Rewarded { account: 1, rewards: 26 },
+				Event::Rewarded { account: 7, rewards: 7 },
+				Event::Rewarded { account: 10, rewards: 7 },
 			];
 			expected.append(&mut new2);
 			assert_eq_events!(expected.clone());
@@ -3522,9 +3522,9 @@ fn parachain_bond_inflation_reserve_matches_config() {
 					selected_collators_number: 5,
 					total_balance: 130,
 				},
-				Event::Rewarded { account: 1, rewards: 20 },
-				Event::Rewarded { account: 7, rewards: 4 },
-				Event::Rewarded { account: 10, rewards: 4 },
+				Event::Rewarded { account: 1, rewards: 21 },
+				Event::Rewarded { account: 7, rewards: 5 },
+				Event::Rewarded { account: 10, rewards: 5 },
 			];
 			expected.append(&mut new3);
 			assert_eq_events!(expected.clone());
@@ -3533,7 +3533,7 @@ fn parachain_bond_inflation_reserve_matches_config() {
 			roll_to(40);
 			// no more paying 6
 			let mut new4 = vec![
-				Event::ReservedForParachainBond { account: 11, value: 31 },
+				Event::ReservedForParachainBond { account: 11, value: 32 },
 				Event::CollatorChosen { round: 9, collator_account: 1, total_exposed_amount: 40 },
 				Event::CollatorChosen { round: 9, collator_account: 2, total_exposed_amount: 40 },
 				Event::CollatorChosen { round: 9, collator_account: 3, total_exposed_amount: 20 },
@@ -3551,7 +3551,7 @@ fn parachain_bond_inflation_reserve_matches_config() {
 			];
 			expected.append(&mut new4);
 			assert_eq_events!(expected.clone());
-			assert_eq!(Balances::free_balance(&11), 126);
+			assert_eq!(Balances::free_balance(&11), 127);
 			set_author(8, 1, 100);
 			assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(8), 1, 10, 10, 10));
 			roll_to(45);
@@ -3581,7 +3581,7 @@ fn parachain_bond_inflation_reserve_matches_config() {
 			];
 			expected.append(&mut new5);
 			assert_eq_events!(expected.clone());
-			assert_eq!(Balances::free_balance(&11), 159);
+			assert_eq!(Balances::free_balance(&11), 160);
 			set_author(9, 1, 100);
 			set_author(10, 1, 100);
 			roll_to(50);
@@ -3605,11 +3605,11 @@ fn parachain_bond_inflation_reserve_matches_config() {
 			];
 			expected.append(&mut new6);
 			assert_eq_events!(expected.clone());
-			assert_eq!(Balances::free_balance(&11), 194);
+			assert_eq!(Balances::free_balance(&11), 195);
 			roll_to(55);
 			// new delegation is rewarded, 2 rounds after joining (`RewardPaymentDelay` is 2)
 			let mut new7 = vec![
-				Event::ReservedForParachainBond { account: 11, value: 36 },
+				Event::ReservedForParachainBond { account: 11, value: 37 },
 				Event::CollatorChosen { round: 12, collator_account: 1, total_exposed_amount: 50 },
 				Event::CollatorChosen { round: 12, collator_account: 2, total_exposed_amount: 40 },
 				Event::CollatorChosen { round: 12, collator_account: 3, total_exposed_amount: 20 },
@@ -3628,7 +3628,7 @@ fn parachain_bond_inflation_reserve_matches_config() {
 			];
 			expected.append(&mut new7);
 			assert_eq_events!(expected);
-			assert_eq!(Balances::free_balance(&11), 230);
+			assert_eq!(Balances::free_balance(&11), 232);
 		});
 }
 
@@ -4407,9 +4407,9 @@ fn payouts_follow_delegation_changes() {
 					selected_collators_number: 5,
 					total_balance: 130,
 				},
-				Event::Rewarded { account: 1, rewards: 30 },
-				Event::Rewarded { account: 7, rewards: 9 },
-				Event::Rewarded { account: 10, rewards: 9 },
+				Event::Rewarded { account: 1, rewards: 35 },
+				Event::Rewarded { account: 7, rewards: 11 },
+				Event::Rewarded { account: 10, rewards: 11 },
 				Event::CollatorChosen { round: 8, collator_account: 1, total_exposed_amount: 40 },
 				Event::CollatorChosen { round: 8, collator_account: 2, total_exposed_amount: 40 },
 				Event::CollatorChosen { round: 8, collator_account: 3, total_exposed_amount: 20 },
@@ -4421,9 +4421,9 @@ fn payouts_follow_delegation_changes() {
 					selected_collators_number: 5,
 					total_balance: 130,
 				},
-				Event::Rewarded { account: 1, rewards: 31 },
-				Event::Rewarded { account: 7, rewards: 10 },
-				Event::Rewarded { account: 10, rewards: 10 },
+				Event::Rewarded { account: 1, rewards: 36 },
+				Event::Rewarded { account: 7, rewards: 12 },
+				Event::Rewarded { account: 10, rewards: 12 },
 			];
 			expected.append(&mut new3);
 			assert_eq_events!(expected.clone());
@@ -4443,8 +4443,8 @@ fn payouts_follow_delegation_changes() {
 					total_balance: 130,
 				},
 				Event::Rewarded { account: 1, rewards: 38 },
-				Event::Rewarded { account: 7, rewards: 12 },
-				Event::Rewarded { account: 10, rewards: 12 },
+				Event::Rewarded { account: 7, rewards: 13 },
+				Event::Rewarded { account: 10, rewards: 13 },
 			];
 			expected.append(&mut new4);
 			assert_eq_events!(expected.clone());
@@ -4470,7 +4470,7 @@ fn payouts_follow_delegation_changes() {
 					selected_collators_number: 5,
 					total_balance: 140,
 				},
-				Event::Rewarded { account: 1, rewards: 39 },
+				Event::Rewarded { account: 1, rewards: 40 },
 				Event::Rewarded { account: 7, rewards: 13 },
 				Event::Rewarded { account: 10, rewards: 13 },
 			];
@@ -4491,7 +4491,7 @@ fn payouts_follow_delegation_changes() {
 					selected_collators_number: 5,
 					total_balance: 140,
 				},
-				Event::Rewarded { account: 1, rewards: 41 },
+				Event::Rewarded { account: 1, rewards: 42 },
 				Event::Rewarded { account: 7, rewards: 14 },
 				Event::Rewarded { account: 10, rewards: 14 },
 			];
@@ -4512,7 +4512,7 @@ fn payouts_follow_delegation_changes() {
 					selected_collators_number: 5,
 					total_balance: 140,
 				},
-				Event::Rewarded { account: 1, rewards: 38 },
+				Event::Rewarded { account: 1, rewards: 39 },
 				Event::Rewarded { account: 7, rewards: 12 },
 				Event::Rewarded { account: 10, rewards: 12 },
 				Event::Rewarded { account: 8, rewards: 12 },
@@ -5586,7 +5586,7 @@ fn test_delegator_scheduled_for_revoke_is_rewarded_for_previous_rounds_but_not_f
 
 			roll_to_round_begin(4);
 			assert_eq_last_events!(
-				vec![Event::<Test>::Rewarded { account: 1, rewards: 4 }],
+				vec![Event::<Test>::Rewarded { account: 1, rewards: 5 }],
 				"delegator was rewarded unexpectedly"
 			);
 			let collator_snapshot = AtStake::<Test>::get(Round::<Test>::get().current, 1);
@@ -5596,7 +5596,7 @@ fn test_delegator_scheduled_for_revoke_is_rewarded_for_previous_rounds_but_not_f
 				"collator snapshot's delegator count was reduced unexpectedly"
 			);
 			assert_eq!(
-				30, collator_snapshot.total,
+				20, collator_snapshot.total,
 				"collator snapshot's total was reduced unexpectedly",
 			);
 		});
@@ -5632,7 +5632,7 @@ fn test_delegator_scheduled_for_revoke_is_rewarded_when_request_cancelled() {
 
 			roll_to_round_begin(4);
 			assert_eq_last_events!(
-				vec![Event::<Test>::Rewarded { account: 1, rewards: 4 }],
+				vec![Event::<Test>::Rewarded { account: 1, rewards: 5 }],
 				"delegator was rewarded unexpectedly",
 			);
 			let collator_snapshot = AtStake::<Test>::get(Round::<Test>::get().current, 1);
@@ -5699,7 +5699,7 @@ fn test_delegator_scheduled_for_bond_decrease_is_rewarded_for_previous_rounds_bu
 			roll_to_round_begin(4);
 			assert_eq_last_events!(
 				vec![
-					Event::<Test>::Rewarded { account: 1, rewards: 3 },
+					Event::<Test>::Rewarded { account: 1, rewards: 4 },
 					Event::<Test>::Rewarded { account: 2, rewards: 1 },
 				],
 				"delegator was rewarded unexpectedly"
@@ -5711,7 +5711,7 @@ fn test_delegator_scheduled_for_bond_decrease_is_rewarded_for_previous_rounds_bu
 				"collator snapshot's delegator count was reduced unexpectedly"
 			);
 			assert_eq!(
-				40, collator_snapshot.total,
+				30, collator_snapshot.total,
 				"collator snapshot's total was reduced unexpectedly",
 			);
 		});
@@ -5752,7 +5752,7 @@ fn test_delegator_scheduled_for_bond_decrease_is_rewarded_when_request_cancelled
 			roll_to_round_begin(4);
 			assert_eq_last_events!(
 				vec![
-					Event::<Test>::Rewarded { account: 1, rewards: 3 },
+					Event::<Test>::Rewarded { account: 1, rewards: 4 },
 					Event::<Test>::Rewarded { account: 2, rewards: 1 },
 				],
 				"delegator was rewarded unexpectedly",
@@ -5814,7 +5814,7 @@ fn test_delegator_scheduled_for_leave_is_rewarded_for_previous_rounds_but_not_fo
 
 			roll_to_round_begin(4);
 			assert_eq_last_events!(
-				vec![Event::<Test>::Rewarded { account: 1, rewards: 4 },],
+				vec![Event::<Test>::Rewarded { account: 1, rewards: 5 },],
 				"delegator was rewarded unexpectedly"
 			);
 			let collator_snapshot = AtStake::<Test>::get(Round::<Test>::get().current, 1);
@@ -5824,7 +5824,7 @@ fn test_delegator_scheduled_for_leave_is_rewarded_for_previous_rounds_but_not_fo
 				"collator snapshot's delegator count was reduced unexpectedly"
 			);
 			assert_eq!(
-				30, collator_snapshot.total,
+				20, collator_snapshot.total,
 				"collator snapshot's total was reduced unexpectedly",
 			);
 		});
@@ -5859,7 +5859,7 @@ fn test_delegator_scheduled_for_leave_is_rewarded_when_request_cancelled() {
 
 			roll_to_round_begin(4);
 			assert_eq_last_events!(
-				vec![Event::<Test>::Rewarded { account: 1, rewards: 4 },],
+				vec![Event::<Test>::Rewarded { account: 1, rewards: 5 },],
 				"delegator was rewarded unexpectedly",
 			);
 			let collator_snapshot = AtStake::<Test>::get(Round::<Test>::get().current, 1);
diff --git a/pallets/parachain-staking/src/types.rs b/pallets/parachain-staking/src/types.rs
index e7b933f57..c8c2b1802 100644
--- a/pallets/parachain-staking/src/types.rs
+++ b/pallets/parachain-staking/src/types.rs
@@ -34,6 +34,11 @@ use crate::{
 	COLLATOR_LOCK_ID, DELEGATOR_LOCK_ID,
 };
 
+pub struct CountedDelegations<T: Config> {
+	pub uncounted_stake: BalanceOf<T>,
+	pub rewardable_delegations: Vec<Bond<T::AccountId, BalanceOf<T>>>,
+}
+
 #[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)]
 pub struct Bond<AccountId, Balance> {
 	pub owner: AccountId,
diff --git a/pallets/slp/src/mocks/mock.rs b/pallets/slp/src/mocks/mock.rs
index 4495ad6be..47a728994 100644
--- a/pallets/slp/src/mocks/mock.rs
+++ b/pallets/slp/src/mocks/mock.rs
@@ -41,10 +41,9 @@ use frame_system::{EnsureRoot, EnsureSignedBy};
 use orml_traits::{location::RelativeReserveProvider, parameter_type_with_key};
 use parity_scale_codec::{Decode, Encode};
 use sp_core::{bounded::BoundedVec, hashing::blake2_256, ConstU32};
-pub use sp_runtime::Perbill;
 use sp_runtime::{
 	traits::{AccountIdConversion, Convert, IdentityLookup, TrailingZeroInput},
-	AccountId32, BuildStorage, Percent,
+	AccountId32, BuildStorage,
 };
 use sp_std::{boxed::Box, vec::Vec};
 use xcm::v3::{prelude::*, MultiLocation, Weight};
@@ -216,7 +215,6 @@ impl bifrost_vtoken_minting::Config for Runtime {
 
 parameter_types! {
 	pub const MinBlocksPerRound: u32 = 3;
-	pub const DefaultBlocksPerRound: u32 = 5;
 	pub const LeaveCandidatesDelay: u32 = 2;
 	pub const CandidateBondLessDelay: u32 = 2;
 	pub const LeaveDelegatorsDelay: u32 = 2;
@@ -227,8 +225,6 @@ parameter_types! {
 	pub const MaxTopDelegationsPerCandidate: u32 = 4;
 	pub const MaxBottomDelegationsPerCandidate: u32 = 4;
 	pub const MaxDelegationsPerDelegator: u32 = 4;
-	pub const DefaultCollatorCommission: Perbill = Perbill::from_percent(20);
-	pub const DefaultParachainBondReservePercent: Percent = Percent::from_percent(30);
 	pub const MinCollatorStk: u128 = 10;
 	pub const MinDelegatorStk: u128 = 5;
 	pub const MinDelegation: u128 = 3;
@@ -242,7 +238,6 @@ impl bifrost_parachain_staking::Config for Runtime {
 	type Currency = Balances;
 	type MonetaryGovernanceOrigin = frame_system::EnsureRoot<AccountId>;
 	type MinBlocksPerRound = MinBlocksPerRound;
-	type DefaultBlocksPerRound = DefaultBlocksPerRound;
 	type LeaveCandidatesDelay = LeaveCandidatesDelay;
 	type CandidateBondLessDelay = CandidateBondLessDelay;
 	type LeaveDelegatorsDelay = LeaveDelegatorsDelay;
@@ -253,8 +248,6 @@ impl bifrost_parachain_staking::Config for Runtime {
 	type MaxTopDelegationsPerCandidate = MaxTopDelegationsPerCandidate;
 	type MaxBottomDelegationsPerCandidate = MaxBottomDelegationsPerCandidate;
 	type MaxDelegationsPerDelegator = MaxDelegationsPerDelegator;
-	type DefaultCollatorCommission = DefaultCollatorCommission;
-	type DefaultParachainBondReservePercent = DefaultParachainBondReservePercent;
 	type MinCollatorStk = MinCollatorStk;
 	type MinCandidateStk = MinCollatorStk;
 	type MinDelegatorStk = MinDelegatorStk;
diff --git a/pallets/slp/src/mocks/mock_kusama.rs b/pallets/slp/src/mocks/mock_kusama.rs
index adb01aa24..141e0c1b8 100644
--- a/pallets/slp/src/mocks/mock_kusama.rs
+++ b/pallets/slp/src/mocks/mock_kusama.rs
@@ -43,10 +43,9 @@ use hex_literal::hex;
 use orml_traits::{location::RelativeReserveProvider, parameter_type_with_key};
 use parity_scale_codec::{Decode, Encode};
 use sp_core::{bounded::BoundedVec, hashing::blake2_256};
-pub use sp_runtime::Perbill;
 use sp_runtime::{
 	traits::{AccountIdConversion, Convert, TrailingZeroInput},
-	AccountId32, BuildStorage, Percent,
+	AccountId32, BuildStorage,
 };
 use sp_std::{boxed::Box, vec::Vec};
 use xcm::v3::{prelude::*, Weight};
@@ -272,7 +271,6 @@ impl bifrost_vtoken_minting::Config for Runtime {
 
 parameter_types! {
 	pub const MinBlocksPerRound: u32 = 3;
-	pub const DefaultBlocksPerRound: u32 = 5;
 	pub const LeaveCandidatesDelay: u32 = 2;
 	pub const CandidateBondLessDelay: u32 = 2;
 	pub const LeaveDelegatorsDelay: u32 = 2;
@@ -283,8 +281,6 @@ parameter_types! {
 	pub const MaxTopDelegationsPerCandidate: u32 = 4;
 	pub const MaxBottomDelegationsPerCandidate: u32 = 4;
 	pub const MaxDelegationsPerDelegator: u32 = 4;
-	pub const DefaultCollatorCommission: Perbill = Perbill::from_percent(20);
-	pub const DefaultParachainBondReservePercent: Percent = Percent::from_percent(30);
 	pub const MinCollatorStk: u128 = 10;
 	pub const MinDelegatorStk: u128 = 5;
 	pub const MinDelegation: u128 = 3;
@@ -298,7 +294,6 @@ impl bifrost_parachain_staking::Config for Runtime {
 	type Currency = Balances;
 	type MonetaryGovernanceOrigin = frame_system::EnsureRoot<AccountId>;
 	type MinBlocksPerRound = MinBlocksPerRound;
-	type DefaultBlocksPerRound = DefaultBlocksPerRound;
 	type LeaveCandidatesDelay = LeaveCandidatesDelay;
 	type CandidateBondLessDelay = CandidateBondLessDelay;
 	type LeaveDelegatorsDelay = LeaveDelegatorsDelay;
@@ -309,8 +304,6 @@ impl bifrost_parachain_staking::Config for Runtime {
 	type MaxTopDelegationsPerCandidate = MaxTopDelegationsPerCandidate;
 	type MaxBottomDelegationsPerCandidate = MaxBottomDelegationsPerCandidate;
 	type MaxDelegationsPerDelegator = MaxDelegationsPerDelegator;
-	type DefaultCollatorCommission = DefaultCollatorCommission;
-	type DefaultParachainBondReservePercent = DefaultParachainBondReservePercent;
 	type MinCollatorStk = MinCollatorStk;
 	type MinCandidateStk = MinCollatorStk;
 	type MinDelegatorStk = MinDelegatorStk;
diff --git a/runtime/bifrost-kusama/src/lib.rs b/runtime/bifrost-kusama/src/lib.rs
index b25e34213..d697fe916 100644
--- a/runtime/bifrost-kusama/src/lib.rs
+++ b/runtime/bifrost-kusama/src/lib.rs
@@ -878,8 +878,6 @@ impl cumulus_pallet_aura_ext::Config for Runtime {}
 parameter_types! {
 	/// Minimum round length is 2 minutes (10 * 12 second block times)
 	pub const MinBlocksPerRound: u32 = 10;
-	/// Blocks per round
-	pub const DefaultBlocksPerRound: u32 = prod_or_fast!(2 * HOURS, 10);
 	/// Rounds before the collator leaving the candidates request can be executed
 	pub const LeaveCandidatesDelay: u32 = 84;
 	/// Rounds before the candidate bond increase/decrease can be executed
@@ -900,10 +898,6 @@ parameter_types! {
 	pub const MaxBottomDelegationsPerCandidate: u32 = 50;
 	/// Maximum delegations per delegator
 	pub const MaxDelegationsPerDelegator: u32 = 100;
-	/// Default fixed percent a collator takes off the top of due rewards
-	pub const DefaultCollatorCommission: Perbill = Perbill::from_percent(10);
-	/// Default percent of inflation set aside for parachain bond every round
-	pub const DefaultParachainBondReservePercent: Percent = Percent::from_percent(0);
 	/// Minimum stake required to become a collator
 	pub MinCollatorStk: u128 = 5000 * BNCS;
 	/// Minimum stake required to be reserved to be a candidate
@@ -928,7 +922,6 @@ impl bifrost_parachain_staking::Config for Runtime {
 	type Currency = Balances;
 	type MonetaryGovernanceOrigin = TechAdminOrCouncil;
 	type MinBlocksPerRound = MinBlocksPerRound;
-	type DefaultBlocksPerRound = DefaultBlocksPerRound;
 	type LeaveCandidatesDelay = LeaveCandidatesDelay;
 	type CandidateBondLessDelay = CandidateBondLessDelay;
 	type LeaveDelegatorsDelay = LeaveDelegatorsDelay;
@@ -939,8 +932,6 @@ impl bifrost_parachain_staking::Config for Runtime {
 	type MaxTopDelegationsPerCandidate = MaxTopDelegationsPerCandidate;
 	type MaxBottomDelegationsPerCandidate = MaxBottomDelegationsPerCandidate;
 	type MaxDelegationsPerDelegator = MaxDelegationsPerDelegator;
-	type DefaultCollatorCommission = DefaultCollatorCommission;
-	type DefaultParachainBondReservePercent = DefaultParachainBondReservePercent;
 	type MinCollatorStk = MinCollatorStk;
 	type MinCandidateStk = MinCandidateStk;
 	type MinDelegation = MinDelegatorStk;

From c6f72d51ec793b7df98a1166ff3b554bf541d80c Mon Sep 17 00:00:00 2001
From: SunTiebing <87381708+SunTiebing@users.noreply.github.com>
Date: Tue, 15 Oct 2024 09:56:34 +0800
Subject: [PATCH 20/31] Optimize system-staking pallet. (#1461)

* Optimize system-staking pallet.

* change unwrap_or_default to unwrap
---
 pallets/system-staking/src/benchmarking.rs   |  16 +-
 pallets/system-staking/src/lib.rs            | 138 +++++++++++----
 pallets/system-staking/src/migrations/mod.rs |  19 +++
 pallets/system-staking/src/migrations/v1.rs  | 130 ++++++++++++++
 pallets/system-staking/src/mock.rs           |   5 +-
 pallets/system-staking/src/tests.rs          | 169 ++++++++++++++++++-
 pallets/system-staking/src/types.rs          |  76 ++++++---
 runtime/bifrost-kusama/src/lib.rs            |   1 +
 runtime/bifrost-polkadot/src/lib.rs          |   1 +
 9 files changed, 492 insertions(+), 63 deletions(-)
 create mode 100644 pallets/system-staking/src/migrations/mod.rs
 create mode 100644 pallets/system-staking/src/migrations/v1.rs

diff --git a/pallets/system-staking/src/benchmarking.rs b/pallets/system-staking/src/benchmarking.rs
index ab8dc86c4..d40ef8b1a 100644
--- a/pallets/system-staking/src/benchmarking.rs
+++ b/pallets/system-staking/src/benchmarking.rs
@@ -35,7 +35,7 @@ benchmarks! {
 		assert_ok!(SystemStaking::<T>::token_config(
 			RawOrigin::Root.into(),
 			KSM,
-			Some(1),
+			Some(BlockNumberFor::<T>::from(1u32)),
 			Some(Permill::from_percent(80)),
 			Some(false),
 			Some(BalanceOf::<T>::unique_saturated_from(1000u128)),
@@ -45,7 +45,7 @@ benchmarks! {
 		assert_ok!(SystemStaking::<T>::token_config(
 			RawOrigin::Root.into(),
 			MOVR,
-			Some(2),
+			Some(BlockNumberFor::<T>::from(2u32)),
 			Some(Permill::from_percent(80)),
 			Some(false),
 			Some(BalanceOf::<T>::unique_saturated_from(1000u128)),
@@ -66,14 +66,14 @@ benchmarks! {
 		const KSM: CurrencyId = CurrencyId::Token(TokenSymbol::KSM);
 		let token_amount = BalanceOf::<T>::unique_saturated_from(1000u128);
 		let pool_id = PoolId::from(1u32);
-	}: _(RawOrigin::Root, KSM, Some(1), Some(Permill::from_percent(80)),Some(false),Some(token_amount),Some(vec![pool_id]),Some(vec![Perbill::from_percent(100)]))
+	}: _(RawOrigin::Root, KSM, Some(BlockNumberFor::<T>::from(1u32)), Some(Permill::from_percent(80)),Some(false),Some(token_amount),Some(vec![pool_id]),Some(vec![Perbill::from_percent(100)]))
 
 	refresh_token_info {
 		const KSM: CurrencyId = CurrencyId::Token(TokenSymbol::KSM);
 		assert_ok!(SystemStaking::<T>::token_config(
 			RawOrigin::Root.into(),
 			KSM,
-			Some(1),
+			Some(BlockNumberFor::<T>::from(1u32)),
 			Some(Permill::from_percent(80)),
 			Some(false),
 			Some(BalanceOf::<T>::unique_saturated_from(1000u128)),
@@ -87,7 +87,7 @@ benchmarks! {
 		assert_ok!(SystemStaking::<T>::token_config(
 			RawOrigin::Root.into(),
 			KSM,
-			Some(1),
+			Some(BlockNumberFor::<T>::from(1u32)),
 			Some(Permill::from_percent(80)),
 			Some(false),
 			Some(BalanceOf::<T>::unique_saturated_from(1000u128)),
@@ -104,7 +104,7 @@ benchmarks! {
 		assert_ok!(SystemStaking::<T>::token_config(
 			RawOrigin::Root.into(),
 			KSM,
-			Some(1),
+			Some(BlockNumberFor::<T>::from(1u32)),
 			Some(Permill::from_percent(80)),
 			Some(false),
 			Some(BalanceOf::<T>::unique_saturated_from(1000u128)),
@@ -120,7 +120,7 @@ benchmarks! {
 		assert_ok!(SystemStaking::<T>::token_config(
 			RawOrigin::Root.into(),
 			KSM,
-			Some(1),
+			Some(BlockNumberFor::<T>::from(1u32)),
 			Some(Permill::from_percent(80)),
 			Some(false),
 			Some(BalanceOf::<T>::unique_saturated_from(1000u128)),
@@ -137,7 +137,7 @@ benchmarks! {
 		assert_ok!(SystemStaking::<T>::token_config(
 			RawOrigin::Root.into(),
 			KSM,
-			Some(1),
+			Some(BlockNumberFor::<T>::from(1u32)),
 			Some(Permill::from_percent(80)),
 			Some(false),
 			Some(BalanceOf::<T>::unique_saturated_from(1000u128)),
diff --git a/pallets/system-staking/src/lib.rs b/pallets/system-staking/src/lib.rs
index a496f8e4e..5a7cbd392 100644
--- a/pallets/system-staking/src/lib.rs
+++ b/pallets/system-staking/src/lib.rs
@@ -23,6 +23,7 @@ pub use weights::WeightInfo;
 use bifrost_primitives::{CurrencyId, FarmingInfo, PoolId, VtokenMintingInterface};
 pub use frame_support::weights::Weight;
 use frame_support::{dispatch::DispatchResultWithPostInfo, traits::Get, PalletId};
+use frame_system::pallet_prelude::BlockNumberFor;
 use orml_traits::MultiCurrency;
 pub use pallet::*;
 use sp_runtime::{
@@ -41,6 +42,8 @@ mod tests;
 #[cfg(feature = "runtime-benchmarks")]
 mod benchmarking;
 
+pub mod migrations;
+
 pub type AccountIdOf<T> = <T as frame_system::Config>::AccountId;
 
 pub type CurrencyIdOf<T> = <<T as Config>::MultiCurrency as MultiCurrency<
@@ -98,13 +101,18 @@ pub mod pallet {
 		#[pallet::constant]
 		type PalletId: Get<PalletId>;
 
-		/// 1500
+		/// The number of blocks per round, as defined in the runtime.
+		///
+		/// This value is set to 1500 in the runtime configuration.
 		#[pallet::constant]
 		type BlocksPerRound: Get<u32>;
 	}
 
+	const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);
+
 	#[pallet::pallet]
 	#[pallet::without_storage_info]
+	#[pallet::storage_version(STORAGE_VERSION)]
 	pub struct Pallet<T>(PhantomData<T>);
 
 	/// Current Round Information
@@ -113,8 +121,13 @@ pub mod pallet {
 
 	/// The tokenInfo for each currency
 	#[pallet::storage]
-	pub(crate) type TokenStatus<T: Config> =
-		StorageMap<_, Twox64Concat, CurrencyIdOf<T>, TokenInfo<BalanceOf<T>>, OptionQuery>;
+	pub(crate) type TokenStatus<T: Config> = StorageMap<
+		_,
+		Twox64Concat,
+		CurrencyIdOf<T>,
+		TokenInfo<BalanceOf<T>, BlockNumberFor<T>>,
+		OptionQuery,
+	>;
 
 	/// All token sets
 	#[pallet::storage]
@@ -124,20 +137,38 @@ pub mod pallet {
 	#[pallet::event]
 	#[pallet::generate_deposit(pub(super) fn deposit_event)]
 	pub enum Event<T: Config> {
-		NewRound {
-			current: RoundIndex,
-			first: BlockNumberFor<T>,
-			length: u32,
-		},
+		/// A new staking round has started.
+		///
+		/// - `current`: The index of the current round.
+		/// - `first`: The block number at which this round started.
+		/// - `length`: The length of the round in blocks.
+		NewRound { current: RoundIndex, first: BlockNumberFor<T>, length: u32 },
+		/// Configuration of a token has been changed.
+		///
+		/// - `token`: The identifier of the token whose configuration changed.
+		/// - `exec_delay`: The delay in blocks before the changes take effect.
+		/// - `system_stakable_farming_rate`: The farming rate applied to system-stakable tokens.
+		/// - `add_or_sub`: Whether to add or subtract from the stakable farming rate.
+		/// - `system_stakable_base`: The base value of system-stakable assets.
+		/// - `farming_poolids`: List of pool IDs related to the token.
+		/// - `lptoken_rates`: List of rates for liquidity provider (LP) tokens.
 		TokenConfigChanged {
 			token: CurrencyIdOf<T>,
-			exec_delay: u32,
+			exec_delay: BlockNumberFor<T>,
 			system_stakable_farming_rate: Permill,
 			add_or_sub: bool,
 			system_stakable_base: BalanceOf<T>,
-			farming_poolids: Vec<PoolId>,
-			lptoken_rates: Vec<Perbill>,
+			farming_poolids: BoundedVec<PoolId, ConstU32<32>>,
+			lptoken_rates: BoundedVec<Perbill, ConstU32<32>>,
 		},
+		/// A deposit operation has failed.
+		///
+		/// - `token`: The identifier of the token being deposited.
+		/// - `amount`: The amount of the token to be deposited.
+		/// - `farming_staking_amount`: The amount staked in the farming pool.
+		/// - `system_stakable_amount`: The amount staked in the system-stakable pool.
+		/// - `system_shadow_amount`: The amount shadow-staked in the system.
+		/// - `pending_redeem_amount`: The amount pending redemption.
 		DepositFailed {
 			token: CurrencyIdOf<T>,
 			amount: BalanceOf<T>,
@@ -146,6 +177,15 @@ pub mod pallet {
 			system_shadow_amount: BalanceOf<T>,
 			pending_redeem_amount: BalanceOf<T>,
 		},
+
+		/// Minting operation succeeded.
+		///
+		/// - `token`: The identifier of the token being minted.
+		/// - `amount`: The amount of the token to be minted.
+		/// - `farming_staking_amount`: The amount staked in the farming pool.
+		/// - `system_stakable_amount`: The amount staked in the system-stakable pool.
+		/// - `system_shadow_amount`: The amount shadow-staked in the system.
+		/// - `pending_redeem_amount`: The amount pending redemption.
 		MintSuccess {
 			token: CurrencyIdOf<T>,
 			amount: BalanceOf<T>,
@@ -154,6 +194,10 @@ pub mod pallet {
 			system_shadow_amount: BalanceOf<T>,
 			pending_redeem_amount: BalanceOf<T>,
 		},
+		/// Minting operation failed.
+		///
+		/// # Parameters
+		/// (Same as MintSuccess)
 		MintFailed {
 			token: CurrencyIdOf<T>,
 			amount: BalanceOf<T>,
@@ -162,6 +206,10 @@ pub mod pallet {
 			system_shadow_amount: BalanceOf<T>,
 			pending_redeem_amount: BalanceOf<T>,
 		},
+		/// Withdrawal operation succeeded.
+		///
+		/// # Parameters
+		/// (Same as MintSuccess)
 		WithdrawSuccess {
 			token: CurrencyIdOf<T>,
 			amount: BalanceOf<T>,
@@ -170,6 +218,10 @@ pub mod pallet {
 			system_shadow_amount: BalanceOf<T>,
 			pending_redeem_amount: BalanceOf<T>,
 		},
+		/// Withdrawal operation failed.
+		///
+		/// # Parameters
+		/// (Same as MintSuccess)
 		WithdrawFailed {
 			token: CurrencyIdOf<T>,
 			amount: BalanceOf<T>,
@@ -178,6 +230,11 @@ pub mod pallet {
 			system_shadow_amount: BalanceOf<T>,
 			pending_redeem_amount: BalanceOf<T>,
 		},
+
+		/// A redemption operation has succeeded.
+		///
+		/// # Parameters
+		/// (Same as MintSuccess)
 		Redeemed {
 			token: CurrencyIdOf<T>,
 			amount: BalanceOf<T>,
@@ -186,6 +243,10 @@ pub mod pallet {
 			system_shadow_amount: BalanceOf<T>,
 			pending_redeem_amount: BalanceOf<T>,
 		},
+		/// A redemption operation has failed.
+		///
+		/// # Parameters
+		/// (Same as MintSuccess)
 		RedeemFailed {
 			token: CurrencyIdOf<T>,
 			amount: BalanceOf<T>,
@@ -194,12 +255,24 @@ pub mod pallet {
 			system_shadow_amount: BalanceOf<T>,
 			pending_redeem_amount: BalanceOf<T>,
 		},
-		VtokenNotFound {
-			token: CurrencyIdOf<T>,
-		},
-		TokenInfoRefreshed {
-			token: CurrencyIdOf<T>,
-		},
+		/// The specified token could not be found.
+		///
+		/// - `token`: The identifier of the token that was not found.
+		VtokenNotFound { token: CurrencyIdOf<T> },
+		/// Token information has been refreshed.
+		///
+		/// - `token`: The identifier of the token whose information was refreshed.
+		TokenInfoRefreshed { token: CurrencyIdOf<T> },
+		/// A payout has been made.
+		///
+		/// - `token`: The identifier of the token involved in the payout.
+		/// - `vtoken`: The identifier of the vtoken involved.
+		/// - `from`: The account from which the payout originated.
+		/// - `to`: The account to which the payout was made.
+		/// - `amount`: The total amount of the payout.
+		/// - `free`: The amount of free balance after the payout.
+		/// - `vfree`: The amount of vtoken free balance after the payout.
+		/// - `shadow`: The shadow balance after the payout.
 		Payout {
 			token: CurrencyIdOf<T>,
 			vtoken: CurrencyIdOf<T>,
@@ -224,6 +297,8 @@ pub mod pallet {
 		TokenInfoNotFound,
 		/// payout error
 		PayoutFailed,
+		/// Error converting Vec to BoundedVec.
+		ConversionError,
 	}
 
 	#[pallet::hooks]
@@ -296,7 +371,7 @@ pub mod pallet {
 		pub fn token_config(
 			origin: OriginFor<T>,
 			token: CurrencyIdOf<T>,
-			exec_delay: Option<u32>, // TODO: blocknum
+			exec_delay: Option<BlockNumberFor<T>>,
 			system_stakable_farming_rate: Option<Permill>,
 			add_or_sub: Option<bool>,
 			system_stakable_base: Option<BalanceOf<T>>,
@@ -311,7 +386,7 @@ pub mod pallet {
 				state
 			} else {
 				new_token = true;
-				<TokenInfo<BalanceOf<T>>>::default()
+				<TokenInfo<BalanceOf<T>, BlockNumberFor<T>>>::default()
 			};
 
 			// Set token_info.new_config
@@ -319,16 +394,12 @@ pub mod pallet {
 
 			// Set token_info.new_config.exec_delay = exec_delay
 			if let Some(exec_delay) = exec_delay {
-				ensure!(exec_delay != 0, Error::<T>::InvalidTokenConfig);
+				ensure!(!exec_delay.is_zero(), Error::<T>::InvalidTokenConfig);
 				token_info.new_config.exec_delay = exec_delay;
 			}
 
 			// Set token_info.new_config.system_stakable_farming_rate = system_stakable_farming_rate
 			if let Some(system_stakable_farming_rate) = system_stakable_farming_rate {
-				ensure!(
-					system_stakable_farming_rate >= Permill::zero(),
-					Error::<T>::InvalidTokenConfig
-				);
 				token_info.new_config.system_stakable_farming_rate = system_stakable_farming_rate;
 			}
 
@@ -349,7 +420,9 @@ pub mod pallet {
 					farming_poolids.len() as u32 <= T::MaxFarmingPoolIdLen::get(),
 					Error::<T>::ExceedMaxFarmingPoolidLen
 				);
-				token_info.new_config.farming_poolids = farming_poolids.clone();
+				token_info.new_config.farming_poolids =
+					BoundedVec::try_from(farming_poolids.clone())
+						.map_err(|_| Error::<T>::ConversionError)?;
 			}
 
 			// Set token_info.new_config.lptoken_rates = lptoken_rates
@@ -359,7 +432,8 @@ pub mod pallet {
 					lptoken_rates.len() as u32 <= T::MaxFarmingPoolIdLen::get(),
 					Error::<T>::ExceedMaxFarmingPoolidLen
 				);
-				token_info.new_config.lptoken_rates = lptoken_rates.clone();
+				token_info.new_config.lptoken_rates = BoundedVec::try_from(lptoken_rates.clone())
+					.map_err(|_| Error::<T>::ConversionError)?;
 			}
 
 			// Update token info
@@ -487,7 +561,7 @@ pub mod pallet {
 impl<T: Config> Pallet<T> {
 	fn process_token_info(
 		account: AccountIdOf<T>,
-		mut token_info: TokenInfo<BalanceOf<T>>,
+		mut token_info: TokenInfo<BalanceOf<T>, BlockNumberFor<T>>,
 		token_id: CurrencyIdOf<T>,
 	) -> DispatchResultWithPostInfo {
 		// Query farming info
@@ -561,11 +635,9 @@ impl<T: Config> Pallet<T> {
 				system_shadow_amount: token_info.system_shadow_amount,
 				pending_redeem_amount: token_info.pending_redeem_amount,
 			});
-		}
-
 		// Check stakable_amount < (system_shadow_amount - pending_redeem_amount) ===> redeem vksm ,
 		// update pending_redeem_amount += token_amount
-		if stakable_amount <
+		} else if stakable_amount <
 			token_info.system_shadow_amount.saturating_sub(token_info.pending_redeem_amount)
 		{
 			// redeem_amount = system_shadow_amount - pending_redeem_amount - stakable_amount
@@ -589,7 +661,7 @@ impl<T: Config> Pallet<T> {
 					let new_token_info = if let Some(state) = <TokenStatus<T>>::get(&token_id) {
 						state
 					} else {
-						<TokenInfo<BalanceOf<T>>>::default()
+						<TokenInfo<BalanceOf<T>, BlockNumberFor<T>>>::default()
 					};
 					token_info.pending_redeem_amount = new_token_info.pending_redeem_amount;
 				}
@@ -618,7 +690,7 @@ impl<T: Config> Pallet<T> {
 		let mut token_info = if let Some(state) = <TokenStatus<T>>::get(&token_id) {
 			state
 		} else {
-			<TokenInfo<BalanceOf<T>>>::default()
+			<TokenInfo<BalanceOf<T>, BlockNumberFor<T>>>::default()
 		};
 
 		// pending_redeem_amount -= token_amount
@@ -682,7 +754,7 @@ impl<T: Config> Pallet<T> {
 		let mut token_info = if let Some(state) = <TokenStatus<T>>::get(&token_id) {
 			state
 		} else {
-			<TokenInfo<BalanceOf<T>>>::default()
+			<TokenInfo<BalanceOf<T>, BlockNumberFor<T>>>::default()
 		};
 
 		// pending_redeem_amount += token_amount
diff --git a/pallets/system-staking/src/migrations/mod.rs b/pallets/system-staking/src/migrations/mod.rs
new file mode 100644
index 000000000..379d174c5
--- /dev/null
+++ b/pallets/system-staking/src/migrations/mod.rs
@@ -0,0 +1,19 @@
+// 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 <https://www.gnu.org/licenses/>.
+
+pub mod v1;
diff --git a/pallets/system-staking/src/migrations/v1.rs b/pallets/system-staking/src/migrations/v1.rs
new file mode 100644
index 000000000..4468a16ae
--- /dev/null
+++ b/pallets/system-staking/src/migrations/v1.rs
@@ -0,0 +1,130 @@
+// 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 <https://www.gnu.org/licenses/>.
+
+use crate::*;
+use frame_support::{
+	ensure,
+	pallet_prelude::StorageVersion,
+	traits::{GetStorageVersion, OnRuntimeUpgrade},
+};
+use parity_scale_codec::{Decode, Encode};
+#[cfg(feature = "try-runtime")]
+use sp_runtime::TryRuntimeError;
+
+const LOG_TARGET: &str = "system-staking::migration";
+
+pub struct MigrateToV1<T>(sp_std::marker::PhantomData<T>);
+impl<T: Config> OnRuntimeUpgrade for MigrateToV1<T> {
+	fn on_runtime_upgrade() -> frame_support::weights::Weight {
+		// Check the storage version
+		let onchain_version = Pallet::<T>::on_chain_storage_version();
+		if onchain_version < 1 {
+			// Transform storage values
+			// We transform the storage values from the old into the new format.
+			log::info!(target: LOG_TARGET, "Start to migrate TokenStatus storage...");
+			TokenStatus::<T>::translate::<TokenInfo<BalanceOf<T>, BlockNumberFor<T>>, _>(
+				|k: CurrencyId, old_token_info: TokenInfo<BalanceOf<T>, BlockNumberFor<T>>| {
+					log::info!(target: LOG_TARGET, "Migrated to boundedvec for {:?}...", k);
+
+					let mut new_token_info =
+						<TokenInfo<BalanceOf<T>, BlockNumberFor<T>>>::default();
+
+					new_token_info.farming_staking_amount = old_token_info.farming_staking_amount;
+					new_token_info.system_stakable_amount = old_token_info.system_stakable_amount;
+					new_token_info.system_shadow_amount = old_token_info.system_shadow_amount;
+					new_token_info.pending_redeem_amount = old_token_info.pending_redeem_amount;
+
+					new_token_info.current_config.exec_delay =
+						BlockNumberFor::<T>::from(old_token_info.current_config.exec_delay);
+					new_token_info.current_config.system_stakable_farming_rate =
+						old_token_info.current_config.system_stakable_farming_rate;
+					new_token_info.current_config.lptoken_rates =
+						BoundedVec::try_from(old_token_info.current_config.lptoken_rates)
+							.map_err(|e| { log::error!("Failed to convert old current_config.lptoken_rates into BoundedVec during migration for {:?}: {:?}", k, e) })
+							.unwrap();
+					new_token_info.current_config.add_or_sub =
+						old_token_info.current_config.add_or_sub;
+					new_token_info.current_config.system_stakable_base =
+						old_token_info.current_config.system_stakable_base;
+					new_token_info.current_config.farming_poolids =
+						BoundedVec::try_from(old_token_info.current_config.farming_poolids)
+							.map_err(|e| { log::error!("Failed to convert old current_config.farming_poolids into BoundedVec during migration for {:?}: {:?}", k, e) })
+							.unwrap();
+
+					new_token_info.new_config.exec_delay =
+						BlockNumberFor::<T>::from(old_token_info.new_config.exec_delay);
+					new_token_info.new_config.system_stakable_farming_rate =
+						old_token_info.new_config.system_stakable_farming_rate;
+					new_token_info.new_config.lptoken_rates =
+						BoundedVec::try_from(old_token_info.new_config.lptoken_rates)
+							.map_err(|e| { log::error!("Failed to convert old new_config.lptoken_rates into BoundedVec during migration for {:?}: {:?}", k, e) })
+							.unwrap();
+					new_token_info.new_config.add_or_sub = old_token_info.new_config.add_or_sub;
+					new_token_info.new_config.system_stakable_base =
+						old_token_info.new_config.system_stakable_base;
+					new_token_info.new_config.farming_poolids =
+						BoundedVec::try_from(old_token_info.new_config.farming_poolids)
+							.map_err(|e| { log::error!("Failed to convert old new_config.farming_poolids into BoundedVec during migration for {:?}: {:?}", k, e) })
+							.unwrap();
+
+					Some(new_token_info)
+				},
+			);
+
+			// Update the storage version
+			StorageVersion::new(1).put::<Pallet<T>>();
+
+			// Return the consumed weight
+			let count = TokenStatus::<T>::iter().count();
+			Weight::from(T::DbWeight::get().reads_writes(count as u64 + 1, count as u64 + 1))
+		} else {
+			// We don't do anything here.
+			Weight::zero()
+		}
+	}
+
+	#[cfg(feature = "try-runtime")]
+	fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
+		let cnt = TokenStatus::<T>::iter().count();
+		// print out the pre-migrate storage count
+		log::info!(target: LOG_TARGET, "TokenStatus pre-migrate storage count: {:?}", cnt);
+		Ok((cnt as u64).encode())
+	}
+
+	#[cfg(feature = "try-runtime")]
+	fn post_upgrade(cnt: Vec<u8>) -> Result<(), TryRuntimeError> {
+		let new_count = TokenStatus::<T>::iter().count();
+
+		let old_count: u64 = Decode::decode(&mut cnt.as_slice())
+			.expect("the state parameter should be something that was generated by pre_upgrade");
+
+		// print out the post-migrate storage count
+		log::info!(
+			target: LOG_TARGET,
+			"TokenStatus post-migrate storage count: {:?}",
+			new_count
+		);
+
+		ensure!(
+			new_count as u64 == old_count,
+			"Post-migration storage count does not match pre-migration count"
+		);
+
+		Ok(())
+	}
+}
diff --git a/pallets/system-staking/src/mock.rs b/pallets/system-staking/src/mock.rs
index a50e2f26a..dbb3fd60a 100644
--- a/pallets/system-staking/src/mock.rs
+++ b/pallets/system-staking/src/mock.rs
@@ -38,7 +38,7 @@ use frame_system::{EnsureRoot, EnsureSignedBy};
 use orml_traits::{location::RelativeReserveProvider, parameter_type_with_key};
 use sp_core::ConstU32;
 use sp_runtime::{
-	traits::{ConvertInto, IdentityLookup},
+	traits::{AccountIdConversion, ConvertInto, IdentityLookup},
 	AccountId32, BuildStorage,
 };
 use sp_std::vec;
@@ -47,6 +47,7 @@ use xcm_builder::{FixedWeightBounds, FrameTransactionalProcessor};
 use xcm_executor::XcmExecutor;
 
 use crate as system_staking;
+use crate::Config;
 
 pub type BlockNumber = u64;
 pub type Amount = i128;
@@ -407,6 +408,7 @@ impl ExtBuilder {
 	}
 
 	pub fn one_hundred_for_alice_n_bob(self) -> Self {
+		let pallet_account = <Runtime as Config>::PalletId::get().into_account_truncating();
 		self.balances(vec![
 			(ALICE, BNC, 100),
 			(BOB, BNC, 100),
@@ -417,6 +419,7 @@ impl ExtBuilder {
 			(BOB, VKSM, 1000),
 			(BOB, KSM, 10000000000),
 			(BOB, MOVR, 1000000000000000000000),
+			(pallet_account, VKSM, 100),
 		])
 	}
 
diff --git a/pallets/system-staking/src/tests.rs b/pallets/system-staking/src/tests.rs
index 75544e3ba..cabff83e5 100644
--- a/pallets/system-staking/src/tests.rs
+++ b/pallets/system-staking/src/tests.rs
@@ -21,7 +21,7 @@ use bifrost_asset_registry::AssetMetadata;
 use bifrost_primitives::{TimeUnit, TokenInfo, VtokenMintingOperator};
 use bifrost_runtime_common::milli;
 use frame_support::{
-	assert_ok,
+	assert_noop, assert_ok,
 	sp_runtime::{Perbill, Permill},
 };
 use sp_std::{collections::btree_map::BTreeMap, prelude::*};
@@ -32,7 +32,7 @@ fn token_config_should_work() {
 		assert_ok!(SystemStaking::token_config(
 			RuntimeOrigin::root(),
 			KSM,
-			Some(1),
+			Some(BlockNumberFor::<Runtime>::from(1u32)),
 			Some(Permill::from_percent(80)),
 			Some(false),
 			Some(100),
@@ -151,6 +151,171 @@ fn refresh_token_info_should_work() {
 	});
 }
 
+#[test]
+fn payout_should_work() {
+	ExtBuilder::default().one_hundred_for_alice_n_bob().build().execute_with(|| {
+		let (pid, _tokens) = init_farming_no_gauge();
+		asset_registry();
+
+		assert_ok!(VtokenMinting::set_minimum_mint(RuntimeOrigin::signed(ALICE), KSM, 0));
+		pub const FEE: Permill = Permill::from_percent(5);
+		assert_ok!(VtokenMinting::set_fees(RuntimeOrigin::root(), FEE, FEE));
+
+		assert_ok!(SystemStaking::token_config(
+			RuntimeOrigin::root(),
+			KSM,
+			Some(1),
+			Some(Permill::from_percent(80)),
+			Some(false),
+			Some(100),
+			Some(vec![pid]),
+			Some(vec![Perbill::from_percent(100)]),
+		));
+
+		assert_ok!(VtokenMinting::mint(
+			RuntimeOrigin::signed(ALICE),
+			KSM,
+			1000,
+			BoundedVec::default(),
+			Some(0u32),
+		));
+
+		let pallet_account = <Runtime as Config>::PalletId::get().into_account_truncating();
+
+		let pallet_vfree_balance = Currencies::free_balance(VKSM, &pallet_account);
+		assert_eq!(pallet_vfree_balance, 100);
+
+		assert_ok!(SystemStaking::payout(RuntimeOrigin::root(), KSM));
+
+		let pallet_vfree_balance = Currencies::free_balance(VKSM, &pallet_account);
+		assert_eq!(pallet_vfree_balance, 1);
+
+		let treasury_balance = Currencies::free_balance(VKSM, &TreasuryAccount::get());
+		assert_eq!(treasury_balance, 99);
+	});
+}
+
+#[test]
+fn payout_should_fail() {
+	ExtBuilder::default().one_hundred_for_alice_n_bob().build().execute_with(|| {
+		asset_registry();
+
+		assert_ok!(VtokenMinting::set_minimum_mint(RuntimeOrigin::signed(ALICE), KSM, 0));
+		pub const FEE: Permill = Permill::from_percent(5);
+		assert_ok!(VtokenMinting::set_fees(RuntimeOrigin::root(), FEE, FEE));
+
+		assert_ok!(VtokenMinting::mint(
+			RuntimeOrigin::signed(ALICE),
+			KSM,
+			1000,
+			BoundedVec::default(),
+			Some(0u32),
+		));
+
+		assert_noop!(
+			SystemStaking::payout(RuntimeOrigin::root(), KSM),
+			Error::<Runtime>::TokenInfoNotFound
+		);
+	});
+}
+
+#[test]
+fn on_redeem_success_should_work() {
+	ExtBuilder::default().one_hundred_for_alice_n_bob().build().execute_with(|| {
+		asset_registry();
+
+		let pallet_account = <Runtime as Config>::PalletId::get().into_account_truncating();
+
+		let pallet_vfree_balance = Currencies::free_balance(VKSM, &pallet_account);
+		assert_eq!(pallet_vfree_balance, 100);
+
+		SystemStaking::on_redeem_success(VKSM, pallet_account.clone(), 10);
+
+		let pallet_vfree_balance = Currencies::free_balance(VKSM, &pallet_account);
+		assert_eq!(pallet_vfree_balance, 90);
+		let mut token_info = <TokenStatus<Runtime>>::get(VKSM).unwrap();
+		assert_eq!(token_info.pending_redeem_amount, 0);
+		assert_eq!(token_info.system_shadow_amount, 0);
+
+		token_info.pending_redeem_amount = 100;
+		token_info.system_shadow_amount = 100;
+		<TokenStatus<Runtime>>::insert(&VKSM, token_info.clone());
+		assert_eq!(token_info.pending_redeem_amount, 100);
+		assert_eq!(token_info.system_shadow_amount, 100);
+
+		SystemStaking::on_redeem_success(VKSM, pallet_account.clone(), 90);
+
+		let pallet_vfree_balance = Currencies::free_balance(VKSM, &pallet_account);
+		assert_eq!(pallet_vfree_balance, 0);
+		let token_info = <TokenStatus<Runtime>>::get(VKSM).unwrap();
+		assert_eq!(token_info.pending_redeem_amount, 10);
+		assert_eq!(token_info.system_shadow_amount, 10);
+	});
+}
+
+#[test]
+fn on_refund_should_work() {
+	ExtBuilder::default().one_hundred_for_alice_n_bob().build().execute_with(|| {
+		asset_registry();
+
+		let pallet_account = <Runtime as Config>::PalletId::get().into_account_truncating();
+
+		let pallet_vfree_balance = Currencies::free_balance(VKSM, &pallet_account);
+		assert_eq!(pallet_vfree_balance, 100);
+
+		SystemStaking::on_refund(VKSM, pallet_account.clone(), 10);
+
+		let pallet_vfree_balance = Currencies::free_balance(VKSM, &pallet_account);
+		assert_eq!(pallet_vfree_balance, 90);
+		let mut token_info = <TokenStatus<Runtime>>::get(VKSM).unwrap();
+		assert_eq!(token_info.pending_redeem_amount, 0);
+		assert_eq!(token_info.system_shadow_amount, 0);
+
+		token_info.pending_redeem_amount = 100;
+		token_info.system_shadow_amount = 100;
+		<TokenStatus<Runtime>>::insert(&VKSM, token_info.clone());
+		assert_eq!(token_info.pending_redeem_amount, 100);
+		assert_eq!(token_info.system_shadow_amount, 100);
+
+		SystemStaking::on_refund(VKSM, pallet_account.clone(), 90);
+
+		let pallet_vfree_balance = Currencies::free_balance(VKSM, &pallet_account);
+		assert_eq!(pallet_vfree_balance, 0);
+		let token_info = <TokenStatus<Runtime>>::get(VKSM).unwrap();
+		assert_eq!(token_info.pending_redeem_amount, 10);
+		assert_eq!(token_info.system_shadow_amount, 10);
+	});
+}
+
+#[test]
+fn on_redeemed_should_work() {
+	ExtBuilder::default().one_hundred_for_alice_n_bob().build().execute_with(|| {
+		asset_registry();
+
+		let pallet_account = <Runtime as Config>::PalletId::get().into_account_truncating();
+		let pallet_vfree_balance = Currencies::free_balance(VKSM, &pallet_account);
+		assert_eq!(pallet_vfree_balance, 100);
+
+		SystemStaking::on_redeemed(pallet_account.clone(), VKSM, 10, 0, 0);
+
+		let pallet_vfree_balance = Currencies::free_balance(VKSM, &pallet_account);
+		assert_eq!(pallet_vfree_balance, 100);
+		let mut token_info = <TokenStatus<Runtime>>::get(VKSM).unwrap();
+		assert_eq!(token_info.pending_redeem_amount, 10);
+
+		token_info.pending_redeem_amount = 100;
+		<TokenStatus<Runtime>>::insert(&VKSM, token_info.clone());
+		assert_eq!(token_info.pending_redeem_amount, 100);
+
+		SystemStaking::on_redeemed(pallet_account.clone(), VKSM, 10, 0, 0);
+
+		let pallet_vfree_balance = Currencies::free_balance(VKSM, &pallet_account);
+		assert_eq!(pallet_vfree_balance, 100);
+		let token_info = <TokenStatus<Runtime>>::get(VKSM).unwrap();
+		assert_eq!(token_info.pending_redeem_amount, 110);
+	});
+}
+
 #[test]
 fn round_process_token() {
 	ExtBuilder::default().one_hundred_for_alice_n_bob().build().execute_with(|| {
diff --git a/pallets/system-staking/src/types.rs b/pallets/system-staking/src/types.rs
index 08b7a64c4..d0ce95821 100644
--- a/pallets/system-staking/src/types.rs
+++ b/pallets/system-staking/src/types.rs
@@ -54,9 +54,9 @@ impl<
 	}
 
 	/// Check exec_delay match
-	pub fn check_delay(&self, now: B, delay: u32) -> bool {
+	pub fn check_delay(&self, now: B, delay: B) -> bool {
 		//Current blockNumber -  BlockNumber of Round Start == delay blockNumber ===> true
-		now - self.first == delay.into() && delay != 0
+		now - self.first == delay && delay != 0.into()
 	}
 }
 impl<
@@ -69,7 +69,14 @@ impl<
 }
 
 #[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)]
-pub struct TokenInfo<Balance: Copy> {
+pub struct TokenInfo<
+	Balance: Copy,
+	BlockNumber: Copy
+		+ sp_std::ops::Add<Output = BlockNumber>
+		+ sp_std::ops::Sub<Output = BlockNumber>
+		+ From<u32>
+		+ PartialOrd,
+> {
 	/// The number of token staking in Farming
 	pub farming_staking_amount: Balance,
 	/// token_config.system_stakable_farming_rate(100%) * farming_staking_amount(0) +/-
@@ -80,25 +87,41 @@ pub struct TokenInfo<Balance: Copy> {
 	/// Number of pending redemptions
 	pub pending_redeem_amount: Balance,
 	/// Current TokenConfig
-	pub current_config: TokenConfig<Balance>,
+	pub current_config: TokenConfig<Balance, BlockNumber>,
 	/// New TokenConfig
-	pub new_config: TokenConfig<Balance>,
+	pub new_config: TokenConfig<Balance, BlockNumber>,
 }
 
-impl<Balance: Zero + Copy> Default for TokenInfo<Balance> {
-	fn default() -> TokenInfo<Balance> {
+impl<
+		Balance: Zero + Copy,
+		BlockNumber: Copy
+			+ sp_std::ops::Add<Output = BlockNumber>
+			+ sp_std::ops::Sub<Output = BlockNumber>
+			+ From<u32>
+			+ PartialOrd,
+	> Default for TokenInfo<Balance, BlockNumber>
+{
+	fn default() -> TokenInfo<Balance, BlockNumber> {
 		TokenInfo {
 			farming_staking_amount: Balance::zero(),
 			system_stakable_amount: Balance::zero(),
 			system_shadow_amount: Balance::zero(),
 			pending_redeem_amount: Balance::zero(),
-			current_config: TokenConfig::<Balance>::default(),
-			new_config: TokenConfig::<Balance>::default(),
+			current_config: TokenConfig::<Balance, BlockNumber>::default(),
+			new_config: TokenConfig::<Balance, BlockNumber>::default(),
 		}
 	}
 }
 
-impl<Balance: Copy + PartialEq> TokenInfo<Balance> {
+impl<
+		Balance: Copy + PartialEq,
+		BlockNumber: Copy
+			+ sp_std::ops::Add<Output = BlockNumber>
+			+ sp_std::ops::Sub<Output = BlockNumber>
+			+ From<u32>
+			+ PartialOrd,
+	> TokenInfo<Balance, BlockNumber>
+{
 	pub fn check_config_change(&self) -> bool {
 		self.current_config != self.new_config
 	}
@@ -109,30 +132,45 @@ impl<Balance: Copy + PartialEq> TokenInfo<Balance> {
 }
 
 #[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)]
-pub struct TokenConfig<Balance> {
+pub struct TokenConfig<Balance, BlockNumber>
+where
+	BlockNumber: Copy
+		+ sp_std::ops::Add<Output = BlockNumber>
+		+ sp_std::ops::Sub<Output = BlockNumber>
+		+ From<u32>
+		+ PartialOrd,
+{
 	/// Number of blocks with delayed execution
-	pub exec_delay: u32,
+	pub exec_delay: BlockNumber,
 	/// 100 %
 	pub system_stakable_farming_rate: Permill,
 	///
-	pub lptoken_rates: Vec<Perbill>,
+	pub lptoken_rates: BoundedVec<Perbill, ConstU32<32>>,
 	/// true: add, false: sub , +/- token_config.system_stakable_base
 	pub add_or_sub: bool,
 	///
 	pub system_stakable_base: Balance,
 	/// Farming pool ids
-	pub farming_poolids: Vec<PoolId>,
+	pub farming_poolids: BoundedVec<PoolId, ConstU32<32>>,
 }
 
-impl<Balance: Zero> Default for TokenConfig<Balance> {
-	fn default() -> TokenConfig<Balance> {
+impl<
+		Balance: Zero,
+		BlockNumber: Copy
+			+ sp_std::ops::Add<Output = BlockNumber>
+			+ sp_std::ops::Sub<Output = BlockNumber>
+			+ From<u32>
+			+ PartialOrd,
+	> Default for TokenConfig<Balance, BlockNumber>
+{
+	fn default() -> TokenConfig<Balance, BlockNumber> {
 		TokenConfig {
-			exec_delay: 0u32,
+			exec_delay: 0u32.into(),
 			system_stakable_farming_rate: Permill::from_percent(0),
-			lptoken_rates: Vec::new(),
+			lptoken_rates: BoundedVec::default(),
 			system_stakable_base: Balance::zero(),
 			add_or_sub: true, // default add
-			farming_poolids: Vec::new(),
+			farming_poolids: BoundedVec::default(),
 		}
 	}
 }
diff --git a/runtime/bifrost-kusama/src/lib.rs b/runtime/bifrost-kusama/src/lib.rs
index d697fe916..a7ef423db 100644
--- a/runtime/bifrost-kusama/src/lib.rs
+++ b/runtime/bifrost-kusama/src/lib.rs
@@ -1905,6 +1905,7 @@ pub mod migrations {
 		VSBondAuctionClearPalletId<Runtime>,
 		frame_support::migrations::RemovePallet<SystemMakerName, RocksDbWeight>,
 		frame_support::migrations::RemovePallet<VSBondAuctionName, RocksDbWeight>,
+		bifrost_system_staking::migrations::v1::MigrateToV1<Runtime>,
 	);
 }
 
diff --git a/runtime/bifrost-polkadot/src/lib.rs b/runtime/bifrost-polkadot/src/lib.rs
index 9bded4470..4f2431d13 100644
--- a/runtime/bifrost-polkadot/src/lib.rs
+++ b/runtime/bifrost-polkadot/src/lib.rs
@@ -1835,6 +1835,7 @@ pub mod migrations {
 		bifrost_asset_registry::migrations::v1::MigrateToV1<Runtime>,
 		bifrost_slpx::migration::v2::MigrateToV2<Runtime>,
 		frame_support::migrations::RemovePallet<SystemMakerName, RocksDbWeight>,
+		bifrost_system_staking::migrations::v1::MigrateToV1<Runtime>,
 	);
 }
 

From 3f0cf674560e862bc0a747a8aa347229f939cc8f Mon Sep 17 00:00:00 2001
From: yooml <ymlll0508@gmail.com>
Date: Tue, 15 Oct 2024 09:58:15 +0800
Subject: [PATCH 21/31] =?UTF-8?q?fix:=20=F0=9F=90=9B=20for=20review=20(#14?=
 =?UTF-8?q?62)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 pallets/farming/src/gauge.rs |  9 +++++
 pallets/farming/src/lib.rs   | 65 ++++++++++++++++++++++++++++++++++++
 2 files changed, 74 insertions(+)

diff --git a/pallets/farming/src/gauge.rs b/pallets/farming/src/gauge.rs
index 4827eed16..7062935e8 100644
--- a/pallets/farming/src/gauge.rs
+++ b/pallets/farming/src/gauge.rs
@@ -30,14 +30,23 @@ use crate::*;
 
 #[derive(Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo)]
 pub struct GaugeInfo<BalanceOf: HasCompact, BlockNumberFor, AccountIdOf> {
+	/// Gauge pool controller
 	pub who: AccountIdOf,
+	/// The amount of the user deposited in the gauge pool.
 	pub gauge_amount: BalanceOf,
+	/// Total time factor
 	pub total_time_factor: u128,
+	/// The latest time factor when the user deposit/withdraw.
 	pub latest_time_factor: u128,
+	/// The time factor when the user claimed the rewards last time.
 	pub claimed_time_factor: u128,
+	/// The block number when the pool started to gauge.
 	pub gauge_start_block: BlockNumberFor,
+	/// The block number when the pool stopped to gauge.
 	pub gauge_stop_block: BlockNumberFor,
+	/// The block number when the user deposit/withdraw last time.
 	pub gauge_last_block: BlockNumberFor,
+	/// The block number when the user claimed the rewards last time.
 	pub last_claim_block: BlockNumberFor,
 }
 
diff --git a/pallets/farming/src/lib.rs b/pallets/farming/src/lib.rs
index b86a75ea7..84fbac7f3 100644
--- a/pallets/farming/src/lib.rs
+++ b/pallets/farming/src/lib.rs
@@ -128,82 +128,137 @@ pub mod pallet {
 	#[pallet::event]
 	#[pallet::generate_deposit(pub(super) fn deposit_event)]
 	pub enum Event<T: Config> {
+		/// A farming pool is created.
 		FarmingPoolCreated {
+			/// The pool id of the new pool.
 			pid: PoolId,
 		},
+		/// The farming pool is reset.
 		FarmingPoolReset {
+			/// The pool id of the pool to reset.
 			pid: PoolId,
 		},
+		/// The farming pool is closed.
 		FarmingPoolClosed {
+			/// The pool id of the pool to close.
 			pid: PoolId,
 		},
+		/// The farming pool is killed.
 		FarmingPoolKilled {
+			/// The pool id of the pool to kill.
 			pid: PoolId,
 		},
+		/// The farming pool is edited.
 		FarmingPoolEdited {
+			/// The pool id of the pool to edit.
 			pid: PoolId,
 		},
+		/// The pool is charged.
 		Charged {
+			/// The exchanger who charged the pool.
 			who: AccountIdOf<T>,
+			/// Charged pool id.
 			pid: PoolId,
+			/// Charged rewards.
 			rewards: Vec<(CurrencyIdOf<T>, BalanceOf<T>)>,
+			/// Returns true if the reward is for gauge pool, false otherwise.
 			if_gauge: bool,
 		},
+		/// The pool is deposited.
 		Deposited {
+			/// The exchanger who deposited the pool.
 			who: AccountIdOf<T>,
+			/// Deposited pool id.
 			pid: PoolId,
+			/// Deposited value.
 			add_value: BalanceOf<T>,
 		},
+		/// The pool is withdrawn.
 		Withdrawn {
+			/// The exchanger who withdrew the pool.
 			who: AccountIdOf<T>,
+			/// Withdrawn pool id.
 			pid: PoolId,
+			/// Withdrawn value.
 			remove_value: Option<BalanceOf<T>>,
 		},
+		/// The pool is claimed.
 		Claimed {
+			/// The exchanger who claimed the pool.
 			who: AccountIdOf<T>,
+			/// Claimed pool id.
 			pid: PoolId,
 		},
+		/// The pool is withdrawn claimed.
 		WithdrawClaimed {
+			/// The exchanger who withdrew claimed the pool.
 			who: AccountIdOf<T>,
+			/// Withdraw claimed pool id.
 			pid: PoolId,
 		},
+		/// The gauge pool is withdrawn.
 		GaugeWithdrawn {
+			/// The exchanger who withdrew the gauge pool.
 			who: AccountIdOf<T>,
+			/// Withdrawn gauge pool id.
 			gid: PoolId,
 		},
+		/// All gauge pools have been claimed.
 		AllForceGaugeClaimed {
+			/// Last claimed gauge pool id.
 			gid: PoolId,
 		},
+		/// Partially gauge pools have been claimed.
 		PartiallyForceGaugeClaimed {
+			/// Last claimed gauge pool id.
 			gid: PoolId,
 		},
+		/// All pools is retired.
 		AllRetired {
+			/// Last retired pool id.
 			pid: PoolId,
 		},
+		/// Partially pools is retired.
 		PartiallyRetired {
+			/// Last retired pool id.
 			pid: PoolId,
 		},
+		/// The retire limit is set.
 		RetireLimitSet {
+			/// The retire limit.
 			limit: u32,
 		},
+		/// The round has ended.
 		RoundEnd {
 			// voting_pools: BTreeMap<PoolId, BalanceOf<T>>,
 			total_votes: BalanceOf<T>,
+			/// The start block of the round.
 			start_round: BlockNumberFor<T>,
+			/// The end block of the round.
 			end_round: BlockNumberFor<T>,
 		},
+		/// The round has started to fail.
 		RoundStartError {
+			/// The error
 			info: DispatchError,
 		},
+		/// The round has started.
 		RoundStart {
+			/// The length of the round.
 			round_length: BlockNumberFor<T>,
 		},
+		/// The exchanger is voted.
 		Voted {
+			/// The exchanger who voted.
 			who: AccountIdOf<T>,
+			/// Voted pool id.
 			vote_list: Vec<(PoolId, Percent)>,
 		},
+		/// The boost pool is charged.
 		BoostCharged {
+			/// The exchanger who charged the boost pool.
 			who: AccountIdOf<T>,
+			/// Charged boost pool id.
 			rewards: Vec<(CurrencyIdOf<T>, BalanceOf<T>)>,
 		},
 	}
@@ -252,12 +307,15 @@ pub mod pallet {
 		InvalidRemoveAmount,
 	}
 
+	/// Record the id of the new pool.
 	#[pallet::storage]
 	pub type PoolNextId<T: Config> = StorageValue<_, PoolId, ValueQuery>;
 
+	/// Record the id of the new gauge pool.
 	#[pallet::storage]
 	pub type GaugePoolNextId<T: Config> = StorageValue<_, PoolId, ValueQuery>;
 
+	/// The upper limit of a single retirement pool
 	#[pallet::storage]
 	pub type RetireLimit<T: Config> = StorageValue<_, u32, ValueQuery>;
 
@@ -283,6 +341,7 @@ pub mod pallet {
 		GaugePoolInfo<BalanceOf<T>, CurrencyIdOf<T>, AccountIdOf<T>, BlockNumberFor<T>>,
 	>;
 
+	/// Record gauge config
 	#[pallet::storage]
 	pub type GaugeInfos<T: Config> = StorageDoubleMap<
 		_,
@@ -307,23 +366,29 @@ pub mod pallet {
 		ShareInfo<BalanceOf<T>, CurrencyIdOf<T>, BlockNumberFor<T>, AccountIdOf<T>>,
 	>;
 
+	/// Record all voting pool information.
 	#[pallet::storage]
 	pub type BoostPoolInfos<T: Config> =
 		StorageValue<_, BoostPoolInfo<BalanceOf<T>, BlockNumberFor<T>>, ValueQuery>;
 
+	/// Record the voting pool id and the voting percentage of the user.
 	#[pallet::storage]
 	pub type UserBoostInfos<T: Config> =
 		StorageMap<_, Blake2_128Concat, T::AccountId, UserBoostInfo<T>>;
 
+	/// Record the pools which the user can voted for.
 	#[pallet::storage]
 	pub type BoostWhitelist<T: Config> = StorageMap<_, Twox64Concat, PoolId, ()>;
 
+	/// Record the pools which the user can voted for in the next round.
 	#[pallet::storage]
 	pub type BoostNextRoundWhitelist<T: Config> = StorageMap<_, Twox64Concat, PoolId, ()>;
 
+	/// Record the voting amount for each pool.
 	#[pallet::storage]
 	pub type BoostVotingPools<T: Config> = StorageMap<_, Twox64Concat, PoolId, BalanceOf<T>>;
 
+	/// Voting rewards for corresponding currency.
 	#[pallet::storage]
 	pub type BoostBasicRewards<T: Config> =
 		StorageDoubleMap<_, Twox64Concat, PoolId, Twox64Concat, CurrencyIdOf<T>, BalanceOf<T>>;

From f1bf1c41347e929bd8d93411a463ef50dffe8f18 Mon Sep 17 00:00:00 2001
From: yooml <ymlll0508@gmail.com>
Date: Tue, 15 Oct 2024 09:59:09 +0800
Subject: [PATCH 22/31] =?UTF-8?q?fix:=20=F0=9F=90=9B=20for=20review=20(#14?=
 =?UTF-8?q?63)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 pallets/stable-asset/src/lib.rs | 154 +++++++++++++++++++++++++++++++-
 1 file changed, 152 insertions(+), 2 deletions(-)

diff --git a/pallets/stable-asset/src/lib.rs b/pallets/stable-asset/src/lib.rs
index 77d6e473a..8477985fc 100644
--- a/pallets/stable-asset/src/lib.rs
+++ b/pallets/stable-asset/src/lib.rs
@@ -41,7 +41,7 @@ use scale_info::TypeInfo;
 use sp_core::{U256, U512};
 use sp_runtime::{
 	traits::{AccountIdConversion, CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, One, Zero},
-	DispatchError, SaturatedConversion,
+	ArithmeticError, DispatchError, SaturatedConversion,
 };
 use sp_std::prelude::*;
 
@@ -400,9 +400,11 @@ pub mod pallet {
 	#[pallet::without_storage_info]
 	pub struct Pallet<T>(_);
 
+	/// The last pool id.
 	#[pallet::storage]
 	pub type PoolCount<T: Config> = StorageValue<_, StableAssetPoolId, ValueQuery>;
 
+	/// The pool info.
 	#[pallet::storage]
 	pub type Pools<T: Config> = StorageMap<
 		_,
@@ -417,6 +419,7 @@ pub mod pallet {
 		>,
 	>;
 
+	/// Price anchor used to bind the corresponding pool and currency.
 	#[pallet::storage]
 	pub type TokenRateCaches<T: Config> = StorageDoubleMap<
 		_,
@@ -427,193 +430,340 @@ pub mod pallet {
 		(T::AtLeast64BitUnsigned, T::AtLeast64BitUnsigned),
 	>;
 
+	/// Record the maximum percentage that can exceed the token rate.
 	#[pallet::storage]
 	pub type TokenRateHardcap<T: Config> = StorageMap<_, Twox64Concat, T::AssetId, Permill>;
 
 	#[pallet::event]
 	#[pallet::generate_deposit(pub fn deposit_event)]
 	pub enum Event<T: Config> {
+		/// A new pool is created.
 		CreatePool {
+			/// The pool id.
 			pool_id: StableAssetPoolId,
+			/// Amplification coefficient of the pool.
 			a: T::AtLeast64BitUnsigned,
+			/// The system account of the pool.
 			swap_id: T::AccountId,
+			/// Pallet id.
 			pallet_id: T::AccountId,
 		},
+		/// Liquidity is added to the pool.
 		LiquidityAdded {
+			/// The account who added the liquidity.
 			minter: T::AccountId,
+			/// The pool id.
 			pool_id: StableAssetPoolId,
+			/// Amplification coefficient of the pool.
 			a: T::AtLeast64BitUnsigned,
+			/// The input amounts of the assets.
 			input_amounts: Vec<T::Balance>,
+			/// Expected minimum output amount.
 			min_output_amount: T::Balance,
+			/// Balances data.
 			balances: Vec<T::Balance>,
+			/// The total supply of the pool asset.
 			total_supply: T::Balance,
+			/// fee amount of the pool asset.
 			fee_amount: T::Balance,
+			/// Actual minimum output amount.
 			output_amount: T::Balance,
 		},
+		/// Token is swapped.
 		TokenSwapped {
+			/// The account who swapped the token.
 			swapper: T::AccountId,
+			/// The pool id.
 			pool_id: StableAssetPoolId,
+			/// Amplification coefficient of the pool.
 			a: T::AtLeast64BitUnsigned,
+			/// The input asset type.
 			input_asset: T::AssetId,
+			/// The output asset type.
 			output_asset: T::AssetId,
+			/// The input amount of the input asset.
 			input_amount: T::Balance,
+			/// The expected minimum output amount of the output asset.
 			min_output_amount: T::Balance,
+			/// Balances data.
 			balances: Vec<T::Balance>,
+			/// The total supply of the pool asset.
 			total_supply: T::Balance,
+			/// Actual output amount of the output asset.
 			output_amount: T::Balance,
 		},
+		/// Token is redeemed by proportion.
 		RedeemedProportion {
+			/// The account who redeemed the token.
 			redeemer: T::AccountId,
+			/// The pool id.
 			pool_id: StableAssetPoolId,
+			/// Amplification coefficient of the pool.
 			a: T::AtLeast64BitUnsigned,
+			/// The input amount of the pool asset.
 			input_amount: T::Balance,
+			/// The expected minimum output amounts of the assets.
 			min_output_amounts: Vec<T::Balance>,
+			/// Balances data.
 			balances: Vec<T::Balance>,
+			/// The total supply of the pool asset.
 			total_supply: T::Balance,
+			/// fee amount of the pool asset.
 			fee_amount: T::Balance,
+			/// Actual output amounts of the assets.
 			output_amounts: Vec<T::Balance>,
 		},
+		/// Token is redeemed by single asset.
 		RedeemedSingle {
+			/// The account who redeemed the token.
 			redeemer: T::AccountId,
+			/// The pool id.
 			pool_id: StableAssetPoolId,
+			/// Amplification coefficient of the pool.
 			a: T::AtLeast64BitUnsigned,
+			/// The input asset type.
 			input_amount: T::Balance,
+			/// The output asset type.
 			output_asset: T::AssetId,
+			/// The expected minimum output amount of the output asset.
 			min_output_amount: T::Balance,
+			/// Balances data.
 			balances: Vec<T::Balance>,
+			/// The total supply of the pool asset.
 			total_supply: T::Balance,
+			/// fee amount of the pool asset.
 			fee_amount: T::Balance,
+			/// Actual output amount of the output asset.
 			output_amount: T::Balance,
 		},
+		/// Token is redeemed by multiple assets.
 		RedeemedMulti {
+			/// The account who redeemed the token.
 			redeemer: T::AccountId,
+			/// The pool id.
 			pool_id: StableAssetPoolId,
+			/// Amplification coefficient of the pool.
 			a: T::AtLeast64BitUnsigned,
+			/// The expected output amounts.
 			output_amounts: Vec<T::Balance>,
+			/// The maximum input amount of the pool asset to get the output amounts.
 			max_input_amount: T::Balance,
+			/// Balances data.
 			balances: Vec<T::Balance>,
+			/// The total supply of the pool asset.
 			total_supply: T::Balance,
+			/// fee amount of the pool asset.
 			fee_amount: T::Balance,
+			/// Actual input amount of the pool asset.
 			input_amount: T::Balance,
 		},
+		/// The pool field balances is updated.
 		BalanceUpdated {
+			/// The pool id.
 			pool_id: StableAssetPoolId,
+			/// The old balances.
 			old_balances: Vec<T::Balance>,
+			/// The new balances.
 			new_balances: Vec<T::Balance>,
 		},
+		/// Yield is collected.
 		YieldCollected {
+			/// The pool id.
 			pool_id: StableAssetPoolId,
+			/// Amplification coefficient of the pool.
 			a: T::AtLeast64BitUnsigned,
+			/// The old total supply of the pool asset.
 			old_total_supply: T::Balance,
+			/// The new total supply of the pool asset.
 			new_total_supply: T::Balance,
+			/// The account who collected the yield.
 			who: T::AccountId,
+			/// The amount of the pool asset collected.
 			amount: T::Balance,
 		},
+		/// Fee is collected.
 		FeeCollected {
+			/// The pool id.
 			pool_id: StableAssetPoolId,
+			/// Amplification coefficient of the pool.
 			a: T::AtLeast64BitUnsigned,
+			/// The old balances.
 			old_balances: Vec<T::Balance>,
+			/// The new balances.
 			new_balances: Vec<T::Balance>,
+			/// The old total supply of the pool asset.
 			old_total_supply: T::Balance,
+			/// The new total supply of the pool asset.
 			new_total_supply: T::Balance,
+			/// The account who has been collected the fee.
 			who: T::AccountId,
+			/// The fee amount of the pool asset.
 			amount: T::Balance,
 		},
+		/// The pool amplification coefficient is modified.
 		AModified {
+			/// The pool id.
 			pool_id: StableAssetPoolId,
+			/// The new amplification coefficient.
 			value: T::AtLeast64BitUnsigned,
+			/// The block number when the new amplification coefficient will be effective.
 			time: BlockNumberFor<T>,
 		},
+		/// The pool fees are modified.
 		FeeModified {
+			/// The pool id.
 			pool_id: StableAssetPoolId,
+			/// The new mint fee.
 			mint_fee: T::AtLeast64BitUnsigned,
+			/// The new swap fee.
 			swap_fee: T::AtLeast64BitUnsigned,
+			/// The new redeem fee.
 			redeem_fee: T::AtLeast64BitUnsigned,
 		},
+		/// The pool recipients are modified.
 		RecipientModified {
+			/// The pool id.
 			pool_id: StableAssetPoolId,
+			/// The new fee recipient.
 			fee_recipient: T::AccountId,
+			/// The new yield recipient.
 			yield_recipient: T::AccountId,
 		},
+		/// The token rate is set.
 		TokenRateSet {
+			/// The pool id.
 			pool_id: StableAssetPoolId,
+			/// The token rate info[(currency_id, (denominator, numerator))].
 			token_rate: Vec<(T::AssetId, (T::AtLeast64BitUnsigned, T::AtLeast64BitUnsigned))>,
 		},
+		/// The hardcap of the token rate is configured.
 		TokenRateHardcapConfigured {
+			/// The token type.
 			vtoken: T::AssetId,
+			/// The hardcap of the token rate.
 			hardcap: Permill,
 		},
+		/// The hardcap of the token rate is removed.
 		TokenRateHardcapRemoved {
+			/// The token type.
 			vtoken: T::AssetId,
 		},
+		/// The token rate is refreshed.
 		TokenRateRefreshFailed {
+			/// The pool id.
 			pool_id: StableAssetPoolId,
 		},
 	}
 
 	#[pallet::error]
 	pub enum Error<T> {
+		/// The pool is existed, cannot create again.
 		InconsistentStorage,
+		/// The pool asset is invalid.
 		InvalidPoolAsset,
+		/// The arguments are mismatch, not match the expected length.
 		ArgumentsMismatch,
+		/// The arguments are error.
 		ArgumentsError,
+		/// The pool is not found, cannot modify.
 		PoolNotFound,
+		/// make mistakes in calculation.
 		Math,
+		/// The new invariant of the pool is invalid.
 		InvalidPoolValue,
+		/// The actual output amount is less than the expected minimum output amount when add
+		/// liquidity.
 		MintUnderMin,
+		/// The actual output amount is less than the expected minimum output amount when swap.
 		SwapUnderMin,
+		/// The actual output amount is less than the expected minimum output amount when redeem.
 		RedeemUnderMin,
+		/// The actual input amount is more than the expected maximum input amount when redeem
+		/// multi.
 		RedeemOverMax,
+		/// The old token rate is not cleared.
 		TokenRateNotCleared,
 	}
 
+	/// The add liquidity result.
 	#[derive(Encode, Decode, Clone, Default, PartialEq, Eq, Debug)]
 	pub struct MintResult<T: Config> {
+		/// The amount of the pool asset that the user will get.
 		pub mint_amount: T::Balance,
+		/// The fee amount of the pool asset that the user will pay.
 		pub fee_amount: T::Balance,
+		/// The balances data.
 		pub balances: Vec<T::Balance>,
+		/// The total supply of the pool asset.
 		pub total_supply: T::Balance,
 	}
 
+	/// The swap result.
 	#[derive(Encode, Decode, Clone, Default, PartialEq, Eq, Debug)]
 	pub struct SwapResult<Balance> {
+		/// the input amount.
 		pub dx: Balance,
+		/// the output amount.
 		pub dy: Balance,
+		/// the output amount in balances field.
 		pub y: Balance,
+		/// the input amount in balances field.
 		pub balance_i: Balance,
 	}
 
+	/// The redeem proportion result.
 	#[derive(Encode, Decode, Clone, Default, PartialEq, Eq, Debug)]
 	pub struct RedeemProportionResult<Balance> {
+		/// The amounts of the assets that the user will get.
 		pub amounts: Vec<Balance>,
+		/// Balances data.
 		pub balances: Vec<Balance>,
+		/// The fee amount of the pool asset that the user will pay.
 		pub fee_amount: Balance,
+		/// The total supply of the pool asset.
 		pub total_supply: Balance,
+		/// The amount of the pool asset that the user want to redeem.
 		pub redeem_amount: Balance,
 	}
 
+	/// The redeem single result.
 	#[derive(Encode, Decode, Clone, Default, PartialEq, Eq, Debug)]
 	pub struct RedeemSingleResult<T: Config> {
+		/// The amount of the token index i that the user will get.
 		pub dy: T::Balance,
+		/// The fee amount of the pool asset that the user will pay.
 		pub fee_amount: T::Balance,
+		/// The total supply of the pool asset.
 		pub total_supply: T::Balance,
+		/// The balances data.
 		pub balances: Vec<T::Balance>,
+		/// The amount of the pool asset that the user want to redeem.
 		pub redeem_amount: T::Balance,
 	}
 
+	/// The redeem multi result.
 	#[derive(Encode, Decode, Clone, Default, PartialEq, Eq, Debug)]
 	pub struct RedeemMultiResult<T: Config> {
+		/// The amount of the pool asset that the user should redeemed.
 		pub redeem_amount: T::Balance,
+		/// The fee amount of the pool asset that the user will pay.
 		pub fee_amount: T::Balance,
+		/// The balances data.
 		pub balances: Vec<T::Balance>,
+		/// The total supply of the pool asset.
 		pub total_supply: T::Balance,
+		/// The amount of the pool asset that the user should redeemed except fee amount.
 		pub burn_amount: T::Balance,
 	}
 
+	/// The pending fee result.
 	#[derive(Encode, Decode, Clone, Default, PartialEq, Eq, Debug)]
 	pub struct PendingFeeResult<T: Config> {
+		/// The fee amount of the pool asset that the user will pay.
 		pub fee_amount: T::Balance,
+		/// The balances data.
 		pub balances: Vec<T::Balance>,
+		/// The total supply of the pool asset.
 		pub total_supply: T::Balance,
 	}
 
@@ -1814,7 +1964,7 @@ impl<T: Config> StableAsset for Pallet<T> {
 				Ok(())
 			})?;
 
-			*pool_count = pool_id.checked_add(1).ok_or(Error::<T>::InconsistentStorage)?;
+			*pool_count = pool_id.checked_add(1).ok_or(ArithmeticError::Overflow)?;
 
 			Self::deposit_event(Event::CreatePool {
 				pool_id,

From d980c23272c7dba484f9b14eb114210335b570af Mon Sep 17 00:00:00 2001
From: SunTiebing <87381708+SunTiebing@users.noreply.github.com>
Date: Tue, 15 Oct 2024 09:59:37 +0800
Subject: [PATCH 23/31] Optimize stable pool (#1465)

* change unwrap_or_default to unwrap

* optimize stable-pool pallet
---
 pallets/stable-pool/src/lib.rs | 67 ++++++++++++++++++++++++++++++----
 1 file changed, 60 insertions(+), 7 deletions(-)

diff --git a/pallets/stable-pool/src/lib.rs b/pallets/stable-pool/src/lib.rs
index 3499248e6..e324d65cd 100644
--- a/pallets/stable-pool/src/lib.rs
+++ b/pallets/stable-pool/src/lib.rs
@@ -66,23 +66,24 @@ pub mod pallet {
 	pub trait Config:
 		frame_system::Config + bifrost_stable_asset::Config<AssetId = AssetIdOf<Self>>
 	{
+		/// Weight information for the pallet's dispatchables.
 		type WeightInfo: WeightInfo;
-
+		/// Origin type that will be used to enforce permissions.
 		type ControlOrigin: EnsureOrigin<Self::RuntimeOrigin>;
-
+		/// MultiCurrency trait for handling various currencies associated with accounts.
 		type MultiCurrency: MultiCurrency<
 			AccountIdOf<Self>,
 			CurrencyId = AssetIdOf<Self>,
 			Balance = Self::Balance,
 		>;
-
+		/// Represents the currency identifier type, implementing necessary traits.
 		type CurrencyId: Parameter
 			+ Ord
 			+ Copy
 			+ CurrencyIdExt
 			+ From<CurrencyId>
 			+ Into<CurrencyId>;
-
+		/// The stable asset interface used for handling stable assets.
 		type StableAsset: bifrost_stable_asset::StableAsset<
 			AssetId = AssetIdOf<Self>,
 			Balance = Self::Balance,
@@ -91,30 +92,36 @@ pub mod pallet {
 			Config = Self,
 			BlockNumber = BlockNumberFor<Self>,
 		>;
-
+		/// Interface for minting tokens.
 		type VtokenMinting: VtokenMintingOperator<
 			AssetIdOf<Self>,
 			Self::Balance,
 			AccountIdOf<Self>,
 			TimeUnit,
 		>;
-
+		/// Type for converting between different currency IDs.
 		type CurrencyIdConversion: CurrencyIdConversion<AssetIdOf<Self>>;
-
+		/// Type for registering currency IDs.
 		type CurrencyIdRegister: CurrencyIdRegister<AssetIdOf<Self>>;
 	}
 
 	#[pallet::error]
 	pub enum Error<T> {
+		/// A swap occurred, but the result is below the minimum swap amount.
 		SwapUnderMin,
+		/// A minting operation occurred, but the minted amount is below the minimum mint amount.
 		MintUnderMin,
+		/// Cannot mint tokens, possibly due to invalid parameters or illegal state.
 		CantMint,
+		/// The redeemed amount exceeds the allowed maximum.
 		RedeemOverMax,
+		/// The token rate is not set, preventing related operations.
 		TokenRateNotSet,
 	}
 
 	#[pallet::call]
 	impl<T: Config> Pallet<T> {
+		/// Creates a new liquidity pool with the specified parameters.
 		#[pallet::call_index(0)]
 		#[pallet::weight(<T as pallet::Config>::WeightInfo::create_pool())]
 		pub fn create_pool(
@@ -129,8 +136,10 @@ pub mod pallet {
 			yield_recipient: AccountIdOf<T>,
 			precision: AtLeast64BitUnsignedOf<T>,
 		) -> DispatchResult {
+			// Ensure the caller has the necessary control origin
 			T::ControlOrigin::ensure_origin(origin)?;
 
+			// Register the metadata for the new pool
 			let pool_id = PoolCount::<T>::get();
 			T::CurrencyIdRegister::register_blp_metadata(
 				pool_id,
@@ -140,6 +149,8 @@ pub mod pallet {
 					.ok_or(bifrost_stable_asset::Error::<T>::ArgumentsMismatch)?
 					.saturated_into::<u8>(),
 			)?;
+
+			// Create the liquidity pool in the StableAsset module
 			T::StableAsset::create_pool(
 				CurrencyId::BLP(pool_id).into(),
 				assets,
@@ -154,6 +165,7 @@ pub mod pallet {
 			)
 		}
 
+		/// Adds liquidity to an existing pool.
 		#[pallet::call_index(1)]
 		#[pallet::weight(<T as pallet::Config>::WeightInfo::add_liquidity())]
 		pub fn add_liquidity(
@@ -163,9 +175,11 @@ pub mod pallet {
 			min_mint_amount: T::Balance,
 		) -> DispatchResult {
 			let who = ensure_signed(origin)?;
+			// Mint new liquidity tokens based on the provided amounts
 			Self::mint_inner(&who, pool_id, amounts, min_mint_amount)
 		}
 
+		/// Swaps one asset for another in a specified pool.
 		#[pallet::call_index(2)]
 		#[pallet::weight(<T as pallet::Config>::WeightInfo::swap())]
 		pub fn swap(
@@ -177,9 +191,11 @@ pub mod pallet {
 			min_dy: T::Balance,
 		) -> DispatchResult {
 			let who = ensure_signed(origin)?;
+			// Execute the swap operation
 			Self::on_swap(&who, pool_id, i, j, dx, min_dy)
 		}
 
+		/// Redeems a proportion of assets from a liquidity pool.
 		#[pallet::call_index(3)]
 		#[pallet::weight(<T as pallet::Config>::WeightInfo::redeem_proportion())]
 		pub fn redeem_proportion(
@@ -189,9 +205,11 @@ pub mod pallet {
 			min_redeem_amounts: Vec<T::Balance>,
 		) -> DispatchResult {
 			let who = ensure_signed(origin)?;
+			// Redeem a specified proportion of tokens
 			Self::redeem_proportion_inner(&who, pool_id, amount, min_redeem_amounts)
 		}
 
+		/// Redeems a single asset from a liquidity pool.
 		#[pallet::call_index(4)]
 		#[pallet::weight(<T as pallet::Config>::WeightInfo::redeem_single())]
 		pub fn redeem_single(
@@ -203,10 +221,12 @@ pub mod pallet {
 			asset_length: u32,
 		) -> DispatchResult {
 			let who = ensure_signed(origin)?;
+			// Redeem a single asset from the pool
 			Self::redeem_single_inner(&who, pool_id, amount, i, min_redeem_amount, asset_length)?;
 			Ok(())
 		}
 
+		/// Redeems multiple assets from a liquidity pool.
 		#[pallet::call_index(5)]
 		#[pallet::weight(<T as pallet::Config>::WeightInfo::redeem_multi())]
 		pub fn redeem_multi(
@@ -216,9 +236,11 @@ pub mod pallet {
 			max_redeem_amount: T::Balance,
 		) -> DispatchResult {
 			let who = ensure_signed(origin)?;
+			// Redeem multiple assets based on provided amounts
 			Self::redeem_multi_inner(&who, pool_id, amounts, max_redeem_amount)
 		}
 
+		/// Modifies the parameter 'a' of a pool at a future block.
 		#[pallet::call_index(6)]
 		#[pallet::weight(<T as pallet::Config>::WeightInfo::modify_a())]
 		pub fn modify_a(
@@ -227,10 +249,13 @@ pub mod pallet {
 			a: T::AtLeast64BitUnsigned,
 			future_a_block: BlockNumberFor<T>,
 		) -> DispatchResult {
+			// Ensure the caller has the necessary control origin
 			T::ControlOrigin::ensure_origin(origin)?;
+			// Modify the parameter 'a' in the StableAsset module
 			T::StableAsset::modify_a(pool_id, a, future_a_block)
 		}
 
+		/// Modifies the fees of a specified liquidity pool.
 		#[pallet::call_index(7)]
 		#[pallet::weight(<T as pallet::Config>::WeightInfo::modify_fees())]
 		pub fn modify_fees(
@@ -240,14 +265,19 @@ pub mod pallet {
 			swap_fee: Option<T::AtLeast64BitUnsigned>,
 			redeem_fee: Option<T::AtLeast64BitUnsigned>,
 		) -> DispatchResult {
+			// Ensure the caller has the necessary control origin
 			T::ControlOrigin::ensure_origin(origin)?;
 			let fee_denominator: T::AtLeast64BitUnsigned = T::FeePrecision::get();
+
+			// Ensure that the provided fees are within valid limits
 			ensure!(
 				mint_fee.map(|x| x < fee_denominator).unwrap_or(true) &&
 					swap_fee.map(|x| x < fee_denominator).unwrap_or(true) &&
 					redeem_fee.map(|x| x < fee_denominator).unwrap_or(true),
 				bifrost_stable_asset::Error::<T>::ArgumentsError
 			);
+
+			// Update the pool's fee information
 			Pools::<T>::try_mutate_exists(pool_id, |maybe_pool_info| -> DispatchResult {
 				let pool_info = maybe_pool_info
 					.as_mut()
@@ -261,6 +291,7 @@ pub mod pallet {
 				if let Some(fee) = redeem_fee {
 					pool_info.redeem_fee = fee;
 				}
+				// Emit an event indicating that the fees have been modified
 				bifrost_stable_asset::Pallet::<T>::deposit_event(
 					bifrost_stable_asset::Event::<T>::FeeModified {
 						pool_id,
@@ -273,6 +304,7 @@ pub mod pallet {
 			})
 		}
 
+		/// Modifies the fee and yield recipients of a liquidity pool.
 		#[pallet::call_index(8)]
 		#[pallet::weight(<T as pallet::Config>::WeightInfo::modify_recipients())]
 		pub fn modify_recipients(
@@ -281,6 +313,7 @@ pub mod pallet {
 			fee_recipient: Option<T::AccountId>,
 			yield_recipient: Option<T::AccountId>,
 		) -> DispatchResult {
+			// Ensure the caller has the necessary control origin
 			T::ControlOrigin::ensure_origin(origin)?;
 			Pools::<T>::try_mutate_exists(pool_id, |maybe_pool_info| -> DispatchResult {
 				let pool_info = maybe_pool_info
@@ -292,6 +325,7 @@ pub mod pallet {
 				if let Some(recipient) = yield_recipient {
 					pool_info.yield_recipient = recipient;
 				}
+				// Emit an event indicating that the recipients have been modified
 				bifrost_stable_asset::Pallet::<T>::deposit_event(
 					bifrost_stable_asset::Event::<T>::RecipientModified {
 						pool_id,
@@ -303,6 +337,7 @@ pub mod pallet {
 			})
 		}
 
+		/// Edits the token rates for the specified pool.
 		#[pallet::call_index(9)]
 		#[pallet::weight(<T as pallet::Config>::WeightInfo::edit_token_rate())]
 		pub fn edit_token_rate(
@@ -313,10 +348,16 @@ pub mod pallet {
 				(AtLeast64BitUnsignedOf<T>, AtLeast64BitUnsignedOf<T>),
 			)>,
 		) -> DispatchResult {
+			// Ensure the caller has the necessary control origin
 			T::ControlOrigin::ensure_origin(origin)?;
+			// Update the token rates in the StableAsset module
 			bifrost_stable_asset::Pallet::<T>::set_token_rate(pool_id, token_rate_info)
 		}
 
+		/// Configures the auto-refresh settings for a given vToken.
+		///
+		/// This method sets the hard cap for the specified vToken's token rate.
+		/// Only an authorized origin can call this function.
 		#[pallet::call_index(10)]
 		#[pallet::weight(<T as pallet::Config>::WeightInfo::config_vtoken_auto_refresh())]
 		pub fn config_vtoken_auto_refresh(
@@ -324,30 +365,42 @@ pub mod pallet {
 			vtoken: AssetIdOf<T>,
 			hardcap: Permill,
 		) -> DispatchResult {
+			// Ensure the caller has the necessary control origin
 			T::ControlOrigin::ensure_origin(origin)?;
 
+			// Ensure that the provided vtoken is valid
 			ensure!(
 				CurrencyId::is_vtoken(&vtoken.into()),
 				bifrost_stable_asset::Error::<T>::ArgumentsError
 			);
+			// Insert the hardcap for the specified vToken into storage
 			TokenRateHardcap::<T>::insert(vtoken, hardcap);
 
+			// Emit an event indicating that the vToken's hardcap has been configured
 			bifrost_stable_asset::Pallet::<T>::deposit_event(
 				bifrost_stable_asset::Event::<T>::TokenRateHardcapConfigured { vtoken, hardcap },
 			);
+
 			Ok(())
 		}
 
+		/// Removes the auto-refresh configuration for a given vToken.
+		///
+		/// This method deletes the hard cap setting for the specified vToken.
+		/// Only an authorized origin can call this function.
 		#[pallet::call_index(11)]
 		#[pallet::weight(<T as pallet::Config>::WeightInfo::remove_vtoken_auto_refresh())]
 		pub fn remove_vtoken_auto_refresh(
 			origin: OriginFor<T>,
 			vtoken: AssetIdOf<T>,
 		) -> DispatchResult {
+			// Ensure the caller has the necessary control origin
 			T::ControlOrigin::ensure_origin(origin)?;
 
+			// Remove the hardcap setting for the specified vToken from storage
 			TokenRateHardcap::<T>::remove(vtoken);
 
+			// Emit an event indicating that the vToken's hardcap has been removed
 			bifrost_stable_asset::Pallet::<T>::deposit_event(
 				bifrost_stable_asset::Event::<T>::TokenRateHardcapRemoved { vtoken },
 			);

From 4196c42f9934b27e0d5ec305bce1f1f6ba6d99d1 Mon Sep 17 00:00:00 2001
From: yooml <ymlll0508@gmail.com>
Date: Tue, 15 Oct 2024 22:26:50 +0800
Subject: [PATCH 24/31] =?UTF-8?q?fix:=20=F0=9F=90=9B=20for=20review=20(#14?=
 =?UTF-8?q?67)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 pallets/leverage-staking/src/lib.rs | 23 ++++++++++++++++++-----
 1 file changed, 18 insertions(+), 5 deletions(-)

diff --git a/pallets/leverage-staking/src/lib.rs b/pallets/leverage-staking/src/lib.rs
index 6522cb1d9..50b50756f 100644
--- a/pallets/leverage-staking/src/lib.rs
+++ b/pallets/leverage-staking/src/lib.rs
@@ -87,23 +87,36 @@ pub mod pallet {
 
 	#[pallet::error]
 	pub enum Error<T> {
+		/// Arguments error, old rate is equal to new rate
 		ArgumentsError,
+		/// Not support token type
 		NotSupportTokenType,
 	}
 
 	#[pallet::event]
 	#[pallet::generate_deposit(pub (crate) fn deposit_event)]
 	pub enum Event<T: Config> {
+		/// User's leverage rate has been changed.
 		FlashLoanDeposited {
+			/// Account who change the leverage rate.
 			who: AccountIdOf<T>,
+			/// The asset id of the token.
 			asset_id: AssetIdOf<T>,
+			/// The old leverage rate.
 			old_rate: Rate,
+			/// The new leverage rate.
 			new_rate: Rate,
 		},
 	}
 
 	#[pallet::call]
 	impl<T: Config> Pallet<T> {
+		/// Deposit flash loan
+		///
+		/// Using borrowed funds to increase the amount of liquid staking (yield-bearing) assets.
+		///
+		/// - `asset_id`: The asset id of the token
+		/// - `rate`: Leverage rate
 		#[pallet::call_index(0)]
 		#[pallet::weight(<T as pallet::Config>::WeightInfo::flash_loan_deposit())]
 		pub fn flash_loan_deposit(
@@ -111,7 +124,9 @@ pub mod pallet {
 			asset_id: AssetIdOf<T>,
 			rate: Rate,
 		) -> DispatchResult {
-			Pallet::<T>::flash_loan_deposit_inner(origin, asset_id, rate)
+			let who = ensure_signed(origin)?;
+
+			Pallet::<T>::flash_loan_deposit_inner(who, asset_id, rate)
 		}
 	}
 }
@@ -119,12 +134,10 @@ pub mod pallet {
 impl<T: Config> Pallet<T> {
 	#[transactional]
 	pub fn flash_loan_deposit_inner(
-		origin: OriginFor<T>,
+		who: AccountIdOf<T>,
 		asset_id: AssetIdOf<T>,
 		rate: Rate,
 	) -> DispatchResult {
-		let who = ensure_signed(origin)?;
-
 		let vtoken_id = T::CurrencyIdConversion::convert_to_vtoken(asset_id)
 			.map_err(|_| Error::<T>::NotSupportTokenType)?;
 
@@ -182,7 +195,7 @@ impl<T: Config> Pallet<T> {
 	) -> DispatchResult {
 		let (pool_id, currency_id_in, currency_id_out) =
 			T::StablePoolHandler::get_pool_id(&vtoken_id, &asset_id)
-				.ok_or(Error::<T>::ArgumentsError)?;
+				.ok_or(Error::<T>::NotSupportTokenType)?;
 
 		<T as lend_market::Config>::Assets::mint_into(asset_id, &who, reduce_amount)?;
 

From 87accfb37d3f9e5b17782823b31ed3c821584033 Mon Sep 17 00:00:00 2001
From: SunTiebing <87381708+SunTiebing@users.noreply.github.com>
Date: Wed, 16 Oct 2024 09:36:38 +0800
Subject: [PATCH 25/31] optimize lend-market pallet (#1468)

* optimize lend-market pallet

* Correct the indentation format.
---
 pallets/lend-market/Cargo.toml            |   2 +
 pallets/lend-market/src/lib.rs            |  52 +++++----
 pallets/lend-market/src/migrations/mod.rs |  19 +++
 pallets/lend-market/src/migrations/v1.rs  | 136 ++++++++++++++++++++++
 pallets/lend-market/src/mock.rs           |   2 +
 pallets/leverage-staking/src/mock.rs      |   2 +
 runtime/bifrost-kusama/src/lib.rs         |   2 +
 runtime/bifrost-polkadot/src/lib.rs       |   2 +
 8 files changed, 192 insertions(+), 25 deletions(-)
 create mode 100644 pallets/lend-market/src/migrations/mod.rs
 create mode 100644 pallets/lend-market/src/migrations/v1.rs

diff --git a/pallets/lend-market/Cargo.toml b/pallets/lend-market/Cargo.toml
index e530d0f87..fa38f07ba 100644
--- a/pallets/lend-market/Cargo.toml
+++ b/pallets/lend-market/Cargo.toml
@@ -23,6 +23,7 @@ pallet-traits = { workspace = true }
 parity-scale-codec = { workspace = true, features = ["derive"] }
 scale-info = { workspace = true, features = ["derive"] }
 serde = { workspace = true, features = ['derive'], optional = true }
+sp-core = { workspace = true }
 sp-io = { workspace = true }
 sp-runtime = { workspace = true }
 sp-std = { workspace = true }
@@ -49,6 +50,7 @@ std = [
 	'frame-benchmarking/std',
 	'orml-traits/std',
 	'bifrost-primitives/std',
+	'sp-core/std',
 	'sp-runtime/std',
 	'sp-std/std',
 	'sp-io/std',
diff --git a/pallets/lend-market/src/lib.rs b/pallets/lend-market/src/lib.rs
index 743701a0e..f5ad462b2 100644
--- a/pallets/lend-market/src/lib.rs
+++ b/pallets/lend-market/src/lib.rs
@@ -45,6 +45,7 @@ use pallet_traits::{
 	ConvertToBigUint, LendMarket as LendMarketTrait, LendMarketMarketDataProvider,
 	LendMarketPositionDataProvider, MarketInfo, MarketStatus,
 };
+use sp_core::bounded::BoundedVec;
 use sp_runtime::{
 	traits::{
 		AccountIdConversion, CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, One,
@@ -62,6 +63,7 @@ pub use weights::WeightInfo;
 #[cfg(feature = "runtime-benchmarks")]
 mod benchmarking;
 
+pub mod migrations;
 #[cfg(test)]
 pub mod mock;
 #[cfg(test)]
@@ -75,9 +77,6 @@ mod types;
 
 pub mod weights;
 
-pub const MAX_INTEREST_CALCULATING_INTERVAL: u64 = 5 * 24 * 3600; // 5 days
-pub const MIN_INTEREST_CALCULATING_INTERVAL: u64 = 100; // 100 seconds
-
 pub const MAX_EXCHANGE_RATE: u128 = 1_000_000_000_000_000_000; // 1
 pub const MIN_EXCHANGE_RATE: u128 = 20_000_000_000_000_000; // 0.02
 
@@ -87,12 +86,6 @@ pub type AssetIdOf<T> =
 pub type BalanceOf<T> =
 	<<T as Config>::Assets as Inspect<<T as frame_system::Config>::AccountId>>::Balance;
 
-/// Utility type for managing upgrades/migrations.
-#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug, TypeInfo)]
-pub enum Versions {
-	V0,
-}
-
 #[frame_support::pallet]
 pub mod pallet {
 
@@ -132,6 +125,9 @@ pub mod pallet {
 
 		#[pallet::constant]
 		type LiquidationFreeAssetId: Get<AssetIdOf<Self>>;
+
+		#[pallet::constant]
+		type MaxLengthLimit: Get<u32>;
 	}
 
 	#[pallet::error]
@@ -196,6 +192,8 @@ pub mod pallet {
 		CollateralReserved,
 		/// Market bond does not exist
 		MarketBondDoesNotExist,
+		/// Error converting Vec to BoundedVec.
+		ConversionError,
 	}
 
 	#[pallet::event]
@@ -275,7 +273,8 @@ pub mod pallet {
 
 	/// Liquidation free collateral.
 	#[pallet::storage]
-	pub type LiquidationFreeCollaterals<T: Config> = StorageValue<_, Vec<AssetIdOf<T>>, ValueQuery>;
+	pub type LiquidationFreeCollaterals<T: Config> =
+		StorageValue<_, BoundedVec<AssetIdOf<T>, T::MaxLengthLimit>, ValueQuery>;
 
 	/// Total number of collateral tokens in circulation
 	/// CollateralType -> Balance
@@ -434,21 +433,13 @@ pub mod pallet {
 
 	#[pallet::storage]
 	pub type MarketBond<T: Config> =
-		StorageMap<_, Blake2_128Concat, AssetIdOf<T>, Vec<AssetIdOf<T>>>;
-
-	/// DefaultVersion is using for initialize the StorageVersion
-	#[pallet::type_value]
-	pub(super) fn DefaultVersion() -> Versions {
-		Versions::V0
-	}
+		StorageMap<_, Blake2_128Concat, AssetIdOf<T>, BoundedVec<AssetIdOf<T>, T::MaxLengthLimit>>;
 
-	/// Storage version of the pallet.
-	#[pallet::storage]
-	pub(crate) type StorageVersion<T: Config> =
-		StorageValue<_, Versions, ValueQuery, DefaultVersion>;
+	const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);
 
 	#[pallet::pallet]
 	#[pallet::without_storage_info]
+	#[pallet::storage_version(STORAGE_VERSION)]
 	pub struct Pallet<T>(PhantomData<T>);
 
 	#[pallet::call]
@@ -1110,9 +1101,16 @@ pub mod pallet {
 			collaterals: Vec<AssetIdOf<T>>,
 		) -> DispatchResultWithPostInfo {
 			T::UpdateOrigin::ensure_origin(origin)?;
-			LiquidationFreeCollaterals::<T>::mutate(|liquidation_free_collaterals| {
-				*liquidation_free_collaterals = collaterals.clone()
-			});
+			LiquidationFreeCollaterals::<T>::try_mutate(
+				|liquidation_free_collaterals| -> DispatchResultWithPostInfo {
+					// Attempt to convert `collaterals` into a `BoundedVec` and handle potential
+					// conversion error
+					*liquidation_free_collaterals = BoundedVec::try_from(collaterals.clone())
+						.map_err(|_| Error::<T>::ConversionError)?;
+					Ok(().into())
+				},
+			)?;
+
 			Self::deposit_event(Event::<T>::LiquidationFreeCollateralsUpdated(collaterals));
 			Ok(().into())
 		}
@@ -1126,7 +1124,11 @@ pub mod pallet {
 			market_bond: Vec<AssetIdOf<T>>,
 		) -> DispatchResultWithPostInfo {
 			T::UpdateOrigin::ensure_origin(origin)?;
-			MarketBond::<T>::insert(asset_id, market_bond.clone());
+			MarketBond::<T>::insert(
+				asset_id,
+				BoundedVec::try_from(market_bond.clone())
+					.map_err(|_| Error::<T>::ConversionError)?,
+			);
 
 			Self::deposit_event(Event::<T>::MarketBonded { asset_id, market_bond });
 			Ok(().into())
diff --git a/pallets/lend-market/src/migrations/mod.rs b/pallets/lend-market/src/migrations/mod.rs
new file mode 100644
index 000000000..379d174c5
--- /dev/null
+++ b/pallets/lend-market/src/migrations/mod.rs
@@ -0,0 +1,19 @@
+// 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 <https://www.gnu.org/licenses/>.
+
+pub mod v1;
diff --git a/pallets/lend-market/src/migrations/v1.rs b/pallets/lend-market/src/migrations/v1.rs
new file mode 100644
index 000000000..e79155a62
--- /dev/null
+++ b/pallets/lend-market/src/migrations/v1.rs
@@ -0,0 +1,136 @@
+// 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 <https://www.gnu.org/licenses/>.
+
+use crate::*;
+use frame_support::{
+	ensure,
+	pallet_prelude::StorageVersion,
+	traits::{GetStorageVersion, Len, OnRuntimeUpgrade},
+};
+use parity_scale_codec::{Decode, Encode};
+#[cfg(feature = "try-runtime")]
+use sp_runtime::TryRuntimeError;
+
+const LOG_TARGET: &str = "lend-market::migration";
+
+pub struct MigrateToV1<T>(sp_std::marker::PhantomData<T>);
+impl<T: Config> OnRuntimeUpgrade for MigrateToV1<T> {
+	fn on_runtime_upgrade() -> frame_support::weights::Weight {
+		// Check the storage version
+		let onchain_version = Pallet::<T>::on_chain_storage_version();
+		if onchain_version < 1 {
+			// Transform storage values
+			// We transform the storage values from the old into the new format.
+			log::info!(target: LOG_TARGET, "Start to migrate LiquidationFreeCollateralsstorage...");
+			LiquidationFreeCollaterals::<T>::translate::<Vec<AssetIdOf<T>>, _>(
+				|maybe_value: Option<Vec<AssetIdOf<T>>>| {
+					let target_bounded_vec: BoundedVec<AssetIdOf<T>, T::MaxLengthLimit>;
+					if let Some(value) = maybe_value {
+						// If there's a value, try to convert Vec to BoundedVec
+						target_bounded_vec = BoundedVec::try_from(value).unwrap();
+					} else {
+						// If there's no value (None), set the BoundedVec to default (empty)
+						target_bounded_vec =
+							BoundedVec::<AssetIdOf<T>, T::MaxLengthLimit>::default();
+					}
+					// Return the new BoundedVec as the migrated value
+					Some(target_bounded_vec)
+				},
+			)
+			.unwrap();
+
+			log::info!(target: LOG_TARGET, "Start to migrate MarketBond storage...");
+			MarketBond::<T>::translate::<Vec<AssetIdOf<T>>, _>(
+				|k: AssetIdOf<T>, value: Vec<AssetIdOf<T>>| {
+					log::info!(target: LOG_TARGET, "Migrated to boundedvec for {:?}...", k);
+
+					let target_bounded_vec: BoundedVec<AssetIdOf<T>, T::MaxLengthLimit>;
+					if value.len() != 0 {
+						target_bounded_vec = BoundedVec::try_from(value).unwrap();
+					} else {
+						target_bounded_vec =
+							BoundedVec::<AssetIdOf<T>, T::MaxLengthLimit>::default();
+					}
+
+					Some(target_bounded_vec)
+				},
+			);
+
+			// Update the storage version
+			StorageVersion::new(1).put::<Pallet<T>>();
+
+			// Return the consumed weight
+			let liquidation_free_collaterals_count = 1u64;
+			let market_bond_count = MarketBond::<T>::iter().count();
+			Weight::from(T::DbWeight::get().reads_writes(
+				liquidation_free_collaterals_count + market_bond_count as u64 + 1,
+				liquidation_free_collaterals_count as u64 + market_bond_count as u64 + 1,
+			))
+		} else {
+			// We don't do anything here.
+			Weight::zero()
+		}
+	}
+
+	#[cfg(feature = "try-runtime")]
+	fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
+		let liquidation_free_collaterals_count = LiquidationFreeCollaterals::<T>::get().len();
+		let market_bond_count = MarketBond::<T>::iter().count();
+
+		// print out the pre-migrate storage count
+		log::info!(target: LOG_TARGET, "LiquidationFreeCollaterals pre-migrate storage count: {:?}", liquidation_free_collaterals_count);
+		log::info!(target: LOG_TARGET, "MarketBond pre-migrate storage count: {:?}", market_bond_count);
+		Ok((liquidation_free_collaterals_count as u64, market_bond_count as u64).encode())
+	}
+
+	#[cfg(feature = "try-runtime")]
+	fn post_upgrade(cnt: Vec<u8>) -> Result<(), TryRuntimeError> {
+		let new_liquidation_free_collaterals_count = LiquidationFreeCollaterals::<T>::get().len();
+		let new_market_bond_count = MarketBond::<T>::iter().count();
+
+		let (old_liquidation_free_collaterals_count, old_market_bond_count): (u64, u64) =
+			Decode::decode(&mut cnt.as_slice()).expect(
+				"the state parameter should be something that was generated by pre_upgrade",
+			);
+
+		// print out the post-migrate storage count
+		log::info!(
+			target: LOG_TARGET,
+			"LiquidationFreeCollaterals post-migrate storage count: {:?}",
+			new_liquidation_free_collaterals_count
+		);
+
+		log::info!(
+			target: LOG_TARGET,
+			"MarketBond post-migrate storage count: {:?}",
+			new_market_bond_count
+		);
+
+		ensure!(
+			new_liquidation_free_collaterals_count as u64 == old_liquidation_free_collaterals_count,
+			"LiquidationFreeCollaterals Post-migration storage count does not match pre-migration count"
+		);
+
+		ensure!(
+			new_market_bond_count as u64 == old_market_bond_count,
+			"MarketBond Post-migration storage count does not match pre-migration count"
+		);
+
+		Ok(())
+	}
+}
diff --git a/pallets/lend-market/src/mock.rs b/pallets/lend-market/src/mock.rs
index 9e2ba4bb1..332debd7d 100644
--- a/pallets/lend-market/src/mock.rs
+++ b/pallets/lend-market/src/mock.rs
@@ -308,6 +308,7 @@ impl pallet_prices::Config for Test {
 parameter_types! {
 	pub const RewardAssetId: CurrencyId = BNC;
 	pub const LiquidationFreeAssetId: CurrencyId = DOT;
+	pub const MaxLengthLimit: u32 = 500;
 }
 
 impl Config for Test {
@@ -321,6 +322,7 @@ impl Config for Test {
 	type Assets = Currencies;
 	type RewardAssetId = RewardAssetId;
 	type LiquidationFreeAssetId = LiquidationFreeAssetId;
+	type MaxLengthLimit = MaxLengthLimit;
 }
 
 pub(crate) fn new_test_ext() -> sp_io::TestExternalities {
diff --git a/pallets/leverage-staking/src/mock.rs b/pallets/leverage-staking/src/mock.rs
index dc76e26b3..0e4e7cf35 100644
--- a/pallets/leverage-staking/src/mock.rs
+++ b/pallets/leverage-staking/src/mock.rs
@@ -437,6 +437,7 @@ impl OraclePriceProvider for MockOraclePriceProvider {
 parameter_types! {
 	pub const RewardAssetId: CurrencyId = BNC;
 	pub const LiquidationFreeAssetId: CurrencyId = DOT;
+	pub const MaxLengthLimit: u32 = 500;
 }
 
 impl lend_market::Config for Test {
@@ -450,6 +451,7 @@ impl lend_market::Config for Test {
 	type Assets = Currencies;
 	type RewardAssetId = RewardAssetId;
 	type LiquidationFreeAssetId = LiquidationFreeAssetId;
+	type MaxLengthLimit = MaxLengthLimit;
 }
 
 impl pallet_prices::Config for Test {
diff --git a/runtime/bifrost-kusama/src/lib.rs b/runtime/bifrost-kusama/src/lib.rs
index a7ef423db..023e7fbc9 100644
--- a/runtime/bifrost-kusama/src/lib.rs
+++ b/runtime/bifrost-kusama/src/lib.rs
@@ -1592,6 +1592,7 @@ impl lend_market::Config for Runtime {
 	type Assets = Currencies;
 	type RewardAssetId = NativeCurrencyId;
 	type LiquidationFreeAssetId = RelayCurrencyId;
+	type MaxLengthLimit = MaxLengthLimit;
 }
 
 parameter_types! {
@@ -1906,6 +1907,7 @@ pub mod migrations {
 		frame_support::migrations::RemovePallet<SystemMakerName, RocksDbWeight>,
 		frame_support::migrations::RemovePallet<VSBondAuctionName, RocksDbWeight>,
 		bifrost_system_staking::migrations::v1::MigrateToV1<Runtime>,
+		lend_market::migrations::v1::MigrateToV1<Runtime>,
 	);
 }
 
diff --git a/runtime/bifrost-polkadot/src/lib.rs b/runtime/bifrost-polkadot/src/lib.rs
index 4f2431d13..38f978abb 100644
--- a/runtime/bifrost-polkadot/src/lib.rs
+++ b/runtime/bifrost-polkadot/src/lib.rs
@@ -1455,6 +1455,7 @@ impl lend_market::Config for Runtime {
 	type Assets = Currencies;
 	type RewardAssetId = NativeCurrencyId;
 	type LiquidationFreeAssetId = RelayCurrencyId;
+	type MaxLengthLimit = MaxLengthLimit;
 }
 
 parameter_types! {
@@ -1836,6 +1837,7 @@ pub mod migrations {
 		bifrost_slpx::migration::v2::MigrateToV2<Runtime>,
 		frame_support::migrations::RemovePallet<SystemMakerName, RocksDbWeight>,
 		bifrost_system_staking::migrations::v1::MigrateToV1<Runtime>,
+		lend_market::migrations::v1::MigrateToV1<Runtime>,
 	);
 }
 

From a7b8eda9ff59bd010e2ad261e7a9f1d1ee0b4970 Mon Sep 17 00:00:00 2001
From: NingBo Wang <2536935847@qq.com>
Date: Wed, 16 Oct 2024 12:04:15 +0800
Subject: [PATCH 26/31] Optimize vtoken minting (#1469)

* Optimize vtoken minting

* Fix clippy
---
 Cargo.lock                                    |    1 -
 node/rpc/src/lib.rs                           |    4 +-
 pallets/bb-bnc/src/mock.rs                    |    4 -
 pallets/buy-back/src/mock.rs                  |    4 -
 pallets/deprecated/system-maker/src/mock.rs   |    4 -
 pallets/fee-share/src/mock.rs                 |    4 -
 pallets/leverage-staking/src/lib.rs           |   10 +-
 pallets/leverage-staking/src/mock.rs          |    4 -
 pallets/salp/src/lib.rs                       |    2 +-
 pallets/salp/src/mock.rs                      |    4 -
 pallets/salp/src/tests.rs                     |    2 +-
 pallets/slp-v2/src/mock.rs                    |    4 -
 pallets/slp/src/mocks/mock.rs                 |    4 -
 pallets/slp/src/mocks/mock_kusama.rs          |    4 -
 pallets/slpx/src/lib.rs                       |   16 +-
 pallets/slpx/src/mock.rs                      |    4 -
 pallets/stable-pool/src/mock.rs               |    4 -
 pallets/system-staking/src/lib.rs             |   24 +-
 pallets/system-staking/src/mock.rs            |    4 -
 pallets/vtoken-minting/Cargo.toml             |    2 -
 .../vtoken-minting/rpc/runtime-api/src/lib.rs |    7 +-
 pallets/vtoken-minting/rpc/src/lib.rs         |   77 +-
 pallets/vtoken-minting/src/benchmarking.rs    |    4 +-
 pallets/vtoken-minting/src/impls.rs           | 1008 ++++++++
 pallets/vtoken-minting/src/lib.rs             | 2019 ++++-------------
 pallets/vtoken-minting/src/mock.rs            |  181 +-
 pallets/vtoken-minting/src/tests.rs           |   11 +-
 pallets/vtoken-minting/src/weights.rs         |    4 +-
 primitives/src/time_unit.rs                   |   16 +
 primitives/src/traits.rs                      |   25 +-
 runtime/bifrost-kusama/src/lib.rs             |   16 +-
 .../src/weights/bifrost_vtoken_minting.rs     |    2 +-
 runtime/bifrost-polkadot/src/lib.rs           |   14 +-
 .../src/weights/bifrost_vtoken_minting.rs     |    2 +-
 34 files changed, 1623 insertions(+), 1872 deletions(-)
 create mode 100644 pallets/vtoken-minting/src/impls.rs

diff --git a/Cargo.lock b/Cargo.lock
index 3af063867..8dac475d6 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2272,7 +2272,6 @@ dependencies = [
  "bifrost-currencies",
  "bifrost-primitives",
  "bifrost-runtime-common",
- "bifrost-slp",
  "cumulus-primitives-core",
  "env_logger",
  "frame-benchmarking",
diff --git a/node/rpc/src/lib.rs b/node/rpc/src/lib.rs
index 1bfb4d3cd..7f1b7d55e 100644
--- a/node/rpc/src/lib.rs
+++ b/node/rpc/src/lib.rs
@@ -110,7 +110,7 @@ where
 	C::Api: SalpRuntimeApi<Block, ParaId, AccountId>,
 	C::Api: StablePoolRuntimeApi<Block>,
 	C::Api: LendMarketApi<Block, AccountId, Balance>,
-	C::Api: VtokenMintingRuntimeApi<Block, CurrencyId>,
+	C::Api: VtokenMintingRuntimeApi<Block, CurrencyId, Balance>,
 	C::Api: ZenlinkProtocolRuntimeApi<Block, AccountId, AssetId>,
 	C::Api:
 		zenlink_stable_amm_runtime_api::StableAmmApi<Block, CurrencyId, Balance, AccountId, PoolId>,
@@ -154,7 +154,7 @@ where
 	C::Api: SalpRuntimeApi<Block, ParaId, AccountId>,
 	C::Api: BbBNCRuntimeApi<Block, AccountId>,
 	C::Api: LendMarketApi<Block, AccountId, Balance>,
-	C::Api: VtokenMintingRuntimeApi<Block, CurrencyId>,
+	C::Api: VtokenMintingRuntimeApi<Block, CurrencyId, Balance>,
 	C::Api: ZenlinkProtocolRuntimeApi<Block, AccountId, AssetId>,
 	C::Api: StablePoolRuntimeApi<Block>,
 	C::Api: BlockBuilder<Block>,
diff --git a/pallets/bb-bnc/src/mock.rs b/pallets/bb-bnc/src/mock.rs
index 5bfd05d76..36d34a318 100644
--- a/pallets/bb-bnc/src/mock.rs
+++ b/pallets/bb-bnc/src/mock.rs
@@ -207,11 +207,8 @@ impl bifrost_vtoken_minting::Config for Runtime {
 	type ExitAccount = BifrostExitAccount;
 	type FeeAccount = BifrostFeeAccount;
 	type RedeemFeeAccount = BifrostFeeAccount;
-	type BifrostSlp = Slp;
 	type BifrostSlpx = SlpxInterface;
 	type RelayChainToken = RelayCurrencyId;
-	type CurrencyIdConversion = AssetIdMaps<Runtime>;
-	type CurrencyIdRegister = AssetIdMaps<Runtime>;
 	type WeightInfo = ();
 	type OnRedeemSuccess = ();
 	type XcmTransfer = XTokens;
@@ -220,7 +217,6 @@ impl bifrost_vtoken_minting::Config for Runtime {
 	type MaxLockRecords = ConstU32<100>;
 	type IncentivePoolAccount = IncentivePoolAccount;
 	type BbBNC = ();
-	type AssetIdMaps = AssetIdMaps<Runtime>;
 }
 
 ord_parameter_types! {
diff --git a/pallets/buy-back/src/mock.rs b/pallets/buy-back/src/mock.rs
index ce98941ad..c11aa3872 100644
--- a/pallets/buy-back/src/mock.rs
+++ b/pallets/buy-back/src/mock.rs
@@ -293,11 +293,8 @@ impl bifrost_vtoken_minting::Config for Runtime {
 	type ExitAccount = BifrostExitAccount;
 	type FeeAccount = BifrostFeeAccount;
 	type RedeemFeeAccount = BifrostFeeAccount;
-	type BifrostSlp = Slp;
 	type BifrostSlpx = SlpxInterface;
 	type RelayChainToken = RelayCurrencyId;
-	type CurrencyIdConversion = AssetIdMaps<Runtime>;
-	type CurrencyIdRegister = AssetIdMaps<Runtime>;
 	type WeightInfo = ();
 	type OnRedeemSuccess = ();
 	type XcmTransfer = XTokens;
@@ -306,7 +303,6 @@ impl bifrost_vtoken_minting::Config for Runtime {
 	type MaxLockRecords = ConstU32<100>;
 	type IncentivePoolAccount = IncentivePoolAccount;
 	type BbBNC = ();
-	type AssetIdMaps = AssetIdMaps<Runtime>;
 }
 
 parameter_types! {
diff --git a/pallets/deprecated/system-maker/src/mock.rs b/pallets/deprecated/system-maker/src/mock.rs
index 33f85fb4f..7a309d1ae 100644
--- a/pallets/deprecated/system-maker/src/mock.rs
+++ b/pallets/deprecated/system-maker/src/mock.rs
@@ -292,11 +292,8 @@ impl bifrost_vtoken_minting::Config for Runtime {
 	type ExitAccount = BifrostExitAccount;
 	type FeeAccount = BifrostFeeAccount;
 	type RedeemFeeAccount = BifrostFeeAccount;
-	type BifrostSlp = Slp;
 	type BifrostSlpx = SlpxInterface;
 	type RelayChainToken = RelayCurrencyId;
-	type CurrencyIdConversion = AssetIdMaps<Runtime>;
-	type CurrencyIdRegister = AssetIdMaps<Runtime>;
 	type WeightInfo = ();
 	type OnRedeemSuccess = ();
 	type XcmTransfer = XTokens;
@@ -305,7 +302,6 @@ impl bifrost_vtoken_minting::Config for Runtime {
 	type MaxLockRecords = ConstU32<100>;
 	type IncentivePoolAccount = IncentivePoolAccount;
 	type BbBNC = ();
-	type AssetIdMaps = AssetIdMaps<Runtime>;
 }
 
 parameter_types! {
diff --git a/pallets/fee-share/src/mock.rs b/pallets/fee-share/src/mock.rs
index 5b404135b..f138d448f 100644
--- a/pallets/fee-share/src/mock.rs
+++ b/pallets/fee-share/src/mock.rs
@@ -405,11 +405,8 @@ impl bifrost_vtoken_minting::Config for Runtime {
 	type ExitAccount = BifrostExitAccount;
 	type FeeAccount = BifrostFeeAccount;
 	type RedeemFeeAccount = BifrostFeeAccount;
-	type BifrostSlp = Slp;
 	type BifrostSlpx = SlpxInterface;
 	type RelayChainToken = RelayCurrencyId;
-	type CurrencyIdConversion = AssetIdMaps<Runtime>;
-	type CurrencyIdRegister = AssetIdMaps<Runtime>;
 	type WeightInfo = ();
 	type OnRedeemSuccess = ();
 	type XcmTransfer = XTokens;
@@ -418,7 +415,6 @@ impl bifrost_vtoken_minting::Config for Runtime {
 	type MaxLockRecords = ConstU32<100>;
 	type IncentivePoolAccount = IncentivePoolAccount;
 	type BbBNC = ();
-	type AssetIdMaps = AssetIdMaps<Runtime>;
 }
 
 parameter_types! {
diff --git a/pallets/leverage-staking/src/lib.rs b/pallets/leverage-staking/src/lib.rs
index 50b50756f..4ddf4b32d 100644
--- a/pallets/leverage-staking/src/lib.rs
+++ b/pallets/leverage-staking/src/lib.rs
@@ -149,9 +149,13 @@ impl<T: Config> Pallet<T> {
 		let account_borrows = lend_market::Pallet::<T>::get_current_borrow_balance(&who, asset_id)?;
 
 		// Formula
-		// current_rate = account_borrows / ( vtoken_to_token(account_deposits) - account_borrows )
-		let deposits_token_value =
-			T::VtokenMinting::vtoken_to_token(asset_id, vtoken_id, account_deposits)?;
+		// current_rate = account_borrows / (
+		// get_currency_amount_by_v_currency_amount(account_deposits) - account_borrows )
+		let deposits_token_value = T::VtokenMinting::get_currency_amount_by_v_currency_amount(
+			asset_id,
+			vtoken_id,
+			account_deposits,
+		)?;
 		let base_token_value = deposits_token_value
 			.checked_sub(account_borrows)
 			.ok_or(ArithmeticError::Overflow)?;
diff --git a/pallets/leverage-staking/src/mock.rs b/pallets/leverage-staking/src/mock.rs
index 0e4e7cf35..e984ffb6b 100644
--- a/pallets/leverage-staking/src/mock.rs
+++ b/pallets/leverage-staking/src/mock.rs
@@ -301,10 +301,7 @@ impl bifrost_vtoken_minting::Config for Test {
 	type ExitAccount = BifrostExitAccount;
 	type FeeAccount = One;
 	type RedeemFeeAccount = One;
-	type BifrostSlp = Slp;
 	type RelayChainToken = RelayCurrencyId;
-	type CurrencyIdConversion = AssetIdMaps<Test>;
-	type CurrencyIdRegister = AssetIdMaps<Test>;
 	type WeightInfo = ();
 	type OnRedeemSuccess = ();
 	type XcmTransfer = XTokens;
@@ -314,7 +311,6 @@ impl bifrost_vtoken_minting::Config for Test {
 	type MaxLockRecords = ConstU32<100>;
 	type IncentivePoolAccount = IncentivePoolAccount;
 	type BbBNC = ();
-	type AssetIdMaps = AssetIdMaps<Test>;
 }
 
 pub struct Slp;
diff --git a/pallets/salp/src/lib.rs b/pallets/salp/src/lib.rs
index d4943958e..ae042ac7a 100644
--- a/pallets/salp/src/lib.rs
+++ b/pallets/salp/src/lib.rs
@@ -690,7 +690,7 @@ pub mod pallet {
 					)?;
 				},
 				cid if cid == relay_vtoken_id => {
-					let token_value = T::VtokenMinting::vtoken_to_token(
+					let token_value = T::VtokenMinting::get_currency_amount_by_v_currency_amount(
 						relay_currency_id,
 						relay_vtoken_id,
 						value,
diff --git a/pallets/salp/src/mock.rs b/pallets/salp/src/mock.rs
index f377cbab3..4d3970623 100644
--- a/pallets/salp/src/mock.rs
+++ b/pallets/salp/src/mock.rs
@@ -419,10 +419,7 @@ impl bifrost_vtoken_minting::Config for Test {
 	type ExitAccount = BifrostExitAccount;
 	type FeeAccount = CouncilAccount;
 	type RedeemFeeAccount = CouncilAccount;
-	type BifrostSlp = Slp;
 	type RelayChainToken = RelayCurrencyId;
-	type CurrencyIdConversion = AssetIdMaps<Test>;
-	type CurrencyIdRegister = AssetIdMaps<Test>;
 	type WeightInfo = ();
 	type OnRedeemSuccess = ();
 	type XcmTransfer = XTokens;
@@ -432,7 +429,6 @@ impl bifrost_vtoken_minting::Config for Test {
 	type MaxLockRecords = ConstU32<100>;
 	type IncentivePoolAccount = IncentivePoolAccount;
 	type BbBNC = ();
-	type AssetIdMaps = AssetIdMaps<Test>;
 }
 
 parameter_types! {
diff --git a/pallets/salp/src/tests.rs b/pallets/salp/src/tests.rs
index b30fb0d16..6c80cbeef 100644
--- a/pallets/salp/src/tests.rs
+++ b/pallets/salp/src/tests.rs
@@ -981,7 +981,7 @@ fn refund_meanwhile_issue_should_work() {
 			Salp::buyback_vstoken_by_stable_pool(Some(ALICE).into(), 1, KSM, 100),
 			orml_tokens::Error::<Test>::BalanceTooLow
 		);
-		let token_value = VtokenMinting::token_to_vtoken(KSM, VKSM, 100);
+		let token_value = VtokenMinting::get_v_currency_amount_by_currency_amount(KSM, VKSM, 100);
 		assert_eq!(token_value, Ok(100));
 		assert_eq!(Tokens::free_balance(KSM, &ALICE), 95000);
 		assert_ok!(Tokens::set_balance(RuntimeOrigin::root(), buyback_account, KSM, 100, 0));
diff --git a/pallets/slp-v2/src/mock.rs b/pallets/slp-v2/src/mock.rs
index c4f8990eb..afa120a69 100644
--- a/pallets/slp-v2/src/mock.rs
+++ b/pallets/slp-v2/src/mock.rs
@@ -241,9 +241,6 @@ impl bifrost_vtoken_minting::Config for Test {
 	type FeeAccount = BifrostFeeAccount;
 	type RedeemFeeAccount = BifrostFeeAccount;
 	type RelayChainToken = RelayCurrencyId;
-	type CurrencyIdConversion = AssetIdMaps<Test>;
-	type CurrencyIdRegister = AssetIdMaps<Test>;
-	type BifrostSlp = MockSlp;
 	type BifrostSlpx = SlpxInterface;
 	type WeightInfo = ();
 	type OnRedeemSuccess = ();
@@ -253,7 +250,6 @@ impl bifrost_vtoken_minting::Config for Test {
 	type MaxLockRecords = ConstU32<100>;
 	type IncentivePoolAccount = IncentivePoolAccount;
 	type BbBNC = ();
-	type AssetIdMaps = AssetIdMaps<Test>;
 }
 
 parameter_types! {
diff --git a/pallets/slp/src/mocks/mock.rs b/pallets/slp/src/mocks/mock.rs
index 47a728994..a8328f5b3 100644
--- a/pallets/slp/src/mocks/mock.rs
+++ b/pallets/slp/src/mocks/mock.rs
@@ -198,9 +198,6 @@ impl bifrost_vtoken_minting::Config for Runtime {
 	type FeeAccount = BifrostFeeAccount;
 	type RedeemFeeAccount = BifrostFeeAccount;
 	type RelayChainToken = RelayCurrencyId;
-	type CurrencyIdConversion = AssetIdMaps<Runtime>;
-	type CurrencyIdRegister = AssetIdMaps<Runtime>;
-	type BifrostSlp = Slp;
 	type BifrostSlpx = SlpxInterface;
 	type WeightInfo = ();
 	type OnRedeemSuccess = ();
@@ -210,7 +207,6 @@ impl bifrost_vtoken_minting::Config for Runtime {
 	type MaxLockRecords = ConstU32<100>;
 	type IncentivePoolAccount = IncentivePoolAccount;
 	type BbBNC = ();
-	type AssetIdMaps = AssetIdMaps<Runtime>;
 }
 
 parameter_types! {
diff --git a/pallets/slp/src/mocks/mock_kusama.rs b/pallets/slp/src/mocks/mock_kusama.rs
index 141e0c1b8..6c7c53986 100644
--- a/pallets/slp/src/mocks/mock_kusama.rs
+++ b/pallets/slp/src/mocks/mock_kusama.rs
@@ -254,9 +254,6 @@ impl bifrost_vtoken_minting::Config for Runtime {
 	type FeeAccount = BifrostFeeAccount;
 	type RedeemFeeAccount = BifrostFeeAccount;
 	type RelayChainToken = RelayCurrencyId;
-	type CurrencyIdConversion = AssetIdMaps<Runtime>;
-	type CurrencyIdRegister = AssetIdMaps<Runtime>;
-	type BifrostSlp = Slp;
 	type BifrostSlpx = SlpxInterface;
 	type WeightInfo = ();
 	type OnRedeemSuccess = ();
@@ -266,7 +263,6 @@ impl bifrost_vtoken_minting::Config for Runtime {
 	type MaxLockRecords = ConstU32<100>;
 	type IncentivePoolAccount = IncentivePoolAccount;
 	type BbBNC = ();
-	type AssetIdMaps = AssetIdMaps<Runtime>;
 }
 
 parameter_types! {
diff --git a/pallets/slpx/src/lib.rs b/pallets/slpx/src/lib.rs
index 407832e2a..1e3fdb129 100644
--- a/pallets/slpx/src/lib.rs
+++ b/pallets/slpx/src/lib.rs
@@ -515,8 +515,7 @@ pub mod pallet {
 			// Check the validity of origin
 			T::ControlOrigin::ensure_origin(origin)?;
 			// Check in advance to avoid hook errors
-			T::VtokenMintingInterface::vtoken_id(currency_id)
-				.ok_or(Error::<T>::ErrorConvertVtoken)?;
+			currency_id.to_vtoken().map_err(|_| Error::<T>::ErrorConvertVtoken)?;
 			let mut currency_list = CurrencyIdList::<T>::get();
 			if is_support {
 				ensure!(!currency_list.contains(&currency_id), Error::<T>::CurrencyAlreadyExists);
@@ -1100,12 +1099,13 @@ impl<T: Config> Pallet<T> {
 				let vtoken_id =
 					order.currency_id.to_vtoken().map_err(|_| Error::<T>::ErrorConvertVtoken)?;
 
-				let vtoken_amount = T::VtokenMintingInterface::token_to_vtoken(
-					order.currency_id,
-					vtoken_id,
-					currency_amount,
-				)
-				.map_err(|_| Error::<T>::ErrorVtokenMiting)?;
+				let vtoken_amount =
+					T::VtokenMintingInterface::get_v_currency_amount_by_currency_amount(
+						order.currency_id,
+						vtoken_id,
+						currency_amount,
+					)
+					.map_err(|_| Error::<T>::ErrorVtokenMiting)?;
 
 				T::VtokenMintingInterface::mint(
 					order.derivative_account.clone(),
diff --git a/pallets/slpx/src/mock.rs b/pallets/slpx/src/mock.rs
index 0abbbe43d..12c3aa264 100644
--- a/pallets/slpx/src/mock.rs
+++ b/pallets/slpx/src/mock.rs
@@ -182,9 +182,6 @@ impl bifrost_vtoken_minting::Config for Test {
 	type FeeAccount = BifrostFeeAccount;
 	type RedeemFeeAccount = BifrostFeeAccount;
 	type RelayChainToken = RelayCurrencyId;
-	type CurrencyIdConversion = AssetIdMaps<Test>;
-	type CurrencyIdRegister = AssetIdMaps<Test>;
-	type BifrostSlp = MockSlp;
 	type BifrostSlpx = SlpxInterface;
 	type WeightInfo = ();
 	type OnRedeemSuccess = ();
@@ -194,7 +191,6 @@ impl bifrost_vtoken_minting::Config for Test {
 	type MaxLockRecords = ConstU32<100>;
 	type IncentivePoolAccount = IncentivePoolAccount;
 	type BbBNC = ();
-	type AssetIdMaps = AssetIdMaps<Test>;
 }
 
 parameter_types! {
diff --git a/pallets/stable-pool/src/mock.rs b/pallets/stable-pool/src/mock.rs
index 5dd4d6798..20dcfac75 100644
--- a/pallets/stable-pool/src/mock.rs
+++ b/pallets/stable-pool/src/mock.rs
@@ -279,10 +279,7 @@ impl bifrost_vtoken_minting::Config for Test {
 	type ExitAccount = BifrostExitAccount;
 	type FeeAccount = One;
 	type RedeemFeeAccount = One;
-	type BifrostSlp = Slp;
 	type RelayChainToken = RelayCurrencyId;
-	type CurrencyIdConversion = AssetIdMaps<Test>;
-	type CurrencyIdRegister = AssetIdMaps<Test>;
 	type WeightInfo = ();
 	type OnRedeemSuccess = ();
 	type XcmTransfer = XTokens;
@@ -292,7 +289,6 @@ impl bifrost_vtoken_minting::Config for Test {
 	type MaxLockRecords = ConstU32<100>;
 	type IncentivePoolAccount = IncentivePoolAccount;
 	type BbBNC = ();
-	type AssetIdMaps = AssetIdMaps<Test>;
 }
 
 pub struct Slp;
diff --git a/pallets/system-staking/src/lib.rs b/pallets/system-staking/src/lib.rs
index 5a7cbd392..9f6f8daee 100644
--- a/pallets/system-staking/src/lib.rs
+++ b/pallets/system-staking/src/lib.rs
@@ -518,20 +518,26 @@ pub mod pallet {
 			let token_info = <TokenStatus<T>>::get(&token).ok_or(Error::<T>::TokenInfoNotFound)?;
 
 			// token_id convert to vtoken_id
-			let vtoken_id =
-				T::VtokenMintingInterface::vtoken_id(token).ok_or(Error::<T>::TokenInfoNotFound)?;
+			let vtoken_id = token.to_vtoken().map_err(|_| Error::<T>::TokenInfoNotFound)?;
 
 			let pallet_account: AccountIdOf<T> = T::PalletId::get().into_account_truncating();
 
 			// Calculate the revenue generated by vtoken
 			let vfree_amount = T::MultiCurrency::free_balance(vtoken_id, &pallet_account);
-			let free_amount =
-				T::VtokenMintingInterface::vtoken_to_token(token, vtoken_id, vfree_amount)?;
+			let free_amount = T::VtokenMintingInterface::get_currency_amount_by_v_currency_amount(
+				token,
+				vtoken_id,
+				vfree_amount,
+			)?;
 			let token_amount = free_amount.saturating_sub(token_info.system_shadow_amount);
 
 			// Calculate the number of benefits converted to vtoken
 			let vtoken_amount =
-				T::VtokenMintingInterface::token_to_vtoken(token, vtoken_id, token_amount)?;
+				T::VtokenMintingInterface::get_v_currency_amount_by_currency_amount(
+					token,
+					vtoken_id,
+					token_amount,
+				)?;
 
 			// Transfer vtoken(benefits) to TreasuryAccount
 			T::MultiCurrency::transfer(
@@ -647,11 +653,15 @@ impl<T: Config> Pallet<T> {
 				.saturating_sub(stakable_amount);
 
 			// token_id convert to vtoken_id
-			if let Some(vtoken_id) = T::VtokenMintingInterface::vtoken_id(token_id) {
+			if let Ok(vtoken_id) = token_id.to_vtoken() {
 				// Calculate how many ksm can be received by vksm through VtokenMintingInterface
 				// ===> vredeem_amount(vksm amount)
 				let vredeem_amount =
-					T::VtokenMintingInterface::token_to_vtoken(token_id, vtoken_id, redeem_amount)?;
+					T::VtokenMintingInterface::get_v_currency_amount_by_currency_amount(
+						token_id,
+						vtoken_id,
+						redeem_amount,
+					)?;
 				if vredeem_amount != BalanceOf::<T>::zero() {
 					// redeem vksm ===> vTokenMinting redeem_inner on_redeemed , update
 					// pending_redeem_amount += token_amount
diff --git a/pallets/system-staking/src/mock.rs b/pallets/system-staking/src/mock.rs
index dbb3fd60a..4bd238afb 100644
--- a/pallets/system-staking/src/mock.rs
+++ b/pallets/system-staking/src/mock.rs
@@ -189,11 +189,8 @@ impl bifrost_vtoken_minting::Config for Runtime {
 	type ExitAccount = BifrostExitAccount;
 	type FeeAccount = BifrostFeeAccount;
 	type RedeemFeeAccount = BifrostFeeAccount;
-	type BifrostSlp = Slp;
 	type BifrostSlpx = SlpxInterface;
 	type RelayChainToken = RelayCurrencyId;
-	type CurrencyIdConversion = AssetIdMaps<Runtime>;
-	type CurrencyIdRegister = AssetIdMaps<Runtime>;
 	type WeightInfo = ();
 	type OnRedeemSuccess = ();
 	type XcmTransfer = XTokens;
@@ -202,7 +199,6 @@ impl bifrost_vtoken_minting::Config for Runtime {
 	type MaxLockRecords = ConstU32<100>;
 	type IncentivePoolAccount = IncentivePoolAccount;
 	type BbBNC = ();
-	type AssetIdMaps = AssetIdMaps<Runtime>;
 }
 
 ord_parameter_types! {
diff --git a/pallets/vtoken-minting/Cargo.toml b/pallets/vtoken-minting/Cargo.toml
index 248ac8e8d..4226b370e 100644
--- a/pallets/vtoken-minting/Cargo.toml
+++ b/pallets/vtoken-minting/Cargo.toml
@@ -38,7 +38,6 @@ xcm-executor = { workspace = true }
 xcm-builder = { workspace = true }
 pallet-xcm = { workspace = true }
 xcm = { workspace = true }
-bifrost-slp = { workspace = true }
 bifrost-asset-registry = { workspace = true }
 bifrost-runtime-common = { workspace = true }
 env_logger = { workspace = true }
@@ -54,7 +53,6 @@ std = [
 	"bifrost-primitives/std",
 	"orml-traits/std",
 	"orml-xtokens/std",
-	"bifrost-slp/std",
 	"bifrost-asset-registry/std",
 	"bifrost-runtime-common/std",
 ]
diff --git a/pallets/vtoken-minting/rpc/runtime-api/src/lib.rs b/pallets/vtoken-minting/rpc/runtime-api/src/lib.rs
index 6af2840b8..9f086e44a 100644
--- a/pallets/vtoken-minting/rpc/runtime-api/src/lib.rs
+++ b/pallets/vtoken-minting/rpc/runtime-api/src/lib.rs
@@ -20,12 +20,11 @@
 
 use parity_scale_codec::Codec;
 use sp_api::decl_runtime_apis;
-use sp_core::U256;
-use sp_std::vec::Vec;
 
 decl_runtime_apis! {
-	pub trait VtokenMintingRuntimeApi<CurrencyId> where CurrencyId: Codec
+	pub trait VtokenMintingRuntimeApi<CurrencyId, Balance> where CurrencyId: Codec, Balance: Codec
 	{
-		fn get_exchange_rate(token_id: Option<CurrencyId>) -> Vec<(CurrencyId, U256)>;
+		fn get_v_currency_amount_by_currency_amount(currency_id: CurrencyId, v_currency_id: CurrencyId, currency_amount: Balance) -> Balance;
+		fn get_currency_amount_by_v_currency_amount(currency_id: CurrencyId, v_currency_id: CurrencyId, v_currency_amount: Balance) -> Balance;
 	}
 }
diff --git a/pallets/vtoken-minting/rpc/src/lib.rs b/pallets/vtoken-minting/rpc/src/lib.rs
index 301d82f26..7c412626f 100644
--- a/pallets/vtoken-minting/rpc/src/lib.rs
+++ b/pallets/vtoken-minting/rpc/src/lib.rs
@@ -27,19 +27,29 @@ use jsonrpsee::{
 use parity_scale_codec::Codec;
 use sp_api::ProvideRuntimeApi;
 use sp_blockchain::HeaderBackend;
-use sp_core::U256;
-use sp_rpc::number::NumberOrHex;
 use sp_runtime::traits::Block as BlockT;
 
 #[rpc(client, server)]
-pub trait VtokenMintingRpcApi<CurrencyId, BlockHash> {
+pub trait VtokenMintingRpcApi<CurrencyId, Balance, BlockHash> {
 	/// rpc method for getting vtoken exchange rate
-	#[method(name = "vtoken_minting_getExchangeRate")]
-	fn get_exchange_rate(
+	#[method(name = "vtoken_minting_get_v_currency_amount_by_currency_amount")]
+	fn get_v_currency_amount_by_currency_amount(
 		&self,
-		asset_id: Option<CurrencyId>,
+		currency_id: CurrencyId,
+		v_currency_id: CurrencyId,
+		currency_amount: Balance,
 		at: Option<BlockHash>,
-	) -> RpcResult<Vec<(CurrencyId, NumberOrHex)>>;
+	) -> RpcResult<Balance>;
+
+	/// rpc method for getting vtoken exchange rate
+	#[method(name = "vtoken_minting_get_currency_amount_by_v_currency_amount")]
+	fn get_currency_amount_by_v_currency_amount(
+		&self,
+		currency_id: CurrencyId,
+		v_currency_id: CurrencyId,
+		v_currency_amount: Balance,
+		at: Option<BlockHash>,
+	) -> RpcResult<Balance>;
 }
 
 #[derive(Clone, Debug)]
@@ -55,29 +65,62 @@ impl<C, Block> VtokenMintingRpc<C, Block> {
 }
 
 #[async_trait]
-impl<C, Block, CurrencyId> VtokenMintingRpcApiServer<CurrencyId, <Block as BlockT>::Hash>
+impl<C, Block, CurrencyId, Balance>
+	VtokenMintingRpcApiServer<CurrencyId, Balance, <Block as BlockT>::Hash>
 	for VtokenMintingRpc<C, Block>
 where
 	Block: BlockT,
 	C: Send + Sync + 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block>,
-	C::Api: VtokenMintingRuntimeApi<Block, CurrencyId>,
+	C::Api: VtokenMintingRuntimeApi<Block, CurrencyId, Balance>,
 	CurrencyId: Codec,
+	Balance: Codec,
 {
-	fn get_exchange_rate(
+	fn get_v_currency_amount_by_currency_amount(
+		&self,
+		currency_id: CurrencyId,
+		v_currency_id: CurrencyId,
+		currency_amount: Balance,
+		at: Option<<Block as BlockT>::Hash>,
+	) -> RpcResult<Balance> {
+		let api = self.client.runtime_api();
+		let at = at.unwrap_or_else(|| self.client.info().best_hash);
+
+		let rs: Result<Balance, _> = api.get_v_currency_amount_by_currency_amount(
+			at,
+			currency_id,
+			v_currency_id,
+			currency_amount,
+		);
+
+		match rs {
+			Ok(data) => Ok(data),
+			Err(e) => Err(ErrorObject::owned(
+				ErrorCode::InternalError.code(),
+				"Failed to get find_block_epoch.",
+				Some(format!("{:?}", e)),
+			)),
+		}
+	}
+
+	fn get_currency_amount_by_v_currency_amount(
 		&self,
-		token_id: Option<CurrencyId>,
+		currency_id: CurrencyId,
+		v_currency_id: CurrencyId,
+		v_currency_amount: Balance,
 		at: Option<<Block as BlockT>::Hash>,
-	) -> RpcResult<Vec<(CurrencyId, NumberOrHex)>> {
+	) -> RpcResult<Balance> {
 		let api = self.client.runtime_api();
 		let at = at.unwrap_or_else(|| self.client.info().best_hash);
 
-		let rs: Result<Vec<(CurrencyId, U256)>, _> = api.get_exchange_rate(at, token_id);
+		let rs: Result<Balance, _> = api.get_currency_amount_by_v_currency_amount(
+			at,
+			currency_id,
+			v_currency_id,
+			v_currency_amount,
+		);
 
 		match rs {
-			Ok(data) => Ok(data
-				.into_iter()
-				.map(|(token, rate)| (token, NumberOrHex::Hex(rate.into())))
-				.collect()),
+			Ok(data) => Ok(data),
 			Err(e) => Err(ErrorObject::owned(
 				ErrorCode::InternalError.code(),
 				"Failed to get find_block_epoch.",
diff --git a/pallets/vtoken-minting/src/benchmarking.rs b/pallets/vtoken-minting/src/benchmarking.rs
index 56691957e..181296889 100644
--- a/pallets/vtoken-minting/src/benchmarking.rs
+++ b/pallets/vtoken-minting/src/benchmarking.rs
@@ -20,7 +20,7 @@
 #![cfg(feature = "runtime-benchmarks")]
 
 use crate::{Pallet as VtokenMinting, *};
-use bifrost_primitives::{CurrencyId, TokenSymbol, VKSM};
+use bifrost_primitives::{CurrencyId, TokenSymbol, VtokenMintingOperator, VKSM};
 use frame_benchmarking::v1::{benchmarks, whitelisted_caller, BenchmarkError};
 use frame_support::{assert_ok, sp_runtime::traits::UniqueSaturatedFrom};
 use frame_system::RawOrigin;
@@ -73,7 +73,7 @@ benchmarks! {
 		let token = CurrencyId::Token(TokenSymbol::KSM);
 	}: _<T::RuntimeOrigin>(origin, token, TimeUnit::Era(1))
 
-	recreate_currency_ongoing_time_unit {
+	set_ongoing_time_unit {
 		let origin = T::ControlOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
 		let token = CurrencyId::Token(TokenSymbol::KSM);
 	}: _<T::RuntimeOrigin>(origin, token, TimeUnit::Era(1))
diff --git a/pallets/vtoken-minting/src/impls.rs b/pallets/vtoken-minting/src/impls.rs
new file mode 100644
index 000000000..d0315f99b
--- /dev/null
+++ b/pallets/vtoken-minting/src/impls.rs
@@ -0,0 +1,1008 @@
+// 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 <https://www.gnu.org/licenses/>.
+
+// Ensure we're `no_std` when compiling for Wasm.
+#![cfg_attr(not(feature = "std"), no_std)]
+
+use crate::{
+	AccountIdOf, BalanceOf, Config, CurrencyIdOf, Error, Event, Fees, HookIterationLimit,
+	MinTimeUnit, MinimumMint, MinimumRedeem, MintWithLockBlocks, OnRedeemSuccess, OngoingTimeUnit,
+	Pallet, RedeemTo, TimeUnitUnlockLedger, TokenPool, TokenUnlockLedger, TokenUnlockNextId,
+	UnlockDuration, UnlockId, UnlockingTotal, UserUnlockLedger, VtokenIncentiveCoef,
+	VtokenLockLedger, WeightInfo,
+};
+use bb_bnc::traits::BbBNCInterface;
+use bifrost_primitives::{
+	currency::BNC, AstarChainId, CurrencyId, CurrencyIdExt, HydrationChainId, InterlayChainId,
+	MantaChainId, RedeemType, SlpxOperator, TimeUnit, VTokenMintRedeemProvider,
+	VTokenSupplyProvider, VtokenMintingInterface, VtokenMintingOperator, FIL,
+};
+use frame_support::{
+	pallet_prelude::{DispatchResultWithPostInfo, *},
+	sp_runtime::{
+		traits::{AccountIdConversion, CheckedAdd, CheckedSub, UniqueSaturatedInto, Zero},
+		DispatchError, FixedU128, Permill, SaturatedConversion,
+	},
+	traits::LockIdentifier,
+	transactional, BoundedVec,
+};
+use frame_system::pallet_prelude::*;
+use orml_traits::{MultiCurrency, MultiLockableCurrency, XcmTransfer};
+use sp_core::U256;
+use sp_runtime::{helpers_128bit::multiply_by_rational_with_rounding, Rounding};
+use sp_std::{vec, vec::Vec};
+use xcm::{prelude::*, v4::Location};
+
+// incentive lock id for vtoken minted by user
+const INCENTIVE_LOCK_ID: LockIdentifier = *b"vmincntv";
+
+#[derive(Encode, Decode, Clone, Copy, Debug, PartialEq, Eq)]
+pub enum Operation {
+	Set,
+	Add,
+	Sub,
+}
+
+impl<T: Config> Pallet<T> {
+	/// Update the token pool amount.
+	/// Parameters:
+	/// - `currency_id`: The currency id.
+	/// - `currency_amount`: The currency amount.
+	/// - `operation`: The operation type. Set, Add, Sub.
+	pub fn update_token_pool(
+		currency_id: &CurrencyId,
+		currency_amount: &BalanceOf<T>,
+		operation: Operation,
+	) -> DispatchResult {
+		TokenPool::<T>::mutate(currency_id, |token_pool_amount| -> DispatchResult {
+			match operation {
+				Operation::Set => *token_pool_amount = *currency_amount,
+				Operation::Add =>
+					*token_pool_amount = token_pool_amount
+						.checked_add(currency_amount)
+						.ok_or(Error::<T>::CalculationOverflow)?,
+				Operation::Sub =>
+					*token_pool_amount = token_pool_amount
+						.checked_sub(currency_amount)
+						.ok_or(Error::<T>::CalculationOverflow)?,
+			}
+			Ok(())
+		})
+	}
+
+	/// Update the unlocking total amount.
+	/// Parameters:
+	/// - `currency_id`: The currency id.
+	/// - `currency_amount`: The currency amount.
+	/// - `operation`: The operation type. Set, Add, Sub.
+	pub fn update_unlocking_total(
+		currency_id: &CurrencyId,
+		currency_amount: &BalanceOf<T>,
+		operation: Operation,
+	) -> DispatchResult {
+		UnlockingTotal::<T>::mutate(currency_id, |unlocking_total_amount| -> DispatchResult {
+			match operation {
+				Operation::Set => *unlocking_total_amount = *currency_amount,
+				Operation::Add =>
+					*unlocking_total_amount = unlocking_total_amount
+						.checked_add(currency_amount)
+						.ok_or(Error::<T>::CalculationOverflow)?,
+				Operation::Sub =>
+					*unlocking_total_amount = unlocking_total_amount
+						.checked_sub(currency_amount)
+						.ok_or(Error::<T>::CalculationOverflow)?,
+			}
+			Ok(())
+		})
+	}
+
+	/// Update the token unlock ledger.
+	/// Parameters:
+	/// - `currency_id`: The currency id.
+	/// - `currency_amount`: The redeem currency amount.
+	/// - `unlock_id`: The unlock id.
+	/// - `lock_to_time_unit`: The lock to time unit.
+	/// - `redeem_type`: The redeem type.
+	/// Returns:
+	/// - `bool`: Whether the record is removed.
+	pub fn update_token_unlock_ledger(
+		redeemer: &AccountIdOf<T>,
+		currency_id: &CurrencyId,
+		currency_amount: &BalanceOf<T>,
+		unlock_id: &UnlockId,
+		lock_to_time_unit: &TimeUnit,
+		redeem_type: Option<RedeemType<AccountIdOf<T>>>,
+		operation: Operation,
+	) -> Result<bool, Error<T>> {
+		TokenUnlockLedger::<T>::mutate_exists(currency_id, unlock_id, |value| match operation {
+			Operation::Set | Operation::Add => {
+				let redeem_type = redeem_type.ok_or(Error::<T>::TimeUnitUnlockLedgerNotFound)?;
+				*value = Some((
+					redeemer.clone(),
+					*currency_amount,
+					lock_to_time_unit.clone(),
+					redeem_type,
+				));
+				Ok(false)
+			},
+			Operation::Sub => {
+				let (_, total_locked_amount, _, _) =
+					value.as_mut().ok_or(Error::<T>::TimeUnitUnlockLedgerNotFound)?;
+
+				if currency_amount >= total_locked_amount {
+					*value = None;
+					Ok(true)
+				} else {
+					*total_locked_amount = total_locked_amount
+						.checked_sub(currency_amount)
+						.ok_or(Error::<T>::CalculationOverflow)?;
+					Ok(false)
+				}
+			},
+		})
+	}
+
+	/// Update the time unit unlock ledger.
+	/// Parameters:
+	/// - `time_unit`: The time unit.
+	/// - `currency_id`: The currency id.
+	/// - `currency_amount`: The redeem currency amount.
+	/// - `unlock_id`: The unlock id.
+	/// - `operation`: The operation type. Set, Add, Sub.
+	/// - `is_remove_record`: Whether to remove the record.
+	pub fn update_time_unit_unlock_ledger(
+		time_unit: &TimeUnit,
+		currency_id: &CurrencyId,
+		currency_amount: &BalanceOf<T>,
+		unlock_id: &UnlockId,
+		operation: Operation,
+		is_remove_record: bool,
+	) -> DispatchResult {
+		TimeUnitUnlockLedger::<T>::mutate_exists(time_unit, currency_id, |unlocking_ledger| {
+			match operation {
+				Operation::Set | Operation::Add => match unlocking_ledger {
+					Some((total_locked, ledger_list, _token_id)) => {
+						ledger_list.try_push(*unlock_id).map_err(|_| Error::<T>::TooManyRedeems)?;
+
+						*total_locked = total_locked
+							.checked_add(&currency_amount)
+							.ok_or(Error::<T>::CalculationOverflow)?;
+					},
+					None =>
+						*unlocking_ledger = Some((
+							*currency_amount,
+							BoundedVec::try_from(vec![*unlock_id])
+								.map_err(|_| Error::<T>::TooManyRedeems)?,
+							*currency_id,
+						)),
+				},
+				Operation::Sub => {
+					let (total_locked_amount, ledger_list, _) = unlocking_ledger
+						.as_mut()
+						.ok_or(Error::<T>::TimeUnitUnlockLedgerNotFound)?;
+
+					if currency_amount >= total_locked_amount {
+						*unlocking_ledger = None;
+					} else {
+						*total_locked_amount = total_locked_amount
+							.checked_sub(currency_amount)
+							.ok_or(Error::<T>::CalculationOverflow)?;
+						if is_remove_record {
+							ledger_list.retain(|x| x != unlock_id);
+						}
+					}
+				},
+			}
+			Ok(())
+		})
+	}
+
+	/// Update the user unlock ledger.
+	/// Parameters:
+	/// - `account`: The account id.
+	/// - `currency_id`: The currency id.
+	/// - `currency_amount`: The redeem currency amount.
+	/// - `unlock_id`: The unlock id.
+	/// - `operation`: The operation type. Set, Add, Sub.
+	/// - `is_remove_record`: Whether to remove the record.
+	pub fn update_user_unlock_ledger(
+		account: &AccountIdOf<T>,
+		currency_id: &CurrencyId,
+		currency_amount: &BalanceOf<T>,
+		unlock_id: &UnlockId,
+		operation: Operation,
+		is_remove_record: bool,
+	) -> Result<(), Error<T>> {
+		UserUnlockLedger::<T>::mutate_exists(account, currency_id, |user_unlock_ledger| {
+			match operation {
+				Operation::Set | Operation::Add => match user_unlock_ledger {
+					Some((total_locked, ledger_list)) => {
+						ledger_list.try_push(*unlock_id).map_err(|_| Error::<T>::TooManyRedeems)?;
+
+						*total_locked = total_locked
+							.checked_add(&currency_amount)
+							.ok_or(Error::<T>::CalculationOverflow)?;
+					},
+					None => {
+						*user_unlock_ledger = Some((
+							*currency_amount,
+							BoundedVec::try_from(vec![*unlock_id])
+								.map_err(|_| Error::<T>::TooManyRedeems)?,
+						));
+					},
+				},
+				Operation::Sub => {
+					let (total_locked_amount, ledger_list) = user_unlock_ledger
+						.as_mut()
+						.ok_or(Error::<T>::TimeUnitUnlockLedgerNotFound)?;
+
+					if currency_amount >= total_locked_amount {
+						*user_unlock_ledger = None;
+					} else {
+						*total_locked_amount = total_locked_amount
+							.checked_sub(currency_amount)
+							.ok_or(Error::<T>::CalculationOverflow)?;
+						if is_remove_record {
+							ledger_list.retain(|x| x != unlock_id);
+						}
+					}
+				},
+			}
+			Ok(())
+		})
+	}
+
+	/// Update the token lock ledger.
+	/// Parameters:
+	/// - `account`: The account id.
+	/// - `currency_id`: The currency id.
+	/// - `currency_amount`: The redeem currency amount.
+	/// - `unlock_id`: The unlock id.
+	/// - `lock_to_time_unit`: The lock to time unit.
+	/// - `redeem_type`: The redeem type.
+	/// - `operation`: The operation type. Set, Add, Sub.
+	pub fn update_unlock_ledger(
+		account: &AccountIdOf<T>,
+		currency_id: &CurrencyId,
+		currency_amount: &BalanceOf<T>,
+		unlock_id: &UnlockId,
+		lock_to_time_unit: &TimeUnit,
+		redeem_type: Option<RedeemType<AccountIdOf<T>>>,
+		operation: Operation,
+	) -> Result<bool, DispatchError> {
+		let is_remove_record = Self::update_token_unlock_ledger(
+			account,
+			currency_id,
+			currency_amount,
+			unlock_id,
+			lock_to_time_unit,
+			redeem_type,
+			operation,
+		)?;
+		Self::update_user_unlock_ledger(
+			account,
+			currency_id,
+			currency_amount,
+			unlock_id,
+			operation,
+			is_remove_record,
+		)?;
+		Self::update_time_unit_unlock_ledger(
+			lock_to_time_unit,
+			currency_id,
+			currency_amount,
+			unlock_id,
+			operation,
+			is_remove_record,
+		)?;
+		Self::update_unlocking_total(&currency_id, &currency_amount, operation)?;
+		Ok(is_remove_record)
+	}
+
+	/// Mint without transfer.
+	/// Parameters:
+	/// - `minter`: The minter account id.
+	/// - `v_currency_id`: The v_currency id.
+	/// - `currency_id`: The currency id.
+	/// - `currency_amount`: The currency amount.
+	/// Returns:
+	/// - `(BalanceOf<T>, BalanceOf<T>, BalanceOf<T>)`: The currency amount, v_currency amount, mint
+	///   fee.
+	pub fn mint_without_transfer(
+		minter: &AccountIdOf<T>,
+		v_currency_id: CurrencyId,
+		currency_id: CurrencyId,
+		currency_amount: BalanceOf<T>,
+	) -> Result<(BalanceOf<T>, BalanceOf<T>, BalanceOf<T>), DispatchError> {
+		let (mint_rate, _) = Fees::<T>::get();
+		let mint_fee = mint_rate.mul_floor(currency_amount);
+		// Charging fees
+		T::MultiCurrency::transfer(currency_id, minter, &T::FeeAccount::get(), mint_fee)?;
+
+		let currency_amount =
+			currency_amount.checked_sub(&mint_fee).ok_or(Error::<T>::CalculationOverflow)?;
+		let v_currency_amount = Self::get_v_currency_amount_by_currency_amount(
+			currency_id,
+			v_currency_id,
+			currency_amount,
+		)?;
+
+		// Issue the corresponding v_currency to the user's account.
+		T::MultiCurrency::deposit(v_currency_id, minter, v_currency_amount)?;
+		// Increase the token pool amount.
+		Self::update_token_pool(&currency_id, &currency_amount, Operation::Add)?;
+
+		Ok((currency_amount, v_currency_amount, mint_fee))
+	}
+
+	/// Process redeem.
+	/// Parameters:
+	/// - `redeem_currency_id`: The redeem currency id.
+	/// - `redeemer`: The redeemer account id.
+	/// - `unlock_id`: The unlock id.
+	/// - `redeem_currency_amount`: The redeem currency amount.
+	/// - `entrance_account_balance`: The entrance account balance.
+	/// - `time_unit`: The time unit.
+	/// - `redeem_type`: The redeem type.
+	fn process_redeem(
+		redeem_currency_id: CurrencyId,
+		redeemer: AccountIdOf<T>,
+		unlock_id: &UnlockId,
+		redeem_currency_amount: BalanceOf<T>,
+		entrance_account_balance: BalanceOf<T>,
+		time_unit: TimeUnit,
+		redeem_type: RedeemType<AccountIdOf<T>>,
+	) -> DispatchResult {
+		let (redeem_currency_amount, redeem_to) = Self::transfer_to_by_redeem_type(
+			redeemer.clone(),
+			redeem_currency_id,
+			redeem_currency_amount,
+			entrance_account_balance,
+			redeem_type,
+		)?;
+
+		Self::update_unlock_ledger(
+			&redeemer,
+			&redeem_currency_id,
+			&redeem_currency_amount,
+			unlock_id,
+			&time_unit,
+			None,
+			Operation::Sub,
+		)?;
+
+		T::OnRedeemSuccess::on_redeem_success(
+			redeem_currency_id,
+			redeemer.clone(),
+			redeem_currency_amount,
+		);
+
+		Self::deposit_event(Event::RedeemSuccess {
+			redeemer,
+			unlock_id: *unlock_id,
+			currency_id: redeem_currency_id,
+			to: redeem_to,
+			currency_amount: redeem_currency_amount,
+		});
+		Ok(())
+	}
+
+	/// Transfer to by redeem type.
+	/// Parameters:
+	/// - `redeemer`: The redeemer account id.
+	/// - `redeem_currency_id`: The redeem currency id.
+	/// - `redeem_currency_amount`: The redeem currency amount.
+	/// - `entrance_account_balance`: The entrance account balance.
+	/// - `redeem_type`: The redeem type.
+	/// Returns:
+	/// - `(BalanceOf<T>, RedeemTo<T::AccountId>)`: The redeem currency amount, redeem to.
+	pub fn transfer_to_by_redeem_type(
+		redeemer: T::AccountId,
+		redeem_currency_id: CurrencyId,
+		mut redeem_currency_amount: BalanceOf<T>,
+		entrance_account_balance: BalanceOf<T>,
+		redeem_type: RedeemType<T::AccountId>,
+	) -> Result<(BalanceOf<T>, RedeemTo<T::AccountId>), DispatchError> {
+		let entrance_account = T::EntranceAccount::get().into_account_truncating();
+		if entrance_account_balance >= redeem_currency_amount {
+			if let RedeemType::Native = redeem_type {
+				let ed = T::MultiCurrency::minimum_balance(redeem_currency_id);
+				if redeem_currency_amount >= ed {
+					T::MultiCurrency::transfer(
+						redeem_currency_id,
+						&entrance_account,
+						&redeemer,
+						redeem_currency_amount,
+					)?;
+				}
+				return Ok((redeem_currency_amount, RedeemTo::Native(redeemer)));
+			}
+			let (dest, redeem_to) = match redeem_type {
+				RedeemType::Astar(receiver) => (
+					Location::new(
+						1,
+						[
+							Parachain(AstarChainId::get()),
+							AccountId32 {
+								network: None,
+								id: receiver.encode().try_into().unwrap(),
+							},
+						],
+					),
+					RedeemTo::Astar(receiver),
+				),
+				RedeemType::Hydradx(receiver) => (
+					Location::new(
+						1,
+						[
+							Parachain(HydrationChainId::get()),
+							AccountId32 {
+								network: None,
+								id: receiver.encode().try_into().unwrap(),
+							},
+						],
+					),
+					RedeemTo::Hydradx(receiver),
+				),
+				RedeemType::Interlay(receiver) => (
+					Location::new(
+						1,
+						[
+							Parachain(InterlayChainId::get()),
+							AccountId32 {
+								network: None,
+								id: receiver.encode().try_into().unwrap(),
+							},
+						],
+					),
+					RedeemTo::Interlay(receiver),
+				),
+				RedeemType::Manta(receiver) => (
+					Location::new(
+						1,
+						[
+							Parachain(MantaChainId::get()),
+							AccountId32 {
+								network: None,
+								id: receiver.encode().try_into().unwrap(),
+							},
+						],
+					),
+					RedeemTo::Manta(receiver),
+				),
+				RedeemType::Moonbeam(receiver) => (
+					Location::new(
+						1,
+						[
+							Parachain(T::MoonbeamChainId::get()),
+							AccountKey20 { network: None, key: receiver.to_fixed_bytes() },
+						],
+					),
+					RedeemTo::Moonbeam(receiver),
+				),
+				RedeemType::Native => {
+					unreachable!()
+				},
+			};
+			if redeem_currency_id == FIL {
+				let assets = vec![
+					(redeem_currency_id, redeem_currency_amount),
+					(BNC, T::BifrostSlpx::get_moonbeam_transfer_to_fee()),
+				];
+
+				T::XcmTransfer::transfer_multicurrencies(
+					entrance_account.clone(),
+					assets,
+					1,
+					dest,
+					Unlimited,
+				)?;
+			} else {
+				T::XcmTransfer::transfer(
+					entrance_account.clone(),
+					redeem_currency_id,
+					redeem_currency_amount,
+					dest,
+					Unlimited,
+				)?;
+			};
+			Ok((redeem_currency_amount, redeem_to))
+		} else {
+			redeem_currency_amount = entrance_account_balance;
+			let ed = T::MultiCurrency::minimum_balance(redeem_currency_id);
+			if redeem_currency_amount >= ed {
+				T::MultiCurrency::transfer(
+					redeem_currency_id,
+					&entrance_account,
+					&redeemer,
+					redeem_currency_amount,
+				)?;
+			}
+			Ok((redeem_currency_amount, RedeemTo::Native(redeemer)))
+		}
+	}
+
+	#[transactional]
+	pub fn handle_ledger_by_currency(currency: CurrencyId) -> DispatchResult {
+		let time_unit = MinTimeUnit::<T>::get(currency);
+		if let Some((_total_locked, ledger_list, currency_id)) =
+			TimeUnitUnlockLedger::<T>::get(&time_unit, currency)
+		{
+			for unlock_id in ledger_list.iter().take(HookIterationLimit::<T>::get() as usize) {
+				if let Some((account, unlock_amount, time_unit, redeem_type)) =
+					TokenUnlockLedger::<T>::get(currency_id, unlock_id)
+				{
+					let entrance_account_balance = T::MultiCurrency::free_balance(
+						currency_id,
+						&T::EntranceAccount::get().into_account_truncating(),
+					);
+					if entrance_account_balance == BalanceOf::<T>::zero() {
+						break;
+					}
+
+					Self::process_redeem(
+						currency_id,
+						account,
+						unlock_id,
+						unlock_amount,
+						entrance_account_balance,
+						time_unit,
+						redeem_type,
+					)?;
+				}
+			}
+		} else {
+			MinTimeUnit::<T>::mutate(currency, |time_unit| -> Result<(), Error<T>> {
+				let unlock_duration =
+					UnlockDuration::<T>::get(currency).ok_or(Error::<T>::UnlockDurationNotFound)?;
+				let ongoing_time =
+					OngoingTimeUnit::<T>::get(currency).ok_or(Error::<T>::OngoingTimeUnitNotSet)?;
+				let result_time_unit =
+					ongoing_time.add(unlock_duration).ok_or(Error::<T>::CalculationOverflow)?;
+				if result_time_unit.gt(time_unit) {
+					*time_unit = time_unit.clone().add_one();
+				}
+				Ok(())
+			})?;
+		};
+
+		Ok(())
+	}
+
+	pub fn do_mint(
+		minter: AccountIdOf<T>,
+		currency_id: CurrencyIdOf<T>,
+		currency_amount: BalanceOf<T>,
+		remark: BoundedVec<u8, ConstU32<32>>,
+		channel_id: Option<u32>,
+	) -> Result<BalanceOf<T>, DispatchError> {
+		ensure!(
+			currency_amount >= MinimumMint::<T>::get(currency_id),
+			Error::<T>::BelowMinimumMint
+		);
+		let v_currency_id = currency_id.to_vtoken().map_err(|_| Error::<T>::NotSupportTokenType)?;
+
+		let (currency_amount_excluding_fee, v_currency_amount, mint_fee) =
+			Self::mint_without_transfer(&minter, v_currency_id, currency_id, currency_amount)?;
+
+		// Transfer the user's token to EntranceAccount.
+		T::MultiCurrency::transfer(
+			currency_id,
+			&minter,
+			&T::EntranceAccount::get().into_account_truncating(),
+			currency_amount_excluding_fee,
+		)?;
+
+		// record the minting information for ChannelCommission module
+		T::ChannelCommission::record_mint_amount(channel_id, v_currency_id, v_currency_amount)?;
+
+		Self::deposit_event(Event::Minted {
+			minter,
+			currency_id,
+			currency_amount,
+			v_currency_amount,
+			mint_fee,
+			remark,
+			channel_id,
+		});
+		Ok(v_currency_amount.into())
+	}
+
+	pub fn do_redeem(
+		redeemer: AccountIdOf<T>,
+		v_currency_id: CurrencyIdOf<T>,
+		v_currency_amount: BalanceOf<T>,
+		redeem_type: RedeemType<AccountIdOf<T>>,
+	) -> DispatchResultWithPostInfo {
+		let currency_id = v_currency_id.to_token().map_err(|_| Error::<T>::NotSupportTokenType)?;
+		ensure!(
+			v_currency_amount >= MinimumRedeem::<T>::get(v_currency_id),
+			Error::<T>::BelowMinimumRedeem
+		);
+
+		// Charging fees
+		let (_, redeem_rate) = Fees::<T>::get();
+		let redeem_fee = redeem_rate.mul_floor(v_currency_amount);
+		T::MultiCurrency::transfer(
+			v_currency_id,
+			&redeemer,
+			&T::RedeemFeeAccount::get(),
+			redeem_fee,
+		)?;
+
+		// Calculate the currency amount by v_currency_amount
+		let v_currency_amount = v_currency_amount
+			.checked_sub(&redeem_fee)
+			.ok_or(Error::<T>::CalculationOverflow)?;
+		let currency_amount = Self::get_currency_amount_by_v_currency_amount(
+			currency_id,
+			v_currency_id,
+			v_currency_amount,
+		)?;
+
+		// Withdraw the token from redeemer
+		T::MultiCurrency::withdraw(v_currency_id, &redeemer, v_currency_amount)?;
+
+		// Calculate the time to be locked
+		let ongoing_time_unit =
+			OngoingTimeUnit::<T>::get(currency_id).ok_or(Error::<T>::OngoingTimeUnitNotSet)?;
+		let unlock_duration =
+			UnlockDuration::<T>::get(currency_id).ok_or(Error::<T>::UnlockDurationNotFound)?;
+		let lock_to_time_unit = ongoing_time_unit
+			.add(unlock_duration)
+			.ok_or(Error::<T>::UnlockDurationNotFound)?;
+
+		// Decrease the token pool amount
+		Self::update_token_pool(&currency_id, &currency_amount, Operation::Sub)?;
+
+		TokenUnlockNextId::<T>::mutate(&currency_id, |next_id| -> DispatchResultWithPostInfo {
+			Self::update_unlock_ledger(
+				&redeemer,
+				&currency_id,
+				&currency_amount,
+				&next_id,
+				&lock_to_time_unit,
+				Some(redeem_type),
+				Operation::Add,
+			)?;
+
+			Self::deposit_event(Event::Redeemed {
+				redeemer: redeemer.clone(),
+				currency_id,
+				v_currency_amount,
+				currency_amount,
+				redeem_fee,
+				unlock_id: *next_id,
+			});
+
+			// Increase the next unlock id
+			*next_id = next_id.checked_add(1).ok_or(Error::<T>::CalculationOverflow)?;
+
+			T::ChannelCommission::record_redeem_amount(v_currency_id, v_currency_amount)?;
+			let extra_weight = T::OnRedeemSuccess::on_redeemed(
+				redeemer,
+				currency_id,
+				currency_amount,
+				v_currency_amount,
+				redeem_fee,
+			);
+			Ok(Some(T::WeightInfo::redeem() + extra_weight).into())
+		})
+	}
+
+	pub fn incentive_pool_account() -> AccountIdOf<T> {
+		T::IncentivePoolAccount::get().into_account_truncating()
+	}
+
+	// to lock user vtoken for incentive minting
+	pub fn lock_vtoken_for_incentive_minting(
+		minter: AccountIdOf<T>,
+		v_currency_id: CurrencyIdOf<T>,
+		v_currency_amount: BalanceOf<T>,
+	) -> Result<(), Error<T>> {
+		// first, lock the vtoken
+		// second, record the lock in ledger
+
+		// check whether the minter has enough vtoken
+		T::MultiCurrency::ensure_can_withdraw(v_currency_id, &minter, v_currency_amount)
+			.map_err(|_| Error::<T>::NotEnoughBalance)?;
+
+		// new amount that should be locked
+		let mut new_lock_total = v_currency_amount;
+
+		// check the previous locked amount under the same v_currency_id from ledger
+		// and revise ledger to set the new_amount to be previous_amount + v_currency_amount
+		VtokenLockLedger::<T>::mutate_exists(
+			&minter,
+			&v_currency_id,
+			|v_token_lock_ledger| -> Result<(), Error<T>> {
+				// get the vtoken lock duration from VtokenIncentiveCoef
+				let lock_duration = MintWithLockBlocks::<T>::get(v_currency_id)
+					.ok_or(Error::<T>::IncentiveLockBlocksNotSet)?;
+				let current_block = frame_system::Pallet::<T>::block_number();
+				let due_block = current_block
+					.checked_add(&lock_duration)
+					.ok_or(Error::<T>::CalculationOverflow)?;
+
+				match v_token_lock_ledger {
+					Some((total_locked, lock_records)) => {
+						// check the total locked amount
+						new_lock_total = total_locked
+							.checked_add(&v_currency_amount)
+							.ok_or(Error::<T>::CalculationOverflow)?;
+
+						*total_locked = new_lock_total;
+
+						// push new item to the boundedvec of the ledger
+						lock_records
+							.try_push((v_currency_amount, due_block))
+							.map_err(|_| Error::<T>::TooManyLocks)?;
+					},
+					None =>
+						*v_token_lock_ledger = Some((
+							v_currency_amount,
+							BoundedVec::try_from(vec![(v_currency_amount, due_block)])
+								.map_err(|_| Error::<T>::TooManyLocks)?,
+						)),
+				}
+
+				// extend the locked amount to be new_lock_total
+				T::MultiCurrency::set_lock(
+					INCENTIVE_LOCK_ID,
+					v_currency_id,
+					&minter,
+					new_lock_total,
+				)
+				.map_err(|_| Error::<T>::NotEnoughBalance)
+			},
+		)
+	}
+
+	pub fn calculate_incentive_vtoken_amount(
+		minter: &AccountIdOf<T>,
+		v_currency_id: CurrencyIdOf<T>,
+		v_currency_amount: BalanceOf<T>,
+	) -> Result<BalanceOf<T>, Error<T>> {
+		// get the vtoken pool balance
+		let vtoken_pool_balance =
+			T::MultiCurrency::free_balance(v_currency_id, &Self::incentive_pool_account());
+		ensure!(vtoken_pool_balance > BalanceOf::<T>::zero(), Error::<T>::NotEnoughBalance);
+
+		// get current block number
+		let current_block_number: BlockNumberFor<T> = frame_system::Pallet::<T>::block_number();
+		// get the veBNC total amount
+		let vebnc_total_issuance = T::BbBNC::total_supply(current_block_number)
+			.map_err(|_| Error::<T>::VeBNCCheckingError)?;
+		ensure!(vebnc_total_issuance > BalanceOf::<T>::zero(), Error::<T>::BalanceZero);
+
+		// get the veBNC balance of the minter
+		let minter_vebnc_balance =
+			T::BbBNC::balance_of(minter, None).map_err(|_| Error::<T>::VeBNCCheckingError)?;
+		ensure!(minter_vebnc_balance > BalanceOf::<T>::zero(), Error::<T>::NotEnoughBalance);
+
+		// get the percentage of the veBNC balance of the minter to the total veBNC amount and
+		// get the square root of the percentage
+		let percentage = Permill::from_rational(minter_vebnc_balance, vebnc_total_issuance);
+		let sqrt_percentage =
+			FixedU128::from_inner(percentage * 1_000_000_000_000_000_000u128).sqrt();
+		let percentage = Permill::from_rational(
+			sqrt_percentage.into_inner(),
+			1_000_000_000_000_000_000u128.into(),
+		);
+		// get the total issuance of the vtoken
+		let v_currency_total_issuance = T::MultiCurrency::total_issuance(v_currency_id);
+
+		// get the incentive coef for the vtoken
+		let incentive_coef = VtokenIncentiveCoef::<T>::get(v_currency_id)
+			.ok_or(Error::<T>::IncentiveCoefNotFound)?;
+
+		// calculate the incentive amount, but mind the overflow
+		// incentive_amount = vtoken_pool_balance * incentive_coef * v_currency_amount *
+		// sqrt_percentage / v_currency_total_issuance
+		let incentive_amount =
+			U256::from(percentage.mul_ceil(vtoken_pool_balance).saturated_into::<u128>())
+				.checked_mul(U256::from(incentive_coef))
+				.and_then(|x| x.checked_mul(U256::from(v_currency_amount.saturated_into::<u128>())))
+				// .and_then(|x| x.checked_mul(percentage))
+				.and_then(|x| {
+					x.checked_div(U256::from(v_currency_total_issuance.saturated_into::<u128>()))
+				})
+				// first turn into u128,then use unique_saturated_into BalanceOf<T>
+				.map(|x| x.saturated_into::<u128>())
+				.map(|x| x.unique_saturated_into())
+				.ok_or(Error::<T>::CalculationOverflow)?;
+
+		Ok(incentive_amount)
+	}
+}
+
+impl<T: Config> VtokenMintingOperator<CurrencyId, BalanceOf<T>, AccountIdOf<T>, TimeUnit>
+	for Pallet<T>
+{
+	fn get_token_pool(currency_id: CurrencyId) -> BalanceOf<T> {
+		TokenPool::<T>::get(currency_id)
+	}
+
+	fn increase_token_pool(
+		currency_id: CurrencyId,
+		currency_amount: BalanceOf<T>,
+	) -> DispatchResult {
+		Self::update_token_pool(&currency_id, &currency_amount, Operation::Add)
+	}
+
+	fn decrease_token_pool(
+		currency_id: CurrencyId,
+		currency_amount: BalanceOf<T>,
+	) -> DispatchResult {
+		Self::update_token_pool(&currency_id, &currency_amount, Operation::Sub)
+	}
+
+	fn update_ongoing_time_unit(currency_id: CurrencyId, time_unit: TimeUnit) -> DispatchResult {
+		OngoingTimeUnit::<T>::mutate(currency_id, |time_unit_old| -> Result<(), Error<T>> {
+			*time_unit_old = Some(time_unit);
+			Ok(())
+		})?;
+
+		Ok(())
+	}
+
+	fn get_ongoing_time_unit(currency_id: CurrencyId) -> Option<TimeUnit> {
+		OngoingTimeUnit::<T>::get(currency_id)
+	}
+
+	fn get_unlock_records(
+		currency_id: CurrencyId,
+		time_unit: TimeUnit,
+	) -> Option<(BalanceOf<T>, Vec<u32>)> {
+		if let Some((balance, list, _)) = TimeUnitUnlockLedger::<T>::get(&time_unit, currency_id) {
+			Some((balance, list.into_inner()))
+		} else {
+			None
+		}
+	}
+
+	fn get_entrance_and_exit_accounts() -> (AccountIdOf<T>, AccountIdOf<T>) {
+		(
+			T::EntranceAccount::get().into_account_truncating(),
+			T::ExitAccount::get().into_account_truncating(),
+		)
+	}
+
+	fn get_token_unlock_ledger(
+		currency_id: CurrencyId,
+		index: u32,
+	) -> Option<(AccountIdOf<T>, BalanceOf<T>, TimeUnit, RedeemType<AccountIdOf<T>>)> {
+		TokenUnlockLedger::<T>::get(currency_id, index)
+	}
+
+	fn get_moonbeam_parachain_id() -> u32 {
+		T::MoonbeamChainId::get()
+	}
+}
+
+impl<T: Config> VtokenMintingInterface<AccountIdOf<T>, CurrencyIdOf<T>, BalanceOf<T>>
+	for Pallet<T>
+{
+	fn mint(
+		exchanger: AccountIdOf<T>,
+		currency_id: CurrencyIdOf<T>,
+		currency_amount: BalanceOf<T>,
+		remark: BoundedVec<u8, ConstU32<32>>,
+		channel_id: Option<u32>,
+	) -> Result<BalanceOf<T>, DispatchError> {
+		Self::do_mint(exchanger, currency_id, currency_amount, remark, channel_id)
+	}
+
+	fn redeem(
+		exchanger: AccountIdOf<T>,
+		v_currency_id: CurrencyIdOf<T>,
+		v_currency_amount: BalanceOf<T>,
+	) -> DispatchResultWithPostInfo {
+		Self::do_redeem(exchanger, v_currency_id, v_currency_amount, RedeemType::Native)
+	}
+
+	fn slpx_redeem(
+		exchanger: AccountIdOf<T>,
+		v_currency_id: CurrencyIdOf<T>,
+		v_currency_amount: BalanceOf<T>,
+		redeem_type: RedeemType<AccountIdOf<T>>,
+	) -> DispatchResultWithPostInfo {
+		Self::do_redeem(exchanger, v_currency_id, v_currency_amount, redeem_type)
+	}
+
+	fn get_v_currency_amount_by_currency_amount(
+		currency_id: CurrencyIdOf<T>,
+		v_currency_id: CurrencyIdOf<T>,
+		currency_amount: BalanceOf<T>,
+	) -> Result<BalanceOf<T>, DispatchError> {
+		let token_pool_amount = TokenPool::<T>::get(currency_id);
+		let v_currency_total_issuance = T::MultiCurrency::total_issuance(v_currency_id);
+
+		if BalanceOf::<T>::zero().eq(&token_pool_amount) {
+			Ok(currency_amount)
+		} else {
+			Ok(multiply_by_rational_with_rounding(
+				currency_amount.saturated_into::<u128>(),
+				v_currency_total_issuance.saturated_into::<u128>(),
+				token_pool_amount.saturated_into::<u128>(),
+				Rounding::Down,
+			)
+			.ok_or(Error::<T>::CalculationOverflow)?
+			.unique_saturated_into())
+		}
+	}
+
+	/// Get the v_currency amount by currency amount.
+	/// Parameters:
+	/// - `currency_id`: The currency id.
+	/// - `v_currency_id`: The v_currency id.
+	/// - `currency_amount`: The currency amount.
+	/// Returns:
+	/// - `Result`: The v_currency amount.
+	fn get_currency_amount_by_v_currency_amount(
+		currency_id: CurrencyIdOf<T>,
+		v_currency_id: CurrencyIdOf<T>,
+		v_currency_amount: BalanceOf<T>,
+	) -> Result<BalanceOf<T>, DispatchError> {
+		let token_pool_amount = TokenPool::<T>::get(currency_id);
+		let v_currency_total_issuance = T::MultiCurrency::total_issuance(v_currency_id);
+
+		if BalanceOf::<T>::zero().eq(&v_currency_total_issuance) {
+			Ok(v_currency_amount)
+		} else {
+			Ok(multiply_by_rational_with_rounding(
+				v_currency_amount.saturated_into::<u128>(),
+				token_pool_amount.saturated_into::<u128>(),
+				v_currency_total_issuance.saturated_into::<u128>(),
+				Rounding::Down,
+			)
+			.ok_or(Error::<T>::CalculationOverflow)?
+			.unique_saturated_into())
+		}
+	}
+
+	fn get_minimums_redeem(v_currency_id: CurrencyIdOf<T>) -> BalanceOf<T> {
+		MinimumRedeem::<T>::get(v_currency_id)
+	}
+
+	fn get_token_pool(currency_id: CurrencyId) -> BalanceOf<T> {
+		TokenPool::<T>::get(currency_id)
+	}
+
+	fn get_moonbeam_parachain_id() -> u32 {
+		T::MoonbeamChainId::get()
+	}
+}
+
+impl<T: Config> VTokenSupplyProvider<CurrencyIdOf<T>, BalanceOf<T>> for Pallet<T> {
+	fn get_vtoken_supply(vtoken: CurrencyIdOf<T>) -> Option<BalanceOf<T>> {
+		if CurrencyId::is_vtoken(&vtoken) {
+			Some(T::MultiCurrency::total_issuance(vtoken))
+		} else {
+			None
+		}
+	}
+
+	fn get_token_supply(token: CurrencyIdOf<T>) -> Option<BalanceOf<T>> {
+		if CurrencyId::is_token(&token) | CurrencyId::is_native(&token) {
+			Some(TokenPool::<T>::get(token))
+		} else {
+			None
+		}
+	}
+}
diff --git a/pallets/vtoken-minting/src/lib.rs b/pallets/vtoken-minting/src/lib.rs
index b145c2de7..849633dab 100644
--- a/pallets/vtoken-minting/src/lib.rs
+++ b/pallets/vtoken-minting/src/lib.rs
@@ -28,44 +28,37 @@ mod tests;
 #[cfg(feature = "runtime-benchmarks")]
 mod benchmarking;
 
+pub mod impls;
 pub mod migration;
 pub mod traits;
 pub mod weights;
 pub use weights::WeightInfo;
 
+use crate::impls::Operation;
 use bb_bnc::traits::BbBNCInterface;
-use bifrost_asset_registry::AssetMetadata;
 use bifrost_primitives::{
-	CurrencyId, CurrencyIdConversion, CurrencyIdExt, CurrencyIdMapping, CurrencyIdRegister,
-	RedeemType, SlpOperator, SlpxOperator, TimeUnit, VTokenMintRedeemProvider,
-	VTokenSupplyProvider, VtokenMintingInterface, VtokenMintingOperator,
+	CurrencyId, RedeemType, SlpxOperator, TimeUnit, VTokenMintRedeemProvider,
 };
 use frame_support::{
-	pallet_prelude::*,
+	pallet_prelude::{DispatchResultWithPostInfo, *},
 	sp_runtime::{
-		traits::{
-			AccountIdConversion, CheckedAdd, CheckedSub, Saturating, UniqueSaturatedInto, Zero,
-		},
-		ArithmeticError, DispatchError, FixedU128, Permill, SaturatedConversion,
+		traits::{CheckedAdd, CheckedSub, Saturating, Zero},
+		DispatchError, Permill,
 	},
 	traits::LockIdentifier,
-	transactional, BoundedVec, PalletId,
+	BoundedVec, PalletId,
 };
 use frame_system::pallet_prelude::*;
 use log;
-use orml_traits::{MultiCurrency, MultiLockableCurrency};
+use orml_traits::{MultiCurrency, MultiLockableCurrency, XcmTransfer};
 pub use pallet::*;
-use sp_core::U256;
-use sp_std::{vec, vec::Vec};
+use sp_std::vec;
 pub use traits::*;
-use xcm::v3::MultiLocation;
 
 pub type AccountIdOf<T> = <T as frame_system::Config>::AccountId;
-
 pub type CurrencyIdOf<T> = <<T as Config>::MultiCurrency as MultiCurrency<
 	<T as frame_system::Config>::AccountId,
 >>::CurrencyId;
-
 pub type BalanceOf<T> = <<T as Config>::MultiCurrency as MultiCurrency<AccountIdOf<T>>>::Balance;
 
 pub type UnlockId = u32;
@@ -76,12 +69,6 @@ const INCENTIVE_LOCK_ID: LockIdentifier = *b"vmincntv";
 #[frame_support::pallet]
 pub mod pallet {
 	use super::*;
-	use bifrost_primitives::{
-		currency::BNC, AstarChainId, HydrationChainId, InterlayChainId, MantaChainId, FIL,
-	};
-	use frame_support::pallet_prelude::DispatchResultWithPostInfo;
-	use orml_traits::XcmTransfer;
-	use xcm::{prelude::*, v4::Location};
 
 	#[pallet::pallet]
 	pub struct Pallet<T>(_);
@@ -89,13 +76,13 @@ pub mod pallet {
 	#[pallet::config]
 	pub trait Config: frame_system::Config {
 		type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
-
-		type MultiCurrency: MultiCurrency<AccountIdOf<Self>, CurrencyId = CurrencyId>
-			+ MultiLockableCurrency<AccountIdOf<Self>>;
-
+		/// Set default weight.
+		type WeightInfo: WeightInfo;
 		/// The only origin that can edit token issuer list
 		type ControlOrigin: EnsureOrigin<Self::RuntimeOrigin>;
-
+		/// The multi currency trait.
+		type MultiCurrency: MultiCurrency<AccountIdOf<Self>, CurrencyId = CurrencyId>
+			+ MultiLockableCurrency<AccountIdOf<Self>>;
 		/// Handler to notify the runtime when redeem success
 		/// If you don't need it, you can specify the type `()`.
 		type OnRedeemSuccess: OnRedeemSuccess<
@@ -103,30 +90,39 @@ pub mod pallet {
 			CurrencyIdOf<Self>,
 			BalanceOf<Self>,
 		>;
-
-		/// xtokens xcm transfer interface
+		/// Xtokens xcm transfer interface
 		type XcmTransfer: XcmTransfer<AccountIdOf<Self>, BalanceOf<Self>, CurrencyIdOf<Self>>;
+		/// Slpx operator
+		type BifrostSlpx: SlpxOperator<BalanceOf<Self>>;
+		/// bbBNC interface
+		type BbBNC: BbBNCInterface<
+			AccountIdOf<Self>,
+			CurrencyIdOf<Self>,
+			BalanceOf<Self>,
+			BlockNumberFor<Self>,
+		>;
+		/// Channel commission provider
+		type ChannelCommission: VTokenMintRedeemProvider<CurrencyId, BalanceOf<Self>>;
 
-		/// The amount of mint
+		/// Maximum unlock id of user
 		#[pallet::constant]
 		type MaximumUnlockIdOfUser: Get<u32>;
-
+		/// Maximum unlock id of time unit
 		#[pallet::constant]
 		type MaximumUnlockIdOfTimeUnit: Get<u32>;
-
-		// maximum unlocked vtoken records minted in an incentive mode
+		/// Maximum unlocked vtoken records minted in an incentive mode
 		#[pallet::constant]
 		type MaxLockRecords: Get<u32>;
-
+		/// Currency receive account
 		#[pallet::constant]
 		type EntranceAccount: Get<PalletId>;
-
+		/// Currency exit account
 		#[pallet::constant]
 		type ExitAccount: Get<PalletId>;
-
+		/// Fee account
 		#[pallet::constant]
 		type FeeAccount: Get<Self::AccountId>;
-
+		/// Redeem fee account
 		#[pallet::constant]
 		type RedeemFeeAccount: Get<Self::AccountId>;
 
@@ -138,192 +134,249 @@ pub mod pallet {
 
 		#[pallet::constant]
 		type MoonbeamChainId: Get<u32>;
-
-		type BifrostSlp: SlpOperator<CurrencyId>;
-
-		type BifrostSlpx: SlpxOperator<BalanceOf<Self>>;
-
-		// bbBNC interface
-		type BbBNC: BbBNCInterface<
-			AccountIdOf<Self>,
-			CurrencyIdOf<Self>,
-			BalanceOf<Self>,
-			BlockNumberFor<Self>,
-		>;
-
-		type CurrencyIdConversion: CurrencyIdConversion<CurrencyId>;
-
-		type CurrencyIdRegister: CurrencyIdRegister<CurrencyId>;
-
-		type ChannelCommission: VTokenMintRedeemProvider<CurrencyId, BalanceOf<Self>>;
-
-		type AssetIdMaps: CurrencyIdMapping<
-			CurrencyId,
-			MultiLocation,
-			AssetMetadata<BalanceOf<Self>>,
-		>;
-
-		/// Set default weight.
-		type WeightInfo: WeightInfo;
 	}
 
 	#[pallet::event]
 	#[pallet::generate_deposit(pub(super) fn deposit_event)]
 	pub enum Event<T: Config> {
+		/// Vtoken minted successfully.
 		Minted {
-			address: AccountIdOf<T>,
-			token_id: CurrencyIdOf<T>,
-			token_amount: BalanceOf<T>,
-			vtoken_amount: BalanceOf<T>,
-			fee: BalanceOf<T>,
+			/// The minter account.
+			minter: AccountIdOf<T>,
+			/// The currency id minted.
+			currency_id: CurrencyIdOf<T>,
+			/// The currency amount minted.
+			currency_amount: BalanceOf<T>,
+			/// The v_currency amount minted.
+			v_currency_amount: BalanceOf<T>,
+			/// The mint fee.
+			mint_fee: BalanceOf<T>,
+			/// The remark of minting.
 			remark: BoundedVec<u8, ConstU32<32>>,
+			/// The channel id of minting.
 			channel_id: Option<u32>,
 		},
+		///	Vtoken redeemed successfully.
 		Redeemed {
-			address: AccountIdOf<T>,
-			token_id: CurrencyIdOf<T>,
-			token_amount: BalanceOf<T>,
-			vtoken_amount: BalanceOf<T>,
-			fee: BalanceOf<T>,
+			/// The redeemer account.
+			redeemer: AccountIdOf<T>,
+			/// The currency id redeemed.
+			currency_id: CurrencyIdOf<T>,
+			/// Will be received currency amount.
+			currency_amount: BalanceOf<T>,
+			/// The v_currency amount redeemed.
+			v_currency_amount: BalanceOf<T>,
+			/// The redeem fee.
+			redeem_fee: BalanceOf<T>,
+			/// The unlock_id of redeeming.
 			unlock_id: UnlockId,
 		},
+		/// Process redeem successfully.
 		RedeemSuccess {
+			/// The redeemer account.
+			redeemer: AccountIdOf<T>,
+			/// The unlock_id redeemed.
 			unlock_id: UnlockId,
-			token_id: CurrencyIdOf<T>,
+			/// The currency id redeemed.
+			currency_id: CurrencyIdOf<T>,
+			/// Will transfer to this account.
 			to: RedeemTo<AccountIdOf<T>>,
-			token_amount: BalanceOf<T>,
+			/// The redeem amount.
+			currency_amount: BalanceOf<T>,
 		},
+		/// Vtoken rebonded successfully.
 		Rebonded {
-			address: AccountIdOf<T>,
-			token_id: CurrencyIdOf<T>,
-			token_amount: BalanceOf<T>,
-			vtoken_amount: BalanceOf<T>,
+			/// The rebonder account.
+			rebonder: AccountIdOf<T>,
+			/// The currency id rebonded.
+			currency_id: CurrencyIdOf<T>,
+			/// The currency amount rebonded.
+			currency_amount: BalanceOf<T>,
+			/// The v_currency amount rebonded.
+			v_currency_amount: BalanceOf<T>,
+			/// Mint fee
 			fee: BalanceOf<T>,
 		},
+		/// Vtoken rebonded by unlock_id successfully.
 		RebondedByUnlockId {
-			address: AccountIdOf<T>,
-			token_id: CurrencyIdOf<T>,
-			token_amount: BalanceOf<T>,
-			vtoken_amount: BalanceOf<T>,
+			/// The rebonder account.
+			rebonder: AccountIdOf<T>,
+			/// The currency id rebonded.
+			currency_id: CurrencyIdOf<T>,
+			/// The currency amount rebonded.
+			currency_amount: BalanceOf<T>,
+			/// The v_currency amount rebonded.
+			v_currency_amount: BalanceOf<T>,
+			/// Mint fee
 			fee: BalanceOf<T>,
+			/// The unlock_id rebonded.
 			unlock_id: UnlockId,
 		},
+		/// Set unlock duration.
 		UnlockDurationSet {
-			token_id: CurrencyIdOf<T>,
+			/// The currency id set unlock duration.
+			currency_id: CurrencyIdOf<T>,
+			/// The unlock duration set.
 			unlock_duration: TimeUnit,
 		},
+		/// Set minimum mint amount.
 		MinimumMintSet {
-			token_id: CurrencyIdOf<T>,
-			amount: BalanceOf<T>,
+			/// The currency id set minimum mint amount.
+			currency_id: CurrencyIdOf<T>,
+			/// The minimum mint amount set.
+			minimum_amount: BalanceOf<T>,
 		},
+		/// Set minimum redeem amount.
 		MinimumRedeemSet {
-			token_id: CurrencyIdOf<T>,
-			amount: BalanceOf<T>,
+			/// The currency id set minimum redeem amount.
+			currency_id: CurrencyIdOf<T>,
+			/// The minimum redeem amount set.
+			minimum_amount: BalanceOf<T>,
 		},
+		/// Support rebond token added.
 		SupportRebondTokenAdded {
-			token_id: CurrencyIdOf<T>,
+			/// The currency id support rebond.
+			currency_id: CurrencyIdOf<T>,
 		},
+		/// Support rebond token removed.
 		SupportRebondTokenRemoved {
-			token_id: CurrencyIdOf<T>,
+			/// The currency id remove support rebond.
+			currency_id: CurrencyIdOf<T>,
 		},
-		/// Several fees has been set.
+		/// Set mint fee and redeem fee.
 		FeeSet {
+			/// The mint fee rate set.
 			mint_fee: Permill,
+			/// The redeem fee rate set.
 			redeem_fee: Permill,
-			// hosting_fee: BalanceOf<T>,
-		},
-		HookIterationLimitSet {
-			limit: u32,
 		},
+		/// Set hook iteration limit.
+		HookIterationLimitSet { limit: u32 },
+		/// Set unlock total amount.
 		UnlockingTotalSet {
-			token_id: CurrencyIdOf<T>,
-			amount: BalanceOf<T>,
+			/// The currency id set unlock total amount.
+			currency_id: CurrencyIdOf<T>,
+			/// The unlock total amount set.
+			currency_amount: BalanceOf<T>,
 		},
+		/// Set minimum time unit.
 		MinTimeUnitSet {
-			token_id: CurrencyIdOf<T>,
+			/// The currency id set minimum time unit.
+			currency_id: CurrencyIdOf<T>,
+			/// The minimum time unit set.
 			time_unit: TimeUnit,
 		},
-		FastRedeemFailed {
-			err: DispatchError,
-		},
-		CurrencyTimeUnitRecreated {
-			token_id: CurrencyIdOf<T>,
+		/// Fast redeem failed.
+		FastRedeemFailed { err: DispatchError },
+		/// Set ongoing time unit.
+		SetOngoingTimeUnit {
+			/// The currency id set ongoing time unit.
+			currency_id: CurrencyIdOf<T>,
+			/// The ongoing time unit set.
 			time_unit: TimeUnit,
 		},
+		/// Incentivized minting.
 		IncentivizedMinting {
 			address: AccountIdOf<T>,
-			token_id: CurrencyIdOf<T>,
-			token_amount: BalanceOf<T>,
+			currency_id: CurrencyIdOf<T>,
+			currency_amount: BalanceOf<T>,
 			locked_vtoken_amount: BalanceOf<T>,
 			incentive_vtoken_amount: BalanceOf<T>,
 		},
-		VtokenIncentiveCoefSet {
-			vtoken_id: CurrencyIdOf<T>,
-			coefficient: Option<u128>,
-		},
+		/// Incentive coefficient set.
+		VtokenIncentiveCoefSet { v_currency_id: CurrencyIdOf<T>, coefficient: Option<u128> },
+		/// Incentive lock blocks set.
 		VtokenIncentiveLockBlocksSet {
-			vtoken_id: CurrencyIdOf<T>,
+			v_currency_id: CurrencyIdOf<T>,
 			blocks: Option<BlockNumberFor<T>>,
 		},
 	}
 
 	#[pallet::error]
 	pub enum Error<T> {
+		/// Below minimum mint amount.
 		BelowMinimumMint,
+		/// Below minimum redeem amount.
 		BelowMinimumRedeem,
 		/// Invalid token to rebond.
 		InvalidRebondToken,
 		/// Token type not support.
 		NotSupportTokenType,
+		/// Not enough balance to unlock.
 		NotEnoughBalanceToUnlock,
+		/// Token unlock ledger not found.
 		TokenToRebondNotZero,
+		/// Ongoing time unit not set.
 		OngoingTimeUnitNotSet,
+		/// Token unlock ledger not found.
 		TokenUnlockLedgerNotFound,
+		/// User unlock ledger not found.
 		UserUnlockLedgerNotFound,
+		/// Time unit unlock ledger not found.
 		TimeUnitUnlockLedgerNotFound,
+		/// Unlock duration not found.
 		UnlockDurationNotFound,
+		/// Unexpected error.
 		Unexpected,
+		/// Calculation overflow.
 		CalculationOverflow,
+		/// Exceed maximum unlock id.
 		ExceedMaximumUnlockId,
+		/// Too many redeems.
 		TooManyRedeems,
-		CanNotRedeem,
+		/// Can not rebond.
 		CanNotRebond,
+		/// Not enough balance.
 		NotEnoughBalance,
+		/// veBNC checking error.
 		VeBNCCheckingError,
+		/// IncentiveCoef not found.
 		IncentiveCoefNotFound,
+		/// Too many locks.
 		TooManyLocks,
-		ConvertError,
+		/// No unlock record.
 		NoUnlockRecord,
+		/// Fail to remove lock.
 		FailToRemoveLock,
+		/// Balance not zero.
 		BalanceZero,
+		/// IncentiveLockBlocksNotSet
 		IncentiveLockBlocksNotSet,
 	}
 
+	/// The mint fee and redeem fee.
 	#[pallet::storage]
 	pub type Fees<T: Config> = StorageValue<_, (Permill, Permill), ValueQuery>;
 
+	/// Token pool amount
 	#[pallet::storage]
 	pub type TokenPool<T: Config> =
 		StorageMap<_, Twox64Concat, CurrencyIdOf<T>, BalanceOf<T>, ValueQuery>;
 
+	/// Unlock duration for each currency
 	#[pallet::storage]
 	pub type UnlockDuration<T: Config> = StorageMap<_, Twox64Concat, CurrencyIdOf<T>, TimeUnit>;
 
+	/// Ongoing time unit for each currency
 	#[pallet::storage]
 	pub type OngoingTimeUnit<T: Config> = StorageMap<_, Twox64Concat, CurrencyIdOf<T>, TimeUnit>;
 
+	/// Minimum mint amount for each currency
 	#[pallet::storage]
 	pub type MinimumMint<T: Config> =
 		StorageMap<_, Twox64Concat, CurrencyIdOf<T>, BalanceOf<T>, ValueQuery>;
 
+	/// Minimum redeem amount for each currency
 	#[pallet::storage]
 	pub type MinimumRedeem<T: Config> =
 		StorageMap<_, Twox64Concat, CurrencyIdOf<T>, BalanceOf<T>, ValueQuery>;
 
+	/// Next unlock id for each currency
 	#[pallet::storage]
 	pub type TokenUnlockNextId<T: Config> =
 		StorageMap<_, Twox64Concat, CurrencyIdOf<T>, u32, ValueQuery>;
 
+	/// According to currency_id and unlock_id, unlock information are stored.
 	#[pallet::storage]
 	pub type TokenUnlockLedger<T: Config> = StorageDoubleMap<
 		_,
@@ -331,10 +384,20 @@ pub mod pallet {
 		CurrencyIdOf<T>,
 		Blake2_128Concat,
 		UnlockId,
-		(T::AccountId, BalanceOf<T>, TimeUnit, RedeemType<AccountIdOf<T>>),
+		(
+			// redeemer account
+			T::AccountId,
+			// redeem amount
+			BalanceOf<T>,
+			// lock to time unit
+			TimeUnit,
+			// redeem type
+			RedeemType<AccountIdOf<T>>,
+		),
 		OptionQuery,
 	>;
 
+	/// According to the user's account, the locked amount and unlock id list are stored.
 	#[pallet::storage]
 	pub type UserUnlockLedger<T: Config> = StorageDoubleMap<
 		_,
@@ -342,10 +405,16 @@ pub mod pallet {
 		AccountIdOf<T>,
 		Blake2_128Concat,
 		CurrencyIdOf<T>,
-		(BalanceOf<T>, BoundedVec<UnlockId, T::MaximumUnlockIdOfUser>),
+		(
+			// Total locked amount
+			BalanceOf<T>,
+			// UnlockId list
+			BoundedVec<UnlockId, T::MaximumUnlockIdOfUser>,
+		),
 		OptionQuery,
 	>;
 
+	/// The total amount of tokens that are currently locked for unlocking.
 	#[pallet::storage]
 	pub type TimeUnitUnlockLedger<T: Config> = StorageDoubleMap<
 		_,
@@ -353,21 +422,32 @@ pub mod pallet {
 		TimeUnit,
 		Blake2_128Concat,
 		CurrencyIdOf<T>,
-		(BalanceOf<T>, BoundedVec<UnlockId, T::MaximumUnlockIdOfTimeUnit>, CurrencyIdOf<T>),
+		(
+			// Total locked amount
+			BalanceOf<T>,
+			// UnlockId list
+			BoundedVec<UnlockId, T::MaximumUnlockIdOfTimeUnit>,
+			// CurrencyId
+			CurrencyIdOf<T>,
+		),
 		OptionQuery,
 	>;
 
+	/// The total amount of tokens that are currently locked for rebonding.
 	#[pallet::storage]
 	pub type TokenToRebond<T: Config> = StorageMap<_, Twox64Concat, CurrencyIdOf<T>, BalanceOf<T>>;
 
+	/// The min time unit for each currency
 	#[pallet::storage]
 	pub type MinTimeUnit<T: Config> =
 		StorageMap<_, Twox64Concat, CurrencyIdOf<T>, TimeUnit, ValueQuery>;
 
+	/// The total amount of tokens that are currently unlocking.
 	#[pallet::storage]
 	pub type UnlockingTotal<T: Config> =
 		StorageMap<_, Twox64Concat, CurrencyIdOf<T>, BalanceOf<T>, ValueQuery>;
 
+	/// The hook iteration limit
 	#[pallet::storage]
 	pub type HookIterationLimit<T: Config> = StorageValue<_, u32, ValueQuery>;
 
@@ -397,17 +477,20 @@ pub mod pallet {
 	#[pallet::hooks]
 	impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
 		fn on_initialize(_n: BlockNumberFor<T>) -> Weight {
-			Self::handle_on_initialize()
-				.map_err(|err| {
-					Self::deposit_event(Event::FastRedeemFailed { err });
-					log::error!(
-						target: "runtime::vtoken-minting",
-						"Received invalid justification for {:?}",
-						err,
-					);
-					err
-				})
-				.ok();
+			for currency in OngoingTimeUnit::<T>::iter_keys() {
+				let result = Self::handle_ledger_by_currency(currency);
+				match result {
+					Ok(_) => (),
+					Err(err) => {
+						Self::deposit_event(Event::FastRedeemFailed { err });
+						log::error!(
+							target: "runtime::vtoken-minting",
+							"Received invalid justification for {:?}",
+							err,
+						);
+					},
+				}
+			}
 
 			T::WeightInfo::on_initialize()
 		}
@@ -415,401 +498,293 @@ pub mod pallet {
 
 	#[pallet::call]
 	impl<T: Config> Pallet<T> {
+		/// Mint v_currency by transferring currency to entrance_account.
+		/// The minted v_currency will be deposited to the minter's account.
+		/// Parameters:
+		/// - `currency_id`: The currency to mint.
+		/// - `currency_amount`: The amount of currency to mint.
+		/// - `remark`: The remark of minting.
+		/// - `channel_id`: The channel id of minting.
 		#[pallet::call_index(0)]
 		#[pallet::weight(T::WeightInfo::mint())]
 		pub fn mint(
 			origin: OriginFor<T>,
-			token_id: CurrencyIdOf<T>,
-			token_amount: BalanceOf<T>,
+			currency_id: CurrencyIdOf<T>,
+			currency_amount: BalanceOf<T>,
 			remark: BoundedVec<u8, ConstU32<32>>,
 			channel_id: Option<u32>,
 		) -> DispatchResult {
 			// Check origin
-			let exchanger = ensure_signed(origin)?;
-			Self::mint_inner(exchanger, token_id, token_amount, remark, channel_id).map(|_| ())
+			let minter = ensure_signed(origin)?;
+			Self::do_mint(minter, currency_id, currency_amount, remark, channel_id)?;
+			Ok(())
 		}
 
+		/// Redeem currency by burning v_currency. But need to wait for the unlock period.
+		/// The redeemed currency will be transferred to the redeemer's account.
+		/// Parameters:
+		/// - `v_currency_id`: The v_currency to redeem.
+		/// - `v_currency_amount`: The amount of v_currency to redeem.
 		#[pallet::call_index(1)]
 		#[pallet::weight(T::WeightInfo::redeem())]
 		pub fn redeem(
 			origin: OriginFor<T>,
-			vtoken_id: CurrencyIdOf<T>,
-			vtoken_amount: BalanceOf<T>,
+			v_currency_id: CurrencyIdOf<T>,
+			v_currency_amount: BalanceOf<T>,
 		) -> DispatchResultWithPostInfo {
-			let exchanger = ensure_signed(origin)?;
-			Self::redeem_inner(exchanger, vtoken_id, vtoken_amount, RedeemType::Native)
+			let redeemer = ensure_signed(origin)?;
+			Self::do_redeem(redeemer, v_currency_id, v_currency_amount, RedeemType::Native)
 		}
 
+		/// Already redeemed currency by burning v_currency. But need to wait for the unlock period.
+		/// In unlock period, you call rebond to cancel the redeem.
+		/// Parameters:
+		/// - `currency_id`: The currency to rebond.
+		/// - `currency_amount`: The amount of currency to rebond. The amount should be less than or
+		///   equal to the redeem amount.
 		#[pallet::call_index(2)]
 		#[pallet::weight(T::WeightInfo::rebond())]
 		pub fn rebond(
 			origin: OriginFor<T>,
-			token_id: CurrencyIdOf<T>,
-			token_amount: BalanceOf<T>,
+			currency_id: CurrencyIdOf<T>,
+			currency_amount: BalanceOf<T>,
 		) -> DispatchResult {
-			let exchanger = ensure_signed(origin)?;
-			let vtoken_id = T::CurrencyIdConversion::convert_to_vtoken(token_id)
-				.map_err(|_| Error::<T>::NotSupportTokenType)?;
-			let _token_amount_to_rebond =
-				TokenToRebond::<T>::get(token_id).ok_or(Error::<T>::InvalidRebondToken)?;
-			if let Some((user_unlock_amount, mut ledger_list)) =
-				UserUnlockLedger::<T>::get(&exchanger, token_id)
-			{
-				ensure!(user_unlock_amount >= token_amount, Error::<T>::NotEnoughBalanceToUnlock);
-				let mut tmp_amount = token_amount;
-				let ledger_list_rev: Vec<UnlockId> = ledger_list.into_iter().rev().collect();
-				ledger_list =
-					BoundedVec::<UnlockId, T::MaximumUnlockIdOfUser>::try_from(ledger_list_rev)
-						.map_err(|_| Error::<T>::ExceedMaximumUnlockId)?;
-				let mut tmp = ledger_list
-					.iter()
-					.map(|&index| -> Result<(UnlockId, bool), Error<T>> {
-						if let Some((_, unlock_amount, time_unit, _)) =
-							TokenUnlockLedger::<T>::get(token_id, index)
-						{
-							if tmp_amount >= unlock_amount {
-								if let Some((_, _, time_unit, _)) =
-									TokenUnlockLedger::<T>::take(&token_id, &index)
-								{
-									TimeUnitUnlockLedger::<T>::mutate_exists(
-										&time_unit,
-										&token_id,
-										|value| -> Result<(), Error<T>> {
-											if let Some((
-												total_locked_origin,
-												ledger_list_origin,
-												_,
-											)) = value
-											{
-												if total_locked_origin == &unlock_amount {
-													*value = None;
-													return Ok(());
-												}
-												*total_locked_origin = total_locked_origin
-													.checked_sub(&unlock_amount)
-													.ok_or(Error::<T>::CalculationOverflow)?;
-												ledger_list_origin.retain(|&x| x != index);
-											} else {
-												return Err(
-													Error::<T>::TimeUnitUnlockLedgerNotFound,
-												);
-											}
-											Ok(())
-										},
-									)?;
-									tmp_amount = tmp_amount.saturating_sub(unlock_amount);
-								} else {
-									return Err(Error::<T>::TokenUnlockLedgerNotFound.into());
-								}
-								Ok((index, false))
-							} else {
-								TokenUnlockLedger::<T>::mutate_exists(
-									&token_id,
-									&index,
-									|value| -> Result<(), Error<T>> {
-										if let Some((_, total_locked_origin, _, _)) = value {
-											if total_locked_origin == &tmp_amount {
-												*value = None;
-												return Ok(());
-											}
-											*total_locked_origin = total_locked_origin
-												.checked_sub(&tmp_amount)
-												.ok_or(Error::<T>::CalculationOverflow)?;
-										} else {
-											return Err(Error::<T>::TokenUnlockLedgerNotFound);
-										}
-										Ok(())
-									},
-								)?;
-								TimeUnitUnlockLedger::<T>::mutate_exists(
-									&time_unit,
-									&token_id,
-									|value| -> Result<(), Error<T>> {
-										if let Some((total_locked_origin, _, _)) = value {
-											if total_locked_origin == &tmp_amount {
-												*value = None;
-												return Ok(());
-											}
-											*total_locked_origin = total_locked_origin
-												.checked_sub(&tmp_amount)
-												.ok_or(Error::<T>::CalculationOverflow)?;
-										} else {
-											return Err(Error::<T>::TimeUnitUnlockLedgerNotFound);
-										}
-										Ok(())
-									},
-								)?;
-								Ok((index, true))
-							}
-						} else {
-							Ok((index, true))
-						}
-					})
-					.collect::<Result<Vec<(UnlockId, bool)>, Error<T>>>()?;
-				tmp.retain(|(_index, result)| *result);
-
-				let ledger_list_tmp: Vec<UnlockId> =
-					tmp.into_iter().map(|(index, _)| index).rev().collect();
-
-				ledger_list =
-					BoundedVec::<UnlockId, T::MaximumUnlockIdOfUser>::try_from(ledger_list_tmp)
-						.map_err(|_| Error::<T>::ExceedMaximumUnlockId)?;
-
-				UnlockingTotal::<T>::mutate(&token_id, |pool| -> Result<(), Error<T>> {
-					*pool =
-						pool.checked_sub(&token_amount).ok_or(Error::<T>::CalculationOverflow)?;
-					Ok(())
-				})?;
-				UserUnlockLedger::<T>::mutate_exists(
-					&exchanger,
-					&token_id,
-					|value| -> Result<(), Error<T>> {
-						if let Some((total_locked_origin, ledger_list_origin)) = value {
-							if total_locked_origin == &token_amount {
-								*value = None;
-								return Ok(());
-							}
-							*ledger_list_origin = ledger_list;
-							*total_locked_origin = total_locked_origin
-								.checked_sub(&token_amount)
-								.ok_or(Error::<T>::CalculationOverflow)?;
-						} else {
-							return Err(Error::<T>::UserUnlockLedgerNotFound);
-						}
-						Ok(())
-					},
+			let rebonder = ensure_signed(origin)?;
+			let v_currency_id =
+				currency_id.to_vtoken().map_err(|_| Error::<T>::NotSupportTokenType)?;
+
+			let (user_unlock_amount, unlock_id_list) =
+				UserUnlockLedger::<T>::get(&rebonder, currency_id)
+					.ok_or(Error::<T>::UserUnlockLedgerNotFound)?;
+			ensure!(user_unlock_amount >= currency_amount, Error::<T>::NotEnoughBalanceToUnlock);
+
+			let mut temp_currency_amount = currency_amount;
+			for unlock_id in unlock_id_list.into_iter().rev() {
+				let (_, mut unlock_amount, time_unit, _) =
+					TokenUnlockLedger::<T>::get(currency_id, unlock_id)
+						.ok_or(Error::<T>::TokenUnlockLedgerNotFound)?;
+
+				if temp_currency_amount <= unlock_amount {
+					unlock_amount = temp_currency_amount;
+				} else {
+					temp_currency_amount = temp_currency_amount.saturating_sub(unlock_amount);
+				}
+
+				let is_remove_record = Self::update_unlock_ledger(
+					&rebonder,
+					&currency_id,
+					&unlock_amount,
+					&unlock_id,
+					&time_unit,
+					None,
+					Operation::Sub,
 				)?;
-			} else {
-				return Err(Error::<T>::UserUnlockLedgerNotFound.into());
+
+				if !is_remove_record {
+					break;
+				}
 			}
 
-			let (_, vtoken_amount, fee) =
-				Self::mint_without_tranfer(&exchanger, vtoken_id, token_id, token_amount)?;
+			let (_, v_currency_amount, fee) = Self::mint_without_transfer(
+				&rebonder,
+				v_currency_id,
+				currency_id,
+				currency_amount,
+			)?;
 
-			TokenToRebond::<T>::mutate(&token_id, |value| -> Result<(), Error<T>> {
-				if let Some(value_info) = value {
-					*value_info = value_info
-						.checked_add(&token_amount)
-						.ok_or(Error::<T>::CalculationOverflow)?;
-				} else {
-					return Err(Error::<T>::InvalidRebondToken);
+			TokenToRebond::<T>::mutate(&currency_id, |maybe_value| -> Result<(), Error<T>> {
+				match maybe_value {
+					Some(rebonded_amount) => {
+						*rebonded_amount = rebonded_amount
+							.checked_add(&currency_amount)
+							.ok_or(Error::<T>::CalculationOverflow)?;
+						Ok(())
+					},
+					None => Err(Error::<T>::InvalidRebondToken),
 				}
-				Ok(())
 			})?;
 
 			Self::deposit_event(Event::Rebonded {
-				address: exchanger,
-				token_id,
-				token_amount,
-				vtoken_amount,
+				rebonder,
+				currency_id,
+				currency_amount,
+				v_currency_amount,
 				fee,
 			});
 			Ok(())
 		}
 
+		/// Same function as Rebond. But need to provide unlock_id.
+		/// Parameters:
+		/// - `currency_id`: The currency to rebond.
+		/// - `unlock_id`: The unlock_id to rebond.
 		#[pallet::call_index(3)]
 		#[pallet::weight(T::WeightInfo::rebond_by_unlock_id())]
 		pub fn rebond_by_unlock_id(
 			origin: OriginFor<T>,
-			token_id: CurrencyIdOf<T>,
+			currency_id: CurrencyIdOf<T>,
 			unlock_id: UnlockId,
 		) -> DispatchResult {
-			let exchanger = ensure_signed(origin)?;
-
-			let vtoken_id = T::CurrencyIdConversion::convert_to_vtoken(token_id)
-				.map_err(|_| Error::<T>::NotSupportTokenType)?;
-			let _token_amount_to_rebond =
-				TokenToRebond::<T>::get(token_id).ok_or(Error::<T>::InvalidRebondToken)?;
-
-			let unlock_amount = match TokenUnlockLedger::<T>::get(token_id, unlock_id) {
-				Some((who, unlock_amount, time_unit, _)) => {
-					ensure!(who == exchanger, Error::<T>::CanNotRebond);
-					TimeUnitUnlockLedger::<T>::mutate_exists(
-						&time_unit,
-						&token_id,
-						|value| -> Result<(), Error<T>> {
-							if let Some((total_locked_origin, ledger_list_origin, _)) = value {
-								if total_locked_origin == &unlock_amount {
-									*value = None;
-									return Ok(());
-								}
-								*total_locked_origin = total_locked_origin
-									.checked_sub(&unlock_amount)
-									.ok_or(Error::<T>::CalculationOverflow)?;
-								ledger_list_origin.retain(|&x| x != unlock_id);
-							} else {
-								return Err(Error::<T>::TimeUnitUnlockLedgerNotFound);
-							}
-							Ok(())
-						},
-					)?;
-
-					UserUnlockLedger::<T>::mutate_exists(
-						&who,
-						&token_id,
-						|value| -> Result<(), Error<T>> {
-							if let Some((total_locked_origin, ledger_list_origin)) = value {
-								if total_locked_origin == &unlock_amount {
-									*value = None;
-									return Ok(());
-								}
-								*total_locked_origin = total_locked_origin
-									.checked_sub(&unlock_amount)
-									.ok_or(Error::<T>::CalculationOverflow)?;
-								ledger_list_origin.retain(|&x| x != unlock_id);
-							} else {
-								return Err(Error::<T>::UserUnlockLedgerNotFound);
-							}
-							Ok(())
-						},
-					)?;
-					UnlockingTotal::<T>::mutate(&token_id, |pool| -> Result<(), Error<T>> {
-						*pool = pool
-							.checked_sub(&unlock_amount)
-							.ok_or(Error::<T>::CalculationOverflow)?;
-						Ok(())
-					})?;
+			let rebonder = ensure_signed(origin)?;
 
-					TokenUnlockLedger::<T>::remove(&token_id, &unlock_id);
-					unlock_amount
-				},
-				_ => return Err(Error::<T>::TokenUnlockLedgerNotFound.into()),
-			};
+			let v_currency_id =
+				currency_id.to_vtoken().map_err(|_| Error::<T>::NotSupportTokenType)?;
 
-			let (token_amount, vtoken_amount, fee) =
-				Self::mint_without_tranfer(&exchanger, vtoken_id, token_id, unlock_amount)?;
+			let (who, unlock_amount, time_unit, _) =
+				TokenUnlockLedger::<T>::get(currency_id, unlock_id)
+					.ok_or(Error::<T>::TokenUnlockLedgerNotFound)?;
+			ensure!(who == rebonder, Error::<T>::CanNotRebond);
 
-			TokenToRebond::<T>::mutate(&token_id, |value| -> Result<(), Error<T>> {
-				if let Some(value_info) = value {
-					*value_info = value_info
-						.checked_add(&token_amount)
-						.ok_or(Error::<T>::CalculationOverflow)?;
-				} else {
-					return Err(Error::<T>::InvalidRebondToken);
+			Self::update_unlock_ledger(
+				&rebonder,
+				&currency_id,
+				&unlock_amount,
+				&unlock_id,
+				&time_unit,
+				None,
+				Operation::Sub,
+			)?;
+
+			let (currency_amount, v_currency_amount, fee) =
+				Self::mint_without_transfer(&rebonder, v_currency_id, currency_id, unlock_amount)?;
+
+			TokenToRebond::<T>::mutate(&currency_id, |maybe_value| -> Result<(), Error<T>> {
+				match maybe_value {
+					Some(rebonded_amount) => {
+						*rebonded_amount = rebonded_amount
+							.checked_add(&currency_amount)
+							.ok_or(Error::<T>::CalculationOverflow)?;
+						Ok(())
+					},
+					None => Err(Error::<T>::InvalidRebondToken),
 				}
-				Ok(())
 			})?;
 
 			Self::deposit_event(Event::RebondedByUnlockId {
-				address: exchanger,
-				token_id,
-				token_amount: unlock_amount,
-				vtoken_amount,
+				rebonder,
+				currency_id,
+				currency_amount: unlock_amount,
+				v_currency_amount,
 				fee,
 				unlock_id,
 			});
 			Ok(())
 		}
 
+		/// Set the unlock duration for a currency.
+		/// Parameters:
+		/// - `currency_id`: The currency to set unlock duration.
+		/// - `unlock_duration`: The unlock duration to set.
 		#[pallet::call_index(4)]
 		#[pallet::weight(T::WeightInfo::set_unlock_duration())]
 		pub fn set_unlock_duration(
 			origin: OriginFor<T>,
-			token_id: CurrencyIdOf<T>,
+			currency_id: CurrencyIdOf<T>,
 			unlock_duration: TimeUnit,
 		) -> DispatchResult {
 			T::ControlOrigin::ensure_origin(origin)?;
 
-			UnlockDuration::<T>::mutate(token_id, |old_unlock_duration| {
+			UnlockDuration::<T>::mutate(currency_id, |old_unlock_duration| {
 				*old_unlock_duration = Some(unlock_duration.clone());
 			});
 
-			Self::deposit_event(Event::UnlockDurationSet { token_id, unlock_duration });
-
+			Self::deposit_event(Event::UnlockDurationSet { currency_id, unlock_duration });
 			Ok(())
 		}
 
+		/// Set the minimum mint amount for a currency.
+		/// Parameters:
+		/// - `currency_id`: The currency to set minimum mint amount.
+		/// - `minimum_amount`: The minimum mint amount to set.
 		#[pallet::call_index(5)]
 		#[pallet::weight(T::WeightInfo::set_minimum_mint())]
 		pub fn set_minimum_mint(
 			origin: OriginFor<T>,
-			token_id: CurrencyIdOf<T>,
-			amount: BalanceOf<T>,
+			currency_id: CurrencyIdOf<T>,
+			minimum_amount: BalanceOf<T>,
 		) -> DispatchResult {
 			T::ControlOrigin::ensure_origin(origin)?;
 
-			if !MinimumMint::<T>::contains_key(token_id) {
-				// mutate_exists
-				MinimumMint::<T>::insert(token_id, amount);
-			} else {
-				MinimumMint::<T>::mutate(token_id, |old_amount| {
-					*old_amount = amount;
-				});
-			}
-
-			match token_id {
-				CurrencyId::Token(token_symbol) =>
-					if !T::CurrencyIdRegister::check_vtoken_registered(token_symbol) {
-						T::CurrencyIdRegister::register_vtoken_metadata(token_symbol)?;
-					},
-				CurrencyId::Token2(token_id) => {
-					if !T::CurrencyIdRegister::check_vtoken2_registered(token_id) {
-						T::CurrencyIdRegister::register_vtoken2_metadata(token_id)?;
-					}
-				},
-				_ => (),
-			}
+			MinimumMint::<T>::mutate(currency_id, |old_amount| {
+				*old_amount = minimum_amount;
+			});
 
-			Self::deposit_event(Event::MinimumMintSet { token_id, amount });
+			Self::deposit_event(Event::MinimumMintSet { currency_id, minimum_amount });
 
 			Ok(())
 		}
 
+		/// Set the minimum redeem amount for a currency.
+		/// Parameters:
+		/// - `currency_id`: The currency to set minimum redeem amount.
+		/// - `minimum_amount`: The minimum redeem amount to set.
 		#[pallet::call_index(6)]
 		#[pallet::weight(T::WeightInfo::set_minimum_redeem())]
 		pub fn set_minimum_redeem(
 			origin: OriginFor<T>,
-			token_id: CurrencyIdOf<T>,
-			amount: BalanceOf<T>,
+			currency_id: CurrencyIdOf<T>,
+			minimum_amount: BalanceOf<T>,
 		) -> DispatchResult {
 			T::ControlOrigin::ensure_origin(origin)?;
 
-			MinimumRedeem::<T>::mutate(token_id, |old_amount| {
-				*old_amount = amount;
+			MinimumRedeem::<T>::mutate(currency_id, |old_amount| {
+				*old_amount = minimum_amount;
 			});
 
-			Self::deposit_event(Event::MinimumRedeemSet { token_id, amount });
+			Self::deposit_event(Event::MinimumRedeemSet { currency_id, minimum_amount });
 			Ok(())
 		}
 
+		/// Support a token to rebond.
+		/// Parameters:
+		/// - `currency_id`: The currency to support rebond.
 		#[pallet::call_index(7)]
 		#[pallet::weight(T::WeightInfo::add_support_rebond_token())]
 		pub fn add_support_rebond_token(
 			origin: OriginFor<T>,
-			token_id: CurrencyIdOf<T>,
+			currency_id: CurrencyIdOf<T>,
 		) -> DispatchResult {
 			T::ControlOrigin::ensure_origin(origin)?;
 
-			if !TokenToRebond::<T>::contains_key(token_id) {
-				TokenToRebond::<T>::insert(token_id, BalanceOf::<T>::zero());
-				Self::deposit_event(Event::SupportRebondTokenAdded { token_id });
-			}
-
-			Ok(())
+			TokenToRebond::<T>::mutate(currency_id, |maybe_value| -> DispatchResult {
+				match maybe_value {
+					Some(_) => Err(Error::<T>::InvalidRebondToken.into()),
+					None => {
+						*maybe_value = Some(BalanceOf::<T>::zero());
+						Self::deposit_event(Event::SupportRebondTokenAdded { currency_id });
+						Ok(())
+					},
+				}
+			})
 		}
 
+		/// Remove the support of a token to rebond.
+		/// Parameters:
+		/// - `currency_id`: The currency to remove support rebond.
 		#[pallet::call_index(8)]
 		#[pallet::weight(T::WeightInfo::remove_support_rebond_token())]
 		pub fn remove_support_rebond_token(
 			origin: OriginFor<T>,
-			token_id: CurrencyIdOf<T>,
+			currency_id: CurrencyIdOf<T>,
 		) -> DispatchResult {
 			T::ControlOrigin::ensure_origin(origin)?;
 
-			if TokenToRebond::<T>::contains_key(token_id) {
-				let token_amount_to_rebond =
-					TokenToRebond::<T>::get(token_id).ok_or(Error::<T>::InvalidRebondToken)?;
-				ensure!(
-					token_amount_to_rebond == BalanceOf::<T>::zero(),
-					Error::<T>::TokenToRebondNotZero
-				);
-
-				TokenToRebond::<T>::remove(token_id);
-				Self::deposit_event(Event::SupportRebondTokenRemoved { token_id });
-			}
-			Ok(())
+			TokenToRebond::<T>::mutate(currency_id, |maybe_value| -> DispatchResult {
+				match maybe_value {
+					Some(_) => {
+						*maybe_value = None;
+						Self::deposit_event(Event::SupportRebondTokenRemoved { currency_id });
+						Ok(())
+					},
+					None => Err(Error::<T>::InvalidRebondToken.into()),
+				}
+			})
 		}
 
+		/// Set the fees for mint and redeem.
+		/// Parameters:
+		/// - `mint_fee`: The fee for mint.
+		/// - `redeem_fee`: The fee for redeem.
 		#[pallet::call_index(9)]
 		#[pallet::weight(T::WeightInfo::set_fees())]
 		pub fn set_fees(
@@ -825,6 +800,9 @@ pub mod pallet {
 			Ok(())
 		}
 
+		/// Set the hook iteration limit.
+		/// Parameters:
+		/// - `limit`: The hook iteration limit.
 		#[pallet::call_index(10)]
 		#[pallet::weight(T::WeightInfo::set_hook_iteration_limit())]
 		pub fn set_hook_iteration_limit(origin: OriginFor<T>, limit: u32) -> DispatchResult {
@@ -838,50 +816,63 @@ pub mod pallet {
 			Ok(())
 		}
 
+		/// Set the total amount of tokens that are currently locked for unlocking.
+		/// Parameters:
+		/// - `currency_id`: The currency to set unlocking total.
+		/// - `currency_amount`: The total amount of tokens that are currently locked for unlocking.
 		#[pallet::call_index(11)]
 		#[pallet::weight(T::WeightInfo::set_unlocking_total())]
 		pub fn set_unlocking_total(
 			origin: OriginFor<T>,
-			token_id: CurrencyIdOf<T>,
-			amount: BalanceOf<T>,
+			currency_id: CurrencyIdOf<T>,
+			currency_amount: BalanceOf<T>,
 		) -> DispatchResult {
 			T::ControlOrigin::ensure_origin(origin)?;
 
-			UnlockingTotal::<T>::mutate(&token_id, |unlocking_total| *unlocking_total = amount);
-
-			Self::deposit_event(Event::UnlockingTotalSet { token_id, amount });
+			Self::update_unlocking_total(&currency_id, &currency_amount, Operation::Set)?;
+			Self::deposit_event(Event::UnlockingTotalSet { currency_id, currency_amount });
 			Ok(())
 		}
 
+		/// Set the minimum time unit for a currency.
+		/// Parameters:
+		/// - `currency_id`: The currency to set minimum time unit.
+		/// - `time_unit`: The minimum time unit to set.
 		#[pallet::call_index(12)]
 		#[pallet::weight(T::WeightInfo::set_min_time_unit())]
 		pub fn set_min_time_unit(
 			origin: OriginFor<T>,
-			token_id: CurrencyIdOf<T>,
+			currency_id: CurrencyIdOf<T>,
 			time_unit: TimeUnit,
 		) -> DispatchResult {
 			T::ControlOrigin::ensure_origin(origin)?;
 
-			MinTimeUnit::<T>::mutate(&token_id, |old_time_unit| *old_time_unit = time_unit.clone());
+			MinTimeUnit::<T>::mutate(&currency_id, |old_time_unit| {
+				*old_time_unit = time_unit.clone()
+			});
 
-			Self::deposit_event(Event::MinTimeUnitSet { token_id, time_unit });
+			Self::deposit_event(Event::MinTimeUnitSet { currency_id, time_unit });
 			Ok(())
 		}
 
+		/// Set the ongoing time unit for a currency.
+		/// Parameters:
+		/// - `currency_id`: The currency to set ongoing time unit.
+		/// - `time_unit`: The ongoing time unit to set.
 		#[pallet::call_index(13)]
-		#[pallet::weight(T::WeightInfo::recreate_currency_ongoing_time_unit())]
-		pub fn recreate_currency_ongoing_time_unit(
+		#[pallet::weight(T::WeightInfo::set_ongoing_time_unit())]
+		pub fn set_ongoing_time_unit(
 			origin: OriginFor<T>,
-			token_id: CurrencyIdOf<T>,
+			currency_id: CurrencyIdOf<T>,
 			time_unit: TimeUnit,
 		) -> DispatchResult {
 			T::ControlOrigin::ensure_origin(origin)?;
 
-			OngoingTimeUnit::<T>::mutate(&token_id, |old_time_unit| {
+			OngoingTimeUnit::<T>::mutate(&currency_id, |old_time_unit| {
 				*old_time_unit = Some(time_unit.clone())
 			});
 
-			Self::deposit_event(Event::CurrencyTimeUnitRecreated { token_id, time_unit });
+			Self::deposit_event(Event::SetOngoingTimeUnit { currency_id, time_unit });
 			Ok(())
 		}
 
@@ -890,20 +881,20 @@ pub mod pallet {
 		#[pallet::weight(T::WeightInfo::mint_with_lock())]
 		pub fn mint_with_lock(
 			origin: OriginFor<T>,
-			token_id: CurrencyIdOf<T>,
-			token_amount: BalanceOf<T>,
+			currency_id: CurrencyIdOf<T>,
+			currency_amount: BalanceOf<T>,
 			remark: BoundedVec<u8, ConstU32<32>>,
 			channel_id: Option<u32>,
 		) -> DispatchResult {
 			// Check origin
 			let minter = ensure_signed(origin)?;
 
-			// check if the minter has at least token_amount of token_id which is transferable
-			T::MultiCurrency::ensure_can_withdraw(token_id, &minter, token_amount)
+			// check if the minter has at least currency_amount of currency_id which is transferable
+			T::MultiCurrency::ensure_can_withdraw(currency_id, &minter, currency_amount)
 				.map_err(|_| Error::<T>::NotEnoughBalance)?;
 
-			// check whether the token_id is supported
-			ensure!(MinimumMint::<T>::contains_key(token_id), Error::<T>::NotSupportTokenType);
+			// check whether the currency_id is supported
+			ensure!(MinimumMint::<T>::contains_key(currency_id), Error::<T>::NotSupportTokenType);
 
 			// check whether the user has veBNC
 			let vebnc_balance =
@@ -911,36 +902,36 @@ pub mod pallet {
 			ensure!(vebnc_balance > BalanceOf::<T>::zero(), Error::<T>::NotEnoughBalance);
 
 			// check whether the vtoken coefficient is set
-			let vtoken_id = T::CurrencyIdConversion::convert_to_vtoken(token_id)
-				.map_err(|_| Error::<T>::NotSupportTokenType)?;
+			let v_currency_id =
+				currency_id.to_vtoken().map_err(|_| Error::<T>::NotSupportTokenType)?;
 
 			ensure!(
-				VtokenIncentiveCoef::<T>::contains_key(vtoken_id),
+				VtokenIncentiveCoef::<T>::contains_key(v_currency_id),
 				Error::<T>::IncentiveCoefNotFound
 			);
 
-			// check whether the pool has balance of vtoken_id
+			// check whether the pool has balance of v_currency_id
 			let incentive_pool_account = &Self::incentive_pool_account();
 			let vtoken_pool_balance =
-				T::MultiCurrency::free_balance(vtoken_id, &incentive_pool_account);
+				T::MultiCurrency::free_balance(v_currency_id, &incentive_pool_account);
 
 			ensure!(vtoken_pool_balance > BalanceOf::<T>::zero(), Error::<T>::NotEnoughBalance);
 
 			// mint vtoken
 			let vtoken_minted =
-				Self::mint_inner(minter.clone(), token_id, token_amount, remark, channel_id)?;
+				Self::do_mint(minter.clone(), currency_id, currency_amount, remark, channel_id)?;
 
 			// lock vtoken and record the lock
-			Self::lock_vtoken_for_incentive_minting(minter.clone(), vtoken_id, vtoken_minted)?;
+			Self::lock_vtoken_for_incentive_minting(minter.clone(), v_currency_id, vtoken_minted)?;
 
 			// calculate the incentive amount
 			let incentive_amount =
-				Self::calculate_incentive_vtoken_amount(&minter, vtoken_id, vtoken_minted)?;
+				Self::calculate_incentive_vtoken_amount(&minter, v_currency_id, vtoken_minted)?;
 
 			// Since the user has already locked the vtoken, we can directly transfer the incentive
 			// vtoken. It won't fail. transfer the incentive amount to the minter
 			T::MultiCurrency::transfer(
-				vtoken_id,
+				v_currency_id,
 				incentive_pool_account,
 				&minter,
 				incentive_amount,
@@ -950,8 +941,8 @@ pub mod pallet {
 			// deposit event
 			Self::deposit_event(Event::IncentivizedMinting {
 				address: minter,
-				token_id,
-				token_amount,
+				currency_id,
+				currency_amount,
 				locked_vtoken_amount: vtoken_minted,
 				incentive_vtoken_amount: incentive_amount,
 			});
@@ -959,23 +950,26 @@ pub mod pallet {
 			Ok(())
 		}
 
+		/// Unlock the vtoken minted in an incentive mode
+		/// Parameters:
+		/// - `v_currency_id`: The v_currency to unlock.
 		#[pallet::call_index(15)]
 		#[pallet::weight(T::WeightInfo::unlock_incentive_minted_vtoken())]
 		pub fn unlock_incentive_minted_vtoken(
 			origin: OriginFor<T>,
-			vtoken_id: CurrencyIdOf<T>,
+			v_currency_id: CurrencyIdOf<T>,
 		) -> DispatchResult {
 			let unlocker = ensure_signed(origin)?;
 
 			// get the user's VtokenLockLedger
 			ensure!(
-				VtokenLockLedger::<T>::contains_key(&unlocker, vtoken_id),
+				VtokenLockLedger::<T>::contains_key(&unlocker, v_currency_id),
 				Error::<T>::UserUnlockLedgerNotFound
 			);
 
 			VtokenLockLedger::<T>::mutate_exists(
 				&unlocker,
-				vtoken_id,
+				v_currency_id,
 				|maybe_ledger| -> Result<(), Error<T>> {
 					let current_block = frame_system::Pallet::<T>::block_number();
 
@@ -1012,8 +1006,12 @@ pub mod pallet {
 							.ok_or(Error::<T>::CalculationOverflow)?;
 
 						if remaining_locked_amount == BalanceOf::<T>::zero() {
-							T::MultiCurrency::remove_lock(INCENTIVE_LOCK_ID, vtoken_id, &unlocker)
-								.map_err(|_| Error::<T>::FailToRemoveLock)?;
+							T::MultiCurrency::remove_lock(
+								INCENTIVE_LOCK_ID,
+								v_currency_id,
+								&unlocker,
+							)
+							.map_err(|_| Error::<T>::FailToRemoveLock)?;
 
 							// remove the ledger
 							*maybe_ledger = None;
@@ -1024,7 +1022,7 @@ pub mod pallet {
 							// reset the locked amount to be remaining_locked_amount
 							T::MultiCurrency::set_lock(
 								INCENTIVE_LOCK_ID,
-								vtoken_id,
+								v_currency_id,
 								&unlocker,
 								remaining_locked_amount,
 							)
@@ -1041,1151 +1039,58 @@ pub mod pallet {
 			Ok(())
 		}
 
+		/// Set the incentive coefficient for a vtoken when minted in an incentive mode
+		/// Parameters:
+		/// - `v_currency_id`: The v_currency to set incentive coefficient.
+		/// - `new_coef_op`: The new incentive coefficient to set.
 		#[pallet::call_index(16)]
 		#[pallet::weight(T::WeightInfo::set_incentive_coef())]
 		pub fn set_incentive_coef(
 			origin: OriginFor<T>,
-			vtoken_id: CurrencyIdOf<T>,
+			v_currency_id: CurrencyIdOf<T>,
 			new_coef_op: Option<u128>,
 		) -> DispatchResult {
 			T::ControlOrigin::ensure_origin(origin)?;
 
 			if let Some(new_coef) = new_coef_op {
-				VtokenIncentiveCoef::<T>::insert(vtoken_id, new_coef);
+				VtokenIncentiveCoef::<T>::insert(v_currency_id, new_coef);
 			} else {
-				VtokenIncentiveCoef::<T>::remove(vtoken_id);
+				VtokenIncentiveCoef::<T>::remove(v_currency_id);
 			}
 
 			Self::deposit_event(Event::VtokenIncentiveCoefSet {
-				vtoken_id,
+				v_currency_id,
 				coefficient: new_coef_op,
 			});
 
 			Ok(())
 		}
 
+		/// Set the locked blocks for a vtoken when minted in an incentive mode
+		/// Parameters:
+		/// - `v_currency_id`: The v_currency to set locked blocks.
+		/// - `new_blockes_op`: The new locked blocks to set.
 		#[pallet::call_index(17)]
 		#[pallet::weight(T::WeightInfo::set_vtoken_incentive_lock_blocks())]
 		pub fn set_vtoken_incentive_lock_blocks(
 			origin: OriginFor<T>,
-			vtoken_id: CurrencyIdOf<T>,
+			v_currency_id: CurrencyIdOf<T>,
 			new_blockes_op: Option<BlockNumberFor<T>>,
 		) -> DispatchResult {
 			T::ControlOrigin::ensure_origin(origin)?;
 
 			if let Some(new_blocks) = new_blockes_op {
-				MintWithLockBlocks::<T>::insert(vtoken_id, new_blocks);
+				MintWithLockBlocks::<T>::insert(v_currency_id, new_blocks);
 			} else {
-				MintWithLockBlocks::<T>::remove(vtoken_id);
+				MintWithLockBlocks::<T>::remove(v_currency_id);
 			}
 
 			Self::deposit_event(Event::VtokenIncentiveLockBlocksSet {
-				vtoken_id,
+				v_currency_id,
 				blocks: new_blockes_op,
 			});
 
 			Ok(())
 		}
 	}
-
-	impl<T: Config> Pallet<T> {
-		#[transactional]
-		pub fn add_time_unit(a: TimeUnit, b: TimeUnit) -> Result<TimeUnit, DispatchError> {
-			let result = match a {
-				TimeUnit::Era(era_a) => match b {
-					TimeUnit::Era(era_b) => TimeUnit::Era(
-						era_a.checked_add(era_b).ok_or(Error::<T>::CalculationOverflow)?,
-					),
-					_ => return Err(Error::<T>::Unexpected.into()),
-				},
-				TimeUnit::Round(round_a) => match b {
-					TimeUnit::Round(round_b) => TimeUnit::Round(
-						round_a.checked_add(round_b).ok_or(Error::<T>::CalculationOverflow)?,
-					),
-					_ => return Err(Error::<T>::Unexpected.into()),
-				},
-				TimeUnit::SlashingSpan(slashing_span_a) => match b {
-					TimeUnit::SlashingSpan(slashing_span_b) => TimeUnit::SlashingSpan(
-						slashing_span_a
-							.checked_add(slashing_span_b)
-							.ok_or(Error::<T>::CalculationOverflow)?,
-					),
-					_ => return Err(Error::<T>::Unexpected.into()),
-				},
-				TimeUnit::Kblock(kblock_a) => match b {
-					TimeUnit::Kblock(kblock_b) => TimeUnit::Kblock(
-						kblock_a.checked_add(kblock_b).ok_or(Error::<T>::CalculationOverflow)?,
-					),
-					_ => return Err(Error::<T>::Unexpected.into()),
-				},
-				TimeUnit::Hour(hour_a) => match b {
-					TimeUnit::Hour(hour_b) => TimeUnit::Hour(
-						hour_a.checked_add(hour_b).ok_or(Error::<T>::CalculationOverflow)?,
-					),
-					_ => return Err(Error::<T>::Unexpected.into()),
-				},
-				// _ => return Err(Error::<T>::Unexpected.into()),
-			};
-
-			Ok(result)
-		}
-
-		#[transactional]
-		pub fn mint_without_tranfer(
-			exchanger: &AccountIdOf<T>,
-			vtoken_id: CurrencyId,
-			token_id: CurrencyId,
-			token_amount: BalanceOf<T>,
-		) -> Result<(BalanceOf<T>, BalanceOf<T>, BalanceOf<T>), DispatchError> {
-			let token_pool_amount = TokenPool::<T>::get(token_id);
-			let vtoken_total_issuance = T::MultiCurrency::total_issuance(vtoken_id);
-			let (mint_rate, _redeem_rate) = Fees::<T>::get();
-			let mint_fee = mint_rate * token_amount;
-			let token_amount_excluding_fee =
-				token_amount.checked_sub(&mint_fee).ok_or(Error::<T>::CalculationOverflow)?;
-			let mut vtoken_amount = token_amount_excluding_fee;
-			if token_pool_amount != BalanceOf::<T>::zero() {
-				vtoken_amount = U256::from(token_amount_excluding_fee.saturated_into::<u128>())
-					.saturating_mul(vtoken_total_issuance.saturated_into::<u128>().into())
-					.checked_div(token_pool_amount.saturated_into::<u128>().into())
-					.map(|x| u128::try_from(x))
-					.ok_or(Error::<T>::CalculationOverflow)?
-					.map_err(|_| Error::<T>::CalculationOverflow)?
-					.unique_saturated_into();
-			}
-
-			// Charging fees
-			T::MultiCurrency::transfer(token_id, exchanger, &T::FeeAccount::get(), mint_fee)?;
-			// Issue the corresponding vtoken to the user's account.
-			T::MultiCurrency::deposit(vtoken_id, exchanger, vtoken_amount)?;
-			TokenPool::<T>::mutate(&token_id, |pool| -> Result<(), Error<T>> {
-				*pool = pool
-					.checked_add(&token_amount_excluding_fee)
-					.ok_or(Error::<T>::CalculationOverflow)?;
-				Ok(())
-			})?;
-			Ok((token_amount_excluding_fee, vtoken_amount, mint_fee))
-		}
-
-		#[transactional]
-		fn on_initialize_update_ledger(
-			token_id: CurrencyId,
-			account: AccountIdOf<T>,
-			index: &UnlockId,
-			mut unlock_amount: BalanceOf<T>,
-			entrance_account_balance: BalanceOf<T>,
-			time_unit: TimeUnit,
-			redeem_type: RedeemType<AccountIdOf<T>>,
-		) -> DispatchResult {
-			let ed = T::MultiCurrency::minimum_balance(token_id);
-			let mut account_to_send = account.clone();
-			let mut redeem_to = RedeemTo::Native(account_to_send.clone());
-
-			if unlock_amount < ed {
-				let receiver_balance = T::MultiCurrency::total_balance(token_id, &account);
-
-				let receiver_balance_after = receiver_balance
-					.checked_add(&unlock_amount)
-					.ok_or(ArithmeticError::Overflow)?;
-				if receiver_balance_after < ed {
-					account_to_send = T::FeeAccount::get();
-					redeem_to = RedeemTo::Native(T::FeeAccount::get());
-				}
-			}
-			if entrance_account_balance >= unlock_amount {
-				T::MultiCurrency::transfer(
-					token_id,
-					&T::EntranceAccount::get().into_account_truncating(),
-					&account_to_send,
-					unlock_amount,
-				)?;
-				TokenUnlockLedger::<T>::remove(&token_id, &index);
-
-				TimeUnitUnlockLedger::<T>::mutate_exists(
-					&time_unit,
-					&token_id,
-					|value| -> Result<(), Error<T>> {
-						if let Some((total_locked_origin, ledger_list_origin, _)) = value {
-							if total_locked_origin == &unlock_amount {
-								*value = None;
-								return Ok(());
-							}
-							*total_locked_origin = total_locked_origin
-								.checked_sub(&unlock_amount)
-								.ok_or(Error::<T>::CalculationOverflow)?;
-							ledger_list_origin.retain(|x| x != index);
-						} else {
-							return Err(Error::<T>::TimeUnitUnlockLedgerNotFound);
-						}
-						Ok(())
-					},
-				)?;
-
-				UserUnlockLedger::<T>::mutate_exists(
-					&account,
-					&token_id,
-					|value| -> Result<(), Error<T>> {
-						if let Some((total_locked_origin, ledger_list_origin)) = value {
-							if total_locked_origin == &unlock_amount {
-								*value = None;
-								return Ok(());
-							}
-							ledger_list_origin.retain(|x| x != index);
-							*total_locked_origin = total_locked_origin
-								.checked_sub(&unlock_amount)
-								.ok_or(Error::<T>::CalculationOverflow)?;
-						} else {
-							return Err(Error::<T>::UserUnlockLedgerNotFound);
-						}
-						Ok(())
-					},
-				)?;
-				match redeem_type {
-					RedeemType::Native => {},
-					RedeemType::Astar(receiver) => {
-						let dest = Location::new(
-							1,
-							[
-								Parachain(AstarChainId::get()),
-								AccountId32 {
-									network: None,
-									id: receiver.encode().try_into().unwrap(),
-								},
-							],
-						);
-						T::XcmTransfer::transfer(
-							account.clone(),
-							token_id,
-							unlock_amount,
-							dest,
-							Unlimited,
-						)?;
-						redeem_to = RedeemTo::Astar(receiver);
-					},
-					RedeemType::Hydradx(receiver) => {
-						let dest = Location::new(
-							1,
-							[
-								Parachain(HydrationChainId::get()),
-								AccountId32 {
-									network: None,
-									id: receiver.encode().try_into().unwrap(),
-								},
-							],
-						);
-						T::XcmTransfer::transfer(
-							account.clone(),
-							token_id,
-							unlock_amount,
-							dest,
-							Unlimited,
-						)?;
-						redeem_to = RedeemTo::Hydradx(receiver);
-					},
-					RedeemType::Interlay(receiver) => {
-						let dest = Location::new(
-							1,
-							[
-								Parachain(InterlayChainId::get()),
-								AccountId32 {
-									network: None,
-									id: receiver.encode().try_into().unwrap(),
-								},
-							],
-						);
-						T::XcmTransfer::transfer(
-							account.clone(),
-							token_id,
-							unlock_amount,
-							dest,
-							Unlimited,
-						)?;
-						redeem_to = RedeemTo::Interlay(receiver);
-					},
-					RedeemType::Manta(receiver) => {
-						let dest = Location::new(
-							1,
-							[
-								Parachain(MantaChainId::get()),
-								AccountId32 {
-									network: None,
-									id: receiver.encode().try_into().unwrap(),
-								},
-							],
-						);
-						T::XcmTransfer::transfer(
-							account.clone(),
-							token_id,
-							unlock_amount,
-							dest,
-							Unlimited,
-						)?;
-						redeem_to = RedeemTo::Manta(receiver);
-					},
-					RedeemType::Moonbeam(receiver) => {
-						let dest = Location::new(
-							1,
-							[
-								Parachain(T::MoonbeamChainId::get()),
-								AccountKey20 { network: None, key: receiver.to_fixed_bytes() },
-							],
-						);
-						if token_id == FIL {
-							let assets = vec![
-								(token_id, unlock_amount),
-								(BNC, T::BifrostSlpx::get_moonbeam_transfer_to_fee()),
-							];
-
-							T::XcmTransfer::transfer_multicurrencies(
-								account.clone(),
-								assets,
-								1,
-								dest,
-								Unlimited,
-							)?;
-						} else {
-							T::XcmTransfer::transfer(
-								account.clone(),
-								token_id,
-								unlock_amount,
-								dest,
-								Unlimited,
-							)?;
-						}
-						redeem_to = RedeemTo::Moonbeam(receiver);
-					},
-				};
-			} else {
-				match redeem_type {
-					RedeemType::Astar(_) |
-					RedeemType::Moonbeam(_) |
-					RedeemType::Hydradx(_) |
-					RedeemType::Manta(_) |
-					RedeemType::Interlay(_) => {
-						return Ok(());
-					},
-					RedeemType::Native => {},
-				};
-				unlock_amount = entrance_account_balance;
-				T::MultiCurrency::transfer(
-					token_id,
-					&T::EntranceAccount::get().into_account_truncating(),
-					&account_to_send,
-					unlock_amount,
-				)?;
-				TokenUnlockLedger::<T>::mutate_exists(
-					&token_id,
-					&index,
-					|value| -> Result<(), Error<T>> {
-						if let Some((_, total_locked_origin, _, _)) = value {
-							if total_locked_origin == &unlock_amount {
-								*value = None;
-								return Ok(());
-							}
-							*total_locked_origin = total_locked_origin
-								.checked_sub(&unlock_amount)
-								.ok_or(Error::<T>::CalculationOverflow)?;
-						} else {
-							return Err(Error::<T>::TokenUnlockLedgerNotFound);
-						}
-						Ok(())
-					},
-				)?;
-
-				TimeUnitUnlockLedger::<T>::mutate_exists(
-					&time_unit,
-					&token_id,
-					|value| -> Result<(), Error<T>> {
-						if let Some((total_locked_origin, _ledger_list_origin, _)) = value {
-							if total_locked_origin == &unlock_amount {
-								*value = None;
-								return Ok(());
-							}
-							*total_locked_origin = total_locked_origin
-								.checked_sub(&unlock_amount)
-								.ok_or(Error::<T>::CalculationOverflow)?;
-						} else {
-							return Err(Error::<T>::TimeUnitUnlockLedgerNotFound);
-						}
-						Ok(())
-					},
-				)?;
-
-				UserUnlockLedger::<T>::mutate_exists(
-					&account,
-					&token_id,
-					|value| -> Result<(), Error<T>> {
-						if let Some((total_locked_origin, _ledger_list_origin)) = value {
-							if total_locked_origin == &unlock_amount {
-								*value = None;
-								return Ok(());
-							}
-
-							*total_locked_origin = total_locked_origin
-								.checked_sub(&unlock_amount)
-								.ok_or(Error::<T>::CalculationOverflow)?;
-						} else {
-							return Err(Error::<T>::UserUnlockLedgerNotFound);
-						}
-						Ok(())
-					},
-				)?;
-			}
-
-			entrance_account_balance
-				.checked_sub(&unlock_amount)
-				.ok_or(Error::<T>::CalculationOverflow)?;
-
-			UnlockingTotal::<T>::mutate(&token_id, |pool| -> Result<(), Error<T>> {
-				*pool = pool.checked_sub(&unlock_amount).ok_or(Error::<T>::CalculationOverflow)?;
-				Ok(())
-			})?;
-
-			T::OnRedeemSuccess::on_redeem_success(token_id, account.clone(), unlock_amount);
-
-			Self::deposit_event(Event::RedeemSuccess {
-				unlock_id: *index,
-				token_id,
-				to: redeem_to,
-				token_amount: unlock_amount,
-			});
-			Ok(())
-		}
-
-		#[transactional]
-		fn handle_on_initialize() -> DispatchResult {
-			for currency in OngoingTimeUnit::<T>::iter_keys() {
-				Self::handle_ledger_by_currency(currency)?;
-			}
-			Ok(())
-		}
-
-		fn handle_ledger_by_currency(currency: CurrencyId) -> DispatchResult {
-			let time_unit = MinTimeUnit::<T>::get(currency);
-			let unlock_duration_elem = match UnlockDuration::<T>::get(currency) {
-				Some(TimeUnit::Era(unlock_duration_era)) => unlock_duration_era,
-				Some(TimeUnit::Round(unlock_duration_round)) => unlock_duration_round,
-				Some(TimeUnit::Kblock(unlock_duration_kblock)) => unlock_duration_kblock,
-				Some(TimeUnit::Hour(unlock_duration_hour)) => unlock_duration_hour,
-				_ => 0,
-			};
-			let ongoing_elem = match OngoingTimeUnit::<T>::get(currency) {
-				Some(TimeUnit::Era(ongoing_era)) => ongoing_era,
-				Some(TimeUnit::Round(ongoing_round)) => ongoing_round,
-				Some(TimeUnit::Kblock(ongoing_kblock)) => ongoing_kblock,
-				Some(TimeUnit::Hour(ongoing_hour)) => ongoing_hour,
-				_ => 0,
-			};
-			if let Some((_total_locked, ledger_list, token_id)) =
-				TimeUnitUnlockLedger::<T>::get(time_unit.clone(), currency)
-			{
-				for index in ledger_list.iter().take(HookIterationLimit::<T>::get() as usize) {
-					if let Some((account, unlock_amount, time_unit, redeem_type)) =
-						TokenUnlockLedger::<T>::get(token_id, index)
-					{
-						let entrance_account_balance = T::MultiCurrency::free_balance(
-							token_id,
-							&T::EntranceAccount::get().into_account_truncating(),
-						);
-						if entrance_account_balance != BalanceOf::<T>::zero() {
-							Self::on_initialize_update_ledger(
-								token_id,
-								account,
-								index,
-								unlock_amount,
-								entrance_account_balance,
-								time_unit,
-								redeem_type,
-							)
-							.ok();
-						}
-					}
-				}
-			} else {
-				MinTimeUnit::<T>::mutate(currency, |time_unit| -> Result<(), Error<T>> {
-					match time_unit {
-						TimeUnit::Era(era) => {
-							if ongoing_elem + unlock_duration_elem > *era {
-								*era = era.checked_add(1).ok_or(Error::<T>::CalculationOverflow)?;
-							}
-							Ok(())
-						},
-						TimeUnit::Round(round) => {
-							if ongoing_elem + unlock_duration_elem > *round {
-								*round =
-									round.checked_add(1).ok_or(Error::<T>::CalculationOverflow)?;
-							}
-							Ok(())
-						},
-						TimeUnit::Kblock(kblock) => {
-							if ongoing_elem + unlock_duration_elem > *kblock {
-								*kblock =
-									kblock.checked_add(1).ok_or(Error::<T>::CalculationOverflow)?;
-							}
-							Ok(())
-						},
-						TimeUnit::Hour(hour) => {
-							if ongoing_elem + unlock_duration_elem > *hour {
-								*hour =
-									hour.checked_add(1).ok_or(Error::<T>::CalculationOverflow)?;
-							}
-							Ok(())
-						},
-						_ => Ok(()),
-					}
-				})?;
-			};
-
-			Ok(())
-		}
-
-		#[transactional]
-		pub fn mint_inner(
-			exchanger: AccountIdOf<T>,
-			token_id: CurrencyIdOf<T>,
-			token_amount: BalanceOf<T>,
-			remark: BoundedVec<u8, ConstU32<32>>,
-			channel_id: Option<u32>,
-		) -> Result<BalanceOf<T>, DispatchError> {
-			ensure!(token_amount >= MinimumMint::<T>::get(token_id), Error::<T>::BelowMinimumMint);
-
-			let vtoken_id = T::CurrencyIdConversion::convert_to_vtoken(token_id)
-				.map_err(|_| Error::<T>::NotSupportTokenType)?;
-			let (token_amount_excluding_fee, vtoken_amount, fee) =
-				Self::mint_without_tranfer(&exchanger, vtoken_id, token_id, token_amount)?;
-			// Transfer the user's token to EntranceAccount.
-			T::MultiCurrency::transfer(
-				token_id,
-				&exchanger,
-				&T::EntranceAccount::get().into_account_truncating(),
-				token_amount_excluding_fee,
-			)?;
-
-			// record the minting information for ChannelCommission module
-			T::ChannelCommission::record_mint_amount(channel_id, vtoken_id, vtoken_amount)?;
-
-			Self::deposit_event(Event::Minted {
-				address: exchanger,
-				token_id,
-				token_amount,
-				vtoken_amount,
-				fee,
-				remark,
-				channel_id,
-			});
-			Ok(vtoken_amount.into())
-		}
-
-		#[transactional]
-		pub fn redeem_inner(
-			exchanger: AccountIdOf<T>,
-			vtoken_id: CurrencyIdOf<T>,
-			vtoken_amount: BalanceOf<T>,
-			redeem_type: RedeemType<AccountIdOf<T>>,
-		) -> DispatchResultWithPostInfo {
-			let token_id = T::CurrencyIdConversion::convert_to_token(vtoken_id)
-				.map_err(|_| Error::<T>::NotSupportTokenType)?;
-			ensure!(
-				vtoken_amount >= MinimumRedeem::<T>::get(vtoken_id),
-				Error::<T>::BelowMinimumRedeem
-			);
-
-			ensure!(
-				!T::BifrostSlp::all_delegation_requests_occupied(token_id),
-				Error::<T>::CanNotRedeem,
-			);
-
-			let (_mint_rate, redeem_rate) = Fees::<T>::get();
-			let redeem_fee = redeem_rate * vtoken_amount;
-			let vtoken_amount =
-				vtoken_amount.checked_sub(&redeem_fee).ok_or(Error::<T>::CalculationOverflow)?;
-			// Charging fees
-			T::MultiCurrency::transfer(
-				vtoken_id,
-				&exchanger,
-				&T::RedeemFeeAccount::get(),
-				redeem_fee,
-			)?;
-
-			let token_pool_amount = TokenPool::<T>::get(token_id);
-			let vtoken_total_issuance = T::MultiCurrency::total_issuance(vtoken_id);
-			let token_amount: BalanceOf<T> = U256::from(vtoken_amount.saturated_into::<u128>())
-				.saturating_mul(token_pool_amount.saturated_into::<u128>().into())
-				.checked_div(vtoken_total_issuance.saturated_into::<u128>().into())
-				.map(|x| u128::try_from(x))
-				.ok_or(Error::<T>::CalculationOverflow)?
-				.map_err(|_| Error::<T>::CalculationOverflow)?
-				.unique_saturated_into();
-
-			let next_id = TokenUnlockNextId::<T>::get(token_id);
-			match OngoingTimeUnit::<T>::get(token_id) {
-				Some(time_unit) => {
-					// Calculate the time to be locked
-					let result_time_unit = Self::add_time_unit(
-						UnlockDuration::<T>::get(token_id)
-							.ok_or(Error::<T>::UnlockDurationNotFound)?,
-						time_unit,
-					)?;
-
-					T::MultiCurrency::withdraw(vtoken_id, &exchanger, vtoken_amount)?;
-					TokenPool::<T>::mutate(&token_id, |pool| -> Result<(), Error<T>> {
-						*pool = pool
-							.checked_sub(&token_amount)
-							.ok_or(Error::<T>::CalculationOverflow)?;
-						Ok(())
-					})?;
-					UnlockingTotal::<T>::mutate(&token_id, |pool| -> Result<(), Error<T>> {
-						*pool = pool
-							.checked_add(&token_amount)
-							.ok_or(Error::<T>::CalculationOverflow)?;
-						Ok(())
-					})?;
-					TokenUnlockLedger::<T>::insert(
-						&token_id,
-						&next_id,
-						(&exchanger, token_amount, &result_time_unit, redeem_type),
-					);
-
-					if UserUnlockLedger::<T>::get(&exchanger, &token_id).is_some() {
-						UserUnlockLedger::<T>::mutate(
-							&exchanger,
-							&token_id,
-							|value| -> Result<(), Error<T>> {
-								if let Some((total_locked, ledger_list)) = value {
-									ledger_list
-										.try_push(next_id)
-										.map_err(|_| Error::<T>::TooManyRedeems)?;
-
-									*total_locked = total_locked
-										.checked_add(&token_amount)
-										.ok_or(Error::<T>::CalculationOverflow)?;
-								};
-								Ok(())
-							},
-						)?;
-					} else {
-						let mut ledger_list_origin =
-							BoundedVec::<UnlockId, T::MaximumUnlockIdOfUser>::default();
-						ledger_list_origin
-							.try_push(next_id)
-							.map_err(|_| Error::<T>::TooManyRedeems)?;
-						UserUnlockLedger::<T>::insert(
-							&exchanger,
-							&token_id,
-							(token_amount, ledger_list_origin),
-						);
-					}
-
-					if let Some((_, _, _token_id)) =
-						TimeUnitUnlockLedger::<T>::get(&result_time_unit, &token_id)
-					{
-						TimeUnitUnlockLedger::<T>::mutate(
-							&result_time_unit,
-							&token_id,
-							|value| -> Result<(), Error<T>> {
-								if let Some((total_locked, ledger_list, _token_id)) = value {
-									ledger_list
-										.try_push(next_id)
-										.map_err(|_| Error::<T>::TooManyRedeems)?;
-									*total_locked = total_locked
-										.checked_add(&token_amount)
-										.ok_or(Error::<T>::CalculationOverflow)?;
-								};
-								Ok(())
-							},
-						)?;
-					} else {
-						let mut ledger_list_origin =
-							BoundedVec::<UnlockId, T::MaximumUnlockIdOfTimeUnit>::default();
-						ledger_list_origin
-							.try_push(next_id)
-							.map_err(|_| Error::<T>::TooManyRedeems)?;
-
-						TimeUnitUnlockLedger::<T>::insert(
-							&result_time_unit,
-							&token_id,
-							(token_amount, ledger_list_origin, token_id),
-						);
-					}
-				},
-				None => return Err(Error::<T>::OngoingTimeUnitNotSet.into()),
-			}
-
-			TokenUnlockNextId::<T>::mutate(&token_id, |unlock_id| -> Result<(), Error<T>> {
-				*unlock_id = unlock_id.checked_add(1).ok_or(Error::<T>::CalculationOverflow)?;
-				Ok(())
-			})?;
-
-			let extra_weight = T::OnRedeemSuccess::on_redeemed(
-				exchanger.clone(),
-				token_id,
-				token_amount,
-				vtoken_amount,
-				redeem_fee,
-			);
-
-			T::ChannelCommission::record_redeem_amount(vtoken_id, vtoken_amount)?;
-
-			Self::deposit_event(Event::Redeemed {
-				address: exchanger,
-				token_id,
-				vtoken_amount,
-				token_amount,
-				fee: redeem_fee,
-				unlock_id: next_id,
-			});
-			Ok(Some(T::WeightInfo::redeem() + extra_weight).into())
-		}
-
-		pub fn token_to_vtoken_inner(
-			token_id: CurrencyIdOf<T>,
-			vtoken_id: CurrencyIdOf<T>,
-			token_amount: BalanceOf<T>,
-		) -> Result<BalanceOf<T>, DispatchError> {
-			let token_pool_amount = TokenPool::<T>::get(token_id);
-			let vtoken_total_issuance = T::MultiCurrency::total_issuance(vtoken_id);
-
-			let value = U256::from(token_amount.saturated_into::<u128>())
-				.saturating_mul(vtoken_total_issuance.saturated_into::<u128>().into())
-				.checked_div(token_pool_amount.saturated_into::<u128>().into())
-				.ok_or(Error::<T>::CalculationOverflow)?;
-
-			Ok(u128::try_from(value)
-				.map(|x| x.unique_saturated_into())
-				.map_err(|_| Error::<T>::CalculationOverflow)?)
-		}
-
-		pub fn vtoken_to_token_inner(
-			token_id: CurrencyIdOf<T>,
-			vtoken_id: CurrencyIdOf<T>,
-			vtoken_amount: BalanceOf<T>,
-		) -> Result<BalanceOf<T>, DispatchError> {
-			let token_pool_amount = TokenPool::<T>::get(token_id);
-			let vtoken_total_issuance = T::MultiCurrency::total_issuance(vtoken_id);
-
-			let value = U256::from(vtoken_amount.saturated_into::<u128>())
-				.saturating_mul(token_pool_amount.saturated_into::<u128>().into())
-				.checked_div(vtoken_total_issuance.saturated_into::<u128>().into())
-				.ok_or(Error::<T>::CalculationOverflow)?;
-
-			Ok(u128::try_from(value)
-				.map(|x| x.unique_saturated_into())
-				.map_err(|_| Error::<T>::CalculationOverflow)?)
-		}
-
-		pub fn vtoken_id_inner(token_id: CurrencyIdOf<T>) -> Option<CurrencyIdOf<T>> {
-			T::CurrencyIdConversion::convert_to_vtoken(token_id).ok()
-		}
-
-		pub fn token_id_inner(vtoken_id: CurrencyIdOf<T>) -> Option<CurrencyIdOf<T>> {
-			T::CurrencyIdConversion::convert_to_token(vtoken_id).ok()
-		}
-
-		pub fn incentive_pool_account() -> AccountIdOf<T> {
-			T::IncentivePoolAccount::get().into_account_truncating()
-		}
-
-		// to lock user vtoken for incentive minting
-		fn lock_vtoken_for_incentive_minting(
-			minter: AccountIdOf<T>,
-			vtoken_id: CurrencyIdOf<T>,
-			vtoken_amount: BalanceOf<T>,
-		) -> Result<(), Error<T>> {
-			// first, lock the vtoken
-			// second, record the lock in ledger
-
-			// check whether the minter has enough vtoken
-			T::MultiCurrency::ensure_can_withdraw(vtoken_id, &minter, vtoken_amount)
-				.map_err(|_| Error::<T>::NotEnoughBalance)?;
-
-			// new amount that should be locked
-			let mut new_lock_total = vtoken_amount;
-
-			// check the previous locked amount under the same vtoken_id from ledger
-			// and revise ledger to set the new_amount to be previous_amount + vtoken_amount
-			VtokenLockLedger::<T>::mutate_exists(
-				&minter,
-				&vtoken_id,
-				|value| -> Result<(), Error<T>> {
-					// get the vtoken lock duration from VtokenIncentiveCoef
-					let lock_duration = MintWithLockBlocks::<T>::get(vtoken_id)
-						.ok_or(Error::<T>::IncentiveLockBlocksNotSet)?;
-					let current_block = frame_system::Pallet::<T>::block_number();
-					let due_block = current_block
-						.checked_add(&lock_duration)
-						.ok_or(Error::<T>::CalculationOverflow)?;
-
-					if let Some(ref mut ledger) = value {
-						new_lock_total = ledger
-							.0
-							.checked_add(&vtoken_amount)
-							.ok_or(Error::<T>::CalculationOverflow)?;
-
-						ledger.0 = new_lock_total;
-
-						// push new item to the boundedvec of the ledger
-						ledger
-							.1
-							.try_push((vtoken_amount, due_block))
-							.map_err(|_| Error::<T>::TooManyLocks)?;
-					} else {
-						let item = BoundedVec::try_from(vec![(vtoken_amount, due_block)])
-							.map_err(|_| Error::<T>::ConvertError)?;
-
-						*value = Some((vtoken_amount, item));
-					}
-					Ok(())
-				},
-			)?;
-
-			// extend the locked amount to be new_lock_total
-			T::MultiCurrency::set_lock(INCENTIVE_LOCK_ID, vtoken_id, &minter, new_lock_total)
-				.map_err(|_| Error::<T>::NotEnoughBalance)?;
-
-			Ok(())
-		}
-
-		fn calculate_incentive_vtoken_amount(
-			minter: &AccountIdOf<T>,
-			vtoken_id: CurrencyIdOf<T>,
-			vtoken_amount: BalanceOf<T>,
-		) -> Result<BalanceOf<T>, Error<T>> {
-			// get the vtoken pool balance
-			let vtoken_pool_balance =
-				T::MultiCurrency::free_balance(vtoken_id, &Self::incentive_pool_account());
-			ensure!(vtoken_pool_balance > BalanceOf::<T>::zero(), Error::<T>::NotEnoughBalance);
-
-			// get current block number
-			let current_block_number: BlockNumberFor<T> = frame_system::Pallet::<T>::block_number();
-			// get the veBNC total amount
-			let vebnc_total_issuance = T::BbBNC::total_supply(current_block_number)
-				.map_err(|_| Error::<T>::VeBNCCheckingError)?;
-			ensure!(vebnc_total_issuance > BalanceOf::<T>::zero(), Error::<T>::BalanceZero);
-
-			// get the veBNC balance of the minter
-			let minter_vebnc_balance =
-				T::BbBNC::balance_of(minter, None).map_err(|_| Error::<T>::VeBNCCheckingError)?;
-			ensure!(minter_vebnc_balance > BalanceOf::<T>::zero(), Error::<T>::NotEnoughBalance);
-
-			// get the percentage of the veBNC balance of the minter to the total veBNC amount and
-			// get the square root of the percentage
-			let percentage = Permill::from_rational(minter_vebnc_balance, vebnc_total_issuance);
-			let sqrt_percentage =
-				FixedU128::from_inner(percentage * 1_000_000_000_000_000_000u128).sqrt();
-			let percentage = Permill::from_rational(
-				sqrt_percentage.into_inner(),
-				1_000_000_000_000_000_000u128.into(),
-			);
-			// get the total issuance of the vtoken
-			let vtoken_total_issuance = T::MultiCurrency::total_issuance(vtoken_id);
-
-			// get the incentive coef for the vtoken
-			let incentive_coef = VtokenIncentiveCoef::<T>::get(vtoken_id)
-				.ok_or(Error::<T>::IncentiveCoefNotFound)?;
-
-			// calculate the incentive amount, but mind the overflow
-			// incentive_amount = vtoken_pool_balance * incentive_coef * vtoken_amount *
-			// sqrt_percentage / vtoken_total_issuance
-			let incentive_amount =
-				U256::from(percentage.mul_ceil(vtoken_pool_balance).saturated_into::<u128>())
-					.checked_mul(U256::from(incentive_coef))
-					.and_then(|x| x.checked_mul(U256::from(vtoken_amount.saturated_into::<u128>())))
-					// .and_then(|x| x.checked_mul(percentage))
-					.and_then(|x| {
-						x.checked_div(U256::from(vtoken_total_issuance.saturated_into::<u128>()))
-					})
-					// first turn into u128,then use unique_saturated_into BalanceOf<T>
-					.map(|x| x.saturated_into::<u128>())
-					.map(|x| x.unique_saturated_into())
-					.ok_or(Error::<T>::CalculationOverflow)?;
-
-			Ok(incentive_amount)
-		}
-
-		pub fn get_exchange_rate(
-			token_id: Option<CurrencyId>,
-		) -> Result<Vec<(CurrencyIdOf<T>, U256)>, DispatchError> {
-			let mut result: Vec<(CurrencyIdOf<T>, U256)> = Vec::new();
-
-			match token_id {
-				Some(token_id) => {
-					let vtoken_amount = Self::get_vtoken_amount(token_id, 1000u128)?;
-					result.push((token_id, vtoken_amount));
-				},
-				None =>
-					for token_id in T::AssetIdMaps::get_all_currency() {
-						if token_id.is_vtoken() {
-							let vtoken_id = token_id;
-							let token_id = T::CurrencyIdConversion::convert_to_token(vtoken_id)
-								.map_err(|_| Error::<T>::NotSupportTokenType)?;
-
-							let vtoken_amount = Self::get_vtoken_amount(token_id, 1000u128)?;
-							result.push((token_id, vtoken_amount));
-						}
-					},
-			}
-			Ok(result)
-		}
-
-		fn get_vtoken_amount(token: CurrencyIdOf<T>, amount: u128) -> Result<U256, DispatchError> {
-			let vtoken_id = T::CurrencyIdConversion::convert_to_vtoken(token)
-				.map_err(|_| Error::<T>::NotSupportTokenType)?;
-
-			let token_pool_amount = TokenPool::<T>::get(token);
-			let vtoken_total_issuance = T::MultiCurrency::total_issuance(vtoken_id);
-
-			let mut vtoken_amount = U256::from(amount);
-			if token_pool_amount != BalanceOf::<T>::zero() {
-				let vtoken_total_issuance_u256 =
-					U256::from(vtoken_total_issuance.saturated_into::<u128>());
-				let token_pool_amount_u256 = U256::from(token_pool_amount.saturated_into::<u128>());
-
-				vtoken_amount = vtoken_amount
-					.saturating_mul(vtoken_total_issuance_u256)
-					.checked_div(token_pool_amount_u256)
-					.ok_or(Error::<T>::CalculationOverflow)?;
-			}
-			Ok(vtoken_amount)
-		}
-	}
-}
-
-impl<T: Config> VtokenMintingOperator<CurrencyId, BalanceOf<T>, AccountIdOf<T>, TimeUnit>
-	for Pallet<T>
-{
-	fn get_token_pool(currency_id: CurrencyId) -> BalanceOf<T> {
-		TokenPool::<T>::get(currency_id)
-	}
-
-	fn increase_token_pool(currency_id: CurrencyId, token_amount: BalanceOf<T>) -> DispatchResult {
-		TokenPool::<T>::mutate(currency_id, |pool| -> Result<(), Error<T>> {
-			*pool = pool.checked_add(&token_amount).ok_or(Error::<T>::CalculationOverflow)?;
-
-			Ok(())
-		})?;
-
-		Ok(())
-	}
-
-	fn decrease_token_pool(currency_id: CurrencyId, token_amount: BalanceOf<T>) -> DispatchResult {
-		TokenPool::<T>::mutate(currency_id, |pool| -> Result<(), Error<T>> {
-			*pool = pool.checked_sub(&token_amount).ok_or(Error::<T>::CalculationOverflow)?;
-			Ok(())
-		})?;
-
-		Ok(())
-	}
-
-	fn update_ongoing_time_unit(currency_id: CurrencyId, time_unit: TimeUnit) -> DispatchResult {
-		OngoingTimeUnit::<T>::mutate(currency_id, |time_unit_old| -> Result<(), Error<T>> {
-			*time_unit_old = Some(time_unit);
-			Ok(())
-		})?;
-
-		Ok(())
-	}
-
-	fn get_ongoing_time_unit(currency_id: CurrencyId) -> Option<TimeUnit> {
-		OngoingTimeUnit::<T>::get(currency_id)
-	}
-
-	fn get_unlock_records(
-		currency_id: CurrencyId,
-		time_unit: TimeUnit,
-	) -> Option<(BalanceOf<T>, Vec<u32>)> {
-		if let Some((balance, list, _)) = TimeUnitUnlockLedger::<T>::get(&time_unit, currency_id) {
-			Some((balance, list.into_inner()))
-		} else {
-			None
-		}
-	}
-
-	#[transactional]
-	fn deduct_unlock_amount(
-		currency_id: CurrencyId,
-		index: u32,
-		deduct_amount: BalanceOf<T>,
-	) -> DispatchResult {
-		if let Some((who, unlock_amount, time_unit, _)) =
-			TokenUnlockLedger::<T>::get(currency_id, index)
-		{
-			ensure!(unlock_amount >= deduct_amount, Error::<T>::NotEnoughBalanceToUnlock);
-
-			UnlockingTotal::<T>::mutate(&currency_id, |pool| -> Result<(), Error<T>> {
-				*pool = pool.checked_sub(&deduct_amount).ok_or(Error::<T>::CalculationOverflow)?;
-				Ok(())
-			})?;
-
-			TimeUnitUnlockLedger::<T>::mutate_exists(
-				&time_unit,
-				&currency_id,
-				|value| -> Result<(), Error<T>> {
-					if let Some((total_locked_origin, ledger_list_origin, _)) = value {
-						if total_locked_origin == &deduct_amount {
-							*value = None;
-							return Ok(());
-						}
-						*total_locked_origin = total_locked_origin
-							.checked_sub(&deduct_amount)
-							.ok_or(Error::<T>::CalculationOverflow)?;
-						if unlock_amount == deduct_amount {
-							ledger_list_origin.retain(|&x| x != index);
-						}
-					} else {
-						return Err(Error::<T>::TimeUnitUnlockLedgerNotFound);
-					}
-					Ok(())
-				},
-			)?;
-
-			UserUnlockLedger::<T>::mutate_exists(
-				&who,
-				&currency_id,
-				|value| -> Result<(), Error<T>> {
-					if let Some((total_locked_origin, ledger_list_origin)) = value {
-						if total_locked_origin == &deduct_amount {
-							*value = None;
-							return Ok(());
-						}
-						*total_locked_origin = total_locked_origin
-							.checked_sub(&deduct_amount)
-							.ok_or(Error::<T>::CalculationOverflow)?;
-						if unlock_amount == deduct_amount {
-							ledger_list_origin.retain(|&x| x != index);
-						}
-					} else {
-						return Err(Error::<T>::UserUnlockLedgerNotFound);
-					}
-					Ok(())
-				},
-			)?;
-
-			if unlock_amount == deduct_amount {
-				TokenUnlockLedger::<T>::remove(&currency_id, &index);
-			} else {
-				TokenUnlockLedger::<T>::mutate_exists(
-					&currency_id,
-					&index,
-					|value| -> Result<(), Error<T>> {
-						if let Some((_, total_locked_origin, _, _)) = value {
-							if total_locked_origin == &deduct_amount {
-								*value = None;
-								return Ok(());
-							}
-							*total_locked_origin = total_locked_origin
-								.checked_sub(&deduct_amount)
-								.ok_or(Error::<T>::CalculationOverflow)?;
-						} else {
-							return Err(Error::<T>::TokenUnlockLedgerNotFound);
-						}
-						Ok(())
-					},
-				)?;
-			}
-		}
-		Ok(())
-	}
-
-	fn get_entrance_and_exit_accounts() -> (AccountIdOf<T>, AccountIdOf<T>) {
-		(
-			T::EntranceAccount::get().into_account_truncating(),
-			T::ExitAccount::get().into_account_truncating(),
-		)
-	}
-
-	fn get_token_unlock_ledger(
-		currency_id: CurrencyId,
-		index: u32,
-	) -> Option<(AccountIdOf<T>, BalanceOf<T>, TimeUnit, RedeemType<AccountIdOf<T>>)> {
-		TokenUnlockLedger::<T>::get(currency_id, index)
-	}
-
-	fn get_moonbeam_parachain_id() -> u32 {
-		T::MoonbeamChainId::get()
-	}
-}
-
-impl<T: Config> VtokenMintingInterface<AccountIdOf<T>, CurrencyIdOf<T>, BalanceOf<T>>
-	for Pallet<T>
-{
-	fn mint(
-		exchanger: AccountIdOf<T>,
-		token_id: CurrencyIdOf<T>,
-		token_amount: BalanceOf<T>,
-		remark: BoundedVec<u8, ConstU32<32>>,
-		channel_id: Option<u32>,
-	) -> Result<BalanceOf<T>, DispatchError> {
-		Self::mint_inner(exchanger, token_id, token_amount, remark, channel_id)
-	}
-
-	fn redeem(
-		exchanger: AccountIdOf<T>,
-		vtoken_id: CurrencyIdOf<T>,
-		vtoken_amount: BalanceOf<T>,
-	) -> DispatchResultWithPostInfo {
-		Self::redeem_inner(exchanger, vtoken_id, vtoken_amount, RedeemType::Native)
-	}
-
-	fn slpx_redeem(
-		exchanger: AccountIdOf<T>,
-		vtoken_id: CurrencyIdOf<T>,
-		vtoken_amount: BalanceOf<T>,
-		redeem_type: RedeemType<AccountIdOf<T>>,
-	) -> DispatchResultWithPostInfo {
-		Self::redeem_inner(exchanger, vtoken_id, vtoken_amount, redeem_type)
-	}
-
-	fn token_to_vtoken(
-		token_id: CurrencyIdOf<T>,
-		vtoken_id: CurrencyIdOf<T>,
-		token_amount: BalanceOf<T>,
-	) -> Result<BalanceOf<T>, DispatchError> {
-		Self::token_to_vtoken_inner(token_id, vtoken_id, token_amount)
-	}
-
-	fn vtoken_to_token(
-		token_id: CurrencyIdOf<T>,
-		vtoken_id: CurrencyIdOf<T>,
-		vtoken_amount: BalanceOf<T>,
-	) -> Result<BalanceOf<T>, DispatchError> {
-		Self::vtoken_to_token_inner(token_id, vtoken_id, vtoken_amount)
-	}
-
-	fn vtoken_id(token_id: CurrencyIdOf<T>) -> Option<CurrencyIdOf<T>> {
-		Self::vtoken_id_inner(token_id)
-	}
-
-	fn token_id(vtoken_id: CurrencyIdOf<T>) -> Option<CurrencyIdOf<T>> {
-		Self::token_id_inner(vtoken_id)
-	}
-
-	fn get_minimums_redeem(vtoken_id: CurrencyIdOf<T>) -> BalanceOf<T> {
-		MinimumRedeem::<T>::get(vtoken_id)
-	}
-
-	fn get_token_pool(currency_id: CurrencyId) -> BalanceOf<T> {
-		TokenPool::<T>::get(currency_id)
-	}
-
-	fn get_moonbeam_parachain_id() -> u32 {
-		T::MoonbeamChainId::get()
-	}
-}
-
-impl<T: Config> VTokenSupplyProvider<CurrencyIdOf<T>, BalanceOf<T>> for Pallet<T> {
-	fn get_vtoken_supply(vtoken: CurrencyIdOf<T>) -> Option<BalanceOf<T>> {
-		if CurrencyId::is_vtoken(&vtoken) {
-			Some(T::MultiCurrency::total_issuance(vtoken))
-		} else {
-			None
-		}
-	}
-
-	fn get_token_supply(token: CurrencyIdOf<T>) -> Option<BalanceOf<T>> {
-		if CurrencyId::is_token(&token) | CurrencyId::is_native(&token) {
-			Some(TokenPool::<T>::get(token))
-		} else {
-			None
-		}
-	}
 }
diff --git a/pallets/vtoken-minting/src/mock.rs b/pallets/vtoken-minting/src/mock.rs
index 3a7bb38ad..46bffd730 100644
--- a/pallets/vtoken-minting/src/mock.rs
+++ b/pallets/vtoken-minting/src/mock.rs
@@ -26,26 +26,17 @@ use bifrost_asset_registry::AssetIdMaps;
 use bifrost_primitives::{
 	currency::{BNC, DOT, FIL, KSM, MOVR, VBNC, VFIL, VKSM, VMOVR},
 	BifrostEntranceAccount, BifrostExitAccount, BifrostFeeAccount, CurrencyId, CurrencyIdMapping,
-	IncentivePoolAccount, MoonbeamChainId, SlpxOperator, KUSD,
+	IncentivePoolAccount, MockXcmTransfer, MoonbeamChainId, SlpxOperator, KUSD,
 };
 use bifrost_runtime_common::{micro, milli};
-use bifrost_slp::{QueryId, QueryResponseManager};
-pub use cumulus_primitives_core::ParaId;
-use frame_support::{
-	derive_impl, ord_parameter_types,
-	pallet_prelude::Get,
-	parameter_types,
-	traits::{Everything, Nothing},
-};
-use frame_system::{EnsureRoot, EnsureSignedBy};
-use orml_traits::{location::RelativeReserveProvider, parameter_type_with_key};
+use frame_support::{derive_impl, ord_parameter_types, parameter_types, traits::Nothing};
+use frame_system::EnsureSignedBy;
+use orml_traits::parameter_type_with_key;
 use sp_runtime::{
 	traits::{ConstU32, IdentityLookup},
 	AccountId32, BuildStorage, DispatchError, DispatchResult,
 };
-use xcm::{prelude::*, v3::Weight};
-use xcm_builder::{FixedWeightBounds, FrameTransactionalProcessor};
-use xcm_executor::XcmExecutor;
+use xcm::prelude::*;
 
 use crate as vtoken_minting;
 
@@ -63,13 +54,10 @@ frame_support::construct_runtime!(
 	pub enum Runtime {
 		System: frame_system,
 		Tokens: orml_tokens,
-		XTokens: orml_xtokens,
 		Balances: pallet_balances,
 		Currencies: bifrost_currencies,
 		VtokenMinting: vtoken_minting,
-		Slp: bifrost_slp,
 		AssetRegistry: bifrost_asset_registry,
-		PolkadotXcm: pallet_xcm,
 	}
 );
 
@@ -164,31 +152,6 @@ parameter_type_with_key! {
 	};
 }
 
-parameter_types! {
-	pub SelfRelativeLocation: Location = Location::here();
-	pub const BaseXcmWeight: Weight = Weight::from_parts(1000_000_000u64, 0);
-	pub const MaxAssetsForTransfer: usize = 2;
-}
-
-impl orml_xtokens::Config for Runtime {
-	type RuntimeEvent = RuntimeEvent;
-	type Balance = Balance;
-	type CurrencyId = CurrencyId;
-	type CurrencyIdConvert = ();
-	type AccountIdToLocation = ();
-	type UniversalLocation = UniversalLocation;
-	type SelfLocation = SelfRelativeLocation;
-	type XcmExecutor = XcmExecutor<XcmConfig>;
-	type Weigher = FixedWeightBounds<UnitWeightCost, RuntimeCall, MaxInstructions>;
-	type BaseXcmWeight = BaseXcmWeight;
-	type MaxAssetsForTransfer = MaxAssetsForTransfer;
-	type MinXcmFee = ParachainMinFee;
-	type LocationsFilter = Everything;
-	type ReserveProvider = RelativeReserveProvider;
-	type RateLimiter = ();
-	type RateLimiterId = ();
-}
-
 parameter_types! {
 	pub const MaximumUnlockIdOfUser: u32 = 1_000;
 	pub const MaximumUnlockIdOfTimeUnit: u32 = 1_000;
@@ -212,18 +175,14 @@ impl vtoken_minting::Config for Runtime {
 	type FeeAccount = BifrostFeeAccount;
 	type RedeemFeeAccount = BifrostFeeAccount;
 	type IncentivePoolAccount = IncentivePoolAccount;
-	type BifrostSlp = Slp;
 	type BifrostSlpx = SlpxInterface;
 	type BbBNC = BbBNC;
 	type RelayChainToken = RelayCurrencyId;
-	type CurrencyIdConversion = AssetIdMaps<Runtime>;
-	type CurrencyIdRegister = AssetIdMaps<Runtime>;
 	type WeightInfo = ();
 	type OnRedeemSuccess = ();
-	type XcmTransfer = XTokens;
+	type XcmTransfer = MockXcmTransfer;
 	type MoonbeamChainId = MoonbeamChainId;
 	type ChannelCommission = ();
-	type AssetIdMaps = AssetIdMaps<Runtime>;
 }
 
 ord_parameter_types! {
@@ -235,35 +194,6 @@ impl bifrost_asset_registry::Config for Runtime {
 	type RegisterOrigin = EnsureSignedBy<CouncilAccount, AccountId>;
 	type WeightInfo = ();
 }
-pub struct ParachainId;
-impl Get<ParaId> for ParachainId {
-	fn get() -> ParaId {
-		2001.into()
-	}
-}
-
-parameter_types! {
-	pub const MaxTypeEntryPerBlock: u32 = 10;
-	pub const MaxRefundPerBlock: u32 = 10;
-	pub const MaxLengthLimit: u32 = 100;
-}
-
-pub struct SubstrateResponseManager;
-impl QueryResponseManager<QueryId, Location, u64, RuntimeCall> for SubstrateResponseManager {
-	fn get_query_response_record(_query_id: QueryId) -> bool {
-		Default::default()
-	}
-	fn create_query_record(
-		_responder: Location,
-		_call_back: Option<RuntimeCall>,
-		_timeout: u64,
-	) -> u64 {
-		Default::default()
-	}
-	fn remove_query_record(_query_id: QueryId) -> bool {
-		Default::default()
-	}
-}
 
 pub struct SlpxInterface;
 impl SlpxOperator<Balance> for SlpxInterface {
@@ -272,105 +202,6 @@ impl SlpxOperator<Balance> 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;
-	type RuntimeCall = RuntimeCall;
-	type MultiCurrency = Currencies;
-	type ControlOrigin = EnsureSignedBy<One, AccountId>;
-	type WeightInfo = ();
-	type VtokenMinting = VtokenMinting;
-	type AccountConverter = ();
-	type ParachainId = ParachainId;
-	type SubstrateResponseManager = SubstrateResponseManager;
-	type MaxTypeEntryPerBlock = MaxTypeEntryPerBlock;
-	type MaxRefundPerBlock = MaxRefundPerBlock;
-	type ParachainStaking = ();
-	type XcmTransfer = XTokens;
-	type MaxLengthLimit = MaxLengthLimit;
-	type XcmWeightAndFeeHandler = ();
-	type ChannelCommission = ();
-	type StablePoolHandler = ();
-	type AssetIdMaps = AssetIdMaps<Runtime>;
-	type TreasuryAccount = TreasuryAccount;
-}
-
-parameter_types! {
-	// One XCM operation is 200_000_000 XcmWeight, cross-chain transfer ~= 2x of transfer = 3_000_000_000
-	pub UnitWeightCost: Weight = Weight::from_parts(200_000_000, 0);
-	pub const MaxInstructions: u32 = 100;
-	pub UniversalLocation: InteriorLocation = Parachain(2001).into();
-}
-
-pub struct XcmConfig;
-impl xcm_executor::Config for XcmConfig {
-	type AssetClaims = PolkadotXcm;
-	type AssetTransactor = ();
-	type AssetTrap = PolkadotXcm;
-	type Barrier = ();
-	type RuntimeCall = RuntimeCall;
-	type IsReserve = ();
-	type IsTeleporter = ();
-	type UniversalLocation = UniversalLocation;
-	type OriginConverter = ();
-	type ResponseHandler = PolkadotXcm;
-	type SubscriptionService = PolkadotXcm;
-	type Trader = ();
-	type Weigher = FixedWeightBounds<UnitWeightCost, RuntimeCall, MaxInstructions>;
-	type XcmSender = ();
-	type PalletInstancesInfo = AllPalletsWithSystem;
-	type MaxAssetsIntoHolding = ConstU32<64>;
-	type FeeManager = ();
-	type MessageExporter = ();
-	type UniversalAliases = Nothing;
-	type CallDispatcher = RuntimeCall;
-	type SafeCallFilter = Everything;
-	type AssetLocker = ();
-	type AssetExchanger = ();
-	type Aliasers = Nothing;
-	type TransactionalProcessor = FrameTransactionalProcessor;
-	type HrmpNewChannelOpenRequestHandler = ();
-	type HrmpChannelAcceptedHandler = ();
-	type HrmpChannelClosingHandler = ();
-	type XcmRecorder = ();
-}
-
-#[cfg(feature = "runtime-benchmarks")]
-parameter_types! {
-	pub ReachableDest: Option<Location> = Some(Parent.into());
-}
-
-impl pallet_xcm::Config for Runtime {
-	type RuntimeEvent = RuntimeEvent;
-	type ExecuteXcmOrigin = xcm_builder::EnsureXcmOrigin<RuntimeOrigin, ()>;
-	type UniversalLocation = UniversalLocation;
-	type SendXcmOrigin = xcm_builder::EnsureXcmOrigin<RuntimeOrigin, ()>;
-	type Weigher = FixedWeightBounds<UnitWeightCost, RuntimeCall, MaxInstructions>;
-	type XcmExecuteFilter = Nothing;
-	type XcmExecutor = XcmExecutor<XcmConfig>;
-	type XcmReserveTransferFilter = Everything;
-	type XcmRouter = ();
-	type XcmTeleportFilter = Nothing;
-	type RuntimeOrigin = RuntimeOrigin;
-	type RuntimeCall = RuntimeCall;
-	const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100;
-	type AdvertisedXcmVersion = ConstU32<2>;
-	type Currency = Balances;
-	type CurrencyMatcher = ();
-	type TrustedLockers = ();
-	type SovereignAccountOf = ();
-	type MaxLockers = ConstU32<8>;
-	type WeightInfo = pallet_xcm::TestWeightInfo;
-	type AdminOrigin = EnsureRoot<AccountId>;
-	type MaxRemoteLockConsumers = ConstU32<0>;
-	type RemoteLockConsumerIdentifier = ();
-}
-
 pub struct ExtBuilder {
 	endowed_accounts: Vec<(AccountId, CurrencyId, Balance)>,
 }
diff --git a/pallets/vtoken-minting/src/tests.rs b/pallets/vtoken-minting/src/tests.rs
index 20e47dac7..791eddc4f 100644
--- a/pallets/vtoken-minting/src/tests.rs
+++ b/pallets/vtoken-minting/src/tests.rs
@@ -21,7 +21,10 @@
 #![cfg(test)]
 
 use crate::{mock::*, DispatchError::Module, *};
-use bifrost_primitives::currency::{BNC, FIL, KSM, MOVR, VBNC, VFIL, VKSM, VMOVR};
+use bifrost_primitives::{
+	currency::{BNC, FIL, KSM, MOVR, VBNC, VFIL, VKSM, VMOVR},
+	VtokenMintingOperator,
+};
 use frame_support::{assert_noop, assert_ok, sp_runtime::Permill, BoundedVec};
 use sp_runtime::ModuleError;
 
@@ -492,7 +495,7 @@ fn fast_redeem_for_fil() {
 }
 
 #[test]
-fn recreate_currency_ongoing_time_unit_should_work() {
+fn set_ongoing_time_unit_should_work() {
 	ExtBuilder::default().one_hundred_for_alice_n_bob().build().execute_with(|| {
 		env_logger::try_init().unwrap_or(());
 
@@ -500,8 +503,8 @@ fn recreate_currency_ongoing_time_unit_should_work() {
 		OngoingTimeUnit::<Runtime>::insert(KSM, TimeUnit::Era(1));
 		assert_eq!(OngoingTimeUnit::<Runtime>::get(KSM), Some(TimeUnit::Era(1)));
 
-		// recreate_currency_ongoing_time_unit the ongoing time unit of KSM to be Round(2)
-		assert_ok!(VtokenMinting::recreate_currency_ongoing_time_unit(
+		// set_ongoing_time_unit the ongoing time unit of KSM to be Round(2)
+		assert_ok!(VtokenMinting::set_ongoing_time_unit(
 			RuntimeOrigin::signed(ALICE),
 			KSM,
 			TimeUnit::Round(2)
diff --git a/pallets/vtoken-minting/src/weights.rs b/pallets/vtoken-minting/src/weights.rs
index 68f316aaf..708be1483 100644
--- a/pallets/vtoken-minting/src/weights.rs
+++ b/pallets/vtoken-minting/src/weights.rs
@@ -58,7 +58,7 @@ pub trait WeightInfo {
 	fn set_unlock_duration() -> Weight;
 	fn set_unlocking_total() -> Weight;
 	fn set_min_time_unit() -> Weight;
-	fn recreate_currency_ongoing_time_unit() -> Weight;
+	fn set_ongoing_time_unit() -> Weight;
 	fn add_support_rebond_token() -> Weight;
 	fn remove_support_rebond_token() -> Weight;
 	fn set_fees() -> Weight;
@@ -137,7 +137,7 @@ impl WeightInfo for () {
 	}
 	/// Storage: `VtokenMinting::OngoingTimeUnit` (r:1 w:1)
 	/// Proof: `VtokenMinting::OngoingTimeUnit` (`max_values`: None, `max_size`: Some(27), added: 2502, mode: `MaxEncodedLen`)
-	fn recreate_currency_ongoing_time_unit() -> Weight {
+	fn set_ongoing_time_unit() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `180`
 		//  Estimated: `3492`
diff --git a/primitives/src/time_unit.rs b/primitives/src/time_unit.rs
index 8d6a5cafb..bf2242bc1 100644
--- a/primitives/src/time_unit.rs
+++ b/primitives/src/time_unit.rs
@@ -51,9 +51,25 @@ impl TimeUnit {
 	pub fn add(self, other_time: Self) -> Option<Self> {
 		match (self, other_time) {
 			(TimeUnit::Era(a), TimeUnit::Era(b)) => Some(TimeUnit::Era(a.saturating_add(b))),
+			(TimeUnit::SlashingSpan(a), TimeUnit::SlashingSpan(b)) =>
+				Some(TimeUnit::SlashingSpan(a.saturating_add(b))),
+			(TimeUnit::Round(a), TimeUnit::Round(b)) => Some(TimeUnit::Round(a.saturating_add(b))),
+			(TimeUnit::Kblock(a), TimeUnit::Kblock(b)) =>
+				Some(TimeUnit::Kblock(a.saturating_add(b))),
+			(TimeUnit::Hour(a), TimeUnit::Hour(b)) => Some(TimeUnit::Hour(a.saturating_add(b))),
 			_ => None,
 		}
 	}
+
+	pub fn into_value(self) -> u32 {
+		match self {
+			TimeUnit::Era(a) => a,
+			TimeUnit::SlashingSpan(a) => a,
+			TimeUnit::Round(a) => a,
+			TimeUnit::Kblock(a) => a,
+			TimeUnit::Hour(a) => a,
+		}
+	}
 }
 
 impl Default for TimeUnit {
diff --git a/primitives/src/traits.rs b/primitives/src/traits.rs
index 1d9f630bc..e7d7e5d69 100644
--- a/primitives/src/traits.rs
+++ b/primitives/src/traits.rs
@@ -121,13 +121,6 @@ pub trait VtokenMintingOperator<CurrencyId, Balance, AccountId, TimeUnit> {
 		time_unit: TimeUnit,
 	) -> Option<(Balance, Vec<u32>)>;
 
-	/// Revise the currency indexed unlocking record by some amount.
-	fn deduct_unlock_amount(
-		currency_id: CurrencyId,
-		index: u32,
-		deduct_amount: Balance,
-	) -> DispatchResult;
-
 	/// Get currency Entrance and Exit accounts.【entrance_account, exit_account】
 	fn get_entrance_and_exit_accounts() -> (AccountId, AccountId);
 
@@ -260,18 +253,16 @@ pub trait VtokenMintingInterface<AccountId, CurrencyId, Balance> {
 		vtoken_amount: Balance,
 		redeem: RedeemType<AccountId>,
 	) -> DispatchResultWithPostInfo;
-	fn token_to_vtoken(
+	fn get_v_currency_amount_by_currency_amount(
 		token_id: CurrencyId,
 		vtoken_id: CurrencyId,
 		token_amount: Balance,
 	) -> Result<Balance, DispatchError>;
-	fn vtoken_to_token(
+	fn get_currency_amount_by_v_currency_amount(
 		token_id: CurrencyId,
 		vtoken_id: CurrencyId,
 		vtoken_amount: Balance,
 	) -> Result<Balance, DispatchError>;
-	fn vtoken_id(token_id: CurrencyId) -> Option<CurrencyId>;
-	fn token_id(vtoken_id: CurrencyId) -> Option<CurrencyId>;
 	fn get_token_pool(currency_id: CurrencyId) -> Balance;
 	fn get_minimums_redeem(vtoken_id: CurrencyId) -> Balance;
 	fn get_moonbeam_parachain_id() -> u32;
@@ -307,7 +298,7 @@ impl<AccountId, CurrencyId, Balance: Zero> VtokenMintingInterface<AccountId, Cur
 		Ok(().into())
 	}
 
-	fn token_to_vtoken(
+	fn get_v_currency_amount_by_currency_amount(
 		_token_id: CurrencyId,
 		_vtoken_id: CurrencyId,
 		_token_amount: Balance,
@@ -315,7 +306,7 @@ impl<AccountId, CurrencyId, Balance: Zero> VtokenMintingInterface<AccountId, Cur
 		Ok(Zero::zero())
 	}
 
-	fn vtoken_to_token(
+	fn get_currency_amount_by_v_currency_amount(
 		_token_id: CurrencyId,
 		_vtoken_id: CurrencyId,
 		_vtoken_amount: Balance,
@@ -323,14 +314,6 @@ impl<AccountId, CurrencyId, Balance: Zero> VtokenMintingInterface<AccountId, Cur
 		Ok(Zero::zero())
 	}
 
-	fn vtoken_id(_token_id: CurrencyId) -> Option<CurrencyId> {
-		None
-	}
-
-	fn token_id(_vtoken_id: CurrencyId) -> Option<CurrencyId> {
-		None
-	}
-
 	fn get_token_pool(_currency_id: CurrencyId) -> Balance {
 		Zero::zero()
 	}
diff --git a/runtime/bifrost-kusama/src/lib.rs b/runtime/bifrost-kusama/src/lib.rs
index 023e7fbc9..69f7802df 100644
--- a/runtime/bifrost-kusama/src/lib.rs
+++ b/runtime/bifrost-kusama/src/lib.rs
@@ -57,7 +57,7 @@ pub use pallet_balances::Call as BalancesCall;
 pub use pallet_timestamp::Call as TimestampCall;
 use sp_api::impl_runtime_apis;
 use sp_arithmetic::Percent;
-use sp_core::{ConstBool, OpaqueMetadata, U256};
+use sp_core::{ConstBool, OpaqueMetadata};
 use sp_runtime::{
 	create_runtime_str, generic, impl_opaque_keys,
 	traits::{
@@ -1448,20 +1448,16 @@ impl bifrost_vtoken_minting::Config for Runtime {
 	type ExitAccount = SlpExitPalletId;
 	type FeeAccount = BifrostFeeAccount;
 	type RedeemFeeAccount = BifrostFeeAccount;
-	type BifrostSlp = Slp;
 	type BifrostSlpx = Slpx;
 	type WeightInfo = weights::bifrost_vtoken_minting::BifrostWeight<Runtime>;
 	type OnRedeemSuccess = OnRedeemSuccess;
 	type RelayChainToken = RelayCurrencyId;
-	type CurrencyIdConversion = AssetIdMaps<Runtime>;
-	type CurrencyIdRegister = AssetIdMaps<Runtime>;
 	type XcmTransfer = XTokens;
 	type MoonbeamChainId = MoonriverChainId;
 	type ChannelCommission = ChannelCommission;
 	type MaxLockRecords = ConstU32<100>;
 	type IncentivePoolAccount = IncentivePoolAccount;
 	type BbBNC = ();
-	type AssetIdMaps = AssetIdMaps<Runtime>;
 }
 
 impl bifrost_slpx::Config for Runtime {
@@ -2254,9 +2250,13 @@ impl_runtime_apis! {
 		}
 	}
 
-	impl bifrost_vtoken_minting_rpc_runtime_api::VtokenMintingRuntimeApi<Block, CurrencyId> for Runtime {
-		fn get_exchange_rate(token_id: Option<CurrencyId>) -> Vec<(CurrencyId, U256)> {
-			VtokenMinting::get_exchange_rate(token_id).unwrap_or(Vec::new())
+	impl bifrost_vtoken_minting_rpc_runtime_api::VtokenMintingRuntimeApi<Block, CurrencyId, Balance> for Runtime {
+		fn get_currency_amount_by_v_currency_amount(currnecy_id: CurrencyId, v_currency_id: CurrencyId, v_currency_amount: Balance) -> Balance {
+			VtokenMinting::get_currency_amount_by_v_currency_amount(currnecy_id, v_currency_id, v_currency_amount).unwrap_or(0)
+		}
+
+		fn get_v_currency_amount_by_currency_amount(currnecy_id: CurrencyId, v_currency_id: CurrencyId, currency_amount: Balance) -> Balance {
+			VtokenMinting::get_v_currency_amount_by_currency_amount(currnecy_id, v_currency_id, currency_amount).unwrap_or(0)
 		}
 	}
 
diff --git a/runtime/bifrost-kusama/src/weights/bifrost_vtoken_minting.rs b/runtime/bifrost-kusama/src/weights/bifrost_vtoken_minting.rs
index c53ec8bb6..b8430618a 100644
--- a/runtime/bifrost-kusama/src/weights/bifrost_vtoken_minting.rs
+++ b/runtime/bifrost-kusama/src/weights/bifrost_vtoken_minting.rs
@@ -115,7 +115,7 @@ impl<T: frame_system::Config> bifrost_vtoken_minting::WeightInfo for BifrostWeig
 	}
 	/// Storage: `VtokenMinting::OngoingTimeUnit` (r:1 w:1)
 	/// Proof: `VtokenMinting::OngoingTimeUnit` (`max_values`: None, `max_size`: Some(27), added: 2502, mode: `MaxEncodedLen`)
-	fn recreate_currency_ongoing_time_unit() -> Weight {
+	fn set_ongoing_time_unit() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `180`
 		//  Estimated: `3492`
diff --git a/runtime/bifrost-polkadot/src/lib.rs b/runtime/bifrost-polkadot/src/lib.rs
index 38f978abb..17f9270b1 100644
--- a/runtime/bifrost-polkadot/src/lib.rs
+++ b/runtime/bifrost-polkadot/src/lib.rs
@@ -1334,20 +1334,16 @@ impl bifrost_vtoken_minting::Config for Runtime {
 	type ExitAccount = SlpExitPalletId;
 	type FeeAccount = BifrostFeeAccount;
 	type RedeemFeeAccount = BifrostFeeAccount;
-	type BifrostSlp = Slp;
 	type BifrostSlpx = Slpx;
 	type WeightInfo = weights::bifrost_vtoken_minting::BifrostWeight<Runtime>;
 	type OnRedeemSuccess = OnRedeemSuccess;
 	type RelayChainToken = RelayCurrencyId;
-	type CurrencyIdConversion = AssetIdMaps<Runtime>;
-	type CurrencyIdRegister = AssetIdMaps<Runtime>;
 	type XcmTransfer = XTokens;
 	type MoonbeamChainId = MoonbeamChainId;
 	type ChannelCommission = ChannelCommission;
 	type MaxLockRecords = ConstU32<100>;
 	type IncentivePoolAccount = IncentivePoolAccount;
 	type BbBNC = BbBNC;
-	type AssetIdMaps = AssetIdMaps<Runtime>;
 }
 
 parameter_types! {
@@ -2459,9 +2455,13 @@ impl fp_rpc::EthereumRuntimeRPCApi<Block> for Runtime {
 		}
 	}
 
-	impl bifrost_vtoken_minting_rpc_runtime_api::VtokenMintingRuntimeApi<Block, CurrencyId> for Runtime {
-		fn get_exchange_rate(token_id: Option<CurrencyId>) -> Vec<(CurrencyId, U256)> {
-			VtokenMinting::get_exchange_rate(token_id).unwrap_or(Vec::new())
+	impl bifrost_vtoken_minting_rpc_runtime_api::VtokenMintingRuntimeApi<Block, CurrencyId, Balance> for Runtime {
+		fn get_currency_amount_by_v_currency_amount(currnecy_id: CurrencyId, v_currency_id: CurrencyId, v_currency_amount: Balance) -> Balance {
+			VtokenMinting::get_currency_amount_by_v_currency_amount(currnecy_id, v_currency_id, v_currency_amount).unwrap_or(0)
+		}
+
+		fn get_v_currency_amount_by_currency_amount(currnecy_id: CurrencyId, v_currency_id: CurrencyId, currency_amount: Balance) -> Balance {
+			VtokenMinting::get_v_currency_amount_by_currency_amount(currnecy_id, v_currency_id, currency_amount).unwrap_or(0)
 		}
 	}
 
diff --git a/runtime/bifrost-polkadot/src/weights/bifrost_vtoken_minting.rs b/runtime/bifrost-polkadot/src/weights/bifrost_vtoken_minting.rs
index c53ec8bb6..b8430618a 100644
--- a/runtime/bifrost-polkadot/src/weights/bifrost_vtoken_minting.rs
+++ b/runtime/bifrost-polkadot/src/weights/bifrost_vtoken_minting.rs
@@ -115,7 +115,7 @@ impl<T: frame_system::Config> bifrost_vtoken_minting::WeightInfo for BifrostWeig
 	}
 	/// Storage: `VtokenMinting::OngoingTimeUnit` (r:1 w:1)
 	/// Proof: `VtokenMinting::OngoingTimeUnit` (`max_values`: None, `max_size`: Some(27), added: 2502, mode: `MaxEncodedLen`)
-	fn recreate_currency_ongoing_time_unit() -> Weight {
+	fn set_ongoing_time_unit() -> Weight {
 		// Proof Size summary in bytes:
 		//  Measured:  `180`
 		//  Estimated: `3492`

From bcd1527121649ddfa71e5aeb0e08842c6eb1fbb7 Mon Sep 17 00:00:00 2001
From: MJLNSN <96321798+MJLNSN@users.noreply.github.com>
Date: Wed, 16 Oct 2024 23:14:11 +0800
Subject: [PATCH 27/31] Replaced bifrost-finance with bifrost-io. (#1466)

* updated

* unsolved

* unsolved

* Fix compile

---------

Co-authored-by: hqwangningbo <2536935847@qq.com>
---
 Cargo.lock                          | 84 ++++++++++++++---------------
 Cargo.toml                          | 82 ++++++++++++++--------------
 README.md                           |  8 +--
 node/cli/src/command.rs             |  4 +-
 pallets/parachain-staking/README.md |  6 +--
 pallets/system-staking/Cargo.toml   |  4 +-
 scripts/bifrost-ecosystem.config.js |  2 +-
 7 files changed, 95 insertions(+), 95 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 8dac475d6..c201192fd 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4736,7 +4736,7 @@ dependencies = [
 [[package]]
 name = "fc-api"
 version = "1.0.0-dev"
-source = "git+https://github.com/bifrost-finance/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
+source = "git+https://github.com/bifrost-io/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
 dependencies = [
  "async-trait",
  "fp-storage",
@@ -4748,7 +4748,7 @@ dependencies = [
 [[package]]
 name = "fc-consensus"
 version = "2.0.0-dev"
-source = "git+https://github.com/bifrost-finance/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
+source = "git+https://github.com/bifrost-io/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
 dependencies = [
  "async-trait",
  "fp-consensus",
@@ -4764,7 +4764,7 @@ dependencies = [
 [[package]]
 name = "fc-db"
 version = "2.0.0-dev"
-source = "git+https://github.com/bifrost-finance/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
+source = "git+https://github.com/bifrost-io/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
 dependencies = [
  "async-trait",
  "ethereum 0.15.0",
@@ -4794,7 +4794,7 @@ dependencies = [
 [[package]]
 name = "fc-mapping-sync"
 version = "2.0.0-dev"
-source = "git+https://github.com/bifrost-finance/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
+source = "git+https://github.com/bifrost-io/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
 dependencies = [
  "fc-db",
  "fc-storage",
@@ -4817,7 +4817,7 @@ dependencies = [
 [[package]]
 name = "fc-rpc"
 version = "2.0.0-dev"
-source = "git+https://github.com/bifrost-finance/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
+source = "git+https://github.com/bifrost-io/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
 dependencies = [
  "ethereum 0.15.0",
  "ethereum-types",
@@ -4871,7 +4871,7 @@ dependencies = [
 [[package]]
 name = "fc-rpc-core"
 version = "1.1.0-dev"
-source = "git+https://github.com/bifrost-finance/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
+source = "git+https://github.com/bifrost-io/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
 dependencies = [
  "ethereum 0.15.0",
  "ethereum-types",
@@ -4886,7 +4886,7 @@ dependencies = [
 [[package]]
 name = "fc-storage"
 version = "1.0.0-dev"
-source = "git+https://github.com/bifrost-finance/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
+source = "git+https://github.com/bifrost-io/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
 dependencies = [
  "ethereum 0.15.0",
  "ethereum-types",
@@ -5088,7 +5088,7 @@ dependencies = [
 [[package]]
 name = "fp-account"
 version = "1.0.0-dev"
-source = "git+https://github.com/bifrost-finance/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
+source = "git+https://github.com/bifrost-io/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
 dependencies = [
  "hex",
  "impl-serde",
@@ -5106,7 +5106,7 @@ dependencies = [
 [[package]]
 name = "fp-consensus"
 version = "2.0.0-dev"
-source = "git+https://github.com/bifrost-finance/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
+source = "git+https://github.com/bifrost-io/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
 dependencies = [
  "ethereum 0.15.0",
  "parity-scale-codec",
@@ -5117,7 +5117,7 @@ dependencies = [
 [[package]]
 name = "fp-dynamic-fee"
 version = "1.0.0"
-source = "git+https://github.com/bifrost-finance/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
+source = "git+https://github.com/bifrost-io/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
 dependencies = [
  "async-trait",
  "sp-core",
@@ -5127,7 +5127,7 @@ dependencies = [
 [[package]]
 name = "fp-ethereum"
 version = "1.0.0-dev"
-source = "git+https://github.com/bifrost-finance/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
+source = "git+https://github.com/bifrost-io/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
 dependencies = [
  "ethereum 0.15.0",
  "ethereum-types",
@@ -5139,7 +5139,7 @@ dependencies = [
 [[package]]
 name = "fp-evm"
 version = "3.0.0-dev"
-source = "git+https://github.com/bifrost-finance/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
+source = "git+https://github.com/bifrost-io/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
 dependencies = [
  "evm",
  "frame-support",
@@ -5154,7 +5154,7 @@ dependencies = [
 [[package]]
 name = "fp-rpc"
 version = "3.0.0-dev"
-source = "git+https://github.com/bifrost-finance/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
+source = "git+https://github.com/bifrost-io/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
 dependencies = [
  "ethereum 0.15.0",
  "ethereum-types",
@@ -5170,7 +5170,7 @@ dependencies = [
 [[package]]
 name = "fp-self-contained"
 version = "1.0.0-dev"
-source = "git+https://github.com/bifrost-finance/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
+source = "git+https://github.com/bifrost-io/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
 dependencies = [
  "frame-support",
  "parity-scale-codec",
@@ -5182,7 +5182,7 @@ dependencies = [
 [[package]]
 name = "fp-storage"
 version = "2.0.0"
-source = "git+https://github.com/bifrost-finance/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
+source = "git+https://github.com/bifrost-io/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
 dependencies = [
  "parity-scale-codec",
  "serde",
@@ -7549,7 +7549,7 @@ dependencies = [
 [[package]]
 name = "merkle-distributor"
 version = "0.1.0"
-source = "git+https://github.com/bifrost-finance/Zenlink-DEX-Module?branch=release-polkadot-v1.13.0#64e75422be893afe8b5029ce831b7318748a99c6"
+source = "git+https://github.com/bifrost-io/Zenlink-DEX-Module?branch=release-polkadot-v1.13.0#870ec20d64a994f6ab1ae87c6b819f07d3311319"
 dependencies = [
  "frame-support",
  "frame-system",
@@ -8427,7 +8427,7 @@ dependencies = [
 [[package]]
 name = "orml-oracle"
 version = "0.13.0"
-source = "git+https://github.com/bifrost-finance/open-runtime-module-library?branch=release-polkadot-v1.13.0#a7ea052e958275502022b25f1fc1e5b0e146fe51"
+source = "git+https://github.com/bifrost-io/open-runtime-module-library?branch=release-polkadot-v1.13.0#a7ea052e958275502022b25f1fc1e5b0e146fe51"
 dependencies = [
  "frame-benchmarking",
  "frame-support",
@@ -8446,7 +8446,7 @@ dependencies = [
 [[package]]
 name = "orml-tokens"
 version = "0.13.0"
-source = "git+https://github.com/bifrost-finance/open-runtime-module-library?branch=release-polkadot-v1.13.0#a7ea052e958275502022b25f1fc1e5b0e146fe51"
+source = "git+https://github.com/bifrost-io/open-runtime-module-library?branch=release-polkadot-v1.13.0#a7ea052e958275502022b25f1fc1e5b0e146fe51"
 dependencies = [
  "frame-support",
  "frame-system",
@@ -8463,7 +8463,7 @@ dependencies = [
 [[package]]
 name = "orml-traits"
 version = "0.13.0"
-source = "git+https://github.com/bifrost-finance/open-runtime-module-library?branch=release-polkadot-v1.13.0#a7ea052e958275502022b25f1fc1e5b0e146fe51"
+source = "git+https://github.com/bifrost-io/open-runtime-module-library?branch=release-polkadot-v1.13.0#a7ea052e958275502022b25f1fc1e5b0e146fe51"
 dependencies = [
  "frame-support",
  "impl-trait-for-tuples",
@@ -8483,7 +8483,7 @@ dependencies = [
 [[package]]
 name = "orml-unknown-tokens"
 version = "0.13.0"
-source = "git+https://github.com/bifrost-finance/open-runtime-module-library?branch=release-polkadot-v1.13.0#a7ea052e958275502022b25f1fc1e5b0e146fe51"
+source = "git+https://github.com/bifrost-io/open-runtime-module-library?branch=release-polkadot-v1.13.0#a7ea052e958275502022b25f1fc1e5b0e146fe51"
 dependencies = [
  "frame-support",
  "frame-system",
@@ -8498,7 +8498,7 @@ dependencies = [
 [[package]]
 name = "orml-utilities"
 version = "0.13.0"
-source = "git+https://github.com/bifrost-finance/open-runtime-module-library?branch=release-polkadot-v1.13.0#a7ea052e958275502022b25f1fc1e5b0e146fe51"
+source = "git+https://github.com/bifrost-io/open-runtime-module-library?branch=release-polkadot-v1.13.0#a7ea052e958275502022b25f1fc1e5b0e146fe51"
 dependencies = [
  "frame-support",
  "parity-scale-codec",
@@ -8513,7 +8513,7 @@ dependencies = [
 [[package]]
 name = "orml-xcm"
 version = "0.13.0"
-source = "git+https://github.com/bifrost-finance/open-runtime-module-library?branch=release-polkadot-v1.13.0#a7ea052e958275502022b25f1fc1e5b0e146fe51"
+source = "git+https://github.com/bifrost-io/open-runtime-module-library?branch=release-polkadot-v1.13.0#a7ea052e958275502022b25f1fc1e5b0e146fe51"
 dependencies = [
  "frame-support",
  "frame-system",
@@ -8527,7 +8527,7 @@ dependencies = [
 [[package]]
 name = "orml-xcm-support"
 version = "0.13.0"
-source = "git+https://github.com/bifrost-finance/open-runtime-module-library?branch=release-polkadot-v1.13.0#a7ea052e958275502022b25f1fc1e5b0e146fe51"
+source = "git+https://github.com/bifrost-io/open-runtime-module-library?branch=release-polkadot-v1.13.0#a7ea052e958275502022b25f1fc1e5b0e146fe51"
 dependencies = [
  "frame-support",
  "orml-traits",
@@ -8541,7 +8541,7 @@ dependencies = [
 [[package]]
 name = "orml-xtokens"
 version = "0.13.0"
-source = "git+https://github.com/bifrost-finance/open-runtime-module-library?branch=release-polkadot-v1.13.0#a7ea052e958275502022b25f1fc1e5b0e146fe51"
+source = "git+https://github.com/bifrost-io/open-runtime-module-library?branch=release-polkadot-v1.13.0#a7ea052e958275502022b25f1fc1e5b0e146fe51"
 dependencies = [
  "frame-support",
  "frame-system",
@@ -8745,7 +8745,7 @@ dependencies = [
 [[package]]
 name = "pallet-base-fee"
 version = "1.0.0"
-source = "git+https://github.com/bifrost-finance/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
+source = "git+https://github.com/bifrost-io/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
 dependencies = [
  "fp-evm",
  "frame-support",
@@ -8946,7 +8946,7 @@ dependencies = [
 [[package]]
 name = "pallet-dynamic-fee"
 version = "4.0.0-dev"
-source = "git+https://github.com/bifrost-finance/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
+source = "git+https://github.com/bifrost-io/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
 dependencies = [
  "fp-dynamic-fee",
  "fp-evm",
@@ -9017,7 +9017,7 @@ dependencies = [
 [[package]]
 name = "pallet-ethereum"
 version = "4.0.0-dev"
-source = "git+https://github.com/bifrost-finance/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
+source = "git+https://github.com/bifrost-io/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
 dependencies = [
  "ethereum 0.15.0",
  "ethereum-types",
@@ -9039,7 +9039,7 @@ dependencies = [
 [[package]]
 name = "pallet-evm"
 version = "6.0.0-dev"
-source = "git+https://github.com/bifrost-finance/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
+source = "git+https://github.com/bifrost-io/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
 dependencies = [
  "environmental",
  "evm",
@@ -9089,7 +9089,7 @@ dependencies = [
 [[package]]
 name = "pallet-evm-chain-id"
 version = "1.0.0-dev"
-source = "git+https://github.com/bifrost-finance/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
+source = "git+https://github.com/bifrost-io/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
 dependencies = [
  "frame-support",
  "frame-system",
@@ -9100,7 +9100,7 @@ dependencies = [
 [[package]]
 name = "pallet-evm-precompile-blake2"
 version = "2.0.0-dev"
-source = "git+https://github.com/bifrost-finance/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
+source = "git+https://github.com/bifrost-io/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
 dependencies = [
  "fp-evm",
 ]
@@ -9108,7 +9108,7 @@ dependencies = [
 [[package]]
 name = "pallet-evm-precompile-bn128"
 version = "2.0.0-dev"
-source = "git+https://github.com/bifrost-finance/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
+source = "git+https://github.com/bifrost-io/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
 dependencies = [
  "fp-evm",
  "sp-core",
@@ -9118,7 +9118,7 @@ dependencies = [
 [[package]]
 name = "pallet-evm-precompile-dispatch"
 version = "2.0.0-dev"
-source = "git+https://github.com/bifrost-finance/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
+source = "git+https://github.com/bifrost-io/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
 dependencies = [
  "fp-evm",
  "frame-support",
@@ -9130,7 +9130,7 @@ dependencies = [
 [[package]]
 name = "pallet-evm-precompile-modexp"
 version = "2.0.0-dev"
-source = "git+https://github.com/bifrost-finance/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
+source = "git+https://github.com/bifrost-io/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
 dependencies = [
  "fp-evm",
  "num",
@@ -9139,7 +9139,7 @@ dependencies = [
 [[package]]
 name = "pallet-evm-precompile-sha3fips"
 version = "2.0.0-dev"
-source = "git+https://github.com/bifrost-finance/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
+source = "git+https://github.com/bifrost-io/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
 dependencies = [
  "fp-evm",
  "tiny-keccak",
@@ -9148,7 +9148,7 @@ dependencies = [
 [[package]]
 name = "pallet-evm-precompile-simple"
 version = "2.0.0-dev"
-source = "git+https://github.com/bifrost-finance/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
+source = "git+https://github.com/bifrost-io/frontier?branch=release-polkadot-v1.13.0#24a48ebc221399d129712eff41787ad800dc8a26"
 dependencies = [
  "fp-evm",
  "ripemd",
@@ -18034,7 +18034,7 @@ dependencies = [
 [[package]]
 name = "zenlink-protocol"
 version = "0.4.4"
-source = "git+https://github.com/bifrost-finance/Zenlink-DEX-Module?branch=release-polkadot-v1.13.0#64e75422be893afe8b5029ce831b7318748a99c6"
+source = "git+https://github.com/bifrost-io/Zenlink-DEX-Module?branch=release-polkadot-v1.13.0#870ec20d64a994f6ab1ae87c6b819f07d3311319"
 dependencies = [
  "cumulus-primitives-core",
  "frame-benchmarking",
@@ -18056,7 +18056,7 @@ dependencies = [
 [[package]]
 name = "zenlink-protocol-rpc"
 version = "0.4.4"
-source = "git+https://github.com/bifrost-finance/Zenlink-DEX-Module?branch=release-polkadot-v1.13.0#64e75422be893afe8b5029ce831b7318748a99c6"
+source = "git+https://github.com/bifrost-io/Zenlink-DEX-Module?branch=release-polkadot-v1.13.0#870ec20d64a994f6ab1ae87c6b819f07d3311319"
 dependencies = [
  "jsonrpsee",
  "parity-scale-codec",
@@ -18072,7 +18072,7 @@ dependencies = [
 [[package]]
 name = "zenlink-protocol-runtime-api"
 version = "0.4.4"
-source = "git+https://github.com/bifrost-finance/Zenlink-DEX-Module?branch=release-polkadot-v1.13.0#64e75422be893afe8b5029ce831b7318748a99c6"
+source = "git+https://github.com/bifrost-io/Zenlink-DEX-Module?branch=release-polkadot-v1.13.0#870ec20d64a994f6ab1ae87c6b819f07d3311319"
 dependencies = [
  "parity-scale-codec",
  "sp-api",
@@ -18083,7 +18083,7 @@ dependencies = [
 [[package]]
 name = "zenlink-stable-amm"
 version = "0.1.0"
-source = "git+https://github.com/bifrost-finance/Zenlink-DEX-Module?branch=release-polkadot-v1.13.0#64e75422be893afe8b5029ce831b7318748a99c6"
+source = "git+https://github.com/bifrost-io/Zenlink-DEX-Module?branch=release-polkadot-v1.13.0#870ec20d64a994f6ab1ae87c6b819f07d3311319"
 dependencies = [
  "frame-support",
  "frame-system",
@@ -18100,7 +18100,7 @@ dependencies = [
 [[package]]
 name = "zenlink-stable-amm-rpc"
 version = "0.1.0"
-source = "git+https://github.com/bifrost-finance/Zenlink-DEX-Module?branch=release-polkadot-v1.13.0#64e75422be893afe8b5029ce831b7318748a99c6"
+source = "git+https://github.com/bifrost-io/Zenlink-DEX-Module?branch=release-polkadot-v1.13.0#870ec20d64a994f6ab1ae87c6b819f07d3311319"
 dependencies = [
  "jsonrpsee",
  "parity-scale-codec",
@@ -18114,7 +18114,7 @@ dependencies = [
 [[package]]
 name = "zenlink-stable-amm-runtime-api"
 version = "0.1.0"
-source = "git+https://github.com/bifrost-finance/Zenlink-DEX-Module?branch=release-polkadot-v1.13.0#64e75422be893afe8b5029ce831b7318748a99c6"
+source = "git+https://github.com/bifrost-io/Zenlink-DEX-Module?branch=release-polkadot-v1.13.0#870ec20d64a994f6ab1ae87c6b819f07d3311319"
 dependencies = [
  "parity-scale-codec",
  "sp-api",
@@ -18125,7 +18125,7 @@ dependencies = [
 [[package]]
 name = "zenlink-swap-router"
 version = "0.1.0"
-source = "git+https://github.com/bifrost-finance/Zenlink-DEX-Module?branch=release-polkadot-v1.13.0#64e75422be893afe8b5029ce831b7318748a99c6"
+source = "git+https://github.com/bifrost-io/Zenlink-DEX-Module?branch=release-polkadot-v1.13.0#870ec20d64a994f6ab1ae87c6b819f07d3311319"
 dependencies = [
  "frame-support",
  "frame-system",
diff --git a/Cargo.toml b/Cargo.toml
index dbe0830a0..f3b79a2b5 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -106,51 +106,51 @@ pallet-prices                          = { path = "pallets/prices", default-feat
 pallet-traits                          = { path = "pallets/traits", default-features = false }
 
 # Zenlink
-merkle-distributor             = { git = "https://github.com/bifrost-finance/Zenlink-DEX-Module", branch = "release-polkadot-v1.13.0", default-features = false }
-zenlink-protocol               = { git = "https://github.com/bifrost-finance/Zenlink-DEX-Module", branch = "release-polkadot-v1.13.0", default-features = false }
-zenlink-protocol-rpc           = { git = "https://github.com/bifrost-finance/Zenlink-DEX-Module", branch = "release-polkadot-v1.13.0" }
-zenlink-protocol-runtime-api   = { git = "https://github.com/bifrost-finance/Zenlink-DEX-Module", branch = "release-polkadot-v1.13.0", default-features = false }
-zenlink-stable-amm             = { git = "https://github.com/bifrost-finance/Zenlink-DEX-Module", branch = "release-polkadot-v1.13.0", default-features = false }
-zenlink-stable-amm-rpc         = { git = "https://github.com/bifrost-finance/Zenlink-DEX-Module", branch = "release-polkadot-v1.13.0" }
-zenlink-stable-amm-runtime-api = { git = "https://github.com/bifrost-finance/Zenlink-DEX-Module", branch = "release-polkadot-v1.13.0", default-features = false }
-zenlink-swap-router            = { git = "https://github.com/bifrost-finance/Zenlink-DEX-Module", branch = "release-polkadot-v1.13.0", default-features = false }
+merkle-distributor             = { git = "https://github.com/bifrost-io/Zenlink-DEX-Module", branch = "release-polkadot-v1.13.0", default-features = false }
+zenlink-protocol               = { git = "https://github.com/bifrost-io/Zenlink-DEX-Module", branch = "release-polkadot-v1.13.0", default-features = false }
+zenlink-protocol-rpc           = { git = "https://github.com/bifrost-io/Zenlink-DEX-Module", branch = "release-polkadot-v1.13.0" }
+zenlink-protocol-runtime-api   = { git = "https://github.com/bifrost-io/Zenlink-DEX-Module", branch = "release-polkadot-v1.13.0", default-features = false }
+zenlink-stable-amm             = { git = "https://github.com/bifrost-io/Zenlink-DEX-Module", branch = "release-polkadot-v1.13.0", default-features = false }
+zenlink-stable-amm-rpc         = { git = "https://github.com/bifrost-io/Zenlink-DEX-Module", branch = "release-polkadot-v1.13.0" }
+zenlink-stable-amm-runtime-api = { git = "https://github.com/bifrost-io/Zenlink-DEX-Module", branch = "release-polkadot-v1.13.0", default-features = false }
+zenlink-swap-router            = { git = "https://github.com/bifrost-io/Zenlink-DEX-Module", branch = "release-polkadot-v1.13.0", default-features = false }
 
 # Orml
-orml-tokens         = { git = "https://github.com/bifrost-finance/open-runtime-module-library", branch = "release-polkadot-v1.13.0", default-features = false }
-orml-traits         = { git = "https://github.com/bifrost-finance/open-runtime-module-library", branch = "release-polkadot-v1.13.0", default-features = false }
-orml-unknown-tokens = { git = "https://github.com/bifrost-finance/open-runtime-module-library", branch = "release-polkadot-v1.13.0", default-features = false }
-orml-utilities      = { git = "https://github.com/bifrost-finance/open-runtime-module-library", branch = "release-polkadot-v1.13.0", default-features = false }
-orml-xcm            = { git = "https://github.com/bifrost-finance/open-runtime-module-library", branch = "release-polkadot-v1.13.0", default-features = false }
-orml-xcm-support    = { git = "https://github.com/bifrost-finance/open-runtime-module-library", branch = "release-polkadot-v1.13.0", default-features = false }
-orml-xtokens        = { git = "https://github.com/bifrost-finance/open-runtime-module-library", branch = "release-polkadot-v1.13.0", default-features = false }
-orml-oracle         = { git = "https://github.com/bifrost-finance/open-runtime-module-library", branch = "release-polkadot-v1.13.0", default-features = false }
+orml-tokens         = { git = "https://github.com/bifrost-io/open-runtime-module-library", branch = "release-polkadot-v1.13.0", default-features = false }
+orml-traits         = { git = "https://github.com/bifrost-io/open-runtime-module-library", branch = "release-polkadot-v1.13.0", default-features = false }
+orml-unknown-tokens = { git = "https://github.com/bifrost-io/open-runtime-module-library", branch = "release-polkadot-v1.13.0", default-features = false }
+orml-utilities      = { git = "https://github.com/bifrost-io/open-runtime-module-library", branch = "release-polkadot-v1.13.0", default-features = false }
+orml-xcm            = { git = "https://github.com/bifrost-io/open-runtime-module-library", branch = "release-polkadot-v1.13.0", default-features = false }
+orml-xcm-support    = { git = "https://github.com/bifrost-io/open-runtime-module-library", branch = "release-polkadot-v1.13.0", default-features = false }
+orml-xtokens        = { git = "https://github.com/bifrost-io/open-runtime-module-library", branch = "release-polkadot-v1.13.0", default-features = false }
+orml-oracle         = { git = "https://github.com/bifrost-io/open-runtime-module-library", branch = "release-polkadot-v1.13.0", default-features = false }
 
 # Frontier
-fc-api                         = { git = "https://github.com/bifrost-finance/frontier", branch = "release-polkadot-v1.13.0", default-features = false }
-fc-consensus                   = { git = "https://github.com/bifrost-finance/frontier", branch = "release-polkadot-v1.13.0", default-features = false }
-fc-db                          = { git = "https://github.com/bifrost-finance/frontier", branch = "release-polkadot-v1.13.0", default-features = false }
-fc-mapping-sync                = { git = "https://github.com/bifrost-finance/frontier", branch = "release-polkadot-v1.13.0", default-features = false }
-fc-rpc                         = { git = "https://github.com/bifrost-finance/frontier", branch = "release-polkadot-v1.13.0", default-features = false }
-fc-rpc-core                    = { git = "https://github.com/bifrost-finance/frontier", branch = "release-polkadot-v1.13.0", default-features = false }
-fc-storage                     = { git = "https://github.com/bifrost-finance/frontier", branch = "release-polkadot-v1.13.0", default-features = false }
-fp-account                     = { git = "https://github.com/bifrost-finance/frontier", branch = "release-polkadot-v1.13.0", default-features = false }
-fp-consensus                   = { git = "https://github.com/bifrost-finance/frontier", branch = "release-polkadot-v1.13.0", default-features = false }
-fp-dynamic-fee                 = { git = "https://github.com/bifrost-finance/frontier", branch = "release-polkadot-v1.13.0", default-features = false }
-fp-evm                         = { git = "https://github.com/bifrost-finance/frontier", branch = "release-polkadot-v1.13.0", default-features = false }
-fp-rpc                         = { git = "https://github.com/bifrost-finance/frontier", branch = "release-polkadot-v1.13.0", default-features = false }
-fp-self-contained              = { git = "https://github.com/bifrost-finance/frontier", branch = "release-polkadot-v1.13.0", default-features = false }
-fp-storage                     = { git = "https://github.com/bifrost-finance/frontier", branch = "release-polkadot-v1.13.0", default-features = false }
-pallet-base-fee                = { git = "https://github.com/bifrost-finance/frontier", branch = "release-polkadot-v1.13.0", default-features = false }
-pallet-dynamic-fee             = { git = "https://github.com/bifrost-finance/frontier", branch = "release-polkadot-v1.13.0", default-features = false }
-pallet-ethereum                = { git = "https://github.com/bifrost-finance/frontier", branch = "release-polkadot-v1.13.0", default-features = false }
-pallet-evm                     = { git = "https://github.com/bifrost-finance/frontier", branch = "release-polkadot-v1.13.0", default-features = false }
-pallet-evm-chain-id            = { git = "https://github.com/bifrost-finance/frontier", branch = "release-polkadot-v1.13.0", default-features = false }
-pallet-evm-precompile-blake2   = { git = "https://github.com/bifrost-finance/frontier", branch = "release-polkadot-v1.13.0", default-features = false }
-pallet-evm-precompile-bn128    = { git = "https://github.com/bifrost-finance/frontier", branch = "release-polkadot-v1.13.0", default-features = false }
-pallet-evm-precompile-dispatch = { git = "https://github.com/bifrost-finance/frontier", branch = "release-polkadot-v1.13.0", default-features = false }
-pallet-evm-precompile-modexp   = { git = "https://github.com/bifrost-finance/frontier", branch = "release-polkadot-v1.13.0", default-features = false }
-pallet-evm-precompile-sha3fips = { git = "https://github.com/bifrost-finance/frontier", branch = "release-polkadot-v1.13.0", default-features = false }
-pallet-evm-precompile-simple   = { git = "https://github.com/bifrost-finance/frontier", branch = "release-polkadot-v1.13.0", default-features = false }
+fc-api                         = { git = "https://github.com/bifrost-io/frontier", branch = "release-polkadot-v1.13.0", default-features = false }
+fc-consensus                   = { git = "https://github.com/bifrost-io/frontier", branch = "release-polkadot-v1.13.0", default-features = false }
+fc-db                          = { git = "https://github.com/bifrost-io/frontier", branch = "release-polkadot-v1.13.0", default-features = false }
+fc-mapping-sync                = { git = "https://github.com/bifrost-io/frontier", branch = "release-polkadot-v1.13.0", default-features = false }
+fc-rpc                         = { git = "https://github.com/bifrost-io/frontier", branch = "release-polkadot-v1.13.0", default-features = false }
+fc-rpc-core                    = { git = "https://github.com/bifrost-io/frontier", branch = "release-polkadot-v1.13.0", default-features = false }
+fc-storage                     = { git = "https://github.com/bifrost-io/frontier", branch = "release-polkadot-v1.13.0", default-features = false }
+fp-account                     = { git = "https://github.com/bifrost-io/frontier", branch = "release-polkadot-v1.13.0", default-features = false }
+fp-consensus                   = { git = "https://github.com/bifrost-io/frontier", branch = "release-polkadot-v1.13.0", default-features = false }
+fp-dynamic-fee                 = { git = "https://github.com/bifrost-io/frontier", branch = "release-polkadot-v1.13.0", default-features = false }
+fp-evm                         = { git = "https://github.com/bifrost-io/frontier", branch = "release-polkadot-v1.13.0", default-features = false }
+fp-rpc                         = { git = "https://github.com/bifrost-io/frontier", branch = "release-polkadot-v1.13.0", default-features = false }
+fp-self-contained              = { git = "https://github.com/bifrost-io/frontier", branch = "release-polkadot-v1.13.0", default-features = false }
+fp-storage                     = { git = "https://github.com/bifrost-io/frontier", branch = "release-polkadot-v1.13.0", default-features = false }
+pallet-base-fee                = { git = "https://github.com/bifrost-io/frontier", branch = "release-polkadot-v1.13.0", default-features = false }
+pallet-dynamic-fee             = { git = "https://github.com/bifrost-io/frontier", branch = "release-polkadot-v1.13.0", default-features = false }
+pallet-ethereum                = { git = "https://github.com/bifrost-io/frontier", branch = "release-polkadot-v1.13.0", default-features = false }
+pallet-evm                     = { git = "https://github.com/bifrost-io/frontier", branch = "release-polkadot-v1.13.0", default-features = false }
+pallet-evm-chain-id            = { git = "https://github.com/bifrost-io/frontier", branch = "release-polkadot-v1.13.0", default-features = false }
+pallet-evm-precompile-blake2   = { git = "https://github.com/bifrost-io/frontier", branch = "release-polkadot-v1.13.0", default-features = false }
+pallet-evm-precompile-bn128    = { git = "https://github.com/bifrost-io/frontier", branch = "release-polkadot-v1.13.0", default-features = false }
+pallet-evm-precompile-dispatch = { git = "https://github.com/bifrost-io/frontier", branch = "release-polkadot-v1.13.0", default-features = false }
+pallet-evm-precompile-modexp   = { git = "https://github.com/bifrost-io/frontier", branch = "release-polkadot-v1.13.0", default-features = false }
+pallet-evm-precompile-sha3fips = { git = "https://github.com/bifrost-io/frontier", branch = "release-polkadot-v1.13.0", default-features = false }
+pallet-evm-precompile-simple   = { git = "https://github.com/bifrost-io/frontier", branch = "release-polkadot-v1.13.0", default-features = false }
 
 # polkadot-sdk (wasm)
 cumulus-client-collator                    = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.13.0", default-features = false }
diff --git a/README.md b/README.md
index c2d31c536..60bcfa523 100644
--- a/README.md
+++ b/README.md
@@ -21,13 +21,13 @@ Bifrost is a Web3 derivatives protocol that provides decentralized cross-chain l
   <a href="https://bootcamp.web3.foundation/"><img src="docs/res/readme/web3-bootcamp.svg" width="200" alt="Web3 Bootcamp"></a>
 </p>
 
-[![master-build](https://img.shields.io/github/actions/workflow/status/bifrost-finance/bifrost/ci-build.yml?logo=Buddy)](https://github.com/bifrost-finance/bifrost/actions/workflows/ci-build.yml)
-[![Codacy Badge](https://app.codacy.com/project/badge/Grade/acec53276777415593c2b02b2200f62e)](https://www.codacy.com/gh/bifrost-finance/bifrost?utm_source=github.com&utm_medium=referral&utm_content=bifrost-finance/bifrost&utm_campaign=Badge_Grade)
+[![master-build](https://img.shields.io/github/actions/workflow/status/bifrost-io/bifrost/ci-build.yml?logo=Buddy)](https://github.com/bifrost-io/bifrost/actions/workflows/ci-build.yml)
+[![Codacy Badge](https://app.codacy.com/project/badge/Grade/acec53276777415593c2b02b2200f62e)](https://www.codacy.com/gh/bifrost-io/bifrost?utm_source=github.com&utm_medium=referral&utm_content=bifrost-io/bifrost&utm_campaign=Badge_Grade)
 [![Substrate Version](https://img.shields.io/badge/Substrate-latest-brightgreen?logo=Parity%20Substrate)](https://github.com/paritytech/substrate)
-[![License](https://img.shields.io/github/license/bifrost-finance/bifrost?color=blue)](https://github.com/bifrost-finance/bifrost/blob/master/LICENSE)
+[![License](https://img.shields.io/github/license/bifrost-io/bifrost?color=blue)](https://github.com/bifrost-io/bifrost/blob/master/LICENSE)
 [![Dapp](https://img.shields.io/badge/Dapp-5c5c5c?logo=Icinga)](https://app.bifrost.io)
 [![Analytics](https://img.shields.io/badge/-Analytics-5c5c5c?logo=Google%20Analytics)](https://stats.bifrost.io)
-[![Discord](https://img.shields.io/badge/-Discord-5c5c5c?logo=Discord)](https://discord.gg/bifrost-finance)
+[![Discord](https://img.shields.io/badge/-Discord-5c5c5c?logo=Discord)](https://discord.gg/bifrost-io)
 [![Twitter](https://img.shields.io/badge/-X-5c5c5c?logo=X&logoColor=white)](https://x.com/Bifrost)
 
 ## Get Build Help
diff --git a/node/cli/src/command.rs b/node/cli/src/command.rs
index ec2445401..f415a92b1 100644
--- a/node/cli/src/command.rs
+++ b/node/cli/src/command.rs
@@ -137,7 +137,7 @@ impl SubstrateCli for Cli {
 	}
 
 	fn support_url() -> String {
-		"https://github.com/bifrost-finance/bifrost/issues/new".into()
+		"https://github.com/bifrost-io/bifrost/issues/new".into()
 	}
 
 	fn copyright_start_year() -> i32 {
@@ -171,7 +171,7 @@ impl SubstrateCli for RelayChainCli {
 	}
 
 	fn support_url() -> String {
-		"https://github.com/bifrost-finance/bifrost/issues/new".into()
+		"https://github.com/bifrost-io/bifrost/issues/new".into()
 	}
 
 	fn copyright_start_year() -> i32 {
diff --git a/pallets/parachain-staking/README.md b/pallets/parachain-staking/README.md
index f995f3161..9a8e2f58a 100644
--- a/pallets/parachain-staking/README.md
+++ b/pallets/parachain-staking/README.md
@@ -1,6 +1,6 @@
 # Collator Staking
 
-[![Rust Check & Build](https://github.com/bifrost-finance/parachain-staking/actions/workflows/ci.yml/badge.svg)](https://github.com/bifrost-finance/parachain-staking/actions/workflows/ci.yml)
+[![Rust Check & Build](https://github.com/bifrost-io/parachain-staking/actions/workflows/ci.yml/badge.svg)](https://github.com/bifrost-io/parachain-staking/actions/workflows/ci.yml)
 
 ## check && build
 
@@ -114,7 +114,7 @@ mainly reference moonbeam implementation while decouple `nimbus` from staking, i
 
 ### Decomple with Nimbus
 
-<https://github.com/bifrost-finance/moonbeam/commit/2e3f7dddad6294b661e08d17b45f42e853b4ecff>
+<https://github.com/bifrost-io/moonbeam/commit/2e3f7dddad6294b661e08d17b45f42e853b4ecff>
 
 ## Benifit of Nimbus
 
@@ -122,7 +122,7 @@ mainly reference moonbeam implementation while decouple `nimbus` from staking, i
 
 actually we've prepared another branch with nimbus integration and we may try it later if required
 
-<https://github.com/bifrost-finance/bifrost/tree/collator-staking>
+<https://github.com/bifrost-io/bifrost/tree/collator-staking>
 
 ## api docs
 
diff --git a/pallets/system-staking/Cargo.toml b/pallets/system-staking/Cargo.toml
index f89f6a445..d6ed5d30a 100644
--- a/pallets/system-staking/Cargo.toml
+++ b/pallets/system-staking/Cargo.toml
@@ -3,10 +3,10 @@ name = "bifrost-system-staking"
 version = "4.0.0-dev"
 description = "System staking pallet"
 authors = ["Akagi201 <akagi201@gmail.com>"]
-homepage = "https://github.com/bifrost-finance/bifrost"
+homepage = "https://github.com/bifrost-io/bifrost"
 edition = "2021"
 publish = false
-repository = "https://github.com/bifrost-finance/bifrost"
+repository = "https://github.com/bifrost-io/bifrost"
 readme = 'README.md'
 
 [package.metadata.docs.rs]
diff --git a/scripts/bifrost-ecosystem.config.js b/scripts/bifrost-ecosystem.config.js
index 61d39cb87..da9bfd2fd 100644
--- a/scripts/bifrost-ecosystem.config.js
+++ b/scripts/bifrost-ecosystem.config.js
@@ -13,7 +13,7 @@ module.exports = {
       "host" : ["192.168.0.13", "192.168.0.14", "192.168.0.15"],
       "key": "~/.ssh/deploy_rsa.pub",
       "ref"  : "origin/develop",
-      "repo" : "git@github.com/bifrost-finance/bifrost.git",
+      "repo" : "git@github.com/bifrost-io/bifrost.git",
       "path" : "/home/bifrost/app",
       "post-setup": "make build-bifrost-release",
       'post-deploy' : 'pm2 reload scripts/bifost-ecosystem.config.js --env production'

From 8fe2c9c38c76ddbed2c6492eee7ee5699112fa7f Mon Sep 17 00:00:00 2001
From: yooml <ymlll0508@gmail.com>
Date: Wed, 16 Oct 2024 23:16:10 +0800
Subject: [PATCH 28/31] =?UTF-8?q?fix:=20=F0=9F=90=9B=20pool=20ID=20for=20b?=
 =?UTF-8?q?bBNC=20(#1471)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 pallets/bb-bnc/src/lib.rs     |  2 +-
 pallets/buy-back/src/lib.rs   |  5 ++---
 pallets/buy-back/src/tests.rs | 36 +++++++++++++++++++++++++++++------
 3 files changed, 33 insertions(+), 10 deletions(-)

diff --git a/pallets/bb-bnc/src/lib.rs b/pallets/bb-bnc/src/lib.rs
index e88290f02..a027655d5 100644
--- a/pallets/bb-bnc/src/lib.rs
+++ b/pallets/bb-bnc/src/lib.rs
@@ -62,7 +62,7 @@ pub type CurrencyIdOf<T> = <<T as Config>::MultiCurrency as MultiCurrency<
 
 const BB_LOCK_ID: LockIdentifier = *b"bbbnclck";
 const MARKUP_LOCK_ID: LockIdentifier = *b"bbbncmkp";
-const BB_BNC_SYSTEM_POOL_ID: PoolId = u32::MAX;
+pub const BB_BNC_SYSTEM_POOL_ID: PoolId = u32::MAX;
 #[derive(Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo, Default)]
 pub struct BbConfig<Balance, BlockNumber> {
 	/// Minimum number of TokenType that users can lock
diff --git a/pallets/buy-back/src/lib.rs b/pallets/buy-back/src/lib.rs
index f6668d663..3c8445906 100644
--- a/pallets/buy-back/src/lib.rs
+++ b/pallets/buy-back/src/lib.rs
@@ -30,7 +30,7 @@ mod benchmarking;
 
 pub mod weights;
 
-use bb_bnc::BbBNCInterface;
+use bb_bnc::{BbBNCInterface, BB_BNC_SYSTEM_POOL_ID};
 use bifrost_primitives::{currency::BNC, CurrencyId, CurrencyIdRegister, TryConvertFrom};
 use cumulus_primitives_core::ParaId;
 use frame_support::{
@@ -414,9 +414,8 @@ pub mod pallet {
 				T::MultiCurrency::withdraw(BNC, &buyback_address, destruction_amount)?;
 			}
 			let bnc_balance = T::MultiCurrency::free_balance(BNC, &buyback_address);
-			let pool_id = 0;
 			T::BbBNC::notify_reward(
-				pool_id,
+				BB_BNC_SYSTEM_POOL_ID,
 				&Some(buyback_address.clone()),
 				vec![(BNC, bnc_balance)],
 			)
diff --git a/pallets/buy-back/src/tests.rs b/pallets/buy-back/src/tests.rs
index 864c9dfd9..462542f05 100644
--- a/pallets/buy-back/src/tests.rs
+++ b/pallets/buy-back/src/tests.rs
@@ -108,7 +108,11 @@ fn buy_back_with_burn_should_work() {
 		assert_eq!(Currencies::free_balance(BNC, &zenlink_pair_account_id), 2000);
 		assert_eq!(Currencies::free_balance(BNC, &buyback_account), 0);
 		assert_eq!(Currencies::free_balance(BNC, &incentive_account), 0);
-		BbBNC::set_incentive(0, Some(7 * 86400 / 12), Some(buyback_account.clone()));
+		BbBNC::set_incentive(
+			BB_BNC_SYSTEM_POOL_ID,
+			Some(7 * 86400 / 12),
+			Some(buyback_account.clone()),
+		);
 		assert_ok!(BuyBack::charge(RuntimeOrigin::signed(ALICE), VKSM, 1000));
 		let infos = Infos::<Runtime>::get(VKSM).unwrap();
 		assert_ok!(BuyBack::buy_back(&buyback_account, VKSM, &infos, 0));
@@ -146,7 +150,11 @@ fn buy_back_no_burn_should_work() {
 		assert_eq!(Currencies::free_balance(BNC, &zenlink_pair_account_id), 2000);
 		assert_eq!(Currencies::free_balance(BNC, &buyback_account), 0);
 		assert_eq!(Currencies::free_balance(BNC, &incentive_account), 0);
-		BbBNC::set_incentive(0, Some(7 * 86400 / 12), Some(buyback_account.clone()));
+		BbBNC::set_incentive(
+			BB_BNC_SYSTEM_POOL_ID,
+			Some(7 * 86400 / 12),
+			Some(buyback_account.clone()),
+		);
 		assert_ok!(BuyBack::charge(RuntimeOrigin::signed(ALICE), VKSM, 1000));
 		let infos = Infos::<Runtime>::get(VKSM).unwrap();
 		assert_ok!(BuyBack::buy_back(&buyback_account, VKSM, &infos, 0));
@@ -184,7 +192,11 @@ fn on_initialize_no_burn_should_work() {
 		assert_eq!(Currencies::free_balance(BNC, &zenlink_pair_account_id), 2000);
 		assert_eq!(Currencies::free_balance(BNC, &buyback_account), 0);
 		assert_eq!(Currencies::free_balance(BNC, &incentive_account), 0);
-		BbBNC::set_incentive(0, Some(7 * 86400 / 12), Some(buyback_account.clone()));
+		BbBNC::set_incentive(
+			BB_BNC_SYSTEM_POOL_ID,
+			Some(7 * 86400 / 12),
+			Some(buyback_account.clone()),
+		);
 		assert_ok!(BuyBack::charge(RuntimeOrigin::signed(ALICE), VKSM, 1000));
 		BuyBack::on_initialize(1);
 		BuyBack::on_initialize(2);
@@ -222,7 +234,11 @@ fn on_initialize_with_burn_should_work() {
 		assert_eq!(Currencies::free_balance(BNC, &zenlink_pair_account_id), 2000);
 		assert_eq!(Currencies::free_balance(BNC, &buyback_account), 0);
 		assert_eq!(Currencies::free_balance(BNC, &incentive_account), 0);
-		BbBNC::set_incentive(0, Some(7 * 86400 / 12), Some(buyback_account.clone()));
+		BbBNC::set_incentive(
+			BB_BNC_SYSTEM_POOL_ID,
+			Some(7 * 86400 / 12),
+			Some(buyback_account.clone()),
+		);
 		assert_ok!(BuyBack::charge(RuntimeOrigin::signed(ALICE), VKSM, 1000));
 		BuyBack::on_initialize(<frame_system::Pallet<Runtime>>::block_number() + 1);
 		System::set_block_number(System::block_number() + 1);
@@ -261,7 +277,11 @@ fn on_initialize_with_bias_should_work() {
 		assert_eq!(Currencies::free_balance(BNC, &zenlink_pair_account_id), 2000);
 		assert_eq!(Currencies::free_balance(BNC, &buyback_account), 0);
 		assert_eq!(Currencies::free_balance(BNC, &incentive_account), 0);
-		BbBNC::set_incentive(0, Some(7 * 86400 / 12), Some(buyback_account.clone()));
+		BbBNC::set_incentive(
+			BB_BNC_SYSTEM_POOL_ID,
+			Some(7 * 86400 / 12),
+			Some(buyback_account.clone()),
+		);
 		assert_ok!(BuyBack::charge(RuntimeOrigin::signed(ALICE), VKSM, 1000));
 		BuyBack::on_initialize(1);
 		let path = vec![
@@ -311,7 +331,11 @@ fn on_initialize_with_bias_should_not_work() {
 		assert_eq!(Currencies::free_balance(BNC, &zenlink_pair_account_id), 2000);
 		assert_eq!(Currencies::free_balance(BNC, &buyback_account), 0);
 		assert_eq!(Currencies::free_balance(BNC, &incentive_account), 0);
-		BbBNC::set_incentive(0, Some(7 * 86400 / 12), Some(buyback_account.clone()));
+		BbBNC::set_incentive(
+			BB_BNC_SYSTEM_POOL_ID,
+			Some(7 * 86400 / 12),
+			Some(buyback_account.clone()),
+		);
 		assert_ok!(BuyBack::charge(RuntimeOrigin::signed(ALICE), VKSM, 1000));
 		BuyBack::on_initialize(1);
 		let path = vec![

From a742f749924103cd7a207597d786d57e7c2a82f3 Mon Sep 17 00:00:00 2001
From: yooml <ymlll0508@gmail.com>
Date: Thu, 17 Oct 2024 10:12:36 +0800
Subject: [PATCH 29/31] =?UTF-8?q?test:=20=F0=9F=92=8D=20add=20boost=20test?=
 =?UTF-8?q?ing=20(#1470)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* test: 💍 add boost testing

* fix: 🐛 farming boost

* refactor: 💡 start_boost_round
---
 pallets/farming/src/boost.rs |   4 +-
 pallets/farming/src/lib.rs   |   5 ++
 pallets/farming/src/tests.rs | 167 +++++++++++++++++++++++++++++++++++
 3 files changed, 174 insertions(+), 2 deletions(-)

diff --git a/pallets/farming/src/boost.rs b/pallets/farming/src/boost.rs
index 50ada6193..4d85616ac 100644
--- a/pallets/farming/src/boost.rs
+++ b/pallets/farming/src/boost.rs
@@ -103,12 +103,12 @@ impl<T: Config> Pallet<T> {
 			ensure!(BoostWhitelist::<T>::iter_keys().count() != 0, Error::<T>::WhitelistEmpty);
 		}
 
-		Self::send_boost_rewards(&boost_pool_info)?;
 		let current_block_number: BlockNumberFor<T> = frame_system::Pallet::<T>::block_number();
 		boost_pool_info.start_round = current_block_number;
-		boost_pool_info.round_length = round_length;
 		boost_pool_info.end_round = current_block_number.saturating_add(round_length);
 		boost_pool_info.total_votes = Zero::zero();
+		boost_pool_info.round_length = round_length;
+		Self::send_boost_rewards(&boost_pool_info)?;
 		BoostPoolInfos::<T>::set(boost_pool_info);
 		let _ = BoostVotingPools::<T>::clear(u32::max_value(), None);
 		Self::deposit_event(Event::RoundStart { round_length });
diff --git a/pallets/farming/src/lib.rs b/pallets/farming/src/lib.rs
index 84fbac7f3..b31125d1f 100644
--- a/pallets/farming/src/lib.rs
+++ b/pallets/farming/src/lib.rs
@@ -1010,6 +1010,11 @@ pub mod pallet {
 			T::ControlOrigin::ensure_origin(origin)?;
 			whitelist.iter().for_each(|pid| {
 				BoostWhitelist::<T>::insert(pid, ());
+				BoostVotingPools::<T>::mutate_exists(pid, |maybe_total_votes| {
+					if maybe_total_votes.is_none() {
+						*maybe_total_votes = Some(Zero::zero());
+					}
+				})
 			});
 			Ok(())
 		}
diff --git a/pallets/farming/src/tests.rs b/pallets/farming/src/tests.rs
index 3afbc3987..f9eefcb4d 100644
--- a/pallets/farming/src/tests.rs
+++ b/pallets/farming/src/tests.rs
@@ -426,3 +426,170 @@ fn create_farming_pool() {
 		assert_eq!(Tokens::free_balance(KSM, &ALICE), 3800);
 	})
 }
+
+#[test]
+fn add_boost_pool_whitelist() {
+	ExtBuilder::default().one_hundred_for_alice_n_bob().build().execute_with(|| {
+		let mut whitelist = vec![0];
+		assert_ok!(Farming::add_boost_pool_whitelist(
+			RuntimeOrigin::signed(ALICE),
+			whitelist.clone()
+		));
+		assert_eq!(BoostWhitelist::<Runtime>::iter().count(), 1);
+		whitelist.push(1);
+		assert_ok!(Farming::add_boost_pool_whitelist(
+			RuntimeOrigin::signed(ALICE),
+			whitelist.clone()
+		));
+		assert_eq!(BoostWhitelist::<Runtime>::iter().count(), 2);
+		assert_err!(
+			Farming::add_boost_pool_whitelist(RuntimeOrigin::signed(BOB), whitelist.clone()),
+			DispatchError::BadOrigin
+		);
+	})
+}
+
+#[test]
+fn set_next_round_whitelist() {
+	ExtBuilder::default().one_hundred_for_alice_n_bob().build().execute_with(|| {
+		let mut whitelist = vec![0];
+		assert_ok!(Farming::set_next_round_whitelist(
+			RuntimeOrigin::signed(ALICE),
+			whitelist.clone()
+		));
+		assert_eq!(BoostNextRoundWhitelist::<Runtime>::iter().count(), 1);
+		whitelist.push(1);
+		assert_ok!(Farming::set_next_round_whitelist(
+			RuntimeOrigin::signed(ALICE),
+			whitelist.clone()
+		));
+		assert_eq!(BoostNextRoundWhitelist::<Runtime>::iter().count(), 2);
+		assert_err!(
+			Farming::set_next_round_whitelist(RuntimeOrigin::signed(BOB), whitelist.clone()),
+			DispatchError::BadOrigin
+		);
+	})
+}
+
+#[test]
+fn start_boost_round() {
+	ExtBuilder::default().one_hundred_for_alice_n_bob().build().execute_with(|| {
+		let vote_list = vec![(0u32, Percent::from_percent(100))];
+		let whitelist = vec![0];
+		assert_ok!(Farming::set_next_round_whitelist(
+			RuntimeOrigin::signed(ALICE),
+			whitelist.clone()
+		));
+		assert_ok!(Farming::add_boost_pool_whitelist(
+			RuntimeOrigin::signed(ALICE),
+			whitelist.clone()
+		));
+		assert_ok!(Farming::vote(RuntimeOrigin::signed(ALICE), vote_list.clone()));
+		assert_ok!(Farming::vote(RuntimeOrigin::signed(BOB), vote_list.clone()));
+		assert_ok!(Farming::vote(RuntimeOrigin::signed(CHARLIE), vote_list.clone()));
+		assert_ok!(Farming::start_boost_round(RuntimeOrigin::signed(ALICE), 100));
+		assert_eq!(BoostVotingPools::<Runtime>::iter().count(), 0);
+		assert_eq!(UserBoostInfos::<Runtime>::iter().count(), 3);
+		assert_eq!(BoostWhitelist::<Runtime>::iter().count(), 1);
+		assert_eq!(BoostNextRoundWhitelist::<Runtime>::iter().count(), 0);
+	})
+}
+
+#[test]
+fn vote() {
+	ExtBuilder::default().one_hundred_for_alice_n_bob().build().execute_with(|| {
+		env_logger::try_init().unwrap_or(());
+
+		BbBNC::set_incentive(0, Some(7 * 86400 / 12), Some(ALICE.clone()));
+
+		let (pid, _tokens) = init_gauge();
+		let vote_list = vec![(pid, Percent::from_percent(100))];
+		let whitelist = vec![pid];
+		assert_ok!(Farming::set_next_round_whitelist(
+			RuntimeOrigin::signed(ALICE),
+			whitelist.clone()
+		));
+		assert_ok!(Farming::add_boost_pool_whitelist(
+			RuntimeOrigin::signed(ALICE),
+			whitelist.clone()
+		));
+
+		let charge_rewards = vec![(KSM, 300_000)];
+		assert_ok!(Farming::charge_boost(RuntimeOrigin::signed(CHARLIE), charge_rewards));
+		assert_eq!(BoostVotingPools::<Runtime>::iter().count(), 1);
+		assert_ok!(Farming::start_boost_round(RuntimeOrigin::signed(ALICE), 100));
+		let boost_pool_info =
+			BoostPoolInfo { total_votes: 0, end_round: 100, start_round: 0, round_length: 100 };
+		assert_eq!(BoostPoolInfos::<Runtime>::get(), boost_pool_info);
+
+		assert_ok!(Farming::vote(RuntimeOrigin::signed(ALICE), vote_list.clone()));
+		assert_ok!(Farming::vote(RuntimeOrigin::signed(BOB), vote_list.clone()));
+		assert_ok!(Farming::vote(RuntimeOrigin::signed(CHARLIE), vote_list.clone()));
+		assert_eq!(BoostVotingPools::<Runtime>::iter().count(), 1);
+		assert_eq!(UserBoostInfos::<Runtime>::iter().count(), 3);
+
+		assert_eq!(UserBoostInfos::<Runtime>::get(ALICE).unwrap().vote_amount, 99716198400);
+		let boost_pool_info = BoostPoolInfo {
+			total_votes: 99716198400,
+			end_round: 100,
+			start_round: 0,
+			round_length: 100,
+		};
+		assert_eq!(BoostPoolInfos::<Runtime>::get(), boost_pool_info);
+		assert_ok!(BbBNC::create_lock_inner(
+			&CHARLIE,
+			100_000_000_000,
+			(365 * 86400 - 7 * 86400) / 12
+		));
+		assert_eq!(BoostPoolInfos::<Runtime>::get().total_votes, 99716198400);
+		// vote again to refresh the vote amount of CHARLIE
+		assert_ok!(Farming::vote(RuntimeOrigin::signed(CHARLIE), vote_list.clone()));
+		assert_eq!(BoostPoolInfos::<Runtime>::get().total_votes, 124645248000);
+
+		assert_eq!(BoostBasicRewards::<Runtime>::get(pid, KSM), Some(3000));
+		Farming::on_initialize(0);
+		Farming::on_initialize(1);
+		Farming::on_initialize(2);
+		assert_ok!(Farming::claim(RuntimeOrigin::signed(ALICE), pid));
+		assert_eq!(Tokens::free_balance(KSM, &ALICE), 10000);
+		System::set_block_number(System::block_number() + 100);
+		assert_ok!(Farming::claim(RuntimeOrigin::signed(ALICE), pid));
+		assert_eq!(Tokens::free_balance(KSM, &ALICE), 11519);
+
+		assert_ok!(Farming::end_boost_round(RuntimeOrigin::signed(ALICE)));
+		assert_eq!(BoostPoolInfos::<Runtime>::get().end_round, 0);
+	})
+}
+
+#[test]
+fn charge_boost() {
+	ExtBuilder::default().one_hundred_for_alice_n_bob().build().execute_with(|| {
+		let vote_list = vec![(0u32, Percent::from_percent(100))];
+		let whitelist = vec![0];
+		assert_ok!(Farming::set_next_round_whitelist(
+			RuntimeOrigin::signed(ALICE),
+			whitelist.clone()
+		));
+		assert_ok!(Farming::add_boost_pool_whitelist(
+			RuntimeOrigin::signed(ALICE),
+			whitelist.clone()
+		));
+		assert_ok!(Farming::vote(RuntimeOrigin::signed(ALICE), vote_list.clone()));
+		assert_ok!(Farming::vote(RuntimeOrigin::signed(BOB), vote_list.clone()));
+		assert_ok!(Farming::vote(RuntimeOrigin::signed(CHARLIE), vote_list.clone()));
+		assert_ok!(Farming::start_boost_round(RuntimeOrigin::signed(ALICE), 100));
+		assert_eq!(BoostVotingPools::<Runtime>::iter().count(), 0);
+		assert_eq!(UserBoostInfos::<Runtime>::iter().count(), 3);
+		assert_eq!(BoostWhitelist::<Runtime>::iter().count(), 1);
+		assert_eq!(BoostNextRoundWhitelist::<Runtime>::iter().count(), 0);
+		let charge_rewards = vec![(KSM, 300000)];
+		assert_ok!(Farming::charge_boost(RuntimeOrigin::signed(BOB), charge_rewards));
+		let boost_pool_info =
+			BoostPoolInfo { total_votes: 0, end_round: 100, start_round: 0, round_length: 100 };
+		assert_eq!(BoostPoolInfos::<Runtime>::get(), boost_pool_info);
+		assert_eq!(BoostVotingPools::<Runtime>::iter().count(), 0);
+		assert_eq!(UserBoostInfos::<Runtime>::iter().count(), 3);
+		assert_eq!(BoostWhitelist::<Runtime>::iter().count(), 1);
+		assert_eq!(BoostNextRoundWhitelist::<Runtime>::iter().count(), 0);
+	})
+}

From 2e5e1141c2f2c21c26c9df5f6e68f8478058dfbe Mon Sep 17 00:00:00 2001
From: SunTiebing <1045060705@qq.com>
Date: Tue, 22 Oct 2024 21:33:48 +0800
Subject: [PATCH 30/31] Ban vbnc transfer

---
 primitives/src/currency.rs        |   6 ++
 runtime/bifrost-kusama/src/lib.rs | 132 +++++++++++++++++++++++++++++-
 2 files changed, 137 insertions(+), 1 deletion(-)

diff --git a/primitives/src/currency.rs b/primitives/src/currency.rs
index e6d1e67f4..fc1b0ab2a 100644
--- a/primitives/src/currency.rs
+++ b/primitives/src/currency.rs
@@ -90,6 +90,12 @@ pub const LDOT: CurrencyId = CurrencyId::Lend(0);
 pub const LKSM: CurrencyId = CurrencyId::Lend(1);
 pub const LUSDT: CurrencyId = CurrencyId::Lend(2);
 pub const LVDOT: CurrencyId = CurrencyId::Lend(3);
+pub const BLP_BNC_VBNC: CurrencyId = CurrencyId::BLP(2);
+pub const LP_BNC_VBNC: CurrencyId = CurrencyId::LPToken(TokenSymbol::ASG, 0, TokenSymbol::BNC, 1);
+pub const KUSAMA_VBNC_ASSET_INDEX: AssetId =
+	AssetId { chain_id: 2001, asset_type: 2, asset_index: 257 };
+pub const KUSAMA_BNC_ASSET_INDEX: AssetId =
+	AssetId { chain_id: 2001, asset_type: 0, asset_index: 0 };
 
 macro_rules! create_currency_id {
 	($(#[$meta:meta])*
diff --git a/runtime/bifrost-kusama/src/lib.rs b/runtime/bifrost-kusama/src/lib.rs
index 69f7802df..f3beb3fee 100644
--- a/runtime/bifrost-kusama/src/lib.rs
+++ b/runtime/bifrost-kusama/src/lib.rs
@@ -26,6 +26,7 @@
 #[cfg(feature = "std")]
 include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
 
+use bifrost_primitives::{BLP_BNC_VBNC, KUSAMA_VBNC_ASSET_INDEX, LP_BNC_VBNC, VBNC};
 use bifrost_slp::{DerivativeAccountProvider, QueryResponseManager};
 use core::convert::TryInto;
 // A few exports that help ease life for downstream crates.
@@ -220,11 +221,140 @@ parameter_types! {
 	pub const StableAssetPalletId: PalletId = PalletId(*b"bf/stabl");
 }
 
+pub struct CallFilter;
+impl Contains<RuntimeCall> for CallFilter {
+	fn contains(call: &RuntimeCall) -> bool {
+		let is_core_call = matches!(
+			call,
+			RuntimeCall::System(_) | RuntimeCall::Timestamp(_) | RuntimeCall::ParachainSystem(_)
+		);
+		if is_core_call {
+			// always allow core call
+			return true;
+		}
+
+		// disable transfer
+		let is_transfer = matches!(call, RuntimeCall::Tokens(_) | RuntimeCall::Balances(_));
+		if is_transfer {
+			let is_disabled =
+				match call {
+					RuntimeCall::Tokens(orml_tokens::Call::transfer {
+						dest: _,
+						currency_id,
+						amount: _,
+					}) =>
+						VBNC == *currency_id ||
+							BLP_BNC_VBNC == *currency_id || LP_BNC_VBNC == *currency_id,
+					RuntimeCall::Tokens(orml_tokens::Call::transfer_all {
+						dest: _,
+						currency_id,
+						keep_alive: _,
+					}) =>
+						VBNC == *currency_id ||
+							BLP_BNC_VBNC == *currency_id || LP_BNC_VBNC == *currency_id,
+					RuntimeCall::Tokens(orml_tokens::Call::transfer_keep_alive {
+						dest: _,
+						currency_id,
+						amount: _,
+					}) =>
+						VBNC == *currency_id ||
+							BLP_BNC_VBNC == *currency_id || LP_BNC_VBNC == *currency_id,
+
+					RuntimeCall::StablePool(bifrost_stable_pool::Call::add_liquidity {
+						pool_id,
+						amounts: _,
+						min_mint_amount: _,
+					}) => *pool_id == 2,
+					RuntimeCall::StablePool(bifrost_stable_pool::Call::swap {
+						pool_id,
+						i: _,
+						j: _,
+						dx: _,
+						min_dy: _,
+					}) => *pool_id == 2,
+					RuntimeCall::StablePool(bifrost_stable_pool::Call::redeem_proportion {
+						pool_id,
+						amount: _,
+						min_redeem_amounts: _,
+					}) => *pool_id == 2,
+					RuntimeCall::StablePool(bifrost_stable_pool::Call::redeem_single {
+						pool_id,
+						amount: _,
+						i: _,
+						min_redeem_amount: _,
+						asset_length: _,
+					}) => *pool_id == 2,
+					RuntimeCall::StablePool(bifrost_stable_pool::Call::redeem_multi {
+						pool_id,
+						amounts: _,
+						max_redeem_amount: _,
+					}) => *pool_id == 2,
+
+					RuntimeCall::ZenlinkProtocol(zenlink_protocol::Call::transfer {
+						asset_id,
+						recipient: _,
+						amount: _,
+					}) => *asset_id == KUSAMA_VBNC_ASSET_INDEX,
+					RuntimeCall::ZenlinkProtocol(zenlink_protocol::Call::add_liquidity {
+						asset_0,
+						asset_1,
+						amount_0_desired: _,
+						amount_1_desired: _,
+						amount_0_min: _,
+						amount_1_min: _,
+						deadline: _,
+					}) => *asset_0 == KUSAMA_VBNC_ASSET_INDEX || *asset_1 == KUSAMA_VBNC_ASSET_INDEX,
+					RuntimeCall::ZenlinkProtocol(zenlink_protocol::Call::remove_liquidity {
+						asset_0,
+						asset_1,
+						liquidity: _,
+						amount_0_min: _,
+						amount_1_min: _,
+						recipient: _,
+						deadline: _,
+					}) => *asset_0 == KUSAMA_VBNC_ASSET_INDEX || *asset_1 == KUSAMA_VBNC_ASSET_INDEX,
+					RuntimeCall::ZenlinkProtocol(
+						zenlink_protocol::Call::swap_exact_assets_for_assets {
+							amount_in: _,
+							amount_out_min: _,
+							path,
+							recipient: _,
+							deadline: _,
+						},
+					) => path.contains(&KUSAMA_VBNC_ASSET_INDEX),
+					RuntimeCall::ZenlinkProtocol(
+						zenlink_protocol::Call::swap_assets_for_exact_assets {
+							amount_out: _,
+							amount_in_max: _,
+							path,
+							recipient: _,
+							deadline: _,
+						},
+					) => path.contains(&KUSAMA_VBNC_ASSET_INDEX),
+					RuntimeCall::ZenlinkProtocol(zenlink_protocol::Call::bootstrap_claim {
+						recipient: _,
+						asset_0,
+						asset_1,
+						deadline: _,
+					}) => *asset_0 == KUSAMA_VBNC_ASSET_INDEX || *asset_1 == KUSAMA_VBNC_ASSET_INDEX,
+
+					_ => false,
+				};
+
+			if is_disabled {
+				// no switched off call
+				return false;
+			}
+		}
+		true
+	}
+}
+
 impl frame_system::Config for Runtime {
 	type AccountData = pallet_balances::AccountData<Balance>;
 	/// The identifier used to distinguish between accounts.
 	type AccountId = AccountId;
-	type BaseCallFilter = InsideBoth<Everything, TxPause>;
+	type BaseCallFilter = InsideBoth<CallFilter, TxPause>;
 	/// Maximum number of block number to block hash mappings to keep (oldest pruned first).
 	type BlockHashCount = BlockHashCount;
 	type BlockLength = RuntimeBlockLength;

From 6f2cf00084275e66caa53c3c0963ecf9c79f3b92 Mon Sep 17 00:00:00 2001
From: SunTiebing <1045060705@qq.com>
Date: Wed, 30 Oct 2024 22:53:01 +0800
Subject: [PATCH 31/31] Add restriction conditions for
 zenlink_protocol::Call::transfer

---
 primitives/src/currency.rs        |   2 +
 runtime/bifrost-kusama/src/lib.rs | 206 +++++++++++++++---------------
 2 files changed, 107 insertions(+), 101 deletions(-)

diff --git a/primitives/src/currency.rs b/primitives/src/currency.rs
index fc1b0ab2a..6f8f76b42 100644
--- a/primitives/src/currency.rs
+++ b/primitives/src/currency.rs
@@ -94,6 +94,8 @@ pub const BLP_BNC_VBNC: CurrencyId = CurrencyId::BLP(2);
 pub const LP_BNC_VBNC: CurrencyId = CurrencyId::LPToken(TokenSymbol::ASG, 0, TokenSymbol::BNC, 1);
 pub const KUSAMA_VBNC_ASSET_INDEX: AssetId =
 	AssetId { chain_id: 2001, asset_type: 2, asset_index: 257 };
+pub const KUSAMA_VBNC_LP_ASSET_INDEX: AssetId =
+	AssetId { chain_id: 2001, asset_type: 2, asset_index: 1103806596608 };
 pub const KUSAMA_BNC_ASSET_INDEX: AssetId =
 	AssetId { chain_id: 2001, asset_type: 0, asset_index: 0 };
 
diff --git a/runtime/bifrost-kusama/src/lib.rs b/runtime/bifrost-kusama/src/lib.rs
index 824108b56..e0ecd6cb5 100644
--- a/runtime/bifrost-kusama/src/lib.rs
+++ b/runtime/bifrost-kusama/src/lib.rs
@@ -26,7 +26,9 @@
 #[cfg(feature = "std")]
 include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
 
-use bifrost_primitives::{BLP_BNC_VBNC, KUSAMA_VBNC_ASSET_INDEX, LP_BNC_VBNC, VBNC};
+use bifrost_primitives::{
+	BLP_BNC_VBNC, KUSAMA_VBNC_ASSET_INDEX, KUSAMA_VBNC_LP_ASSET_INDEX, LP_BNC_VBNC, VBNC,
+};
 use bifrost_slp::{DerivativeAccountProvider, QueryResponseManager};
 use core::convert::TryInto;
 // A few exports that help ease life for downstream crates.
@@ -236,110 +238,112 @@ impl Contains<RuntimeCall> for CallFilter {
 		// disable transfer
 		let is_transfer = matches!(call, RuntimeCall::Tokens(_) | RuntimeCall::Balances(_));
 		if is_transfer {
-			let is_disabled =
-				match call {
-					RuntimeCall::Tokens(orml_tokens::Call::transfer {
-						dest: _,
-						currency_id,
-						amount: _,
-					}) =>
-						VBNC == *currency_id ||
-							BLP_BNC_VBNC == *currency_id || LP_BNC_VBNC == *currency_id,
-					RuntimeCall::Tokens(orml_tokens::Call::transfer_all {
-						dest: _,
-						currency_id,
-						keep_alive: _,
-					}) =>
-						VBNC == *currency_id ||
-							BLP_BNC_VBNC == *currency_id || LP_BNC_VBNC == *currency_id,
-					RuntimeCall::Tokens(orml_tokens::Call::transfer_keep_alive {
-						dest: _,
-						currency_id,
-						amount: _,
-					}) =>
-						VBNC == *currency_id ||
-							BLP_BNC_VBNC == *currency_id || LP_BNC_VBNC == *currency_id,
-
-					RuntimeCall::StablePool(bifrost_stable_pool::Call::add_liquidity {
-						pool_id,
-						amounts: _,
-						min_mint_amount: _,
-					}) => *pool_id == 2,
-					RuntimeCall::StablePool(bifrost_stable_pool::Call::swap {
-						pool_id,
-						i: _,
-						j: _,
-						dx: _,
-						min_dy: _,
-					}) => *pool_id == 2,
-					RuntimeCall::StablePool(bifrost_stable_pool::Call::redeem_proportion {
-						pool_id,
-						amount: _,
-						min_redeem_amounts: _,
-					}) => *pool_id == 2,
-					RuntimeCall::StablePool(bifrost_stable_pool::Call::redeem_single {
-						pool_id,
-						amount: _,
-						i: _,
-						min_redeem_amount: _,
-						asset_length: _,
-					}) => *pool_id == 2,
-					RuntimeCall::StablePool(bifrost_stable_pool::Call::redeem_multi {
-						pool_id,
-						amounts: _,
-						max_redeem_amount: _,
-					}) => *pool_id == 2,
-
-					RuntimeCall::ZenlinkProtocol(zenlink_protocol::Call::transfer {
-						asset_id,
+			let is_disabled = match call {
+				RuntimeCall::Tokens(orml_tokens::Call::transfer {
+					dest: _,
+					currency_id,
+					amount: _,
+				}) =>
+					VBNC == *currency_id ||
+						BLP_BNC_VBNC == *currency_id ||
+						LP_BNC_VBNC == *currency_id,
+				RuntimeCall::Tokens(orml_tokens::Call::transfer_all {
+					dest: _,
+					currency_id,
+					keep_alive: _,
+				}) =>
+					VBNC == *currency_id ||
+						BLP_BNC_VBNC == *currency_id ||
+						LP_BNC_VBNC == *currency_id,
+				RuntimeCall::Tokens(orml_tokens::Call::transfer_keep_alive {
+					dest: _,
+					currency_id,
+					amount: _,
+				}) =>
+					VBNC == *currency_id ||
+						BLP_BNC_VBNC == *currency_id ||
+						LP_BNC_VBNC == *currency_id,
+
+				RuntimeCall::StablePool(bifrost_stable_pool::Call::add_liquidity {
+					pool_id,
+					amounts: _,
+					min_mint_amount: _,
+				}) => *pool_id == 2,
+				RuntimeCall::StablePool(bifrost_stable_pool::Call::swap {
+					pool_id,
+					i: _,
+					j: _,
+					dx: _,
+					min_dy: _,
+				}) => *pool_id == 2,
+				RuntimeCall::StablePool(bifrost_stable_pool::Call::redeem_proportion {
+					pool_id,
+					amount: _,
+					min_redeem_amounts: _,
+				}) => *pool_id == 2,
+				RuntimeCall::StablePool(bifrost_stable_pool::Call::redeem_single {
+					pool_id,
+					amount: _,
+					i: _,
+					min_redeem_amount: _,
+					asset_length: _,
+				}) => *pool_id == 2,
+				RuntimeCall::StablePool(bifrost_stable_pool::Call::redeem_multi {
+					pool_id,
+					amounts: _,
+					max_redeem_amount: _,
+				}) => *pool_id == 2,
+
+				RuntimeCall::ZenlinkProtocol(zenlink_protocol::Call::transfer {
+					asset_id,
+					recipient: _,
+					amount: _,
+				}) => *asset_id == KUSAMA_VBNC_ASSET_INDEX || *asset_id == KUSAMA_VBNC_LP_ASSET_INDEX,
+				RuntimeCall::ZenlinkProtocol(zenlink_protocol::Call::add_liquidity {
+					asset_0,
+					asset_1,
+					amount_0_desired: _,
+					amount_1_desired: _,
+					amount_0_min: _,
+					amount_1_min: _,
+					deadline: _,
+				}) => *asset_0 == KUSAMA_VBNC_ASSET_INDEX || *asset_1 == KUSAMA_VBNC_ASSET_INDEX,
+				RuntimeCall::ZenlinkProtocol(zenlink_protocol::Call::remove_liquidity {
+					asset_0,
+					asset_1,
+					liquidity: _,
+					amount_0_min: _,
+					amount_1_min: _,
+					recipient: _,
+					deadline: _,
+				}) => *asset_0 == KUSAMA_VBNC_ASSET_INDEX || *asset_1 == KUSAMA_VBNC_ASSET_INDEX,
+				RuntimeCall::ZenlinkProtocol(
+					zenlink_protocol::Call::swap_exact_assets_for_assets {
+						amount_in: _,
+						amount_out_min: _,
+						path,
 						recipient: _,
-						amount: _,
-					}) => *asset_id == KUSAMA_VBNC_ASSET_INDEX,
-					RuntimeCall::ZenlinkProtocol(zenlink_protocol::Call::add_liquidity {
-						asset_0,
-						asset_1,
-						amount_0_desired: _,
-						amount_1_desired: _,
-						amount_0_min: _,
-						amount_1_min: _,
 						deadline: _,
-					}) => *asset_0 == KUSAMA_VBNC_ASSET_INDEX || *asset_1 == KUSAMA_VBNC_ASSET_INDEX,
-					RuntimeCall::ZenlinkProtocol(zenlink_protocol::Call::remove_liquidity {
-						asset_0,
-						asset_1,
-						liquidity: _,
-						amount_0_min: _,
-						amount_1_min: _,
+					},
+				) => path.contains(&KUSAMA_VBNC_ASSET_INDEX),
+				RuntimeCall::ZenlinkProtocol(
+					zenlink_protocol::Call::swap_assets_for_exact_assets {
+						amount_out: _,
+						amount_in_max: _,
+						path,
 						recipient: _,
 						deadline: _,
-					}) => *asset_0 == KUSAMA_VBNC_ASSET_INDEX || *asset_1 == KUSAMA_VBNC_ASSET_INDEX,
-					RuntimeCall::ZenlinkProtocol(
-						zenlink_protocol::Call::swap_exact_assets_for_assets {
-							amount_in: _,
-							amount_out_min: _,
-							path,
-							recipient: _,
-							deadline: _,
-						},
-					) => path.contains(&KUSAMA_VBNC_ASSET_INDEX),
-					RuntimeCall::ZenlinkProtocol(
-						zenlink_protocol::Call::swap_assets_for_exact_assets {
-							amount_out: _,
-							amount_in_max: _,
-							path,
-							recipient: _,
-							deadline: _,
-						},
-					) => path.contains(&KUSAMA_VBNC_ASSET_INDEX),
-					RuntimeCall::ZenlinkProtocol(zenlink_protocol::Call::bootstrap_claim {
-						recipient: _,
-						asset_0,
-						asset_1,
-						deadline: _,
-					}) => *asset_0 == KUSAMA_VBNC_ASSET_INDEX || *asset_1 == KUSAMA_VBNC_ASSET_INDEX,
-
-					_ => false,
-				};
+					},
+				) => path.contains(&KUSAMA_VBNC_ASSET_INDEX),
+				RuntimeCall::ZenlinkProtocol(zenlink_protocol::Call::bootstrap_claim {
+					recipient: _,
+					asset_0,
+					asset_1,
+					deadline: _,
+				}) => *asset_0 == KUSAMA_VBNC_ASSET_INDEX || *asset_1 == KUSAMA_VBNC_ASSET_INDEX,
+
+				_ => false,
+			};
 
 			if is_disabled {
 				// no switched off call