Bridge Hub questions

I am reading Polkadot <> Kusama Bridge Overview and have too many questions and I figured it could be easier to get my answers by having this post.

The Bridge Hub will have all required bridge pallets in its runtime. We hope that later, other teams will be able to use our bridge hubs too and have their pallets there.

What does exactly this mean? Presumably bridge hub is willing to accept more bridge pallets but only bridge pallets?

You won’t be able to directly use bridge hub transactions to send XCM messages over the bridge. Instead, you’ll need to use other parachains transactions, which will use HRMP to deliver messages to the Bridge Hub.

Great. How does a parachain to establish HRMP channel with bridge hub? The way that we need governance action to setup HRMP connect to Statemine/t is just bad. Please provide a better alternative. e.g. when a parachain sent open request, automatically accept it and send open request back.

For that bridge (pair of parachains under different consensus systems) we’ll be using the lane 00000000. Later, when other parachains will join the bridge, they will be using other lanes for their messages.

How does lane got allocated?

Who is Rewarding Relayers

This reads like it is the receiving chain paying for rewards, which make sense but how does the receiving chain prevent abuse / spam? e.g. Is it possible for someone to DoS a parachain by send spam messages to drain the rewards? Can parachain do anything about it?

On top of those questions, I have much more questions regards bridge hub:

  • Are there any docs for parachain teams? Showing how does one integrate their parachain with bridge hub?
  • What are the exact steps to bridge DOT from Statemint to Statemine? What’s the XCM going to look like? What is the reserve chain for DOT on Statemine?
  • How about Snowfork? What are the exact steps to bridge ERC20 from Ethereum to Statemint? and bridge back? and bridge such ERC20 from Statemint to Statemine?
1 Like

Hi Bryan, the Polkadot <> Kusama bridge is still in development, with this high-level roadmap/milestones (you can drill-down on milestones for more details). I’ll try to answer most of your questions here too.

The Bridge Hub will have all required bridge pallets in its runtime. We hope that later, other teams will be able to use our bridge hubs too and have their pallets there.

What does exactly this mean? Presumably bridge hub is willing to accept more bridge pallets but only bridge pallets?

Right, bridge-hub parachain plans to host multiple trustless bridges from Polkadot/Kusama to other chains. AFAIK the only bridges in dev planned to be deployed on Bridge Hub paras are Polkadot<>Kusama bridge and Snowfork Polkadot<>Ethereum bridge (probably initially Snowfork Kusama<>Ethereum bridge?).

Here is the referenda for adding BH on Kusama with more details around the topic.

How does a parachain to establish HRMP channel with bridge hub? The way that we need governance action to setup HRMP connect to Statemine/t is just bad. Please provide a better alternative. e.g. when a parachain sent open request, automatically accept it and send open request back.

For initial deployment it’ll be the same with BH: governance action to HRMP connect. Future upgrades could add a dynamic mechanism like the one you describe, if that’s what the network decides (again through governance).

How does lane got allocated?

Initial deployment has static lane allocation. New lanes can be opened through governance. Dynamic lanes addition is on the roadmap for future upgrades.

This reads like it is the receiving chain paying for rewards, which make sense but how does the receiving chain prevent abuse / spam? e.g. Is it possible for someone to DoS a parachain by send spam messages to drain the rewards? Can parachain do anything about it?

It is actually the sending chain that is paying for rewards. It is paying at both ends of the bridge from sovereign accounts on each BH.
For example StatemintStatemine transfer will involve relayers getting some rewards/cost-refunds on BHP from Statemint sov account on BHP and some on BHK from Statemint (again) sov account on BHK.

Regarding the DoS/spam - this is protected against. It is a longer explanation with multiple mechanisms in place. Some relevant issues/PRs for further research on how:

Are there any docs for parachain teams? Showing how does one integrate their parachain with bridge hub?

AFAIK not yet

What are the exact steps to bridge DOT from Statemint to Statemine? What’s the XCM going to look like? What is the reserve chain for DOT on Statemine?

This warrants its own post maybe - Asset transfer is in development here. Mechanism for dynamically wrapping assets is here and here.

Maybe @bkontur or @Vincent can summarize the mechanism on this thread seeing how the code/PRs are hard to read for the general audience.

1 Like

How about Snowfork? What are the exact steps to bridge ERC20 from Ethereum to Statemint? and bridge back? and bridge such ERC20 from Statemint to Statemine?

