From 2e31e7c3ce39d54e14f214aa7b1827e76057ebb0 Mon Sep 17 00:00:00 2001 From: MrPai <1164934857@qq.com> Date: Wed, 7 Dec 2022 16:05:35 +0800 Subject: [PATCH] Fix: xcm multilocation (#1911) * add paraid to CurrencyIdConvert * Revert "add paraid to CurrencyIdConvert" This reverts commit 9a44745517618cb2c41028ee08a79f7edb116cd7. * add wrapconvert * add to runtime * add log * rm * fix XcmFeesToAccount * Update xcm.rs * fix test --- integration-tests/src/polkadot_transfer.rs | 3 +- integration-tests/src/setup.rs | 51 +++++++++------- integration-tests/src/sibling_transfer.rs | 3 +- pallets/traits/src/xcm.rs | 71 ++++++++++++++++++++++ runtime/heiko/src/lib.rs | 20 +++--- runtime/kerria/src/lib.rs | 20 +++--- runtime/parallel/src/lib.rs | 20 +++--- runtime/vanilla/src/lib.rs | 20 +++--- 8 files changed, 145 insertions(+), 63 deletions(-) diff --git a/integration-tests/src/polkadot_transfer.rs b/integration-tests/src/polkadot_transfer.rs index befd03779..9d031e0ca 100644 --- a/integration-tests/src/polkadot_transfer.rs +++ b/integration-tests/src/polkadot_transfer.rs @@ -97,11 +97,10 @@ fn transfer_sibling_chain_asset() { .into() .into() ), - //just use para to mock clv here Box::new( ( X1(GeneralKey(WeakBoundedVec::>::force_from( - b"PARA".to_vec(), + b"CLV".to_vec(), None ))), para(10) diff --git a/integration-tests/src/setup.rs b/integration-tests/src/setup.rs index 3dc2d5964..9ad0fbf6f 100644 --- a/integration-tests/src/setup.rs +++ b/integration-tests/src/setup.rs @@ -296,9 +296,8 @@ impl ExtBuilder { 1, X2( Parachain(2000), - //since we use hko to mock kar,just use hko location here GeneralKey(WeakBoundedVec::>::force_from( - b"HKO".to_vec(), + b"KAR".to_vec(), None, )), ), @@ -465,9 +464,8 @@ impl ExtBuilder { 1, X2( Parachain(2002), - //since we use para to mock clv,just use para location here GeneralKey(WeakBoundedVec::>::force_from( - b"PARA".to_vec(), + b"CLV".to_vec(), None, )), ), @@ -579,19 +577,23 @@ impl ExtBuilder { let mut ext = sp_io::TestExternalities::new(self.init()); ext.execute_with(|| { System::set_block_number(1); - let hko_asset_location = MultiLocation::new( - 0, - X1(GeneralKey(WeakBoundedVec::>::force_from( - b"HKO".to_vec(), - None, - ))), + let kar_asset_location = MultiLocation::new( + 1, + X2( + Parachain(2000), + GeneralKey(WeakBoundedVec::>::force_from( + b"KAR".to_vec(), + None, + )), + ), ); - let hko_asset_type = AssetType::Xcm(hko_asset_location); - AssetRegistry::register_asset(RuntimeOrigin::root(), HKO, hko_asset_type.clone()) + let kar_asset_type = AssetType::Xcm(kar_asset_location); + // use HKO mock native balance + AssetRegistry::register_asset(RuntimeOrigin::root(), HKO, kar_asset_type.clone()) .unwrap(); AssetRegistry::update_asset_units_per_second( RuntimeOrigin::root(), - hko_asset_type, + kar_asset_type, HKO_WEIGHT_PER_SEC, ) .unwrap(); @@ -600,23 +602,26 @@ impl ExtBuilder { } pub fn clv_build(self) -> sp_io::TestExternalities { - use heiko_runtime::{AssetRegistry, RuntimeOrigin, System}; + use parallel_runtime::{AssetRegistry, RuntimeOrigin, System}; let mut ext = sp_io::TestExternalities::new(self.init()); ext.execute_with(|| { System::set_block_number(1); - let para_asset_location = MultiLocation::new( - 0, - X1(GeneralKey(WeakBoundedVec::>::force_from( - b"PARA".to_vec(), - None, - ))), + let clv_asset_location = MultiLocation::new( + 1, + X2( + Parachain(2002), + GeneralKey(WeakBoundedVec::>::force_from( + b"CLV".to_vec(), + None, + )), + ), ); - let para_asset_type = AssetType::Xcm(para_asset_location); - AssetRegistry::register_asset(RuntimeOrigin::root(), PARA, para_asset_type.clone()) + let clv_asset_type = AssetType::Xcm(clv_asset_location); + AssetRegistry::register_asset(RuntimeOrigin::root(), PARA, clv_asset_type.clone()) .unwrap(); AssetRegistry::update_asset_units_per_second( RuntimeOrigin::root(), - para_asset_type, + clv_asset_type, PARA_WEIGHT_PER_SEC, ) .unwrap(); diff --git a/integration-tests/src/sibling_transfer.rs b/integration-tests/src/sibling_transfer.rs index 7b7aaae6c..5c29342aa 100644 --- a/integration-tests/src/sibling_transfer.rs +++ b/integration-tests/src/sibling_transfer.rs @@ -81,11 +81,10 @@ fn transfer_sibling_chain_asset() { .into() .into() ), - //just use hko to mock kar here Box::new( ( X1(GeneralKey(WeakBoundedVec::>::force_from( - b"HKO".to_vec(), + b"KAR".to_vec(), None ))), heiko(10) diff --git a/pallets/traits/src/xcm.rs b/pallets/traits/src/xcm.rs index 93558d787..621f061aa 100644 --- a/pallets/traits/src/xcm.rs +++ b/pallets/traits/src/xcm.rs @@ -25,6 +25,7 @@ use frame_support::{ }, weights::constants::WEIGHT_PER_SECOND, }; +use primitives::ParaId; use scale_info::TypeInfo; use sp_core::H256; use sp_runtime::traits::{BlakeTwo256, Convert, Hash as THash, SaturatedConversion, Zero}; @@ -584,3 +585,73 @@ impl> } } } + +// Multilocation stores in Pallet AssetRegistry start with parent 1 +// And due to `assets.reanchored` in xcm-executor, +// So manually convert here, then query currency_id + +// Consider optimizing under this issue +// https://github.com/paritytech/polkadot/issues/4489 +pub struct XcmAssetRegistry( + PhantomData<(AssetId, AssetType, AssetIdInfoGetter, ParachainId)>, +); + +impl + XcmAssetRegistry +where + AssetType: From + Into> + Clone, + ParachainId: Get, +{ + fn convert(asset_type: AssetType) -> AssetType { + if let Some(location) = asset_type.clone().into() { + if location.parents != 0 { + return asset_type; + } + let mut new_location = location.clone(); + new_location.parents = 1; + new_location = new_location + .pushed_front_with_interior(Parachain(ParachainId::get().into())) + .unwrap_or_else(|_| location.clone()); + log::trace!( + target: "xcm::asset_registry_convert", + "old_location: {:?}, new_location: {:?}", + location, + new_location, + ); + return new_location.into(); + } + + asset_type + } +} + +impl AssetTypeGetter + for XcmAssetRegistry +where + AssetType: From + Into> + Clone, + AssetIdInfoGetter: AssetTypeGetter, + ParachainId: Get, +{ + fn get_asset_type(asset_id: AssetId) -> Option { + AssetIdInfoGetter::get_asset_type(asset_id) + } + + fn get_asset_id(asset_type: AssetType) -> Option { + AssetIdInfoGetter::get_asset_id(Self::convert(asset_type)) + } +} + +impl UnitsToWeightRatio + for XcmAssetRegistry +where + AssetType: From + Into> + Clone, + AssetIdInfoGetter: UnitsToWeightRatio, + ParachainId: Get, +{ + fn payment_is_supported(asset_type: AssetType) -> bool { + AssetIdInfoGetter::payment_is_supported(Self::convert(asset_type)) + } + fn get_units_per_second(asset_type: AssetType) -> Option { + AssetIdInfoGetter::get_units_per_second(Self::convert(asset_type)) + } +} diff --git a/runtime/heiko/src/lib.rs b/runtime/heiko/src/lib.rs index 872a7231a..d4e9410a4 100644 --- a/runtime/heiko/src/lib.rs +++ b/runtime/heiko/src/lib.rs @@ -99,7 +99,7 @@ pub use pallet_streaming; use pallet_traits::{ xcm::{ AccountIdToMultiLocation, AsAssetType, AssetType, CurrencyIdConvert, FirstAssetTrader, - MultiCurrencyAdapter, + MultiCurrencyAdapter, XcmAssetRegistry, }, DecimalProvider, EmergencyCallFilter, ValidationDataProvider, }; @@ -393,7 +393,7 @@ impl orml_xtokens::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Balance = Balance; type CurrencyId = CurrencyId; - type CurrencyIdConvert = CurrencyIdConvert; + type CurrencyIdConvert = CurrencyIdConvert; type AccountIdToMultiLocation = AccountIdToMultiLocation; type SelfLocation = SelfLocation; type XcmExecutor = XcmExecutor; @@ -992,13 +992,13 @@ pub type LocalAssetTransactor = MultiCurrencyAdapter< // Use this currency: CurrencyAdapter, // Use this currency when it is a fungible asset matching the given location or name: - IsNativeConcrete>, + IsNativeConcrete>, // Our chain's account ID type (we can't get away without mentioning it explicitly): AccountId, Balance, // Do a simple punn to convert an AccountId32 MultiLocation into a native chain account ID: LocationToAccountId, - CurrencyIdConvert, + CurrencyIdConvert, NativeCurrencyId, ExistentialDeposit, GiftAccount, @@ -1051,7 +1051,7 @@ impl TakeRevenue for ToTreasury { fun: Fungibility::Fungible(amount), } = revenue { - if let Some(currency_id) = CurrencyIdConvert::::convert(id) { + if let Some(currency_id) = CurrencyIdConvert::::convert(id) { let _ = Assets::mint_into(currency_id, &TreasuryAccount::get(), amount); } } @@ -1062,6 +1062,8 @@ parameter_types! { pub CheckingAccount: AccountId = PolkadotXcm::check_account(); } +pub type WrapAssetRegistry = XcmAssetRegistry; + /// The non-reserve fungible transactor type /// It will use pallet-assets, and the Id will be matched against AsAssetType pub type ForeignFungiblesTransactor = FungiblesAdapter< @@ -1072,7 +1074,7 @@ pub type ForeignFungiblesTransactor = FungiblesAdapter< ConvertedConcreteAssetId< CurrencyId, Balance, - AsAssetType, + AsAssetType, JustTry, >, ), @@ -1094,12 +1096,12 @@ pub type AssetTransactors = (LocalAssetTransactor, ForeignFungiblesTransactor); /// We do not burn anything because we want to mimic exactly what /// the sovereign account has pub type XcmFeesToAccount = pallet_traits::xcm::XcmFeesToAccount< - Assets, + CurrencyAdapter, ( ConvertedConcreteAssetId< CurrencyId, Balance, - AsAssetType, + AsAssetType, JustTry, >, ), @@ -1120,7 +1122,7 @@ impl Config for XcmConfig { type LocationInverter = LocationInverter; type Barrier = Barrier; type Weigher = FixedWeightBounds; - type Trader = FirstAssetTrader; + type Trader = FirstAssetTrader; type ResponseHandler = PolkadotXcm; type SubscriptionService = PolkadotXcm; type AssetTrap = PolkadotXcm; diff --git a/runtime/kerria/src/lib.rs b/runtime/kerria/src/lib.rs index 4c3c73e54..2b30e4a06 100644 --- a/runtime/kerria/src/lib.rs +++ b/runtime/kerria/src/lib.rs @@ -103,7 +103,7 @@ pub use pallet_streaming; use pallet_traits::{ xcm::{ AccountIdToMultiLocation, AsAssetType, AssetType, CurrencyIdConvert, FirstAssetTrader, - MultiCurrencyAdapter, + MultiCurrencyAdapter, XcmAssetRegistry, }, DecimalProvider, EmergencyCallFilter, ValidationDataProvider, }; @@ -422,7 +422,7 @@ impl orml_xtokens::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Balance = Balance; type CurrencyId = CurrencyId; - type CurrencyIdConvert = CurrencyIdConvert; + type CurrencyIdConvert = CurrencyIdConvert; type AccountIdToMultiLocation = AccountIdToMultiLocation; type SelfLocation = SelfLocation; type XcmExecutor = XcmExecutor; @@ -1161,13 +1161,13 @@ pub type LocalAssetTransactor = MultiCurrencyAdapter< // Use this currency: CurrencyAdapter, // Use this currency when it is a fungible asset matching the given location or name: - IsNativeConcrete>, + IsNativeConcrete>, // Our chain's account ID type (we can't get away without mentioning it explicitly): AccountId, Balance, // Do a simple punn to convert an AccountId32 MultiLocation into a native chain account ID: LocationToAccountId, - CurrencyIdConvert, + CurrencyIdConvert, NativeCurrencyId, ExistentialDeposit, GiftAccount, @@ -1220,7 +1220,7 @@ impl TakeRevenue for ToTreasury { fun: Fungibility::Fungible(amount), } = revenue { - if let Some(currency_id) = CurrencyIdConvert::::convert(id) { + if let Some(currency_id) = CurrencyIdConvert::::convert(id) { let _ = Assets::mint_into(currency_id, &TreasuryAccount::get(), amount); } } @@ -1243,6 +1243,8 @@ parameter_types! { pub CheckingAccount: AccountId = PolkadotXcm::check_account(); } +pub type WrapAssetRegistry = XcmAssetRegistry; + /// The non-reserve fungible transactor type /// It will use pallet-assets, and the Id will be matched against AsAssetType pub type ForeignFungiblesTransactor = FungiblesAdapter< @@ -1253,7 +1255,7 @@ pub type ForeignFungiblesTransactor = FungiblesAdapter< ConvertedConcreteAssetId< CurrencyId, Balance, - AsAssetType, + AsAssetType, JustTry, >, ), @@ -1275,12 +1277,12 @@ pub type AssetTransactors = (LocalAssetTransactor, ForeignFungiblesTransactor); /// We do not burn anything because we want to mimic exactly what /// the sovereign account has pub type XcmFeesToAccount = pallet_traits::xcm::XcmFeesToAccount< - Assets, + CurrencyAdapter, ( ConvertedConcreteAssetId< CurrencyId, Balance, - AsAssetType, + AsAssetType, JustTry, >, ), @@ -1301,7 +1303,7 @@ impl Config for XcmConfig { type LocationInverter = LocationInverter; type Barrier = Barrier; type Weigher = FixedWeightBounds; - type Trader = FirstAssetTrader; + type Trader = FirstAssetTrader; type ResponseHandler = PolkadotXcm; type SubscriptionService = PolkadotXcm; type AssetTrap = PolkadotXcm; diff --git a/runtime/parallel/src/lib.rs b/runtime/parallel/src/lib.rs index daa8816e8..21db4a81a 100644 --- a/runtime/parallel/src/lib.rs +++ b/runtime/parallel/src/lib.rs @@ -100,7 +100,7 @@ pub use pallet_streaming; use pallet_traits::{ xcm::{ AccountIdToMultiLocation, AsAssetType, AssetType, CurrencyIdConvert, FirstAssetTrader, - MultiCurrencyAdapter, + MultiCurrencyAdapter, XcmAssetRegistry, }, DecimalProvider, EmergencyCallFilter, ValidationDataProvider, }; @@ -397,7 +397,7 @@ impl orml_xtokens::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Balance = Balance; type CurrencyId = CurrencyId; - type CurrencyIdConvert = CurrencyIdConvert; + type CurrencyIdConvert = CurrencyIdConvert; type AccountIdToMultiLocation = AccountIdToMultiLocation; type SelfLocation = SelfLocation; type XcmExecutor = XcmExecutor; @@ -992,13 +992,13 @@ pub type LocalAssetTransactor = MultiCurrencyAdapter< // Use this currency: CurrencyAdapter, // Use this currency when it is a fungible asset matching the given location or name: - IsNativeConcrete>, + IsNativeConcrete>, // Our chain's account ID type (we can't get away without mentioning it explicitly): AccountId, Balance, // Do a simple punn to convert an AccountId32 MultiLocation into a native chain account ID: LocationToAccountId, - CurrencyIdConvert, + CurrencyIdConvert, NativeCurrencyId, ExistentialDeposit, GiftAccount, @@ -1051,7 +1051,7 @@ impl TakeRevenue for ToTreasury { fun: Fungibility::Fungible(amount), } = revenue { - if let Some(currency_id) = CurrencyIdConvert::::convert(id) { + if let Some(currency_id) = CurrencyIdConvert::::convert(id) { let _ = Assets::mint_into(currency_id, &TreasuryAccount::get(), amount); } } @@ -1062,6 +1062,8 @@ parameter_types! { pub CheckingAccount: AccountId = PolkadotXcm::check_account(); } +pub type WrapAssetRegistry = XcmAssetRegistry; + /// The non-reserve fungible transactor type /// It will use pallet-assets, and the Id will be matched against AsAssetType pub type ForeignFungiblesTransactor = FungiblesAdapter< @@ -1072,7 +1074,7 @@ pub type ForeignFungiblesTransactor = FungiblesAdapter< ConvertedConcreteAssetId< CurrencyId, Balance, - AsAssetType, + AsAssetType, JustTry, >, ), @@ -1094,12 +1096,12 @@ pub type AssetTransactors = (LocalAssetTransactor, ForeignFungiblesTransactor); /// We do not burn anything because we want to mimic exactly what /// the sovereign account has pub type XcmFeesToAccount = pallet_traits::xcm::XcmFeesToAccount< - Assets, + CurrencyAdapter, ( ConvertedConcreteAssetId< CurrencyId, Balance, - AsAssetType, + AsAssetType, JustTry, >, ), @@ -1120,7 +1122,7 @@ impl Config for XcmConfig { type LocationInverter = LocationInverter; type Barrier = Barrier; type Weigher = FixedWeightBounds; - type Trader = FirstAssetTrader; + type Trader = FirstAssetTrader; type ResponseHandler = PolkadotXcm; type SubscriptionService = PolkadotXcm; type AssetTrap = PolkadotXcm; diff --git a/runtime/vanilla/src/lib.rs b/runtime/vanilla/src/lib.rs index 2ae276b4e..f489c4882 100644 --- a/runtime/vanilla/src/lib.rs +++ b/runtime/vanilla/src/lib.rs @@ -103,7 +103,7 @@ use pallet_evm::{FeeCalculator, Runner}; use pallet_traits::{ xcm::{ AccountIdToMultiLocation, AsAssetType, AssetType, CurrencyIdConvert, FirstAssetTrader, - MultiCurrencyAdapter, + MultiCurrencyAdapter, XcmAssetRegistry, }, DecimalProvider, EmergencyCallFilter, ValidationDataProvider, }; @@ -422,7 +422,7 @@ impl orml_xtokens::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Balance = Balance; type CurrencyId = CurrencyId; - type CurrencyIdConvert = CurrencyIdConvert; + type CurrencyIdConvert = CurrencyIdConvert; type AccountIdToMultiLocation = AccountIdToMultiLocation; type SelfLocation = SelfLocation; type XcmExecutor = XcmExecutor; @@ -1169,13 +1169,13 @@ pub type LocalAssetTransactor = MultiCurrencyAdapter< // Use this currency: CurrencyAdapter, // Use this currency when it is a fungible asset matching the given location or name: - IsNativeConcrete>, + IsNativeConcrete>, // Our chain's account ID type (we can't get away without mentioning it explicitly): AccountId, Balance, // Do a simple punn to convert an AccountId32 MultiLocation into a native chain account ID: LocationToAccountId, - CurrencyIdConvert, + CurrencyIdConvert, NativeCurrencyId, ExistentialDeposit, GiftAccount, @@ -1228,7 +1228,7 @@ impl TakeRevenue for ToTreasury { fun: Fungibility::Fungible(amount), } = revenue { - if let Some(currency_id) = CurrencyIdConvert::::convert(id) { + if let Some(currency_id) = CurrencyIdConvert::::convert(id) { let _ = Assets::mint_into(currency_id, &TreasuryAccount::get(), amount); } } @@ -1251,6 +1251,8 @@ parameter_types! { pub CheckingAccount: AccountId = PolkadotXcm::check_account(); } +pub type WrapAssetRegistry = XcmAssetRegistry; + /// The non-reserve fungible transactor type /// It will use pallet-assets, and the Id will be matched against AsAssetType pub type ForeignFungiblesTransactor = FungiblesAdapter< @@ -1261,7 +1263,7 @@ pub type ForeignFungiblesTransactor = FungiblesAdapter< ConvertedConcreteAssetId< CurrencyId, Balance, - AsAssetType, + AsAssetType, JustTry, >, ), @@ -1283,12 +1285,12 @@ pub type AssetTransactors = (LocalAssetTransactor, ForeignFungiblesTransactor); /// We do not burn anything because we want to mimic exactly what /// the sovereign account has pub type XcmFeesToAccount = pallet_traits::xcm::XcmFeesToAccount< - Assets, + CurrencyAdapter, ( ConvertedConcreteAssetId< CurrencyId, Balance, - AsAssetType, + AsAssetType, JustTry, >, ), @@ -1309,7 +1311,7 @@ impl Config for XcmConfig { type LocationInverter = LocationInverter; type Barrier = Barrier; type Weigher = FixedWeightBounds; - type Trader = FirstAssetTrader; + type Trader = FirstAssetTrader; type ResponseHandler = PolkadotXcm; type SubscriptionService = PolkadotXcm; type AssetTrap = PolkadotXcm;