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):
- (BridgeHubRococo) initialize bridge - Rococo governance call
xcm::Transact
with initialize call
- (BridgeHubWococo) initialize bridge - Wococo governance call
xcm::Transact
with initialize call
Steps to allow bridge transfer were:
- (Rococo)
force_open_hrmp_channel(rockmine2_para_id, bridge_hub_rococo_para_id)
and back as governance call
- (Statemine) add configuration to allow send assets to Wococo:Wockmint - Rococo governance call
xcm::Transact
with add_exporter_config call
- (Wococo)
force_open_hrmp_channel(wockmint_para_id, bridge_hub_wococo_para_id)
and back as governance call
- (Wockmint) add configuration for trusted
UniversalOrigin/Alias
mapping - Wococo governance call xcm::Transact
with add_universal_alias call
- (Wockmint) add configuration for trusted
reserve location
- Wococo governance call xcm::Transact
with add_reserve_location call
- (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