:source-highlighter: highlight.js
:highlightjs-languages: rust
:github-icon: pass:[<svg class="icon"><use href="#github-icon"/></svg>]

= pezpallet_xcm

Branch/Release: `release-pezkuwi-v1.10.0`

Source Code link:https://github.com/pezkuwichain/pezkuwi-sdk/blob/release-pezkuwi-v1.10.0/pezkuwi/xcm/pezpallet-xcm/src/lib.rs[{github-icon},role=heading-link]

== Purpose

`pezpallet-xcm` is responsible for filtering, routing, and executing incoming XCM.

== Config

* Pezpezpallet-specific origins:
** `AdminOrigin` -- The origin that is allowed to call privileged operations on the XCM pezpallet. Type must implement trait `EnsureOrigin`.
** `ExecuteXcmOrigin` -- Required origin for executing XCM messages, including the teleport functionality. If successful, it returns a `xref:glossary.adoc#multilocation[MultiLocation]` which exists as an interior location within this chain's XCM context. Type must implement trait `EnsureOrigin`.
** `SendXcmOrigin` -- Required origin for sending XCM messages. If successful, it resolves to `MultiLocation`. Type must implement trait `EnsureOrigin`.

* Pezpezpallet-specific ID types:
** `RemoteLockConsumerIdentifier` -- The ID type for local consumers of remote locks. The type must implement `Copy`.

* Pezpezpallet-specific handlers:
** `Currency` -- Lockable currency used in the pezpallet. Type must implement the trait `LockableCurrency`.
** `Weigher` -- Measures xref:glossary.adoc#weight[weight] consumed by XCM local execution. Type must implement the trait `WeightBounds`.
** `XcmExecutor` -- Means of executing XCM. Type must implement the trait `ExecuteXcm`.
** `XcmRouter` --  The type used to dispatch an XCM to its destination. Type must implement the trait `SendXcm`.

* Pezpezpallet-specific filters:
** `XcmExecuteFilter` -- XCM filter for which messages to be executed using `XcmExecutor` must pass. Type must implement trait `Contains<(MultiLocation, Xcm<<Self as Config>::RuntimeCall>)>`.
** `XcmReserveTransferFilter` -- XCM filter for which messages to be reserve-transferred using the dedicated extrinsic must pass.Type must implement the trait `Contains<(MultiLocation, Vec<MultiAsset>)>`.
** `XcmTeleportFilter` -- XCM filter for which messages to be teleported using the dedicated extrinsic must pass. Type must implement the trait `Contains<(MultiLocation, Vec<MultiAsset>)>`.
** `TrustedLockers` -- Returns whether or not the origin can be trusted for a specific asset. Type must implement `ContainsPair` where each pair is an `asset` and an `origin` thereby entrusting `origin` for operations relating to `asset`.

* Pezpezpallet-specific converters:
** `CurrencyMatcher` -- The `xref:glossary.adoc#multiasset[MultiAsset]` matcher for `Currency`. Type must implement the trait `MatchesFungible`.
** `SovereignAccountOf` -- How to get an `AccountId` value from a `MultiLocation`, useful for handling asset locks. Type must implement `ConvertLocation`.

* Pezpezpallet-specific constants:
** `VERSION_DISCOVERY_QUEUE_SIZE` -- `u32` measures the size of the version discovery queue. Typically set to `100`.
** `AdvertisedXcmVersion` -- The latest supported XCM version that this chain accepts. Type must implement the trait `Get<XcmVersion>`. Commonly set to `pezpallet_xcm::CurrentXcmVersion`.
** `MaxLockers` --  The maximum number of local XCM locks that a single account may have. Type must implement the trait `Get<u32>`.
** `MaxRemoteLockConsumers` -- The maximum number of consumers a single remote lock may have. Type must implement the trait `Get<u32>`.
** `UniversalLocation` -- This chain's Universal Location. Type must implement the trait `Get<InteriorMultiLocation>`.

* Common configs:
** `RuntimeEvent`
** `RuntimeCall`
** `RuntimeOrigin`
** `WeightInfo`

== Dispatchables

[.contract-item]
[[send]]
==== `[.contract-item-name]#++send++#`
[source,rust]
----
pub fn send(
    origin: OriginFor<T>,
    dest: Box<VersionedMultiLocation>,
    message: Box<VersionedXcm<()>>,
)
----

