# Use an ERC-20 paymaster with Web3Auth

> Enable users to pay gas fees with ERC-20 tokens using a paymaster with Embedded Wallets Native Account Abstraction | Web3Auth

A paymaster is a vital component in the ERC-4337 standard, responsible for covering transaction costs on behalf of the user. There are various types of paymasters, such as gasless paymasters, ERC-20 paymasters, and more.

This guide demonstrates how to use Pimlico's ERC-20 Paymaster with an Embedded Wallets' account abstraction provider to allow your users to pay for their transactions using ERC-20 tokens.

:::tip

If you are looking to use sponsored paymaster, you can refer to the [sponsored paymaster guide](/tutorials/sending-gasless-transaction).

:::

## Prerequisites

- Pimlico Account: Since we'll be using the Pimlico paymaster, you'll need to have an API key from Pimlico. You can get a free API key from [Pimlico Dashboard](https://dashboard.pimlico.io/apikeys).
- Embedded Wallets account: If you haven't already, sign up on the [Embedded Wallets dashboard](https://developer.metamask.io/). It's free and gives you access to the base plan.

:::tip

See the documentation for detailed instructions on [setting up the Embedded Wallets dashboard](/embedded-wallets/dashboard/).

:::

- Web3Auth PnP Web SDK: This guide assumes that you already know how to [integrate the Embedded Wallets SDK in your project](/embedded-wallets/sdk/react/).

- Ensure you have enough USDC balance in the wallet to pay the transaction fees. [Request faucet for USDC tokens](https://faucet.circle.com/).

## Step 1: Integrate `AccountAbstractionProvider`

After you set up the Embedded Wallets dashboard and create a project, integrate the Embedded Wallets account abstraction provider into your web application. For this guide, use the [`@web3auth/account-abstraction-provider`](https://www.npmjs.com/package/@web3auth/account-abstraction-provider). This package manages the configuration for the account abstraction provider and bundler and prepares user operations.

If you are already using the Embedded Wallets SDK in your project, you just need to configure the `AccountAbstractionProvider` with the paymaster details, and pass it to Embedded Wallets' Web3Auth instance. No other changes are required.

### 1.1 Installation

```bash
npm install --save @web3auth/account-abstraction-provider
```

### 1.2 Configure ERC-20 Paymaster

The `AccountAbstractionProvider` requires specific configurations to function correctly. One key configuration is the paymaster. Embedded Wallets supports custom paymaster configurations, allowing you to deploy your own paymaster and integrate it with the provider.

You can choose from a variety of paymaster services available in the ecosystem. In this guide, we'll be configuring the Pimlico's ERC-20 Paymaster. However, it's important to note that paymaster support is not limited to the Pimlico, giving you the flexibility to integrate any compatible paymaster service that suits your requirements.

To configure the ERC-20 Paymaster, you need to pass the `token` in the `paymasterContext` which allows you to specify the ERC-20 token that will be used to pay for the transaction. For this guide, we'll use the USDC token. [Find the USDC token address for your desired network](https://developers.circle.com/stablecoins/docs/usdc-on-test-networks).

For simplicity, we have only used `SafeSmartAccount`, but you choose your favorite smart account provider from the available ones. Learn how to [configure the smart account](/embedded-wallets/sdk/react/advanced/smart-accounts).

```ts
// focus-start

  AccountAbstractionProvider,
  SafeSmartAccount,
} from '@web3auth/account-abstraction-provider'
// focus-end

const chainConfig = {
  chainNamespace: CHAIN_NAMESPACES.EIP155,
  chainId: '0xaa36a7',
  rpcTarget: 'https://ethereum-sepolia.publicnode.com',
  displayName: 'Ethereum Sepolia Testnet',
  blockExplorerUrl: 'https://sepolia.etherscan.io',
  ticker: 'ETH',
  tickerName: 'Ethereum',
  logo: 'https://cryptologos.cc/logos/ethereum-eth-logo.png',
}

// focus-start
const accountAbstractionProvider = new AccountAbstractionProvider({
  config: {
    chainConfig,
    bundlerConfig: {
      // Get the pimlico API Key from dashboard.pimlico.io
      url: `https://api.pimlico.io/v2/${chainId}/rpc?apikey=${pimlicoAPIKey}`,
      paymasterContext: {
        // USDC address on Ethereum Sepolia
        token: '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238',
      },
    },
    smartAccountInit: new SafeSmartAccount(),
    paymasterConfig: {
      // Get the pimlico API Key from dashboard.pimlico.io
      url: `https://api.pimlico.io/v2/${chainId}/rpc?apikey=${pimlicoAPIKey}`,
    },
  },
})
// focus-end
```

## Step 2: Configure Embedded Wallets

After you configure `AccountAbstractionProvider`, plug it into your Embedded Wallets modal or no-modal instance. If you use an external wallet such as MetaMask, set `useAAWithExternalWallet` in `IWeb3AuthCoreOptions` to control whether Web3Auth uses `AccountAbstractionProvider` or `EthereumPrivateKeyProvider`.

:::tip

For the generic web SDK setup, see the [JavaScript SDK guide](/embedded-wallets/sdk/js).

:::

If you are setting `useAAWithExternalWallet` to `true`, it'll create a new smart account for your user, where the signer/creator of the smart account would be the external wallet.

If you are setting `useAAWithExternalWallet` to `false`, it'll skip creating a new smart account, and directly use the external wallet to sign the transactions.

<Tabs
  defaultValue="modal"
  values={[
    { label: "PnP Modal SDK", value: "modal" },
    { label: "PnP No Modal SDK", value: "no-modal" },
  ]}
>

<TabItem value="modal">

```ts

