From 8acac244af5edb21bfc5b555347c4e6593b375d4 Mon Sep 17 00:00:00 2001 From: muharem Date: Tue, 12 Mar 2024 12:53:11 +0100 Subject: [PATCH 01/10] unity balance conversion --- .../collectives-westend/src/fellowship/mod.rs | 16 ++++++++--- polkadot/runtime/common/src/impls.rs | 24 +++++++++++++++- polkadot/runtime/westend/src/lib.rs | 19 +++++++++---- polkadot/xcm/xcm-builder/src/barriers.rs | 21 ++++++++++++++ polkadot/xcm/xcm-builder/src/lib.rs | 4 +-- substrate/frame/support/src/traits/tokens.rs | 4 +-- .../frame/support/src/traits/tokens/misc.rs | 28 +++++++++++++++++++ 7 files changed, 101 insertions(+), 15 deletions(-) diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/fellowship/mod.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/fellowship/mod.rs index 3816d2ed848e..2549c54c95fa 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/fellowship/mod.rs +++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/fellowship/mod.rs @@ -24,10 +24,12 @@ use crate::{ AccountId, AssetRate, Balance, Balances, FellowshipReferenda, GovernanceLocation, Preimage, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, Scheduler, WestendTreasuryAccount, DAYS, }; +use cumulus_primitives_core::ParaId; use frame_support::{ parameter_types, traits::{ - EitherOf, EitherOfDiverse, MapSuccess, NeverEnsureOrigin, OriginTrait, TryWithMorphedArg, + tokens::UnityOrOuterConversion, EitherOf, EitherOfDiverse, MapSuccess, NeverEnsureOrigin, + OriginTrait, TryWithMorphedArg, }, PalletId, }; @@ -40,10 +42,10 @@ use pallet_ranked_collective::EnsureOfRank; use pallet_xcm::{EnsureXcm, IsVoiceOfBody}; use parachains_common::impls::ToParentTreasury; use polkadot_runtime_common::impls::{ - LocatableAssetConverter, VersionedLocatableAsset, VersionedLocationConverter, + ContainsLatest, LocatableAssetConverter, VersionedLocatableAsset, VersionedLocationConverter, }; use sp_arithmetic::Permill; -use sp_core::{ConstU128, ConstU32}; +use sp_core::{ConstU128, ConstU32, ConstU8}; use sp_runtime::traits::{ConstU16, ConvertToValue, IdentityLookup, Replace, TakeFirst}; use testnet_parachains_constants::westend::{account, currency::GRAND}; use westend_runtime_constants::time::HOURS; @@ -345,7 +347,13 @@ impl pallet_treasury::Config for Runtime { type Paymaster = FellowshipTreasuryPaymaster; #[cfg(feature = "runtime-benchmarks")] type Paymaster = PayWithEnsure>>; - type BalanceConverter = AssetRate; + type BalanceConverter = UnityOrOuterConversion< + ContainsLatest< + xcm_builder::IsSiblingSystemParachain, + xcm_builder::IsParentsOnly>, + >, + AssetRate, + >; type PayoutPeriod = ConstU32<{ 30 * DAYS }>; #[cfg(feature = "runtime-benchmarks")] type BenchmarkHelper = polkadot_runtime_common::impls::benchmarks::TreasuryArguments< diff --git a/polkadot/runtime/common/src/impls.rs b/polkadot/runtime/common/src/impls.rs index 4ba85a3c8353..0e5919d5347a 100644 --- a/polkadot/runtime/common/src/impls.rs +++ b/polkadot/runtime/common/src/impls.rs @@ -17,7 +17,8 @@ //! Auxiliary `struct`/`enum`s for polkadot runtime. use crate::NegativeImbalance; -use frame_support::traits::{Currency, Imbalance, OnUnbalanced}; +use core::marker::PhantomData; +use frame_support::traits::{Contains, Currency, Imbalance, OnUnbalanced}; use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; use primitives::Balance; use sp_runtime::{traits::TryConvert, Perquintill, RuntimeDebug}; @@ -150,6 +151,27 @@ impl TryConvert<&VersionedLocation, xcm::latest::Location> for VersionedLocation } } +/// Adapter for [`Contains`] trait to match [`VersionedLocatableAsset`] type converted to the latest +/// version of itself where it's location matched by `L` and it's asset id by `A` parameter types. +pub struct ContainsLatest(PhantomData<(L, A)>); +impl Contains for ContainsLatest +where + L: Contains, + A: Contains, +{ + fn contains(asset: &VersionedLocatableAsset) -> bool { + use VersionedLocatableAsset::*; + let (location, asset_id) = match asset.clone() { + V3 { location, asset_id } => match (location.try_into(), asset_id.try_into()) { + (Ok(l), Ok(a)) => (l, a), + _ => return false, + }, + V4 { location, asset_id } => (location, asset_id), + }; + L::contains(&location) && A::contains(&asset_id.0) + } +} + #[cfg(feature = "runtime-benchmarks")] pub mod benchmarks { use super::VersionedLocatableAsset; diff --git a/polkadot/runtime/westend/src/lib.rs b/polkadot/runtime/westend/src/lib.rs index 45bbd0260e5e..f424341699e2 100644 --- a/polkadot/runtime/westend/src/lib.rs +++ b/polkadot/runtime/westend/src/lib.rs @@ -31,9 +31,9 @@ use frame_support::{ genesis_builder_helper::{build_config, create_default_config}, parameter_types, traits::{ - fungible::HoldConsideration, ConstU32, Contains, EitherOf, EitherOfDiverse, EverythingBut, - InstanceFilter, KeyOwnerProofSystem, LinearStoragePrice, ProcessMessage, - ProcessMessageError, WithdrawReasons, + fungible::HoldConsideration, tokens::UnityOrOuterConversion, ConstU32, Contains, EitherOf, + EitherOfDiverse, EverythingBut, InstanceFilter, KeyOwnerProofSystem, LinearStoragePrice, + ProcessMessage, ProcessMessageError, WithdrawReasons, }, weights::{ConstantMultiplier, WeightMeter}, PalletId, @@ -59,7 +59,8 @@ use runtime_common::{ elections::OnChainAccuracy, identity_migrator, impl_runtime_weights, impls::{ - LocatableAssetConverter, ToAuthor, VersionedLocatableAsset, VersionedLocationConverter, + ContainsLatest, LocatableAssetConverter, ToAuthor, VersionedLocatableAsset, + VersionedLocationConverter, }, paras_registrar, paras_sudo_wrapper, prod_or_fast, slots, traits::Leaser, @@ -82,7 +83,7 @@ use runtime_parachains::{ shared as parachains_shared, }; use scale_info::TypeInfo; -use sp_core::{OpaqueMetadata, RuntimeDebug, H256}; +use sp_core::{ConstU8, OpaqueMetadata, RuntimeDebug, H256}; use sp_runtime::{ create_runtime_str, curve::PiecewiseLinear, @@ -761,7 +762,13 @@ impl pallet_treasury::Config for Runtime { LocatableAssetConverter, VersionedLocationConverter, >; - type BalanceConverter = AssetRate; + type BalanceConverter = UnityOrOuterConversion< + ContainsLatest< + xcm_builder::IsChildSystemParachain, + xcm_builder::IsParentsOnly>, + >, + AssetRate, + >; type PayoutPeriod = PayoutSpendPeriod; #[cfg(feature = "runtime-benchmarks")] type BenchmarkHelper = runtime_common::impls::benchmarks::TreasuryArguments; diff --git a/polkadot/xcm/xcm-builder/src/barriers.rs b/polkadot/xcm/xcm-builder/src/barriers.rs index 80411ab5a224..f92a9e6a1309 100644 --- a/polkadot/xcm/xcm-builder/src/barriers.rs +++ b/polkadot/xcm/xcm-builder/src/barriers.rs @@ -322,6 +322,27 @@ impl> Contains for IsChildSystemParachain } } +/// Matches if the given location is a system-level sibling parachain. +pub struct IsSiblingSystemParachain(PhantomData); +impl> Contains for IsSiblingSystemParachain { + fn contains(l: &Location) -> bool { + matches!( + l.interior().as_slice(), + [Junction::Parachain(id)] + if ParaId::from(*id).is_system() && l.parent_count() == 1, + ) + } +} + +/// Matches if the given location contains only the specified amount of parents and no interior +/// junctions. +pub struct IsParentsOnly(PhantomData); +impl> Contains for IsParentsOnly { + fn contains(t: &Location) -> bool { + t.contains_parents_only(Count::get()) + } +} + /// Allows only messages if the generic `ResponseHandler` expects them via `expecting_response`. pub struct AllowKnownQueryResponses(PhantomData); impl ShouldExecute for AllowKnownQueryResponses { diff --git a/polkadot/xcm/xcm-builder/src/lib.rs b/polkadot/xcm/xcm-builder/src/lib.rs index e2af8187136e..0b5a834e355e 100644 --- a/polkadot/xcm/xcm-builder/src/lib.rs +++ b/polkadot/xcm/xcm-builder/src/lib.rs @@ -37,8 +37,8 @@ mod barriers; pub use barriers::{ AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, DenyReserveTransferToRelayChain, - DenyThenTry, IsChildSystemParachain, RespectSuspension, TakeWeightCredit, TrailingSetTopicAsId, - WithComputedOrigin, + DenyThenTry, IsChildSystemParachain, IsParentsOnly, IsSiblingSystemParachain, + RespectSuspension, TakeWeightCredit, TrailingSetTopicAsId, WithComputedOrigin, }; mod controller; diff --git a/substrate/frame/support/src/traits/tokens.rs b/substrate/frame/support/src/traits/tokens.rs index 3635311e6435..8842b2058018 100644 --- a/substrate/frame/support/src/traits/tokens.rs +++ b/substrate/frame/support/src/traits/tokens.rs @@ -31,7 +31,7 @@ pub mod pay; pub use misc::{ AssetId, Balance, BalanceStatus, ConversionFromAssetBalance, ConversionToAssetBalance, ConvertRank, DepositConsequence, ExistenceRequirement, Fortitude, GetSalary, Locker, Precision, - Preservation, Provenance, Restriction, UnityAssetBalanceConversion, WithdrawConsequence, - WithdrawReasons, + Preservation, Provenance, Restriction, UnityAssetBalanceConversion, UnityOrOuterConversion, + WithdrawConsequence, WithdrawReasons, }; pub use pay::{Pay, PayFromAccount, PaymentStatus}; diff --git a/substrate/frame/support/src/traits/tokens/misc.rs b/substrate/frame/support/src/traits/tokens/misc.rs index fd497bc4eda6..97166d8ff1a3 100644 --- a/substrate/frame/support/src/traits/tokens/misc.rs +++ b/substrate/frame/support/src/traits/tokens/misc.rs @@ -17,6 +17,7 @@ //! Miscellaneous types. +use crate::traits::Contains; use codec::{Decode, Encode, FullCodec, MaxEncodedLen}; use sp_arithmetic::traits::{AtLeast32BitUnsigned, Zero}; use sp_core::RuntimeDebug; @@ -299,6 +300,33 @@ where fn ensure_successful(_: AssetId) {} } +/// Implements [`ConversionFromAssetBalance`], allowing for a 1:1 balance conversion of the asset +/// when it meets the conditions specified by `C`. If the conditions are not met, the conversion is +/// delegated to `O`. +pub struct UnityOrOuterConversion(core::marker::PhantomData<(C, O)>); +impl + ConversionFromAssetBalance for UnityOrOuterConversion +where + C: Contains, + O: ConversionFromAssetBalance, + AssetBalance: Into, +{ + type Error = O::Error; + fn from_asset_balance( + balance: AssetBalance, + asset_id: AssetId, + ) -> Result { + if C::contains(&asset_id) { + return Ok(balance.into()); + } + O::from_asset_balance(balance, asset_id) + } + #[cfg(feature = "runtime-benchmarks")] + fn ensure_successful(asset_id: AssetId) { + O::from_asset_balance(balance, asset_id) + } +} + /// Trait to handle NFT locking mechanism to ensure interactions with the asset can be implemented /// downstream to extend logic of Uniques/Nfts current functionality. pub trait Locker { From f7217a5b9ce5f79a4e568f03e5c3f14d6fb335a2 Mon Sep 17 00:00:00 2001 From: muharem Date: Tue, 12 Mar 2024 13:10:54 +0100 Subject: [PATCH 02/10] fix --- substrate/frame/support/src/traits/tokens/misc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/frame/support/src/traits/tokens/misc.rs b/substrate/frame/support/src/traits/tokens/misc.rs index 97166d8ff1a3..208ff1c4d228 100644 --- a/substrate/frame/support/src/traits/tokens/misc.rs +++ b/substrate/frame/support/src/traits/tokens/misc.rs @@ -323,7 +323,7 @@ where } #[cfg(feature = "runtime-benchmarks")] fn ensure_successful(asset_id: AssetId) { - O::from_asset_balance(balance, asset_id) + O::ensure_successful(asset_id) } } From 870c2ecf6b32ca039336f10a95052c3c3609cbdc Mon Sep 17 00:00:00 2001 From: muharem Date: Wed, 13 Mar 2024 11:47:38 +0100 Subject: [PATCH 03/10] tests --- Cargo.lock | 34 +++ Cargo.toml | 1 + .../emulated/chains/relays/rococo/src/lib.rs | 2 + .../tests/assets/asset-hub-rococo/Cargo.toml | 4 + .../assets/asset-hub-rococo/src/tests/mod.rs | 1 + .../asset-hub-rococo/src/tests/treasury.rs | 269 ++++++++++++++++++ .../collectives-westend/Cargo.toml | 43 +++ .../collectives-westend/src/lib.rs | 77 +++++ .../src/tests/fellowship_treasury.rs | 233 +++++++++++++++ .../collectives-westend/src/tests/mod.rs | 16 ++ polkadot/runtime/rococo/src/lib.rs | 19 +- 11 files changed, 693 insertions(+), 6 deletions(-) create mode 100644 cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/treasury.rs create mode 100644 cumulus/parachains/integration-tests/emulated/tests/collectives/collectives-westend/Cargo.toml create mode 100644 cumulus/parachains/integration-tests/emulated/tests/collectives/collectives-westend/src/lib.rs create mode 100644 cumulus/parachains/integration-tests/emulated/tests/collectives/collectives-westend/src/tests/fellowship_treasury.rs create mode 100644 cumulus/parachains/integration-tests/emulated/tests/collectives/collectives-westend/src/tests/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 5eab3cf7c24f..e486657c8a63 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -838,10 +838,14 @@ dependencies = [ "pallet-assets", "pallet-balances", "pallet-message-queue", + "pallet-treasury", + "pallet-utility", "pallet-xcm", "parachains-common", "parity-scale-codec", + "polkadot-runtime-common", "rococo-runtime", + "rococo-runtime-constants", "rococo-system-emulated-network", "sp-runtime", "staging-xcm", @@ -2711,6 +2715,36 @@ dependencies = [ "testnet-parachains-constants", ] +[[package]] +name = "collectives-westend-integration-tests" +version = "1.0.0" +dependencies = [ + "assert_matches", + "asset-hub-westend-runtime", + "collectives-westend-runtime", + "cumulus-pallet-parachain-system", + "cumulus-pallet-xcmp-queue", + "emulated-integration-tests-common", + "frame-support", + "pallet-asset-rate", + "pallet-assets", + "pallet-balances", + "pallet-message-queue", + "pallet-treasury", + "pallet-utility", + "pallet-xcm", + "parachains-common", + "parity-scale-codec", + "polkadot-runtime-common", + "sp-runtime", + "staging-xcm", + "staging-xcm-executor", + "testnet-parachains-constants", + "westend-runtime", + "westend-runtime-constants", + "westend-system-emulated-network", +] + [[package]] name = "collectives-westend-runtime" version = "3.0.0" diff --git a/Cargo.toml b/Cargo.toml index f256d02808a8..b533b229ffe4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -94,6 +94,7 @@ members = [ "cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend", "cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo", "cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend", + "cumulus/parachains/integration-tests/emulated/tests/collectives/collectives-westend", "cumulus/parachains/integration-tests/emulated/tests/people/people-rococo", "cumulus/parachains/integration-tests/emulated/tests/people/people-westend", "cumulus/parachains/pallets/collective-content", diff --git a/cumulus/parachains/integration-tests/emulated/chains/relays/rococo/src/lib.rs b/cumulus/parachains/integration-tests/emulated/chains/relays/rococo/src/lib.rs index e0d37302120f..591423aadad0 100644 --- a/cumulus/parachains/integration-tests/emulated/chains/relays/rococo/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/chains/relays/rococo/src/lib.rs @@ -39,6 +39,8 @@ decl_test_relay_chains! { Hrmp: rococo_runtime::Hrmp, Identity: rococo_runtime::Identity, IdentityMigrator: rococo_runtime::IdentityMigrator, + Treasury: rococo_runtime::Treasury, + AssetRate: rococo_runtime::AssetRate, } }, } diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/Cargo.toml b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/Cargo.toml index 0a397c2617b4..11109487c931 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/Cargo.toml @@ -21,12 +21,16 @@ pallet-balances = { path = "../../../../../../../substrate/frame/balances", defa pallet-assets = { path = "../../../../../../../substrate/frame/assets", default-features = false } pallet-asset-conversion = { path = "../../../../../../../substrate/frame/asset-conversion", default-features = false } pallet-message-queue = { path = "../../../../../../../substrate/frame/message-queue", default-features = false } +pallet-treasury = { path = "../../../../../../../substrate/frame/treasury", default-features = false } +pallet-utility = { path = "../../../../../../../substrate/frame/utility", default-features = false } # Polkadot xcm = { package = "staging-xcm", path = "../../../../../../../polkadot/xcm", default-features = false } pallet-xcm = { path = "../../../../../../../polkadot/xcm/pallet-xcm", default-features = false } xcm-executor = { package = "staging-xcm-executor", path = "../../../../../../../polkadot/xcm/xcm-executor", default-features = false } rococo-runtime = { path = "../../../../../../../polkadot/runtime/rococo" } +polkadot-runtime-common = { path = "../../../../../../../polkadot/runtime/common" } +rococo-runtime-constants = { path = "../../../../../../../polkadot/runtime/rococo/constants" } # Cumulus asset-test-utils = { path = "../../../../../runtimes/assets/test-utils" } diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/mod.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/mod.rs index 21bed234304e..67c0a9a87949 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/mod.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/mod.rs @@ -18,6 +18,7 @@ mod send; mod set_xcm_versions; mod swap; mod teleport; +mod treasury; use crate::*; emulated_integration_tests_common::include_penpal_create_foreign_asset_on_asset_hub!( diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/treasury.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/treasury.rs new file mode 100644 index 000000000000..29b9c9eaf946 --- /dev/null +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/treasury.rs @@ -0,0 +1,269 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::*; +use emulated_integration_tests_common::accounts::{ALICE, BOB}; +use frame_support::{ + dispatch::RawOrigin, + sp_runtime::traits::Dispatchable, + traits::{ + fungible::Inspect, + fungibles::{Create, Inspect as FungiblesInspect, Mutate}, + }, +}; +use polkadot_runtime_common::impls::VersionedLocatableAsset; +use rococo_runtime::OriginCaller; +use rococo_runtime_constants::currency::GRAND; +use xcm_executor::traits::ConvertLocation; + +// Fund Treasury account on Asset Hub from Treasury account on Relay Chain with ROCs. +#[test] +fn spend_roc_on_asset_hub() { + // initial treasury balance on Asset Hub in ROCs. + let treasury_balance = 9_000 * GRAND; + // the balance spend on Asset Hub. + let treasury_spend_balance = 1_000 * GRAND; + + let init_alice_balance = AssetHubRococo::execute_with(|| { + <::Balances as Inspect<_>>::balance( + &Rococo::account_id_of(ALICE), + ) + }); + + Rococo::execute_with(|| { + type RuntimeEvent = ::RuntimeEvent; + type RuntimeCall = ::RuntimeCall; + type Runtime = ::Runtime; + type Balances = ::Balances; + type Treasury = ::Treasury; + + // Fund Treasury account on Asset Hub with ROCs. + + let root = ::RuntimeOrigin::root(); + let treasury_account = Treasury::account_id(); + + // Mist assets to Treasury account on Relay Chain. + assert_ok!(Balances::force_set_balance( + root.clone(), + treasury_account.clone().into(), + treasury_balance * 2, + )); + + let native_asset = Location::here(); + let asset_hub_location: Location = [Parachain(1000)].into(); + let treasury_location_on_asset_hub: Location = (Parent, PalletInstance(18)).into(); + + let teleport_call = RuntimeCall::Utility(pallet_utility::Call::::dispatch_as { + as_origin: bx!(OriginCaller::system(RawOrigin::Signed(treasury_account))), + call: bx!(RuntimeCall::XcmPallet(pallet_xcm::Call::::teleport_assets { + dest: bx!(VersionedLocation::V4(asset_hub_location.clone())), + beneficiary: bx!(VersionedLocation::V4(treasury_location_on_asset_hub)), + assets: bx!(VersionedAssets::V4( + Asset { id: native_asset.clone().into(), fun: treasury_balance.into() }.into() + )), + fee_asset_item: 0, + })), + }); + + // Dispatched from Root to `despatch_as` `Signed(treasury_account)`. + assert_ok!(teleport_call.dispatch(root)); + + assert_expected_events!( + Rococo, + vec![ + RuntimeEvent::XcmPallet(pallet_xcm::Event::Sent { .. }) => {}, + ] + ); + }); + + Rococo::execute_with(|| { + type RuntimeEvent = ::RuntimeEvent; + type RuntimeCall = ::RuntimeCall; + type RuntimeOrigin = ::RuntimeOrigin; + type Runtime = ::Runtime; + type Treasury = ::Treasury; + + // Fund Alice account from Rococo Treasury account on Asset Hub. + + let treasury_origin: RuntimeOrigin = + rococo_runtime::governance::pallet_custom_origins::Origin::Treasurer.into(); + + let alice_location: Location = + [Junction::AccountId32 { network: None, id: Rococo::account_id_of(ALICE).into() }] + .into(); + let asset_hub_location: Location = [Parachain(1000)].into(); + let native_asset_on_asset_hub = Location::parent(); + + let treasury_spend_call = RuntimeCall::Treasury(pallet_treasury::Call::::spend { + asset_kind: bx!(VersionedLocatableAsset::V4 { + location: asset_hub_location.clone(), + asset_id: native_asset_on_asset_hub.into(), + }), + amount: treasury_spend_balance, + beneficiary: bx!(VersionedLocation::V4(alice_location)), + valid_from: None, + }); + + assert_ok!(treasury_spend_call.dispatch(treasury_origin)); + + // Claim the spend. + + let bob_signed = RuntimeOrigin::signed(Rococo::account_id_of(BOB)); + assert_ok!(Treasury::payout(bob_signed.clone(), 0)); + + assert_expected_events!( + Rococo, + vec![ + RuntimeEvent::Treasury(pallet_treasury::Event::AssetSpendApproved { .. }) => {}, + RuntimeEvent::Treasury(pallet_treasury::Event::Paid { .. }) => {}, + ] + ); + }); + + AssetHubRococo::execute_with(|| { + type RuntimeEvent = ::RuntimeEvent; + type Balances = ::Balances; + + // Ensure that the funds deposited to Alice account. + + let alice_account = Rococo::account_id_of(ALICE); + assert_eq!( + >::balance(&alice_account), + treasury_spend_balance + init_alice_balance + ); + + // Assert events triggered by xcm pay program: + // 1. treasury asset transferred to spend beneficiary; + // 2. response to Relay Chain Treasury pallet instance sent back; + // 3. XCM program completed; + assert_expected_events!( + AssetHubRococo, + vec![ + RuntimeEvent::Balances(pallet_balances::Event::Transfer { .. }) => {}, + RuntimeEvent::ParachainSystem(cumulus_pallet_parachain_system::Event::UpwardMessageSent { .. }) => {}, + RuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true ,.. }) => {}, + ] + ); + }); +} + +#[test] +fn create_and_claim_treasury_spend_in_usdt() { + const ASSET_ID: u32 = 1984; + const SPEND_AMOUNT: u128 = 1_000_000; + // treasury location from a sibling parachain. + let treasury_location: Location = Location::new(1, PalletInstance(18)); + // treasury account on a sibling parachain. + let treasury_account = + asset_hub_rococo_runtime::xcm_config::LocationToAccountId::convert_location( + &treasury_location, + ) + .unwrap(); + let asset_hub_location = + v3::Location::new(0, v3::Junction::Parachain(AssetHubRococo::para_id().into())); + let root = ::RuntimeOrigin::root(); + // asset kind to be spend from the treasury. + let asset_kind = VersionedLocatableAsset::V3 { + location: asset_hub_location, + asset_id: v3::AssetId::Concrete( + (v3::Junction::PalletInstance(50), v3::Junction::GeneralIndex(ASSET_ID.into())).into(), + ), + }; + // treasury spend beneficiary. + let alice: AccountId = Rococo::account_id_of(ALICE); + let bob: AccountId = Rococo::account_id_of(BOB); + let bob_signed = ::RuntimeOrigin::signed(bob.clone()); + + AssetHubRococo::execute_with(|| { + type Assets = ::Assets; + + // create an asset class and mint some assets to the treasury account. + assert_ok!(>::create( + ASSET_ID, + treasury_account.clone(), + true, + SPEND_AMOUNT / 2 + )); + assert_ok!(>::mint_into(ASSET_ID, &treasury_account, SPEND_AMOUNT * 4)); + // beneficiary has zero balance. + assert_eq!(>::balance(ASSET_ID, &alice,), 0u128,); + }); + + Rococo::execute_with(|| { + type RuntimeEvent = ::RuntimeEvent; + type Treasury = ::Treasury; + type AssetRate = ::AssetRate; + + // create a conversion rate from `asset_kind` to the native currency. + assert_ok!(AssetRate::create(root.clone(), Box::new(asset_kind.clone()), 2.into())); + + // create and approve a treasury spend. + assert_ok!(Treasury::spend( + root, + Box::new(asset_kind), + SPEND_AMOUNT, + Box::new(Location::new(0, Into::<[u8; 32]>::into(alice.clone())).into()), + None, + )); + // claim the spend. + assert_ok!(Treasury::payout(bob_signed.clone(), 0)); + + assert_expected_events!( + Rococo, + vec![ + RuntimeEvent::Treasury(pallet_treasury::Event::Paid { .. }) => {}, + ] + ); + }); + + AssetHubRococo::execute_with(|| { + type RuntimeEvent = ::RuntimeEvent; + type Assets = ::Assets; + + // assert events triggered by xcm pay program + // 1. treasury asset transferred to spend beneficiary + // 2. response to Relay Chain treasury pallet instance sent back + // 3. XCM program completed + assert_expected_events!( + AssetHubRococo, + vec![ + RuntimeEvent::Assets(pallet_assets::Event::Transferred { asset_id: id, from, to, amount }) => { + id: id == &ASSET_ID, + from: from == &treasury_account, + to: to == &alice, + amount: amount == &SPEND_AMOUNT, + }, + RuntimeEvent::ParachainSystem(cumulus_pallet_parachain_system::Event::UpwardMessageSent { .. }) => {}, + RuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true ,.. }) => {}, + ] + ); + // beneficiary received the assets from the treasury. + assert_eq!(>::balance(ASSET_ID, &alice,), SPEND_AMOUNT,); + }); + + Rococo::execute_with(|| { + type RuntimeEvent = ::RuntimeEvent; + type Treasury = ::Treasury; + + // check the payment status to ensure the response from the AssetHub was received. + assert_ok!(Treasury::check_status(bob_signed, 0)); + assert_expected_events!( + Rococo, + vec![ + RuntimeEvent::Treasury(pallet_treasury::Event::SpendProcessed { .. }) => {}, + ] + ); + }); +} diff --git a/cumulus/parachains/integration-tests/emulated/tests/collectives/collectives-westend/Cargo.toml b/cumulus/parachains/integration-tests/emulated/tests/collectives/collectives-westend/Cargo.toml new file mode 100644 index 000000000000..d1dbef9fc415 --- /dev/null +++ b/cumulus/parachains/integration-tests/emulated/tests/collectives/collectives-westend/Cargo.toml @@ -0,0 +1,43 @@ +[package] +name = "collectives-westend-integration-tests" +version = "1.0.0" +authors.workspace = true +edition.workspace = true +license = "Apache-2.0" +description = "Collectives Westend runtime integration tests with xcm-emulator" +publish = false + +[lints] +workspace = true + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.4.0", default-features = false } +assert_matches = "1.5.0" + +# Substrate +sp-runtime = { path = "../../../../../../../substrate/primitives/runtime", default-features = false } +frame-support = { path = "../../../../../../../substrate/frame/support", default-features = false } +pallet-balances = { path = "../../../../../../../substrate/frame/balances", default-features = false } +pallet-asset-rate = { path = "../../../../../../../substrate/frame/asset-rate", default-features = false } +pallet-assets = { path = "../../../../../../../substrate/frame/assets", default-features = false } +pallet-treasury = { path = "../../../../../../../substrate/frame/treasury", default-features = false } +pallet-message-queue = { path = "../../../../../../../substrate/frame/message-queue", default-features = false } +pallet-utility = { path = "../../../../../../../substrate/frame/utility", default-features = false } + +# Polkadot +polkadot-runtime-common = { path = "../../../../../../../polkadot/runtime/common" } +xcm = { package = "staging-xcm", path = "../../../../../../../polkadot/xcm", default-features = false } +xcm-executor = { package = "staging-xcm-executor", path = "../../../../../../../polkadot/xcm/xcm-executor", default-features = false } +pallet-xcm = { path = "../../../../../../../polkadot/xcm/pallet-xcm", default-features = false } +westend-runtime = { path = "../../../../../../../polkadot/runtime/westend" } +westend-runtime-constants = { path = "../../../../../../../polkadot/runtime/westend/constants" } + +# Cumulus +parachains-common = { path = "../../../../../../parachains/common" } +testnet-parachains-constants = { path = "../../../../../runtimes/constants", features = ["westend"] } +asset-hub-westend-runtime = { path = "../../../../../runtimes/assets/asset-hub-westend" } +collectives-westend-runtime = { path = "../../../../../runtimes/collectives/collectives-westend" } +cumulus-pallet-xcmp-queue = { default-features = false, path = "../../../../../../pallets/xcmp-queue" } +cumulus-pallet-parachain-system = { default-features = false, path = "../../../../../../pallets/parachain-system" } +emulated-integration-tests-common = { path = "../../../common", default-features = false } +westend-system-emulated-network = { path = "../../../networks/westend-system" } diff --git a/cumulus/parachains/integration-tests/emulated/tests/collectives/collectives-westend/src/lib.rs b/cumulus/parachains/integration-tests/emulated/tests/collectives/collectives-westend/src/lib.rs new file mode 100644 index 000000000000..b5ee284679fe --- /dev/null +++ b/cumulus/parachains/integration-tests/emulated/tests/collectives/collectives-westend/src/lib.rs @@ -0,0 +1,77 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +pub use codec::Encode; + +// Substrate +pub use frame_support::{ + assert_err, assert_ok, + instances::Instance1, + pallet_prelude::Weight, + sp_runtime::{AccountId32, DispatchError, DispatchResult, ModuleError}, + traits::fungibles::Inspect, + BoundedVec, +}; + +// Westend +pub use xcm::{ + prelude::{AccountId32 as AccountId32Junction, *}, + v3::{self, Error, NetworkId::Westend as WestendId}, +}; + +// Cumulus +pub use emulated_integration_tests_common::{ + xcm_emulator::{ + assert_expected_events, bx, helpers::weight_within_threshold, Chain, Parachain as Para, + RelayChain as Relay, Test, TestArgs, TestContext, TestExt, + }, + xcm_helpers::{xcm_transact_paid_execution, xcm_transact_unpaid_execution}, + PROOF_SIZE_THRESHOLD, REF_TIME_THRESHOLD, XCM_V3, +}; +pub use parachains_common::{AccountId, Balance}; +pub use westend_system_emulated_network::{ + asset_hub_westend_emulated_chain::{ + genesis::ED as ASSET_HUB_POLKADOT_ED, AssetHubWestendParaPallet as AssetHubWestendPallet, + }, + collectives_westend_emulated_chain::{ + genesis::ED as COLLECTIVES_POLKADOT_ED, + CollectivesWestendParaPallet as CollectivesWestendPallet, + }, + penpal_emulated_chain::PenpalBParaPallet as PenpalBPallet, + westend_emulated_chain::{genesis::ED as POLKADOT_ED, WestendRelayPallet as WestendPallet}, + AssetHubWestendPara as AssetHubWestend, AssetHubWestendParaReceiver as AssetHubWestendReceiver, + AssetHubWestendParaSender as AssetHubWestendSender, BridgeHubWestendPara as BridgeHubWestend, + BridgeHubWestendParaReceiver as BridgeHubWestendReceiver, + CollectivesWestendPara as CollectivesWestend, PenpalAPara as PenpalA, + PenpalAParaReceiver as PenpalAReceiver, PenpalAParaSender as PenpalASender, + PenpalBPara as PenpalB, PenpalBParaReceiver as PenpalBReceiver, + PenpalBParaSender as PenpalBSender, WestendRelay as Westend, + WestendRelayReceiver as WestendReceiver, WestendRelaySender as WestendSender, +}; + +pub const ASSET_ID: u32 = 1; +pub const ASSET_MIN_BALANCE: u128 = 1000; +// `Assets` pallet index +pub const ASSETS_PALLET_ID: u8 = 50; + +pub type RelayToSystemParaTest = Test; +pub type RelayToParaTest = Test; +pub type SystemParaToRelayTest = Test; +pub type SystemParaToParaTest = Test; +pub type ParaToSystemParaTest = Test; +pub type ParaToParaTest = Test; + +#[cfg(test)] +mod tests; diff --git a/cumulus/parachains/integration-tests/emulated/tests/collectives/collectives-westend/src/tests/fellowship_treasury.rs b/cumulus/parachains/integration-tests/emulated/tests/collectives/collectives-westend/src/tests/fellowship_treasury.rs new file mode 100644 index 000000000000..cd1aa3d7f916 --- /dev/null +++ b/cumulus/parachains/integration-tests/emulated/tests/collectives/collectives-westend/src/tests/fellowship_treasury.rs @@ -0,0 +1,233 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::*; +use asset_hub_westend_runtime::xcm_config::LocationToAccountId as AssetHubLocationToAccountId; +use emulated_integration_tests_common::accounts::ALICE; +use frame_support::{ + dispatch::RawOrigin, sp_runtime::traits::Dispatchable, traits::fungible::Inspect, +}; +use polkadot_runtime_common::impls::VersionedLocatableAsset; +use westend_runtime::OriginCaller; +use westend_runtime_constants::currency::UNITS; +use xcm_executor::traits::ConvertLocation; + +// Fund Fellowship Treasury from Westend Treasury and spend from Fellowship Treasury. +#[test] +fn fellowship_treasury_spend() { + // initial treasury balance on Asset Hub in WNDs. + let treasury_balance = 20_000_000 * UNITS; + // target fellowship balance on Asset Hub in WNDs. + let fellowship_treasury_balance = 1_000_000 * UNITS; + // fellowship first spend balance in WNDs. + let fellowship_spend_balance = 10_000 * UNITS; + + let init_alice_balance = AssetHubWestend::execute_with(|| { + <::Balances as Inspect<_>>::balance( + &Westend::account_id_of(ALICE), + ) + }); + + Westend::execute_with(|| { + type RuntimeEvent = ::RuntimeEvent; + type RuntimeCall = ::RuntimeCall; + type Runtime = ::Runtime; + type Balances = ::Balances; + type Treasury = ::Treasury; + + // Fund Treasury account on Asset Hub with WNDs. + + let root = ::RuntimeOrigin::root(); + let treasury_account = Treasury::account_id(); + + // Mist assets to Treasury account on Relay Chain. + assert_ok!(Balances::force_set_balance( + root.clone(), + treasury_account.clone().into(), + treasury_balance * 2, + )); + + let native_asset = Location::here(); + let asset_hub_location: Location = [Parachain(1000)].into(); + let treasury_location_on_asset_hub: Location = (Parent, PalletInstance(37)).into(); + + let teleport_call = RuntimeCall::Utility(pallet_utility::Call::::dispatch_as { + as_origin: bx!(OriginCaller::system(RawOrigin::Signed(treasury_account))), + call: bx!(RuntimeCall::XcmPallet(pallet_xcm::Call::::teleport_assets { + dest: bx!(VersionedLocation::V4(asset_hub_location.clone())), + beneficiary: bx!(VersionedLocation::V4(treasury_location_on_asset_hub)), + assets: bx!(VersionedAssets::V4( + Asset { id: native_asset.clone().into(), fun: treasury_balance.into() }.into() + )), + fee_asset_item: 0, + })), + }); + + // Dispatched from Root to `despatch_as` `Signed(treasury_account)`. + assert_ok!(teleport_call.dispatch(root)); + + assert_expected_events!( + Westend, + vec![ + RuntimeEvent::XcmPallet(pallet_xcm::Event::Sent { .. }) => {}, + ] + ); + }); + + Westend::execute_with(|| { + type RuntimeEvent = ::RuntimeEvent; + type RuntimeCall = ::RuntimeCall; + type RuntimeOrigin = ::RuntimeOrigin; + type Runtime = ::Runtime; + type Treasury = ::Treasury; + + // Fund Fellowship Treasury from Westend Treasury. + + let treasury_origin: RuntimeOrigin = + westend_runtime::governance::pallet_custom_origins::Origin::Treasurer.into(); + let fellowship_treasury_location: Location = + Location::new(1, [Parachain(1001), PalletInstance(65)]); + let asset_hub_location: Location = [Parachain(1000)].into(); + let native_asset_on_asset_hub = Location::parent(); + + let treasury_spend_call = RuntimeCall::Treasury(pallet_treasury::Call::::spend { + asset_kind: bx!(VersionedLocatableAsset::V4 { + location: asset_hub_location.clone(), + asset_id: native_asset_on_asset_hub.into(), + }), + amount: fellowship_treasury_balance, + beneficiary: bx!(VersionedLocation::V4(fellowship_treasury_location)), + valid_from: None, + }); + + assert_ok!(treasury_spend_call.dispatch(treasury_origin)); + + // Claim the spend. + + let alice_signed = RuntimeOrigin::signed(Westend::account_id_of(ALICE)); + assert_ok!(Treasury::payout(alice_signed.clone(), 0)); + + assert_expected_events!( + Westend, + vec![ + RuntimeEvent::Treasury(pallet_treasury::Event::AssetSpendApproved { .. }) => {}, + RuntimeEvent::Treasury(pallet_treasury::Event::Paid { .. }) => {}, + ] + ); + }); + + AssetHubWestend::execute_with(|| { + type RuntimeEvent = ::RuntimeEvent; + type Balances = ::Balances; + + // Ensure that the funds deposited to the Fellowship Treasury account. + + let fellowship_treasury_location: Location = + Location::new(1, [Parachain(1001), PalletInstance(65)]); + let fellowship_treasury_account = + AssetHubLocationToAccountId::convert_location(&fellowship_treasury_location).unwrap(); + + assert_eq!( + >::balance(&fellowship_treasury_account), + fellowship_treasury_balance + ); + + // Assert events triggered by xcm pay program: + // 1. treasury asset transferred to spend beneficiary; + // 2. response to Relay Chain Treasury pallet instance sent back; + // 3. XCM program completed; + assert_expected_events!( + AssetHubWestend, + vec![ + RuntimeEvent::Balances(pallet_balances::Event::Transfer { .. }) => {}, + RuntimeEvent::ParachainSystem(cumulus_pallet_parachain_system::Event::UpwardMessageSent { .. }) => {}, + RuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true ,.. }) => {}, + ] + ); + }); + + CollectivesWestend::execute_with(|| { + type RuntimeEvent = ::RuntimeEvent; + type RuntimeCall = ::RuntimeCall; + type RuntimeOrigin = ::RuntimeOrigin; + type Runtime = ::Runtime; + type FellowshipTreasury = + ::FellowshipTreasury; + + // Fund Alice account from Fellowship Treasury. + + let fellows_origin: RuntimeOrigin = + collectives_westend_runtime::fellowship::pallet_fellowship_origins::Origin::Fellows + .into(); + let asset_hub_location: Location = (Parent, Parachain(1000)).into(); + let native_asset_on_asset_hub = Location::parent(); + + let alice_location: Location = + [Junction::AccountId32 { network: None, id: Westend::account_id_of(ALICE).into() }] + .into(); + + let fellowship_treasury_spend_call = + RuntimeCall::FellowshipTreasury(pallet_treasury::Call::::spend { + asset_kind: bx!(VersionedLocatableAsset::V4 { + location: asset_hub_location, + asset_id: native_asset_on_asset_hub.into(), + }), + amount: fellowship_spend_balance, + beneficiary: bx!(VersionedLocation::V4(alice_location)), + valid_from: None, + }); + + assert_ok!(fellowship_treasury_spend_call.dispatch(fellows_origin)); + + // Claim the spend. + + let alice_signed = RuntimeOrigin::signed(Westend::account_id_of(ALICE)); + assert_ok!(FellowshipTreasury::payout(alice_signed.clone(), 0)); + + assert_expected_events!( + CollectivesWestend, + vec![ + RuntimeEvent::FellowshipTreasury(pallet_treasury::Event::AssetSpendApproved { .. }) => {}, + RuntimeEvent::FellowshipTreasury(pallet_treasury::Event::Paid { .. }) => {}, + ] + ); + }); + + AssetHubWestend::execute_with(|| { + type RuntimeEvent = ::RuntimeEvent; + type Balances = ::Balances; + + // Ensure that the funds deposited to Alice account. + + let alice_account = Westend::account_id_of(ALICE); + assert_eq!( + >::balance(&alice_account), + fellowship_spend_balance + init_alice_balance + ); + + // Assert events triggered by xcm pay program: + // 1. treasury asset transferred to spend beneficiary; + // 2. response to Relay Chain Treasury pallet instance sent back; + // 3. XCM program completed; + assert_expected_events!( + AssetHubWestend, + vec![ + RuntimeEvent::Balances(pallet_balances::Event::Transfer { .. }) => {}, + RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::XcmpMessageSent { .. }) => {}, + RuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true ,.. }) => {}, + ] + ); + }); +} diff --git a/cumulus/parachains/integration-tests/emulated/tests/collectives/collectives-westend/src/tests/mod.rs b/cumulus/parachains/integration-tests/emulated/tests/collectives/collectives-westend/src/tests/mod.rs new file mode 100644 index 000000000000..a9f65df34b64 --- /dev/null +++ b/cumulus/parachains/integration-tests/emulated/tests/collectives/collectives-westend/src/tests/mod.rs @@ -0,0 +1,16 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +mod fellowship_treasury; diff --git a/polkadot/runtime/rococo/src/lib.rs b/polkadot/runtime/rococo/src/lib.rs index ff54c7776701..fce6b24353e4 100644 --- a/polkadot/runtime/rococo/src/lib.rs +++ b/polkadot/runtime/rococo/src/lib.rs @@ -35,7 +35,8 @@ use rococo_runtime_constants::system_parachain::BROKER_ID; use runtime_common::{ assigned_slots, auctions, claims, crowdloan, identity_migrator, impl_runtime_weights, impls::{ - LocatableAssetConverter, ToAuthor, VersionedLocatableAsset, VersionedLocationConverter, + ContainsLatest, LocatableAssetConverter, ToAuthor, VersionedLocatableAsset, + VersionedLocationConverter, }, paras_registrar, paras_sudo_wrapper, prod_or_fast, slots, traits::Leaser, @@ -71,9 +72,9 @@ use frame_support::{ genesis_builder_helper::{build_config, create_default_config}, parameter_types, traits::{ - fungible::HoldConsideration, Contains, EitherOf, EitherOfDiverse, EverythingBut, - InstanceFilter, KeyOwnerProofSystem, LinearStoragePrice, PrivilegeCmp, ProcessMessage, - ProcessMessageError, StorageMapShim, WithdrawReasons, + fungible::HoldConsideration, tokens::UnityOrOuterConversion, Contains, EitherOf, + EitherOfDiverse, EverythingBut, InstanceFilter, KeyOwnerProofSystem, LinearStoragePrice, + PrivilegeCmp, ProcessMessage, ProcessMessageError, StorageMapShim, WithdrawReasons, }, weights::{ConstantMultiplier, WeightMeter}, PalletId, @@ -83,7 +84,7 @@ use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId}; use pallet_identity::legacy::IdentityInfo; use pallet_session::historical as session_historical; use pallet_transaction_payment::{CurrencyAdapter, FeeDetails, RuntimeDispatchInfo}; -use sp_core::{ConstU128, OpaqueMetadata, H256}; +use sp_core::{ConstU128, ConstU8, OpaqueMetadata, H256}; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, traits::{ @@ -501,7 +502,13 @@ impl pallet_treasury::Config for Runtime { LocatableAssetConverter, VersionedLocationConverter, >; - type BalanceConverter = AssetRate; + type BalanceConverter = UnityOrOuterConversion< + ContainsLatest< + xcm_builder::IsChildSystemParachain, + xcm_builder::IsParentsOnly>, + >, + AssetRate, + >; type PayoutPeriod = PayoutSpendPeriod; #[cfg(feature = "runtime-benchmarks")] type BenchmarkHelper = runtime_common::impls::benchmarks::TreasuryArguments; From 5d4bdb2e39cef8fb57b0151d18152ba51962caf3 Mon Sep 17 00:00:00 2001 From: muharem Date: Wed, 13 Mar 2024 11:53:42 +0100 Subject: [PATCH 04/10] prdoc --- prdoc/pr_3659.prdoc | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 prdoc/pr_3659.prdoc diff --git a/prdoc/pr_3659.prdoc b/prdoc/pr_3659.prdoc new file mode 100644 index 000000000000..393844d822d8 --- /dev/null +++ b/prdoc/pr_3659.prdoc @@ -0,0 +1,12 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Unity Balance Conversion for Different IDs of Native Asset + +doc: + - audience: Runtime Dev + description: | + Introduce types to define 1:1 balance conversion for different relative asset ids/locations + of native asset for `ConversionToAssetBalance` trait bounds. + +crates: [ ] \ No newline at end of file From 023d7783bb8641cb1735c8e6f0f7417aaaaf7e89 Mon Sep 17 00:00:00 2001 From: muharem Date: Mon, 18 Mar 2024 17:21:45 +0100 Subject: [PATCH 05/10] parachain is not sibling for itself --- .../collectives-westend/src/fellowship/mod.rs | 8 +++++--- polkadot/xcm/xcm-builder/src/barriers.rs | 12 +++++++----- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/fellowship/mod.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/fellowship/mod.rs index 2549c54c95fa..a8ddd3062316 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/fellowship/mod.rs +++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/fellowship/mod.rs @@ -21,8 +21,9 @@ mod tracks; use crate::{ weights, xcm_config::{FellowshipAdminBodyId, LocationToAccountId, TreasurerBodyId, UsdtAssetHub}, - AccountId, AssetRate, Balance, Balances, FellowshipReferenda, GovernanceLocation, Preimage, - Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, Scheduler, WestendTreasuryAccount, DAYS, + AccountId, AssetRate, Balance, Balances, FellowshipReferenda, GovernanceLocation, + ParachainInfo, Preimage, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, Scheduler, + WestendTreasuryAccount, DAYS, }; use cumulus_primitives_core::ParaId; use frame_support::{ @@ -265,6 +266,7 @@ parameter_types! { // The asset's interior location for the paying account. This is the Fellowship Treasury // pallet instance (which sits at index 65). pub FellowshipTreasuryInteriorLocation: InteriorLocation = PalletInstance(65).into(); + pub SelfParaId: ParaId = ParachainInfo::parachain_id(); } #[cfg(feature = "runtime-benchmarks")] @@ -349,7 +351,7 @@ impl pallet_treasury::Config for Runtime { type Paymaster = PayWithEnsure>>; type BalanceConverter = UnityOrOuterConversion< ContainsLatest< - xcm_builder::IsSiblingSystemParachain, + xcm_builder::IsSiblingSystemParachain, xcm_builder::IsParentsOnly>, >, AssetRate, diff --git a/polkadot/xcm/xcm-builder/src/barriers.rs b/polkadot/xcm/xcm-builder/src/barriers.rs index f92a9e6a1309..e8e0ba4fc5ab 100644 --- a/polkadot/xcm/xcm-builder/src/barriers.rs +++ b/polkadot/xcm/xcm-builder/src/barriers.rs @@ -323,13 +323,15 @@ impl> Contains for IsChildSystemParachain } /// Matches if the given location is a system-level sibling parachain. -pub struct IsSiblingSystemParachain(PhantomData); -impl> Contains for IsSiblingSystemParachain { +pub struct IsSiblingSystemParachain(PhantomData<(ParaId, SelfParaId)>); +impl + Eq, SelfParaId: Get> Contains + for IsSiblingSystemParachain +{ fn contains(l: &Location) -> bool { matches!( - l.interior().as_slice(), - [Junction::Parachain(id)] - if ParaId::from(*id).is_system() && l.parent_count() == 1, + l.unpack(), + (1, [Junction::Parachain(id)]) + if SelfParaId::get() != ParaId::from(*id) && ParaId::from(*id).is_system(), ) } } From 9d59fa370c979b522e4a583189260301d372e2c4 Mon Sep 17 00:00:00 2001 From: muharem Date: Wed, 20 Mar 2024 15:32:27 +0100 Subject: [PATCH 06/10] remove unused imports --- .../asset-hub-rococo/src/tests/treasury.rs | 14 ++--- .../collectives-westend/src/lib.rs | 63 +++---------------- .../src/tests/fellowship_treasury.rs | 31 ++++----- 3 files changed, 32 insertions(+), 76 deletions(-) diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/treasury.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/treasury.rs index a448618a36ee..01bf40ae8fdf 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/treasury.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/treasury.rs @@ -39,7 +39,7 @@ fn spend_roc_on_asset_hub() { let init_alice_balance = AssetHubRococo::execute_with(|| { <::Balances as Inspect<_>>::balance( - &Rococo::account_id_of(ALICE), + &AssetHubRococo::account_id_of(ALICE), ) }); @@ -55,7 +55,7 @@ fn spend_roc_on_asset_hub() { let root = ::RuntimeOrigin::root(); let treasury_account = Treasury::account_id(); - // Mist assets to Treasury account on Relay Chain. + // Mint assets to Treasury account on Relay Chain. assert_ok!(Balances::force_set_balance( root.clone(), treasury_account.clone().into(), @@ -64,13 +64,13 @@ fn spend_roc_on_asset_hub() { let native_asset = Location::here(); let asset_hub_location: Location = [Parachain(1000)].into(); - let treasury_location_on_asset_hub: Location = (Parent, PalletInstance(18)).into(); + let treasury_location: Location = (Parent, PalletInstance(18)).into(); let teleport_call = RuntimeCall::Utility(pallet_utility::Call::::dispatch_as { as_origin: bx!(OriginCaller::system(RawOrigin::Signed(treasury_account))), call: bx!(RuntimeCall::XcmPallet(pallet_xcm::Call::::teleport_assets { dest: bx!(VersionedLocation::V4(asset_hub_location.clone())), - beneficiary: bx!(VersionedLocation::V4(treasury_location_on_asset_hub)), + beneficiary: bx!(VersionedLocation::V4(treasury_location)), assets: bx!(VersionedAssets::V4( Asset { id: native_asset.clone().into(), fun: treasury_balance.into() }.into() )), @@ -105,12 +105,12 @@ fn spend_roc_on_asset_hub() { [Junction::AccountId32 { network: None, id: Rococo::account_id_of(ALICE).into() }] .into(); let asset_hub_location: Location = [Parachain(1000)].into(); - let native_asset_on_asset_hub = Location::parent(); + let native_asset = Location::parent(); let treasury_spend_call = RuntimeCall::Treasury(pallet_treasury::Call::::spend { asset_kind: bx!(VersionedLocatableAsset::V4 { location: asset_hub_location.clone(), - asset_id: native_asset_on_asset_hub.into(), + asset_id: native_asset.into(), }), amount: treasury_spend_balance, beneficiary: bx!(VersionedLocation::V4(alice_location)), @@ -139,7 +139,7 @@ fn spend_roc_on_asset_hub() { // Ensure that the funds deposited to Alice account. - let alice_account = Rococo::account_id_of(ALICE); + let alice_account = AssetHubRococo::account_id_of(ALICE); assert_eq!( >::balance(&alice_account), treasury_spend_balance + init_alice_balance diff --git a/cumulus/parachains/integration-tests/emulated/tests/collectives/collectives-westend/src/lib.rs b/cumulus/parachains/integration-tests/emulated/tests/collectives/collectives-westend/src/lib.rs index b5ee284679fe..97239330216a 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/collectives/collectives-westend/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/collectives/collectives-westend/src/lib.rs @@ -13,65 +13,18 @@ // See the License for the specific language governing permissions and // limitations under the License. -pub use codec::Encode; +pub use xcm::{prelude::*, v3}; -// Substrate -pub use frame_support::{ - assert_err, assert_ok, - instances::Instance1, - pallet_prelude::Weight, - sp_runtime::{AccountId32, DispatchError, DispatchResult, ModuleError}, - traits::fungibles::Inspect, - BoundedVec, +pub use emulated_integration_tests_common::xcm_emulator::{ + assert_expected_events, bx, Chain, RelayChain as Relay, TestExt, }; - -// Westend -pub use xcm::{ - prelude::{AccountId32 as AccountId32Junction, *}, - v3::{self, Error, NetworkId::Westend as WestendId}, -}; - -// Cumulus -pub use emulated_integration_tests_common::{ - xcm_emulator::{ - assert_expected_events, bx, helpers::weight_within_threshold, Chain, Parachain as Para, - RelayChain as Relay, Test, TestArgs, TestContext, TestExt, - }, - xcm_helpers::{xcm_transact_paid_execution, xcm_transact_unpaid_execution}, - PROOF_SIZE_THRESHOLD, REF_TIME_THRESHOLD, XCM_V3, -}; -pub use parachains_common::{AccountId, Balance}; pub use westend_system_emulated_network::{ - asset_hub_westend_emulated_chain::{ - genesis::ED as ASSET_HUB_POLKADOT_ED, AssetHubWestendParaPallet as AssetHubWestendPallet, - }, - collectives_westend_emulated_chain::{ - genesis::ED as COLLECTIVES_POLKADOT_ED, - CollectivesWestendParaPallet as CollectivesWestendPallet, - }, - penpal_emulated_chain::PenpalBParaPallet as PenpalBPallet, - westend_emulated_chain::{genesis::ED as POLKADOT_ED, WestendRelayPallet as WestendPallet}, - AssetHubWestendPara as AssetHubWestend, AssetHubWestendParaReceiver as AssetHubWestendReceiver, - AssetHubWestendParaSender as AssetHubWestendSender, BridgeHubWestendPara as BridgeHubWestend, - BridgeHubWestendParaReceiver as BridgeHubWestendReceiver, - CollectivesWestendPara as CollectivesWestend, PenpalAPara as PenpalA, - PenpalAParaReceiver as PenpalAReceiver, PenpalAParaSender as PenpalASender, - PenpalBPara as PenpalB, PenpalBParaReceiver as PenpalBReceiver, - PenpalBParaSender as PenpalBSender, WestendRelay as Westend, - WestendRelayReceiver as WestendReceiver, WestendRelaySender as WestendSender, + asset_hub_westend_emulated_chain::AssetHubWestendParaPallet as AssetHubWestendPallet, + collectives_westend_emulated_chain::CollectivesWestendParaPallet as CollectivesWestendPallet, + westend_emulated_chain::WestendRelayPallet as WestendPallet, + AssetHubWestendPara as AssetHubWestend, CollectivesWestendPara as CollectivesWestend, + WestendRelay as Westend, }; -pub const ASSET_ID: u32 = 1; -pub const ASSET_MIN_BALANCE: u128 = 1000; -// `Assets` pallet index -pub const ASSETS_PALLET_ID: u8 = 50; - -pub type RelayToSystemParaTest = Test; -pub type RelayToParaTest = Test; -pub type SystemParaToRelayTest = Test; -pub type SystemParaToParaTest = Test; -pub type ParaToSystemParaTest = Test; -pub type ParaToParaTest = Test; - #[cfg(test)] mod tests; diff --git a/cumulus/parachains/integration-tests/emulated/tests/collectives/collectives-westend/src/tests/fellowship_treasury.rs b/cumulus/parachains/integration-tests/emulated/tests/collectives/collectives-westend/src/tests/fellowship_treasury.rs index cd1aa3d7f916..bde1220e2495 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/collectives/collectives-westend/src/tests/fellowship_treasury.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/collectives/collectives-westend/src/tests/fellowship_treasury.rs @@ -17,7 +17,8 @@ use crate::*; use asset_hub_westend_runtime::xcm_config::LocationToAccountId as AssetHubLocationToAccountId; use emulated_integration_tests_common::accounts::ALICE; use frame_support::{ - dispatch::RawOrigin, sp_runtime::traits::Dispatchable, traits::fungible::Inspect, + assert_ok, dispatch::RawOrigin, instances::Instance1, sp_runtime::traits::Dispatchable, + traits::fungible::Inspect, }; use polkadot_runtime_common::impls::VersionedLocatableAsset; use westend_runtime::OriginCaller; @@ -36,7 +37,7 @@ fn fellowship_treasury_spend() { let init_alice_balance = AssetHubWestend::execute_with(|| { <::Balances as Inspect<_>>::balance( - &Westend::account_id_of(ALICE), + &AssetHubWestend::account_id_of(ALICE), ) }); @@ -61,13 +62,13 @@ fn fellowship_treasury_spend() { let native_asset = Location::here(); let asset_hub_location: Location = [Parachain(1000)].into(); - let treasury_location_on_asset_hub: Location = (Parent, PalletInstance(37)).into(); + let treasury_location: Location = (Parent, PalletInstance(37)).into(); let teleport_call = RuntimeCall::Utility(pallet_utility::Call::::dispatch_as { as_origin: bx!(OriginCaller::system(RawOrigin::Signed(treasury_account))), call: bx!(RuntimeCall::XcmPallet(pallet_xcm::Call::::teleport_assets { dest: bx!(VersionedLocation::V4(asset_hub_location.clone())), - beneficiary: bx!(VersionedLocation::V4(treasury_location_on_asset_hub)), + beneficiary: bx!(VersionedLocation::V4(treasury_location)), assets: bx!(VersionedAssets::V4( Asset { id: native_asset.clone().into(), fun: treasury_balance.into() }.into() )), @@ -75,7 +76,7 @@ fn fellowship_treasury_spend() { })), }); - // Dispatched from Root to `despatch_as` `Signed(treasury_account)`. + // Dispatched from Root to `dispatch_as` `Signed(treasury_account)`. assert_ok!(teleport_call.dispatch(root)); assert_expected_events!( @@ -100,12 +101,12 @@ fn fellowship_treasury_spend() { let fellowship_treasury_location: Location = Location::new(1, [Parachain(1001), PalletInstance(65)]); let asset_hub_location: Location = [Parachain(1000)].into(); - let native_asset_on_asset_hub = Location::parent(); + let native_asset = Location::parent(); let treasury_spend_call = RuntimeCall::Treasury(pallet_treasury::Call::::spend { asset_kind: bx!(VersionedLocatableAsset::V4 { location: asset_hub_location.clone(), - asset_id: native_asset_on_asset_hub.into(), + asset_id: native_asset.into(), }), amount: fellowship_treasury_balance, beneficiary: bx!(VersionedLocation::V4(fellowship_treasury_location)), @@ -172,17 +173,19 @@ fn fellowship_treasury_spend() { collectives_westend_runtime::fellowship::pallet_fellowship_origins::Origin::Fellows .into(); let asset_hub_location: Location = (Parent, Parachain(1000)).into(); - let native_asset_on_asset_hub = Location::parent(); + let native_asset = Location::parent(); - let alice_location: Location = - [Junction::AccountId32 { network: None, id: Westend::account_id_of(ALICE).into() }] - .into(); + let alice_location: Location = [Junction::AccountId32 { + network: None, + id: CollectivesWestend::account_id_of(ALICE).into(), + }] + .into(); let fellowship_treasury_spend_call = RuntimeCall::FellowshipTreasury(pallet_treasury::Call::::spend { asset_kind: bx!(VersionedLocatableAsset::V4 { location: asset_hub_location, - asset_id: native_asset_on_asset_hub.into(), + asset_id: native_asset.into(), }), amount: fellowship_spend_balance, beneficiary: bx!(VersionedLocation::V4(alice_location)), @@ -193,7 +196,7 @@ fn fellowship_treasury_spend() { // Claim the spend. - let alice_signed = RuntimeOrigin::signed(Westend::account_id_of(ALICE)); + let alice_signed = RuntimeOrigin::signed(CollectivesWestend::account_id_of(ALICE)); assert_ok!(FellowshipTreasury::payout(alice_signed.clone(), 0)); assert_expected_events!( @@ -211,7 +214,7 @@ fn fellowship_treasury_spend() { // Ensure that the funds deposited to Alice account. - let alice_account = Westend::account_id_of(ALICE); + let alice_account = AssetHubWestend::account_id_of(ALICE); assert_eq!( >::balance(&alice_account), fellowship_spend_balance + init_alice_balance From 67ce378f8c62dd8f9448356392fbf330894a3c94 Mon Sep 17 00:00:00 2001 From: Muharem Date: Wed, 20 Mar 2024 15:36:55 +0100 Subject: [PATCH 07/10] Update polkadot/runtime/common/src/impls.rs Co-authored-by: Branislav Kontur --- polkadot/runtime/common/src/impls.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/polkadot/runtime/common/src/impls.rs b/polkadot/runtime/common/src/impls.rs index df7186e7409b..c1098bcd0bdf 100644 --- a/polkadot/runtime/common/src/impls.rs +++ b/polkadot/runtime/common/src/impls.rs @@ -156,8 +156,8 @@ impl TryConvert<&VersionedLocation, xcm::latest::Location> for VersionedLocation pub struct ContainsLatest(PhantomData<(L, A)>); impl Contains for ContainsLatest where - L: Contains, - A: Contains, + L: Contains, + A: Contains, { fn contains(asset: &VersionedLocatableAsset) -> bool { use VersionedLocatableAsset::*; From 190e2242c4a54bc69fff74795935a9f8f6f79ed9 Mon Sep 17 00:00:00 2001 From: muharem Date: Mon, 15 Apr 2024 17:40:31 +0200 Subject: [PATCH 08/10] fix test --- Cargo.lock | 1 + .../emulated/tests/assets/asset-hub-rococo/Cargo.toml | 1 + 2 files changed, 2 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 6fcda8667b24..89541f63acff 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -820,6 +820,7 @@ dependencies = [ "assert_matches", "asset-hub-rococo-runtime", "asset-test-utils", + "cumulus-pallet-parachain-system", "emulated-integration-tests-common", "frame-support", "pallet-asset-conversion", diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/Cargo.toml b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/Cargo.toml index 2ec4a5638284..ddd6d2d04982 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/Cargo.toml @@ -34,6 +34,7 @@ rococo-runtime-constants = { path = "../../../../../../../polkadot/runtime/rococ # Cumulus asset-test-utils = { path = "../../../../../runtimes/assets/test-utils" } +cumulus-pallet-parachain-system = { path = "../../../../../../pallets/parachain-system", default-features = false } parachains-common = { path = "../../../../../common" } asset-hub-rococo-runtime = { path = "../../../../../runtimes/assets/asset-hub-rococo" } penpal-runtime = { path = "../../../../../runtimes/testing/penpal" } From d3fcd1cf4dc18c2c345bf9667449d4493ee43cc9 Mon Sep 17 00:00:00 2001 From: muharem Date: Tue, 16 Apr 2024 17:11:07 +0200 Subject: [PATCH 09/10] contains parts and contains pair --- .../collectives-westend/src/fellowship/mod.rs | 4 ++-- polkadot/runtime/common/src/impls.rs | 11 +++++------ polkadot/runtime/rococo/src/lib.rs | 15 ++++++++++----- polkadot/runtime/westend/src/lib.rs | 14 ++++++++------ substrate/frame/support/src/traits.rs | 2 +- substrate/frame/support/src/traits/members.rs | 9 +++++++++ 6 files changed, 35 insertions(+), 20 deletions(-) diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/fellowship/mod.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/fellowship/mod.rs index a8ddd3062316..e3e4c73a1640 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/fellowship/mod.rs +++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/fellowship/mod.rs @@ -43,7 +43,7 @@ use pallet_ranked_collective::EnsureOfRank; use pallet_xcm::{EnsureXcm, IsVoiceOfBody}; use parachains_common::impls::ToParentTreasury; use polkadot_runtime_common::impls::{ - ContainsLatest, LocatableAssetConverter, VersionedLocatableAsset, VersionedLocationConverter, + ContainsParts, LocatableAssetConverter, VersionedLocatableAsset, VersionedLocationConverter, }; use sp_arithmetic::Permill; use sp_core::{ConstU128, ConstU32, ConstU8}; @@ -350,7 +350,7 @@ impl pallet_treasury::Config for Runtime { #[cfg(feature = "runtime-benchmarks")] type Paymaster = PayWithEnsure>>; type BalanceConverter = UnityOrOuterConversion< - ContainsLatest< + ContainsParts< xcm_builder::IsSiblingSystemParachain, xcm_builder::IsParentsOnly>, >, diff --git a/polkadot/runtime/common/src/impls.rs b/polkadot/runtime/common/src/impls.rs index f58c5257de85..85531e9c04fc 100644 --- a/polkadot/runtime/common/src/impls.rs +++ b/polkadot/runtime/common/src/impls.rs @@ -19,7 +19,7 @@ use frame_support::traits::{ fungible::{Balanced, Credit}, tokens::imbalance::ResolveTo, - Contains, Imbalance, OnUnbalanced, + Contains, ContainsPair, Imbalance, OnUnbalanced, }; use pallet_treasury::TreasuryAccountId; use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; @@ -158,11 +158,10 @@ impl TryConvert<&VersionedLocation, xcm::latest::Location> for VersionedLocation /// Adapter for [`Contains`] trait to match [`VersionedLocatableAsset`] type converted to the latest /// version of itself where it's location matched by `L` and it's asset id by `A` parameter types. -pub struct ContainsLatest(core::marker::PhantomData<(L, A)>); -impl Contains for ContainsLatest +pub struct ContainsParts(core::marker::PhantomData); +impl Contains for ContainsParts where - L: Contains, - A: Contains, + C: ContainsPair, { fn contains(asset: &VersionedLocatableAsset) -> bool { use VersionedLocatableAsset::*; @@ -173,7 +172,7 @@ where }, V4 { location, asset_id } => (location, asset_id), }; - L::contains(&location) && A::contains(&asset_id.0) + C::contains(&location, &asset_id.0) } } diff --git a/polkadot/runtime/rococo/src/lib.rs b/polkadot/runtime/rococo/src/lib.rs index 9a136670c95a..ba80fa6942c7 100644 --- a/polkadot/runtime/rococo/src/lib.rs +++ b/polkadot/runtime/rococo/src/lib.rs @@ -25,7 +25,10 @@ use beefy_primitives::{ ecdsa_crypto::{AuthorityId as BeefyId, Signature as BeefySignature}, mmr::{BeefyDataProvider, MmrLeafVersion}, }; -use frame_support::dynamic_params::{dynamic_pallet_params, dynamic_params}; +use frame_support::{ + dynamic_params::{dynamic_pallet_params, dynamic_params}, + traits::FromContains, +}; use pallet_nis::WithMaximumOf; use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; use primitives::{ @@ -40,7 +43,7 @@ use rococo_runtime_constants::system_parachain::BROKER_ID; use runtime_common::{ assigned_slots, auctions, claims, crowdloan, identity_migrator, impl_runtime_weights, impls::{ - ContainsLatest, LocatableAssetConverter, ToAuthor, VersionedLocatableAsset, + ContainsParts, LocatableAssetConverter, ToAuthor, VersionedLocatableAsset, VersionedLocationConverter, }, paras_registrar, paras_sudo_wrapper, prod_or_fast, slots, @@ -525,9 +528,11 @@ impl pallet_treasury::Config for Runtime { VersionedLocationConverter, >; type BalanceConverter = UnityOrOuterConversion< - ContainsLatest< - xcm_builder::IsChildSystemParachain, - xcm_builder::IsParentsOnly>, + ContainsParts< + FromContains< + xcm_builder::IsChildSystemParachain, + xcm_builder::IsParentsOnly>, + >, >, AssetRate, >; diff --git a/polkadot/runtime/westend/src/lib.rs b/polkadot/runtime/westend/src/lib.rs index e72c384b62c2..a06a1e1f7fc8 100644 --- a/polkadot/runtime/westend/src/lib.rs +++ b/polkadot/runtime/westend/src/lib.rs @@ -32,8 +32,8 @@ use frame_support::{ parameter_types, traits::{ fungible::HoldConsideration, tokens::UnityOrOuterConversion, ConstU32, Contains, EitherOf, - EitherOfDiverse, EverythingBut, InstanceFilter, KeyOwnerProofSystem, LinearStoragePrice, - ProcessMessage, ProcessMessageError, WithdrawReasons, + EitherOfDiverse, EverythingBut, FromContains, InstanceFilter, KeyOwnerProofSystem, + LinearStoragePrice, ProcessMessage, ProcessMessageError, WithdrawReasons, }, weights::{ConstantMultiplier, WeightMeter, WeightToFee as _}, PalletId, @@ -57,7 +57,7 @@ use runtime_common::{ elections::OnChainAccuracy, identity_migrator, impl_runtime_weights, impls::{ - ContainsLatest, LocatableAssetConverter, ToAuthor, VersionedLocatableAsset, + ContainsParts, LocatableAssetConverter, ToAuthor, VersionedLocatableAsset, VersionedLocationConverter, }, paras_registrar, paras_sudo_wrapper, prod_or_fast, slots, @@ -714,9 +714,11 @@ impl pallet_treasury::Config for Runtime { VersionedLocationConverter, >; type BalanceConverter = UnityOrOuterConversion< - ContainsLatest< - xcm_builder::IsChildSystemParachain, - xcm_builder::IsParentsOnly>, + ContainsParts< + FromContains< + xcm_builder::IsChildSystemParachain, + xcm_builder::IsParentsOnly>, + >, >, AssetRate, >; diff --git a/substrate/frame/support/src/traits.rs b/substrate/frame/support/src/traits.rs index 66777cef7b8e..a423656c394f 100644 --- a/substrate/frame/support/src/traits.rs +++ b/substrate/frame/support/src/traits.rs @@ -36,7 +36,7 @@ mod members; pub use members::{AllowAll, DenyAll, Filter}; pub use members::{ AsContains, ChangeMembers, Contains, ContainsLengthBound, ContainsPair, Equals, Everything, - EverythingBut, FromContainsPair, InitializeMembers, InsideBoth, IsInVec, Nothing, + EverythingBut, FromContains, FromContainsPair, InitializeMembers, InsideBoth, IsInVec, Nothing, RankedMembers, RankedMembersSwapHandler, SortedMembers, TheseExcept, }; diff --git a/substrate/frame/support/src/traits/members.rs b/substrate/frame/support/src/traits/members.rs index 3a6e3719593a..53de84ab2245 100644 --- a/substrate/frame/support/src/traits/members.rs +++ b/substrate/frame/support/src/traits/members.rs @@ -66,6 +66,15 @@ impl> Contains<(A, B)> for FromContainsPair { } } +/// A [`ContainsPair`] implementation that has a `Contains` implementation for each member of the +/// pair. +pub struct FromContains(PhantomData<(CA, CB)>); +impl, CB: Contains> ContainsPair for FromContains { + fn contains(a: &A, b: &B) -> bool { + CA::contains(a) && CB::contains(b) + } +} + /// A [`Contains`] implementation that contains every value. pub enum Everything {} impl Contains for Everything { From d294d383ca337078a7f1b220a31a2ff0f4e601db Mon Sep 17 00:00:00 2001 From: muharem Date: Tue, 16 Apr 2024 17:26:15 +0200 Subject: [PATCH 10/10] fix --- .../collectives-westend/src/fellowship/mod.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/fellowship/mod.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/fellowship/mod.rs index e3e4c73a1640..94765287637b 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/fellowship/mod.rs +++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/fellowship/mod.rs @@ -29,8 +29,8 @@ use cumulus_primitives_core::ParaId; use frame_support::{ parameter_types, traits::{ - tokens::UnityOrOuterConversion, EitherOf, EitherOfDiverse, MapSuccess, NeverEnsureOrigin, - OriginTrait, TryWithMorphedArg, + tokens::UnityOrOuterConversion, EitherOf, EitherOfDiverse, FromContains, MapSuccess, + NeverEnsureOrigin, OriginTrait, TryWithMorphedArg, }, PalletId, }; @@ -351,8 +351,10 @@ impl pallet_treasury::Config for Runtime { type Paymaster = PayWithEnsure>>; type BalanceConverter = UnityOrOuterConversion< ContainsParts< - xcm_builder::IsSiblingSystemParachain, - xcm_builder::IsParentsOnly>, + FromContains< + xcm_builder::IsSiblingSystemParachain, + xcm_builder::IsParentsOnly>, + >, >, AssetRate, >;