Guide

Creating accounts

newSmartAccount8130 turns a signer into a counterfactual EIP-8130 smart account. The account is not deployed yet; deployment happens atomically inside its first transaction.

Default smart account

By default the account is an UpgradeableAccount behind an ERC-1967 proxy (swappable later via an admin-signed upgrade). Pass upgradeable: false for an immutable CanonicalHighRatePayerAccount (ERC-1167) when you care about throughput and a fixed implementation.

secp256k1 ownerts
import { privateKeyToAccount, generatePrivateKey } from 'viem/accounts'
import { newSmartAccount8130 } from 'viem/experimental/eip8130'
const owner = privateKeyToAccount(generatePrivateKey())
const account = newSmartAccount8130({ signer: owner })
account.address // counterfactual address
account.createChange // include in accountChanges to deploy on first use

Pass a fixed salt to recover the same address across sessions and chains:

Fixed saltts
const account = newSmartAccount8130({
signer: owner,
salt: '0x0000000000000000000000000000000000000000000000000000000000000001',
})

Signer types

P-256

P-256 signerts
import * as P256 from 'ox/P256'
import { newSmartAccount8130, toP256Signer } from 'viem/experimental/eip8130'
const signer = toP256Signer({ privateKey: P256.randomPrivateKey() })
const account = newSmartAccount8130({ signer })

WebAuthn / passkey

Passkey signerts
import { createWebAuthnCredential, toWebAuthnAccount } from 'viem/account-abstraction'
import { newSmartAccount8130, toWebAuthnSigner } from 'viem/experimental/eip8130'
const credential = await createWebAuthnCredential({ name: 'vibes' })
const signer = toWebAuthnSigner(toWebAuthnAccount({ credential }))
const account = newSmartAccount8130({ signer })

Multiple initial keys

Register additional actors at creation with extraActors and the key.* builders. Viem sorts by actorId for you (a protocol requirement).

K1 + P-256 at creationts
import { key, newSmartAccount8130, toP256Signer } from 'viem/experimental/eip8130'
import * as P256 from 'ox/P256'
import { privateKeyToAccount, generatePrivateKey } from 'viem/accounts'
const owner = privateKeyToAccount(generatePrivateKey())
const p256 = toP256Signer({ privateKey: P256.randomPrivateKey() })
const account = newSmartAccount8130({
signer: owner,
extraActors: [key.p256(p256.publicKey)],
})

Plain / delegated EOAs

For the cheapest auth path (bare 65-byte signature, no contract required), use toEoa8130Account. You can later install smart-account code with account.delegate(impl) in the first transaction's account changes.

EOA accountts
import { privateKeyToAccount, generatePrivateKey } from 'viem/accounts'
import { toEoa8130Account } from 'viem/experimental/eip8130'
const account = toEoa8130Account(privateKeyToAccount(generatePrivateKey()))
// Later: account.delegate(impl) in the first tx's accountChanges

Deployment templates

ConceptMeaning
UpgradeableDefault. ERC-1967 proxy; upgrade via upgradeBySignature.
DefaultHighRateImmutable ERC-1167. Prefer for parallel / high-throughput accounts.
DefaultStandalone building block; EIP-7702 delegation target.
ERC-4337Portable implementation for chains without native 8130 + bundler providers.

Cross-chain (ERC-4337) portability

On chains without native EIP-8130, wrap the same account as a Viem Smart Account with the ERC-4337 implementation. Register the EntryPoint as a trusted-executor actor so it can drive executeBatch.

Portable accountts
import {
canonicalEip8130Deployment,
toSmartAccount8130,
} from 'viem/experimental/eip8130'
const account = await toSmartAccount8130({
client,
owner,
userSalt: '0x…',
initialActors: [/* key.k1(owner.address), … */],
implementation: canonicalEip8130Deployment.accounts.erc4337,
})

Same salt + initial actors give the same counterfactual address on native Vibenet and on portable providers. More in Multichain.