Update on Snowbridge

Howdy everyone, just an update on our progress:

  1. A while back, we completed the re-architecture of our bridge to support BridgeHub, AssetHub, and XCMv3. Please read the following for more details: https://docs.snowbridge.network/architecture/

  2. The Ethereum side of our bridge (also known as the Gateway), is now completely governed by Polkadot OpenGov on the Polkadot side of the bridge. This means there are no governance fallbacks or escape hatches on the Ethereum side. We found a way to make it work.

  3. The main audit of our code has been completed, and after a QA process, we can expect the final report to be published some time next month. We’re working on several issues discovered in the audit. However these are largely straightforward fixes and don’t impact our timelines substantially. Some of the more important audit issues include:

    • On BridgeHub, a permissionless API (create_agent) could be used as DOS vector. The solution involves requiring a deposit for the use of this API.
    • On BridgeHub, Administrative commands to the Ethereum side of the bridge could be throttled and delayed. The solution involves giving these admin commands priority in the outbound queue to Ethereum.
    • On BridgeHub, Incoming messages from Ethereum could be silently discarded if there was HRMP congestion between BridgeHub and the final destination parachain. The solution involves failing the entire substrate transaction, so that message relayers back-off until congestion resolves.
  4. With help from W3F and CommonPrefix, we’ve designed improvements that increase the security of our BEEFY light client running on Ethereum. The light client uses RANDAO on Ethereum PoS as a source of randomness for selecting a subset of BEEFY validators which relayers must provide signatures for. The solution forces relayers to provide increasingly larger number of signatures if they attempt to game the system in a way that biases the selected RANDAO seed in their favour.

  5. We’ve successfully tested bidirectional ERC20 token transfers between Rococo and Goerli (An ethereum PoS testnet). We’ll want to start testing with other Rococo parachains soon.

  6. As an estimation, we’re looking at another month of development before starting the process of deploying on Kusama. Since our bridge lives on a system parachain (BridgeHub), we need to align with Parity’s release process for system parachains.

    • Fixing remaining audit issues (should not take longer than 2-3 weeks)
    • Updating to latest Polkadot-SDK dependencies which includes new BridgeHub & AssetHub APIs we have to consume.
    • Merging portions of our codebase into the bridges subproject of the Polkadot-SDK monorepo
    • Some outstanding issues relating to collecting XCM delivery fees on BridgeHub
    • We also require that BEEFY is deployed and activated on Kusama first.
  7. To be clear, while the core of our bridge is designed to be general-purpose, we are launching features in an iterative manner. Our initial launch will include ERC20 token transfers. A subsequent upgrade post-launch will enable XCM::Transact. Followed by support for transferring Polkadot-native tokens to Ethereum. We believe this iterative process increases the security of the bridge by allowing our team and our auditors to focus on one feature at a time. Nevertheless, we’ve made sure our core architecture and APIs are flexible enough to support this iterative model. For example, on Ethereum, our Gateway.sendToken API will be used to send both Ethereum-native and Polkadot-native tokens to Polkadot

  8. I’ll be presenting at Sub0 next week. We’ll also have a demo booth where people can try out our Rococo bridge.

20 Likes

Hearty congratulations! Its a very long road, I hope you guys enjoy the sweat and tears of the journey =)

Can you write up how this works here (and update snowbridge governance), specifically sharing the timing of regular vs emergency actions that you anticipate could be needed?

Some easy basic FAQ stuff:

  • Does registerToken (of ERC20 vs Assethub tokens) require an explicit OpenGov action?
  • What does a parachain need to do to get their AssetHub / Polkadot native asset as an ERC20?
  • How can the bridge/gateway be paused/resumed?

Congratulations! For Rococo Assethub => Goerli Testnet, can you share the following:

  1. working registerToken AssetHub on Rococo extrinsicID
  2. working sendToken extrinsicID and the evidence of success (tx logs/events) on Goerli Testnet

For Goerli Testnet => Rococo Assethub, can you share the following:

  1. working registerToken(address) transaction hashes
  2. working sendToken(address, ParaID, bytes32, uint128) transaction hashes and the evidence of success (extrinsic events) on Rococo Assethub

Please highlight the outbound/inbound messages and post your Goerli contract addresses / Bridgehub / Assethub runtime versions so people can do a deep-dive, thank you!

Kindly share the url where we can try it?

How is the ethereum side being trusted? Did you go the ETH Light Client rotue?

Sure, yeah we do need to flesh out documentation site. Though let me try and answer some of your questions quickly:

Regarding governance, on BridgeHub there are several privileged governance APIs that only Polkadot OpenGov can invoke. For example:

  • Upgrading the Gateway contract on Ethereum
  • Selectively pausing/resuming the Gateway on Ethereum, for example to disable outbound messages to Polkadot
  • Pausing/resuming specific bridging pallets on BridgeHub. For the sake of uniformity These APIs are actually shared with Polkadot-Kusama bridge, and so we can expect to have similar governance playbooks.

Regular governance actions will include upgrading the Gateway contract (and any of its dependencies, such as our Beefy light client). The upgrades should be audited before being proposed to OpenGov.

