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, allowing you to use any implementation of EIP-7702. Use the following guides to get started with EIP-7702 in your application:

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

Signing EIP-7702 authorizations

Privy provides a useSignAuthorization hook that allows you to sign an EIP-7702 authorization using the user’s embedded wallet. This authorization is a cryptographic signature that allows an EOA to set its code to that of a smart contract, enabling the EOA to behave like a smart account.

import {useSignAuthorization} from '@privy-io/react-auth';

const {signAuthorization} = useSignAuthorization();

const authorization = signAuthorization({
  contractAddress: '0x1234567890abcdef1234567890abcdef12345678', // The address of the smart contract
  chainId: chain.id
});

Learn more about using the signed authorization in the guides below!

Using EIP-7702 capabilities

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 create a project

Head to the ZeroDev dashboard and create a project on a chain that supports EIP-7702 (e.g. Sepolia, Holesky, Odyssey).

Set up a gas sponsorship policy to enable sending sponsored transactions. Copy the Bundler RPC and Paymaster RPC for the network you plan to use.

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. Create a 7702 Kernel account with the ZeroDev SDK

ZeroDev exposes helper functions that take care of generating the 7702 authorization for you. All you need to provide is the signer for the user’s embedded wallet and the Kernel version you want to use.

import {create7702KernelAccount, create7702KernelAccountClient} from '@zerodev/ecdsa-validator';
import {createZeroDevPaymasterClient} from '@zerodev/sdk';
import {KERNEL_V3_3} from '@zerodev/sdk/constants';
import {getEntryPoint} from '@zerodev/sdk/constants';
import {createWalletClient, createPublicClient, custom, http, zeroAddress, Hex} from 'viem';
import {odysseyTestnet} from 'viem/chains';

// Select the chain and Kernel version you want to use
const chain = odysseyTestnet;
const kernelVersion = KERNEL_V3_3;
const entryPoint = getEntryPoint('0.7');

// Grab the embedded wallet created by Privy
const {wallets} = useWallets();
const embeddedWallet = wallets.find((wallet) => wallet.walletClientType === 'privy');

// Build viem clients for the wallet & public RPC
const walletClient = createWalletClient({
  account: embeddedWallet.address as Hex,
  chain,
  transport: custom(await embeddedWallet.getEthereumProvider())
});

const publicClient = createPublicClient({
  chain,
  transport: http()
});

// Create the 7702 Kernel account (no deployment occurs!)
const account = await create7702KernelAccount(publicClient, {
  signer: walletClient,
  entryPoint,
  kernelVersion,
  eip7702Auth: authorization
});

Behind the scenes ZeroDev generates the EIP-7702 authorization and binds the Kernel implementation code to the EOA, giving it smart-account super-powers while keeping the same address.

4. Configure the ZeroDev client for sponsored transactions

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

// Create a paymaster client so the user does not need ETH
const paymasterClient = createZeroDevPaymasterClient({
  chain,
  transport: http(paymasterRpc)
});

// Build a Kernel client that will create & submit UserOperations
const kernelClient = create7702KernelAccountClient({
  account,
  chain,
  bundlerTransport: http(bundlerRpc),
  paymaster: paymasterClient,
  client: publicClient
});

5. Send a gas-sponsored transaction

With the client configured, you can now send gasless UserOperations. Below we send an empty call then wait for it to be mined:

// Send a simple UserOperation
const userOpHash = await kernelClient.sendUserOperation({
  callData: await kernelClient.account.encodeCalls([
    {
      to: zeroAddress,
      value: BigInt(0),
      data: '0x'
    }
  ])
});

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

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

Conclusion

That’s it! You’ve just executed a gasless transaction from a normal EOA upgraded with EIP-7702.

Explore the rest of the ZeroDev docs to learn about batching, session keys, cross-chain actions and more.