7702

xZeroDev

Introduction

EIP-7702 is an Ethereum update that allows externally owned accounts (EOAs) to upgrade into smart accounts. In practical terms, this means that EOA wallets can now enjoy the benefits of account abstraction, such as gas sponsorship, transaction batching, transaction automation, and even chain abstraction.

This guide will show you how to upgrade EOAs to smart accounts using the ZeroDev SDK and Viem.

For integration with specific embedded wallets, check out these guides:

Upgrading EOAs to smart accounts

Local Account StatusLogged Out

Setting up Local Account with 7702

Install Dependencies

npm i @tanstack/react-query wagmi viem @zerodev/ecdsa-validator @zerodev/sdk

Initialise the 7702 client with Viem and Wagmi as follows.

const kernelVersion = KERNEL_V3_3;
const kernelAddresses = KernelVersionToAddressesMap[kernelVersion];

const newPrivateKey = generatePrivateKey();
const newAccount = privateKeyToAccount(newPrivateKey);

const baseSepoliaPublicClient = usePublicClient({
  chainId: baseSepolia.id,
});

const authorization = await account.signAuthorization({
  chainId: baseSepolia.id,
  nonce: 0,
  address: kernelAddresses.accountImplementationAddress,
});

const kernelAccount = await create7702KernelAccount(baseSepoliaPublicClient, {
  signer: account,
  entryPoint,
  kernelVersion,
  eip7702Auth: authorization,
});

const kernelAccountClient = create7702KernelAccountClient({
  account: kernelAccount,
  chain: baseSepolia,
  bundlerTransport: http(baseSepoliaBundlerRpc),
  paymaster: baseSepoliaPaymasterClient,
  client: baseSepoliaPublicClient,
});

1. Gas Sponsorship

To sponsor gas, create a gas policy such as "Sponsor All"on the ZeroDev dashboard.

Then, set up a paymaster client with the paymaster RPC from the dashboard.

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

const kernelAccount = await create7702KernelAccount(...);

const kernelAccountClient = create7702KernelAccountClient({
  paymaster: baseSepoliaPaymasterClient,

  // ...
  bundlerTransport: http(baseSepoliaBundlerRpc),
  account: kernelAccount,
  chain: baseSepolia,
  client: baseSepoliaPublicClient,
});
Create 7702 Account with local to try out the examples!

Sponsor a Transaction

Mint ZDEV Token

Balance: 0

2. Batching

When you need to send multiple transactions, you can batch them together to save on gas fees, latency, and the number of times a user needs to sign.

Each call in the example below that would have been a separate transaction is batched together and sent as a single user operation.

await kernelAccountClient.sendUserOperation({
  calls: [
    {
      to: ZERODEV_TOKEN_ADDRESS,
      value: BigInt(0),
      data: encodeFunctionData({
        abi: ZERODEV_TOKEN_ABI,
        functionName: "mint",
        args: [kernelAccountClient.account.address, amount],
      }),
    },
    {
      to: ZERODEV_TOKEN_ADDRESS,
      value: BigInt(0),
      data: encodeFunctionData({
        abi: ZERODEV_TOKEN_ABI,
        functionName: "transfer",
        args: [toAddress, amount],
      }),
    },
  ],
}
Create 7702 Account with local to try out the examples!

Batching Multiple Transactions

1. Mint ZDEV
2. Transfer Token

Balance: 0

3. Permissions

With ZeroDev smart accounts, you can create temporary keys (session keys) with specific permissions.

With session keys, you can sign transactions without asking for further user confirmations, therefore enabling "1-click trading." You can also automate transactions on the server side, to enable use cases like subscription.

Thanks to permissions, the user can rest assured that their funds are safe, since the session keys can only do what they were explicitly given permissions to do.

In this example, we will create a session key that's allowed to transfer no more than 10 tokens.

const _sessionPrivateKey = generatePrivateKey();
const sessionAccount = privateKeyToAccount(_sessionPrivateKey as Address;

const sessionKeySigner = await toECDSASigner({
  signer: sessionAccount,
});

const permissionPlugin = await toPermissionValidator(publicClient, {
  entryPoint,
  kernelVersion,
  signer: sessionKeySigner,
  policies: [callPolicy],
});

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

const sessionKeyKernelAccount = await createKernelAccount(publicClient, {
  entryPoint,
  plugins: {
    sudo: masterEcdsaValidator,
    regular: permissionPlugin,
  },
  kernelVersion: kernelVersion,
  address: masterKernelAccount.address,
});

const kernelPaymaster = createZeroDevPaymasterClient(...);

const kernelClient = createKernelAccountClient({
  account: sessionKeyKernelAccount,
  chain: baseSepolia,
  bundlerTransport: http(baseSepoliaBundlerRpc),
  paymaster: {
    getPaymasterData(userOperation) {
      return kernelPaymaster.sponsorUserOperation({ userOperation });
    },
  },
});
Create 7702 Account with local to try out the examples!

Permissions Example

1. Create a session key
2. Transfer ZDEV

This transaction will be rejected if the amount is more than 10 ZDEV.

Balance: 0