Emergency actions would be a halting/resuming parts of the bridge, as per the APIs described above.

  • Does registerToken (of ERC20 vs Assethub tokens) require an explicit OpenGov action?

Nope. Token registration is permissionless. However it will require a hefty deposit to discourage spamming. Even so, malicious parties on Ethereum can pay that deposit and register fake ERC20 tokens. It’s up to indexers, users, and other parachains to exercise good judgement when deciding whether to trust a specific bridged token on AssetHub.

  • What does a parachain need to do to get their AssetHub / Polkadot native asset as an ERC20?

As I described in my original post, the bridge does not currently support bridging Polkadot-native tokens to Ethereum. This will be one of the priorities after our initial launch.

We do have a design mapped out, and it will be a 2-step process:

  1. Parachain governance calls a register_token(location, metadata) extrinsic on BridgeHub using Xcm::Transact. This will send a command over to Ethereum, resulting in a new ERC20 contract being instantiated with the provided metadata (name, symbols, decimals).

  2. The parachain can then send regular XCM asset instructions to BridgeHub, resulting in new tokens being minted in the ERC20 contract from (1).

To send Polkadot-native tokens back to Polkadot, users can use the existing Gateway.sendToken API.

We’re not quite ready to support the public in using our Rococo testnet, but in the meantime, here are some of those transactions you’ve requested :slight_smile:.

Note that we are running our own instances of BridgeHub and Asset on Rococo until our auditing process is completed.

Register Token

  1. Register token initiated from Goerli for the Native Goerli ETH (GETH) token.

  2. Snowbridge BridgeHub fork (Parachain 3016) inbound message received.

  3. Snowbridge AssetHub fork (Parachain 3416) Create asset processed.

Send Token

  1. Send token initiated from Goerli for the Wrapped Ether (WETH) token.

  2. Snowbridge BridgeHub fork (Parachain 3016) inbound message submitted.

  3. Snowbridge AssetHub fork (Parachain 3416) Issue asset processed.

Send tokens back to Goerli

  1. Bridge transfer initiated on Snowbridge AssetHub fork (Parachain 3416) to send WETH back to Goerli. (Note this extrinsic is being depreciated in favor of pallet-xcm in future versions)

  2. Snowbridge BridgeHub fork (Parachian 3016) outbound message submitted.

  3. Inbound message received and processed on Goerli.

Hello, another update on the progress of Snowbridge.

Deployment

  1. We are now in the process of merging our pallets and support code into the upstream Polkadot-SDK monorepo. We are doing this using git subtree to avoid having to keep everything in sync using companion PRs.

  2. Once this done, we will publish our crates, and add our pallets to the BridgeHub runtimes in the polkadot-fellows/runtimes repo. The pallets will disabled in production until our ongoing re-audit is finalized.

BEEFY light client

We have improved the resilience of our light client against certain kinds of attacks by implementing a dynamic signature sampling algorithm devised by W3F.

The new algorithm essentially punishes malicious relayers by forcing them to submit more and more BEEFY signatures, at a greater cost to themselves.

Token Bridge

We have improved our Solidity API for sending ERC20 tokens to an arbitrary Polkadot parachain.

A user can call IGateway.quoteSendTokenFee to determine the fee in Ether they would need to pay for the transfer.

    function quoteSendTokenFee(
        address token,
        ParaID destinationChain,
        uint128 destinationFee
    ) external view returns (uint256);

A user can then call IGateway.sendToken to initiate the transfer.

    function sendToken(
        address token,
        ParaID destinationChain,
        MultiAddress calldata destinationAddress,
        uint128 destinationFee,
        uint128 amount
    ) external payable;

The user needs to specify the correct destinationFee (DOT), which is the XCM fee the destination chain would charge for processing the reserve-backed transfer from AssetHub. We envision that the UX layer would keep a table of fees for each parachain.

In the opposite direction, parachains can send tokens back to Ethereum by calling the xcm.reserveTransfer extrinsic on AssetHub, after doing a reserve transfer to AssetHub itself.

Fees & Rewards

In our latest architecture, on-chain conversions between Ether and DOT are performed using static exchange rates that need to be periodically updated by Polkadot governance.

While this will end up increasing pricing for users, it does have several notable benefits:

  • Ensures the decentralized nature of the bridge, which centralized oracles such as Chainlink cannot provide.
  • Reduced gas fees for Ethereum->Polkadot transfers, compared to other approaches which for example could involve paying for fees using wrapped DOT obtained from some DEX like Uniswap.

We assume that once AssetHub implements a DEX, we can consume a live price feed from it, subject to various checks and balances.

For more information about fees & rewards, see our docs.

XCM SetTopic As Message ID

To improve the traceability of bridge messages across the bridge, we are making use of the new SetTopic instruction.

For example, in the Polkadot->Ethereum direction, the xcm topic will logged on the Ethereum side, in the the messageID field of the InboundMessageDispatched event. Similarly, in the other direction, a topic will be included in the message sent to Polkadot.

Protocol Versioning

We have overhauled all our protocol-level data formats with support for versioning. This is important for ensuring that the bridge can be upgraded live without any downtime or potential data loss.

