Multi-chain EVM Bridge
Inspiration
ZKLiquid is an omni-liquidity protocol and inter-chain network that provides a means for crypto assets and blockchain data to be seamlessly and securely transferred across siloed blockchains.
One of the significant problems the crypto space and multi-chain dApps have faced over the past years is with interoperability and the security concerns associated with existing solutions. In 2022 alone, over $2 billion worth of crypto assets were hacked due to exploits on multi-chain bridges that relied on centralized infrastructure services, servers, or nodes for cross-chain data validation and transfer. These centralized solutions are single points of failure where exploiters target to tamper with data being sent across chains.
ZKLiquid provides a secure alternative by leveraging Chainlink's cross-chain interoperability protocol (CCIP). With CCIP, data transfer and sharing between siloed blockchains are tamper-proof. As a decentralized interoperability protocol, CCIP relies on multiple nodes to validate data and transfer, thereby eliminating the single point of failure problem. This makes building interoperable dApps and omni-chain applications more secure and reliable.
What it does
ZKLiquid provides users with the following features and products:
A decentralize and secure multi-chain bridge for stablecoins, and other major crypto assets. Giving users a secure means to move asset from one blockchain to another even the non-EVM compatible ones.
A permissionless multi-chain dApp deployment factory that facilitate the deployment of multichain dApp with simple steps and clicks. These eliminates the complexity that comes with developing cross-chain support for dApps.
Universal liquidity protocol where liquidities on siloed blockchains are connected, this makes it possible for dApps to function as omni-dApps, for example, using assets on one blockchain as collateral on another blockchain without having to bridge or transfer the assets.
How we built it
The current development focussed of developing a multi-chain bridge on EVM compatible blockchains for stablecoins, and major crypto assets. It also allows the integration of new crypto assets support in simple steps. For instance if a project's tokens are on Avalanche and Polygon, the project can leverage ZKLiquid-CCIP implementation and easily connect and bridge the assets on both chains with each other within minutes.
The following gives an overview on how it was developed:
ZKLiquid developed a bidirectional liquidity pool that implements a lock and release (unlock) mechanism to facilitate interchain token transfer. With this, when tokens are transfered from one blokchchain (source) to another (destination), the actual token transfered is locked in the pool contract on the source blockchain and an equivalent token (e.g wrap token of the source token) is released (unlocked) and sent to the recipient from the pool contract on the destination chain. A good example, is if USDT is sent from Avalanche to Polygon, the USDT on Avalanche is locked on the pool contract on Avalanche and USDT on Polygon is released from the pool contract on Polygon to the recipient. The implemented ZKLiquid liquidity pool is bidirectional as earlier mentioned which means it can function as both senders and receivers without any additional modification needed.

To develop this, the following Chainlink technologies were used:
Chainlink's Cross-Chain Interoperability Protocol (CCIP)
CCIP was implemented to send the token transfer data from source blockchain to destination blockchain, the data sent are the equivalent token address to be released on destination chain, the amount to be released and the recipient address.
To send a token, the following steps take place:
When a user interacts with the send token function (sendTokenPayLINK), they select the destination chain. Within the app, the destination chain also specifies the pool address on the destination chain (users do not need to enter this address).
Token Transfer Function

The user then selects the token to be sent, enters the amount to be sent, and specifies the recipient. When the user confirms the transaction, the amount of the selected token is paid (withdrawn from the user) into the pool smart contract on the source chain.
If the deposit of the amount to be sent is successful, the CCIP message sends the token transfer data (equivalent token address on the destination chain, amount, and recipient address). If the withdrawal fails, the smart contract reverts and the data is not sent.
Source to Destination Token Mapping

The above code snippet is a mapping of every source token supported to its equivalent destination token. This works as each chain supported has an equivalent token mapping. The mapping is such that the source token points to a specific destination token on each respective destination chains as shown below:
Mapping Flow
When the sent message is received in the pool smart contract on the source chain, the pending release states are then updated by the received CCIP message.
CCIP Message States Update

The received CCIP message with the token transfer data updates the following states: the pendingTransfer, a mapping of recipient address to amount to be released; the pendingTransferToken, a mapping of recipient address to the address of the token to be released; and the transferAddresses, an array that holds all recipients' address with pending release.
After the update, Chainlink automation then triggers the sending/release of the tokens to the recipient. The recipient can also claim the token for lanes that are not supported by Chainlink automation.
Chainlink Automation
After the CCIP token data updates the states, the tokens are ready to be released and sent to the recipients' wallets. To provide a seamless user experience, I implemented Chainlink Automation for chains supported by Chainlink Automation. This automates the transfer, so recipients do not need to manually claim the tokens received.
Upkeep Check and Perform

