Create Gasless Sponsor

Allow users to transact gas-free.


FunWallets allow anyone to pay for any user's gas. Under the hood you must deposit a certain amount of the native gas token (ETH, MATIC, etc.) into the Gasless Paymaster contract. Next, the gasless paymaster will sponsor gas fees for your users.

You can either use a GaslesSponsor, or build your own.

This guide will show you how to configure a gasless paymaster sponsor.


1

Create Fun Wallet


To use a Gasless Sponsor paymaster in a testable flow, you must first create a FunWallet to test with.

,
sponsorGas.js
const { FunWallet } = require("fun-wallet")
const { Eoa } = require("fun-wallet/auth")
const { GaslessSponsor } = require("fun-wallet/sponsors/GaslessSponsor")
const { fundWallet } = require("fun-wallet/utils")
const API_KEY = "MYny3w7xJh6PRlRgkJ9604sHouY2MTke6lCPpSHq"
const PRIVATE_KEY = "0x98e9cfb323863bc4bfc094482703f3d4ac0cd407e3af2351c00dde1a6732756a"
const auth = new Eoa({ privateKey: PRIVATE_KEY })
const uniqueId = auth.getUniqueId()
const funWallet = new FunWallet( { uniqueId } )
2

Adding gas to your gasless paymaster

Load your gasless paymaster with gas tokens.


In order for the gasless paymaster to function, it needs to be funded with gas. We do this in the following code block by calling .stake() on the gasless paymaster.

const { GaslessSponsor } = require("fun-wallet/sponsors/GaslessSponsor")
const { fundWallet } = require("fun-wallet/utils")
const PRIVATE_KEY = "0x98e9cfb323863bc4bfc094482703f3d4ac0cd407e3af2351c00dde1a6732756a"
const auth = new Eoa({privateKey: PRIVATE_KEY})
// Create a Gasless Paymaster
const gaslessSponsor = new GaslessSponsor()
// Stake native gas tokens to the Gasless Paymaster
const stakeAmount = ".01" // 0.01 ETH
const stake = await gaslessSponsor.stake(authAddress, stakeAmount)
await auth.sendTx(stake)

Here is the full runnable code block.

,
sponsorGas.js
const { FunWallet, configureEnvironment } = require("fun-wallet")
const { Eoa } = require("fun-wallet/auth")
const { fundWallet } = require("fun-wallet/utils")
const { GaslessSponsor } = require("fun-wallet/sponsors/GaslessSponsor")
const PRIVATE_KEY = "0x98e9cfb323863bc4bfc094482703f3d4ac0cd407e3af2351c00dde1a6732756a"
const API_KEY = "MYny3w7xJh6PRlRgkJ9604sHouY2MTke6lCPpSHq"
const stake = async () => {
const auth = new Eoa({privateKey: PRIVATE_KEY})
const options = {
apiKey: API_KEY,
}
await configureEnvironment(options)
uid = await auth.getUniqueId()
wallet = new FunWallet({ uid, index: Math.ceil(Math.random() * 100_000_000) })
const authAddress = await auth.getUniqueId()
await configureEnvironment({
gasSponsor: {
sponsorAddress: await auth.getUniqueId(),
}
})
await fundWallet(auth, wallet, .005)
// Create a Gasless Paymaster
const gaslessSponsor = new GaslessSponsor()
// Stake native gas tokens to the Gasless Paymaster
const stakeAmount = ".01"
const stake = await gaslessSponsor.stake(authAddress, stakeAmount)
await auth.sendTx(stake)
}
stake()
3

(Optional) Whitelisting or Blacklisting Users

See how to set permissions on the paymaster through whitelisting and blacklisting.


Full code

An end to end example for creating a gasless paymaster and sending transactions without gas.


Note, this script is for the Goerli testnet, so you will need to change the chain id to a network fun-wallet supports if you want a different network.

Note, this script will run actual transactions on the network, so you will need to fund the funder wallet with some ETH or use our PRIVATE_KEY for the funder wallet.

Finally, this script will take a few minutes to run as it submits real transactions to the network so please be patient!

,
custom-paymaster.js
const { FunWallet, configureEnvironment } = require("fun-wallet")
const { Eoa } = require("fun-wallet/auth")
const { fundWallet } = require("fun-wallet/utils")
const { GaslessSponsor } = require("fun-wallet/sponsors/GaslessSponsor")
const PRIVATE_KEY = "0x98e9cfb323863bc4bfc094482703f3d4ac0cd407e3af2351c00dde1a6732756a"
const API_KEY = "MYny3w7xJh6PRlRgkJ9604sHouY2MTke6lCPpSHq"
const gasslessExample = async () => {
const auth = new Eoa({privateKey: PRIVATE_KEY})
const options = {
apiKey: API_KEY,
}
await configureEnvironment(options)
uid = await auth.getUniqueId()
console.log("Creating FunWallet...")
wallet = new FunWallet({ uid, index: Math.ceil(Math.random() * 100_000_000) })
console.log("FunWallet Created at:", await wallet.getAddress())
const authAddress = await auth.getUniqueId()
await configureEnvironment({
gasSponsor: {
sponsorAddress: await auth.getUniqueId(),
}
})
await fundWallet(auth, wallet, .005)
console.log("Creating and funding gasless paymaster...")
const gaslessSponsor = new GaslessSponsor()
const stakeAmount = ".01"
const stake = await gaslessSponsor.stake(authAddress, stakeAmount)
await auth.sendTx(stake)
console.log("Gasless paymaster created at", await gaslessSponsor.getPaymasterAddress())
const setWhitelistModeTx = await gaslessSponsor.setToWhitelistMode()
const addSpenderToWhitelistTx = await gaslessSponsor.addSpenderToWhiteList(await wallet.getAddress())
const removeSpenderFromWhitelistTx = await gaslessSponsor.removeSpenderFromWhiteList(await wallet.getAddress())
const whitelistTx = await auth.sendTxs([setWhitelistModeTx, addSpenderToWhitelistTx, removeSpenderFromWhitelistTx])
console.log("Whitelist Transaction Hashes:", whitelistTx[0].transactionHash, whitelistTx[1].transactionHash, whitelistTx[2].transactionHash)
const setBlacklistModeTx = await gaslessSponsor.setToBlacklistMode()
const addSpenderToBlacklistTx = await gaslessSponsor.addSpenderToBlackList(await wallet.getAddress())
const removeSpenderFromBlacklistTx = await gaslessSponsor.removeSpenderFromBlackList(await wallet.getAddress())
const blacklistTx = await auth.sendTxs([setBlacklistModeTx, addSpenderToBlacklistTx, removeSpenderFromBlacklistTx])
console.log("Blacklist Transaction Hashes: ", blacklistTx[0].transactionHash, blacklistTx[1].transactionHash, blacklistTx[2].transactionHash)
console.log("Transferring some funds... without gas!")
await wallet.transfer(auth, {
amount: .0001,
to: "0x3f5CE5FBFe3E9af3971dD833D26bA9b5C936f0bE",
})
console.log("Sent", .0001, "ETH to 0x3f5CE5FBFe3E9af3971dD833D26bA9b5C936f0bE from", await wallet.getAddress())
}
gasslessExample()