Layer Zero
603 days ago
Cross-Chain Automation for Multichain Apps
With the proliferation of the multichain landscape, developers are facing the issue of having multiple applications with their own states living on separate blockchains.
To overcome this, cross-chain messaging protocols like LayerZero enable users to send transactions from one chain to another while retaining a high level of data integrity and security.
However, having multiple dApps living on siloed blockchains, each with its own individual state, makes it very difficult to manage automated processes across different smart contracts.
Projects would typically have to build, run and maintain the custom infrastructure that handles the transaction automation on each of these chains in parallel.
This is where Gelato comes in. As web3’s decentralized backend, Gelato enables projects to automate the execution of smart contract functions across all major blockchains.
Prerequisites
If you're not familiar with Gelato and smart contract automation, please refer to our docs.
For more information on LayerZero and omnichain interoperability, please refer to their docs.
What is cross-chain automation?
Cross-chain automation powered by Gelato allows developers to automate the execution of arbitrary functions that periodically conduct cross-chain messaging calls via protocols like LayerZero to another chain.
A good use case for cross-chain automation is periodically syncing the state between multiple siloed dApps on multiple chains in order to consolidate the accounting of balances for the entire application.
How Does it Work?
Example for cross-chain ice cream licking Users can try to create an Automate task on Avalanche to lick ice cream on Fantom.
Steps
-
Enter 0xC8aE2A55bC4Bf3280a38C76077A43D4D4a086272 as a contract address
-
Select initateCCLick as a function to be automated
-
Enter 0x126E75609cb5B20D07e9250E38e5fC14dFb7851b as _dstLicker
-
Enter the user’s iceCreamNFT token id on fantom as _tokenId or just use 1 as _tokenId
-
Select the interval and pay with your Gelato Balance
When the task is executed, users can check the events on GelatoLickerDst to see that their ice cream was licked.
GelatoLickerSrc - https://snowtrace.io/address/0xC8aE2A55bC4Bf3280a38C76077A43D4D4a086272#code
GelatoLickerDst - https://ftmscan.com/address/0x126E75609cb5B20D07e9250E38e5fC14dFb7851b#code
GelatoLickerSrc
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
interface ILayerZeroEndpoint {
// @notice send a LayerZero message to the specified address at a LayerZero endpoint.
// @param _dstChainId - the destination chain identifier
// @param _destination - the address on destination chain (in bytes). address length/format may vary by chains
// @param _payload - a custom bytes payload to send to the destination contract
// @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address
// @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction
// @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination
function send(
uint16 _dstChainId,
bytes calldata _destination,
bytes calldata _payload,
address payable _refundAddress,
address _zroPaymentAddress,
bytes calldata _adapterParams
) external payable;
}
contract GelatoLickerSrc {
uint16 public constant dstChainId = 112; // fantom lz chainId
ILayerZeroEndpoint public constant lzEndpoint =
ILayerZeroEndpoint(0x3c2269811836af69497E5F486A85D7316753cf62); // avalanche lz endpoint address
mapping(uint256 => uint256) public lastLicked;
receive() external payable {}
//@dev called by Gelato whenever `checker` returns true
function initiateCCLick(address _dstLicker, uint256 _tokenId)
external
payable
{
bytes memory lickPayload = abi.encode(_tokenId);
lastLicked[_tokenId] = block.timestamp;
lzEndpoint.send{value: address(this).balance}(
dstChainId,
abi.encodePacked(_dstLicker, address(this)),
lickPayload,
payable(this),
address(0),
bytes("")
);
}
//@dev called by Gelato check if it is time to call `initiateCCLick`
function checker(address _dstLicker, uint256 _tokenId)
external
view
returns (bool canExec, bytes memory execPayload)
{
if (block.timestamp < lastLicked[_tokenId] + 600) {
canExec = false;
execPayload = bytes(
"CrossChainGelatoLicker: Not time to cross chain lick"
);
return (canExec, execPayload);
}
canExec = true;
execPayload = abi.encodeWithSelector(
this.initiateCCLick.selector,
_dstLicker,
_tokenId
);
return (canExec, execPayload);
}
}
GelatoLickerDst
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
interface ILayerZeroReceiver {
// @notice LayerZero endpoint will invoke this function to deliver the message on the destination
// @param _srcChainId - the source endpoint identifier
// @param _srcAddress - the source sending contract address from the source chain
// @param _nonce - the ordered message nonce
// @param _payload - the signed payload is the UA bytes has encoded to be sent
function lzReceive(
uint16 _srcChainId,
bytes calldata _srcAddress,
uint64 _nonce,
bytes calldata _payload
) external;
}
interface IIceCreamNFT {
function lick(uint256 _tokenId) external;
}
contract GelatoLickerDst is ILayerZeroReceiver {
address public constant lzEndpoint =
address(0xb6319cC6c8c27A8F5dAF0dD3DF91EA35C4720dd7); // fantom lz endpoint
IIceCreamNFT public constant iceCreamNFT =
IIceCreamNFT(0x255F82563b5973264e89526345EcEa766DB3baB2); // fantom IceCreamNFT address
address public constant srcLicker =
address(0xC8aE2A55bC4Bf3280a38C76077A43D4D4a086272); // avalanche gelato licker address
event CCLicked(
uint16 srcChainId,
address srcAddress,
uint256 indexed tokenId,
uint256 timestamp
);
function lzReceive(
uint16 _srcChainId,
bytes memory _srcAddress,
uint64,
bytes memory lickPayload
) external override {
require(
msg.sender == address(lzEndpoint),
"CrossChainGelatoLicker: Only endpoint"
);
address srcAddress;
assembly {
srcAddress := mload(add(_srcAddress, 20))
}
require(
srcAddress == srcLicker,
"CrossChainGelatoLicker: Only srcLicker"
);
uint256 tokenId = abi.decode(lickPayload, (uint256));
iceCreamNFT.lick(tokenId);
emit CCLicked(_srcChainId, srcAddress, tokenId, block.timestamp);
}
}
Omnichain Staking Reward Payouts
Abracadabra is already using LayerZero to optimize the functionality of their protocol.
The team has implemented Gelato and LayerZero to automate and synchronize the payouts of staking rewards across multiple EVM chains.
Abracadabra allows users to stake governance tokens across multiple chains. This is great for the user, but can ultimately cause issues with fractured governance and protocol updates. With Gelato and LayerZero, this problem is quickly alleviated via the implementation of omnichain governance and staking capabilities.
For example, there will be 100 MIM in rewards paid out every day to all SPELL stakers across all chains. However, those MIM rewards are minted on Ethereum and the right amount of MIM has to be automatically transferred to each supported chain based on the total SPELL staked on each of them.
Tutorial
Abracadabra set up two automation tasks with Gelato and has used LayerZero as their cross-chain messaging protocol of choice.
Task #1: The first task is conducting daily snapshots of staked $SPELL on multiple EVM chains (ex. Polygon, Arbitrum) and sending this information to Ethereum for aggregation. Ethereum now knows how much $SPELL was staked on each chain and how much $MIM rewards each chain should receive. More information can be found in the respective Gelato task & smart contract.
Task #2: The second task then distributes $MIM rewards from Ethereum (hub chain) to all the spoke chains based on the snapshot taken earlier. More information can be found within the respective Gelato task & smart contract.
When Should You Use it?
Smart contract developers looking to solve cross-chain communication can use Gelato and LayerZero in the following way:
-
Create a task on Gelato Automate that should trigger a periodic cross-chain messaging call and choose when it should execute e.g daily or via a dynamic parameter
-
Send a message on chain A via the information that you want to pass to chain B
-
Create a second task with Gelato which performs the desired action on chain B with the information from chain A
Gelato & LayerZero: Security Profile
Gelato Automate is made significantly more secure than existing solutions by LayerZero’s omnichain generic messaging technology.
Most crosschain solutions today wrap assets, pass information through centralized entities, or rely on permissioned validator sets that can be compromised. In the recent year, we’ve seen nearly a billion dollars of losses accrue to bridges based on these technologies.
LayerZero simply passes messages between endpoints on multiple chains and never relies on wrapped assets or centralized validator sets. LayerZero does this using a unique ultralight node model which uses independent Relayers and Oracles to pass and validate messages between chains.
Moreover, LayerZero allows applications to select their own Relayers, Oracles, and security parameters to optimize security requirements to their needs.
The combination of secure messaging and user application configurable security profiles makes Gelato Automate the ideal solution for secure and reliable on-chain automation.
About Gelato
Gelato is a Web3 Cloud Platform empowering developers to create automated, gasless, and off-chain-aware Layer 2 chains and smart contracts. Over 400 web3 projects rely on Gelato for years to facilitate millions of transactions in DeFi, NFTs, and gaming.
-
Gelato RaaS: Deploy your own tailor-made ZK or OP L2 chains in a single click with native Account Abstraction and all Gelato middleware baked in.
-
Web3 Functions: Connect your smart contracts to off-chain data & computation by running decentralized cloud functions.
-
Automate: Automate your smart contracts by executing transactions automatically in a reliable, developer-friendly & decentralized manner.
-
Relay: Give your users access to reliable, robust, and scalable gasless transactions via a simple-to-use API.
-
Account Abstraction SDK: Gelato has partnered with Safe, to build a fully-fledged Account Abstraction SDK, combining Gelato's industry's best gasless transaction capabilities, with the industry's most secure smart contract wallet.
Subscribe to our newsletter and turn on your Twitter notifications to get the most recent updates about the Gelato ecosystem! If you are interested in being part of the Gelato team and building the future of the Internet browse the open positions and apply here.