LayerZero Cross-Chain Smart Contracts (v1)

A step-by-step guide on how to build & deploy a LayerZero cross-chain user application.

The video below shows how to deploy a smart contract using LayerZero.

❗️

Warning:

This tutorial is describing on how to build and deloy on LayerZero v1 and not v2. Please stay tune for further updates.

Six Steps to Deploy a Smart Contract using LayerZero

Check the detailed steps below for an in-depth guide:

Step 1. Prerequisites

  • Open your preferred toolset for smart contract development. For this tutorial, we're using the Remix IDE.
  • Open the LayerZero Scan to monitor cross-chain transactions.
  • Connect MetaMask to Optimism and Polygon networks.

🚧

Important Note

Make sure you have enough ETH in your Optimism account to cover the transaction fees for smart contract deployment and setup.

Step 2. Modifying the Smart Contract

  1. Load the 1_Storage.sol contract in the Remix IDE.
  2. Replace the current code with the source code below:
// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.8.2 <0.9.0;

import "https://github.com/LayerZero-Labs/solidity-examples/blob/main/contracts/lzApp/LzApp.sol";

/**
 * @title Storage
 * @dev Store & retrieve value in a variable
 * @custom:dev-run-script ./scripts/deploy_with_ethers.ts
 */
contract Storage is LzApp {

    constructor(address _lzAppEndpoint) LzApp(_lzAppEndpoint) Ownable(msg.sender) {}

    uint256 number;

    /**
     * @dev Store value in variable
     * @param num value to store
     */
    function store(uint256 num, uint16 dstChainId) public payable {
        bytes memory payload = abi.encodePacked(num);
        _lzSend(dstChainId, payload, payable(msg.sender), address(0x0), bytes(""), msg.value);
        number = num;
    }

    function _blockingLzReceive(uint16 _srcChainId, bytes memory _srcAddress, uint64 _nonce, bytes memory _payload) internal override {
        uint256 num = abi.decode(_payload, (uint256));
        number = num;
    }

    /**
     * @dev Return value 
     * @return value of 'number'
     */
    function retrieve() public view returns (uint256){
        return number;
    }
}

Here's a breakdown of the modification steps:

  • Import the LZApp.sol file from LayerZero.
  • Add is LzApp notation and constructor to ensure interaction with LayerZero.
  • Update the store function to include a destination chain ID (dstChainId) to handle the cross-chain transfer fees.
  • Call the lzSend function to send the payload to the destination chain.
  • Overwrite the blockingLzReceive function. This function is triggered when another chain receives a number, allowing the contract to update storage variables accordingly.

📘

Info

Depending on your use case, you can choose an LZ app or another abstract smart contract. For more information, see the LayerZero documentation.

Step 3. Compiling the Smart Contract

  1. Go to the Solidity Compiler in the Remix IDE.
  2. Set the EVM version to Paris for Optimism compatibility.
  3. Click Compile.

Step 4. Deploying the Smart Contract

🚧

Ensure Metamask is set up for both Optimism and Polygon networks.

The steps below are using the Optimism network.

  1. Go to the Deploy tab.
  2. Select Injected Provider for deployment.
  3. Ensure MetaMask is set to Optimism.
  4. In the Deploy field, enter the LayerZero endpoint for Optimism.
  5. Click Deploy to initiate the deployment.
  6. For Polygon, repeat steps 1-5 with MetaMask set to Polygon and enter the LayerZero endpoint for Polygon.

Step 5. Setting Trusted Remotes

The steps below are for setting up communication from Optimism to Polygon.

  1. Use setTrustedRemoteAddress function to set up trusted remotes.
  2. Ensure that MetaMask is connected to Optimism.
  3. Copy the Polygon Chain ID and paste it into the field shown on the screen.
  4. Set the address of the smart contract deployed to Polygon.
  5. Click Transact.
  6. Next, repeat this process with the smart contract deployed on Polygon.
    1. Switch to the Polygon network on MetaMask.
    2. Close the Optimism smart contract.
    3. Open the Polygon smart contract to configure the trusted remote.

📘

Info:

Utility scripts are available for more complex applications. See the LayerZero documentation.

Step 6. Executing Cross-Chain Transactions

The steps below are for initiating a cross-chain transaction for the Optimism network.

  1. Switch to Optimism in MetaMask.
  2. Select the deployed contract on Optimism in Remix.
  3. Enter the number to store and set the destination chain ID to Polygon.
  4. Ensure you have sufficient ETH to cover the transaction fees > Set the Gwei value.
  5. Click Transact.
  6. Copy the Transaction Hash and check the status on the LayerZero Scanner.
  7. Once confirmed, switch the MetaMask to Polygon. Interact with the deployed contract on Polygon to verify the stored number from Optimism.
  8. Call the retrieve function to check if the stored number from Optimism is successfully reflected.
function retrieve() public view returns (uint256){
    return number;
}

👋 Need Help?

Contact us through email or our support page for any issues, bugs, or assistance you may need.