In-Detail: Multi-Chain State Synchronization

Overview

zkLink Nova is powered by zkLink Nexus technology for multi-chain settlement. In zkLink's Nexus, users can deposit and withdraw assets on all connected networks (L1 and L2s). Users' assets are locked in smart contracts on the connected networks and enter the Nova network via the canonical rollup bridge. Nexus boasts Ethereum-grade security, achieved through multi-chain state synchronization by transmitting the sync hashes of on-chain transactions via the canonical roll-up message service.

The connected networks (L1 and L2s) of Nova can be classified into two types serving different roles:

  • Primary Chain: ZK-proofs and data commitments for transaction batches on Nova (L3) are submitted to the primary chain (Linea, L2). The primary chain is responsible for ZKP verification and checking on-chain data consistency by sync hashes.

  • Secondary Chain: Secondary chains send sync hashes to the primary chain via the canonical roll-up message service. Upon successful verification on the primary chain, the confirmed batch root is relayed back to secondary chains, and withdrawal requests on secondary chains can be executed.

Among the secondary chains, Ethereum (L1) holds a special position. Message transmission between the primary chain and other L2 secondary chains occurs via Ethereum, where the arbitrator contract facilitates the forwarding of cross-chain messages."

On-Chain Transaction Synchronization

A user could deposit token assets by initiating an on-chain transaction. Additionally, users can submit other types of on-chain transactions via the connected networks, which the sequencer is force to process.

As shown in the figure above, if a user sends a transaction (e.g., depositing ETH) to the zkLink contract on a secondary chain (step 1), the transaction will be forwarded in real-time by the Nova sequencer to the zkLink contract on the primary chain (step 2). A user can also send a transaction directly to the zkLink contract on the primary chain (step 3). The sequencer monitors the transactions received in the zkLink contract on the primary chain and forwards these transactions (in step 4) to the Nova network (L3) for execution.

Please note that only the sequencer is authorized to relay transactions from the secondary chains to the primary chain. To achieve low-latency synchronization, this process does not rely on a canonical rollup bridge. However, we have a mechanism in place to prevent the sequencer from sending fake information, which will be discussed in a later part of this article."

Step 2:

https://github.com/zkLinkProtocol/era-contracts/blob/zklink_testnet/l1-contracts/contracts/zksync/facets/Mailbox.sol

function forwardRequestL2Transaction( ForwardL2Request calldata _request )

Multi-Chain State Synchronization

The main challenge of building a rollup network deployed across various networks is the risk of deposit fraud. For example, a bad sequencer may falsely inform the primary chain about a fake deposit on one secondary chain that does not exist. In such scenarios, without effective verification mechanisms, it could lead to the loss of user funds.

To prevent this risk, in the state synchronization phase, we add another layer of transaction consistency verification in addition to ZKP verification in a typical ZK-Rollup. This additional layer ensures that the data relayed to the primary chain in real-time is consistent with the sync hashes periodically transmitted via the canonical rollup message service.

For each transaction on a secondary chain, the zkLink contract will calculate the sync hash of this transaction based on the previous sync hash.

syncHashn=hash(tx,syncHashnāˆ’1)syncHash_{n} = hash(tx, syncHash_{n-1})

A relayer will periodically trigger secondary chains to send the latest sync hash to the arbitrator contract on Ethereum via the canonical message service (in steps 1, 2, 3), and the arbitrator contract will forward all sync hashes of secondary chains to the zkLink Contract via the canonical message service (in steps 4, 5, 6).

Step 1: Trigger the zkLink contract on secondary chains to send the latest sync hash to the L2 Gateway.

https://github.com/zkLinkProtocol/zklink-evm-contracts/blob/main/contracts/ZkLink.sol

function syncL2Requests(uint256 _newTotalSyncedPriorityTxs)

Step 2: Transmitting message (sync hash) via canonical rollup bridge.

Step 3: Receive message (sync hash) from canonical message service and forward it to the arbitrator contract. For example:

https://github.com/zkLinkProtocol/zklink-evm-contracts/blob/main/contracts/gateway/zksync/ZkSyncL1Gateway.sol

function finalizeMessage( uint256 _l2BatchNumber, uint256 _l2MessageIndex, uint16 _l2TxNumberInBatch, bytes memory _message, bytes32[] calldata _merkleProof )

Step 4: Forward message (sync hash) from the arbitrator contract to the L1 gateway of primary chain.

https://github.com/zkLinkProtocol/zklink-evm-contracts/blob/main/contracts/Arbitrator.sol

function forwardMessage( IL1Gateway _gateway, uint256 _value, bytes memory _callData, bytes memory _adapterParams )

Step 5: Transmitting message (sync hash) via canonical rollup bridge.

Step 6.1: Receive message (sync hash) from canonical message service of the primary chain and forward it to the zkLink contract on the primary chain.

