XCM Config¶
Introduction¶
The XCM executor is a crucial component responsible for interpreting and executing XCM messages (XCMs) with Polkadot SDK-based chains. It processes and manages XCM instructions, ensuring they are executed correctly and in sequentially. Adhering to the Cross-Consensus Virtual Machine (XCVM) specification, the XCM executor can be customized or replaced with an alternative that also complies with the XCVM standards.
The XcmExecutor
is not a pallet but a struct parameterized by a Config
trait. The Config
trait is the inner configuration, parameterizing the outer XcmExecutor<Config>
struct. Both configurations are set up within the runtime.
The executor is highly configurable, with the XCM builder offering building blocks to tailor the configuration to specific needs. While they serve as a foundation, users can easily create custom blocks to suit unique configurations. Users can also create their building blocks to address unique needs. This article examines the XCM configuration process, explains each configurable item, and provides examples of the tools and types available to help customize these settings.
XCM Executor Configuration¶
The Config
trait defines the XCM executor’s configuration, which requires several associated types. Each type has specific trait bounds that the concrete implementation must fulfill. Some types, such as RuntimeCall
, come with a default implementation in most cases, while others use the unit type ()
as the default. For many of these types, selecting the appropriate implementation carefully is crucial. Predefined solutions and building blocks can be adapted to your specific needs. These solutions can be found in the xcm-builder
folder.
Each type is explained below, along with an overview of some of its implementations:
pub trait Config {
type RuntimeCall: Parameter + Dispatchable<PostInfo = PostDispatchInfo> + GetDispatchInfo;
type XcmSender: SendXcm;
type AssetTransactor: TransactAsset;
type OriginConverter: ConvertOrigin<<Self::RuntimeCall as Dispatchable>::RuntimeOrigin>;
type IsReserve: ContainsPair<MultiAsset, MultiLocation>;
type IsTeleporter: ContainsPair<MultiAsset, MultiLocation>;
type Aliasers: ContainsPair<Location, Location>;
type UniversalLocation: Get<InteriorMultiLocation>;
type Barrier: ShouldExecute;
type Weigher: WeightBounds<Self::RuntimeCall>;
type Trader: WeightTrader;
type ResponseHandler: OnResponse;
type AssetTrap: DropAssets;
type AssetClaims: ClaimAssets;
type AssetLocker: AssetLock;
type AssetExchanger: AssetExchange;
type SubscriptionService: VersionChangeNotifier;
type PalletInstancesInfo: PalletsInfoAccess;
type MaxAssetsIntoHolding: Get<u32>;
type FeeManager: FeeManager;
type MessageExporter: ExportXcm;
type UniversalAliases: Contains<(MultiLocation, Junction)>;
type CallDispatcher: CallDispatcher<Self::RuntimeCall>;
type SafeCallFilter: Contains<Self::RuntimeCall>;
type TransactionalProcessor: ProcessTransaction;
type HrmpNewChannelOpenRequestHandler: HandleHrmpNewChannelOpenRequest;
type HrmpChannelAcceptedHandler: HandleHrmpChannelAccepted;
type HrmpChannelClosingHandler: HandleHrmpChannelClosing;
type XcmRecorder: RecordXcm;
}
Config Items¶
Each configuration item is explained below, detailing the associated type’s purpose and role in the XCM executor. Many of these types have predefined solutions available in the xcm-builder
. Therefore, the available configuration items are:
-
The associated traits signify:RuntimeCall
- defines the runtime's callable functions, created via theframe::runtime
macro. It represents an enum listing the callable functions of all implemented palletsParameter
- ensures the type is encodable, decodable, and usable as a parameterDispatchable
- indicates it can be executed in the runtimeGetDispatchInfo
- provides weight details, determining how long execution takes
-
XcmSender
- implements theSendXcm
trait, specifying how the executor sends XCMs using transport layers (e.g., UMP for relay chains or XCMP for sibling chains). If a runtime lacks certain transport layers, such as HRMP (or XCMP) -
AssetTransactor
- implements theTransactAsset
trait, handling the conversion and transfer of MultiAssets between accounts or registers. It can be configured to support native tokens, fungibles, and non-fungibles or multiple tokens using pre-defined adapters likeFungibleAdapter
or custom solutions -
OriginConverter
- implements theConvertOrigin
trait to mapMultiLocation
origins toRuntimeOrigin
. Multiple implementations can be combined, andOriginKind
is used to resolve conflicts. Pre-defined converters likeSovereignSignedViaLocation
andSignedAccountId32AsNative
handle sovereign and local accounts respectively -
IsReserve
- specifies trusted<MultiAsset, MultiLocation>
pairs for depositing reserve assets. Using the unit type()
blocks reserve deposits. TheNativeAsset
struct is an example of a reserve implementation -
IsTeleporter
- defines trusted<MultiAsset, MultiLocation>
pairs for teleporting assets to the chain. Using()
blocks theReceiveTeleportedAssets
instruction. TheNativeAsset
struct can act as an implementation -
Aliasers
- a list of(Origin, Target)
pairs enabling eachOrigin
to be replaced with its correspondingTarget
-
UniversalLocation
- specifies the runtime's location in the consensus universe- Some examples are:
X1(GlobalConsensus(NetworkId::Polkadot))
for PolkadotX1(GlobalConsensus(NetworkId::Kusama))
for KusamaX2(GlobalConsensus(NetworkId::Polkadot), Parachain(1000))
for Statemint
- Some examples are:
-
Barrier
- implements theShouldExecute
trait, functioning as a firewall for XCM execution. Multiple barriers can be combined in a tuple, where execution halts if one succeeds -
Weigher
- calculates the weight of XCMs and instructions, enforcing limits and refunding unused weight. Common solutions includeFixedWeightBounds
, which uses a base weight and limits on instructions -
Trader
- manages asset-based weight purchases and refunds forBuyExecution
instructions. TheUsingComponents
trader is a common implementation -
ResponseHandler
- handlesQueryResponse
instructions, implementing theOnResponse
trait. FRAME systems typically use the pallet-xcm implementation -
AssetTrap
- handles leftover assets in the holding register after XCM execution, allowing them to be claimed viaClaimAsset
. If unsupported, assets are burned -
AssetClaims
- facilitates the claiming of trapped assets during the execution of theClaimAsset
instruction. Commonly implemented via pallet-xcm -
AssetLocker
- handles the locking and unlocking of assets. Can be omitted using()
if asset locking is unnecessary -
AssetExchanger
- implements theAssetExchange
trait to manage asset exchanges during theExchangeAsset
instruction. The unit type()
disables this functionality -
SubscriptionService
- manages(Un)SubscribeVersion
instructions and returns the XCM version viaQueryResponse
. Typically implemented by pallet-xcm -
PalletInstancesInfo
- provides runtime pallet information forQueryPallet
andExpectPallet
instructions. FRAME-specific systems often use this, or it can be disabled with()
-
MaxAssetsIntoHolding
- limits the number of assets in the Holding register. At most, twice this limit can be held under worst-case conditions -
FeeManager
- manages fees for XCM instructions, determining whether fees should be paid, waived, or handled in specific ways. Fees can be waived entirely using()
-
MessageExporter
- implements theExportXcm
trait, enabling XCMs export to other consensus systems. It can spoof origins for use in bridges. Use()
to disable exporting -
UniversalAliases
- lists origin locations and universal junctions allowed to elevate themselves in theUniversalOrigin
instruction. UsingNothing
prevents origin aliasing -
CallDispatcher
- dispatches calls from theTransact
instruction, adapting the origin or modifying the call as needed. Can default toRuntimeCall
-
SafeCallFilter
- whitelists calls permitted in theTransact
instruction. UsingEverything
allows all calls, though this is temporary until proof size weights are accounted for -
TransactionalProcessor
- implements theProccessTransaction
trait. It ensures that XCM instructions are executed atomically, meaning they either fully succeed or fully fail without any partial effects. This type allows for non-transactional XCM instruction processing by setting the()
type -
HrmpNewChannelOpenRequestHandler
- enables optional logic execution in response to theHrmpNewChannelOpenRequest
XCM notification -
HrmpChannelAcceptedHandler
- enables optional logic execution in response to theHrmpChannelAccepted
XCM notification HrmpChannelClosingHandler
- enables optional logic execution in response to theHrmpChannelClosing
XCM notificationXcmRecorder
- allows tracking of the most recently executed XCM, primarily for use with dry-run runtime APIs
Inner Config¶
The Config
trait underpins the XcmExecutor
, defining its core behavior through associated types for asset handling, XCM processing, and permission management. These types are categorized as follows:
- Handlers - manage XCMs sending, asset transactions, and special notifications
- Filters - define trusted combinations, origin substitutions, and execution barriers
- Converters - handle origin conversion for call execution
- Accessors - provide weight determination and pallet information
- Constants - specify universal locations and asset limits
- Common Configs - include shared settings like
RuntimeCall
The following diagram outlines this categorization:
flowchart LR
A[Inner Config] --> B[Handlers]
A --> C[Filters]
A --> D[Converters]
A --> E[Accessors]
A --> F[Constants]
A --> G[Common Configs]
B --> H[XcmSender]
B --> I[AssetTransactor]
B --> J[Trader]
B --> K[ResponseHandler]
B --> L[AssetTrap]
B --> M[AssetLocker]
B --> N[AssetExchanger]
B --> O[AssetClaims]
B --> P[SubscriptionService]
B --> Q[FeeManager]
B --> R[MessageExporter]
B --> S[CallDispatcher]
B --> T[HrmpNewChannelOpenRequestHandler]
B --> U[HrmpChannelAcceptedHandler]
B --> V[HrmpChannelClosingHandler]
C --> W[IsReserve]
C --> X[IsTeleporter]
C --> Y[Aliasers]
C --> Z[Barrier]
C --> AA[UniversalAliases]
C --> AB[SafeCallFilter]
D --> AC[OriginConverter]
E --> AD[Weigher]
E --> AE[PalletInstancesInfo]
F --> AF[UniversalLocation]
F --> AG[MaxAssetsIntoHolding]
G --> AH[RuntimeCall]
Outer Config¶
The XcmExecutor<Config>
struct extends the functionality of the inner config by introducing fields for execution context, asset handling, error tracking, and operational management. For further details, see the documentation for XcmExecutor<Config>
.
Multiple Implementations¶
Some associated types in the Config
trait are highly configurable and may have multiple implementations (e.g., Barrier). These implementations are organized into a tuple (impl_1, impl_2, ..., impl_n)
, and the execution follows a sequential order. Each item in the tuple is evaluated individually, each being checked to see if it fails. If an item passes (e.g., returns Ok
or true
), the execution stops, and the remaining items are not evaluated. The following example of the Barrier
type demonstrates how this grouping operates (understanding each item in the tuple is unnecessary for this explanation).
In the following example, the system will first check the TakeWeightCredit
type when evaluating the barrier. If it fails, it will check AllowTopLevelPaidExecutionFrom
, and so on, until one of them returns a positive result. If all checks fail, a Barrier error will be triggered.
pub type Barrier = (
TakeWeightCredit,
AllowTopLevelPaidExecutionFrom<Everything>,
AllowKnownQueryResponses<XcmPallet>,
AllowSubscriptionsFrom<Everything>,
);
pub struct XcmConfig;
impl xcm_executor::Config for XcmConfig {
...
type Barrier = Barrier;
...
}
| Created: October 18, 2024