# 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.