EIP-7702 is an upgrade to EVM blockchains that enables externally owned accounts (EOAs) to set their code to that of a smart contract. In practical terms, this means that EOA wallets will gain AA (account abstraction) capabilities such as transaction bundling, gas sponsorship, and custom permissions.

Privy supports all low level interfaces required by 7702 - signing authorizations and sending type 4 transactions. Use these guides to get started with EIP-7702 in your application:

EIP-7702 is only available on certain testnets like Odyssey and Sepolia

In this guide, we demonstrate using ZeroDev, a toolkit for creating smart accounts, together with Privy to enable your users to send gasless (sponsored) transactions.

Want to see a full end to end example? Check out our starter repo here!

0. Install dependencies

In your app’s repository, install the required dependencies from Privy, ZeroDev and viem:

npm i @privy-io/react-auth @zerodev/sdk @zerodev/ecdsa-validator viem

1. Sign up for a ZeroDev account and get your project ID

Visit the ZeroDev dashboard and sign up for a new account if you do not have one already. Set up a new project for your required chain(s) and retrieve your ZeroDev paymaster and bundler RPCs from the dashboard.

Once you have created a project, set up a gas sponsorship policy. This will tell ZeroDev to sponsor gas for your accounts. For this tutorial, you can just set a “Project Policy” like “Sponsor up to 10 requests per minute.”

2. Configure Privy settings

Configure your app to create embedded wallets for all users. Also configure Privy to not show its default wallet UIs. Instead, we recommend you use your own custom UIs for showing users the user operations they sign.

Update your PrivyProvider configuration to include the following properties:

<PrivyProvider
  config={{
    embeddedWallets: {
      showWalletUIs: false, // [!code ++]
      createOnLogin: 'all-users' // [!code ++]
    }
  }}
>
  ...
</PrivyProvider>

3. Sign a wallet authorization with the embedded wallet

The useSignAuthorization hook from the Privy SDK is used to create a cryptographic signature for an EIP-7702 authorization. This authorization allows an EOA (your user’s embedded wallet) to set its code to that of a smart contract (in this case, the Kernel account implementation). According to the EIP-7702 specification, this signature creates a delegation designation that enables the EOA to behave like a smart account, including capabilities for transaction bundling and gas sponsorship.

Use the code snippet below to generate an authorization signature for the wallet:

import {useSignAuthorization} from '@privy-io/react-auth';
import {
  getEntryPoint,
  KERNEL_V3_3_BETA,
  KernelVersionToAddressesMap,
} from "@zerodev/sdk/constants";
import {odysseyTestnet} from "viem/chains";
...
const chain = odysseyTestnet;
const kernelVersion = KERNEL_V3_3_BETA;
const entryPoint = getEntryPoint("0.7");

const {signAuthorization} = useSignAuthorization();
const authorization = signAuthorization({
    contractAddress: KernelVersionToAddressesMap[kernelVersion].accountImplementationAddress,
    sponsor: true,
    chain
})

4. Create a Kernel account with the ZeroDev SDK

Use the signed authorization to create a Kernel account. With EIP-7702, this step doesn’t actually deploy a new smart contract but instead creates a reference to the Kernel implementation that will be used when transactions are sent from the EOA. This delegation allows the user’s EOA to execute transactions as if it were a Kernel smart account, gaining capabilities like gas sponsorship while maintaining the same address as the embedded wallet.

import {
  createKernelAccount,
  createKernelAccountClient,
  createZeroDevPaymasterClient
} from '@zerodev/sdk';
import {createWalletClient, createPublicClient, custom, http} from 'viem';

const {wallets} = useWallets();
const embeddedWallet = wallets.find((wallet) => wallet.walletClientType === 'privy');

const walletClient = createWalletClient({
  account: embeddedWallet.address as Hex,
  chain,
  transport: http()
});

const publicClient = createPublicClient({
  chain,
  transport: custom(await embeddedWallet.getEthereumProvider())
});

const ecdsaValidator = await signerToEcdsaValidator(publicClient, {
  signer: walletClient,
  entryPoint,
  kernelVersion
});

const account = await createKernelAccount(publicClient, {
  plugins: {
    sudo: ecdsaValidator
  },
  entryPoint,
  kernelVersion,
  address: walletClient.account.address,
  eip7702Auth: authorization
});

5. Configure the ZeroDev client for sponsored transactions

This client creates and submits UserOperations (compatible with EIP-4337 infrastructure) that execute within the context of the delegated smart account code, enabling your application to provide a gas-free experience for users.

import {createKernelAccountClient, createZeroDevPaymasterClient} from '@zerodev/sdk';

const paymasterRpc = 'YOUR_PAYMASTER_RPC_URL';
const bundlerRpc = 'YOUR_BUNDLER_RPC_URL';

const paymasterClient = createZeroDevPaymasterClient({
  chain,
  transport: http(paymasterRpc)
});

const kernelClient = createKernelAccountClient({
  account,
  chain,
  bundlerTransport: http(bundlerRpc),
  paymaster: paymasterClient,
  client: publicClient
});

Make sure to replace the paymasterRpc and bundlerRpc with the RPCs from the ZeroDev dashboard.

6. Send transactions with the client

With the Kernel client configured, you can now send gas-sponsored transactions. This example shows how to send a basic transaction and wait for its receipt:

// Send a simple transaction
const userOpHash = await kernelClient.sendTransaction({
  to: zeroAddress,
  value: BigInt(0),
  data: '0x'
});

console.log(userOpHash);

// Wait for the transaction to be processed
const {receipt} = await kernelClient.waitForUserOperationReceipt({
  hash: userOpHash
});

console.log(
  'UserOp completed',
  `${chain.blockExplorers.default.url}/tx/${receipt.transactionHash}`
);

Conclusion

Congratulations! You just sent your first sponsored transaction from a EOA account, with EIP-7702.

If you want to leverage other smart account capabilities such as transaction bundling and permissions, check out the ZeroDev docs.

Was this page helpful?