I can see that many parachains have opened HRMP channels on Rococo and are beginning to experiment with XCM:

enter image description here


I would like to open HRMP channels between parachains on a local Rococo test network.

How do I do this?

1 Answer 1


Feel free to update/modify this if you see something that can be improved upon

Opening HRMP channels between parachains

If you are new to XCM, read the following:

Here is the setup for this tutorial:

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:

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.


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 bidirectional communication 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 call. Do not submit the call, instead copy the encoded call data for later use:

  • 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:

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:

If you're unsure as to how to calculate the parachain's sovereign account checkout this post:

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:

And the account is now funded!

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.

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 - Removes the on-chain asset(s) and accrue them into the XCVM Holding Register. More info here.
  • 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.
  • 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 - 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. In general, we can use the sovereign account of our sender chain(here is {0, X1(Parachain(1001))}), so that we can use the surplus tokens to open the next HRMP channel.

Read more on how RefundSurplus and DepositAsset work here:

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:

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:

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:

And a nice StackExchange write up from a community member on weights and paying for execution here:

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:

Also, open the relay chain's explorer:

You can now submit the XCM extrinsic and you will see the events.

First you will see the events in the parachain's explorer:

Then you will see the events in the relay chain's explorer:


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:

You can also check here:

And note that some amount has been deducted from the sovereign account:

The surplus has gone to Eve's account:

Their balance went from 1,000,000,000,000,000,000 to 1,000,000,885,011,945,986!


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:

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:


Wait one epoch for the change to take place.

You now have established a unidirectional HRMP channel between parachain 1001 and parachain 1002!

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.