WARNING: DEPRECATED. `send` will be removed after June 2024. Use `send_blob` instead.

* Deprecation explanation:
** `pezpallet-xcm` has a new pair of extrinsics, `execute_blob` and `send_blob`. These are meant to be used instead of `execute` and `send`, which are now deprecated and will be removed eventually. These new extrinsics just require you to input the encoded XCM.
** There's a new utility in PezkuwiJS Apps for encoding XCMs you can use: https://pezkuwi.js.org/apps/#/utilities/xcm Just pass in the encoded XCM to the new extrinsics and you're done.
** The migration from the old extrinsic to the new is very simple. If you have your message `xcm: VersionedXcm<Call>`, then instead of passing in `Box::new(xcm)` to both `execute` and `send`, you would pass in `xcm.encode().try_into()` and handle the potential error of its encoded length being bigger than `MAX_XCM_ENCODED_SIZE`.
** `pezpallet-contracts` takes the XCM encoded now as well. It follows the same API as `execute_blob` and `send_blob`.

Send a versioned XCM `message` to the destination `dest`.

The origin must be `SendXcmOrigin` for this call.

**Params:**

- `dest: Box<VersionedMultiLocation>` — destination for the XCM
- `message: Box<VersionedXcm<()>>` — versioned XCM to be sent to the multilocation `dest`

**Errors:**

- `InvalidOrigin` — origin did not match `SendXcmOrigin`
- `BadVersion` — version for XCM not valid

**Events:**

- `Sent(origin, destination, message, message_id)` -- The versioned XCM `message` was sent from the `origin` to the `destination`.


[.contract-item]
[[execute]]
==== `[.contract-item-name]#++execute++#`
[source,rust]
----
pub fn execute(
    origin: OriginFor<T>,
    message: Box<VersionedXcm<<T as Config>::RuntimeCall>>,
    max_weight: Weight,
)
----

WARNING: DEPRECATED. `execute` will be removed after June 2024. Use `execute_blob` instead.

* Deprecation explanation:
** `pezpallet-xcm` has a new pair of extrinsics, `execute_blob` and `send_blob`. These are meant to be used instead of `execute` and `send`, which are now deprecated and will be removed eventually. These new extrinsics just require you to input the encoded XCM.
** There's a new utility in PezkuwiJS Apps for encoding XCMs you can use: https://pezkuwi.js.org/apps/#/utilities/xcm Just pass in the encoded XCM to the new extrinsics and you're done.
** The migration from the old extrinsic to the new is very simple. If you have your message `xcm: VersionedXcm<Call>`, then instead of passing in `Box::new(xcm)` to both `execute` and `send`, you would pass in `xcm.encode().try_into()` and handle the potential error of its encoded length being bigger than `MAX_XCM_ENCODED_SIZE`.
** `pezpallet-contracts` takes the XCM encoded now as well. It follows the same API as `execute_blob` and `send_blob`.

Execute an XCM message from a local, signed, origin.

The origin must be `ExecuteXcmOrigin` for this call.

NOTE: A successful return to this does NOT imply that the `msg` was executed successfully to completion; only that SOME of it was executed.

**Params:**

- `message: Box<VersionedXcm<T as Config::RuntimeCall>>` — versioned XCM to be executed
- `max_weight: Weight` -- No more than this amount of `Weight` will be consumed during this execution attempt.

**Errors:**

- `BadOrigin` —- origin did not match `ExecuteXcmOrigin`
- `BadVersion` —- version for XCM not valid

**Events:**

- `Attempted(outcome)` -- Indicates whether the `msg` was executed completely or only partially.

[.contract-item]
[[force_xcm_version]]
==== `[.contract-item-name]#++force_xcm_version++#`
[source,rust]
----
pub fn force_xcm_version(
    origin: OriginFor<T>,
    location: Box<MultiLocation>,
    version: XcmVersion,
)
----
Set that a particular destination can be communicated with through a particular version of XCM.

The origin must be `AdminOrigin` for this call.

**Params:**

- `location: Box<MultiLocation>` —- The destination that is being described.
- `version: XcmVersion` -- The latest version of XCM that `location` supports.

**Errors:**

- `BadOrigin` — origin did not match `AdminOrigin`

**Events:**

- `Event::SupportedVersionChanged { location, version }` -- `location` was updated to support the latest version of XCM `version`

