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 assumes that you are building a dapp with embedded wallets powered by Dynamic. If you are using another embedded wallet, check here.
In this guide, we will walk you through:
Upgrading EOAs to smart accounts with Dynamic
Setting up Dynamic with 7702
Install Dependencies
npm i @dynamic-labs/wagmi-connector @dynamic-labs/ethereum-aa @dynamic-labs/ethereum @dynamic-labs/sdk-react-core wagmi @zerodev/ecdsa-validator @zerodev/sdk @tanstack/react-query
Setup the Dynamic context with your credentials. Initialise the 7702 client as follows.
import { isZeroDevConnector } from "@dynamic-labs/ethereum-aa";
import { useDynamicContext } from "@dynamic-labs/sdk-react-core"
const kernelVersion = KERNEL_V3_3;
const kernelAddresses = KernelVersionToAddressesMap[kernelVersion];
// switch network to baseSepolia. this is helpful when using multiple chains
// await primaryWallet.connector.switchNetwork({ networkChainId: baseSepolia.id });
const walletClient = primaryWallet.connector.getWalletClient?.();
const connector = primaryWallet.connector;
const kernelAccountClient = connector.getAccountAbstractionProvider({
withSponsorship: true,
});
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.
kernelAccountClient.sendTransaction({
account: kernelAccount,
to: ZERODEV_TOKEN_ADDRESS,
value: BigInt(0),
data: encodeFunctionData({
abi: ZERODEV_TOKEN_ABI,
functionName: "mint",
args: [kernelAccount.address, amount],
}),
})
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