> Feel free to update/modify this document if you see something that can be improved upon # Opening HRMP channels between parachains > If you are new to XCM, read the following: > - https://polkadot.network/blog/xcm-the-cross-consensus-message-format > - https://polkadot.network/blog/xcm-part-two-versioning-and-compatibility > - https://polkadot.network/blog/xcm-part-three-execution-and-error-management > - https://github.com/paritytech/xcm-format Here is the setup for this tutorial: ![](https://i.imgur.com/QtYXysJ.png) You will need the following: - rococo-local relay chain - parachain with paraId 1001 - parachain with paraId 1002 > You can read up more on how to set up a test network here: > - https://substrate.stackexchange.com/questions/4692/how-do-i-spin-up-a-testnet-with-zombienet Since this tutorial is for example purposes, both parachains should have the sudo pallet configured. In a production chain this would be substituted with governance. ## What is HRMP (also known as XCMP-Lite)? Here is an excerpt from the Polkadot Wiki: > While XCMP is still being implemented, a stop-gap > protocol (see definition below) known as Horizontal Relay-routed > Message Passing (HRMP) exists in its place. HRMP has the same > interface and functionality as XCMP but is much more demanding on > resources since it stores all messages in the Relay Chain storage. > When XCMP has been implemented, HRMP is planned to be deprecated and > phased out in favor of it. Source: - https://wiki.polkadot.network/docs/learn-xcm#hrmp-xcmp-lite **HRMP channels are unidirectional** The parachain that wants to open an HRMP channel must make a request to the parachain it wishes to have an open channel with. Once that is done, the other parachain needs to accept this request. This is what we mean by unidirectional flow. For bidirectional communication we need to open another channel in the opposite direction. A channel can be opened only after the recipient confirms it and only on a session change. So in recap, for this tutorial, the idea is that we want a bidirectional channel between parachain 1001 and parachain 1002 so that they can exchange XCM's. ## Create an HRMP open channel request 1. First we need to create an [`hrmpInitOpenChannel`](https://github.com/paritytech/polkadot/blob/efcaa57d5f9d72c1c3fa79dcd929da9cced3af74/runtime/parachains/src/hrmp.rs#L451-L462) call. **Do not submit the call**, instead copy the encoded call data for later use: ![](https://i.imgur.com/UGz1yDZ.png) - `proposed_max_capacity` - specifies how many messages can be in the channel at once. - `proposed_max_message_size` - specifies the maximum size of the messages. These numbers are a subject to the relay chain's configuration limits. You can find this in the relay chain's active configuration: ![](https://i.imgur.com/T19i6tU.png) ## Fund the parachain's sovereign account The next step will be to create and submit an XCM on parachain 1001 with our encoded call data from above, but before we can do this we need to make sure parachain 1001's sovereign account on the relay chain is funded so it can take care of any XCM transact fees. Let's add parachain 1001's sovereign account to our address book. On the relay chain, open the address book and add the following contact: ![](https://i.imgur.com/jHPXcyq.png) > If you're unsure as to how to calculate the parachain's sovereign account checkout this post: > - https://substrate.stackexchange.com/questions/1200/how-to-calculate-sovereignaccount-for-parachain > ![](https://i.imgur.com/ZM3DYEI.png) > > Note that if the parachain's `paraId` changes, then sovereign account will also change. Therefore, as a rule-of-thumb, avoid hard coding the parachain's sovereign account. We can now transfer some tokens from Alice to the sovereign account: ![](https://i.imgur.com/DUwRiVo.png) And the account is now funded! ![](https://i.imgur.com/cjGrpER.png) ## Create the XCM to initiate the open channel request We can now create the XCM on parachain 1001: > A few things to note. > - Below you will see we use `sudo`, in the real-world this would be done via governance. > - Always check what the XCM configuration is for the relay chain you are working with. The numbers below are for example purposes. ![](https://i.imgur.com/bur7DFO.png) ![](https://i.imgur.com/9hJZIoV.png) ![](https://i.imgur.com/zWnJYuJ.png) ![](https://i.imgur.com/au9IIqP.png) ![](https://i.imgur.com/WgiWxjC.png) ![](https://i.imgur.com/5RLFS0g.png) > Notice the encoded call that we created in the beginning of this tutorial is now used in the `Transact`. In the above call, we are executing a few instructions: - [`WithdrawAsset`](https://github.com/paritytech/xcm-format#withdrawasset) - Removes the on-chain asset(s) and accrue them into the XCVM Holding Register. More info [here](https://polkadot.network/blog/xcm-the-cross-consensus-message-format/#-the-holding-register). - [`BuyExecution`](https://github.com/paritytech/xcm-format#buyexecution) - Pays for the execution of the current message using the asset(s) that were deposited in the XCVM Holding Register from our previous `WithdrawAsset` instruction. More info [here](https://polkadot.network/blog/xcm-the-cross-consensus-message-format/#-fee-payment-in-xcm). - [`RefundSurplus`](https://github.com/paritytech/xcm-format#refundsurplus) - Increases Refunded Weight Register to the value of Surplus Weight Register. Attempts to accrue fees previously paid via `BuyExecution` into the XCVM Holding Register for the amount that Refunded Weight Register is increased. - [`DepositAsset`](https://github.com/paritytech/xcm-format#depositasset) - Subtracts the asset(s) from the XCVM Holding Register and deposits on-chain equivalent assets under the ownership of the beneficiary. The operands are: - assets: The asset(s) to remove from the Holding Register. - max_assets: The maximum number of unique assets/asset instances to remove from the Holding Register. Only the first max_assets assets/instances of those matched by assets will be removed, prioritized under standard asset ordering. Any others will remain in holding. - beneficiary: The new owner for the assets. Notice that with `DepositAsset` we are specifying an account where the surplus will go. In this example we have used Eve's account. Read more on how `RefundSurplus` and `DepositAsset` work here: - https://polkadot.network/blog/xcm-part-three-execution-and-error-management/#-weight The first part of this call is the destination - where we want to send the XCM to be executed. In our case we are saying `parent: 1` - the parent of parachain 1001 is the relay chain and in the context of the `parent` we are specifying an `interior: Here` meaning that we want the relay chain to execute the XCM. This is all done by using `MultiLocation`. If you're not familiar with `MultiLocation` then read up here: - https://github.com/paritytech/xcm-format#7-universal-consensus-location-identifiers Additionally, the actual XCM instructions themselves e.g. `WithdrawAsset`, `BuyExecution`, etc. also use `MultiLocation`. In this case the `MultiLocation` is in respect to the system that will be executing the XCM message: > Throughout XCM, messages are authored such that when interpreted from the receiver's point of view they will have the desired meaning/effect. This means that relative paths should always by constructed to be read from the point of view of the receiving system, which may have a completely different meaning in the authoring system. More info here: - https://github.com/paritytech/xcm-format#concrete-identifiers As far as the amount that is needed to withdraw to cover execution, this is something that you will need to calculate ahead of time. More info can be found here: - https://polkadot.network/blog/xcm-the-cross-consensus-message-format/#-fee-payment-in-xcm And a nice StackExchange write up from a community member on weights and paying for execution here: - https://substrate.stackexchange.com/a/5430/29 So in summary, we are going to withdraw some amount from the parachain sovereign account to the XCVM Holding Register. Use the amount in there to "buy" execution time for our XCM `Transact` instruction. Execute the `Transact`. And whatever amount is left over (determined by `RefundSurplus` ) is deposited into an account we specify by using the `DepositAsset` instruction. Before submitting this call, let's open the parachain's explorer: ![](https://i.imgur.com/36uaDLt.png) Also, open the relay chain's explorer: ![](https://i.imgur.com/Pvpo33h.png) You can now submit the XCM extrinsic and you will see the events. First you will see the events in the parachain's explorer: ![](https://i.imgur.com/nWNHQwc.png) Then you will see the events in the relay chain's explorer: ![](https://i.imgur.com/vLHvzXt.png) Success! But let's double check. Check the chain state on the relay chain to see if there is now an HRMP open channel request from parachain 1001 to parachain 1002: ![](https://i.imgur.com/p3K2SwR.png) You can also check here: ![](https://i.imgur.com/2sPYZpB.png) And note that some amount has been deducted from the sovereign account: ![](https://i.imgur.com/PE5818t.png) The surplus has gone to Eve's account: ![](https://i.imgur.com/DwjqxDn.png) Their balance went from 1,000,000,000,000,000,000 to 1,000,000,885,011,945,986! Awesome! We have succeeded in creating an HRMP open channel request. The next step is for parachain 1002 to accept the request. ## Accept the HRMP open channel request On the relay chain create the following call: ![](https://i.imgur.com/i3Pd1XP.png) Copy the encoded call data for later use in our XCM. ## Fund the parachain's sovereign account Make sure that parachain 1002's sovereign account is funded. > You will have to repeat the process of adding and funding parachain 1002's sovereign account which was documented above for parachain 1001. ## Create the XCM to accept the HRMP open channel request Now, create the XCM on parachain 1002: ![](https://i.imgur.com/NFneSmW.png) ![](https://i.imgur.com/j3gJB45.png) ![](https://i.imgur.com/sTf2Wbx.png) ![](https://i.imgur.com/hKttyzp.png) ![](https://i.imgur.com/bPHIVjf.png) Submit. Wait one epoch for the change to take place. You now have established a unidirectional HRMP channel between parachain 1001 and parachain 1002! ![](https://i.imgur.com/30u1vG2.png) ## Create an HRMP channel from parachain 1002 to parachain 1001 And finally, we **repeat** the same process documented throughout this article but instead we do it from parachain 1002 to parachain 1001 and in doing so we will have succefully created a **bidirectional** HRMP channel.