From be14f62124201ff0e18c9d3c06e50ca309b0bbc6 Mon Sep 17 00:00:00 2001 From: yooml Date: Fri, 14 Jul 2023 10:45:19 +0800 Subject: [PATCH 1/2] =?UTF-8?q?fix:=20=F0=9F=90=9B=20rebond=20(#999)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pallets/vtoken-minting/src/lib.rs | 136 ++++++++++++++++-------------- 1 file changed, 72 insertions(+), 64 deletions(-) diff --git a/pallets/vtoken-minting/src/lib.rs b/pallets/vtoken-minting/src/lib.rs index fc4286433..fac7a8124 100644 --- a/pallets/vtoken-minting/src/lib.rs +++ b/pallets/vtoken-minting/src/lib.rs @@ -385,87 +385,95 @@ pub mod pallet { ledger_list = BoundedVec::::try_from(ledger_list_rev) .map_err(|_| Error::::ExceedMaximumUnlockId)?; - ledger_list.retain(|index| { - if let Some((_, unlock_amount, time_unit, _)) = - Self::token_unlock_ledger(token_id, index) - { - if tmp_amount >= unlock_amount { - if let Some((_, _, time_unit, _)) = - TokenUnlockLedger::::take(&token_id, &index) - { + let mut tmp = ledger_list + .iter() + .map(|&index| -> Result<(UnlockId, bool), Error> { + if let Some((_, unlock_amount, time_unit, _)) = + Self::token_unlock_ledger(token_id, index) + { + if tmp_amount >= unlock_amount { + if let Some((_, _, time_unit, _)) = + TokenUnlockLedger::::take(&token_id, &index) + { + TimeUnitUnlockLedger::::mutate_exists( + &time_unit, + &token_id, + |value| -> Result<(), Error> { + 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::::CalculationOverflow)?; + ledger_list_origin.retain(|&x| x != index); + } else { + return Err( + Error::::TimeUnitUnlockLedgerNotFound, + ); + } + Ok(()) + }, + )?; + tmp_amount = tmp_amount.saturating_sub(unlock_amount); + } else { + return Err(Error::::TokenUnlockLedgerNotFound.into()); + } + Ok((index, false)) + } else { + TokenUnlockLedger::::mutate_exists( + &token_id, + &index, + |value| -> Result<(), Error> { + 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::::CalculationOverflow)?; + } else { + return Err(Error::::TokenUnlockLedgerNotFound); + } + Ok(()) + }, + )?; TimeUnitUnlockLedger::::mutate_exists( &time_unit, &token_id, |value| -> Result<(), Error> { - if let Some((total_locked_origin, ledger_list_origin, _)) = - value - { - if total_locked_origin == &unlock_amount { + 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(&unlock_amount) + .checked_sub(&tmp_amount) .ok_or(Error::::CalculationOverflow)?; - ledger_list_origin.retain(|x| x != index); } else { return Err(Error::::TimeUnitUnlockLedgerNotFound); } Ok(()) }, - ) - .ok(); - tmp_amount = tmp_amount.saturating_sub(unlock_amount); - // } else { - // return Err(Error::::TokenUnlockLedgerNotFound.into()); + )?; + Ok((index, true)) } - false } else { - TokenUnlockLedger::::mutate_exists( - &token_id, - &index, - |value| -> Result<(), Error> { - 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::::CalculationOverflow)?; - } else { - return Err(Error::::TokenUnlockLedgerNotFound); - } - Ok(()) - }, - ) - .ok(); - TimeUnitUnlockLedger::::mutate_exists( - &time_unit, - &token_id, - |value| -> Result<(), Error> { - 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::::CalculationOverflow)?; - } else { - return Err(Error::::TimeUnitUnlockLedgerNotFound); - } - Ok(()) - }, - ) - .ok(); - true + Ok((index, true)) } - } else { - true - } - }); - let ledger_list_tmp: Vec = ledger_list.into_iter().rev().collect(); + }) + .collect::, Error>>()?; + tmp.retain(|(_index, result)| *result); + + let ledger_list_tmp: Vec = + tmp.into_iter().map(|(index, _)| index).rev().collect(); ledger_list = BoundedVec::::try_from(ledger_list_tmp) From 46348b9463c94e54d77893e945e6feb181f93271 Mon Sep 17 00:00:00 2001 From: NingBo Wang <2536935847@qq.com> Date: Fri, 14 Jul 2023 15:26:16 +0800 Subject: [PATCH 2/2] Optimize code (#1001) * Reserve code * Optimize code --- Cargo.lock | 25 ++++------- integration-tests/bifrost-kusama/src/slp.rs | 1 - pallets/fee-share/src/mock.rs | 2 +- pallets/flexible-fee/src/mock.rs | 2 +- pallets/salp/src/mock.rs | 2 +- pallets/slp/src/mocks/mock.rs | 2 +- pallets/slp/src/mocks/mock_kusama.rs | 2 +- pallets/slpx/src/lib.rs | 14 +++--- pallets/slpx/src/mock.rs | 2 +- pallets/system-maker/src/mock.rs | 2 +- pallets/system-staking/src/mock.rs | 2 +- pallets/ve-minting/src/mock.rs | 2 +- pallets/vtoken-minting/src/mock.rs | 2 +- runtime/bifrost-kusama/src/xcm_config.rs | 50 ++------------------- runtime/bifrost-polkadot/src/xcm_config.rs | 50 ++------------------- 15 files changed, 32 insertions(+), 128 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 02e52a5fd..32bc123da 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -170,15 +170,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "aho-corasick" -version = "0.7.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" -dependencies = [ - "memchr", -] - [[package]] name = "aho-corasick" version = "1.0.2" @@ -4351,11 +4342,11 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "globset" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc" +checksum = "1391ab1f92ffcc08911957149833e682aa3fe252b9f45f966d2ef972274c97df" dependencies = [ - "aho-corasick 0.7.20", + "aho-corasick", "bstr 1.6.0", "fnv", "log", @@ -10075,9 +10066,9 @@ version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575" dependencies = [ - "aho-corasick 1.0.2", + "aho-corasick", "memchr", - "regex-automata 0.3.2", + "regex-automata 0.3.3", "regex-syntax 0.7.4", ] @@ -10092,11 +10083,11 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83d3daa6976cffb758ec878f108ba0e062a45b2d6ca3a2cca965338855476caf" +checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310" dependencies = [ - "aho-corasick 1.0.2", + "aho-corasick", "memchr", "regex-syntax 0.7.4", ] diff --git a/integration-tests/bifrost-kusama/src/slp.rs b/integration-tests/bifrost-kusama/src/slp.rs index b3326b6ad..9b8436222 100644 --- a/integration-tests/bifrost-kusama/src/slp.rs +++ b/integration-tests/bifrost-kusama/src/slp.rs @@ -423,7 +423,6 @@ fn vtoken_minting() { ), 99900000000000 ); - // TODO : entrance_account should have 100 KSM assert_eq!( Currencies::free_balance( CurrencyId::Token(TokenSymbol::KSM), diff --git a/pallets/fee-share/src/mock.rs b/pallets/fee-share/src/mock.rs index bb2294b53..7be884557 100644 --- a/pallets/fee-share/src/mock.rs +++ b/pallets/fee-share/src/mock.rs @@ -512,7 +512,7 @@ impl pallet_xcm::Config for Runtime { type TrustedLockers = (); type SovereignAccountOf = (); type MaxLockers = ConstU32<8>; - type WeightInfo = pallet_xcm::TestWeightInfo; // TODO: config after polkadot impl WeightInfo for () + type WeightInfo = pallet_xcm::TestWeightInfo; #[cfg(feature = "runtime-benchmarks")] type ReachableDest = ReachableDest; type AdminOrigin = EnsureRoot; diff --git a/pallets/flexible-fee/src/mock.rs b/pallets/flexible-fee/src/mock.rs index e28082a3a..958d308d2 100644 --- a/pallets/flexible-fee/src/mock.rs +++ b/pallets/flexible-fee/src/mock.rs @@ -532,7 +532,7 @@ impl pallet_xcm::Config for Test { type TrustedLockers = (); type SovereignAccountOf = (); type MaxLockers = ConstU32<8>; - type WeightInfo = pallet_xcm::TestWeightInfo; // TODO: config after polkadot impl WeightInfo for () + type WeightInfo = pallet_xcm::TestWeightInfo; #[cfg(feature = "runtime-benchmarks")] type ReachableDest = ReachableDest; type AdminOrigin = EnsureRoot; diff --git a/pallets/salp/src/mock.rs b/pallets/salp/src/mock.rs index 84bb42730..2a9b9fb97 100644 --- a/pallets/salp/src/mock.rs +++ b/pallets/salp/src/mock.rs @@ -425,7 +425,7 @@ impl pallet_xcm::Config for Test { type TrustedLockers = (); type SovereignAccountOf = (); type MaxLockers = ConstU32<8>; - type WeightInfo = pallet_xcm::TestWeightInfo; // TODO: config after polkadot impl WeightInfo for () + type WeightInfo = pallet_xcm::TestWeightInfo; #[cfg(feature = "runtime-benchmarks")] type ReachableDest = ReachableDest; type AdminOrigin = EnsureRoot; diff --git a/pallets/slp/src/mocks/mock.rs b/pallets/slp/src/mocks/mock.rs index 220636e5f..a323528f8 100644 --- a/pallets/slp/src/mocks/mock.rs +++ b/pallets/slp/src/mocks/mock.rs @@ -530,7 +530,7 @@ impl pallet_xcm::Config for Runtime { type TrustedLockers = (); type SovereignAccountOf = (); type MaxLockers = ConstU32<8>; - type WeightInfo = pallet_xcm::TestWeightInfo; // TODO: config after polkadot impl WeightInfo for () + type WeightInfo = pallet_xcm::TestWeightInfo; #[cfg(feature = "runtime-benchmarks")] type ReachableDest = ReachableDest; type AdminOrigin = EnsureRoot; diff --git a/pallets/slp/src/mocks/mock_kusama.rs b/pallets/slp/src/mocks/mock_kusama.rs index 9f806806e..bbc62d355 100644 --- a/pallets/slp/src/mocks/mock_kusama.rs +++ b/pallets/slp/src/mocks/mock_kusama.rs @@ -545,7 +545,7 @@ impl pallet_xcm::Config for Runtime { type TrustedLockers = (); type SovereignAccountOf = (); type MaxLockers = ConstU32<8>; - type WeightInfo = pallet_xcm::TestWeightInfo; // TODO: config after polkadot impl WeightInfo for () + type WeightInfo = pallet_xcm::TestWeightInfo; #[cfg(feature = "runtime-benchmarks")] type ReachableDest = ReachableDest; type AdminOrigin = EnsureRoot; diff --git a/pallets/slpx/src/lib.rs b/pallets/slpx/src/lib.rs index 47b4dd2d1..9f3a7bee3 100644 --- a/pallets/slpx/src/lib.rs +++ b/pallets/slpx/src/lib.rs @@ -36,7 +36,10 @@ use orml_traits::{MultiCurrency, XcmTransfer}; pub use pallet::*; use scale_info::TypeInfo; use sp_core::{Hasher, H160}; -use sp_runtime::{traits::BlakeTwo256, DispatchError, Saturating}; +use sp_runtime::{ + traits::{BlakeTwo256, CheckedSub}, + DispatchError, Saturating, +}; use sp_std::vec; use xcm::{latest::prelude::*, v3::MultiLocation}; use zenlink_protocol::AssetBalance; @@ -555,17 +558,16 @@ impl Pallet { let execution_fee = Self::execution_fee(currency_id).unwrap_or_else(|| Self::get_default_fee(currency_id)); let minimum_balance = T::MultiCurrency::minimum_balance(currency_id); - ensure!( - free_balance > execution_fee.saturating_add(minimum_balance), - Error::::FreeBalanceTooLow - ); T::MultiCurrency::transfer( currency_id, evm_caller_account_id, &T::TreasuryAccount::get(), execution_fee, )?; - Ok(free_balance - execution_fee.saturating_add(minimum_balance)) + let balance_exclude_fee = free_balance + .checked_sub(&execution_fee.saturating_add(minimum_balance)) + .ok_or(Error::::FreeBalanceTooLow)?; + Ok(balance_exclude_fee) } fn match_support_chain( diff --git a/pallets/slpx/src/mock.rs b/pallets/slpx/src/mock.rs index 775c19afe..1c7717aec 100644 --- a/pallets/slpx/src/mock.rs +++ b/pallets/slpx/src/mock.rs @@ -502,7 +502,7 @@ impl pallet_xcm::Config for Test { type TrustedLockers = (); type SovereignAccountOf = (); type MaxLockers = ConstU32<8>; - type WeightInfo = pallet_xcm::TestWeightInfo; // TODO: config after polkadot impl WeightInfo for () + type WeightInfo = pallet_xcm::TestWeightInfo; #[cfg(feature = "runtime-benchmarks")] type ReachableDest = ReachableDest; type AdminOrigin = EnsureRoot; diff --git a/pallets/system-maker/src/mock.rs b/pallets/system-maker/src/mock.rs index 497104aaf..5d6f2504a 100644 --- a/pallets/system-maker/src/mock.rs +++ b/pallets/system-maker/src/mock.rs @@ -519,7 +519,7 @@ impl pallet_xcm::Config for Runtime { type TrustedLockers = (); type SovereignAccountOf = (); type MaxLockers = ConstU32<8>; - type WeightInfo = pallet_xcm::TestWeightInfo; // TODO: config after polkadot impl WeightInfo for () + type WeightInfo = pallet_xcm::TestWeightInfo; #[cfg(feature = "runtime-benchmarks")] type ReachableDest = ReachableDest; type AdminOrigin = EnsureRoot; diff --git a/pallets/system-staking/src/mock.rs b/pallets/system-staking/src/mock.rs index 29747a1a7..432f206ae 100644 --- a/pallets/system-staking/src/mock.rs +++ b/pallets/system-staking/src/mock.rs @@ -448,7 +448,7 @@ impl pallet_xcm::Config for Runtime { type TrustedLockers = (); type SovereignAccountOf = (); type MaxLockers = ConstU32<8>; - type WeightInfo = pallet_xcm::TestWeightInfo; // TODO: config after polkadot impl WeightInfo for () + type WeightInfo = pallet_xcm::TestWeightInfo; #[cfg(feature = "runtime-benchmarks")] type ReachableDest = ReachableDest; type AdminOrigin = EnsureRoot; diff --git a/pallets/ve-minting/src/mock.rs b/pallets/ve-minting/src/mock.rs index 34f4c32ad..5eebf142c 100644 --- a/pallets/ve-minting/src/mock.rs +++ b/pallets/ve-minting/src/mock.rs @@ -447,7 +447,7 @@ impl pallet_xcm::Config for Runtime { type TrustedLockers = (); type SovereignAccountOf = (); type MaxLockers = ConstU32<8>; - type WeightInfo = pallet_xcm::TestWeightInfo; // TODO: config after polkadot impl WeightInfo for () + type WeightInfo = pallet_xcm::TestWeightInfo; #[cfg(feature = "runtime-benchmarks")] type ReachableDest = ReachableDest; type AdminOrigin = EnsureRoot; diff --git a/pallets/vtoken-minting/src/mock.rs b/pallets/vtoken-minting/src/mock.rs index c60098f94..cd0373c03 100644 --- a/pallets/vtoken-minting/src/mock.rs +++ b/pallets/vtoken-minting/src/mock.rs @@ -423,7 +423,7 @@ impl pallet_xcm::Config for Runtime { type TrustedLockers = (); type SovereignAccountOf = (); type MaxLockers = ConstU32<8>; - type WeightInfo = pallet_xcm::TestWeightInfo; // TODO: config after polkadot impl WeightInfo for () + type WeightInfo = pallet_xcm::TestWeightInfo; #[cfg(feature = "runtime-benchmarks")] type ReachableDest = ReachableDest; type AdminOrigin = EnsureRoot; diff --git a/runtime/bifrost-kusama/src/xcm_config.rs b/runtime/bifrost-kusama/src/xcm_config.rs index c877b6b45..e5ef94d17 100644 --- a/runtime/bifrost-kusama/src/xcm_config.rs +++ b/runtime/bifrost-kusama/src/xcm_config.rs @@ -50,8 +50,8 @@ use orml_traits::{ pub use orml_traits::{location::AbsoluteReserveProvider, parameter_type_with_key, MultiCurrency}; use pallet_xcm::XcmPassthrough; use sp_core::bounded::BoundedVec; -use sp_io::hashing::blake2_256; use xcm::v3::prelude::*; +use xcm_builder::Account32Hash; /// Bifrost Asset Matcher pub struct BifrostAssetMatcher( @@ -242,50 +242,6 @@ parameter_types! { pub UniversalLocation: InteriorMultiLocation = X2(GlobalConsensus(RelayNetwork::get()), Parachain(ParachainInfo::parachain_id().into())); } -pub struct ExternalAccountConverter(PhantomData<(Network, AccountId)>); -impl, AccountId: From<[u8; 32]> + Into<[u8; 32]> + Clone> - xcm_executor::traits::Convert - for ExternalAccountConverter -{ - fn convert(location: MultiLocation) -> Result { - log::trace!( - target: "xcm::ExternalAccountConverter::convert", - "location: {:?}", - location.clone(), - ); - match location { - MultiLocation { parents: 1, interior: X2(Parachain(_id), AccountId32 { id, .. }) } => - log::trace!( - target: "xcm::ExternalAccountConverter::convert", - "AccountId32: {:?}", - id, - ), - MultiLocation { - parents: 1, - interior: X2(Parachain(_id), AccountKey20 { key, .. }), - } => log::trace!( - target: "xcm::ExternalAccountConverter::convert", - "AccountKey20: {:?}", - key, - ), - _ => return Err(location), - }; - let hash: [u8; 32] = ("multiloc", location).using_encoded(blake2_256); - let mut account_id = [0u8; 32]; - account_id.copy_from_slice(&hash[0..32]); - log::trace!( - target: "xcm::ExternalAccountConverter::convert", - "account_id: {:?}", - account_id, - ); - Ok(account_id.into()) - } - - fn reverse(who: AccountId) -> Result { - Err(who) - } -} - /// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used /// when determining ownership of accounts for asset transacting and when attempting to use XCM /// `Transact` in order to determine the dispatch RuntimeOrigin. @@ -296,7 +252,8 @@ pub type LocationToAccountId = ( SiblingParachainConvertsVia, // Straight up local `AccountId32` origins just alias directly to `AccountId`. AccountId32Aliases, - ExternalAccountConverter, + // Derives a private `Account32` by hashing `("multiloc", received multilocation)` + Account32Hash, ); /// This is the type we use to convert an (incoming) XCM origin into a local `RuntimeOrigin` @@ -668,7 +625,6 @@ impl Contains for SafeCallFilter { xcm_interface::Call::transfer_statemine_assets { .. } ) | RuntimeCall::Slpx(..) | - // TODO swap RuntimeCall::ZenlinkProtocol( zenlink_protocol::Call::add_liquidity { .. } | zenlink_protocol::Call::remove_liquidity { .. } | diff --git a/runtime/bifrost-polkadot/src/xcm_config.rs b/runtime/bifrost-polkadot/src/xcm_config.rs index 04c2b2443..f0c341f57 100644 --- a/runtime/bifrost-polkadot/src/xcm_config.rs +++ b/runtime/bifrost-polkadot/src/xcm_config.rs @@ -29,7 +29,6 @@ use node_primitives::{ AccountId, CurrencyId, CurrencyIdMapping, TokenSymbol, DOT_TOKEN_ID, GLMR_TOKEN_ID, }; pub use polkadot_parachain::primitives::Sibling; -use sp_io::hashing::blake2_256; use sp_std::{convert::TryFrom, marker::PhantomData}; pub use xcm_builder::{ AccountId32Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom, @@ -48,6 +47,7 @@ use orml_traits::location::Reserve; pub use orml_traits::{location::AbsoluteReserveProvider, parameter_type_with_key, MultiCurrency}; use pallet_xcm::XcmPassthrough; use sp_core::bounded::BoundedVec; +use xcm_builder::Account32Hash; /// Bifrost Asset Matcher pub struct BifrostAssetMatcher( @@ -196,50 +196,6 @@ parameter_types! { pub UniversalLocation: InteriorMultiLocation = X2(GlobalConsensus(RelayNetwork::get()), Parachain(ParachainInfo::parachain_id().into())); } -pub struct ExternalAccountConverter(PhantomData<(Network, AccountId)>); -impl, AccountId: From<[u8; 32]> + Into<[u8; 32]> + Clone> - xcm_executor::traits::Convert - for ExternalAccountConverter -{ - fn convert(location: MultiLocation) -> Result { - log::trace!( - target: "xcm::ExternalAccountConverter::convert", - "location: {:?}", - location.clone(), - ); - match location { - MultiLocation { parents: 1, interior: X2(Parachain(_id), AccountId32 { id, .. }) } => - log::trace!( - target: "xcm::ExternalAccountConverter::convert", - "AccountId32: {:?}", - id, - ), - MultiLocation { - parents: 1, - interior: X2(Parachain(_id), AccountKey20 { key, .. }), - } => log::trace!( - target: "xcm::ExternalAccountConverter::convert", - "AccountKey20: {:?}", - key, - ), - _ => return Err(location), - }; - let hash: [u8; 32] = ("multiloc", location).using_encoded(blake2_256); - let mut account_id = [0u8; 32]; - account_id.copy_from_slice(&hash[0..32]); - log::trace!( - target: "xcm::ExternalAccountConverter::convert", - "account_id: {:?}", - account_id, - ); - Ok(account_id.into()) - } - - fn reverse(who: AccountId) -> Result { - Err(who) - } -} - /// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used /// when determining ownership of accounts for asset transacting and when attempting to use XCM /// `Transact` in order to determine the dispatch RuntimeOrigin. @@ -250,7 +206,8 @@ pub type LocationToAccountId = ( SiblingParachainConvertsVia, // Straight up local `AccountId32` origins just alias directly to `AccountId`. AccountId32Aliases, - ExternalAccountConverter, + // Derives a private `Account32` by hashing `("multiloc", received multilocation)` + Account32Hash, ); /// This is the type we use to convert an (incoming) XCM origin into a local `RuntimeOrigin` @@ -528,7 +485,6 @@ impl Contains for SafeCallFilter { xcm_interface::Call::transfer_statemine_assets { .. } ) | RuntimeCall::Slpx(..) | - // TODO swap RuntimeCall::ZenlinkProtocol( zenlink_protocol::Call::add_liquidity { .. } | zenlink_protocol::Call::remove_liquidity { .. } |