For Snowbridge, we’ve had to re-architect most of our bridge to support BridgeHub and to have tighter integration with XCMv3. We’ll definitely be updating our docs site to cover more aspects of the new design. The current content is a bit outdated.

Here are some details in the interim though.

Bridging ERC20 to any parachain on Polkadot is a two-step process:

  1. If the ERC20 has not been bridged before, some user must first create a new asset class in the ForeignAssets pallet on Statemint. This can be initiated permissionlessly on the Ethereum side by calling NativeTokens.create
  2. Users can now transfer their ERC20 tokens to any parachain on Polkadot by calling NativeTokens.lock

The flow of messages from Ethereum to the final parachain is best described by this diagram:

As for bridge fees and relayer rewards, we have our own implementation that is separate from Polkadot<->Kusama bridge. However both implementations share the high-level concept of message “lanes”. Here’s our model:

In the Ethereum->Polkadot direction, bridge usage fees (ETH) are credited to the destination parachain’s sovereign account on Ethereum. Off-chain message relayers are rewarded with DOT from the destination parachain’s sovereign account on BridgeHub.

In the Polkadot->Ethereum direction, bridge usage fees (DOT) are collected by the origin parachain. Off-chain message relayers are rewarded with ETH from the origin parachain’s sovereign account on Ethereum.

The point of separate messaging lanes is to ensure that the whole bridge doesn’t get blocked if some parachain’s sovereign account runs out of funds to pay relayer rewards.

1 Like

That is a really bad idea and nothing that we should ever implement. With parathreads this would enable anyone to drain all the accounts on the bridge hub by sending messages on behalf other people that never send these messages. I get that the current process is far from being perfect, but then we need to think about how to improve it.

2 Likes

We are running the whole setup on Rococo/Wococo, where we move (periodically) ROC from Rococo:Rockmine2 (statemine runtime) to Wococo:Wockmint (westmint runtime), so it is more close to the “bridge KSM from Statemine to Statemint”.

Initialize bridge itself (allow tracking Rococo/Wococo finality):

  1. (BridgeHubRococo) initialize bridge - Rococo governance call xcm::Transact with initialize call
  2. (BridgeHubWococo) initialize bridge - Wococo governance call xcm::Transact with initialize call

Steps to allow bridge transfer were:

  1. (Rococo) force_open_hrmp_channel(rockmine2_para_id, bridge_hub_rococo_para_id) and back as governance call
  2. (Statemine) add configuration to allow send assets to Wococo:Wockmint - Rococo governance call xcm::Transact with add_exporter_config call
  3. (Wococo) force_open_hrmp_channel(wockmint_para_id, bridge_hub_wococo_para_id) and back as governance call
  4. (Wockmint) add configuration for trusted UniversalOrigin/Alias mapping - Wococo governance call xcm::Transact with add_universal_alias call
  5. (Wockmint) add configuration for trusted reserve location - Wococo governance call xcm::Transact with add_reserve_location call
  6. (Wockmint) create asset for ROC in pallet_assets::ForeignAssets instance - Wococo governance call xcm::Transact with pallet_assets::force_create call

(looks like too much configuration, but adding new stuff does not require runtime upgrade and governance can decide about everything )

I am not sure what exactly “reserve chain for DOT on Statemine” means, but as it works now:

  • user sends some of his ROCs from Rococo:Rockmine2 to Wococo:Wockmint account with new extrinsic transfer_asset_via_bridge
    • first, ROCs are moved to reserve account on Rococo:Rockmine2
      • it is still open question if reserve account will be sovereign account of local bridge hub parachain (in this case BridgeHubRococo) or sovereign account of target remote parachain (in this case Wococo:Wockmint), but probably it will be SA of target remote parachain and for that we need to finish this PR: https://github.com/paritytech/polkadot/pull/7016
    • second, reserved ROCs are sent with xcm over bridge as ReserveAssetDeposited instruction here
      • it is still open for case when we want to send back foreign assets (we should not do reserve but burn instead from reserve account)
  • so, here is XCM with ReserveAssetDeposited which will come to the local bridge hub (BridgeHubRococo) (captured from logs):
