diff --git a/cumulus/pallets/xcmp-queue/src/mock.rs b/cumulus/pallets/xcmp-queue/src/mock.rs index 031c07217537..f8b89258f2f6 100644 --- a/cumulus/pallets/xcmp-queue/src/mock.rs +++ b/cumulus/pallets/xcmp-queue/src/mock.rs @@ -32,7 +32,9 @@ use sp_runtime::{ use xcm::prelude::*; #[allow(deprecated)] use xcm_builder::CurrencyAdapter; -use xcm_builder::{FixedWeightBounds, IsConcrete, NativeAsset, ParentIsPreset}; +use xcm_builder::{ + FixedWeightBounds, FrameTransactionalProcessor, IsConcrete, NativeAsset, ParentIsPreset, +}; use xcm_executor::traits::ConvertOrigin; type Block = frame_system::mocking::MockBlock; @@ -175,6 +177,7 @@ impl xcm_executor::Config for XcmConfig { type CallDispatcher = RuntimeCall; type SafeCallFilter = Everything; type Aliasers = Nothing; + type TransactionalProcessor = FrameTransactionalProcessor; } pub type XcmRouter = ( diff --git a/cumulus/parachain-template/runtime/src/xcm_config.rs b/cumulus/parachain-template/runtime/src/xcm_config.rs index d407292d0bd6..9dd08dc7f3ea 100644 --- a/cumulus/parachain-template/runtime/src/xcm_config.rs +++ b/cumulus/parachain-template/runtime/src/xcm_config.rs @@ -16,11 +16,11 @@ use xcm::latest::prelude::*; use xcm_builder::CurrencyAdapter; use xcm_builder::{ AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowTopLevelPaidExecutionFrom, - DenyReserveTransferToRelayChain, DenyThenTry, EnsureXcmOrigin, FixedWeightBounds, IsConcrete, - NativeAsset, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, - SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, - SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents, - WithComputedOrigin, WithUniqueTopic, + DenyReserveTransferToRelayChain, DenyThenTry, EnsureXcmOrigin, FixedWeightBounds, + FrameTransactionalProcessor, IsConcrete, NativeAsset, ParentIsPreset, RelayChainAsNative, + SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, + SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, + UsingComponents, WithComputedOrigin, WithUniqueTopic, }; use xcm_executor::XcmExecutor; @@ -139,6 +139,7 @@ impl xcm_executor::Config for XcmConfig { type CallDispatcher = RuntimeCall; type SafeCallFilter = Everything; type Aliasers = Nothing; + type TransactionalProcessor = FrameTransactionalProcessor; } /// No local origins on this chain are allowed to dispatch XCM sends/executions. diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index a6dd11250192..d6f2f41ef312 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -1601,6 +1601,13 @@ impl_runtime_apis! { Ok((origin, ticket, assets)) } + fn fee_asset() -> Result { + Ok(Asset { + id: AssetId(TokenLocation::get()), + fun: Fungible(1_000_000 * UNITS), + }) + } + fn unlockable_asset() -> Result<(Location, Location, Asset), BenchmarkError> { Err(BenchmarkError::Skip) } diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs index 91a3337804c9..f5da60d6c9d7 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs @@ -53,10 +53,10 @@ use xcm_builder::CurrencyAdapter; use xcm_builder::{ AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, DenyReserveTransferToRelayChain, - DenyThenTry, DescribeAllTerminal, DescribeFamily, EnsureXcmOrigin, FungiblesAdapter, - GlobalConsensusParachainConvertsFor, HashedDescription, IsConcrete, LocalMint, - NetworkExportTableItem, NoChecking, NonFungiblesAdapter, ParentAsSuperuser, ParentIsPreset, - RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, + DenyThenTry, DescribeAllTerminal, DescribeFamily, EnsureXcmOrigin, FrameTransactionalProcessor, + FungiblesAdapter, GlobalConsensusParachainConvertsFor, HashedDescription, IsConcrete, + LocalMint, NetworkExportTableItem, NoChecking, NonFungiblesAdapter, ParentAsSuperuser, + ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, SovereignPaidRemoteExporter, SovereignSignedViaLocation, StartsWith, StartsWithExplicitGlobalConsensus, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, @@ -652,6 +652,7 @@ impl xcm_executor::Config for XcmConfig { type CallDispatcher = WithOriginFilter; type SafeCallFilter = SafeCallFilter; type Aliasers = Nothing; + type TransactionalProcessor = FrameTransactionalProcessor; } /// Converts a local signed origin into an XCM location. diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs index e642475698ef..66d80fac831f 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -1643,6 +1643,13 @@ impl_runtime_apis! { Ok((origin, ticket, assets)) } + fn fee_asset() -> Result { + Ok(Asset { + id: AssetId(WestendLocation::get()), + fun: Fungible(1_000_000 * UNITS), + }) + } + fn unlockable_asset() -> Result<(Location, Location, Asset), BenchmarkError> { Err(BenchmarkError::Skip) } diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs index df9baa11554a..a3150a9fc369 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs @@ -51,14 +51,14 @@ use xcm_builder::CurrencyAdapter; use xcm_builder::{ AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, DenyReserveTransferToRelayChain, - DenyThenTry, DescribeFamily, DescribePalletTerminal, EnsureXcmOrigin, FungiblesAdapter, - GlobalConsensusParachainConvertsFor, HashedDescription, IsConcrete, LocalMint, - NetworkExportTableItem, NoChecking, NonFungiblesAdapter, ParentAsSuperuser, ParentIsPreset, - RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, - SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, StartsWith, - StartsWithExplicitGlobalConsensus, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents, - WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, XcmFeeManagerFromComponents, - XcmFeeToAccount, + DenyThenTry, DescribeFamily, DescribePalletTerminal, EnsureXcmOrigin, + FrameTransactionalProcessor, FungiblesAdapter, GlobalConsensusParachainConvertsFor, + HashedDescription, IsConcrete, LocalMint, NetworkExportTableItem, NoChecking, + NonFungiblesAdapter, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, + SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, + SignedToAccountId32, SovereignSignedViaLocation, StartsWith, StartsWithExplicitGlobalConsensus, + TakeWeightCredit, TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin, + WithUniqueTopic, XcmFeeManagerFromComponents, XcmFeeToAccount, }; use xcm_executor::{traits::WithOriginFilter, XcmExecutor}; @@ -676,6 +676,7 @@ impl xcm_executor::Config for XcmConfig { type CallDispatcher = WithOriginFilter; type SafeCallFilter = SafeCallFilter; type Aliasers = Nothing; + type TransactionalProcessor = FrameTransactionalProcessor; } /// Local origins on this chain are allowed to dispatch XCM sends/executions. diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs index 4a3ef8ac4e8c..ceba449e6b7b 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs @@ -1216,6 +1216,13 @@ impl_runtime_apis! { Ok((origin, ticket, assets)) } + fn fee_asset() -> Result { + Ok(Asset { + id: AssetId(TokenLocation::get()), + fun: Fungible(1_000_000 * UNITS), + }) + } + fn unlockable_asset() -> Result<(Location, Location, Asset), BenchmarkError> { Err(BenchmarkError::Skip) } diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs index f641b428d4c6..6d48e0656d8d 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs @@ -57,11 +57,12 @@ use xcm::latest::prelude::*; use xcm_builder::{ deposit_or_burn_fee, AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, - CurrencyAdapter, DenyReserveTransferToRelayChain, DenyThenTry, EnsureXcmOrigin, HandleFee, - IsConcrete, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, - SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, - SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents, - WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, XcmFeeToAccount, + CurrencyAdapter, DenyReserveTransferToRelayChain, DenyThenTry, EnsureXcmOrigin, + FrameTransactionalProcessor, HandleFee, IsConcrete, ParentAsSuperuser, ParentIsPreset, + RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, + SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, + TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, + XcmFeeToAccount, }; use xcm_executor::{ traits::{FeeManager, FeeReason, FeeReason::Export, TransactAsset, WithOriginFilter}, @@ -326,6 +327,7 @@ impl xcm_executor::Config for XcmConfig { type CallDispatcher = WithOriginFilter; type SafeCallFilter = SafeCallFilter; type Aliasers = Nothing; + type TransactionalProcessor = FrameTransactionalProcessor; } pub type PriceForParentDelivery = diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs index 34fc2c6080ec..10058ef13be3 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs @@ -914,6 +914,13 @@ impl_runtime_apis! { Ok((origin, ticket, assets)) } + fn fee_asset() -> Result { + Ok(Asset { + id: AssetId(WestendLocation::get()), + fun: Fungible(1_000_000 * UNITS), + }) + } + fn unlockable_asset() -> Result<(Location, Location, Asset), BenchmarkError> { Err(BenchmarkError::Skip) } diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/xcm_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/xcm_config.rs index 085608acf5d8..d2f0f187a20d 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/xcm_config.rs @@ -43,8 +43,8 @@ use xcm_builder::CurrencyAdapter; use xcm_builder::{ AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, DenyReserveTransferToRelayChain, - DenyThenTry, EnsureXcmOrigin, IsConcrete, ParentAsSuperuser, ParentIsPreset, - RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, + DenyThenTry, EnsureXcmOrigin, FrameTransactionalProcessor, IsConcrete, ParentAsSuperuser, + ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, XcmFeeManagerFromComponents, XcmFeeToAccount, @@ -265,6 +265,7 @@ impl xcm_executor::Config for XcmConfig { type CallDispatcher = WithOriginFilter; type SafeCallFilter = SafeCallFilter; type Aliasers = Nothing; + type TransactionalProcessor = FrameTransactionalProcessor; } pub type PriceForParentDelivery = diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/xcm_config.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/xcm_config.rs index aa7dbe991e4b..ad19521898dd 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/xcm_config.rs @@ -41,12 +41,12 @@ use xcm_builder::CurrencyAdapter; use xcm_builder::{ AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, DenyReserveTransferToRelayChain, - DenyThenTry, EnsureXcmOrigin, FixedWeightBounds, IsConcrete, LocatableAssetId, - OriginToPluralityVoice, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, - SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, - SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, - UsingComponents, WithComputedOrigin, WithUniqueTopic, XcmFeeManagerFromComponents, - XcmFeeToAccount, + DenyThenTry, EnsureXcmOrigin, FixedWeightBounds, FrameTransactionalProcessor, IsConcrete, + LocatableAssetId, OriginToPluralityVoice, ParentAsSuperuser, ParentIsPreset, + RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, + SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, + TrailingSetTopicAsId, UsingComponents, WithComputedOrigin, WithUniqueTopic, + XcmFeeManagerFromComponents, XcmFeeToAccount, }; use xcm_executor::{traits::WithOriginFilter, XcmExecutor}; @@ -290,6 +290,7 @@ impl xcm_executor::Config for XcmConfig { type CallDispatcher = WithOriginFilter; type SafeCallFilter = SafeCallFilter; type Aliasers = Nothing; + type TransactionalProcessor = FrameTransactionalProcessor; } /// Converts a local signed origin into an XCM location. diff --git a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/xcm_config.rs index e2cf2c8e51a0..8c0d681361c7 100644 --- a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/xcm_config.rs @@ -42,11 +42,11 @@ use xcm_builder::CurrencyAdapter; use xcm_builder::{ AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, DenyReserveTransferToRelayChain, - DenyThenTry, EnsureXcmOrigin, FixedWeightBounds, IsConcrete, NativeAsset, ParentAsSuperuser, - ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, - SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, - TrailingSetTopicAsId, UsingComponents, WithComputedOrigin, WithUniqueTopic, - XcmFeeManagerFromComponents, XcmFeeToAccount, + DenyThenTry, EnsureXcmOrigin, FixedWeightBounds, FrameTransactionalProcessor, IsConcrete, + NativeAsset, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, + SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, + SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents, + WithComputedOrigin, WithUniqueTopic, XcmFeeManagerFromComponents, XcmFeeToAccount, }; use xcm_executor::XcmExecutor; @@ -198,6 +198,7 @@ impl xcm_executor::Config for XcmConfig { type CallDispatcher = RuntimeCall; type SafeCallFilter = Everything; type Aliasers = Nothing; + type TransactionalProcessor = FrameTransactionalProcessor; } /// Converts a local signed origin into an XCM location. diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs index c5843c1ef293..531a0ffe4f86 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs @@ -804,6 +804,13 @@ impl_runtime_apis! { Ok((origin, ticket, assets)) } + fn fee_asset() -> Result { + Ok(Asset { + id: AssetId(RocRelayLocation::get()), + fun: Fungible(1_000_000 * UNITS), + }) + } + fn unlockable_asset() -> Result<(Location, Location, Asset), BenchmarkError> { Err(BenchmarkError::Skip) } 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 927d8f0a78e6..da4d5b393b47 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/xcm_config.rs @@ -42,8 +42,8 @@ use xcm_builder::CurrencyAdapter; use xcm_builder::{ AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, DenyReserveTransferToRelayChain, - DenyThenTry, EnsureXcmOrigin, IsConcrete, ParentAsSuperuser, ParentIsPreset, - RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, + DenyThenTry, EnsureXcmOrigin, FrameTransactionalProcessor, IsConcrete, ParentAsSuperuser, + ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, XcmFeeManagerFromComponents, XcmFeeToAccount, @@ -238,6 +238,7 @@ impl xcm_executor::Config for XcmConfig { type CallDispatcher = WithOriginFilter; type SafeCallFilter = SafeCallFilter; type Aliasers = Nothing; + type TransactionalProcessor = FrameTransactionalProcessor; } /// Converts a local signed origin into an XCM location. Forms the basis for local origins diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs index a14a6ea3f950..892492724141 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs @@ -791,6 +791,13 @@ impl_runtime_apis! { Ok((origin, ticket, assets)) } + fn fee_asset() -> Result { + Ok(Asset { + id: AssetId(WndRelayLocation::get()), + fun: Fungible(1_000_000 * UNITS), + }) + } + fn unlockable_asset() -> Result<(Location, Location, Asset), BenchmarkError> { Err(BenchmarkError::Skip) } diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/xcm_config.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/xcm_config.rs index f468f29540aa..e57a46877764 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/xcm_config.rs @@ -42,8 +42,8 @@ use xcm_builder::CurrencyAdapter; use xcm_builder::{ AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, DenyReserveTransferToRelayChain, - DenyThenTry, EnsureXcmOrigin, IsConcrete, ParentAsSuperuser, ParentIsPreset, - RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, + DenyThenTry, EnsureXcmOrigin, FrameTransactionalProcessor, IsConcrete, ParentAsSuperuser, + ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, XcmFeeManagerFromComponents, XcmFeeToAccount, @@ -243,6 +243,7 @@ impl xcm_executor::Config for XcmConfig { type CallDispatcher = WithOriginFilter; type SafeCallFilter = SafeCallFilter; type Aliasers = Nothing; + type TransactionalProcessor = FrameTransactionalProcessor; } /// Converts a local signed origin into an XCM location. Forms the basis for local origins diff --git a/cumulus/parachains/runtimes/glutton/glutton-westend/src/xcm_config.rs b/cumulus/parachains/runtimes/glutton/glutton-westend/src/xcm_config.rs index 1c37241563ec..ad61987c0e70 100644 --- a/cumulus/parachains/runtimes/glutton/glutton-westend/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/glutton/glutton-westend/src/xcm_config.rs @@ -24,8 +24,8 @@ use frame_support::{ }; use xcm::latest::prelude::*; use xcm_builder::{ - AllowExplicitUnpaidExecutionFrom, FixedWeightBounds, ParentAsSuperuser, ParentIsPreset, - SovereignSignedViaLocation, + AllowExplicitUnpaidExecutionFrom, FixedWeightBounds, FrameTransactionalProcessor, + ParentAsSuperuser, ParentIsPreset, SovereignSignedViaLocation, }; parameter_types! { @@ -87,6 +87,7 @@ impl xcm_executor::Config for XcmConfig { type CallDispatcher = RuntimeCall; type SafeCallFilter = Everything; type Aliasers = Nothing; + type TransactionalProcessor = FrameTransactionalProcessor; } impl cumulus_pallet_xcm::Config for Runtime { diff --git a/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs b/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs index d775ed1fc56d..b21fdc6a68c9 100644 --- a/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs @@ -776,6 +776,13 @@ impl_runtime_apis! { Ok((origin, ticket, assets)) } + fn fee_asset() -> Result { + Ok(Asset { + id: AssetId(RelayLocation::get()), + fun: Fungible(1_000_000 * UNITS), + }) + } + fn unlockable_asset() -> Result<(Location, Location, Asset), BenchmarkError> { Err(BenchmarkError::Skip) } diff --git a/cumulus/parachains/runtimes/people/people-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/people/people-rococo/src/xcm_config.rs index 168d7eaa605d..c7408b3fa84b 100644 --- a/cumulus/parachains/runtimes/people/people-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/people/people-rococo/src/xcm_config.rs @@ -39,8 +39,8 @@ use xcm_builder::CurrencyAdapter; use xcm_builder::{ AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, DenyReserveTransferToRelayChain, - DenyThenTry, DescribeTerminus, EnsureXcmOrigin, HashedDescription, IsConcrete, - ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, + DenyThenTry, DescribeTerminus, EnsureXcmOrigin, FrameTransactionalProcessor, HashedDescription, + IsConcrete, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, XcmFeeManagerFromComponents, @@ -277,6 +277,7 @@ impl xcm_executor::Config for XcmConfig { type CallDispatcher = WithOriginFilter; type SafeCallFilter = SafeCallFilter; type Aliasers = Nothing; + type TransactionalProcessor = FrameTransactionalProcessor; } /// Converts a local signed origin into an XCM location. Forms the basis for local origins diff --git a/cumulus/parachains/runtimes/people/people-westend/src/lib.rs b/cumulus/parachains/runtimes/people/people-westend/src/lib.rs index 90e08a91d5d2..20d8973417a3 100644 --- a/cumulus/parachains/runtimes/people/people-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/people/people-westend/src/lib.rs @@ -776,6 +776,13 @@ impl_runtime_apis! { Ok((origin, ticket, assets)) } + fn fee_asset() -> Result { + Ok(Asset { + id: AssetId(RelayLocation::get()), + fun: Fungible(1_000_000 * UNITS), + }) + } + fn unlockable_asset() -> Result<(Location, Location, Asset), BenchmarkError> { Err(BenchmarkError::Skip) } diff --git a/cumulus/parachains/runtimes/people/people-westend/src/xcm_config.rs b/cumulus/parachains/runtimes/people/people-westend/src/xcm_config.rs index 18c03a968ef9..baead5234191 100644 --- a/cumulus/parachains/runtimes/people/people-westend/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/people/people-westend/src/xcm_config.rs @@ -39,8 +39,8 @@ use xcm_builder::CurrencyAdapter; use xcm_builder::{ AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, DenyReserveTransferToRelayChain, - DenyThenTry, DescribeTerminus, EnsureXcmOrigin, HashedDescription, IsConcrete, - ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, + DenyThenTry, DescribeTerminus, EnsureXcmOrigin, FrameTransactionalProcessor, HashedDescription, + IsConcrete, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, XcmFeeManagerFromComponents, @@ -285,6 +285,7 @@ impl xcm_executor::Config for XcmConfig { type CallDispatcher = WithOriginFilter; type SafeCallFilter = SafeCallFilter; type Aliasers = Nothing; + type TransactionalProcessor = FrameTransactionalProcessor; } /// Converts a local signed origin into an XCM location. Forms the basis for local origins diff --git a/cumulus/parachains/runtimes/starters/shell/src/xcm_config.rs b/cumulus/parachains/runtimes/starters/shell/src/xcm_config.rs index f5ceabb1eb47..f6af50f76d85 100644 --- a/cumulus/parachains/runtimes/starters/shell/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/starters/shell/src/xcm_config.rs @@ -87,6 +87,7 @@ impl xcm_executor::Config for XcmConfig { type CallDispatcher = RuntimeCall; type SafeCallFilter = Everything; type Aliasers = Nothing; + type TransactionalProcessor = (); } impl cumulus_pallet_xcm::Config for Runtime { diff --git a/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs b/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs index b3f84a4bb9cb..25a437f3fc6a 100644 --- a/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs @@ -50,11 +50,11 @@ use xcm_builder::{ AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, AsPrefixedGeneralIndex, ConvertedConcreteId, CurrencyAdapter, DenyReserveTransferToRelayChain, DenyThenTry, - EnsureXcmOrigin, FixedWeightBounds, FungiblesAdapter, IsConcrete, LocalMint, NativeAsset, - NoChecking, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, - SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, - SovereignSignedViaLocation, StartsWith, TakeWeightCredit, TrailingSetTopicAsId, - UsingComponents, WithComputedOrigin, WithUniqueTopic, + EnsureXcmOrigin, FixedWeightBounds, FrameTransactionalProcessor, FungiblesAdapter, IsConcrete, + LocalMint, NativeAsset, NoChecking, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, + SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, + SignedToAccountId32, SovereignSignedViaLocation, StartsWith, TakeWeightCredit, + TrailingSetTopicAsId, UsingComponents, WithComputedOrigin, WithUniqueTopic, }; use xcm_executor::{traits::JustTry, XcmExecutor}; @@ -355,6 +355,7 @@ impl xcm_executor::Config for XcmConfig { type CallDispatcher = RuntimeCall; type SafeCallFilter = Everything; type Aliasers = Nothing; + type TransactionalProcessor = FrameTransactionalProcessor; } /// No local origins on this chain are allowed to dispatch XCM sends/executions. diff --git a/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs b/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs index 999cc480ce0a..253a492871b2 100644 --- a/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs +++ b/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs @@ -75,7 +75,8 @@ use parachains_common::{ }; use xcm_builder::{ AllowKnownQueryResponses, AllowSubscriptionsFrom, AsPrefixedGeneralIndex, ConvertedConcreteId, - FungiblesAdapter, LocalMint, TrailingSetTopicAsId, WithUniqueTopic, + FrameTransactionalProcessor, FungiblesAdapter, LocalMint, TrailingSetTopicAsId, + WithUniqueTopic, }; use xcm_executor::traits::JustTry; @@ -489,6 +490,7 @@ impl xcm_executor::Config for XcmConfig { type CallDispatcher = RuntimeCall; type SafeCallFilter = Everything; type Aliasers = Nothing; + type TransactionalProcessor = FrameTransactionalProcessor; } /// Local origins on this chain are allowed to dispatch XCM sends/executions. diff --git a/cumulus/primitives/utility/src/lib.rs b/cumulus/primitives/utility/src/lib.rs index bd13ee1119b8..0d8921227429 100644 --- a/cumulus/primitives/utility/src/lib.rs +++ b/cumulus/primitives/utility/src/lib.rs @@ -25,6 +25,7 @@ use frame_support::{ defensive, traits::{tokens::fungibles, Get, OnUnbalanced as OnUnbalancedT}, weights::{Weight, WeightToFee as WeightToFeeT}, + CloneNoBound, }; use pallet_asset_conversion::SwapCredit as SwapCreditT; use polkadot_runtime_common::xcm_sender::PriceForMessageDelivery; @@ -106,6 +107,7 @@ struct AssetTraderRefunder { /// later refund purposes /// Important: Errors if the Trader is being called twice by 2 BuyExecution instructions /// Alternatively we could just return payment in the aforementioned case +#[derive(CloneNoBound)] pub struct TakeFirstAssetTrader< AccountId: Eq, FeeCharger: ChargeWeightInFungibles, diff --git a/polkadot/runtime/rococo/src/lib.rs b/polkadot/runtime/rococo/src/lib.rs index fcaf4a3fe533..69261b2b03f3 100644 --- a/polkadot/runtime/rococo/src/lib.rs +++ b/polkadot/runtime/rococo/src/lib.rs @@ -2393,6 +2393,13 @@ sp_api::impl_runtime_apis! { Ok((origin, ticket, assets)) } + fn fee_asset() -> Result { + Ok(Asset { + id: AssetId(TokenLocation::get()), + fun: Fungible(1_000_000 * UNITS), + }) + } + fn unlockable_asset() -> Result<(Location, Location, Asset), BenchmarkError> { // Rococo doesn't support asset locking Err(BenchmarkError::Skip) diff --git a/polkadot/runtime/rococo/src/xcm_config.rs b/polkadot/runtime/rococo/src/xcm_config.rs index bfa9beb82090..5fddd749dad3 100644 --- a/polkadot/runtime/rococo/src/xcm_config.rs +++ b/polkadot/runtime/rococo/src/xcm_config.rs @@ -42,10 +42,11 @@ use xcm_builder::{ AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, ChildParachainAsNative, ChildParachainConvertsVia, DescribeBodyTerminal, DescribeFamily, FixedWeightBounds, - HashedDescription, IsChildSystemParachain, IsConcrete, MintLocation, OriginToPluralityVoice, - SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, - TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, - XcmFeeManagerFromComponents, XcmFeeToAccount, + FrameTransactionalProcessor, HashedDescription, IsChildSystemParachain, IsConcrete, + MintLocation, OriginToPluralityVoice, SignedAccountId32AsNative, SignedToAccountId32, + SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents, + WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, XcmFeeManagerFromComponents, + XcmFeeToAccount, }; use xcm_executor::XcmExecutor; @@ -222,6 +223,7 @@ impl xcm_executor::Config for XcmConfig { type CallDispatcher = RuntimeCall; type SafeCallFilter = Everything; type Aliasers = Nothing; + type TransactionalProcessor = FrameTransactionalProcessor; } parameter_types! { diff --git a/polkadot/runtime/test-runtime/src/xcm_config.rs b/polkadot/runtime/test-runtime/src/xcm_config.rs index d9d3d6e0752d..a81d35f4d788 100644 --- a/polkadot/runtime/test-runtime/src/xcm_config.rs +++ b/polkadot/runtime/test-runtime/src/xcm_config.rs @@ -22,8 +22,8 @@ use frame_support::{ use frame_system::EnsureRoot; use xcm::latest::prelude::*; use xcm_builder::{ - AllowUnpaidExecutionFrom, EnsureXcmOrigin, FixedWeightBounds, SignedAccountId32AsNative, - SignedToAccountId32, + AllowUnpaidExecutionFrom, EnsureXcmOrigin, FixedWeightBounds, FrameTransactionalProcessor, + SignedAccountId32AsNative, SignedToAccountId32, }; use xcm_executor::{ traits::{TransactAsset, WeightTrader}, @@ -74,6 +74,7 @@ impl TransactAsset for DummyAssetTransactor { } } +#[derive(Clone)] pub struct DummyWeightTrader; impl WeightTrader for DummyWeightTrader { fn new() -> Self { @@ -121,6 +122,7 @@ impl xcm_executor::Config for XcmConfig { type CallDispatcher = super::RuntimeCall; type SafeCallFilter = Everything; type Aliasers = Nothing; + type TransactionalProcessor = FrameTransactionalProcessor; } impl pallet_xcm::Config for crate::Runtime { diff --git a/polkadot/runtime/westend/src/lib.rs b/polkadot/runtime/westend/src/lib.rs index 17406f7ae9fc..67cb9e3ccb83 100644 --- a/polkadot/runtime/westend/src/lib.rs +++ b/polkadot/runtime/westend/src/lib.rs @@ -2421,6 +2421,13 @@ sp_api::impl_runtime_apis! { Ok((origin, ticket, assets)) } + fn fee_asset() -> Result { + Ok(Asset { + id: AssetId(TokenLocation::get()), + fun: Fungible(1_000_000 * UNITS), + }) + } + fn unlockable_asset() -> Result<(Location, Location, Asset), BenchmarkError> { // Westend doesn't support asset locking Err(BenchmarkError::Skip) diff --git a/polkadot/runtime/westend/src/xcm_config.rs b/polkadot/runtime/westend/src/xcm_config.rs index 3c052057d909..8c2fea690060 100644 --- a/polkadot/runtime/westend/src/xcm_config.rs +++ b/polkadot/runtime/westend/src/xcm_config.rs @@ -44,11 +44,11 @@ use xcm_builder::CurrencyAdapter as XcmCurrencyAdapter; use xcm_builder::{ AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, ChildParachainAsNative, - ChildParachainConvertsVia, DescribeBodyTerminal, DescribeFamily, HashedDescription, IsConcrete, - MintLocation, OriginToPluralityVoice, SignedAccountId32AsNative, SignedToAccountId32, - SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents, - WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, XcmFeeManagerFromComponents, - XcmFeeToAccount, + ChildParachainConvertsVia, DescribeBodyTerminal, DescribeFamily, FrameTransactionalProcessor, + HashedDescription, IsConcrete, MintLocation, OriginToPluralityVoice, SignedAccountId32AsNative, + SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, + UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, + XcmFeeManagerFromComponents, XcmFeeToAccount, }; use xcm_executor::XcmExecutor; @@ -217,6 +217,7 @@ impl xcm_executor::Config for XcmConfig { type CallDispatcher = RuntimeCall; type SafeCallFilter = Everything; type Aliasers = Nothing; + type TransactionalProcessor = FrameTransactionalProcessor; } parameter_types! { diff --git a/polkadot/xcm/pallet-xcm-benchmarks/src/fungible/mock.rs b/polkadot/xcm/pallet-xcm-benchmarks/src/fungible/mock.rs index f1d1b2fdef3e..fe3ee81f9d44 100644 --- a/polkadot/xcm/pallet-xcm-benchmarks/src/fungible/mock.rs +++ b/polkadot/xcm/pallet-xcm-benchmarks/src/fungible/mock.rs @@ -26,7 +26,7 @@ use frame_support::{ use sp_core::H256; use sp_runtime::traits::{BlakeTwo256, IdentityLookup}; use xcm::latest::prelude::*; -use xcm_builder::{AllowUnpaidExecutionFrom, MintLocation}; +use xcm_builder::{AllowUnpaidExecutionFrom, FrameTransactionalProcessor, MintLocation}; type Block = frame_system::mocking::MockBlock; @@ -145,6 +145,7 @@ impl xcm_executor::Config for XcmConfig { type CallDispatcher = RuntimeCall; type SafeCallFilter = Everything; type Aliasers = Nothing; + type TransactionalProcessor = FrameTransactionalProcessor; } impl crate::Config for Test { diff --git a/polkadot/xcm/pallet-xcm-benchmarks/src/generic/benchmarking.rs b/polkadot/xcm/pallet-xcm-benchmarks/src/generic/benchmarking.rs index 14d53c4ebf53..8c6ed4b5d0e0 100644 --- a/polkadot/xcm/pallet-xcm-benchmarks/src/generic/benchmarking.rs +++ b/polkadot/xcm/pallet-xcm-benchmarks/src/generic/benchmarking.rs @@ -125,11 +125,15 @@ benchmarks! { } refund_surplus { - let holding = T::worst_case_holding(0).into(); let mut executor = new_executor::(Default::default()); - executor.set_holding(holding); + let holding_assets = T::worst_case_holding(1); + // We can already buy execution since we'll load the holding register manually + let asset_for_fees = T::fee_asset().unwrap(); + let previous_xcm = Xcm(vec![BuyExecution { fees: asset_for_fees, weight_limit: Limited(Weight::from_parts(1337, 1337)) }]); + executor.set_holding(holding_assets.into()); executor.set_total_surplus(Weight::from_parts(1337, 1337)); executor.set_total_refunded(Weight::zero()); + executor.bench_process(previous_xcm).expect("Holding has been loaded, so we can buy execution here"); let instruction = Instruction::>::RefundSurplus; let xcm = Xcm(vec![instruction]); diff --git a/polkadot/xcm/pallet-xcm-benchmarks/src/generic/mock.rs b/polkadot/xcm/pallet-xcm-benchmarks/src/generic/mock.rs index 656c675b6307..c84f062a8d16 100644 --- a/polkadot/xcm/pallet-xcm-benchmarks/src/generic/mock.rs +++ b/polkadot/xcm/pallet-xcm-benchmarks/src/generic/mock.rs @@ -30,7 +30,7 @@ use xcm_builder::{ AssetsInHolding, TestAssetExchanger, TestAssetLocker, TestAssetTrap, TestSubscriptionService, TestUniversalAliases, }, - AliasForeignAccountId32, AllowUnpaidExecutionFrom, + AliasForeignAccountId32, AllowUnpaidExecutionFrom, FrameTransactionalProcessor, }; use xcm_executor::traits::ConvertOrigin; @@ -134,6 +134,7 @@ impl xcm_executor::Config for XcmConfig { type CallDispatcher = RuntimeCall; type SafeCallFilter = Everything; type Aliasers = Aliasers; + type TransactionalProcessor = FrameTransactionalProcessor; } parameter_types! { @@ -196,6 +197,10 @@ impl generic::Config for Test { Ok((Default::default(), ticket, assets)) } + fn fee_asset() -> Result { + Ok(Asset { id: AssetId(Here.into()), fun: Fungible(1_000_000) }) + } + fn unlockable_asset() -> Result<(Location, Location, Asset), BenchmarkError> { let assets: Asset = (AssetId(Here.into()), 100).into(); Ok((Default::default(), account_id_junction::(1).into(), assets)) diff --git a/polkadot/xcm/pallet-xcm-benchmarks/src/generic/mod.rs b/polkadot/xcm/pallet-xcm-benchmarks/src/generic/mod.rs index 3728baea9833..b514eaa47272 100644 --- a/polkadot/xcm/pallet-xcm-benchmarks/src/generic/mod.rs +++ b/polkadot/xcm/pallet-xcm-benchmarks/src/generic/mod.rs @@ -73,6 +73,10 @@ pub mod pallet { /// Return an origin, ticket, and assets that can be trapped and claimed. fn claimable_asset() -> Result<(Location, Location, Assets), BenchmarkError>; + /// Asset used to pay for fees. Used to buy weight in benchmarks, for example in + /// `refund_surplus`. + fn fee_asset() -> Result; + /// Return an unlocker, owner and assets that can be locked and unlocked. fn unlockable_asset() -> Result<(Location, Location, Asset), BenchmarkError>; diff --git a/polkadot/xcm/pallet-xcm/src/mock.rs b/polkadot/xcm/pallet-xcm/src/mock.rs index 1ca30963d595..ec03a8b8668c 100644 --- a/polkadot/xcm/pallet-xcm/src/mock.rs +++ b/polkadot/xcm/pallet-xcm/src/mock.rs @@ -36,9 +36,9 @@ use xcm_builder::{ AccountId32Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, Case, ChildParachainAsNative, ChildParachainConvertsVia, ChildSystemParachainAsSuperuser, DescribeAllTerminal, FixedRateOfFungible, FixedWeightBounds, - FungiblesAdapter, HashedDescription, IsConcrete, MatchedConvertedConcreteId, NoChecking, - SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, - XcmFeeManagerFromComponents, XcmFeeToAccount, + FrameTransactionalProcessor, FungiblesAdapter, HashedDescription, IsConcrete, + MatchedConvertedConcreteId, NoChecking, SignedAccountId32AsNative, SignedToAccountId32, + SovereignSignedViaLocation, TakeWeightCredit, XcmFeeManagerFromComponents, XcmFeeToAccount, }; use xcm_executor::{ traits::{Identity, JustTry}, @@ -516,6 +516,7 @@ impl xcm_executor::Config for XcmConfig { type CallDispatcher = RuntimeCall; type SafeCallFilter = Everything; type Aliasers = Nothing; + type TransactionalProcessor = FrameTransactionalProcessor; } pub type LocalOriginToLocation = SignedToAccountId32; diff --git a/polkadot/xcm/src/v3/multiasset.rs b/polkadot/xcm/src/v3/multiasset.rs index 557ffa568a4c..1b82b46f1928 100644 --- a/polkadot/xcm/src/v3/multiasset.rs +++ b/polkadot/xcm/src/v3/multiasset.rs @@ -567,7 +567,7 @@ impl TryFrom for MultiAsset { /// A `Vec` of `MultiAsset`s. /// /// There are a number of invariants which the construction and mutation functions must ensure are -/// maintained: +/// maintained in order to maintain polynomial time complexity during iteration: /// - It may contain no items of duplicate asset class; /// - All items must be ordered; /// - The number of items should grow no larger than `MAX_ITEMS_IN_MULTIASSETS`. diff --git a/polkadot/xcm/src/v3/traits.rs b/polkadot/xcm/src/v3/traits.rs index 9e9b983fdf85..cfe387df1a86 100644 --- a/polkadot/xcm/src/v3/traits.rs +++ b/polkadot/xcm/src/v3/traits.rs @@ -470,7 +470,7 @@ pub trait SendXcm { /// Intermediate value which connects the two phases of the send operation. type Ticket; - /// Check whether the given `_message` is deliverable to the given `_destination` and if so + /// Check whether the given `message` is deliverable to the given `destination` and if so /// determine the cost which will be paid by this chain to do so, returning a `Validated` token /// which can be used to enact delivery. /// diff --git a/polkadot/xcm/xcm-builder/src/lib.rs b/polkadot/xcm/xcm-builder/src/lib.rs index c00cd62e8726..e3907eee01e9 100644 --- a/polkadot/xcm/xcm-builder/src/lib.rs +++ b/polkadot/xcm/xcm-builder/src/lib.rs @@ -26,26 +26,6 @@ mod tests; #[cfg(feature = "std")] pub mod test_utils; -mod location_conversion; -#[allow(deprecated)] -pub use location_conversion::ForeignChainAliasAccount; -pub use location_conversion::{ - Account32Hash, AccountId32Aliases, AccountKey20Aliases, AliasesIntoAccountId32, - ChildParachainConvertsVia, DescribeAccountId32Terminal, DescribeAccountIdTerminal, - DescribeAccountKey20Terminal, DescribeAllTerminal, DescribeBodyTerminal, DescribeFamily, - DescribeLocation, DescribePalletTerminal, DescribeTerminus, DescribeTreasuryVoiceTerminal, - GlobalConsensusConvertsFor, GlobalConsensusParachainConvertsFor, HashedDescription, - LocalTreasuryVoiceConvertsVia, ParentIsPreset, SiblingParachainConvertsVia, -}; - -mod origin_conversion; -pub use origin_conversion::{ - BackingToPlurality, ChildParachainAsNative, ChildSystemParachainAsSuperuser, EnsureXcmOrigin, - OriginToPluralityVoice, ParentAsSuperuser, RelayChainAsNative, SiblingParachainAsNative, - SiblingSystemParachainAsSuperuser, SignedAccountId32AsNative, SignedAccountKey20AsNative, - SignedToAccountId32, SovereignSignedViaLocation, -}; - mod asset_conversion; #[allow(deprecated)] pub use asset_conversion::ConvertedConcreteAssetId; @@ -61,8 +41,11 @@ pub use barriers::{ WithComputedOrigin, }; -mod process_xcm_message; -pub use process_xcm_message::ProcessXcmMessage; +mod controller; +pub use controller::{ + Controller, ExecuteController, ExecuteControllerWeightInfo, QueryController, + QueryControllerWeightInfo, QueryHandler, SendController, SendControllerWeightInfo, +}; mod currency_adapter; #[allow(deprecated)] @@ -73,6 +56,9 @@ pub use fee_handling::{ deposit_or_burn_fee, HandleFee, XcmFeeManagerFromComponents, XcmFeeToAccount, }; +mod filter_asset_location; +pub use filter_asset_location::{AllAssets, Case, LocationWithAssetFilters, NativeAsset}; + mod fungible_adapter; pub use fungible_adapter::{FungibleAdapter, FungibleMutateAdapter, FungibleTransferAdapter}; @@ -82,14 +68,16 @@ pub use fungibles_adapter::{ LocalMint, MintLocation, NoChecking, NonLocalMint, }; -mod nonfungibles_adapter; -pub use nonfungibles_adapter::{ - NonFungiblesAdapter, NonFungiblesMutateAdapter, NonFungiblesTransferAdapter, -}; - -mod weight; -pub use weight::{ - FixedRateOfFungible, FixedWeightBounds, TakeRevenue, UsingComponents, WeightInfoBounds, +mod location_conversion; +#[allow(deprecated)] +pub use location_conversion::ForeignChainAliasAccount; +pub use location_conversion::{ + Account32Hash, AccountId32Aliases, AccountKey20Aliases, AliasesIntoAccountId32, + ChildParachainConvertsVia, DescribeAccountId32Terminal, DescribeAccountIdTerminal, + DescribeAccountKey20Terminal, DescribeAllTerminal, DescribeBodyTerminal, DescribeFamily, + DescribeLocation, DescribePalletTerminal, DescribeTerminus, DescribeTreasuryVoiceTerminal, + GlobalConsensusConvertsFor, GlobalConsensusParachainConvertsFor, HashedDescription, + LocalTreasuryVoiceConvertsVia, ParentIsPreset, SiblingParachainConvertsVia, }; mod matches_location; @@ -101,12 +89,34 @@ pub use matches_token::IsConcrete; mod matcher; pub use matcher::{CreateMatcher, MatchXcm, Matcher}; -mod filter_asset_location; -pub use filter_asset_location::{AllAssets, Case, LocationWithAssetFilters, NativeAsset}; +mod nonfungibles_adapter; +pub use nonfungibles_adapter::{ + NonFungiblesAdapter, NonFungiblesMutateAdapter, NonFungiblesTransferAdapter, +}; + +mod origin_aliases; +pub use origin_aliases::AliasForeignAccountId32; + +mod origin_conversion; +pub use origin_conversion::{ + BackingToPlurality, ChildParachainAsNative, ChildSystemParachainAsSuperuser, EnsureXcmOrigin, + OriginToPluralityVoice, ParentAsSuperuser, RelayChainAsNative, SiblingParachainAsNative, + SiblingSystemParachainAsSuperuser, SignedAccountId32AsNative, SignedAccountKey20AsNative, + SignedToAccountId32, SovereignSignedViaLocation, +}; + +mod pay; +pub use pay::{FixedLocation, LocatableAssetId, PayAccountId32OnChainOverXcm, PayOverXcm}; + +mod process_xcm_message; +pub use process_xcm_message::ProcessXcmMessage; mod routing; pub use routing::{WithTopicSource, WithUniqueTopic}; +mod transactional; +pub use transactional::FrameTransactionalProcessor; + mod universal_exports; pub use universal_exports::{ ensure_is_remote, BridgeBlobDispatcher, BridgeMessage, DispatchBlob, DispatchBlobError, @@ -114,14 +124,7 @@ pub use universal_exports::{ NetworkExportTableItem, SovereignPaidRemoteExporter, UnpaidLocalExporter, UnpaidRemoteExporter, }; -mod origin_aliases; -pub use origin_aliases::AliasForeignAccountId32; - -mod pay; -pub use pay::{FixedLocation, LocatableAssetId, PayAccountId32OnChainOverXcm, PayOverXcm}; - -mod controller; -pub use controller::{ - Controller, ExecuteController, ExecuteControllerWeightInfo, QueryController, - QueryControllerWeightInfo, QueryHandler, SendController, SendControllerWeightInfo, +mod weight; +pub use weight::{ + FixedRateOfFungible, FixedWeightBounds, TakeRevenue, UsingComponents, WeightInfoBounds, }; diff --git a/polkadot/xcm/xcm-builder/src/tests/mock.rs b/polkadot/xcm/xcm-builder/src/tests/mock.rs index f561c7d3bd4e..4521d5e92a42 100644 --- a/polkadot/xcm/xcm-builder/src/tests/mock.rs +++ b/polkadot/xcm/xcm-builder/src/tests/mock.rs @@ -742,6 +742,7 @@ impl Config for TestConfig { type CallDispatcher = TestCall; type SafeCallFilter = Everything; type Aliasers = AliasForeignAccountId32; + type TransactionalProcessor = (); } pub fn fungible_multi_asset(location: Location, amount: u128) -> Asset { diff --git a/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs b/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs index 76198f84ed68..91e36b2de4b9 100644 --- a/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs +++ b/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs @@ -175,6 +175,7 @@ type OriginConverter = ( ); type Barrier = AllowUnpaidExecutionFrom; +#[derive(Clone)] pub struct DummyWeightTrader; impl WeightTrader for DummyWeightTrader { fn new() -> Self { @@ -217,6 +218,7 @@ impl xcm_executor::Config for XcmConfig { type CallDispatcher = RuntimeCall; type SafeCallFilter = Everything; type Aliasers = Nothing; + type TransactionalProcessor = (); } parameter_types! { diff --git a/polkadot/xcm/xcm-builder/src/transactional.rs b/polkadot/xcm/xcm-builder/src/transactional.rs new file mode 100644 index 000000000000..ffe379b0ed41 --- /dev/null +++ b/polkadot/xcm/xcm-builder/src/transactional.rs @@ -0,0 +1,40 @@ +// Copyright 2021 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 frame_support::storage::{with_transaction, TransactionOutcome}; +use sp_runtime::DispatchError; +use xcm::latest::prelude::*; +use xcm_executor::traits::ProcessTransaction; + +/// Transactional processor implementation using frame transactional layers. +pub struct FrameTransactionalProcessor; +impl ProcessTransaction for FrameTransactionalProcessor { + const IS_TRANSACTIONAL: bool = true; + + fn process(f: F) -> Result<(), XcmError> + where + F: FnOnce() -> Result<(), XcmError>, + { + with_transaction(|| -> TransactionOutcome> { + let output = f(); + match &output { + Ok(()) => TransactionOutcome::Commit(Ok(output)), + _ => TransactionOutcome::Rollback(Ok(output)), + } + }) + .map_err(|_| XcmError::ExceedsStackLimit)? + } +} diff --git a/polkadot/xcm/xcm-builder/src/weight.rs b/polkadot/xcm/xcm-builder/src/weight.rs index 2ae6a043843f..6026218f5531 100644 --- a/polkadot/xcm/xcm-builder/src/weight.rs +++ b/polkadot/xcm/xcm-builder/src/weight.rs @@ -232,12 +232,13 @@ impl< } fn refund_weight(&mut self, weight: Weight, context: &XcmContext) -> Option { - log::trace!(target: "xcm::weight", "UsingComponents::refund_weight weight: {:?}, context: {:?}", weight, context); + log::trace!(target: "xcm::weight", "UsingComponents::refund_weight weight: {:?}, context: {:?}, available weight: {:?}, available amount: {:?}", weight, context, self.0, self.1); let weight = weight.min(self.0); let amount = WeightToFee::weight_to_fee(&weight); self.0 -= weight; self.1 = self.1.saturating_sub(amount); let amount: u128 = amount.saturated_into(); + log::trace!(target: "xcm::weight", "UsingComponents::refund_weight amount to refund: {:?}", amount); if amount > 0 { Some((AssetIdValue::get(), amount).into()) } else { diff --git a/polkadot/xcm/xcm-builder/tests/mock/mod.rs b/polkadot/xcm/xcm-builder/tests/mock/mod.rs index 73df22561d12..7e08cb779a4a 100644 --- a/polkadot/xcm/xcm-builder/tests/mock/mod.rs +++ b/polkadot/xcm/xcm-builder/tests/mock/mod.rs @@ -212,6 +212,7 @@ impl xcm_executor::Config for XcmConfig { type CallDispatcher = RuntimeCall; type SafeCallFilter = Everything; type Aliasers = Nothing; + type TransactionalProcessor = (); } pub type LocalOriginToLocation = SignedToAccountId32; diff --git a/polkadot/xcm/xcm-executor/src/config.rs b/polkadot/xcm/xcm-executor/src/config.rs index 3f1ea6d1fb8e..ebe532a42fd3 100644 --- a/polkadot/xcm/xcm-executor/src/config.rs +++ b/polkadot/xcm/xcm-executor/src/config.rs @@ -16,8 +16,8 @@ use crate::traits::{ AssetExchange, AssetLock, CallDispatcher, ClaimAssets, ConvertOrigin, DropAssets, ExportXcm, - FeeManager, OnResponse, ShouldExecute, TransactAsset, VersionChangeNotifier, WeightBounds, - WeightTrader, + FeeManager, OnResponse, ProcessTransaction, ShouldExecute, TransactAsset, + VersionChangeNotifier, WeightBounds, WeightTrader, }; use frame_support::{ dispatch::{GetDispatchInfo, Parameter, PostDispatchInfo}, @@ -111,4 +111,7 @@ pub trait Config { /// Use this type to explicitly whitelist calls that cannot undergo recursion. This is a /// temporary measure until we properly account for proof size weights for XCM instructions. type SafeCallFilter: Contains; + + /// Transactional processor for XCM instructions. + type TransactionalProcessor: ProcessTransaction; } diff --git a/polkadot/xcm/xcm-executor/src/lib.rs b/polkadot/xcm/xcm-executor/src/lib.rs index 1f5f2eba5e2f..86304052fbf9 100644 --- a/polkadot/xcm/xcm-executor/src/lib.rs +++ b/polkadot/xcm/xcm-executor/src/lib.rs @@ -19,7 +19,7 @@ use frame_support::{ dispatch::GetDispatchInfo, ensure, - traits::{Contains, ContainsPair, Get, PalletsInfoAccess}, + traits::{Contains, ContainsPair, Defensive, Get, PalletsInfoAccess}, }; use parity_scale_codec::{Decode, Encode}; use sp_core::defer; @@ -31,8 +31,9 @@ use xcm::latest::prelude::*; pub mod traits; use traits::{ validate_export, AssetExchange, AssetLock, CallDispatcher, ClaimAssets, ConvertOrigin, - DropAssets, Enact, ExportXcm, FeeManager, FeeReason, OnResponse, Properties, ShouldExecute, - TransactAsset, VersionChangeNotifier, WeightBounds, WeightTrader, XcmAssetTransfers, + DropAssets, Enact, ExportXcm, FeeManager, FeeReason, OnResponse, ProcessTransaction, + Properties, ShouldExecute, TransactAsset, VersionChangeNotifier, WeightBounds, WeightTrader, + XcmAssetTransfers, }; mod assets; @@ -373,33 +374,53 @@ impl XcmExecutor { r } - fn subsume_asset(&mut self, asset: Asset) -> Result<(), XcmError> { + fn ensure_can_subsume_assets(&self, assets_length: usize) -> Result<(), XcmError> { // worst-case, holding.len becomes 2 * holding_limit. - ensure!(self.holding.len() < self.holding_limit * 2, XcmError::HoldingWouldOverflow); - self.holding.subsume(asset); - Ok(()) - } - - fn subsume_assets(&mut self, assets: AssetsInHolding) -> Result<(), XcmError> { - // worst-case, holding.len becomes 2 * holding_limit. - // this guarantees that if holding.len() == holding_limit and you have holding_limit more - // items (which has a best case outcome of holding.len() == holding_limit), then you'll - // be guaranteed of making the operation. - let worst_case_holding_len = self.holding.len() + assets.len(); + // this guarantees that if holding.len() == holding_limit and you have more than + // `holding_limit` items (which has a best case outcome of holding.len() == holding_limit), + // then the operation is guaranteed to succeed. + let worst_case_holding_len = self.holding.len() + assets_length; + log::trace!(target: "xcm::ensure_can_subsume_assets", "worst_case_holding_len: {:?}, holding_limit: {:?}", worst_case_holding_len, self.holding_limit); ensure!(worst_case_holding_len <= self.holding_limit * 2, XcmError::HoldingWouldOverflow); - self.holding.subsume_assets(assets); Ok(()) } /// Refund any unused weight. fn refund_surplus(&mut self) -> Result<(), XcmError> { let current_surplus = self.total_surplus.saturating_sub(self.total_refunded); + log::trace!( + target: "xcm::refund_surplus", + "total_surplus: {:?}, total_refunded: {:?}, current_surplus: {:?}", + self.total_surplus, + self.total_refunded, + current_surplus, + ); if current_surplus.any_gt(Weight::zero()) { - self.total_refunded.saturating_accrue(current_surplus); if let Some(w) = self.trader.refund_weight(current_surplus, &self.context) { - self.subsume_asset(w)?; + if !self.holding.contains_asset(&(w.id.clone(), 1).into()) && + self.ensure_can_subsume_assets(1).is_err() + { + let _ = self + .trader + .buy_weight(current_surplus, w.into(), &self.context) + .defensive_proof( + "refund_weight returned an asset capable of buying weight; qed", + ); + log::error!( + target: "xcm::refund_surplus", + "error: HoldingWouldOverflow", + ); + return Err(XcmError::HoldingWouldOverflow) + } + self.total_refunded.saturating_accrue(current_surplus); + self.holding.subsume_assets(w.into()); } } + log::trace!( + target: "xcm::refund_surplus", + "total_refunded: {:?}", + self.total_refunded, + ); Ok(()) } @@ -554,75 +575,101 @@ impl XcmExecutor { ); match instr { WithdrawAsset(assets) => { - let origin = self.cloned_origin().ok_or(XcmError::BadOrigin)?; - // Take `assets` from the origin account (on-chain) and place in holding. - for asset in assets.into_inner().into_iter() { - Config::AssetTransactor::withdraw_asset(&asset, &origin, Some(&self.context))?; - self.subsume_asset(asset)?; - } - Ok(()) + let origin = self.origin_ref().ok_or(XcmError::BadOrigin)?; + self.ensure_can_subsume_assets(assets.len())?; + Config::TransactionalProcessor::process(|| { + // Take `assets` from the origin account (on-chain)... + for asset in assets.inner() { + Config::AssetTransactor::withdraw_asset( + asset, + origin, + Some(&self.context), + )?; + } + Ok(()) + }) + .and_then(|_| { + // ...and place into holding. + self.holding.subsume_assets(assets.into()); + Ok(()) + }) }, ReserveAssetDeposited(assets) => { // check whether we trust origin to be our reserve location for this asset. - for asset in assets.into_inner().into_iter() { - let origin = self.cloned_origin().ok_or(XcmError::BadOrigin)?; + let origin = self.origin_ref().ok_or(XcmError::BadOrigin)?; + self.ensure_can_subsume_assets(assets.len())?; + for asset in assets.inner() { // Must ensure that we recognise the asset as being managed by the origin. ensure!( - Config::IsReserve::contains(&asset, &origin), + Config::IsReserve::contains(asset, origin), XcmError::UntrustedReserveLocation ); - self.subsume_asset(asset)?; } + self.holding.subsume_assets(assets.into()); Ok(()) }, TransferAsset { assets, beneficiary } => { - // Take `assets` from the origin account (on-chain) and place into dest account. - let origin = self.origin_ref().ok_or(XcmError::BadOrigin)?; - for asset in assets.inner() { - Config::AssetTransactor::transfer_asset( - &asset, - origin, - &beneficiary, - &self.context, - )?; - } - Ok(()) + Config::TransactionalProcessor::process(|| { + // Take `assets` from the origin account (on-chain) and place into dest account. + let origin = self.origin_ref().ok_or(XcmError::BadOrigin)?; + for asset in assets.inner() { + Config::AssetTransactor::transfer_asset( + &asset, + origin, + &beneficiary, + &self.context, + )?; + } + Ok(()) + }) }, TransferReserveAsset { mut assets, dest, xcm } => { - let origin = self.origin_ref().ok_or(XcmError::BadOrigin)?; - // Take `assets` from the origin account (on-chain) and place into dest account. - for asset in assets.inner() { - Config::AssetTransactor::transfer_asset(asset, origin, &dest, &self.context)?; - } - let reanchor_context = Config::UniversalLocation::get(); - assets.reanchor(&dest, &reanchor_context).map_err(|()| XcmError::LocationFull)?; - let mut message = vec![ReserveAssetDeposited(assets), ClearOrigin]; - message.extend(xcm.0.into_iter()); - self.send(dest, Xcm(message), FeeReason::TransferReserveAsset)?; - Ok(()) + Config::TransactionalProcessor::process(|| { + let origin = self.origin_ref().ok_or(XcmError::BadOrigin)?; + // Take `assets` from the origin account (on-chain) and place into dest account. + for asset in assets.inner() { + Config::AssetTransactor::transfer_asset( + asset, + origin, + &dest, + &self.context, + )?; + } + let reanchor_context = Config::UniversalLocation::get(); + assets + .reanchor(&dest, &reanchor_context) + .map_err(|()| XcmError::LocationFull)?; + let mut message = vec![ReserveAssetDeposited(assets), ClearOrigin]; + message.extend(xcm.0.into_iter()); + self.send(dest, Xcm(message), FeeReason::TransferReserveAsset)?; + Ok(()) + }) }, ReceiveTeleportedAsset(assets) => { - let origin = self.cloned_origin().ok_or(XcmError::BadOrigin)?; - // check whether we trust origin to teleport this asset to us via config trait. - for asset in assets.inner() { - // We only trust the origin to send us assets that they identify as their - // sovereign assets. - ensure!( - Config::IsTeleporter::contains(asset, &origin), - XcmError::UntrustedTeleportLocation - ); - // We should check that the asset can actually be teleported in (for this to be - // in error, there would need to be an accounting violation by one of the - // trusted chains, so it's unlikely, but we don't want to punish a possibly - // innocent chain/user). - Config::AssetTransactor::can_check_in(&origin, asset, &self.context)?; - } - for asset in assets.into_inner().into_iter() { - let origin = self.origin_ref().ok_or(XcmError::BadOrigin)?; - Config::AssetTransactor::check_in(&origin, &asset, &self.context); - self.subsume_asset(asset)?; - } - Ok(()) + let origin = self.origin_ref().ok_or(XcmError::BadOrigin)?; + self.ensure_can_subsume_assets(assets.len())?; + Config::TransactionalProcessor::process(|| { + // check whether we trust origin to teleport this asset to us via config trait. + for asset in assets.inner() { + // We only trust the origin to send us assets that they identify as their + // sovereign assets. + ensure!( + Config::IsTeleporter::contains(asset, origin), + XcmError::UntrustedTeleportLocation + ); + // We should check that the asset can actually be teleported in (for this to + // be in error, there would need to be an accounting violation by one of the + // trusted chains, so it's unlikely, but we don't want to punish a possibly + // innocent chain/user). + Config::AssetTransactor::can_check_in(origin, asset, &self.context)?; + Config::AssetTransactor::check_in(origin, asset, &self.context); + } + Ok(()) + }) + .and_then(|_| { + self.holding.subsume_assets(assets.into()); + Ok(()) + }) }, Transact { origin_kind, require_weight_at_most, mut call } => { // We assume that the Relay-chain is allowed to use transact on this parachain. @@ -755,62 +802,92 @@ impl XcmExecutor { Ok(()) }, DepositAsset { assets, beneficiary } => { - let deposited = self.holding.saturating_take(assets); - for asset in deposited.into_assets_iter() { - Config::AssetTransactor::deposit_asset( - &asset, - &beneficiary, - Some(&self.context), - )?; + let old_holding = self.holding.clone(); + let result = Config::TransactionalProcessor::process(|| { + let deposited = self.holding.saturating_take(assets); + for asset in deposited.into_assets_iter() { + Config::AssetTransactor::deposit_asset( + &asset, + &beneficiary, + Some(&self.context), + )?; + } + Ok(()) + }); + if Config::TransactionalProcessor::IS_TRANSACTIONAL && result.is_err() { + self.holding = old_holding; } - Ok(()) + result }, DepositReserveAsset { assets, dest, xcm } => { - let deposited = self.holding.saturating_take(assets); - for asset in deposited.assets_iter() { - Config::AssetTransactor::deposit_asset(&asset, &dest, Some(&self.context))?; + let old_holding = self.holding.clone(); + let result = Config::TransactionalProcessor::process(|| { + let deposited = self.holding.saturating_take(assets); + for asset in deposited.assets_iter() { + Config::AssetTransactor::deposit_asset(&asset, &dest, Some(&self.context))?; + } + // Note that we pass `None` as `maybe_failed_bin` and drop any assets which + // cannot be reanchored because we have already called `deposit_asset` on all + // assets. + let assets = Self::reanchored(deposited, &dest, None); + let mut message = vec![ReserveAssetDeposited(assets), ClearOrigin]; + message.extend(xcm.0.into_iter()); + self.send(dest, Xcm(message), FeeReason::DepositReserveAsset)?; + Ok(()) + }); + if Config::TransactionalProcessor::IS_TRANSACTIONAL && result.is_err() { + self.holding = old_holding; } - // Note that we pass `None` as `maybe_failed_bin` and drop any assets which cannot - // be reanchored because we have already called `deposit_asset` on all assets. - let assets = Self::reanchored(deposited, &dest, None); - let mut message = vec![ReserveAssetDeposited(assets), ClearOrigin]; - message.extend(xcm.0.into_iter()); - self.send(dest, Xcm(message), FeeReason::DepositReserveAsset)?; - Ok(()) + result }, InitiateReserveWithdraw { assets, reserve, xcm } => { - // Note that here we are able to place any assets which could not be reanchored - // back into Holding. - let assets = Self::reanchored( - self.holding.saturating_take(assets), - &reserve, - Some(&mut self.holding), - ); - let mut message = vec![WithdrawAsset(assets), ClearOrigin]; - message.extend(xcm.0.into_iter()); - self.send(reserve, Xcm(message), FeeReason::InitiateReserveWithdraw)?; - Ok(()) + let old_holding = self.holding.clone(); + let result = Config::TransactionalProcessor::process(|| { + // Note that here we are able to place any assets which could not be reanchored + // back into Holding. + let assets = Self::reanchored( + self.holding.saturating_take(assets), + &reserve, + Some(&mut self.holding), + ); + let mut message = vec![WithdrawAsset(assets), ClearOrigin]; + message.extend(xcm.0.into_iter()); + self.send(reserve, Xcm(message), FeeReason::InitiateReserveWithdraw)?; + Ok(()) + }); + if Config::TransactionalProcessor::IS_TRANSACTIONAL && result.is_err() { + self.holding = old_holding; + } + result }, InitiateTeleport { assets, dest, xcm } => { - // We must do this first in order to resolve wildcards. - let assets = self.holding.saturating_take(assets); - for asset in assets.assets_iter() { - // We should check that the asset can actually be teleported out (for this to - // be in error, there would need to be an accounting violation by ourselves, - // so it's unlikely, but we don't want to allow that kind of bug to leak into - // a trusted chain. - Config::AssetTransactor::can_check_out(&dest, &asset, &self.context)?; - } - for asset in assets.assets_iter() { - Config::AssetTransactor::check_out(&dest, &asset, &self.context); + let old_holding = self.holding.clone(); + let result = (|| -> Result<(), XcmError> { + // We must do this first in order to resolve wildcards. + let assets = self.holding.saturating_take(assets); + for asset in assets.assets_iter() { + // We should check that the asset can actually be teleported out (for this + // to be in error, there would need to be an accounting violation by + // ourselves, so it's unlikely, but we don't want to allow that kind of bug + // to leak into a trusted chain. + Config::AssetTransactor::can_check_out(&dest, &asset, &self.context)?; + } + // Note that we pass `None` as `maybe_failed_bin` and drop any assets which + // cannot be reanchored because we have already checked all assets out. + let reanchored_assets = Self::reanchored(assets.clone(), &dest, None); + let mut message = vec![ReceiveTeleportedAsset(reanchored_assets), ClearOrigin]; + message.extend(xcm.0.into_iter()); + self.send(dest.clone(), Xcm(message), FeeReason::InitiateTeleport)?; + + for asset in assets.assets_iter() { + Config::AssetTransactor::check_out(&dest, &asset, &self.context); + } + Ok(()) + })(); + if result.is_err() { + self.holding = old_holding; } - // Note that we pass `None` as `maybe_failed_bin` and drop any assets which cannot - // be reanchored because we have already checked all assets out. - let assets = Self::reanchored(assets, &dest, None); - let mut message = vec![ReceiveTeleportedAsset(assets), ClearOrigin]; - message.extend(xcm.0.into_iter()); - self.send(dest, Xcm(message), FeeReason::InitiateTeleport)?; - Ok(()) + result }, ReportHolding { response_info, assets } => { // Note that we pass `None` as `maybe_failed_bin` since no assets were ever removed @@ -826,18 +903,24 @@ impl XcmExecutor { Ok(()) }, BuyExecution { fees, weight_limit } => { - // There is no need to buy any weight is `weight_limit` is `Unlimited` since it + // There is no need to buy any weight if `weight_limit` is `Unlimited` since it // would indicate that `AllowTopLevelPaidExecutionFrom` was unused for execution // and thus there is some other reason why it has been determined that this XCM // should be executed. - if let Some(weight) = Option::::from(weight_limit) { - // pay for `weight` using up to `fees` of the holding register. - let max_fee = - self.holding.try_take(fees.into()).map_err(|_| XcmError::NotHoldingFees)?; + let Some(weight) = Option::::from(weight_limit) else { return Ok(()) }; + let old_holding = self.holding.clone(); + // pay for `weight` using up to `fees` of the holding register. + let max_fee = + self.holding.try_take(fees.into()).map_err(|_| XcmError::NotHoldingFees)?; + let result = || -> Result<(), XcmError> { let unspent = self.trader.buy_weight(weight, max_fee, &self.context)?; - self.subsume_assets(unspent)?; + self.holding.subsume_assets(unspent); + Ok(()) + }(); + if result.is_err() { + self.holding = old_holding; } - Ok(()) + result }, RefundSurplus => self.refund_surplus(), SetErrorHandler(mut handler) => { @@ -862,11 +945,10 @@ impl XcmExecutor { }, ClaimAsset { assets, ticket } => { let origin = self.origin_ref().ok_or(XcmError::BadOrigin)?; + self.ensure_can_subsume_assets(assets.len())?; let ok = Config::AssetClaims::claim_assets(origin, &ticket, &assets, &self.context); ensure!(ok, XcmError::UnknownClaim); - for asset in assets.into_inner().into_iter() { - self.subsume_asset(asset)?; - } + self.holding.subsume_assets(assets.into()); Ok(()) }, Trap(code) => Err(XcmError::Trap(code)), @@ -984,8 +1066,8 @@ impl XcmExecutor { let hash = (self.origin_ref(), &destination).using_encoded(blake2_128); let channel = u32::decode(&mut hash.as_ref()).unwrap_or(0); // Hash identifies the lane on the exporter which we use. We use the pairwise - // combination of the origin and destination to ensure origin/destination pairs will - // generally have their own lanes. + // combination of the origin and destination to ensure origin/destination pairs + // will generally have their own lanes. let (ticket, fee) = validate_export::( network, channel, @@ -993,23 +1075,41 @@ impl XcmExecutor { destination.clone(), xcm, )?; - self.take_fee(fee, FeeReason::Export { network, destination })?; - Config::MessageExporter::deliver(ticket)?; - Ok(()) + let old_holding = self.holding.clone(); + let result = Config::TransactionalProcessor::process(|| { + self.take_fee(fee, FeeReason::Export { network, destination })?; + let _ = Config::MessageExporter::deliver(ticket).defensive_proof( + "`deliver` called immediately after `validate_export`; \ + `take_fee` does not affect the validity of the ticket; qed", + ); + Ok(()) + }); + if Config::TransactionalProcessor::IS_TRANSACTIONAL && result.is_err() { + self.holding = old_holding; + } + result }, LockAsset { asset, unlocker } => { - let origin = self.cloned_origin().ok_or(XcmError::BadOrigin)?; - let (remote_asset, context) = Self::try_reanchor(asset.clone(), &unlocker)?; - let lock_ticket = - Config::AssetLocker::prepare_lock(unlocker.clone(), asset, origin.clone())?; - let owner = - origin.reanchored(&unlocker, &context).map_err(|_| XcmError::ReanchorFailed)?; - let msg = Xcm::<()>(vec![NoteUnlockable { asset: remote_asset, owner }]); - let (ticket, price) = validate_send::(unlocker, msg)?; - self.take_fee(price, FeeReason::LockAsset)?; - lock_ticket.enact()?; - Config::XcmSender::deliver(ticket)?; - Ok(()) + let old_holding = self.holding.clone(); + let result = Config::TransactionalProcessor::process(|| { + let origin = self.cloned_origin().ok_or(XcmError::BadOrigin)?; + let (remote_asset, context) = Self::try_reanchor(asset.clone(), &unlocker)?; + let lock_ticket = + Config::AssetLocker::prepare_lock(unlocker.clone(), asset, origin.clone())?; + let owner = origin + .reanchored(&unlocker, &context) + .map_err(|_| XcmError::ReanchorFailed)?; + let msg = Xcm::<()>(vec![NoteUnlockable { asset: remote_asset, owner }]); + let (ticket, price) = validate_send::(unlocker, msg)?; + self.take_fee(price, FeeReason::LockAsset)?; + lock_ticket.enact()?; + Config::XcmSender::deliver(ticket)?; + Ok(()) + }); + if Config::TransactionalProcessor::IS_TRANSACTIONAL && result.is_err() { + self.holding = old_holding; + } + result }, UnlockAsset { asset, target } => { let origin = self.cloned_origin().ok_or(XcmError::BadOrigin)?; @@ -1033,25 +1133,40 @@ impl XcmExecutor { let msg = Xcm::<()>(vec![UnlockAsset { asset: remote_asset, target: remote_target }]); let (ticket, price) = validate_send::(locker, msg)?; - self.take_fee(price, FeeReason::RequestUnlock)?; - reduce_ticket.enact()?; - Config::XcmSender::deliver(ticket)?; - Ok(()) + let old_holding = self.holding.clone(); + let result = Config::TransactionalProcessor::process(|| { + self.take_fee(price, FeeReason::RequestUnlock)?; + reduce_ticket.enact()?; + Config::XcmSender::deliver(ticket)?; + Ok(()) + }); + if Config::TransactionalProcessor::IS_TRANSACTIONAL && result.is_err() { + self.holding = old_holding; + } + result }, ExchangeAsset { give, want, maximal } => { + let old_holding = self.holding.clone(); let give = self.holding.saturating_take(give); - let r = - Config::AssetExchanger::exchange_asset(self.origin_ref(), give, &want, maximal); - let completed = r.is_ok(); - let received = r.unwrap_or_else(|a| a); - for asset in received.into_assets_iter() { - self.holding.subsume(asset); - } - if completed { - Ok(()) - } else { - Err(XcmError::NoDeal) + let result = (|| -> Result<(), XcmError> { + self.ensure_can_subsume_assets(want.len())?; + let exchange_result = Config::AssetExchanger::exchange_asset( + self.origin_ref(), + give, + &want, + maximal, + ); + if let Ok(received) = exchange_result { + self.holding.subsume_assets(received.into()); + Ok(()) + } else { + Err(XcmError::NoDeal) + } + })(); + if result.is_err() { + self.holding = old_holding; } + result }, SetFeesMode { jit_withdraw } => { self.fees_mode = FeesMode { jit_withdraw }; diff --git a/polkadot/xcm/xcm-executor/src/traits/mod.rs b/polkadot/xcm/xcm-executor/src/traits/mod.rs index 71e75c77e939..b445e84d3912 100644 --- a/polkadot/xcm/xcm-executor/src/traits/mod.rs +++ b/polkadot/xcm/xcm-executor/src/traits/mod.rs @@ -39,6 +39,8 @@ pub use token_matching::{ }; mod on_response; pub use on_response::{OnResponse, QueryHandler, QueryResponseStatus, VersionChangeNotifier}; +mod process_transaction; +pub use process_transaction::ProcessTransaction; mod should_execute; pub use should_execute::{CheckSuspension, Properties, ShouldExecute}; mod transact_asset; @@ -52,8 +54,9 @@ pub mod prelude { pub use super::{ export_xcm, validate_export, AssetExchange, AssetLock, ClaimAssets, ConvertOrigin, DropAssets, Enact, Error, ExportXcm, FeeManager, FeeReason, LockError, MatchesFungible, - MatchesFungibles, MatchesNonFungible, MatchesNonFungibles, OnResponse, ShouldExecute, - TransactAsset, VersionChangeNotifier, WeightBounds, WeightTrader, WithOriginFilter, + MatchesFungibles, MatchesNonFungible, MatchesNonFungibles, OnResponse, ProcessTransaction, + ShouldExecute, TransactAsset, VersionChangeNotifier, WeightBounds, WeightTrader, + WithOriginFilter, }; #[allow(deprecated)] pub use super::{Identity, JustTry}; diff --git a/polkadot/xcm/xcm-executor/src/traits/process_transaction.rs b/polkadot/xcm/xcm-executor/src/traits/process_transaction.rs new file mode 100644 index 000000000000..22ad8755b9c9 --- /dev/null +++ b/polkadot/xcm/xcm-executor/src/traits/process_transaction.rs @@ -0,0 +1,57 @@ +// Copyright 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 xcm::latest::prelude::*; + +/// Provides mechanisms for transactional processing of XCM instructions. +/// +/// This trait defines the behavior required to process XCM instructions in a transactional +/// manner. Implementers of this trait can ensure that XCM instructions are executed +/// atomically, meaning they either fully succeed or fully fail without any partial effects. +/// +/// Implementers of this trait can also choose to not process XCM instructions transactionally. +/// This is useful for cases where the implementer is not able to provide transactional guarantees. +/// In this case the `IS_TRANSACTIONAL` constant should be set to `false`. +/// The `()` type implements this trait in a non-transactional manner. +pub trait ProcessTransaction { + /// Whether or not the implementor of the this trait is actually transactional. + const IS_TRANSACTIONAL: bool; + + /// Processes an XCM instruction encapsulated within the provided closure. Responsible for + /// processing an XCM instruction transactionally. If the closure returns an error, any + /// changes made during its execution should be rolled back. In the case where the + /// implementer is not able to provide transactional guarantees, the closure should be + /// executed as is. + /// # Parameters + /// - `f`: A closure that encapsulates the XCM instruction being processed. It will return a + /// `Result` indicating the success or failure of the instruction. + /// + /// # Returns + /// - A `Result` indicating the overall success or failure of the transactional process. + fn process(f: F) -> Result<(), XcmError> + where + F: FnOnce() -> Result<(), XcmError>; +} + +impl ProcessTransaction for () { + const IS_TRANSACTIONAL: bool = false; + fn process(f: F) -> Result<(), XcmError> + where + F: FnOnce() -> Result<(), XcmError>, + { + f() + } +} diff --git a/polkadot/xcm/xcm-simulator/example/src/parachain.rs b/polkadot/xcm/xcm-simulator/example/src/parachain.rs index 3adfa95d2e85..9c9f481242f5 100644 --- a/polkadot/xcm/xcm-simulator/example/src/parachain.rs +++ b/polkadot/xcm/xcm-simulator/example/src/parachain.rs @@ -40,9 +40,10 @@ use polkadot_parachain_primitives::primitives::{ use xcm::{latest::prelude::*, VersionedXcm}; use xcm_builder::{ Account32Hash, AccountId32Aliases, AllowUnpaidExecutionFrom, ConvertedConcreteId, - EnsureXcmOrigin, FixedRateOfFungible, FixedWeightBounds, FungibleAdapter, IsConcrete, - NativeAsset, NoChecking, NonFungiblesAdapter, ParentIsPreset, SiblingParachainConvertsVia, - SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, + EnsureXcmOrigin, FixedRateOfFungible, FixedWeightBounds, FrameTransactionalProcessor, + FungibleAdapter, IsConcrete, NativeAsset, NoChecking, NonFungiblesAdapter, ParentIsPreset, + SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, + SovereignSignedViaLocation, }; use xcm_executor::{ traits::{ConvertLocation, JustTry}, @@ -250,6 +251,7 @@ impl Config for XcmConfig { type CallDispatcher = RuntimeCall; type SafeCallFilter = Everything; type Aliasers = Nothing; + type TransactionalProcessor = FrameTransactionalProcessor; } #[frame_support::pallet] diff --git a/polkadot/xcm/xcm-simulator/example/src/relay_chain.rs b/polkadot/xcm/xcm-simulator/example/src/relay_chain.rs index d9ed6e800aa2..d96b39aca631 100644 --- a/polkadot/xcm/xcm-simulator/example/src/relay_chain.rs +++ b/polkadot/xcm/xcm-simulator/example/src/relay_chain.rs @@ -36,9 +36,9 @@ use xcm::latest::prelude::*; use xcm_builder::{ Account32Hash, AccountId32Aliases, AllowUnpaidExecutionFrom, AsPrefixedGeneralIndex, ChildParachainAsNative, ChildParachainConvertsVia, ChildSystemParachainAsSuperuser, - ConvertedConcreteId, FixedRateOfFungible, FixedWeightBounds, FungibleAdapter, IsConcrete, - NoChecking, NonFungiblesAdapter, SignedAccountId32AsNative, SignedToAccountId32, - SovereignSignedViaLocation, + ConvertedConcreteId, FixedRateOfFungible, FixedWeightBounds, FrameTransactionalProcessor, + FungibleAdapter, IsConcrete, NoChecking, NonFungiblesAdapter, SignedAccountId32AsNative, + SignedToAccountId32, SovereignSignedViaLocation, }; use xcm_executor::{traits::JustTry, Config, XcmExecutor}; @@ -198,6 +198,7 @@ impl Config for XcmConfig { type CallDispatcher = RuntimeCall; type SafeCallFilter = Everything; type Aliasers = Nothing; + type TransactionalProcessor = FrameTransactionalProcessor; } pub type LocalOriginToLocation = SignedToAccountId32; diff --git a/polkadot/xcm/xcm-simulator/fuzzer/src/parachain.rs b/polkadot/xcm/xcm-simulator/fuzzer/src/parachain.rs index 8a89f8cb0e76..36db24b35a6e 100644 --- a/polkadot/xcm/xcm-simulator/fuzzer/src/parachain.rs +++ b/polkadot/xcm/xcm-simulator/fuzzer/src/parachain.rs @@ -41,8 +41,9 @@ use xcm::{latest::prelude::*, VersionedXcm}; use xcm_builder::CurrencyAdapter as XcmCurrencyAdapter; use xcm_builder::{ AccountId32Aliases, AllowUnpaidExecutionFrom, EnsureXcmOrigin, FixedRateOfFungible, - FixedWeightBounds, IsConcrete, NativeAsset, ParentIsPreset, SiblingParachainConvertsVia, - SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, + FixedWeightBounds, FrameTransactionalProcessor, IsConcrete, NativeAsset, ParentIsPreset, + SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, + SovereignSignedViaLocation, }; use xcm_executor::{Config, XcmExecutor}; @@ -166,6 +167,7 @@ impl Config for XcmConfig { type CallDispatcher = RuntimeCall; type SafeCallFilter = Everything; type Aliasers = Nothing; + type TransactionalProcessor = FrameTransactionalProcessor; } #[frame_support::pallet] diff --git a/polkadot/xcm/xcm-simulator/fuzzer/src/relay_chain.rs b/polkadot/xcm/xcm-simulator/fuzzer/src/relay_chain.rs index 143f8974f3e8..7879d781bd3e 100644 --- a/polkadot/xcm/xcm-simulator/fuzzer/src/relay_chain.rs +++ b/polkadot/xcm/xcm-simulator/fuzzer/src/relay_chain.rs @@ -38,8 +38,8 @@ use xcm_builder::CurrencyAdapter as XcmCurrencyAdapter; use xcm_builder::{ AccountId32Aliases, AllowUnpaidExecutionFrom, ChildParachainAsNative, ChildParachainConvertsVia, ChildSystemParachainAsSuperuser, FixedRateOfFungible, - FixedWeightBounds, IsConcrete, SignedAccountId32AsNative, SignedToAccountId32, - SovereignSignedViaLocation, + FixedWeightBounds, FrameTransactionalProcessor, IsConcrete, SignedAccountId32AsNative, + SignedToAccountId32, SovereignSignedViaLocation, }; use xcm_executor::{Config, XcmExecutor}; @@ -165,6 +165,7 @@ impl Config for XcmConfig { type CallDispatcher = RuntimeCall; type SafeCallFilter = Everything; type Aliasers = Nothing; + type TransactionalProcessor = FrameTransactionalProcessor; } pub type LocalOriginToLocation = SignedToAccountId32; diff --git a/prdoc/pr_1222.prdoc b/prdoc/pr_1222.prdoc new file mode 100644 index 000000000000..82eb341649bc --- /dev/null +++ b/prdoc/pr_1222.prdoc @@ -0,0 +1,33 @@ +title: Transactional processing for XCM + +doc: + - audience: Runtime Dev + description: | + Transactional processing was introduced for certain XCM instructions. They are: + - WithdrawAsset + - ReserveAssetDeposited + - TransferAsset + - TransferReserveAsset + - ReceiveTeleportedAsset + - DepositAsset + - DepositReserveAsset + - InitiateReserveWithdraw + - InitiateTeleport + - BuyExecution + - ClaimAsset + - ExportMessage + - LockAsset + - UnlockAsset + - RequestUnlock + Developers must specify a `TransactionalProcessor` when configuring their XCM executor. + FRAME-based runtimes would simply need to configure it with `FrameTransactionalProcessor` to + enable transactional processing. To disable transactional processing of XCMs, `()` may also be + specified as the type for `TransactionalProcessor`. + For runtimes that are not FRAME-based but would like to still harness transactional processing + of XCMs, a type implementing the `ProcessTransaction` trait must be specified as the type for + `TransactionalProcessor`. This trait is for the purpose of connecting the chain's runtime + transactional processor with the XCM executor -- any implementation of `ProcessTransaction` is + possible to be assigned as the `TransactionalProcessor` for the XCM executor. + +crates: + - name: staging-xcm-executor diff --git a/substrate/frame/contracts/mock-network/src/parachain.rs b/substrate/frame/contracts/mock-network/src/parachain.rs index 90fc23af48d3..03fcef1a56c3 100644 --- a/substrate/frame/contracts/mock-network/src/parachain.rs +++ b/substrate/frame/contracts/mock-network/src/parachain.rs @@ -41,9 +41,10 @@ use xcm::latest::prelude::*; use xcm_builder::CurrencyAdapter as XcmCurrencyAdapter; use xcm_builder::{ AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowTopLevelPaidExecutionFrom, - ConvertedConcreteId, EnsureXcmOrigin, FixedRateOfFungible, FixedWeightBounds, FungiblesAdapter, - IsConcrete, NativeAsset, NoChecking, ParentAsSuperuser, ParentIsPreset, - SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, WithComputedOrigin, + ConvertedConcreteId, EnsureXcmOrigin, FixedRateOfFungible, FixedWeightBounds, + FrameTransactionalProcessor, FungiblesAdapter, IsConcrete, NativeAsset, NoChecking, + ParentAsSuperuser, ParentIsPreset, SignedAccountId32AsNative, SignedToAccountId32, + SovereignSignedViaLocation, WithComputedOrigin, }; use xcm_executor::{traits::JustTry, Config, XcmExecutor}; @@ -284,6 +285,7 @@ impl Config for XcmConfig { type CallDispatcher = RuntimeCall; type SafeCallFilter = Everything; type Aliasers = Nothing; + type TransactionalProcessor = FrameTransactionalProcessor; } impl mock_msg_queue::Config for Runtime { diff --git a/substrate/frame/contracts/mock-network/src/relay_chain.rs b/substrate/frame/contracts/mock-network/src/relay_chain.rs index 9671857fb788..8bb33ff5de8e 100644 --- a/substrate/frame/contracts/mock-network/src/relay_chain.rs +++ b/substrate/frame/contracts/mock-network/src/relay_chain.rs @@ -35,8 +35,8 @@ use xcm_builder::{ AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, ChildParachainAsNative, ChildParachainConvertsVia, ChildSystemParachainAsSuperuser, DescribeAllTerminal, DescribeFamily, FixedRateOfFungible, - FixedWeightBounds, HashedDescription, IsConcrete, SignedAccountId32AsNative, - SignedToAccountId32, SovereignSignedViaLocation, WithComputedOrigin, + FixedWeightBounds, FrameTransactionalProcessor, HashedDescription, IsConcrete, + SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, WithComputedOrigin, }; use xcm_executor::{Config, XcmExecutor}; @@ -185,6 +185,7 @@ impl Config for XcmConfig { type CallDispatcher = RuntimeCall; type SafeCallFilter = Everything; type Aliasers = Nothing; + type TransactionalProcessor = FrameTransactionalProcessor; } pub type LocalOriginToLocation = SignedToAccountId32;