[.contract-item]
[[force_default_xcm_version]]
==== `[.contract-item-name]#++force_default_xcm_version++#`
[source,rust]
----
pub fn force_default_xcm_version(
    origin: OriginFor<T>,
	maybe_xcm_version: Option<XcmVersion>,
)
----
Set a safe XCM version (the version that XCM should be encoded with if the most recent version a destination can accept is unknown).

The origin must be `AdminOrigin` for this call.

**Params:**

- `maybe_xcm_version: Option<XcmVersion>` —- The default XCM encoding version, or `None` to disable.

**Errors:**

- `BadOrigin` — origin did not match `AdminOrigin`

**Events:**

None

[.contract-item]
[[force_subscribe_version_notify]]
==== `[.contract-item-name]#++force_subscribe_version_notify++#`
[source,rust]
----
pub fn force_subscribe_version_notify(
    origin: OriginFor<T>,
	location: Box<VersionedMultiLocation>,
)
----
Ask a location to notify us regarding their XCM version and any changes to it.

The origin must be `AdminOrigin` for this call.

**Params:**

- `location: Box<VersionedMultiLocation>`: The location to which we should subscribe for XCM version notifications.

**Errors:**

- `BadOrigin` — origin did not match `AdminOrigin`

**Events:**

None

[.contract-item]
[[force_unsubscribe_version_notify]]
==== `[.contract-item-name]#++force_unsubscribe_version_notify++#`
[source,rust]
----
pub fn force_unsubscribe_version_notify(
    origin: OriginFor<T>,
	location: Box<VersionedMultiLocation>,
)
----
Require that a particular destination should no longer notify us regarding any XCM version changes.

The origin must be `AdminOrigin` for this call.

**Params:**

- `location: Box<VersionedMultiLocation>`: The location from which we are but no longer wish to subscribe to XCM version notifications.

**Errors:**

- `BadOrigin` —- origin did not match `AdminOrigin`
- `NoSubscription` -- subscription not found to `location`
- `BadLocation` -- location not found

**Events:**

None

[.contract-item]
[[limited_reserve_transfer_assets]]
==== `[.contract-item-name]#++limited_reserve_transfer_assets++#`
[source,rust]
----
pub fn limited_reserve_transfer_assets(
    origin: OriginFor<T>,
    dest: Box<VersionedMultiLocation>,
    beneficiary: Box<VersionedMultiLocation>,
    assets: Box<VersionedMultiAssets>,
    fee_asset_item: u32,
    weight_limit: WeightLimit,
)
----
Transfer some assets from the local chain to the sovereign account of a destination chain and forward a notification XCM.

The origin must be `ExecuteXcmOrigin` for this call.

**Params:**

- `dest: Box<VersionedMultiLocation>` -- Destination context for the assets. Will typically be `X2(Parent, Teyrchain(..))` to send from teyrchain to teyrchain, or `X1(Teyrchain(..))` to send from relay to teyrchain.
- `beneficiary: Box<VersionedMultiLocation>` -- A beneficiary location for the assets in the context of `dest`. Willgenerally be an `AccountId32` value.
- `assets: Box<VersionedMultiAssets>` -- The assets to be withdrawn. This should include the assets used to pay the fee on the `dest` side.
- `fee_asset_item: u32` -- The index into `assets` of the item which should be used to pay fees.
- `weight_limit: WeightLimit` -- The remote-side weight limit, if any, for the XCM fee purchase.

**Errors:**

- `BadOrigin` —- origin did not match `ExecuteXcm`
- `BadVersion` -- `beneficiary` or `assets` have incorrect versioning
- `TooManyAssets` -- assets length exceeds MAX_ASSETS_FOR_TRANSFER which equals 2 in this code

**Events:**

- `Event::Attempted { outcome }` -- Attempted the reserve transfer with returned status `outcome`

[.contract-item]
[[limited_teleport_assets]]
==== `[.contract-item-name]#++limited_teleport_assets++#`
[source,rust]
----
pub fn limited_teleport_assets(
    origin: OriginFor<T>,
    dest: Box<VersionedMultiLocation>,
    beneficiary: Box<VersionedMultiLocation>,
    assets: Box<VersionedMultiAssets>,
    fee_asset_item: u32,
    weight_limit: WeightLimit,
)
----
Teleport some assets from the local chain to some destination chain.

