LazorKit LogoLazorKit
Concepts

Smart Wallet

How LazorKit smart wallets work — passkey authentication, PDA structure, roles, and lifecycle.

Smart Wallet

A LazorKit smart wallet is a group of on-chain accounts controlled by the LazorKit program. The owner authenticates via WebAuthn (passkey) or Ed25519 — no seed phrase or browser extension required.


Account Structure

AccountSeedsSizeDescription
Wallet PDA["wallet", user_seed]8 bytesIdentity anchor
Vault PDA["vault", wallet]0 bytesHolds SOL and tokens
Authority PDA["authority", wallet, id_hash]48+ bytesPer-key auth with role + counter
Session PDA["session", wallet, session_key]80+ bytesEphemeral sub-key with spending limits

Wallet PDA

Minimal 8-byte account. Acts as the identity anchor. The user_seed (32 bytes) is chosen at creation time.

Vault PDA

Zero-data account that holds SOL and tokens. The program signs for it via PDA seeds during Execute. No rent required.

Authority PDA

Each authorized key gets its own PDA. Key fields:

  • authority_typeEd25519 (0) or Secp256r1 (1)
  • roleOwner (0) / Admin (1) / Spender (2)
  • counter — monotonic u32 for Secp256r1 replay protection
  • variable data — pubkey for Ed25519; credential_id_hash + compressed_pubkey + rpId for Secp256r1

One PDA per authority means different authorities on the same wallet execute in parallel — the only writable account during Execute is the caller's own authority PDA (counter increment). Wallet and vault are read-only.


Authentication

Secp256r1 (Passkey)

WebAuthn credentials bound to the device's Secure Enclave (FaceID, TouchID, Windows Hello). The credential never leaves the device. On-chain verification uses the Secp256r1 precompile and enforces:

  • Odometer counter — monotonic u32 per authority. Client submits stored_counter + 1. Committed only after successful verification.
  • Slot freshness — auth payload slot must be within 150 slots of Clock::get().
  • CPI protection — stack height check prevents passkey auth via CPI.
  • Accounts hash — signed payload binds to all account pubkeys, preventing account-swap attacks.

Ed25519

Standard Solana keypair. Verified by the Solana runtime. No counter required.


Roles

RoleValuePermissions
Owner0Full control — add/remove any authority, transfer ownership, create/revoke sessions, execute
Admin1Add Spender authorities, create/revoke sessions, execute
Spender2Execute only

See RBAC for the full permission breakdown.


Wallet Lifecycle

Create

const { instructions, walletPda, vaultPda, authorityPda } = await client.createWallet({
  payer: payer.publicKey,
  userSeed: crypto.randomBytes(32),
  owner: {
    type: 'secp256r1',
    credentialIdHash,     // 32-byte SHA256 of WebAuthn credential ID
    compressedPubkey,     // 33-byte compressed Secp256r1 public key
    rpId: 'your-app.com',
  },
});

Creates Wallet PDA, Vault PDA, and the first Authority PDA in one transaction.

Add Authority

Adds an additional key. Owner can add any role; Admin can only add Spender.

Remove Authority

Closes the authority PDA and refunds rent to a specified destination. Prevents self-removal and removal of the last owner.

Transfer Ownership

Atomically closes the old owner PDA and creates a new owner PDA. Refunds old owner's rent to an explicit destination.


Wallet Lookup

Find wallets by credential hash — no need to store walletPda client-side:

const [wallet] = await client.findWalletsByAuthority(credentialIdHash);
// Returns: { walletPda, authorityPda, vaultPda, role, authorityType }

Costs

Auth TypeWallet CreationExecute (per tx)
Ed255190.002399 SOL0.000005 SOL
Secp256r1 (Passkey)0.002713 SOL0.000005 SOL
Session Key0.001453 SOL (one-time setup)0.000005 SOL

At $150/SOL, wallet creation is ~$0.36–$0.41. Session setup is ~$0.22, with subsequent executes at ~$0.00075 each.