Establish HRMP channel with Turing

Walk through the process of establishing HRMP channel via XCM and Governance

About HRMP Channel

An HRMP (Horizontal Relay Messaging Protocol) channel enables bidirectional communication between two parachains. In order for chain A to open a channel to chain B, there are a few prerequisites that must be met:

Firstly, both chains must already be connected to the same relay chain, such as Kusama.

Secondly, once a parachain is connected to a relay chain, it can send XCM messages to the relay chain, but it cannot directly communicate with sibling parachains. This is why Chain A needs to submit requests to the relay chain, indicating its intention to establish a trusted channel with Chain B.

Lastly, in order to establish a channel in one direction, two requests are necessary, one from the sender and the other from the recipient. As an example, for communication from parachain A to parachain B, A must call hrmp.hrmpInitOpenChannel() for the request, and B must then call hrmp.hrmpAcceptOpenChannel() to accept it.

Note that depending on product usage, sometimes a one-way channel is sufficient between two parachains, but in order to build a bidirectional channel, another pair of init and accept calls in the opposite direction are required.

To checkout what channels have been established on Polkadot and Kusama, check out A request channel is shown by a dashed red line while and accept request is a solid teal line.

A close look

We mentioned that two calls are needed for a channel, so now let’s go into details of them. For clarity, we are using the below parameters for the entire document.

  • Relay chain: Rococo
  • Chain A: paraId 2114 (Turing Staging, testnet of Turing)
  • Chain B: paraId 2006 (Rocstar, testnet of Shiden)

Where to find the above paraIds? Rococo’s Network -> Parachains tab

Now let’s check out the details of the two requests, with the example of channel 2114 -> 2006.

# Chain A: request a channel to open
hrmp.hrmpInitOpenChannel(recipient: 2006, proposedMaxCapacity: 1,000, proposedMaxMessageSize: 102,400)

# Chain B: accept the above request
hrmp.hrmpAcceptOpenChannel(sender: 2114)

Where to find values of the above parameters, proposedMaxCapacity and proposedMaxMessageSize? Best way to check is to go to, Developer -> Chain State, and call configuration.activeConfig() to retrieve the relay chain config.

  hrmpMaxParachainOutboundChannels: 30
  hrmpMaxParathreadOutboundChannels: 0
  hrmpSenderDeposit: 0
  hrmpRecipientDeposit: 0
  hrmpChannelMaxCapacity: 1,000 <===
  hrmpChannelMaxTotalSize: 102,400
  hrmpMaxParachainInboundChannels: 30
  hrmpMaxParathreadInboundChannels: 0
  hrmpChannelMaxMessageSize: 102,400 <===

Besides the above two parameters, the hrmpSenderDeposit is also very important, as it states how many relay chain token deposit required for open the channel. On Rococo it is 0 ROC, but Polkadot takes 10 DOTs to open a channel and to accept it. Note that those funds need to be deposited into the parachain’s sovereign account (view on Subscan).

Although we understand the two calls now, we cannot call them directly. Why? Because those two extrinsics a) happens on Rococo, and b) needs sudo privilege to call. Since none of the parachains has that permission they can’t use the hrmp extrinsic on Rococo directly. The way is to use polkadotXcm.send extrinsic from the parachain to send over the hrmp call as a payload.

Relay chain encoded call

The first step is to prepare an encoded call data for the payload. Here we are using the hrmp.hrmpInitOpenChannel() as an example,

  1. Open polkadot.js app in your browser and select Rococo,
  2. Navigate to Developer -> Extrinsic
  3. Find hrmp.hrmpInitOpenChannel() call and fill out the parameters
    • recipient: 2006
    • proposedMaxCapacity: 1000
    • proposedMaxMessageSize: 102400
  4. Copy and store the encoded call data 0x3c00d6070000e803000000900100 for later use.
  5. Repeat step 1 to 4 to get the encoded call data for the hrmp.hrmpAcceptOpenChannel(). hrmp.hrmpInitOpenChannel() Screenshot

Send the encoded call via XCM

Next, we explain how to send the payload via polkadotXcm pallet. Please make sure polkadot’s pallet-xcm pallet is integrated in your chain.

