diff --git a/Cargo.lock b/Cargo.lock
index 81453f8e51..a34e028c5d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2457,6 +2457,7 @@ dependencies = [
"sp-core 34.0.0",
"sp-genesis-builder",
"sp-inherents",
+ "sp-io 37.0.0",
"sp-offchain",
"sp-runtime 38.0.0",
"sp-session",
diff --git a/relay/kusama/src/impls.rs b/relay/kusama/src/impls.rs
deleted file mode 100644
index 77e7ca941d..0000000000
--- a/relay/kusama/src/impls.rs
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright (C) Parity Technologies (UK) Ltd.
-// This file is part of Polkadot.
-
-// Polkadot 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.
-
-// Polkadot 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 Polkadot. If not, see .
-
-use super::*;
-use core::marker::PhantomData;
-use frame_support::traits::tokens::ConversionFromAssetBalance;
-use polkadot_primitives::Id as ParaId;
-use xcm_builder::IsChildSystemParachain;
-
-// TODO: replace by types from polkadot-sdk https://github.com/paritytech/polkadot-sdk/pull/3659
-/// Determines if the given `asset_kind` is a native asset. If it is, returns the balance without
-/// conversion; otherwise, delegates to the implementation specified by `I`.
-///
-/// Example where the `asset_kind` represents the native asset:
-/// - location: (1, Parachain(1000)), // location of a Sibling Parachain;
-/// - asset_id: (1, Here), // the asset id in the context of `asset_kind.location`;
-pub struct NativeOnSystemParachain(PhantomData);
-impl ConversionFromAssetBalance
- for NativeOnSystemParachain
-where
- I: ConversionFromAssetBalance,
-{
- type Error = ();
- fn from_asset_balance(
- balance: Balance,
- asset_kind: VersionedLocatableAsset,
- ) -> Result {
- use VersionedLocatableAsset::*;
- let (location, asset_id) = match asset_kind.clone() {
- V3 { location, asset_id } => (location.try_into()?, asset_id.try_into()?),
- V4 { location, asset_id } => (location, asset_id),
- };
- if asset_id.0.contains_parents_only(1) &&
- IsChildSystemParachain::::contains(&location)
- {
- Ok(balance)
- } else {
- I::from_asset_balance(balance, asset_kind).map_err(|_| ())
- }
- }
- #[cfg(feature = "runtime-benchmarks")]
- fn ensure_successful(asset_kind: VersionedLocatableAsset) {
- I::ensure_successful(asset_kind)
- }
-}
diff --git a/relay/kusama/src/lib.rs b/relay/kusama/src/lib.rs
index f36bbe75cc..5bd9c28a78 100644
--- a/relay/kusama/src/lib.rs
+++ b/relay/kusama/src/lib.rs
@@ -41,7 +41,8 @@ use polkadot_primitives::{
use polkadot_runtime_common::{
auctions, claims, crowdloan, impl_runtime_weights,
impls::{
- DealWithFees, LocatableAssetConverter, VersionedLocatableAsset, VersionedLocationConverter,
+ ContainsParts as ContainsLocationParts, DealWithFees, LocatableAssetConverter,
+ VersionedLocatableAsset, VersionedLocationConverter,
},
paras_registrar, prod_or_fast, slots, BalanceToU256, BlockHashCount, BlockLength,
CurrencyToVote, SlowAdjustingFeeUpdate, U256ToBalance,
@@ -86,9 +87,10 @@ use frame_support::{
genesis_builder_helper::{build_state, get_preset},
parameter_types,
traits::{
- fungible::HoldConsideration, ConstU32, Contains, EitherOf, EitherOfDiverse, Everything,
- InstanceFilter, KeyOwnerProofSystem, LinearStoragePrice, PrivilegeCmp, ProcessMessage,
- ProcessMessageError, StorageMapShim, WithdrawReasons,
+ fungible::HoldConsideration, tokens::UnityOrOuterConversion, ConstU32, ConstU8, EitherOf,
+ EitherOfDiverse, Everything, FromContains, InstanceFilter, KeyOwnerProofSystem,
+ LinearStoragePrice, PrivilegeCmp, ProcessMessage, ProcessMessageError, StorageMapShim,
+ WithdrawReasons,
},
weights::{ConstantMultiplier, WeightMeter, WeightToFee as _},
PalletId,
@@ -154,9 +156,6 @@ use governance::{
Treasurer, TreasurySpender,
};
-// Implemented types.
-pub mod impls;
-
#[cfg(test)]
mod tests;
@@ -860,7 +859,7 @@ impl pallet_treasury::Config for Runtime {
LocatableAssetConverter,
VersionedLocationConverter,
>;
- type BalanceConverter = impls::NativeOnSystemParachain;
+ type BalanceConverter = AssetRateWithNative;
type PayoutPeriod = PayoutSpendPeriod;
#[cfg(feature = "runtime-benchmarks")]
type BenchmarkHelper = polkadot_runtime_common::impls::benchmarks::TreasuryArguments;
@@ -1614,6 +1613,19 @@ impl pallet_nomination_pools::Config for Runtime {
type AdminOrigin = EitherOf, StakingAdmin>;
}
+/// The [frame_support::traits::tokens::ConversionFromAssetBalance] implementation provided by the
+/// `AssetRate` pallet instance, with additional decoration to identify different IDs/locations of
+/// native asset and provide a one-to-one balance conversion for them.
+pub type AssetRateWithNative = UnityOrOuterConversion<
+ ContainsLocationParts<
+ FromContains<
+ xcm_builder::IsChildSystemParachain,
+ xcm_builder::IsParentsOnly>,
+ >,
+ >,
+ AssetRate,
+>;
+
impl pallet_asset_rate::Config for Runtime {
type WeightInfo = weights::pallet_asset_rate::WeightInfo;
type RuntimeEvent = RuntimeEvent;
diff --git a/relay/kusama/tests/asset_rate.rs b/relay/kusama/tests/asset_rate.rs
new file mode 100644
index 0000000000..72ee7be0b0
--- /dev/null
+++ b/relay/kusama/tests/asset_rate.rs
@@ -0,0 +1,96 @@
+// Copyright (C) Parity Technologies (UK) Ltd.
+// This file is part of Polkadot.
+
+// Polkadot 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.
+
+// Polkadot 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 Polkadot. If not, see .
+
+//! AssetRate pallet instance tests.
+
+use frame_support::traits::tokens::ConversionFromAssetBalance;
+use polkadot_runtime_common::impls::VersionedLocatableAsset;
+use staging_kusama_runtime::AssetRateWithNative;
+use xcm::prelude::*;
+
+#[test]
+fn native_asset_rate_works() {
+ sp_io::TestExternalities::default().execute_with(|| {
+ // success: native asset on Asset Hub as xcm v4 location
+ let native = VersionedLocatableAsset::V4 {
+ location: Location::new(0, [Parachain(1000)]),
+ asset_id: Location::parent().into(),
+ };
+ let actual = AssetRateWithNative::from_asset_balance(100, native).unwrap();
+ assert_eq!(actual, 100);
+
+ // success: native asset on Asset Hub as xcm v3 location
+ let native = VersionedLocatableAsset::V3 {
+ location: xcm::v3::Location::new(
+ 0,
+ xcm::v3::Junctions::X1(xcm::v3::Junction::Parachain(1000)),
+ ),
+ asset_id: xcm::v3::Location::parent().into(),
+ };
+ let actual = AssetRateWithNative::from_asset_balance(100, native).unwrap();
+ assert_eq!(actual, 100);
+
+ // success: native asset on People as xcm v4 location
+ let native = VersionedLocatableAsset::V4 {
+ location: Location::new(0, [Parachain(1004)]),
+ asset_id: Location::parent().into(),
+ };
+ let actual = AssetRateWithNative::from_asset_balance(100, native).unwrap();
+ assert_eq!(actual, 100);
+
+ // success: native asset on People as xcm v3 location
+ let native = VersionedLocatableAsset::V3 {
+ location: xcm::v3::Location::new(
+ 0,
+ xcm::v3::Junctions::X1(xcm::v3::Junction::Parachain(1004)),
+ ),
+ asset_id: xcm::v3::Location::parent().into(),
+ };
+ let actual = AssetRateWithNative::from_asset_balance(100, native).unwrap();
+ assert_eq!(actual, 100);
+
+ // failure: native asset on non system chain as xcm v4 location
+ let native_non_system = VersionedLocatableAsset::V4 {
+ location: Location::new(0, [Parachain(2000)]),
+ asset_id: Location::parent().into(),
+ };
+ assert!(AssetRateWithNative::from_asset_balance(100, native_non_system).is_err());
+
+ // failure: native asset on non system chain as xcm v3 location
+ let native_non_system = VersionedLocatableAsset::V3 {
+ location: xcm::v3::Location::new(
+ 0,
+ xcm::v3::Junctions::X1(xcm::v3::Junction::Parachain(2000)),
+ ),
+ asset_id: xcm::v3::Location::parent().into(),
+ };
+ assert!(AssetRateWithNative::from_asset_balance(100, native_non_system).is_err());
+
+ // failure: some asset on Asset Hub as xcm v4 location
+ let non_native = VersionedLocatableAsset::V4 {
+ location: Location::new(0, [Parachain(2000)]),
+ asset_id: Location::new(0, [PalletInstance(50), GeneralIndex(1984)]).into(),
+ };
+ assert!(AssetRateWithNative::from_asset_balance(100, non_native).is_err());
+
+ // failure: native asset with invalid system chain location as xcm v4 location
+ let native_non_system = VersionedLocatableAsset::V4 {
+ location: Location::new(1, [Parachain(1000)]),
+ asset_id: Location::parent().into(),
+ };
+ assert!(AssetRateWithNative::from_asset_balance(100, native_non_system).is_err());
+ });
+}
diff --git a/relay/polkadot/src/impls.rs b/relay/polkadot/src/impls.rs
index 9d16785485..05188460ab 100644
--- a/relay/polkadot/src/impls.rs
+++ b/relay/polkadot/src/impls.rs
@@ -14,53 +14,9 @@
// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see .
-use super::*;
-use core::marker::PhantomData;
-use frame_support::traits::{tokens::ConversionFromAssetBalance, Contains};
-use polkadot_primitives::Id as ParaId;
-use xcm_builder::IsChildSystemParachain;
-
-// TODO: replace by types from polkadot-sdk https://github.com/paritytech/polkadot-sdk/pull/3659
-/// Determines if the given `asset_kind` is a native asset. If it is, returns the balance without
-/// conversion; otherwise, delegates to the implementation specified by `I`.
-///
-/// Example where the `asset_kind` represents the native asset:
-/// - location: (1, Parachain(1000)), // location of a Sibling Parachain;
-/// - asset_id: (1, Here), // the asset id in the context of `asset_kind.location`;
-pub struct NativeOnSystemParachain(PhantomData);
-impl ConversionFromAssetBalance
- for NativeOnSystemParachain
-where
- I: ConversionFromAssetBalance,
-{
- type Error = ();
- fn from_asset_balance(
- balance: Balance,
- asset_kind: VersionedLocatableAsset,
- ) -> Result {
- use VersionedLocatableAsset::*;
- let (location, asset_id) = match asset_kind.clone() {
- V3 { location, asset_id } => (location.try_into()?, asset_id.try_into()?),
- V4 { location, asset_id } => (location, asset_id),
- };
- if asset_id.0.contains_parents_only(1) &&
- IsChildSystemParachain::::contains(&location)
- {
- Ok(balance)
- } else {
- I::from_asset_balance(balance, asset_kind).map_err(|_| ())
- }
- }
- #[cfg(feature = "runtime-benchmarks")]
- fn ensure_successful(asset_kind: VersionedLocatableAsset) {
- I::ensure_successful(asset_kind)
- }
-}
-
#[cfg(feature = "runtime-benchmarks")]
pub mod benchmarks {
- use super::{xcm_config::CheckAccount, ExistentialDeposit};
- use crate::Balances;
+ use crate::{xcm_config::CheckAccount, Balances, ExistentialDeposit};
use frame_support::{
dispatch::RawOrigin,
traits::{Currency, EnsureOrigin},
diff --git a/relay/polkadot/src/lib.rs b/relay/polkadot/src/lib.rs
index bb7ec1344f..08a782346f 100644
--- a/relay/polkadot/src/lib.rs
+++ b/relay/polkadot/src/lib.rs
@@ -24,7 +24,8 @@ use pallet_transaction_payment::FungibleAdapter;
use polkadot_runtime_common::{
auctions, claims, crowdloan, impl_runtime_weights,
impls::{
- DealWithFees, LocatableAssetConverter, VersionedLocatableAsset, VersionedLocationConverter,
+ ContainsParts as ContainsLocationParts, DealWithFees, LocatableAssetConverter,
+ VersionedLocatableAsset, VersionedLocationConverter,
},
paras_registrar, prod_or_fast, slots,
traits::OnSwap,
@@ -62,9 +63,10 @@ use frame_support::{
genesis_builder_helper::{build_state, get_preset},
parameter_types,
traits::{
- fungible::HoldConsideration, ConstU32, EitherOf, EitherOfDiverse, Everything, Get,
- InstanceFilter, KeyOwnerProofSystem, LinearStoragePrice, OnRuntimeUpgrade, PrivilegeCmp,
- ProcessMessage, ProcessMessageError, WithdrawReasons,
+ fungible::HoldConsideration, tokens::UnityOrOuterConversion, ConstU32, ConstU8, EitherOf,
+ EitherOfDiverse, Everything, FromContains, Get, InstanceFilter, KeyOwnerProofSystem,
+ LinearStoragePrice, OnRuntimeUpgrade, PrivilegeCmp, ProcessMessage, ProcessMessageError,
+ WithdrawReasons,
},
weights::{
constants::{WEIGHT_PROOF_SIZE_PER_KB, WEIGHT_REF_TIME_PER_MICROS},
@@ -826,7 +828,7 @@ impl pallet_treasury::Config for Runtime {
LocatableAssetConverter,
VersionedLocationConverter,
>;
- type BalanceConverter = impls::NativeOnSystemParachain;
+ type BalanceConverter = AssetRateWithNative;
type PayoutPeriod = PayoutSpendPeriod;
#[cfg(feature = "runtime-benchmarks")]
type BenchmarkHelper = polkadot_runtime_common::impls::benchmarks::TreasuryArguments;
@@ -1554,6 +1556,19 @@ impl pallet_state_trie_migration::Config for Runtime {
type MaxKeyLen = MigrationMaxKeyLen;
}
+/// The [frame_support::traits::tokens::ConversionFromAssetBalance] implementation provided by the
+/// `AssetRate` pallet instance, with additional decoration to identify different IDs/locations of
+/// native asset and provide a one-to-one balance conversion for them.
+pub type AssetRateWithNative = UnityOrOuterConversion<
+ ContainsLocationParts<
+ FromContains<
+ xcm_builder::IsChildSystemParachain,
+ xcm_builder::IsParentsOnly>,
+ >,
+ >,
+ AssetRate,
+>;
+
impl pallet_asset_rate::Config for Runtime {
type WeightInfo = weights::pallet_asset_rate::WeightInfo;
type RuntimeEvent = RuntimeEvent;
diff --git a/relay/polkadot/tests/asset_rate.rs b/relay/polkadot/tests/asset_rate.rs
new file mode 100644
index 0000000000..68fde7d7fa
--- /dev/null
+++ b/relay/polkadot/tests/asset_rate.rs
@@ -0,0 +1,96 @@
+// Copyright (C) Parity Technologies (UK) Ltd.
+// This file is part of Polkadot.
+
+// Polkadot 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.
+
+// Polkadot 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 Polkadot. If not, see .
+
+//! AssetRate pallet instance tests.
+
+use frame_support::traits::tokens::ConversionFromAssetBalance;
+use polkadot_runtime::AssetRateWithNative;
+use polkadot_runtime_common::impls::VersionedLocatableAsset;
+use xcm::prelude::*;
+
+#[test]
+fn native_asset_rate_works() {
+ sp_io::TestExternalities::default().execute_with(|| {
+ // success: native asset on Asset Hub as xcm v4 location
+ let native = VersionedLocatableAsset::V4 {
+ location: Location::new(0, [Parachain(1000)]),
+ asset_id: Location::parent().into(),
+ };
+ let actual = AssetRateWithNative::from_asset_balance(100, native).unwrap();
+ assert_eq!(actual, 100);
+
+ // success: native asset on Asset Hub as xcm v3 location
+ let native = VersionedLocatableAsset::V3 {
+ location: xcm::v3::Location::new(
+ 0,
+ xcm::v3::Junctions::X1(xcm::v3::Junction::Parachain(1000)),
+ ),
+ asset_id: xcm::v3::Location::parent().into(),
+ };
+ let actual = AssetRateWithNative::from_asset_balance(100, native).unwrap();
+ assert_eq!(actual, 100);
+
+ // success: native asset on People as xcm v4 location
+ let native = VersionedLocatableAsset::V4 {
+ location: Location::new(0, [Parachain(1004)]),
+ asset_id: Location::parent().into(),
+ };
+ let actual = AssetRateWithNative::from_asset_balance(100, native).unwrap();
+ assert_eq!(actual, 100);
+
+ // success: native asset on People as xcm v3 location
+ let native = VersionedLocatableAsset::V3 {
+ location: xcm::v3::Location::new(
+ 0,
+ xcm::v3::Junctions::X1(xcm::v3::Junction::Parachain(1004)),
+ ),
+ asset_id: xcm::v3::Location::parent().into(),
+ };
+ let actual = AssetRateWithNative::from_asset_balance(100, native).unwrap();
+ assert_eq!(actual, 100);
+
+ // failure: native asset on non system chain as xcm v4 location
+ let native_non_system = VersionedLocatableAsset::V4 {
+ location: Location::new(0, [Parachain(2000)]),
+ asset_id: Location::parent().into(),
+ };
+ assert!(AssetRateWithNative::from_asset_balance(100, native_non_system).is_err());
+
+ // failure: native asset on non system chain as xcm v3 location
+ let native_non_system = VersionedLocatableAsset::V3 {
+ location: xcm::v3::Location::new(
+ 0,
+ xcm::v3::Junctions::X1(xcm::v3::Junction::Parachain(2000)),
+ ),
+ asset_id: xcm::v3::Location::parent().into(),
+ };
+ assert!(AssetRateWithNative::from_asset_balance(100, native_non_system).is_err());
+
+ // failure: some asset on Asset Hub as xcm v4 location
+ let non_native = VersionedLocatableAsset::V4 {
+ location: Location::new(0, [Parachain(2000)]),
+ asset_id: Location::new(0, [PalletInstance(50), GeneralIndex(1984)]).into(),
+ };
+ assert!(AssetRateWithNative::from_asset_balance(100, non_native).is_err());
+
+ // failure: native asset with invalid system chain location as xcm v4 location
+ let native_non_system = VersionedLocatableAsset::V4 {
+ location: Location::new(1, [Parachain(1000)]),
+ asset_id: Location::parent().into(),
+ };
+ assert!(AssetRateWithNative::from_asset_balance(100, native_non_system).is_err());
+ });
+}
diff --git a/system-parachains/collectives/collectives-polkadot/Cargo.toml b/system-parachains/collectives/collectives-polkadot/Cargo.toml
index 247a4f9554..6c7eec3d7d 100644
--- a/system-parachains/collectives/collectives-polkadot/Cargo.toml
+++ b/system-parachains/collectives/collectives-polkadot/Cargo.toml
@@ -87,6 +87,7 @@ system-parachains-constants = { workspace = true }
[dev-dependencies]
collectives-polkadot-runtime-constants = { workspace = true }
+sp-io = { workspace = true }
[build-dependencies]
substrate-wasm-builder = { optional = true, workspace = true }
@@ -221,6 +222,7 @@ std = [
"sp-core/std",
"sp-genesis-builder/std",
"sp-inherents/std",
+ "sp-io/std",
"sp-offchain/std",
"sp-runtime/std",
"sp-session/std",
diff --git a/system-parachains/collectives/collectives-polkadot/src/ambassador/mod.rs b/system-parachains/collectives/collectives-polkadot/src/ambassador/mod.rs
index 94fa1ac705..034206c542 100644
--- a/system-parachains/collectives/collectives-polkadot/src/ambassador/mod.rs
+++ b/system-parachains/collectives/collectives-polkadot/src/ambassador/mod.rs
@@ -36,7 +36,7 @@ pub use origins::pallet_origins as pallet_ambassador_origins;
use crate::{
xcm_config::{AssetHubUsdt, FellowshipAdminBodyId},
- *,
+ AssetRateWithNative, *,
};
use frame_support::{
pallet_prelude::PalletInfoAccess,
@@ -348,7 +348,7 @@ impl pallet_treasury::Config for Runtime {
AmbassadorTreasuryPaymaster,
crate::impls::benchmarks::OpenHrmpChannel>,
>;
- type BalanceConverter = crate::impls::NativeOnSiblingParachain;
+ type BalanceConverter = AssetRateWithNative;
type PayoutPeriod = ConstU32<{ 30 * DAYS }>;
#[cfg(feature = "runtime-benchmarks")]
type BenchmarkHelper = polkadot_runtime_common::impls::benchmarks::TreasuryArguments<
diff --git a/system-parachains/collectives/collectives-polkadot/src/fellowship/mod.rs b/system-parachains/collectives/collectives-polkadot/src/fellowship/mod.rs
index 9f39e5ddfc..b1354bd647 100644
--- a/system-parachains/collectives/collectives-polkadot/src/fellowship/mod.rs
+++ b/system-parachains/collectives/collectives-polkadot/src/fellowship/mod.rs
@@ -23,9 +23,9 @@ use crate::{
impls::ToParentTreasury,
weights,
xcm_config::{AssetHubUsdt, LocationToAccountId, TreasurerBodyId},
- AccountId, AssetRate, Balance, Balances, FellowshipReferenda, GovernanceLocation,
- ParachainInfo, PolkadotTreasuryAccount, Preimage, Runtime, RuntimeCall, RuntimeEvent,
- RuntimeOrigin, Scheduler, DAYS, FELLOWSHIP_TREASURY_PALLET_ID,
+ AccountId, AssetRateWithNative, Balance, Balances, FellowshipReferenda, GovernanceLocation,
+ PolkadotTreasuryAccount, Preimage, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin,
+ Scheduler, DAYS, FELLOWSHIP_TREASURY_PALLET_ID,
};
use frame_support::{
parameter_types,
@@ -324,7 +324,7 @@ impl pallet_treasury::Config for Runtime {
type Paymaster = FellowshipTreasuryPaymaster;
#[cfg(feature = "runtime-benchmarks")]
type Paymaster = PayWithEnsure>>;
- type BalanceConverter = crate::impls::NativeOnSiblingParachain;
+ type BalanceConverter = AssetRateWithNative;
type PayoutPeriod = ConstU32<{ 30 * DAYS }>;
#[cfg(feature = "runtime-benchmarks")]
type BenchmarkHelper = polkadot_runtime_common::impls::benchmarks::TreasuryArguments<
diff --git a/system-parachains/collectives/collectives-polkadot/src/impls.rs b/system-parachains/collectives/collectives-polkadot/src/impls.rs
index c25c21766a..57df1ae2ff 100644
--- a/system-parachains/collectives/collectives-polkadot/src/impls.rs
+++ b/system-parachains/collectives/collectives-polkadot/src/impls.rs
@@ -16,14 +16,10 @@
use super::*;
use frame_support::{
dispatch::DispatchResultWithPostInfo,
- traits::{
- tokens::ConversionFromAssetBalance, Contains, Currency, Get, Imbalance, OnUnbalanced,
- OriginTrait, PrivilegeCmp,
- },
+ traits::{Currency, Get, Imbalance, OnUnbalanced, OriginTrait, PrivilegeCmp},
};
use pallet_alliance::{ProposalIndex, ProposalProvider};
use parachains_common::impls::NegativeImbalance;
-use polkadot_parachain_primitives::primitives::{Id as ParaId, IsSystem};
use sp_runtime::DispatchError;
use sp_std::{cmp::Ordering, marker::PhantomData, prelude::*};
use xcm_executor::traits::ConvertLocation;
@@ -160,55 +156,6 @@ impl PrivilegeCmp for EqualOrGreatestRootCmp {
}
}
-// TODO: replace by types from polkadot-sdk https://github.com/paritytech/polkadot-sdk/pull/3659
-/// Contains a system-level sibling parachain.
-pub struct IsSiblingSystemParachain(PhantomData<(ParaId, SelfParaId)>);
-impl + Eq, SelfParaId: Get> Contains
- for IsSiblingSystemParachain
-{
- fn contains(l: &Location) -> bool {
- matches!(
- l.unpack(),
- (1, [Parachain(id)]) if ParaId::from(*id).is_system() && SelfParaId::get() != ParaId::from(*id),
- )
- }
-}
-
-// TODO: replace by types from polkadot-sdk https://github.com/paritytech/polkadot-sdk/pull/3659
-/// Determines if the given `asset_kind` is a native asset. If it is, returns the balance without
-/// conversion; otherwise, delegates to the implementation specified by `I`.
-pub struct NativeOnSiblingParachain(PhantomData<(I, SelfParaId)>);
-impl ConversionFromAssetBalance
- for NativeOnSiblingParachain
-where
- I: ConversionFromAssetBalance,
- SelfParaId: Get,
-{
- type Error = ();
- fn from_asset_balance(
- balance: Balance,
- asset_kind: VersionedLocatableAsset,
- ) -> Result {
- use VersionedLocatableAsset::*;
- let (location, asset_id) = match asset_kind.clone() {
- V3 { location, asset_id } => (location.try_into()?, asset_id.try_into()?),
- V4 { location, asset_id } => (location, asset_id),
- };
-
- if asset_id.0.contains_parents_only(1) &&
- IsSiblingSystemParachain::::contains(&location)
- {
- Ok(balance)
- } else {
- I::from_asset_balance(balance, asset_kind).map_err(|_| ())
- }
- }
- #[cfg(feature = "runtime-benchmarks")]
- fn ensure_successful(asset_kind: VersionedLocatableAsset) {
- I::ensure_successful(asset_kind)
- }
-}
-
#[cfg(feature = "runtime-benchmarks")]
pub mod benchmarks {
use super::*;
diff --git a/system-parachains/collectives/collectives-polkadot/src/lib.rs b/system-parachains/collectives/collectives-polkadot/src/lib.rs
index 8dcd46e3ea..d798048d32 100644
--- a/system-parachains/collectives/collectives-polkadot/src/lib.rs
+++ b/system-parachains/collectives/collectives-polkadot/src/lib.rs
@@ -50,7 +50,9 @@ use cumulus_pallet_parachain_system::RelayNumberMonotonicallyIncreases;
use cumulus_primitives_core::{AggregateMessageOrigin, ParaId};
use fellowship::{pallet_fellowship_origins, Fellows};
use impls::{AllianceProposalProvider, EqualOrGreatestRootCmp, ToParentTreasury};
-use polkadot_runtime_common::impls::VersionedLocatableAsset;
+use polkadot_runtime_common::impls::{
+ ContainsParts as ContainsLocationParts, VersionedLocatableAsset,
+};
use sp_api::impl_runtime_apis;
use sp_core::{crypto::KeyTypeId, OpaqueMetadata};
use sp_runtime::{
@@ -72,8 +74,10 @@ use frame_support::{
genesis_builder_helper::{build_state, get_preset},
parameter_types,
traits::{
- fungible::HoldConsideration, tokens::imbalance::ResolveTo, ConstBool, ConstU16, ConstU32,
- ConstU64, ConstU8, EitherOfDiverse, InstanceFilter, LinearStoragePrice, TransformOrigin,
+ fungible::HoldConsideration,
+ tokens::{imbalance::ResolveTo, UnityOrOuterConversion},
+ ConstBool, ConstU16, ConstU32, ConstU64, ConstU8, EitherOfDiverse, FromContains,
+ InstanceFilter, LinearStoragePrice, TransformOrigin,
},
weights::{ConstantMultiplier, Weight, WeightToFee as _},
PalletId,
@@ -92,7 +96,7 @@ use system_parachains_constants::{
SLOT_DURATION,
};
use xcm_config::{
- GovernanceLocation, LocationToAccountId, StakingPot, TreasurerBodyId,
+ GovernanceLocation, LocationToAccountId, SelfParaId, StakingPot, TreasurerBodyId,
XcmOriginToTransactDispatchOrigin,
};
@@ -646,6 +650,19 @@ impl pallet_preimage::Config for Runtime {
>;
}
+/// The [frame_support::traits::tokens::ConversionFromAssetBalance] implementation provided by the
+/// `AssetRate` pallet instance, with additional decoration to identify different IDs/locations of
+/// native asset and provide a one-to-one balance conversion for them.
+pub type AssetRateWithNative = UnityOrOuterConversion<
+ ContainsLocationParts<
+ FromContains<
+ xcm_builder::IsSiblingSystemParachain,
+ xcm_builder::IsParentsOnly>,
+ >,
+ >,
+ AssetRate,
+>;
+
impl pallet_asset_rate::Config for Runtime {
type WeightInfo = weights::pallet_asset_rate::WeightInfo;
type RuntimeEvent = RuntimeEvent;
diff --git a/system-parachains/collectives/collectives-polkadot/src/xcm_config.rs b/system-parachains/collectives/collectives-polkadot/src/xcm_config.rs
index 08e48844b2..dd20acca0b 100644
--- a/system-parachains/collectives/collectives-polkadot/src/xcm_config.rs
+++ b/system-parachains/collectives/collectives-polkadot/src/xcm_config.rs
@@ -18,6 +18,7 @@ use super::{
ParachainSystem, PolkadotXcm, PriceForParentDelivery, Runtime, RuntimeCall, RuntimeEvent,
RuntimeOrigin, WeightToFee, XcmpQueue,
};
+use cumulus_primitives_core::ParaId;
use frame_support::{
parameter_types,
traits::{tokens::imbalance::ResolveTo, ConstU32, Contains, Equals, Everything, Nothing},
@@ -72,6 +73,7 @@ parameter_types! {
asset_id: (PalletInstance(50), GeneralIndex(1984)).into(),
};
pub StakingPot: AccountId = CollatorSelection::account_id();
+ pub SelfParaId: ParaId = ParachainInfo::parachain_id();
}
/// Type for specifying how a `Location` can be converted into an `AccountId`. This is used
diff --git a/system-parachains/collectives/collectives-polkadot/tests/asset_rate.rs b/system-parachains/collectives/collectives-polkadot/tests/asset_rate.rs
new file mode 100644
index 0000000000..05d0b7dae4
--- /dev/null
+++ b/system-parachains/collectives/collectives-polkadot/tests/asset_rate.rs
@@ -0,0 +1,96 @@
+// Copyright (C) Parity Technologies (UK) Ltd.
+// This file is part of Polkadot.
+
+// Polkadot 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.
+
+// Polkadot 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 Polkadot. If not, see .
+
+//! AssetRate pallet instance tests.
+
+use collectives_polkadot_runtime::AssetRateWithNative;
+use frame_support::traits::tokens::ConversionFromAssetBalance;
+use polkadot_runtime_common::impls::VersionedLocatableAsset;
+use xcm::prelude::*;
+
+#[test]
+fn native_asset_rate_works() {
+ sp_io::TestExternalities::default().execute_with(|| {
+ // success: native asset on Asset Hub as xcm v4 location
+ let native = VersionedLocatableAsset::V4 {
+ location: Location::new(1, [Parachain(1000)]),
+ asset_id: Location::parent().into(),
+ };
+ let actual = AssetRateWithNative::from_asset_balance(100, native).unwrap();
+ assert_eq!(actual, 100);
+
+ // success: native asset on Asset Hub as xcm v3 location
+ let native = VersionedLocatableAsset::V3 {
+ location: xcm::v3::Location::new(
+ 1,
+ xcm::v3::Junctions::X1(xcm::v3::Junction::Parachain(1000)),
+ ),
+ asset_id: xcm::v3::Location::parent().into(),
+ };
+ let actual = AssetRateWithNative::from_asset_balance(100, native).unwrap();
+ assert_eq!(actual, 100);
+
+ // success: native asset on People as xcm v4 location
+ let native = VersionedLocatableAsset::V4 {
+ location: Location::new(1, [Parachain(1004)]),
+ asset_id: Location::parent().into(),
+ };
+ let actual = AssetRateWithNative::from_asset_balance(100, native).unwrap();
+ assert_eq!(actual, 100);
+
+ // success: native asset on People as xcm v3 location
+ let native = VersionedLocatableAsset::V3 {
+ location: xcm::v3::Location::new(
+ 1,
+ xcm::v3::Junctions::X1(xcm::v3::Junction::Parachain(1004)),
+ ),
+ asset_id: xcm::v3::Location::parent().into(),
+ };
+ let actual = AssetRateWithNative::from_asset_balance(100, native).unwrap();
+ assert_eq!(actual, 100);
+
+ // failure: native asset on non system chain as xcm v4 location
+ let native_non_system = VersionedLocatableAsset::V4 {
+ location: Location::new(1, [Parachain(2000)]),
+ asset_id: Location::parent().into(),
+ };
+ assert!(AssetRateWithNative::from_asset_balance(100, native_non_system).is_err());
+
+ // failure: native asset on non system chain as xcm v3 location
+ let native_non_system = VersionedLocatableAsset::V3 {
+ location: xcm::v3::Location::new(
+ 1,
+ xcm::v3::Junctions::X1(xcm::v3::Junction::Parachain(2000)),
+ ),
+ asset_id: xcm::v3::Location::parent().into(),
+ };
+ assert!(AssetRateWithNative::from_asset_balance(100, native_non_system).is_err());
+
+ // failure: some asset on Asset Hub as xcm v4 location
+ let non_native = VersionedLocatableAsset::V4 {
+ location: Location::new(1, [Parachain(2000)]),
+ asset_id: Location::new(0, [PalletInstance(50), GeneralIndex(1984)]).into(),
+ };
+ assert!(AssetRateWithNative::from_asset_balance(100, non_native).is_err());
+
+ // failure: native asset with invalid system chain location as xcm v4 location
+ let native_non_system = VersionedLocatableAsset::V4 {
+ location: Location::new(0, [Parachain(1000)]),
+ asset_id: Location::parent().into(),
+ };
+ assert!(AssetRateWithNative::from_asset_balance(100, native_non_system).is_err());
+ });
+}