The logic of Chainlink Automation is shown in the code snippet above. This is a conditional implementation. The checkUpkeep function checks if the condition to trigger an upkeep is met. Since upkeep is needed when there is token transfer data, the condition checks the pending transfer addresses (transferAddresses), which hold all the addresses with pending transfers. When there is at least one address, the condition becomes true, and the performUpkeep function is triggered, thereby calling the transferTokensAuto function. This function runs the send logic for every address in the transferAddresses array and then clears it.
Challenges we ran into
While implementing CCIP, the main challenges I faced were, firstly, figuring out how to send the correct token transfer data, which includes the token amount, the token address, and the recipient. The sample code for sending arbitrary data implemented sending a string, but I needed to send a struct containing these information. Secondly, the token address sent is actually the address of the token on the destination chain that is equivalent (same) to the token being sent on the source chain. To achieve this, I needed to figure out a proper source token to destination token mapping implementation. In addition, I wanted the implemention to be scalable in such a way that addition chains and tokens support can be easily added after deployment, so the mapping needed to map each token on a chain to all its equivalents on other chains where transfers can be made.
These challenges took me some time to figure out, but with the resources Chainlink provided and the support from the team, I was able to solve them.
Accomplishments that we're proud of
I am proud to have built a professionally looking, user-friendly, fully functional decentralized multichain bridge dApp (testnet) using Chainlink's CCIP and Automation. The developed dApp currently supports 5 chains, and support for additional chains can be added in simple steps. It is also easy to add additional token support. By leveraging Chainlink and following security considerations, I am most proud that the dApp I developed provides a proof of concept for a secure, decentralized, multichain, multi-asset bridge.
What we learned
While working on my project, I gained extensive knowledge about how Chainlink CCIP and Automation work. I learned how powerful the protocol is and how it can be leveraged to build secure multichain/interoperable applications. This understanding has helped me map out all the potential ways the protocol can be used to continue developing ZKLiquid beyond the hackathon.
What's next for ZKLiquid
I will continue to develop ZKLiquid with the near-term goal of launching the mainnet beta version of the bridge on Avalanche, Polygon, zkEVM, Arbitrum, Ethereum, Base, and BSC Chain. This launch will also include the rollout of the liquidity protocol on those chains. The protocol will enable users to add liquidity to the bridge and earn interest on their assets. The launch will initially focus on bridging stablecoins, with other major assets to follow. I also welcome individuals who would like to join in building ZKLiquid.
Additional information and details
Tokens support
To facilitate testing the dApp, we deployed test tokens on the chains supported. Here are the details of the tokens
USDT
Avalanche Fuji
0x361Dfe9E413A684f1677742Da2BA9311ec35D70D
Sepolia
0xC6DA1DFB5d9672B180523cDe045E6EDaeDcCA823
Polygon Amoy
0xF6CFcF77838cF17cd6863a633CC5a218549cD36d
Arbitrum Sepolia
0xA17389EAAA6Eb19b6f288cD0a555137E13a947a1
BSC Testnet
0xec1804F0DE8fbB3689D4b13BfB8035B77283a6D1
USDC
Avalanche Fuji
0xE94A73848224907453e872D20078E0C4621BbA92
Sepolia
0x0341Fb8609f1bA3bDeE99125291615BEAa3FAE15
Polygon Amoy
0x46b74833C07800953250Ab8dc192ce830AA3fc64
Arbitrum Sepolia
0xec1804F0DE8fbB3689D4b13BfB8035B77283a6D1
BSC Testnet
0xA17389EAAA6Eb19b6f288cD0a555137E13a947a1
Pools with CCIP and Automation implementation
The following are the smart contracts of ZKLiquid liquidity pools with CCIP implementation and Automation for token transfer across multiple chains
Avalanche Fuji
0x96120cBa6C7D933e06C290cC0BBE41ce17194c1F
Sepolia
0x2B5474bCCCae8C9cce8D70Ed0e24B8D3797b2BAD
Polygon Amoy
0x7Ae98Fa33148917aa67fED319764d0dB880f23F6
Arbitrum Sepolia
0x08FED545c34848c4d2CdAB952097D86eb4426708
BSC Testnet
0x08FED545c34848c4d2CdAB952097D86eb4426708
Faucet
Link to the faucet were users can claim test tokens:
Automation Upkeep Links
Here are the links to all the automation Upkeep
Last updated