diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/xcm_config.rs index da4d5b393b47..13816f8ce711 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/xcm_config.rs @@ -15,11 +15,12 @@ // along with Cumulus. If not, see . use super::{ - AccountId, AllPalletsWithSystem, Balances, BaseDeliveryFee, FeeAssetId, ParachainInfo, + AccountId, AllPalletsWithSystem, Balances, BaseDeliveryFee, Broker, FeeAssetId, ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, TransactionByteFee, WeightToFee, XcmpQueue, }; use frame_support::{ + pallet_prelude::PalletInfoAccess, parameter_types, traits::{ConstU32, Contains, Equals, Everything, Nothing}, }; @@ -42,11 +43,12 @@ use xcm_builder::CurrencyAdapter; use xcm_builder::{ AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, DenyReserveTransferToRelayChain, - DenyThenTry, EnsureXcmOrigin, FrameTransactionalProcessor, IsConcrete, ParentAsSuperuser, - ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, - SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, - TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, - XcmFeeManagerFromComponents, XcmFeeToAccount, + DenyThenTry, EnsureXcmOrigin, FrameTransactionalProcessor, IsConcrete, NonFungibleAdapter, + ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, + SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, + SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents, + WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, XcmFeeManagerFromComponents, + XcmFeeToAccount, }; use xcm_executor::{traits::WithOriginFilter, XcmExecutor}; @@ -56,6 +58,8 @@ parameter_types! { pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into(); pub UniversalLocation: InteriorLocation = [GlobalConsensus(RelayNetwork::get().unwrap()), Parachain(ParachainInfo::parachain_id().into())].into(); + pub BrokerPalletLocation: Location = + PalletInstance(::index() as u8).into(); pub const MaxInstructions: u32 = 100; pub const MaxAssetsIntoHolding: u32 = 64; pub const GovernanceLocation: Location = Location::parent(); @@ -90,6 +94,23 @@ pub type CurrencyTransactor = CurrencyAdapter< (), >; +/// Means for transacting coretime regions on this chain. +pub type RegionTransactor = NonFungibleAdapter< + // Use this non-fungible implementation: + Broker, + // This adapter will handle coretime regions from the broker pallet. + IsConcrete, + // Convert an XCM Location into a local account id: + LocationToAccountId, + // Our chain's account ID type (we can't get away without mentioning it explicitly): + AccountId, + // We don't track any teleports. + (), +>; + +/// Means for transacting assets on this chain. +pub type AssetTransactors = (CurrencyTransactor, RegionTransactor); + /// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance, /// ready for dispatching a transaction with XCM's `Transact`. There is an `OriginKind` that can /// bias the kind of local `Origin` it will become. @@ -205,7 +226,7 @@ pub struct XcmConfig; impl xcm_executor::Config for XcmConfig { type RuntimeCall = RuntimeCall; type XcmSender = XcmRouter; - type AssetTransactor = CurrencyTransactor; + type AssetTransactor = AssetTransactors; type OriginConverter = XcmOriginToTransactDispatchOrigin; // Coretime chain does not recognize a reserve location for any asset. Users must teleport ROC // where allowed (e.g. with the Relay Chain). diff --git a/prdoc/pr_3077.prdoc b/prdoc/pr_3077.prdoc new file mode 100644 index 000000000000..d82ecffb937f --- /dev/null +++ b/prdoc/pr_3077.prdoc @@ -0,0 +1,13 @@ +# 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: Enable cross-chain Coretime region transfers on Rococo Coretime chain + +doc: + - audience: Runtime User + description: | + This PR allows Coretime regions to be cross-chain transferred from the Rococo Coretime chain. + +crates: + - name: pallet-broker + - name: coretime-rococo-runtime diff --git a/substrate/frame/broker/src/nonfungible_impl.rs b/substrate/frame/broker/src/nonfungible_impl.rs index fe95438cb1af..b2e88bf09a0e 100644 --- a/substrate/frame/broker/src/nonfungible_impl.rs +++ b/substrate/frame/broker/src/nonfungible_impl.rs @@ -18,7 +18,7 @@ use super::*; use frame_support::{ pallet_prelude::{DispatchResult, *}, - traits::nonfungible::{Inspect, Transfer}, + traits::nonfungible::{Inspect, Mutate, Transfer}, }; use sp_std::vec::Vec; @@ -50,3 +50,7 @@ impl Transfer for Pallet { Self::do_transfer((*index).into(), None, dest.clone()).map_err(Into::into) } } + +// We don't allow any of the mutate operations, so the default implementation is used, which will +// return `TokenError::Unsupported` in case any of the operations is called. +impl Mutate for Pallet {} diff --git a/substrate/frame/broker/src/tests.rs b/substrate/frame/broker/src/tests.rs index 6aa9ca84fc41..e5efb70ae8d5 100644 --- a/substrate/frame/broker/src/tests.rs +++ b/substrate/frame/broker/src/tests.rs @@ -20,11 +20,11 @@ use crate::{core_mask::*, mock::*, *}; use frame_support::{ assert_noop, assert_ok, - traits::nonfungible::{Inspect as NftInspect, Transfer}, + traits::nonfungible::{Inspect as NftInspect, Mutate, Transfer}, BoundedVec, }; use frame_system::RawOrigin::Root; -use sp_runtime::traits::Get; +use sp_runtime::{traits::Get, TokenError}; use CoreAssignment::*; use CoretimeTraceItem::*; use Finality::*; @@ -197,6 +197,26 @@ fn transfer_works() { }); } +#[test] +fn mutate_operations_unsupported_for_regions() { + TestExt::new().execute_with(|| { + let region_id = RegionId { begin: 0, core: 0, mask: CoreMask::complete() }; + assert_noop!( + >::mint_into(®ion_id.into(), &2), + TokenError::Unsupported + ); + assert_noop!(>::burn(®ion_id.into(), None), TokenError::Unsupported); + assert_noop!( + >::set_attribute(®ion_id.into(), &[], &[]), + TokenError::Unsupported + ); + assert_noop!( + >::set_typed_attribute::(®ion_id.into(), &0, &0), + TokenError::Unsupported + ); + }); +} + #[test] fn permanent_is_not_reassignable() { TestExt::new().endow(1, 1000).execute_with(|| {