LayerZero V2 + Morph: Seamless Cross-Chain Token Transfers
Layerzero & the need for seamless interoperability
As blockchain ecosystems continue to expand, the need for cross-chain functionality has become increasingly critical. Assets and data often exist in isolation on different blockchains, limiting users and developers who wish to interact with multiple ecosystems simultaneously. Cross-chain functionality addresses this by allowing assets, tokens, and information to move freely between chains, enhancing user experience and opening up, new possibilities for decentralized applications (dApps).
LayerZero is an interoperability protocol that allows developers to build applications (and tokens) that can connect to multiple blockchains. LayerZero defines these types of applications as "omnichain" applications.
The LayerZero protocol is made up of immutable on-chain Endpoints, a configurable Security Stack, and a permissionless set of Executors that transfer messages between chains.
Bridging ERC20 token to Morph using Layerzero v2
In this tutorial, we will walk through deploying and configuring an OFT(Omnichain Fungible Token).
Omnichain Fungible Tokens (OFTs) are a new token standard pioneered by LayerZero for cross-chain assets. OFTs allow fungible tokens to be transferred across different blockchains without the need for asset wrapping or liquidity pools, all whilst maintaining a unified supply.
In this guide, You'll learn how to configure your environment for cross-chain deployments, deploy your OFT contract, set peers and transfer tokens from sepolia to Morph holesky .
Prerequisites
- Pnpm
- A wallet configured with Sepolia and morph holesky.
- Testnet funds:
Setting up your environment
In your terminal, create a new folder and paste in the command below. We will be using the layerzero CLI to provision our dApp.
After running the command above , you should get options on how to configure your dapp. For this guide, we will be using the OFT example.
So for the first question, which is where to start the project, hit “Enter” to select the fault option.
Next, we select OFT as our starting point, then we select pnpm to install our dependencies.
hardhat.config.ts
After opening our project on vscode, our first stop is the hardhat config. This is where we will be configuring the networks for our dApp. In the networks section of the config file, replace the default networks with the ones below.
Your hardhat config file should look like this.
For this tutorial, we will be transferring tokens (which we are going to create) from Sepolia to Morph. Eid refers to the endpoint ID of the network. Each chain on layer zero has an endpoint address(we will use this later) and an endpoint ID. url is the respective URLs of the networks.
.env
The next step is provisioning our environment variables. In the root folder of your project, rename the .env.example file to .env. Next, we add and populate a number of variables.
MyOFT.sol
Now, its time to work on the contract itself. We will be making a slight modification to the existing contract. We will be adding the line below to the constructor function to mint on deployment, 1000000 tokens to the deployer.
Next, we compile the contracts to ensure all works as expected.
Deploying the OFT contract
To deploy our OFT contract, we must first initialise our layerzero.config.ts file. Delete the layerzero.config.ts file from your root folder and run the following command in your terminal
The above command should return two options to you which are the networks we added to the hardhat.config.ts file. Use the spacebar key to select both chains and then hit Enter.
Ensure the my_oft_config.ts file has been created and populated. It should be exactly like the one below.
Finally, to deploy the contract, run and again, select both networks and hit Enter. For the deploy script tag option, hit enter to use the default option(all the scripts).
Running the deploy command should deploy our OFT contract to both networks. You could check out the deployed contracts on Sepolia and Morph holesky explorer.
Configuring cross chain pathways
Next step is configuring each pathway for our contract. You can read up more on configuring pathways here. To modify your layerzero contract, run the command below
For each pathway on your config file, this task will call:
fromContract.OApp.setPeer fromContract.OApp.setEnforcedOptions fromContract.EndpointV2.setSendLibrary fromContract.EndpointV2.setReceiveLibrary fromContract.EndpointV2.setReceiveLibraryTimeout fromContract.EndpointV2.setConfig(OApp, sendLibrary, sendConfig) fromContract.EndpointV2.setConfig(OApp, receiveLibrary, receiveConfig)
Running the command should also populate your my_oft_config.ts file by applying all the custom configurations needed . Your config file should now look like below.
Sending tokens from Sepolia to Morph
After configuring the path, we can finally start working on sending tokens across chains. First we create a folder called tasks in our root directory of our project. Inside the folder, we create a file called sendToken.ts. After creating the file, paste in the code below.
After pasting in the code above, you might get some warnings. Your next step(which also clears those warnings) should be to navigate to hardhat.config.ts and add the import below. This imports the sendToken task to our hardhat config.
Finally, we run the command below to transfer the tokens
Replace the placeholder texts with the contract address of your sepolia and holesky deployments. In my case, this is what it looks like
You should get a successful response like below in your terminal
You can see the successful transaction on layerzero scan
If we check on the morph holesky explorer, we can also see the 1000 tokens we received from sepolia.
Conclusion
We have taken a step by step approach to building a crosschain dapp that sends tokens from one chain (Sepolia) to another (Morph). This approach creates the ERC20 token to be sent.
If you want to send already existing tokens, rather than using OFT, you use OFTAdapter and pass in the contract address of the token. The Adapter is deployed on the source chain and the OFT contract(like we just used) is deployed on the destination chain. If you would like to see a guide on this, drop a comment or reach out on discord.