An EVM smart account is a smart contract account deployed on an EVM compatible network that
provides the ability to batch transactions, sponsor gas, and manage spend permissions.
Smart accounts require an owner account to sign on its behalf.
In this example, we will only create the smart account, and use a CDP EVM account as the owner.
Note that the smart contract is not deployed until the following step when you submit the first user operation.
Smart accounts are created with the CREATE2 opcode,
allowing us to access a contract address before it is deployed.
The actual smart contract is not deployed until the first user operation is submitted.
Submit a user operation on Base Sepolia from the smart account which transfers 0 ETH to the EOA
On Base Sepolia, smart account user operations are subsidized, meaning the smart account does not
need to be funded with ETH to submit a user operation. On Base mainnet, you will need to fund the smart account
with ETH before you can submit a user operation.
Copy
Ask AI
import { CdpClient } from "@coinbase/cdp-sdk"; import { parseEther } from "viem"; import dotenv from "dotenv"; dotenv.config(); const cdp = new CdpClient(); const owner = await cdp.evm.createAccount({}); console.log("Created owner account:", owner.address); const smartAccount = await cdp.evm.createSmartAccount({ owner, }); console.log("Created smart account:", smartAccount.address); const result = await cdp.evm.sendUserOperation({ smartAccount, network: "base-sepolia", calls: [ { to: "0x0000000000000000000000000000000000000000", value: parseEther("0"), data: "0x", }, ], }); console.log("User operation status:", result.status); console.log("Waiting for user operation to be confirmed..."); const userOperation = await cdp.evm.waitForUserOperation({ smartAccountAddress: smartAccount.address, userOpHash: result.userOpHash, }); if (userOperation.status === "complete") { console.log("User operation confirmed. Block explorer link:", `https://sepolia.basescan.org/tx/${userOperation.transactionHash}`); } else { console.log("User operation failed"); }
After running the above snippet, you should see similar output:
Copy
Ask AI
Created owner account: 0x088a49cAf927B8DacEFc4ccFD0D5EAdeC06F19A2Created smart account: 0x929444AFfd714c260bb6695c921bEB99d1D31ff7User operation status: broadcastWaiting for user operation to be confirmed...User operation confirmed. Block explorer link: https://basescan.org/tx/0x8e66c974c8d1b2a75fee35e097fe9171d28c48066472bb6ed81ca81a10d3c321```
import { CdpClient } from "@coinbase/cdp-sdk"; import { createPublicClient, http, parseEther, Calls } from "viem"; import { baseSepolia } from "viem/chains"; import dotenv from "dotenv"; dotenv.config(); const cdp = new CdpClient(); const account = await cdp.evm.createAccount(); const smartAccount = await cdp.evm.createSmartAccount({ owner: account }); console.log("Created smart account:", smartAccount.address); const { transactionHash } = await smartAccount.requestFaucet({ network: "base-sepolia", token: "eth", }); const publicClient = createPublicClient({ chain: baseSepolia, transport: http(), }); const faucetTxReceipt = await publicClient.waitForTransactionReceipt({ hash: transactionHash, }); console.log("Faucet transaction confirmed:", faucetTxReceipt.transactionHash); const destinationAddresses = [ "0xba5f3764f0A714EfaEDC00a5297715Fd75A416B7", "0xD84523e4F239190E9553ea59D7e109461752EC3E", "0xf1F7Bf05A81dBd5ACBc701c04ce79FbC82fEAD8b", ]; const calls = destinationAddresses.map((destinationAddress) => ({ to: destinationAddress, value: parseEther("0.000001"), data: "0x", })); console.log("Sending user operation to three destinations..."); const { userOpHash } = await smartAccount.sendUserOperation({ network: "base-sepolia", calls: calls as Calls<unknown[]>, }); console.log("Waiting for user operation to be confirmed..."); const userOperationResult = await smartAccount.waitForUserOperation({ userOpHash, }); if (userOperationResult.status === "complete") { console.log("User operation confirmed. Block explorer link:", `https://sepolia.basescan.org/tx/${userOperationResult.transactionHash}`); } else { console.log("User operation failed."); }
After running the above snippet, you should see output similar to the following:
Copy
Ask AI
Created smart account: 0xA557E90004ba5406A3553897e99D1FC5A2685F6dFaucet transaction confirmed: 0xa691fcfd1dcacad1ef144461e9c2f1fc110172f0fcfe9a10cbc83e5ca2b6b610Sending user operation to three destinations...Waiting for user operation to be confirmed...User operation confirmed. Block explorer link: https://sepolia.basescan.org/tx/0xd01b2089fd6d4673eae0d7629bcdf5488ff950dba2b7741b4725632f29e9f1ab