Xcm([
   "UnpaidExecution"{
      "weight_limit":"Unlimited",
      "check_origin":"None"
   },
   "ExportMessage"{
      "network":"Wococo",
      "destination":X1(Parachain(1000)),
      "xcm":"Xcm("[
         "WithdrawAsset(MultiAssets("[
            "MultiAsset"{
               "id":"Concrete(MultiLocation"{
                  "parents":1,
                  "interior":"Here"
               }")",
               "fun":Fungible(50000000000)
            }
         ]"))",
         "BuyExecution"{
            "fees":"MultiAsset"{
               "id":"Concrete(MultiLocation"{
                  "parents":1,
                  "interior":"Here"
               }")",
               "fun":Fungible(50000000000)
            },
            "weight_limit":"Unlimited"
         },
         "ReserveAssetDeposited(MultiAssets("[
            "MultiAsset"{
               "id":"Concrete(MultiLocation"{
                  "parents":2,
                  "interior":X1(GlobalConsensus(Kusama))
               }")",
               "fun":Fungible(100000000)
            }
         ]"))",
         "ClearOrigin",
         "DepositAsset"{
            "assets":"Definite(MultiAssets("[
               "MultiAsset"{
                  "id":"Concrete(MultiLocation"{
                     "parents":2,
                     "interior":X1(GlobalConsensus(Kusama))
                  }")",
                  "fun":Fungible(100000000)
               }
            ]"))",
            "beneficiary":"MultiLocation"{
               "parents":0,
               "interior":X1(AccountId32{
                  "network":"None",
                  "id":[212,53,147,199,21,253,211,28,97,20,26,189,4,169,159,214,130,44,133,88,133,76,205,227,154,86,132,231,165,109,162,125]
               }")"
            }
         }
      ]")"
   }
])
  • realyer relays xcm from BridgeHubRococo to BridgeHubWococo
  • BridgeHubWococo routes xcm over hrmp to the Wococo:Wockmint
  • Wococo:Wockmint’s XcmExecutor is configured (by governance) with trusted UniversalOrigin/Alias and reserve location
Xcm([
   UniversalOrigin("GlobalConsensus(Rococo))",
   DescendOrigin(X1(Parachain(1000))),
   "WithdrawAsset(MultiAssets("[
      "MultiAsset"{
         "id":"Concrete(MultiLocation"{
            "parents":1,
            "interior":"Here"
         }")",
         "fun":Fungible(50000000000)
      }
   ]"))",
   "BuyExecution"{
      "fees":"MultiAsset"{
         "id":"Concrete(MultiLocation"{
            "parents":1,
            "interior":"Here"
         }")",
         "fun":Fungible(50000000000)
      },
      "weight_limit":"Unlimited"
   },
   "ReserveAssetDeposited(MultiAssets("[
      "MultiAsset"{
         "id":"Concrete(MultiLocation"{
            "parents":2,
            "interior":X1(GlobalConsensus(Kusama))
         }")",
         "fun":Fungible(100000000)
      }
   ]"))",
   "ClearOrigin",
   "DepositAsset"{
      "assets":"Definite(MultiAssets("[
         "MultiAsset"{
            "id":"Concrete(MultiLocation"{
               "parents":2,
               "interior":X1(GlobalConsensus(Kusama))
            }")",
            "fun":Fungible(100000000)
         }
      ]"))",
      "beneficiary":"MultiLocation"{
         "parents":0,
         "interior":X1(AccountId32{
            "network":"None",
            "id":[212,53,147,199,21,253,211,28,97,20,26,189,4,169,159,214,130,44,133,88,133,76,205,227,154,86,132,231,165,109,162,125]
         }")"
      }
   }
])
  • result is that user received ROCs on Wococo:Wockmint in pallet_assets::ForeignAssets instance with assetId: MultiLocation { parents: 2, X1(GlobalConsensus(Kusama)) } Note: Kusama is here because statemine runtime has hard-coded NetworkId as Kusama and we dont have rockmine copy of statemine with Rococo NetworkId

@xlc hope, this answers also to your comment, we actually dont have any high level spec, we have several (now not up-to-date) hackmds based on which this PR is done, so we could consider this post as a latest up-to-date high level spec

1 Like

Thanks for all the answers. They are very helpful.
I now have some understand on what’s implemented and what’s missing. Sounds like it is still a bit too early for parachains to plan integration with bridge hub due to all the open questions. Will keep an eye on those and revisit this topic later once the implementations are more complete.