Fee payment on the destination side is made from the asset in the `assets` vector of index `fee_asset_item`, up to enough to pay for `weight_limit` of weight. If more weight is needed than `weight_limit`, then the operation will fail and the assets send may be at risk.

The origin must be `ExecuteXcmOrigin` for this call.

**Params:**

- `dest: Box<VersionedMultiLocation>` -- Destination context for the assets. Will typically be `X2(Parent, Teyrchain(..))` to teleport from teyrchain to teyrchain, or `X1(Teyrchain(..))` to teleport from relay to teyrchain.
- `beneficiary: Box<VersionedMultiLocation>` -- A beneficiary location for the assets in the context of `dest`. Will generally be an `AccountId32` value.
- `assets: Box<VersionedMultiAssets>` -- The assets to be withdrawn. This should include the assets used to pay the fee on the `dest` side.
- `fee_asset_item: u32` -- The index into `assets` of the item which should be used to pay fees.
- `weight_limit: WeightLimit` -- The remote-side weight limit, if any, for the XCM fee purchase.

**Errors:**

- `BadOrigin` —- origin did not match `ExecuteXcm`
- `BadVersion` -- `beneficiary` or `assets` have incorrect versioning
- `TooManyAssets` -- assets length exceeds MAX_ASSETS_FOR_TRANSFER which equals 2 in this code

**Events:**

- `Event::Attempted { outcome }` -- Attempted the teleport status with returned status `outcome`

[.contract-item]
[[force_suspension]]
==== `[.contract-item-name]#++force_suspension++#`
[source,rust]
----
pub fn force_suspension(
    origin: OriginFor<T>,
    suspended: bool,
)
----
Set or unset the global suspension state of the XCM executor.

The origin must be `AdminOrigin` for this call.

**Params:**

- `suspended: bool` -- `true` to suspend, `false` to resume.

**Errors:**

None

**Events:**

None

[.contract-item]
[[transfer_assets]]
==== `[.contract-item-name]#++transfer_assets++#`
[source,rust]
----
pub fn transfer_assets(
	origin: OriginFor<T>,
	dest: Box<VersionedLocation>,
	beneficiary: Box<VersionedLocation>,
	assets: Box<VersionedAssets>,
	fee_asset_item: u32,
	weight_limit: WeightLimit,
)
----
Transfer some assets from the local chain to the destination chain through their local, destination or remote reserve, or through teleports.

**Params:**

- `dest: Box<VersionedLocation>` -- Destination context for the assets. Will typically be `X2(Parent, Teyrchain(..))` to send from teyrchain to teyrchain, or `X1(Teyrchain(..))` to send from relay to teyrchain.
- `beneficiary: Box<VersionedLocation>` -- A beneficiary location for the assets in the context of `dest`. Will generally be an `AccountId32` value.
- `assets`: The assets to be withdrawn. This should include the assets used to pay the fee on the `dest` (and possibly reserve) chains.
- `fee_asset_item: u32` -- The index into `assets` of the item which should be used to pay fees.
- `weight_limit: WeightLimit` -- The remote-side weight limit, if any, for the XCM fee purchase.

**Errors:**

* `BadOrigin` —- origin did not match `ExecuteXcmOrigin`.
* `BadVersion` -- v2/v3 conversion to v4 failed for `assets`, `dest`, or `beneficiary`.
* `TooManyAssets` -- `assets` contain more than `MAX_ASSETS_FOR_TRANSFER = 2` to transfer.
* `Empty` -- can be a number of different errors:
** `fee_asset_item` is not present in `assets`.
** some fungible asset in `assets` has a value of 0.
** fees or asset transfer type was not determined.
* `TooManyReserves` -- there are more than one transfer type for an asset.
* `InvalidAssetUnknownReserve` -- transfer type can not be determined for a given asset.
* `InvalidAssetUnsupportedReserve` -- asset or fees transfer type is remote reserve and asset and fees asset are different.
* `Filtered` -- can be a number of different errors:
** `XcmReserveTransferFilter` filtered the asset.
** `XcmTeleportFilter` filtered the asset
* `CannotReanchor` -- asset can't be reanchored.
* `CannotCheckOutTeleport` -- asset can't be teleported
* `UnweighableMessage` -- prepared XCM message had issues with weighing (i.e. more instructions than the limit).
* `LocalExecutionIncomplete` -- local execution of XCM message have failed.
* `FeesNotMet` -- unable to charge fees. See the error log of any node to see the details.

