Pay Gas in ERC20s

Allow FunWallet users to pay for gas using ERC-20 tokens

Overview

By leveraging Account Abstraction via EIP-4337, every FunWallet has the ability to pay for gas in any ERC-20. This works by having both the native gas token (e.g eth) as well as the ERC-20 token a set of FunWallets desire to pay gas with both locked in a smart contract called a Paymaster.

Currently, both the native gas token & the ERC-20 token must be supplied by a funder address, not the FunWallet. Eventually, the FunWallet SDK will support the staking of the ERC-20 token by the FunWallet itself.

When a FunWallet wants to perform a Transaction, it's connected Paymaster is notified & performs a swap between the gas token & the ERC-20 based on the price feed of a Chainlink oracle. This ensures that the balance of the gas token never goes down.

Currently, the FunWallet SDK offers the payment of gas in the following ERC-20s:



General Flow

The following flow describes how to pay gas in ERC-20s. For this example flow, we choose the USDC Paymaster.

1

Import Required Libraries

import { ethers } from "ethers";
import { FunWallet, FunWalletConfig, Paymasters } from "@fun-wallet/sdk";
const { PaymasterSponsorInterface } = Paymasters
2

Create an ethers.Wallet EOA Instance

// Hardhat port for local for testing
const rpc = "localhost:8545";
const provider = new ethers.providers.JsonRpcProvider(rpc);
// Note that the key here will be exposed and should never be used in production
const eoa = new ethers.Wallet(PRIV_KEY, provider);
3

Create & Initialize a FunWallet

const chainID = "31337" // Hardhat
const prefundAmt = 0.3 // amount of native gas token to prefund our FunWallet with
const API_KEY = "" // Get your API key from app.fun.xyz/api-key
const config = new FunWalletConfig(eoa, chainID, prefundAmt)
const wallet = new FunWallet(config, API_KEY)
// init will perform the pre-funding of the FunWallet
await wallet.init()
4

Create & Initialize PaymasterSponsorInterface Istance

const paymasterInterface = new PaymasterSponsorInterface(eoa)
await paymasterInterface.init()
5

Deposit & Lock USDC & eth on Paymaster

await paymasterInterface.addTokenDepositTo(wallet.address, USDCETHAMT)
await paymasterInterface.addEthDepositForSponsor(value, eoa.address)
await paymasterInterface.lockTokenDeposit()
await paymasterInterface.setWhitelistMode(true)

Update Paymaster on FunWallet

const usdcPaymaster = new USDCPaymaster(paymasterInterface.paymasterAddress)
wallet.updatePaymaster(usdcPaymaster)

Full Example

,
pay-gas-in-usdc.js
import { ethers } from "ethers";
import { FunWallet, FunWalletConfig, Paymasters } from "@fun-wallet/sdk";
const { PaymasterSponsorInterface } = Paymasters
// Hardhat port for local for testing
const rpc = "localhost:8545";
const provider = new ethers.providers.JsonRpcProvider(rpc);
// Note that the key here will be exposed and should never be used in production
const eoa = new ethers.Wallet(PRIV_KEY, provider);
const chainID = "31337" // Hardhat
const prefundAmt = 0.3 // amount of native gas token to prefund our FunWallet with
const API_KEY = "" // Get your API key from app.fun.xyz/api-key
const config = new FunWalletConfig(eoa, chainID, prefundAmt)
const wallet = new FunWallet(config, API_KEY)
// init will perform the pre-funding of the FunWallet
await wallet.init()
const paymasterInterface = new PaymasterSponsorInterface(eoa)
await paymasterInterface.init()
await paymasterInterface.addTokenDepositTo(wallet.address, USDCETHAMT)
await paymasterInterface.addEthDepositForSponsor(value, eoa.address)
await paymasterInterface.lockTokenDeposit()
await paymasterInterface.setWhitelistMode(true)
const usdcPaymaster = new USDCPaymaster(paymasterInterface.paymasterAddress)
wallet.updatePaymaster(usdcPaymaster)

Mentioned Classes