Ethereum Cancun-Deneb Upgrade

The Ethereum beacon and execution chains will be upgraded sometime in Q1 2024.

We have completed the necessary modifications to our ethereum light client in https://github.com/Snowfork/snowbridge/pull/981.

Audits

  1. Our BEEFY light client has completed a re-audit and is now considered production ready.

  2. There is an ongoing re-audit for the rest of our codebase, covering the following issues discovered in the the initial audit, as well as subsequent improvements:

    • Our usage of the FRAME MessageQueue pallet for buffering outbound messages to Ethereum.
    • Ensuring governance commands are always processed with a higher priority than other commands.
    • Incomplete code and outstanding TODOs, especially around the fee/rewards mechanism
    • Improved API on Ethereum for sending tokens across the bridge

Next Steps

Now that we are essentially code complete (pending the ongoing re-audit), our focus is going to be on the following:

  1. Completing upstream merge to Polkadot-SDK and polkadot-fellows/runtimes.
  2. Organising bug bounty programs on Rococo, Kusama, and Polkadot
  3. Creating an integration guide for third-party parachains.
  4. Adding support for other application-level features that users have been requesting. We already have a prototypes for these and will release them as post-launch upgrades:
    • General-purpose messaging with XCM Transact
    • Bridging Polkadot-native assets to Ethereum
8 Likes

Hello, another update, our first one for the new year.

Audits

This time around, we can finally present our audit reports, which have been published.

  1. After several rounds of review, the comprehensive audits conducted by Oak Security have been finalized and published. These audits cover our Substrate pallets and Ethereum contracts
  2. Initial audit and STRIDE threat model covering our codebase as of August 6th 2023, published here. Bear mind this audit is quite obsolete, as it covers code which is more than 6 months old.
  3. An extension audit, covering subsequent changes, as well as fixes for several critical issues, published here.
  4. We also commissioned CommonPrefix to conduct an extra, redundant audit of our BEEFY light client, published here.

We acknowledge that the extension audit in (3) includes several issues, marked by the auditors as high-severity, that we have chosen to leave unaddressed. Our position is that these issues can be easily remedied in offchain UX layers that mediate access to the bridge. For us to remedy them on-chain would be undesirable in terms of the effect on bridging latency and operational costs (ultimately born by users). In the report, the auditors have included our proposed remedies.

Rococo<->Sepolia Testnet

This stack has been running well for over a month, allowing bidirectional ERC20 transfers from Rococo to the Sepolia testnet.

During this time, together with the Parity Bridges team, we uncovered a edge-case in the BEEFY protocol, where the mandatory BEEFY commitment for each new session did not include sufficient information to allow our BEEFY light client to switch over to the new validator set. This has since been patched upstream, and we managed to recover our bridge successfully.

We are also developing a developer UI to allow third-party parachain teams to test our bridge and ease integration. We will follow up soon with an update on this.

Code Organisation

Since our bridge is launching on the BridgeHub system parachain, we had to make a few significant devops changes to make align our project with the way system parachains are developed and released. Particularly, our substrate pallets have been moved from our Snowbridge monorepo to this directory in the Polkadot-SDK repo.

This ensures that Polkadot-SDK contributors can update our substrate pallets easily without having to submit companion PRs. Additionally, our pallets will automatically be published on crates.io for every new release of the Polkadot-SDK.

Indeed, this publishing of crates is a a prerequisite for adding our pallets to the system runtimes in GitHub - polkadot-fellows/runtimes: The various runtimes which make up the core subsystems of networks for which the Fellowship is represented..

Launch Plan

The next step in launching on Kusama & Polkadot is to have our pallets and runtime configuration added to the system runtimes for AssetHub and BridgeHub. This is being tracked in Draft - Adds Snowbridge (based on Kusama <-> Polkadot bridge PR) by claravanstaden · Pull Request #130 · polkadot-fellows/runtimes · GitHub. As the last comment in the PR states, this is blocked on the runtimes being updated to use 1.7 of the Polkadot SDK.

We are tentatively aiming at mid-March for our code actually being deployed to the system parachains on Kusama & Polkadot.

Note that the bridge will launch in a disabled state, and will require several governance proposals to be properly activated.

Operational Concerns

Another focus for our team is to produce several operational runbooks describing how to maintain all aspects of the bridge. The first one has been published at Updating Snowbridge Pallets, BridgeHub & AssetHub Runtimes - Snowbridge.

Support for XCM Transact

As we stated previously, the bridge will initially launch with only support for ERC20 token transfers.

Many teams also want support for cross-chain XCM Transact, and so we are also prioritizing support for this. We already have a working end-to-end prototype implementation and our plan is to release this post-launch as a soon as possible, once the API and audits are finalized.

Some design specifics:

  • In the Ethereum->Parachain direction, it is a prerequisite that the user on the Ethereum has a pre-funded sovereign account on the destination parachain, from which fees for XCM execution will be withdrawn
  • In the Parachain->Ethereum direction, it is a prerequisite that the consensus system on the origin parachain has already instantiated an proxy contract (known as an Agent) on Ethereum.
12 Likes