Technical Details

SubBridge is different from general cross-chain solutions in that they only realize the transfer of assets and data between two chains.

SubBridge is more like a router linking different cross-chain bridges and allows asset transfer from one chain to any other chains which have been registered. For example, we have implemented the transfer of ERC20 assets on Moonriver and Ethereum to other parachains in the Polkadot ecosystem through SubBridge. To accomplish this, it is not necessary for the parachain receiving the asset to have an EVM cross-chain bridge integrated into its runtime. This is done by the SubBridge.

As shown in the figure below, SubBridge integrates the implementation of multiple bridges, here we use BridgeA, BridgeB, and BridgeC to represent. When SubBridge receives a cross-chain asset transfer, it will choose whether to forward the transaction to another chain according to the destination address. If the transaction is only transferred to an account in the Khala or Phala network, we will deposit the asset directly into the receiving account; in the case of another chain, usually, this needs to ensure:

  • The destination is already supported by a certain bridge, that is, the SubBridge will traverse the list of bridges to check whether the bridge supports transfers to the destination address, and if so, use this bridge for forwarding.

  • Make sure that the format of the path conforms to our specification [see next section] and still has enough assets as a fee to pay the cross-chain fee to the other chain.

It can be seen that we can not only realize the cross-chain transfer of assets through multiple bridges but also try to choose a transfer path with the lowest fee for users

MultiAsset and MultiLocation

The purpose of SubBridge is to connect assets in multiple chains. Therefore, how to unify the definitions of assets and locations in multiple chains is the first problem we need to solve. After research, we thought of MultiAsset and MultiLocation in the Polkadot XCM protocol. MultiAsset is used to represent a certain asset on a certain chain. For example, the asset of PHA can be expressed as:

MultiAsset::new(Fungible(amount), Concrete(pha_location))

Where amount is a certain amount of asset, pha_location is the path of PHA under the XCM protocol standard, which is defined by SubBridge and represented by MultiLocation, usually represented as:

MultiLocation::new(1, X1(Parachain(2035)))

Among them, 2035 is the parachain ID of the Phala network. So how do we use the XCM protocol to represent any non-parachain‘s account address? It determines how SubBridge will recognize and forward cross-chain transactions.

What we do in practice is that we incorporate other non-parachains into sub-addresses of the Phala network, similar to the local area network specified by TCP/IP. In this way, the account address of an EVM chain can be represented as:

MultiLocation::new(1, X4(Parachain(2035), GeneralKey(bridge), GeneralIndex(chain), GeneralKey(account)))

Among them, bridge represents a specific bridge, for example, SygmaBridge uses sygma to represent; ChainBridge uses cb to represent; chain represents the ID of the EVM chain under the EVM Bridge system. Currently, Ethereum is 0 under both SygmaBridge and ChainBridge protocol; account represents the ID on the EVM chain. An account, usually a 20-byte hexadecimal string.

Similarly, the assets of any chain also need to be unified. The assets on the parachain are defined by the team of the parachain to define their corresponding MultiAsset; the EVM chain assets based on SubBridge are also defined as the sub-asset of the Khala network like the account address. That is, the usual asset location would be represented as:

MultiLocation::new(1, X3(Parachain(2035), GeneralIndex(chain), GeneralKey(token)))

Among them, token represents the contract address of a certain ERC20 or ERC721 of EVM.

Asset Registration

The registration of SubBridge assets is mainly divided into two parts:

The first part is to register assets into the pallet-assets module. SubBridge uses the pallet-assets module provided by Substrate to manage the registered assets. The registered assets will be assigned an asset id. Each asset has an extra registry info which contains information of location, enabled bridges and properties. Unregistered assets will fail regardless of whether they are transferred via the EVM bridge or the XCM bridge.

The second part is to enable the corresponding EVM bridge. This part is only for the asset settings that want to carry out the cross-chain requirement from Phala to the EVM chain. In SubBridge, the same asset can enable both SygmaBridge-based bridges and ChainBridge-based bridges. In practice, users are always willing to choose solutions with lower fees.

The steps to do the registration stuff are as follow:

  • Step1, we schedule a call of pallet-registry::forceRegisterAsset with given registration informations. When the council enacted the call, an asset instance will be created by pallet-assets, and some extra registration information will be saved in pallet-registry.

    There are several things we need to pay attention to. The first one is that each asset has a bunch of metadata defined in pallet-assets, like name, symbol, etc. We have provided an extrinsic called forceSetMetadata in pallet-registry which can be used to update the metadata of an asset. Another one is that each asset has some privileged accounts used to manage the asset, like Issuer, Admin, etc. Different account has different permission. In asset-registry, we set all the privileged accounts of each asset to an account derived by PalletId(b"phala/ar"). This means no external account has permission to do things beyond authority.

    All registered assets can be found at here. The asset registration informations are stored on-chain, head to and choose RPC assetsRegistry→registryInfoByIds to see details. Here is a screenshot of KSM registration information:

<figure><img src="../../.gitbook/assets/subbridge-assetinfo.png" alt=""><figcaption><p>Registration infomartion of KSM</p></figcaption></figure>

