To accomplish cross-chain asset transfer, most of the currently available solutions are based on a bridge, a separate, intermediate entity typically trusted with holding these assets during some period of the transaction. This trust assumption is undesirable, as it creates a large opportunity for attack. In this post, I will explain that, assuming the existence of a zkRollup, one can implement cross-chain asset transfer without the need for additional trust assumptions (such as a bridge).
Suppose you hold 500,000 USDT as an L2 asset on Ethereum, and you want to transfer it to USDT on Avalanche. Currently, you would need to contract the services of a bridge, B, a separate entity that will "buy" your ETH-USDT and, shortly after, "sell" you AVE-USDT.
Observe that various assumptions are at work here:
In this post, I will show a way to accomplish this asset transfer without the disadvantages mentioned here. More specifically, I will show that by judiciously combining the underlying primitives and using the standard security assumptions of zkRollups, we can implement cross-chain asset transfer.
To this end, we must first prepare the stage by summarizing Rollups in general and zkRollups in particular. Then, we will examine intra-layer and cross-layer asset transfer and discuss what a proof of transaction entails in each case. This sets the stage for the most important part: cross-chain asset transfer. We will first consider an L1-to-L1 scenario, followed by an L2-to-L2 scenario. As a new contribution, we will present the entangled rollup: one L2 shared by two L1s. This will be followed by a discussion on cross-chain communication methods and underlying assumptions.
In a rollup, transaction processing is taken off-chain and combined into batches to reduce cost and enhance speed. However, every transaction will be recorded on the main chain, along with the overall rollup ledger's state. There is always a delay between the core L2 and its being recorded on L1.
In the words of Vitalik Buterin:
“Rollups move computation (and state storage) off-chain, but keep some data per transaction on-chain. To improve efficiency, they use a whole host of fancy compression tricks to replace data with computation wherever possible. [...] There is a smart contract on-chain which maintains a state root: the Merkle root of the state of the rollup (meaning, the account balances, contract code, etc., that are "inside" the rollup). Anyone can publish a batch, a collection of transactions in a highly compressed form together with the previous state root and the new state root (the Merkle root after processing the transactions). The contract checks that the previous state root in the batch matches its current state root; if it does, it switches the state root to the new state root.”
For data, this means that all transaction data must stay on L1, but in compressed form to reduce gas costs. For processing, this means that computations are moved to L2 as much as possible, while only the results are written on L1.
In other words, a rollup emulates the ledger functionality on top of the original blockchain, which are therefore called Layer 2 and Layer 1, respectively.
But how is transaction validity assured in a rollup?
Just relying on the correctness of the smart contracts that implements the rollup is not enough. The definition of a rollup is that each state transition (i.e.\ transaction validity) is maintained, verified and endorsed by the main chain, which therefore needs an external (software independent) validation or verification mechanism, independent of the L2 implementation.
In an optimistic rollup, an entity (often called the Sequencer) publishes \( oldStateRoot_2, txBatch, newStateRoot \)(which relate to Layer 2) on \( layer_1 \). During a specified period of time (often seven days), this state^ change can be challenged by an outsider. If no such challenge occurs, the proposed state becomes permanent (hence "optimistic"). However, if a state change is challenged, the following process is triggered.
An arbitration contract on L1, assumed to exist, will decide whether the Sequencer or the Challenger is correct. This arbitration contract is activated by the Challenger.
The contract then declares who is right and who is wrong. As a result, the loser of the arbitration will have their bond (a significant deposit) slashed as a penalty.
Thus, in an optimistic rollup, parties have an economic (game-theoretic) incentive to behave honestly.
For a more detailed description about optimistic rollups, see:
ethereum.org/en/developers/docs/scaling/optimistic-rollups/#what-is-an-optimistic-rollup
In a zkRollup, a different approach is taken. For every state transition \( oldStateRoot, txBatch \Longrightarrow newStateRoot \) a proof of knowledge is generated, which shows that \(\text{newStateRoot}_{2}\) is the correct result of executing the batch. Though sometimes known as zero-knowledge proofs, this terminology is misleading, strictly speaking. Privacy isn't an issue in a rollup, since the transactions are supposed to be public anyway. What is an issue, though, is the succinctness of such a proof, since on-chain verification is expensive and therefore should be done efficiently (often a SNARK).
To be more precise: Let \( STF \) denote the state transition function for the Layer 2 ledger. If the Sequencer is honest, we must have that $$ newState = STF(oldState, txBatch) $$
Remember that on a blockchain, transaction contents can take several forms:
So how can L1 (and with it, everybody who's monitoring this main chain) be convinced that L2 indeed computed $newState_2$ correctly from $oldState_2$ and $txBatch$? By applying verifiable computing on STF This means that the execution trace of $STF(oldState_2,batch)$ is sent to a Validity Proof Generator, which produces a succinct non-interactive validity proof that Equation (1) holds.
Subsequently, the rollup contract on L1 has a method which, on input $oldState_2, batch, newState_2, validityProof$, verifies the validity proof and returns an ACCEPT/REJECT verdict. In case of an ACCEPT, $oldState_2, batch, newState_2$ are recorded as valid on L1, while in case of REJECT the batch and state change are simply discarded.
The raison d'être of blockchain is asset transfer, and extreme care is taken to preserve asset invariance during transactions: nothing is lost, nothing is gained. It’s important to note that the underlying security mechanism of asset invariance is subtly different for L1 and L2.
Layer 1
The correctness of asset transfer on L1 is guaranteed by the consensus mechanism adopted for L1 and is publicly verifiable because it is open-source software.
Layer 2.
L1 only guarantees the availability of the rollup data of L2, not its correctness. The correctness of asset transfer on L2 depends on the correct implementation of L2. The zkVM merely verifies that the rollup data published on L1 is consistent with the ledger program on L2, but if there is a mistake in this program, the zkVM will not catch it.
However, since the L2 source is often copied from L1, this risk is minimized.
The decentralized Sequencer ensures that submitted transactions are batched (avoiding censorship) but does not ensure asset invariance.
Given an L1 with an L2 rollup, we can imagine asset transfers between them in two directions. We’ll use Ether as an example:
These cross-layer asset transfers can be interpreted as a vertical bridge, also called a native bridge.
To assure asset invariance, these transactions adhere to one of the following principles, depending on the context:
To accomplish this, we define:
These last two accounts serve to lock and unlock transactions. The smart contracts that manage these accounts are called shadow contracts.
To avoid discussion about lock/unlock versus burn/mint, we assume that, on initialization, a large fixed quantity of ETH₂ is minted for (credited to) RollupAcc₂. These assets remain locked in this account unless unlocked by an equivalent lock transaction on L1 (Polygon does this too). Note that asset invariance should hold: RollupAcc₁ + RollupAcc₂ = InitialQuantity, always.
When transferring assets from L1 to L2, there are two options: using atomicity or the first-destroy-then-create principle.
The rollup smart contract on L1 performs the transaction on both L1 and the rollup, leaving L2 to clean up. Many rollups implement this as an emergency mechanism to avoid censorship.
This approach has some advantages: atomicity is guaranteed by L1, and transaction settlement time is short. However, it complicates sequencing and increases gas costs.
The smart contract on L1 produces a proof of the transaction and sends it to the Sequencer to trigger the transaction on L2. The smart contract on L2 trusts L1, so the proof-of-transaction is not a ZK Proof, just a simple txId.
In step 3, there are several options: SEQ monitors L1, SEQ is alerted by the smart contract on L1, or SEQ is notified by Client X, etc.
The smart contract on L2 produces a proof of the transaction and sends it to the smart contract on L1 as a trigger for the transaction on L1. Since L1 does not trust L2, this proof-of-transaction must be a ZK Proof, which functions like a certified check. Asset invariance is guaranteed through the first-destroy-then-create paradigm.
Measures should be taken to ensure that a check can only be cashed once; maintaining a list of previously cashed checks is a good solution, combined with expiration dates to prevent the list from growing indefinitely.
Note that in this case, triggering the smart contract on L1 to perform the transaction on the rollup and letting L2 clean up the mess is not an option, as the rollup data is compressed and incomprehensible to the smart contract on L1.
Observe that two steps require waiting for the transaction to settle.
This article was written by Jeroen van de Graaf, Senior Cryptographer at ZKM. Part Two of the series will examine the mechanism of the Entangled Rollup in more detail.
To accomplish cross-chain asset transfer, most of the currently available solutions are based on a bridge, a separate, intermediate entity typically trusted with holding these assets during some period of the transaction. This trust assumption is undesirable, as it creates a large opportunity for attack. In this post, I will explain that, assuming the existence of a zkRollup, one can implement cross-chain asset transfer without the need for additional trust assumptions (such as a bridge).
Suppose you hold 500,000 USDT as an L2 asset on Ethereum, and you want to transfer it to USDT on Avalanche. Currently, you would need to contract the services of a bridge, B, a separate entity that will "buy" your ETH-USDT and, shortly after, "sell" you AVE-USDT.
Observe that various assumptions are at work here:
In this post, I will show a way to accomplish this asset transfer without the disadvantages mentioned here. More specifically, I will show that by judiciously combining the underlying primitives and using the standard security assumptions of zkRollups, we can implement cross-chain asset transfer.
To this end, we must first prepare the stage by summarizing Rollups in general and zkRollups in particular. Then, we will examine intra-layer and cross-layer asset transfer and discuss what a proof of transaction entails in each case. This sets the stage for the most important part: cross-chain asset transfer. We will first consider an L1-to-L1 scenario, followed by an L2-to-L2 scenario. As a new contribution, we will present the entangled rollup: one L2 shared by two L1s. This will be followed by a discussion on cross-chain communication methods and underlying assumptions.
In a rollup, transaction processing is taken off-chain and combined into batches to reduce cost and enhance speed. However, every transaction will be recorded on the main chain, along with the overall rollup ledger's state. There is always a delay between the core L2 and its being recorded on L1.
In the words of Vitalik Buterin:
“Rollups move computation (and state storage) off-chain, but keep some data per transaction on-chain. To improve efficiency, they use a whole host of fancy compression tricks to replace data with computation wherever possible. [...] There is a smart contract on-chain which maintains a state root: the Merkle root of the state of the rollup (meaning, the account balances, contract code, etc., that are "inside" the rollup). Anyone can publish a batch, a collection of transactions in a highly compressed form together with the previous state root and the new state root (the Merkle root after processing the transactions). The contract checks that the previous state root in the batch matches its current state root; if it does, it switches the state root to the new state root.”
For data, this means that all transaction data must stay on L1, but in compressed form to reduce gas costs. For processing, this means that computations are moved to L2 as much as possible, while only the results are written on L1.
In other words, a rollup emulates the ledger functionality on top of the original blockchain, which are therefore called Layer 2 and Layer 1, respectively.
But how is transaction validity assured in a rollup?
Just relying on the correctness of the smart contracts that implements the rollup is not enough. The definition of a rollup is that each state transition (i.e.\ transaction validity) is maintained, verified and endorsed by the main chain, which therefore needs an external (software independent) validation or verification mechanism, independent of the L2 implementation.
In an optimistic rollup, an entity (often called the Sequencer) publishes \( oldStateRoot_2, txBatch, newStateRoot \)(which relate to Layer 2) on \( layer_1 \). During a specified period of time (often seven days), this state^ change can be challenged by an outsider. If no such challenge occurs, the proposed state becomes permanent (hence "optimistic"). However, if a state change is challenged, the following process is triggered.
An arbitration contract on L1, assumed to exist, will decide whether the Sequencer or the Challenger is correct. This arbitration contract is activated by the Challenger.
The contract then declares who is right and who is wrong. As a result, the loser of the arbitration will have their bond (a significant deposit) slashed as a penalty.
Thus, in an optimistic rollup, parties have an economic (game-theoretic) incentive to behave honestly.
For a more detailed description about optimistic rollups, see:
ethereum.org/en/developers/docs/scaling/optimistic-rollups/#what-is-an-optimistic-rollup
In a zkRollup, a different approach is taken. For every state transition \( oldStateRoot, txBatch \Longrightarrow newStateRoot \) a proof of knowledge is generated, which shows that \(\text{newStateRoot}_{2}\) is the correct result of executing the batch. Though sometimes known as zero-knowledge proofs, this terminology is misleading, strictly speaking. Privacy isn't an issue in a rollup, since the transactions are supposed to be public anyway. What is an issue, though, is the succinctness of such a proof, since on-chain verification is expensive and therefore should be done efficiently (often a SNARK).
To be more precise: Let \( STF \) denote the state transition function for the Layer 2 ledger. If the Sequencer is honest, we must have that $$ newState = STF(oldState, txBatch) $$
Remember that on a blockchain, transaction contents can take several forms:
So how can L1 (and with it, everybody who's monitoring this main chain) be convinced that L2 indeed computed $newState_2$ correctly from $oldState_2$ and $txBatch$? By applying verifiable computing on STF This means that the execution trace of $STF(oldState_2,batch)$ is sent to a Validity Proof Generator, which produces a succinct non-interactive validity proof that Equation (1) holds.
Subsequently, the rollup contract on L1 has a method which, on input $oldState_2, batch, newState_2, validityProof$, verifies the validity proof and returns an ACCEPT/REJECT verdict. In case of an ACCEPT, $oldState_2, batch, newState_2$ are recorded as valid on L1, while in case of REJECT the batch and state change are simply discarded.
The raison d'être of blockchain is asset transfer, and extreme care is taken to preserve asset invariance during transactions: nothing is lost, nothing is gained. It’s important to note that the underlying security mechanism of asset invariance is subtly different for L1 and L2.
Layer 1
The correctness of asset transfer on L1 is guaranteed by the consensus mechanism adopted for L1 and is publicly verifiable because it is open-source software.
Layer 2.
L1 only guarantees the availability of the rollup data of L2, not its correctness. The correctness of asset transfer on L2 depends on the correct implementation of L2. The zkVM merely verifies that the rollup data published on L1 is consistent with the ledger program on L2, but if there is a mistake in this program, the zkVM will not catch it.
However, since the L2 source is often copied from L1, this risk is minimized.
The decentralized Sequencer ensures that submitted transactions are batched (avoiding censorship) but does not ensure asset invariance.
Given an L1 with an L2 rollup, we can imagine asset transfers between them in two directions. We’ll use Ether as an example:
These cross-layer asset transfers can be interpreted as a vertical bridge, also called a native bridge.
To assure asset invariance, these transactions adhere to one of the following principles, depending on the context:
To accomplish this, we define:
These last two accounts serve to lock and unlock transactions. The smart contracts that manage these accounts are called shadow contracts.
To avoid discussion about lock/unlock versus burn/mint, we assume that, on initialization, a large fixed quantity of ETH₂ is minted for (credited to) RollupAcc₂. These assets remain locked in this account unless unlocked by an equivalent lock transaction on L1 (Polygon does this too). Note that asset invariance should hold: RollupAcc₁ + RollupAcc₂ = InitialQuantity, always.
When transferring assets from L1 to L2, there are two options: using atomicity or the first-destroy-then-create principle.
The rollup smart contract on L1 performs the transaction on both L1 and the rollup, leaving L2 to clean up. Many rollups implement this as an emergency mechanism to avoid censorship.
This approach has some advantages: atomicity is guaranteed by L1, and transaction settlement time is short. However, it complicates sequencing and increases gas costs.
The smart contract on L1 produces a proof of the transaction and sends it to the Sequencer to trigger the transaction on L2. The smart contract on L2 trusts L1, so the proof-of-transaction is not a ZK Proof, just a simple txId.
In step 3, there are several options: SEQ monitors L1, SEQ is alerted by the smart contract on L1, or SEQ is notified by Client X, etc.
The smart contract on L2 produces a proof of the transaction and sends it to the smart contract on L1 as a trigger for the transaction on L1. Since L1 does not trust L2, this proof-of-transaction must be a ZK Proof, which functions like a certified check. Asset invariance is guaranteed through the first-destroy-then-create paradigm.
Measures should be taken to ensure that a check can only be cashed once; maintaining a list of previously cashed checks is a good solution, combined with expiration dates to prevent the list from growing indefinitely.
Note that in this case, triggering the smart contract on L1 to perform the transaction on the rollup and letting L2 clean up the mess is not an option, as the rollup data is compressed and incomprehensible to the smart contract on L1.
Observe that two steps require waiting for the transaction to settle.
This article was written by Jeroen van de Graaf, Senior Cryptographer at ZKM. Part Two of the series will examine the mechanism of the Entangled Rollup in more detail.