Today you will see a bridge between two Ethereum-like chains, with a mechanism for general state synchronization. Presently, bridges have been built due to a need for scaling Ethereum and avoiding big gas fees.
Most bridges have required a trusted authority and separate development effort for each use case (for example, each ERC standard for tokens). Our bridge can handle general states and you will see an example of syncing state mutated on one chain to a second chain.
We are in the Factotum IDE and I have set up an environment with two EVM-based test chains. We will be using the same account address on each chain. This is important because we are effectively replaying the transaction sent from Chain A, on Chain B. We have deployed two Counter contracts, one on each chain.
They have the same address. Then, we have a Light Client contract on chain B, which keeps track of chain A blocks and stores block hashes. And a Prover contract on chain B, to which we will send the transaction data that needs to be replayed on chain B. Now, the counter on chain A is 14 and on-chain B, 14 and they are in sync.
We will make a transaction to increase the counter with 2, on chain A. So, now, when we query the chains, we have 16 on chain A and 14 on chain B.
Not in sync anymore. During this time, the Light client watcher has picked up the new block from chain A, in which the increment counter transactions has been added and has sent it to the Light Client.
So, we can proceed and build our proofs for the Prover contract. The forward and verify function takes in a transaction, receipt and sender account proof for the transaction that we want to be replayed, along with the block header where the transaction has been included. Block header, with a number from the transaction receipt received.
The header contains the receipt tree root, which, along with this receipt proof, allows the Prover contract to verify that the status of the original transaction is the same as the status for the replayed transaction.
It also contains the transaction root, which, along with the transaction proof enables the Prover to verify that the replayed transaction (included already in the proof) is part of the transaction tree sealed by the block.
The Prover contract also checks that the RLP-serialized block header is hashed to a valid block hash, that has been registered with the Light Client.
Last, we send the account proof to make sure we know a valid account nonce, which is used as a monotonically increasing value for tracking the state changes in order thus disallowing the reuse of the same transaction for replay.
The Prover contract keeps a mapping of nonces per transaction sender account and (at least in the current version) does not allow nonces to be skipped.
Now, we can send the forward and verify the transaction. And check the counter values again. Chain A remains the same. Chain B, the counter has been synced with Chain A. You have seen a short demo of bridging two Ethereum chains and keeping state in sync by proving blocks, transactions, receipts and account information.
All, inside Factotum IDE.
Read More: VeChain Breaking Solution