# XCMP Research Xcmp is a way for consensus systems to communicate/operate with eachother over a shared notion of assets. The core spec document [lists the core concepts](https://github.com/paritytech/xcm-format#definitions) (axioms) of the protocol, such as notions of location and account types. Interestingly, an asset definition is not on the list; they are defined in terms of location/identity (see MultiAsset). Assets in XCMP are transferred either through 1. Complete trust between systems, via a *Teleport* 2. Collatoral (derivatives) using a reserve location A *Sovereign Account* is the notion of a consensus system controlling an account in another consensus system. This is used to define the *Reserve Location*, where an asset is backed by an asset on another consensus system (a sovereign account). ## MultiAsset Assets are the topic of all Xcmp messages. The *MultiAsset* format is a way to refer to a single asset, or a class of assets. A single asset may be *fungible* or *nonfungible*. And is identified either abstractly or concretely. A MultiAsset is identified by either an [Abstract Identifier](https://github.com/paritytech/xcm-format#abstract-identifiers) - From an agreed upon global name registry. [Concrete Identifier](https://github.com/paritytech/xcm-format#concrete-identifiers) - A relative location as a *MultiLocation*. Because of the implied hierarchy of systems in Xcmp, MultiLocations are just like file paths `../PalletInstance(3)/GeneralIndex(42)`, and are interpreted from the message recipient's perspective. All these distinctions can be seen directly in the [MultiAsset enum definition](https://github.com/paritytech/polkadot/blob/8daf974142f1a29624e6598ccb167c0d238f7134/xcm/src/v0/multi_asset.rs#L108), and in the [spec](https://github.com/paritytech/xcm-format#format). ## Executing Xcm Messages Within the Polkadot repo, the xcm-executor package will interpret and run messages. To run a cross-chain message in a pallet: 1. Define the Xcm message as a data type ([source code](https://github.com/paritytech/polkadot/blob/8daf974142f1a29624e6598ccb167c0d238f7134/xcm/src/v0/mod.rs#L64) and [spec](https://github.com/paritytech/xcm-format#xcm-message-types)). 2. Pass the message into xcm-executor's [execute_xcm(origin, msg)](https://github.com/paritytech/polkadot/blob/10b0d793302d20e8fbe78b13d5be4d662380ae72/xcm/xcm-executor/src/lib.rs#L38). All messages need an origin to execute, which is a MultiLocation. The `execute_xcm` function is very helpful to understand what is happening on each message type. ## Chaining Messages Xcm must handle any number of hops between systems, and also needs a notion of sequence - after this, do that. To accomplish this, Xcm makes a distinction between *messages* and *orders*. * Messages are the first instruction in an Xcm chain. They do something and place the resulting assets into a *Holding Account*, which is like a temporary buffer. * Orders operate on assets in a holding account, and so are only used after an initial message. Messages (and orders) that have *effects* can chain orders; just like callbacks. ## Concrete Example From the orml pallet, xtokens, here is an Xcm message to move DOT from a parachain to the relay-chain. More specifically, redeem the parachain's local representation of DOT for real DOT in a *reserve location* on the relay-chain, to a relay-chain account. [[Source Code Link](https://github.com/open-web3-stack/open-runtime-module-library/blob/06d37423846b986c2fc4880c2427bd2a0e71137d/xtokens/src/lib.rs#L130)] ```rust let xcm = Xcm::WithdrawAsset { assets: vec![MultiAsset::ConcreteFungible { id: Parent.into(), amount: T::ToRelayChainBalance::convert(amount), }], effects: vec![Order::InitiateReserveWithdraw { assets: vec![MultiAsset::All], reserve: Parent.into(), effects: vec![Order::DepositAsset { assets: vec![MultiAsset::All], dest: AccountId32 { network: T::RelayChainNetworkId::get(), id: T::AccountId32Convert::convert(dest.clone()), }.into(), }], }], }; ``` This datatype-as-code is saying 1. Withdraw `amount` from the origin location, of the origin's asset which is concretely identified as the origin's parent chain's native token (DOT). Place into holding for further instruction. *[Executed at the origin location]* 2. Withdraw the holding asset's underlying *reserve* asset on the parent chain and put into holding. *[Executed partially at origin and partially at parent location]* 3. Deposit the reserve asset into the `dest` account within the same consensus system. *[Executed at the parent (relay-chain) location]* It's worth noting this code could be generic to any parent and origin, except that the final AccountId32 specifies the `network` to be the relay-chain id, which constrains it to only that use case. ___ ## Step by Step through xTokens transfer This is a look at each step of a call to [`transfer_to_parachain`](https://github.com/open-web3-stack/open-runtime-module-library/blob/sw/rococo-v1/xtokens/src/lib.rs#L162) for the Centrifuge use case. It serves as a conceptual proof that the system should work, and a good overview of how xcmp is used and implemented in the xcm polkadot crates and orml xtokens pallet. 1. The function is called with an [`XCurrencyId`](https://github.com/open-web3-stack/open-runtime-module-library/blob/727d6ee4e1280994d4ab584c7eb680c55419346f/xtokens/src/lib.rs#L32) of "RAD". The `XCurrencyId` value is constructed by the user in the UI. 2. Internally, [`transfer_owned_tokens_to_parachain`](https://github.com/open-web3-stack/open-runtime-module-library/blob/727d6ee4e1280994d4ab584c7eb680c55419346f/xtokens/src/lib.rs#L264) gets called (as a thunk). This is the guaranteed case because Centrifuge will only ever transfer its native asset. > [name=miguel] > To clarify, there will be other tokens to move, not just the native one, once we have support for TIN/DROP and alike. 3. The [fn converts](https://github.com/open-web3-stack/open-runtime-module-library/blob/727d6ee4e1280994d4ab584c7eb680c55419346f/xtokens/src/lib.rs#L272) the provided `x_currency_id` into a ConcreteFungible MultiAsset whose id is a `GeneralKey("RAD".into())`, and amount is provided by the fn's argument. 5. [`execute_xcm` is invoked](https://github.com/open-web3-stack/open-runtime-module-library/blob/727d6ee4e1280994d4ab584c7eb680c55419346f/xtokens/src/lib.rs#L205) with the origin as the function caller. XcmExecutor will receive the first message - a [`WithdrawAsset`](https://github.com/open-web3-stack/open-runtime-module-library/blob/727d6ee4e1280994d4ab584c7eb680c55419346f/xtokens/src/lib.rs#L271) - which will [internally invoke `AssetTransactor::withdraw_asset`](https://github.com/paritytech/polkadot/blob/8daf974142f1a29624e6598ccb167c0d238f7134/xcm/xcm-executor/src/lib.rs#L56) on the asset. 6. The internal withdraw_asset fn [checks with the `AssetTransactor::Matcher`](https://github.com/paritytech/polkadot/blob/8daf974142f1a29624e6598ccb167c0d238f7134/xcm/xcm-builder/src/currency_adapter.rs#L48) that the asset `matches_fungible`; which "RAD" does, by [our definition of Matcher](https://github.com/jaybutera/centrifuge-chain/blob/96624f284fa8bb1b0c81e7a4a909dcafc0ad05bf/runtime/src/lib.rs#L314). 7. Then withdraw_asset withdraws `amount` from the origin caller, using `frame_support::traits::Currency`, which means the native token of the chain (RAD). 8. Once withdrawn, the tokens are considered in holding. As an effect of the withdraw, `DepositReserveAsset` is called. This converts the provided `dest`, which is a MultiLocation, into an AccountId on the origin chain, using a LocationConverter - [`SiblingParachainConvertsVia<Sibling, AccountId>`](https://github.com/paritytech/polkadot/blob/10b0d793302d20e8fbe78b13d5be4d662380ae72/xcm/xcm-builder/src/location_conversion.rs#L85). The tokens are then deposited into holding in the converted account. 9. `DepositReserveAsset` sends an xcm message, `ReserveAssetDeposit`, to the `dest` (the other parachain), which lets the destination know that the assets have been deposited to the rserve account. 10. The final effect, [`DepositAsset`](https://github.com/open-web3-stack/open-runtime-module-library/blob/727d6ee4e1280994d4ab584c7eb680c55419346f/xtokens/src/lib.rs#L279), gets the destination parachain to mint those assets to the destination account.