Enabling Gasless Transactions with Gelato & Safe's Account Abstraction SDK

Gelato Team

Jun 28, 2023

Navigating a multitude of dApps can be daunting for newcomers. The onboarding process is often riddled with complex concepts and steps, creating a barrier that hinders mass adoption.

One of these challenges is the concept of "gas"—the fee required to perform transactions on different chains.

To acquire native assets (like ETH, MATIC, etc.) to pay gas fees, you must create an account on an exchange, go through verification, purchase the assets, and then transfer them to your wallet. This process can be intimidating for new users. Even if you already hold ERC20 tokens in your wallet but no native assets, you can’t move or swap those ERC20 tokens because paying gas itself requires a native token. This creates a frustrating cycle.

Simplifying Transactions with Account Abstraction and Safe SDK

Safe tackles this issue with the Safe{Core} Account Abstraction SDK, which lets developers integrate account abstraction into their apps, making the UX smoother.

The Relay Kit, powered by Gelato Relay, enables users to cover gas fees with ERC-20 tokens or even execute gasless transactions.

Mint NFTs Without Paying Gas Using Gelato's Safe Relay Kit

Here’s how you can mint NFTs without gas using the Safe Relay Kit:

Example Contract: A simple ERC721 NFT minting contract with a `mintGelato` function:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.14;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/utils/Counters.sol";

contract GelatoNFT is ERC721, ERC721URIStorage {
    using Counters for Counters.Counter;
    Counters.Counter private _tokenIds;

    string public constant gelatoInitialURI = "https://...ipfs.nftstorage.link/";

    constructor() ERC721("GelatoNFT", "GNFT") {}

    function mintGelato(address to) public {
        _tokenIds.increment();
        uint256 newItemId = _tokenIds.current();
        _mint(to, newItemId);
        _setTokenURI(newItemId, gelatoInitialURI);
    }

    function _burn(uint256 tokenId) internal override(ERC721, ERC721URIStorage) {
        super._burn(tokenId);
    }

    function tokenURI(uint256 tokenId) public view override(ERC721, ERC721URIStorage) returns (string memory) {
        return super.tokenURI(tokenId);
    }

    function supportsInterface(bytes4 interfaceId) public view override(ERC721, ERC721URIStorage) returns (bool) {
        return super.supportsInterface(interfaceId);
    }
}

Step-by-Step Guide

  1. Create a Safe: Go to Safe{Wallet} and create a 1/1 Safe.

  2. Verify Your Contract: Paste your Safe address in a block explorer, verify it, and save the implementation ABI for Gelato.

  3. Deposit Funds: Fund Gelato 1Balance with USDC (Polygon) or testnet tokens.

  4. Create Relay App: In your Gelato Relay App, add your Safe address and enable `execTransaction` as gasless.

  5. Setup Project:

      mkdir gasless-nft-minting
      cd gasless-nft-minting
      yarn init -y
      yarn add ethers @safe-global/relay-kit @safe-global/protocol-kit @safe-global/safe-core-sdk-types
    
    
  6. Import Packages:

      import { ethers } from 'ethers';
      import { GelatoRelayPack } from '@safe-global/relay-kit';
      import Safe, { EthersAdapter, getSafeContract } from '@safe-global/protocol-kit';
      import { MetaTransactionData, MetaTransactionOptions, OperationType } from '@safe-global/safe-core-sdk-types';
    
    
  7. Create Transaction Object:

      const tx: MetaTransactionData = {
        to: targetAddress,
        data: nftContract.interface.encodeFunctionData("mintGelato", [
          "0xYourWalletAddress",
        ]),
        value: "0",
        operation: OperationType.Call,
      };
    
      const options: MetaTransactionOptions = {
        gasLimit,
        isSponsored: true,
      };
    
    
  8. Initialize SDKs:

      const ethAdapter = new EthersAdapter({ ethers, signerOrProvider: signer });
      const safeSDK = await Safe.create({ ethAdapter, safeAddress });
      const relayKit = new GelatoRelayPack(GELATO_RELAY_API_KEY);
    
    
  9. Encode Transaction:

      const safeTransaction = await safeSDK.createTransaction({ safeTransactionData: tx });
      const signedSafeTx = await safeSDK.signTransaction(safeTransaction);
      const safeSingletonContract = await getSafeContract({
        ethAdapter,
        safeVersion: await safeSDK.getContractVersion(),
      });
      const encodedTx = safeSingletonContract.encode("execTransaction", [
        signedSafeTx.data.to,
        signedSafeTx.data.value,
        signedSafeTx.data.data,
        signedSafeTx.data.operation,
        signedSafeTx.data.safeTxGas,
        signedSafeTx.data.baseGas,
        signedSafeTx.data.gasPrice,
        signedSafeTx.data.gasToken,
        signedSafeTx.data.refundReceiver,
        signedSafeTx.encodedSignatures(),
      ]);
    
    
  10. Send to Gelato Relay:

      const relayTransaction = {
        target: safeAddress,
        encodedTransaction: encodedTx,
        chainId,
        options,
      };
      const response = await relayKit.relayTransaction(relayTransaction);
      console.log(`Task ID: https://relay.gelato.digital/tasks/status/${response.taskId}`);
    
    

Conclusion

The Safe Account Abstraction SDK Relay Kit powered by Gelato Relay enables gasless NFT minting and seamless dApp interactions. By removing friction, it paves the way for broader blockchain adoption.

About Gelato Relay

Gelato abstracts blockchain complexities, delivering secure gasless transactions and smoother onboarding. Explore Gelato services: Web3 Functions, Automate, and the Account Abstraction SDK.

Join the community on Discord to connect with developers.

Ready to build?

Start with a testnet, launch your mainnet in days, and scale with industry-leading UX.

Ready to build?

Start with a testnet, launch your mainnet in days, and scale with industry-leading UX.

Ready to build?

Start with a testnet, launch your mainnet in days, and scale with industry-leading UX.

Ready to build?

Start with a testnet, launch your mainnet in days, and scale with industry-leading UX.