Skip to content

Getting Started with Gelato

Gelato Banner

Introduction

Gelato Network is a decentralized automation network for Web3, enabling developers to automate & relay arbitrary smart contract executions on and across EVM-based compatible blockchains. The network relies on a broad set of transaction relayers called executors that are rewarded for the infrastructure and automation services they provide. Gelato is designed to be a more robust, decentralized, and cost-efficient alternative to running your own bot infrastructure.

Gelato is live on both Moonbeam and Moonriver, enabling developers and end-users to automate smart contract interactions with Gelato Ops and the Gelato Relay SDK. First, this guide will demonstrate a step-by-step tutorial to automating a smart contract interaction with Gelato Ops. Next, you'll interact with the Gelato Relay SDK via a hands-on demo.

The information presented herein is for informational purposes only and has been provided by third parties. Moonbeam does not endorse any project listed and described on the Moonbeam docs website (https://docs.moonbeam.network/).

Gelato Ops

Gelato Ops is a front-end for interacting with the Gelato network and managing your transaction automation. There's no sign up or registration step - your account is tied directly to your wallet. In this guide, you'll deploy a signature Gelato ice cream NFT that can be licked via a function call. Then, you'll automate the lick function according to specific parameters.

Gelato Ops 1

Create an Automated Task

To get started with this guide, you'll need to have some GLMR or MOVR in your free balance. Then, head to Gelato Ops and ensure that you have selected the Moonbeam or Moonriver network in your wallet and connected it to Gelato. To kick off the tutorial, press Start Tutorial, then press Mint NFT and confirm the transaction in MetaMask.

Then, take the following steps:

  1. Enter the amount of GLMR / MOVR you'd like to use to fund your Gelato Ops account. These funds will be used to pay for gas. Then press Deposit and confirm the transaction in MetaMask
  2. Press Create Task
  3. Copy the contract address of your ice cream NFT
  4. Paste the contract address to allow the ABI to be automatically fetched by Gelato
  5. Next, select the function you'd like to automate. For this example, choose the lick function
  6. The lick function takes a single parameter, namely, the tokenId of the NFT to lick. Enter the tokenId that corresponds to your ice cream NFT
  7. Next, choose how you'd like your automation scheduled. You can choose from a time-based schedule or Gelato can automatically execute the function whenever possible
  8. Select Gelato Balance to use your deposited funds to pay for the gas of the automated transactions
  9. Enter a task name
  10. Press Create Task and confirm the transaction in MetaMask. Then, sign the next pop-up in MetaMask to confirm your task name

Gelato Ops 2

And that's it! You've successfully set up your first recurring smart contract interaction with Gelato. Your automated smart contract interactions will continue according to the set schedule until the remaining funds for gas are drained or the automation is paused on Gelato Ops. This example was a simple demo, but you can automate much more complex interactions and build increasingly sophisticated logic into your automated tasks. Be sure to check out docs.gelato.network for more information.

Manage your Automated Tasks

On app.gelato.network, you'll see all of your automations and their associated statuses. You can click on an automation to see more details about the task and its execution history. Here you can also make any changes to the automated task, including pausing or resuming the task. To pause a task, press Pause in the upper right corner and confirm the transaction in your wallet. You can resume the automation at any time by pressing Restart and confirming the transaction in your wallet.

At the bottom of the page, you can see your task's execution history including the transaction status and the gas cost. You can click on the Task Logs tab to see a detailed debugging level history of your automated tasks, which may be especially helpful in the event a transaction failed or did not execute.

Gelato Ops 3

Manage your Gas Funds

To manage your gas funds on app.gelato.network, click on the Funds box in the upper left corner. Here, you can top up your balance of gas funds or withdraw them. You can also register be notified with low balance alerts.

To deposit funds for gas, take the following steps:

  1. Click on the Funds box in the upper left corner
  2. Enter the amount of funds you'd like to deposit
  3. Click Deposit and confirm the transaction in your wallet

You can follow a similar set of steps to withdraw your gas funds from Gelato.

Gelato Ops 4

Gelato Relay SDK

Gelato Relay SDK is a collection of functions that enable you to interact with the Gelato Relay API. Per Gelato Docs, Gelato Relay API is a service that allows users and developers to get transactions mined fast, reliably and securely, without having to deal with the low-level complexities of blockchains. A key feature of this offering is the ability to provide users with gasless transactions.

Send a Gasless Transaction with Gelato Relay SDK

Gasless transactions, also referred to as meta transactions, allow end-users to interact with smart contracts without paying for gas. Instead of confirming a transaction in a wallet, a user signs a message that enables a transaction to take place once a relayer submits the transaction and pays the associated gas fee. EIP-2771 is a common standard that enables meta transactions, and is implemented by the HelloWorld.sol contract referenced later in the tutorial.

In this demo, you'll ask Gelato Relay SDK to call a HelloWorld.sol contract on your behalf. The script being built is sourced from the quick start guide on Gelato Docs. Note, there is no dependency on RPC providers - once the transaction and signature are built, you simply pass them along to the Gelato Relay API.

Get Started

Gelato Relay SDK is an NPM package that can be installed locally in the current directory with the following command:

npm install @gelatonetwork/gelato-relay-sdk

You'll also want to install the Ethers.js library with the following command:

npm install ethers

Next, you'll need to create a javascript file for your script. You can create a hello-world.js file by running:

touch hello-world.js

Now you're ready to build. First, you need to import the Gelato Relay SDK and Ethers.js:

  import { Wallet, utils } from "ethers";
  import { GelatoRelaySDK } from "@gelatonetwork/gelato-relay-sdk";

Then, create a function to contain the logic of the script:

const forwardRequestExample = async () => {

}

Within the forwardRequestExample function, define the chain ID and the HelloWorld.sol contract that you want to interact with.

  const chainId = 1284;
  // `HelloWorld.sol` contract on Moonbeam
  const target = "0x3456E168d2D7271847808463D6D383D079Bd5Eaa";

The HelloWorld.sol contract, reproduced below, is configured to have gasless transaction support.

// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;

import {ERC2771Context} from "@openzeppelin/contracts/metatx/ERC2771Context.sol";

/// @title HelloWorld with meta transaction support (EIP-2771)
contract HelloWorld is ERC2771Context {
    event Success(
        address indexed user,
        address indexed feeToken,
        string message
    );

    constructor(address _gelatoMetaBox) ERC2771Context(_gelatoMetaBox) {}

    function sayHiVanilla(address _feeToken) external {
        string memory message = "Hello World";

        emit Success(msg.sender, _feeToken, message);
    }

    function sayHi(address _feeToken) external {
        string memory message = "Hello World";

        emit Success(_msgSender(), _feeToken, message);
    }
}

Next, you'll create a new test account that will submit the gasless transaction. This account is insecure and should not be used in production. This example defines a test_token with a default value for demonstration purposes, but you can specify any token here that you'd like.

  const test_token = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";
  // Create mock wallet
  const wallet = Wallet.createRandom();
  const sponsor = await wallet.getAddress();
  console.log(`Mock PK: ${await wallet._signingKey().privateKey}`);
  console.log(`Mock wallet address: ${sponsor}`);

Add Request Data

In this step you have to provide the ABI-encoded call data for the function you want to interact with. You can generate this by taking the following steps:

  1. Navigate to the Write Contract heading of the HelloWorld.sol contract on Moonscan
  2. Press Connect to Web3. After you accept the terms and conditions, you can connect your wallet
  3. Head to the sayHiVanilla function and provide the following default value for the _feeToken parameter: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE
  4. Press Write
  5. Without confirming the transaction in MetaMask, click on the Hex tab
  6. Press Copy Raw Transaction Data

The resulting ABI-encodeded call data should look like 0x4b327067000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeaeeeeeeeeeeeeeeeee

Gelato Relay SDK

The ABI-encoded call data specifies the contract function to call as well as any relevant parameters, and can be fetched via MetaMask or Remix. More commonly, you might fetch the ABI-encoded call data programmatically via Ethers.js or Web3.js. There are some additional parameters defined in the following example, such as paymentType, maxFee, and gas. There are a variety of possible payment types you can choose from. For simplicity, replay protection has not been considered in this example.

  // ABI encode for HelloWorld.sayHiVanilla(address _feeToken)
  const data = `0x4b327067000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeaeeeeeeeeeeeeeeeee`;
  const paymentType = 1;
  // Maximum fee that sponsor is willing to pay worth of test_token
  const maxFee = "1000000000000000000";
  // Gas limit
  const gas = "200000";

  // Smart contract nonces are not enforced to simplify the example.
  // In reality, this decision depends whether or not target
  // address already implements replay protection. (More info in the docs)
  const sponsorNonce = 0;
  const enforceSponsorNonce = false;
  // Only relevant when enforceSponsorNonce = true
  const enforceSponsorNonceOrdering = false;

  // Build ForwardRequest object
  const forwardRequest = GelatoRelaySDK.forwardRequest(
    chainId,
    target,
    data,
    test_token,
    paymentType,
    maxFee,
    gas,
    sponsorNonce,
    enforceSponsorNonce,
    sponsor
  );

Lastly, the forwardRequest object is created with all of the relevant parameters defined in prior steps. In the final step, the forwardRequest object will be sent to the Gelato Relay API with the required signature.

Send Request Data

The last few steps include hashing the request object and signing the resulting hash. The ultimate step is to submit the request and the signature to the Gelato Relay API. You can copy and paste the below code after the forwardRequest object:

  // Get EIP-712 hash (aka digest) of forwardRequest
  const digest = GelatoRelaySDK.getForwardRequestDigestToSign(forwardRequest);

  // Sign digest using mock private key
  const sponsorSignature = utils.BytesLike = utils.joinSignature(
    await wallet._signingKey().signDigest(digest)
  );

  // Send forwardRequest and its sponsorSignature to Gelato Relay API
  await GelatoRelaySDK.sendForwardRequest(forwardRequest, sponsorSignature);

  console.log("ForwardRequest submitted!");

The EIP-712 standard provides important context to users about the action they're authorizing. Instead of signing a long, unrecognizable bytestring (which is dangerous and could be exploited by bad actors), EIP-712 provides a framework for encoding and displaying the contents of the message in a readable manner, making it substantially safer for end-users.

To execute the script and dispatch the gasless transaction to Gelato Relay API, use the following command:

node hello-world.js

You should see a message logged to the console that says ForwardRequest submitted! You can also verify your relayed transaction was successfully executed by checking the latest transactions of this Gelato contract on Moonscan.

Complete Script

The entire hello-world.js file should contain the following:

import { Wallet, utils } from "ethers";
import { GelatoRelaySDK } from "@gelatonetwork/gelato-relay-sdk";

const forwardRequestExample = async () => {

  const chainId = 1284;
  // `HelloWorld.sol` contract on Moonbeam
  const target = "0x3456E168d2D7271847808463D6D383D079Bd5Eaa";
  const test_token = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";

  // Create mock wallet
  const wallet = Wallet.createRandom();
  const sponsor = await wallet.getAddress();
  console.log(`Mock PK: ${await wallet._signingKey().privateKey}`);
  console.log(`Mock wallet address: ${sponsor}`);

  // ABI encode for HelloWorld.sayHiVanilla(address _feeToken)
  const data = `0x4b327067000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeaeeeeeeeeeeeeeeeee`;
  const paymentType = 1;
  // Maximum fee that sponsor is willing to pay worth of test_token
  const maxFee = "1000000000000000000";
  // Gas limit
  const gas = "200000";

  // Smart contract nonces are not enforced to simplify the example.
  // In reality, this decision depends whether or not target 
  // address already implements replay protection. (More info in the docs)
  const sponsorNonce = 0;
  const enforceSponsorNonce = false;
  // Only relevant when enforceSponsorNonce = true
  const enforceSponsorNonceOrdering = false;

  // Build ForwardRequest object
  const forwardRequest = GelatoRelaySDK.forwardRequest(
    chainId,
    target,
    data,
    test_token,
    paymentType,
    maxFee,
    gas,
    sponsorNonce,
    enforceSponsorNonce,
    sponsor
  );

  // Get EIP-712 hash (aka digest) of forwardRequest
  const digest = GelatoRelaySDK.getForwardRequestDigestToSign(forwardRequest);

  // Sign digest using mock private key
  const sponsorSignature = utils.BytesLike = utils.joinSignature(
    await wallet._signingKey().signDigest(digest)
  );

  // Send forwardRequest and its sponsorSignature to Gelato Relay API
  await GelatoRelaySDK.sendForwardRequest(forwardRequest, sponsorSignature);

  console.log("ForwardRequest submitted!");

};

forwardRequestExample();
The information presented herein has been provided by third parties and is made available solely for general information purposes. Moonbeam does not endorse any project listed and described on the Moonbeam Doc Website (https://docs.moonbeam.network/). Moonbeam Foundation does not warrant the accuracy, completeness or usefulness of this information. Any reliance you place on such information is strictly at your own risk. Moonbeam Foundation disclaims all liability and responsibility arising from any reliance placed on this information by you or by anyone who may be informed of any of its contents. All statements and/or opinions expressed in these materials are solely the responsibility of the person or entity providing those materials and do not necessarily represent the opinion of Moonbeam Foundation. The information should not be construed as professional or financial advice of any kind. Advice from a suitably qualified professional should always be sought in relation to any particular matter or circumstance. The information herein may link to or integrate with other websites operated or content provided by third parties, and such other websites may link to this website. Moonbeam Foundation has no control over any such other websites or their content and will have no liability arising out of or related to such websites or their content. The existence of any such link does not constitute an endorsement of such websites, the content of the websites, or the operators of the websites. These links are being provided to you only as a convenience and you release and hold Moonbeam Foundation harmless from any and all liability arising from your use of this information or the information provided by any third-party website or service.