const privateKeyProvider = new EthereumPrivateKeyProvider({
  // Use the chain config we declared earlier
  config: { chainConfig },
});

const web3auth = new Web3Auth({
  clientId: "YOUR_WEB3AUTH_CLIENT_ID", // Pass your Web3Auth Client ID, ideally using an environment variable
  web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
  privateKeyProvider,
  // Use the account abstraction provider we configured earlier
  accountAbstractionProvider
  // This will allow you to use EthereumPrivateKeyProvider for
  // external wallets, while use the AccountAbstractionProvider
  // for Web3Auth embedded wallets.
  useAAWithExternalWallet: false,
});
```

</TabItem>

<TabItem value="no-modal">

```ts

const privateKeyProvider = new EthereumPrivateKeyProvider({
  config: { chainConfig },
});

const web3auth = new Web3AuthNoModal({
  clientId: "YOUR_WEB3AUTH_CLIENT_ID", // Pass your Web3Auth Client ID, ideally using an environment variable
  web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
  privateKeyProvider,
  // Use the account abstraction provider we configured earlier
  accountAbstractionProvider
  // This will allow you to use EthereumPrivateKeyProvider for
  // external wallets, while use the AccountAbstractionProvider
  // for Web3Auth embedded wallets.
  useAAWithExternalWallet: false,
});

const authadapter = new AuthAdapter();
web3auth.configureAdapter(authadapter);
```

</TabItem>
</Tabs>

## Step 3: Send a transaction

To submit the transaction using ERC-20 paymaster, we'll first need to approve an ERC-20 token to be used by the paymaster. Ideally, we should first check the token allowance, and only approve the allowance needed by the paymaster.

To modify the token allowance, you'll need to perform a write operation on the ERC-20 contract. In the example below, we're using Pimlico, but be sure to update the paymaster and ERC-20 token addresses according to your specific case.

Since, we want to perform the approval transaction and send transaction in a single call, we'll use batch transaction feature of the `AccountAbstractionProvider`. Performing a batch transaction differs slightly from the normal flow.

To execute a batch transaction, you'll need to use the `BundlerClient` generated by the `AccountAbstractionProvider`. Embedded Wallets' Web3Auth instance provider can't be used for this, as it's a proxy provider designed to ensure compatibility with your preferred signer package for basic operations.

:::important

Please make sure you have enough [USDC balance](#prerequisites).

:::

```ts
// Use the same accountAbstractionProvider we created earlier.
const bundlerClient = accountAbstractionProvider.bundlerClient!
const smartAccount = accountAbstractionProvider.smartAccount!

// Pimlico's ERC-20 Paymaster address
const pimlicoPaymasterAddress = '0x0000000000000039cd5e8aE05257CE51C473ddd1'

// USDC address on Ethereum Sepolia
const usdcAddress = '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238'

// 0.00001 ETH in WEI format
const amount = 10000000000000n

// 10 USDC in WEI format. Since USDC has 6 decimals, 10 * 10^6
const approvalAmount = 10000000n

const userOpHash = await bundlerClient.sendUserOperation({
  account: smartAccount,
  calls: [
    // Approve USDC on Sepolia chain for Pimlico's ERC 20 Paymaster
    {
      to: usdcAddress,
      abi: parseAbi(['function approve(address,uint)']),
      functionName: 'approve',
      args: [pimlicoPaymasterAddress, approvalAmount],
    },
    {
      to: 'DESTINATION_ADDRESS',
      value: amount,
      data: '0x',
    },
    {
      to: 'DESTINATION_ADDRESS',
      value: amount,
      data: '0x',
    },
  ],
})

// Retrieve user operation receipt
const receipt = await bundlerClient.waitForUserOperationReceipt({
  hash: userOpHash,
})

const transactionHash = receipt.receipt.transactionHash
```

Congratulations, you have successfully sent your first transaction using the Pimlico's ERC-20 paymaster with Embedded Wallets account abstraction provider.

## Next steps

Learn more about advance features of the account abstraction provider like:

- Performing batch transactions:

<Tabs
  defaultValue="react"
  values={[
    { label: 'React', value: 'react' },
    { label: 'JavaScript', value: 'js' },
    { label: 'Vue', value: 'vue' },
  ]}>
  <TabItem value="react">
    [React smart accounts: batch
    transactions](/embedded-wallets/sdk/react/advanced/smart-accounts#send-batch-transaction)
  </TabItem>
  <TabItem value="js">
    [JS smart accounts: batch
    transactions](/embedded-wallets/sdk/js/advanced/smart-accounts#send-batch-transaction)
  </TabItem>
  <TabItem value="vue">
    [Vue smart accounts: batch
    transactions](/embedded-wallets/sdk/vue/advanced/smart-accounts#send-batch-transaction)
  </TabItem>
</Tabs>

- Using a sponsored paymaster:

<Tabs
  defaultValue="react"
  values={[
    { label: 'React', value: 'react' },
    { label: 'JavaScript', value: 'js' },
    { label: 'Vue', value: 'vue' },
  ]}>
  <TabItem value="react">
    [React smart accounts: configure bundler and
    paymaster](/embedded-wallets/sdk/react/advanced/smart-accounts#configure-bundler-and-paymaster)
  </TabItem>
  <TabItem value="js">
    [JS smart accounts: configure bundler and
    paymaster](/embedded-wallets/sdk/js/advanced/smart-accounts#configure-bundler-and-paymaster)
  </TabItem>
  <TabItem value="vue">
    [Vue smart accounts: configure bundler and
    paymaster](/embedded-wallets/sdk/vue/advanced/smart-accounts#configure-bundler-and-paymaster)
  </TabItem>
</Tabs>