https://github.com/zkLinkProtocol/zklink-evm-contracts/blob/main/contracts/gateway/linea/LineaL2Gateway.sol

function claimMessageCallback( uint256 _value, bytes calldata _callData )

Step 6.2: Once the primary chain receives the sync hash from secondary chains, zkLink contract will verify if it's consistent with the transactions that were previously relayed by the sequencer to the primary chain.

https://github.com/zkLinkProtocol/era-contracts/blob/zklink_testnet/l1-contracts/contracts/zksync/facets/Mailbox.sol

function syncL2Requests( address _secondaryChainGateway, uint256 _newTotalSyncedPriorityTxs, bytes32 _syncHash, uint256 _forwardEthAmount )

Step 7: After the zkLink contract on the primary chain executes ZKP verification for a transaction batch, it checks if all the on-chain transactions in that batch have already been verified based on sync hashes.

https://github.com/zkLinkProtocol/era-contracts/blob/zklink_testnet/l1-contracts/contracts/zksync/facets/Executor.sol

function _collectOperationsFromPriorityQueue(uint256 _nPriorityOps)

Upon successful verification of ZKP and on-chain transaction consistency, settlement on the primary chain can be approved. At this stage, Nova achieves soft finalization on the primary chain (Linea). Afterward, the batch root will be sent to all secondary chains via the canonical message service (in steps 8-13).

Step 8: Trigger the zkLink contract on the primary chain to send the batch root to the gateway.

https://github.com/zkLinkProtocol/era-contracts/blob/zklink_testnet/l1-contracts/contracts/zksync/facets/Mailbox.sol

function syncBatchRoot(address _secondaryChainGateway, uint256 _batchNumber, uint256 _forwardEthAmount)

Step 9: Transmitting message (batch root) via canonical message bridge. Once the message reaches Ethereum, zkLink Nova achieved hard finalization.

Step 10: Receive message (batch root) from canonical message service and forward it to the arbitrator contract.

https://github.com/zkLinkProtocol/zklink-evm-contracts/blob/main/contracts/Arbitrator.sol

function receiveMessage(uint256 _value, bytes memory _callData)

Step 11: Forward message (batch root) from the arbitrator contract to the L1 gateway of secondary chains.

https://github.com/zkLinkProtocol/zklink-evm-contracts/blob/main/contracts/Arbitrator.sol

function forwardMessage( IL1Gateway _gateway, uint256 _value, bytes memory _callData, bytes memory _adapterParams )

Step 12: Transmitting message (batch root) via canonical rollup bridge.

Step 13: Receive message from canonical message service of the secondary chain and forward it to the zkLink contract. For example:

https://github.com/zkLinkProtocol/zklink-evm-contracts/blob/main/contracts/gateway/zksync/ZkSyncL2Gateway.sol

function claimMessageCallback(uint256 _value, bytes memory _callData)

After receiving the batch root, withdrawal requests can be executed in the zkLink contract on the secondary chains.

For further detailed information, please refer to our verified smart contracts.

Bridged Assets Location

ETH:

zkLink Nova applies zkLink Nexus technology, which allows users to deposit ETH from and withdraw ETH to any connected network powered by fund auto-rebalancing. ETH will be transferred from and to any connected chains along with deposit and withdraw transactions via Layer 2s' canonically rollup bridges.

When users deposits ETH from a secondary Chain onto Nova, it will be temporally locked in the zkLink contract on the source chain. In the state synchronization process discussed above (step 1-5), along with sync hash, the ETH will be transferred to the primary chain, and finally locked in the zkLink contract on primary chain.

When users withdraw from Nova to a secondary chain, after the batch including the withdrawal transaction has been verified through ZKP and the all the on-chain transactions in that batch have already been verified based on sync hashes (step 6-7), the ETH to be withdrawn will be transferred to the secondary chain along with batch root (step 8-13).

ERC-20 Tokens:

As ERC-20 tokens may only exist on a Layer 2 network, which is not bridgeable back to Ethereum via rollup bridge, to make it consistent, an ERC-20 token will be locked in the ERC-20 bridge on the chain where it comes from (see the figure below).

Withdrawal Time Discussion

As discussed above, to prevent deposit fraud problem, all on-chain transactions prior to a withdrawal request have to be verified via sync hash consistency check. As zkLink Nova connects to Optimistic rollups like Optimism and Arbitrum, it takes around 7 days to forward transaction hashes to the primary chain via canonical rollup bridge to finish the verification. After transaction hash verification and ZKP verification, withdrawal request to the primary chain Linea can be executed. Therefore, withdrawal to Linea takes around 7 days.

For withdrawal requests to a secondary chain, the transaction should be transmitted from Linea to the secondary chain via Ethereum, which could take around additional 1 day. Therefore, it takes around 8 days to finish the execution of a withdrawal transaction to a secondary chain.

Last updated