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
.
Import Required Libraries
import { ethers } from "ethers";import { FunWallet, FunWalletConfig, Paymasters } from "@fun-wallet/sdk";const { PaymasterSponsorInterface } = Paymasters
Create an ethers.Wallet EOA Instance
// Hardhat port for local for testingconst rpc = "localhost:8545";const provider = new ethers.providers.JsonRpcProvider(rpc);// Note that the key here will be exposed and should never be used in productionconst eoa = new ethers.Wallet(PRIV_KEY, provider);
Create & Initialize a FunWallet
const chainID = "31337" // Hardhatconst prefundAmt = 0.3 // amount of native gas token to prefund our FunWallet withconst API_KEY = "" // Get your API key from app.fun.xyz/api-keyconst config = new FunWalletConfig(eoa, chainID, prefundAmt)const wallet = new FunWallet(config, API_KEY)// init will perform the pre-funding of the FunWalletawait wallet.init()
Create & Initialize PaymasterSponsorInterface Istance
const paymasterInterface = new PaymasterSponsorInterface(eoa)await paymasterInterface.init()
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 testingconst rpc = "localhost:8545";const provider = new ethers.providers.JsonRpcProvider(rpc);// Note that the key here will be exposed and should never be used in productionconst eoa = new ethers.Wallet(PRIV_KEY, provider);const chainID = "31337" // Hardhatconst prefundAmt = 0.3 // amount of native gas token to prefund our FunWallet withconst API_KEY = "" // Get your API key from app.fun.xyz/api-keyconst config = new FunWalletConfig(eoa, chainID, prefundAmt)const wallet = new FunWallet(config, API_KEY)// init will perform the pre-funding of the FunWalletawait 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
FunWallet
Primary class in the FunWallet SDK that orchestrates the movement of assets & data
FunWalletConfig
FunWallet configuration class
USDCPaymaster
A class for storing a user's paymaster data
PaymasterSponsorInterface
The primary class for controlling a user's Paymaster sponsor