If you have a sudo account on your chain, you can use it to construct the polkadotXcm.send() call. However, since Turing Staging has removed sudo, we are using Governance to execute the call. For quick access, here is a link to an Encoded call data example for polkadotXcm.send()

  1. Open chain A’s polkadot.js app.
  2. Navigate to Governance -> Democracy, and click on Submit preimage.
  3. Within submit preimage popup, select polkadotXcm.send with the below parameters, copy the preimage hash, and submit.
    • destination: V3 {XcmV1MultiLocation { parents: 1, interior: Here}}
    • message:
      • V3 (or latest supported version)
      • Add the below 5 instructions to the message
      • WithdrawAsset: {Concrete {0, Here}, Fungible {1000000000000}} The phrase Concrete {0, Here} refers to an asset native to the recipient, such as KSM on Kusama. The value is 1,000,000,000,000 units, or 1 KSM, which is enough to execute the XCM. Keep in mind that the parachain’s sovereign account on the relay chain must be adequately funded.
      • BuyExecution: {Concrete {0, Here}, Fungible {1000000000000}, Unlimited}

        The number value is the same as that in WithdrawAsset

      • Transact: {Native, (1000000000, 10000), }

        Use the encoded call data prepared above; the second parameter is max_weight(refTime, proofSize), whose value is (1,000,000,000, 10,000) and can’t be wrong.

      • RefundSurplus
      • DepositAsset: {Wild {All}, 1, {parents: 0, interior: X1(Parachain(2114))}}

        The 2114 is Chain A’s paraId

    The entire call will look like the below screenshot. polkadotXcm.send() Screenshot

  4. Navigate to Governance -> Council -> Motions, click on “Submit proposal”, paste the above preimage hash and sign.
  5. The external proposal should show up in Council -> Motions, and with enough Ayes it will move to Democracy -> external tab.
  6. Then, Technical Committee can fast-track the external proposal for referendum, and the call will execute through referendum.
  7. After call execution, go to Rococo polkadot.js app for verification. Calling hrmp.hrmpOpenChannelRequest(sender: 2114, recipient: 2006) will show the below result. hrmp.hrmpOpenChannelRequests() Screenshot

That means the call has gone through! Once the other parachain successfully send hrmp.hrmpAcceptOpenChannel() the above requests will be removed from hrmp.hrmpOpenChannelRequest and the channel will show up in hrmp.hrmpChannels().

You will need to send two such calls for both accepting request and initiating it (or you can prepare a batch call). Once channel has been accepted, it will become available at the start of next session.

Relay Chain Specific Configuration


proposedMaxCapacity: 1,000
proposedMaxMessageSize: 102,400
hrmpSenderDeposit: 0
hrmpRecipientDeposit: 0
tokenDecimals: 12


proposedMaxCapacity: 1,000
proposedMaxMessageSize: 102,400
hrmpSenderDeposit: 5,000,000,000,000
hrmpRecipientDeposit: 5,000,000,000,000
tokenDecimals: 12


proposedMaxCapacity: 1,000
proposedMaxMessageSize: 102,400
hrmpSenderDeposit: 100,000,000,000
hrmpRecipientDeposit: 100,000,000,000
tokenDecimals: 10

Turing Staging

The below details can be viewed on Rococo Subscan.

Sovereign Account (Rococo V1): 5Ec4AhNzVAVwDR54oqgWQ5YSoPbxXathSrQqTmqkF5o7xe6y

Sovereign Account (Turing Staging): 5Dt6dpkWPwLaH4BBCKJwjiWrFVAGyYk3tLUabvyn4v7KtESG

Sovereign Account (Parachain): 0x7369626c42080000000000000000000000000000000000000000000000000000

Turing Network

The below details can be viewed on Kusama Subscan.

Sovereign Account (Kusama): F7fq1is7XWry4tWaYVZJ2uSwytCLFhsuEFarS7hit1chXtq

Sovereign Account (Turing Network): 67y2xkd8rZD7gapMM7EA8pug4rSvUCQjaoTm95mVEcTiR3w1

Sovereign Account (Parachain): 0x7061726142080000000000000000000000000000000000000000000000000000

Encoded call data example for polkadotXcm.send()

To perform this call, you can use the Sudo extrinsics of the Governance tab on Polkadot.js Apps interface.

Cross-chain Product Integration
Delegation via Extrinsics