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
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,
});
Sponsor a Transaction
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],
}),
},
],
}
Batching Multiple Transactions
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 });
},
},
});
Permissions Example
This transaction will be rejected if the amount is more than 10 ZDEV.
Balance: 0