**Events:**

- `Sent(origin, destination, message, message_id)`

**Deprecated Extrinsics**:
- `teleport_assets` -- Use `limited_teleport_assets` instead.
- `reserve_transfer_assets` -- Use `limited_reserve_transfer_assets` instead.

[.contract-item]
[[claim_assets]]
==== `[.contract-item-name]#++claim_assets++#`
[source,rust]
----
pub fn claim_assets(
    origin: OriginFor<T>,
    assets: Box<VersionedAssets>,
    beneficiary: Box<VersionedLocation>,
) -> DispatchResult
----

**Params:**

- `origin: OriginFor<T>` -- Must be signed.
- `assets: Box<VersionedAssets>` -- The exact assets that were trapped. Use the version to specify what version was the latest when they were trapped.
- `beneficiary: Box<VersionedLocation>` -- A beneficiary location for the assets in the context of `dest`. Will generally be an `AccountId32` value.

**Errors:**

* `BadOrigin` —- origin did not match `ExecuteXcmOrigin`.
* `BadVersion` -- v2/v3 conversion to v4 failed for `assets`, `dest`, or `beneficiary`.
* `UnweighableMessage` -- prepared XCM message had issues with weighing (i.e. more instructions than the limit).
* `LocalExecutionIncomplete` -- local execution of XCM message have failed.

**Events:**

None

[.contract-item]
[[execute_blob]]
==== `[.contract-item-name]#++execute_blob++#`
[source,rust]
----
pub fn execute_blob(
    origin: OriginFor<T>,
    encoded_message: BoundedVec<u8, MaxXcmEncodedSize>,
    max_weight: Weight,
) -> DispatchResultWithPostInfo
----

Execute an XCM from a local, signed, origin.

**Params:**

- `origin: OriginFor<T>` -- Must be signed.
- `encoded_message: BoundedVec<u8, MaxXcmEncodedSize>` -- The message is passed in encoded. It needs to be decodable as a [`VersionedXcm`].
- `max_weight: Weight` -- No more than `max_weight` will be used in its attempted execution. If this is less than the maximum amount of weight that the message could take to be executed, then no execution attempt will be made.

**Errors:**

* `BadOrigin` —- origin did not match `ExecuteXcmOrigin`.
* `BadVersion` -- v2/v3 conversion to v4 failed for `assets`, `dest`, or `beneficiary`.
* `Filtered` -- can be a number of different errors:
* `LocalExecutionIncomplete` -- local execution of XCM message have failed.
* `UnableToDecode` -- unable to decode the XCM.
* `XcmTooLarge` -- XCM encoded length is larger than `MaxXcmEncodedSize`.

**Events:**

- `Attempted(outcome)` -- Indicates whether the `msg` was executed completely or only partially.

[.contract-item]
[[send_blob]]
==== `[.contract-item-name]#++send_blob++#`
[source,rust]
----
pub fn send_blob(
    origin: OriginFor<T>,
    dest: Box<VersionedLocation>,
    encoded_message: BoundedVec<u8, MaxXcmEncodedSize>,
) -> DispatchResult
----

Send an XCM from a local, signed, origin.

**Params:**

- `origin: OriginFor<T>` -- Must be signed.
- `dest: Box<VersionedLocation>` -- The destination, `dest`, will receive this message with a `DescendOrigin` instruction that makes the origin of the message be the origin on this system.
- `encoded_message: BoundedVec<u8, MaxXcmEncodedSize>` -- The message is passed in encoded. It needs to be decodable as a [`VersionedXcm`].

**Errors:**

* `InvalidOrigin` -- origin did not match `SendXcmOrigin`
* `BadVersion` -- v2/v3 conversion to v4 failed for `assets`, `dest`, or `beneficiary`.
* `UnableToDecode` -- unable to decode the XCM.
* `FeesNotMet` -- unable to charge fees. See the error log of any node to see the details.
* `Unreachable` -- The desired destination was unreachable, generally because there is a no way of routing to it.
* `SendFailure` -- There was some other issue (i.e. not to do with routing) in sending the message. Perhaps a lack of space for buffering the message.

**Events:**

- `Sent(origin, destination, message, message_id)` -- The versioned XCM `message` was sent from the `origin` to the `destination`.

== More Reading

https://wiki.pezkuwi.network/docs/learn-xcm-usecases[Pezkuwi Wiki XCM Use Cases]
