Skip to content

Commit

Permalink
Fix: xcm multilocation (#1911)
Browse files Browse the repository at this point in the history
* add paraid to CurrencyIdConvert

* Revert "add paraid to CurrencyIdConvert"

This reverts commit 9a44745.

* add wrapconvert

* add to runtime

* add log

* rm

* fix XcmFeesToAccount

* Update xcm.rs

* fix test
  • Loading branch information
mclyk authored Dec 7, 2022
1 parent 4c87f31 commit 2e31e7c
Show file tree
Hide file tree
Showing 8 changed files with 145 additions and 63 deletions.
3 changes: 1 addition & 2 deletions integration-tests/src/polkadot_transfer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,10 @@ fn transfer_sibling_chain_asset() {
.into()
.into()
),
//just use para to mock clv here
Box::new(
(
X1(GeneralKey(WeakBoundedVec::<u8, ConstU32<32>>::force_from(
b"PARA".to_vec(),
b"CLV".to_vec(),
None
))),
para(10)
Expand Down
51 changes: 28 additions & 23 deletions integration-tests/src/setup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -296,9 +296,8 @@ impl ExtBuilder {
1,
X2(
Parachain(2000),
//since we use hko to mock kar,just use hko location here
GeneralKey(WeakBoundedVec::<u8, ConstU32<32>>::force_from(
b"HKO".to_vec(),
b"KAR".to_vec(),
None,
)),
),
Expand Down Expand Up @@ -465,9 +464,8 @@ impl ExtBuilder {
1,
X2(
Parachain(2002),
//since we use para to mock clv,just use para location here
GeneralKey(WeakBoundedVec::<u8, ConstU32<32>>::force_from(
b"PARA".to_vec(),
b"CLV".to_vec(),
None,
)),
),
Expand Down Expand Up @@ -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::<u8, ConstU32<32>>::force_from(
b"HKO".to_vec(),
None,
))),
let kar_asset_location = MultiLocation::new(
1,
X2(
Parachain(2000),
GeneralKey(WeakBoundedVec::<u8, ConstU32<32>>::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();
Expand All @@ -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::<u8, ConstU32<32>>::force_from(
b"PARA".to_vec(),
None,
))),
let clv_asset_location = MultiLocation::new(
1,
X2(
Parachain(2002),
GeneralKey(WeakBoundedVec::<u8, ConstU32<32>>::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();
Expand Down
3 changes: 1 addition & 2 deletions integration-tests/src/sibling_transfer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,10 @@ fn transfer_sibling_chain_asset() {
.into()
.into()
),
//just use hko to mock kar here
Box::new(
(
X1(GeneralKey(WeakBoundedVec::<u8, ConstU32<32>>::force_from(
b"HKO".to_vec(),
b"KAR".to_vec(),
None
))),
heiko(10)
Expand Down
71 changes: 71 additions & 0 deletions pallets/traits/src/xcm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -584,3 +585,73 @@ impl<AssetIdInfoGetter: AssetTypeGetter<CurrencyId, AssetType>>
}
}
}

// 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<AssetId, AssetType, AssetIdInfoGetter, ParachainId>(
PhantomData<(AssetId, AssetType, AssetIdInfoGetter, ParachainId)>,
);

impl<AssetId, AssetType, AssetIdInfoGetter, ParachainId>
XcmAssetRegistry<AssetId, AssetType, AssetIdInfoGetter, ParachainId>
where
AssetType: From<MultiLocation> + Into<Option<MultiLocation>> + Clone,
ParachainId: Get<ParaId>,
{
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<AssetId, AssetType, AssetIdInfoGetter, ParachainId> AssetTypeGetter<AssetId, AssetType>
for XcmAssetRegistry<AssetId, AssetType, AssetIdInfoGetter, ParachainId>
where
AssetType: From<MultiLocation> + Into<Option<MultiLocation>> + Clone,
AssetIdInfoGetter: AssetTypeGetter<AssetId, AssetType>,
ParachainId: Get<ParaId>,
{
fn get_asset_type(asset_id: AssetId) -> Option<AssetType> {
AssetIdInfoGetter::get_asset_type(asset_id)
}

fn get_asset_id(asset_type: AssetType) -> Option<AssetId> {
AssetIdInfoGetter::get_asset_id(Self::convert(asset_type))
}
}

impl<AssetId, AssetType, AssetIdInfoGetter, ParachainId> UnitsToWeightRatio<AssetType>
for XcmAssetRegistry<AssetId, AssetType, AssetIdInfoGetter, ParachainId>
where
AssetType: From<MultiLocation> + Into<Option<MultiLocation>> + Clone,
AssetIdInfoGetter: UnitsToWeightRatio<AssetType>,
ParachainId: Get<ParaId>,
{
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<u128> {
AssetIdInfoGetter::get_units_per_second(Self::convert(asset_type))
}
}
20 changes: 11 additions & 9 deletions runtime/heiko/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ pub use pallet_streaming;
use pallet_traits::{
xcm::{
AccountIdToMultiLocation, AsAssetType, AssetType, CurrencyIdConvert, FirstAssetTrader,
MultiCurrencyAdapter,
MultiCurrencyAdapter, XcmAssetRegistry,
},
DecimalProvider, EmergencyCallFilter, ValidationDataProvider,
};
Expand Down Expand Up @@ -393,7 +393,7 @@ impl orml_xtokens::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type Balance = Balance;
type CurrencyId = CurrencyId;
type CurrencyIdConvert = CurrencyIdConvert<AssetRegistry>;
type CurrencyIdConvert = CurrencyIdConvert<WrapAssetRegistry>;
type AccountIdToMultiLocation = AccountIdToMultiLocation<AccountId>;
type SelfLocation = SelfLocation;
type XcmExecutor = XcmExecutor<XcmConfig>;
Expand Down Expand Up @@ -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<CurrencyId, CurrencyIdConvert<AssetRegistry>>,
IsNativeConcrete<CurrencyId, CurrencyIdConvert<WrapAssetRegistry>>,
// 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<AssetRegistry>,
CurrencyIdConvert<WrapAssetRegistry>,
NativeCurrencyId,
ExistentialDeposit,
GiftAccount,
Expand Down Expand Up @@ -1051,7 +1051,7 @@ impl TakeRevenue for ToTreasury {
fun: Fungibility::Fungible(amount),
} = revenue
{
if let Some(currency_id) = CurrencyIdConvert::<AssetRegistry>::convert(id) {
if let Some(currency_id) = CurrencyIdConvert::<WrapAssetRegistry>::convert(id) {
let _ = Assets::mint_into(currency_id, &TreasuryAccount::get(), amount);
}
}
Expand All @@ -1062,6 +1062,8 @@ parameter_types! {
pub CheckingAccount: AccountId = PolkadotXcm::check_account();
}

pub type WrapAssetRegistry = XcmAssetRegistry<CurrencyId, AssetType, AssetRegistry, ParachainInfo>;

/// The non-reserve fungible transactor type
/// It will use pallet-assets, and the Id will be matched against AsAssetType
pub type ForeignFungiblesTransactor = FungiblesAdapter<
Expand All @@ -1072,7 +1074,7 @@ pub type ForeignFungiblesTransactor = FungiblesAdapter<
ConvertedConcreteAssetId<
CurrencyId,
Balance,
AsAssetType<CurrencyId, AssetType, AssetRegistry>,
AsAssetType<CurrencyId, AssetType, WrapAssetRegistry>,
JustTry,
>,
),
Expand All @@ -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<CurrencyId, AssetType, AssetRegistry>,
AsAssetType<CurrencyId, AssetType, WrapAssetRegistry>,
JustTry,
>,
),
Expand All @@ -1120,7 +1122,7 @@ impl Config for XcmConfig {
type LocationInverter = LocationInverter<Ancestry>;
type Barrier = Barrier;
type Weigher = FixedWeightBounds<BaseXcmWeight, RuntimeCall, MaxInstructions>;
type Trader = FirstAssetTrader<AssetType, AssetRegistry, XcmFeesToAccount>;
type Trader = FirstAssetTrader<AssetType, WrapAssetRegistry, XcmFeesToAccount>;
type ResponseHandler = PolkadotXcm;
type SubscriptionService = PolkadotXcm;
type AssetTrap = PolkadotXcm;
Expand Down
20 changes: 11 additions & 9 deletions runtime/kerria/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ pub use pallet_streaming;
use pallet_traits::{
xcm::{
AccountIdToMultiLocation, AsAssetType, AssetType, CurrencyIdConvert, FirstAssetTrader,
MultiCurrencyAdapter,
MultiCurrencyAdapter, XcmAssetRegistry,
},
DecimalProvider, EmergencyCallFilter, ValidationDataProvider,
};
Expand Down Expand Up @@ -422,7 +422,7 @@ impl orml_xtokens::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type Balance = Balance;
type CurrencyId = CurrencyId;
type CurrencyIdConvert = CurrencyIdConvert<AssetRegistry>;
type CurrencyIdConvert = CurrencyIdConvert<WrapAssetRegistry>;
type AccountIdToMultiLocation = AccountIdToMultiLocation<AccountId>;
type SelfLocation = SelfLocation;
type XcmExecutor = XcmExecutor<XcmConfig>;
Expand Down Expand Up @@ -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<CurrencyId, CurrencyIdConvert<AssetRegistry>>,
IsNativeConcrete<CurrencyId, CurrencyIdConvert<WrapAssetRegistry>>,
// 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<AssetRegistry>,
CurrencyIdConvert<WrapAssetRegistry>,
NativeCurrencyId,
ExistentialDeposit,
GiftAccount,
Expand Down Expand Up @@ -1220,7 +1220,7 @@ impl TakeRevenue for ToTreasury {
fun: Fungibility::Fungible(amount),
} = revenue
{
if let Some(currency_id) = CurrencyIdConvert::<AssetRegistry>::convert(id) {
if let Some(currency_id) = CurrencyIdConvert::<WrapAssetRegistry>::convert(id) {
let _ = Assets::mint_into(currency_id, &TreasuryAccount::get(), amount);
}
}
Expand All @@ -1243,6 +1243,8 @@ parameter_types! {
pub CheckingAccount: AccountId = PolkadotXcm::check_account();
}

pub type WrapAssetRegistry = XcmAssetRegistry<CurrencyId, AssetType, AssetRegistry, ParachainInfo>;

/// The non-reserve fungible transactor type
/// It will use pallet-assets, and the Id will be matched against AsAssetType
pub type ForeignFungiblesTransactor = FungiblesAdapter<
Expand All @@ -1253,7 +1255,7 @@ pub type ForeignFungiblesTransactor = FungiblesAdapter<
ConvertedConcreteAssetId<
CurrencyId,
Balance,
AsAssetType<CurrencyId, AssetType, AssetRegistry>,
AsAssetType<CurrencyId, AssetType, WrapAssetRegistry>,
JustTry,
>,
),
Expand All @@ -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<CurrencyId, AssetType, AssetRegistry>,
AsAssetType<CurrencyId, AssetType, WrapAssetRegistry>,
JustTry,
>,
),
Expand All @@ -1301,7 +1303,7 @@ impl Config for XcmConfig {
type LocationInverter = LocationInverter<Ancestry>;
type Barrier = Barrier;
type Weigher = FixedWeightBounds<BaseXcmWeight, RuntimeCall, MaxInstructions>;
type Trader = FirstAssetTrader<AssetType, AssetRegistry, XcmFeesToAccount>;
type Trader = FirstAssetTrader<AssetType, WrapAssetRegistry, XcmFeesToAccount>;
type ResponseHandler = PolkadotXcm;
type SubscriptionService = PolkadotXcm;
type AssetTrap = PolkadotXcm;
Expand Down
Loading

0 comments on commit 2e31e7c

Please sign in to comment.