Note: For assets on Phala, also can be found on Assets tab in polkadot.js app

  • Step2[optional], after the asset was registered, by default all assets will enable XCM crosschain transfer. If the asset is going to enable SygmaBridge or ChainBridge, another call named assetRegistry::forceEnabledSygmaBridge or assetRegistry::forceEnabledChainbridge should be enacted by the council. This will enable the crosschain transfer to a specific EVM chain. And assetRegistry::forceDisableSygmaBridge or assetRegistry::forceDisableChainBridge is used to disable it. When SygmaBridge or ChainBridge was enabled for the asset, you will see we have new data being added to the returned registration information. For example, the enabled-bridges information of ZLK is shown below:

    enabledBridges: [
            config: Xcmp
            config: {
            ChainBridge: {
                chainId: 2
                resourceId: 0x028da1efb56e124f659fa6d5d95b3cc541ce207cbfee2f4f066061cc92d37bae
                reserveAccount: 0xde50ca45c8f7323ea372fd5d7929b9f37946690b0b668985beebe60431badcea
                isMintable: false
            metadata: 0x00

    Looking at the ChainBridge filed, the chainId is 2 means it has enabled crosschain transfer between the Khala network and Moonriver EVM. ResourceId is used to bind ZLK on the Khala network and ERC20-ZLK on Moonriver EVM. reserveAccount is used to save ZLK temporarily when transferring ZLK from the Khala network to Moonriver EVM, and will transfer back to the recipient account when someone transfer ZLK from Moonriver EVM back to Khala network. isMintable is false tells the client that should aware of the ZLK balance of reserve account.

  • Step3[If Step2 has been done], we also need to config your asset in our ChainBridge Bridge contract before finally launching the crosschain transfer through ChainBridge. It including:

    • Binding resource id generated during registration with its ERC20 contract address. This essentially is done by executing method adminSetResource of Bridge contract.

    • Set decimals of the asset by executing method adminSetDecimals. SubBridge is compatible with the scenario that asset has different decimals between substrate side and EVM side.

    • If your asset is burnable and would like to give the mint/burn permission to our contract, we need to tell the contract to mark your asset as burnable by executing method adminSetBurnable. With burnable set, when the user transfers asset from EVM chains, the asset would be burned directly from their account, and mint to the recipient account when someone transfers back to EVM chains.

Note: For SygmaBridge, asset config need to be done by Sygma team.

The Lifecycle of Cross-chain Transaction

The life cycle of a transfer across three chains can be described in the above figure. In the above picture, assets are transferred between Parachains on the left and EVM Chains on the right, passing through the Phala network in the middle.

Take SygmaBridge as an example, when a cross-chain transfer is initiated from a parachain, after executing the local XCM command (such as burning a certain amount of assets from the sending account) it will be wrapped into a cross-chain XCM message and sent from the parachain to the Phala network, the XCM related modules of the Phala network will be responsible for processing the message. The transmission and instruction processing of XCM cross-chain messages are handled by Polkadot’s XCM-related modules. During the execution of the instruction, when the DepositAsset instruction is executed, SubBridge will parse the payment address. If it points to the address of another EVM Chain, the transaction will be forwarded through the SygmaBridge module.

Similarly, when a cross-chain transfer is initiated from EVM Chains, the SygmaBridge Relayer will forward the message to the SygmaBridge pallet module of SubBridge. After the SygmaBridge module performs a series of verifications on the transaction, it will process the asset with the same logic. If it is resolved that the receiving address is not an address in the local Phala network but an address on a parachain, SubBridge’s XCM module will be triggered to forward the transaction.


SubBridge's SygmaBridge in mantained by Phala team and Sygma team together. The substrate side is exist on Phala network, the smart contract on EVM side is deployed by Sygma team and the liquidity is maintained by both Phala team and Sygma team through multi-sig account.

SubBridge’s ChainBridge cross-chain bridge module is maintained and developed by the Phala team and is responsible for running three Relayers. The Relayer of the ChainBridge cross-chain bridge constructs the captured origin chain cross-chain transaction into a proposal, and then the three relayers vote on the Proposal. After the vote is passed, the proposal will be executed and the assets will be deposited in the user address.

About ChainBridge, you can refer to their website.

For the Phala Ethereum ChainBridge contract, please refer to the source code on github.

Code Auditing

The bridges currently integrated by SubBridge include 3 implementations, XCM, SygmaBridge, and ChainBridge.

XCM is a cross-chain message protocol implemented by Parity Tech in the two networks of Polkadot and Kusama. Its code has been audited by a third-party audit firm hired by Parity. The audit report on XCM V2 (the current version of XCM used by SubBridge) can be found here

As for SygmaBridge, both the solidity smart contract and substrate pallet are get audited, the audit report can be found here

Earlier 2022, we deployed ChainBridge’s Solidity contract on Ethereum. The contract info can be found here. Recently we migrated the old contract to the new deploy one 0x8F92e7353b180937895E0C5937d616E8ea1A2Bb9. Up to now, the contract has been running safely for nearly a year, and the contract has also been audited by Certik, a third-party auditor hired by Phala. The detailed audit report can be found here


Last updated