Pay gas in ERC-20 tokens
Pay for wallet deployments, transfers, or NFT mints in ERC-20 tokens.
For a FunWallet to pay gas in an ERC-20 token, 2 assets must be staked in a Token Paymaster contract:
The native gas token (ETH if on Ethereum, MATIC if on Polygon, etc). This token must be transferred to the Token Paymaster contract.
The ERC-20 token to pay gas in. This token can be staked in 2 ways:
By transferring the token to the Token Paymaster contract.
By giving token spend approval to the Token Paymaster contract.
Quick start
Configure environment
Configure the options.gasSponsor environment variable to contain both the address of the gas sponsor & the name of the ERC-20 token to pay gas in. To learn more about gas sponsors for paying gas in ERC-20 tokens, visit the token sponsor section.
await configureEnvironment({gasSponsor: {sponsorAddress: "0x07Ac5A221e5b3263ad0E04aBa6076B795A91aef9" // Our test sponsor address on Göerlitoken: "usdc"}})
Fun offers a publicly-available token sponsor on the Göerli testnet for developer testing purposes. Once Fun has completed smart contract audits, a production-ready token paymaster will be available for use on all supported networks.
erc20-gas.js
const ethers = require("ethers")const { FunWallet, configureEnvironment } = require("fun-wallet")const { Eoa } = require("fun-wallet/auth")const { fundWallet } = require("fun-wallet/utils")const fetch = require('node-fetch')const API_KEY = "MYny3w7xJh6PRlRgkJ9604sHouY2MTke6lCPpSHq"const PRIVATE_KEY = "0x98e9cfb323863bc4bfc094482703f3d4ac0cd407e3af2351c00dde1a6732756a"const DEST_ADDR = "0xd8da6bf26964af9d7eed9e03e53415d37aa96045"const main = async () => {// Configure environmentawait configureEnvironment({gasSponsor: {sponsorAddress: "0x07Ac5A221e5b3263ad0E04aBa6076B795A91aef9" // Our paymaster addresstoken: "usdc"}})const provider = new ethers.providers.JsonRpcProvider("https://goerli.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161")const eoa = new ethers.Wallet(PRIVATE_KEY, provider)const auth = new Eoa({ signer: eoa })const uniqueId = await auth.getUniqueId()const funWallet = new FunWallet( { uniqueId } )const receipt = await funWallet.transfer(auth, {to: DEST_ADDR,amount: 10,token: "USDC"})}main()
This code will fail without step 2.
Give paymaster approval to spend ERC-20s from your wallet
When a FunWallet executes a transaction paying for gas in ERC-20s, the paymaster contract first calculates the amount of gas the transaction will take, then checks an oracle price feed to get the exchange rate between the native gas token & the ERC-20 token intended to pay gas in. Finally, the paymaster contract transfers the necessary ERC-20s to from the FunWallet to itself. I order for the paymaster contract to be able to do this, the FunWallet must give token spend approval to the paymaster contract.
const { TokenSponsor } = require("fun-wallet/sponsors/TokenSponsor")// Get token sponsor objectconst tokenSponsor = new TokenSponsor()// Approve paymaster address to access predefined set of wallet fundsawait funWallet.approve(auth, {spender: tokenSponsor.getPaymasterAddress(),token: "usdc",amount: 10000})
erc20-gas.js
const ethers = require("ethers")const { TokenSponsor } = require("fun-wallet/sponsors/TokenSponsor")const { FunWallet, configureEnvironment } = require("fun-wallet")const { Eoa } = require("fun-wallet/auth")const fetch = require('node-fetch')const API_KEY = "MYny3w7xJh6PRlRgkJ9604sHouY2MTke6lCPpSHq"const PRIVATE_KEY = "0x98e9cfb323863bc4bfc094482703f3d4ac0cd407e3af2351c00dde1a6732756a"const DEST_ADDR = "0xd8da6bf26964af9d7eed9e03e53415d37aa96045"const main = async () => {await configureEnvironment({gasSponsor: {sponsorAddress: "0x07Ac5A221e5b3263ad0E04aBa6076B795A91aef9"token: "usdc"}})const provider = new ethers.providers.JsonRpcProvider("https://goerli.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161")const eoa = new ethers.Wallet(PRIVATE_KEY, provider)const auth = new Eoa({ signer: eoa })const uniqueId = auth.getUniqueId()const funWallet = new FunWallet( { uniqueId } )// Get token sponsor objectconst tokenSponsor = new TokenSponsor()// Approve paymaster address to spend ERC-20s from funWalletawait funWallet.approve(auth, {spender: tokenSponsor.getPaymasterAddress(),token: "usdc",amount: 10000})const receipt = await funWallet.transfer(auth, {to: DEST_ADDR,amount: 10,token: "USDC"})}main()