Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Utilize SDK types for native asset balance conversion #424

Merged
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

58 changes: 0 additions & 58 deletions relay/kusama/src/impls.rs

This file was deleted.

28 changes: 20 additions & 8 deletions relay/kusama/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -154,9 +156,6 @@ use governance::{
Treasurer, TreasurySpender,
};

// Implemented types.
pub mod impls;

#[cfg(test)]
mod tests;

Expand Down Expand Up @@ -860,7 +859,7 @@ impl pallet_treasury::Config for Runtime {
LocatableAssetConverter,
VersionedLocationConverter,
>;
type BalanceConverter = impls::NativeOnSystemParachain<AssetRate>;
type BalanceConverter = AssetRateWithNative;
type PayoutPeriod = PayoutSpendPeriod;
#[cfg(feature = "runtime-benchmarks")]
type BenchmarkHelper = polkadot_runtime_common::impls::benchmarks::TreasuryArguments;
Expand Down Expand Up @@ -1614,6 +1613,19 @@ impl pallet_nomination_pools::Config for Runtime {
type AdminOrigin = EitherOf<EnsureRoot<AccountId>, 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<ParaId>,
xcm_builder::IsParentsOnly<ConstU8<1>>,
>,
>,
AssetRate,
>;

impl pallet_asset_rate::Config for Runtime {
type WeightInfo = weights::pallet_asset_rate::WeightInfo<Runtime>;
type RuntimeEvent = RuntimeEvent;
Expand Down
96 changes: 96 additions & 0 deletions relay/kusama/tests/asset_rate.rs
Original file line number Diff line number Diff line change
@@ -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 <http://www.gnu.org/licenses/>.

//! 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());
});
}
46 changes: 1 addition & 45 deletions relay/polkadot/src/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,53 +14,9 @@
// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.

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<I>(PhantomData<I>);
impl<I> ConversionFromAssetBalance<Balance, VersionedLocatableAsset, Balance>
for NativeOnSystemParachain<I>
where
I: ConversionFromAssetBalance<Balance, VersionedLocatableAsset, Balance>,
{
type Error = ();
fn from_asset_balance(
balance: Balance,
asset_kind: VersionedLocatableAsset,
) -> Result<Balance, Self::Error> {
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::<ParaId>::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},
Expand Down
25 changes: 20 additions & 5 deletions relay/polkadot/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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},
Expand Down Expand Up @@ -826,7 +828,7 @@ impl pallet_treasury::Config for Runtime {
LocatableAssetConverter,
VersionedLocationConverter,
>;
type BalanceConverter = impls::NativeOnSystemParachain<AssetRate>;
type BalanceConverter = AssetRateWithNative;
type PayoutPeriod = PayoutSpendPeriod;
#[cfg(feature = "runtime-benchmarks")]
type BenchmarkHelper = polkadot_runtime_common::impls::benchmarks::TreasuryArguments;
Expand Down Expand Up @@ -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<ParaId>,
xcm_builder::IsParentsOnly<ConstU8<1>>,
>,
>,
AssetRate,
>;

impl pallet_asset_rate::Config for Runtime {
type WeightInfo = weights::pallet_asset_rate::WeightInfo<Runtime>;
type RuntimeEvent = RuntimeEvent;
Expand Down
Loading
Loading