# ERC - Shared Bridge standardization -- DRAFT
## Table of contents
- [Introduction](#Introduction)
- [Chain ID registry](#Chain-id-registry)
- [Cross-chain transactions](#Cross-chain-transaction-standard)
- [](#f)
- [msg.data](#msgdata)
- [msg.sender](#msgsender)
- [msg.value](#msgvalue)
- [Securing token bridging](#Settlement)
- [Bridge Contracts](#Bridge-contracts)
- [Settlement](#Settlement)
- [Finality](#Finality)
- [L3s](#L3s)
- [Message root](#Message-root)
## Introduction
Interop is happening inside multiple L2 ecosystems. It makes sense to standardize these efforts so we can connect these ecosystems. These ecosystems don't trust each other, and each has their own proof system and verifier contracts which might be malicious.
The case study that one should have in mind is a user initiating a cross-chain non-native USDC transfer from ZKsync Era (base token Eth) to Xai Arbitrum L3 (base token Xai). This example illustrates multiple properties:
- the chains are on different ecosystems
- one of the chains is an L3
- the chains have different base tokens
- a token is bridged between the chains
- the bridged token (non-native USDC) requires a custom token contract (USDC token [standard](https://www.circle.com/blog/bridged-usdc-standard#:~:text=Bridged%20USDC%20Standard%20is%20a,native%20issuance%20in%20the%20future.))
The tx is picked on the destination chain and executed automatically without further interaction from the user.
To properly enable interop between chains we need to standardize the following components:
1. Chain-id registry
2. Cross-chain transactions
3. Security assumptions around $msg.value$ and token transfers
4. Bridge contracts
5. Settlement
6. MessageRoot i.e. transaction commitment scheme
We provide a high level outline of each component as well as how they fit together. We will look at what this can mean from a security point of view for chains and a UX point of view for users.
## Chain ID registry
We need to enable a chainId registry, so chains can keep track of each other even in different ecosystems. [EIP-7785](https://github.com/ethereum/ERCs/pull/669), has started this standardization process.
## Cross-chain transaction standard
A user has to start a cross chain transactions on the sender chain, and the destination chain should pick it up automatically requiring no further interaction. This makes the receiving tx like an internal call (it needs no signatures), with the usual fields: $msg.data$, $msg.sender$, $msg.value$, $gasleft$ etc.
External bridging standards cannot execute transactions automatically, as someone with funds has to pay for the receiving tx on the destination chain. By adding native support for cross-chain transactions automatic execution is possible. This means adding a new transaction type which does not use signature verification of the user but merkle proof verification of the cross-chain transaction to pay for gas. We can also provide backwards compatibility with these legacy standards by allowing the user to pass $0$ as the $gasleft$, and allow the tx to be triggered on the recipient chain manually.
Lets look at how we can handle some of these different fields.
### $msg.data$
The $msg.data$ does not need to be changed at all between the sender and destination chain.
### $msg.sender$
The $msg.sender$ address is already aliased for L1->L2 txs, we need to extend this to prevent address collisions. We need to apply different aliases to txs coming from different chains, to be able to differentiate calls from them. The $chainId$ of the calling chain is useful here. Also simple mask aliasing, i.e. $alias(address, chainId) = address + chainId$ does not work, as the sender's chain's proof system could be malicious, so they could choose the address arbitrarily. However $alias(address, chainId) = keccak256(address, chainId) >> 160$ (i.e. 160 bits of the hash) will work. This alias has to be enforced on the destination chain. This method prevents address collisions, i.e. access control will work.
We should not that the $msg.sender$ security assumptions are still slightly different from a single ecosystem. The difference comes from the assumptions for $CREATE2$ addresses. Inside a single ecosystem we can know that a contract deployed at an address specified by $CREATE2$ will have fixed code. With potentially malicious verifiers this is not the case. If an app developer wants to deploy their contracts to multiple chains at a fixed address, they will have to whitelist the verifiers. However to new chains with whitelisted verifiers, the contract could even be deployed permissionlessly. This means it will remain the responsibility of the app developers to whitelist verifiers.
### $msg.value$
We also need to append the $msg.value$ to the cross chain call. This is the hardest to enforce. We should consider the $msg.value$ as an enshrined token application. We just saw that the app developers have to whitelist verifiers on which the app can be deployed. If we want the adding new verifiers to be permissionless, then this will not work. This means we need to add additional infrastructure to verify the correct passing of $msg.value$, and token bridging in general.
### Securing token bridging
We need to be able to track the balance of each token on each chain, making sure no chain can spend more than the funds they have. This idea has multiple names, ZK IP, Interchain Accounting, Asset Tracking.
This means we need to check the cross-chain txs. For each chain we need to:
- store the balance of each token on the chain
- verify and parse outgoing and incoming cross-chain txs,
- check if they are sent by the enshrined bridge contracts,
- check which tokens they are transferring and how much,
- if the txs are outgoing check that the chain has the funds,
- and we need to subtract or add the amounts to the chain's balance.

This process would be verified in universally accepted Asset Tracker contract that is shared between all chains. When the chain settles it main proof, it will also have to verify its Asset Tracker proof[^2] in parallel, and compare that the processed cross-chain messages match. Verification means either running computation in the L1 contract, or using a state commitment and ZK proofs and running the computation offchain. There are benefits to both:
1. On L1 it is expensive[^3] but simple to implement and to coordinate around as there are no additional trust assumptions.
2. Using ZK is cheaper, more complex to implement, but it is especially hard to coordinate around a trusted proof system.
We could implement the smart contract version quite quickly and in the longer term we could upgrade it to a ZK based version. The ZK version could use multi-provers, this would make it easier to coordinate and would provide additional security.
The transition to this system from the current system would require depositing the balance of all chains into a Shared Bridge contracts that is shared by all ecosystems. The bootstrapping of chain balances in the asset tracker would happen with this transfer.
[^2]: There would have to be a separate proof for each L2, as not all chains will be sequenced together. This is a minimal overhead, as the circuits can be optimized for this single task.
[^3]: Although sending single txs using this method would be expensive, as the data would have to be processed on L1, mass transfers could be supported. For this additional L2 contracts would need to be enshrined. It could even be coupled with [LPs for faster bridging](https://www.erc7683.org/).
## Bridge contracts
We need to standardize the bridge contracts. Coming back to our case study, bridging USDC between Era and Xai, where Xai has a custom base token (i.e. not Eth).
USDC token contracts should implement USDC's [standard](https://www.circle.com/blog/bridged-usdc-standard#:~:text=Bridged%20USDC%20Standard%20is%20a,native%20issuance%20in%20the%20future.). Enabling this level of customization needs be enabled in the bridge.
We need to support multiple features here:
- enabling custom token bridging
- enabling custom base token bridging
- supporting the Asset Tracking for custom tokens
The bridge contracts on every chain should be the same, so that apps can deploy seamlessly on every chain.
## Settlement
### Finality
The sender chain needs to provide some sort of finality before the receiving chain can import the tx. Depending on the level of trust between the chains different levels of finality can be used.
1. If the chains do not trust each other at all, L1 state root finality is needed, i.e. when the state root of the sending chain can not change anymore on L1 in the chain's smart contract.
2. If the chains are running each others' nodes, then L1 transaction ordering finality is enough, as the new state root can be calculated based on this.
3. And if the chains trust each other, they can import the txs directly after the block is sealed.
4. If the chains use a Shared Sequencer (with shared block building infrastructure), then the blocks of the two chains can be built in parallel, and cross chain txs can done as the blocks are built.
We should plan to support all of these use cases. The low hanging fruit is 1-3, the parallel block building will require a bit more complicated infrastructure.
Note that 1. might be a bit slow (especially for optimistic rollups), but liquidity providers can make even that solution faster for token transfers.
### L3s and aggregation
In our case study XAI is an L3. There are a lot of L3s live today, they should be able to participate in interop.
The hard part about L3s is integrating them into the is Asset Tracking solution. In short term Asset Tracking will happen in smart contracts, these can be on L1 or L2.
- If they are tracked on L1 the L2s and L3s funds are separate on L1. L3<>L3 txs will be more expensive, as the txs will have to be processed on L1.
- If the funds are tracked on the L2 then the L3s funds are added to the L2's on the L1 asset tracker. In this case the funds are less secure
A mix can also be used, some funds are tracked on L1 some on L2 with some rebalancing mechanism.
In the longer term the Asset Tracker will use ZK proofs. In this case the proofs can be cheaply verified both on L1 and L2. [^4] To make verification cheaper the proofs should also be aggregated. When a proof Asset Tracker proof is settled, it imports some Message Root and outputs outgoing txs commitments. These inputs and outputs can also be aggregated across chains. This would also make it compatible with intermediate proof aggregation layers.
[^4]: the verification on the L2 would not be binding on the L1 contracts, the L2's verifier could implement a mechanism to mitigate discrepancies.
## Message root
Once the cross-chain tx is sent, it needs to be bundled together with other txs, and the cross-chain message root for the L2's block needs to be sent to L1. Here the root needs to be aggregated across multiple chains in a shared Message Root contract.
The destination chain can then import this root, can receive the cross-chain txs, can verify the txs using the Message Root and a merkle proof, and execute the txs. We need to standardize the tree structure and the hash functions.
### Todo
Figure out MessageRoot structure that allows:
- L3s
- Shared sequencing
- proof aggregation in the future for Asset Tracker proofs.