LazorKit is a high-performance, secure smart wallet on Solana designed for distinct Authority storage and modern authentication (Passkeys). It uses pinocchio for efficient zero-copy state management and optimized syscalls.
- Zero-Copy Executions: We strictly use
pinocchioto cast raw bytes into Rust structs. This bypasses Borsh serialization overhead for maximum performance.- Requirement: All state structs must implement
NoPadding(via#[derive(NoPadding)]) to ensure memory safety and perfect packing.
- Requirement: All state structs must implement
- Separated Storage (PDAs): Uses a deterministic PDA for each Authority.
- Benefit: Unlimited distinct authorities per wallet without resizing costs or hitting
10KiBlimits limits inside a single account.
- Benefit: Unlimited distinct authorities per wallet without resizing costs or hitting
- Strict RBAC: Hardcoded Permission Roles (Owner, Admin, Spender) for predictability and secure delegation.
- Transaction Compression: Uses
CompactInstructions(Index-based referencing) to fit complex multi-call payloads into standard Solana transaction limits (~1232 bytes).
- Ed25519: Relies on standard Solana runtime signature verification.
- Secp256r1 (WebAuthn):
- SlotHashes Nonce: Uses the
SlotHashessysvar to verify that the signed payload references a recent slot (within 150 slots). This acts as a highly efficient "Proof of Liveness" without requiring stateful on-chain nonces or counters. - CPI Protection: Explicit
stack_heightcheck prevents the authentication instruction from being called maliciously via CPI (invoke), defending against cross-program attack vectors. - Signature Binding: The
auth_payloadensures signatures are tightly bound to the specific target account and instruction data, mitigating cross-wallet and cross-instruction replays.
- SlotHashes Nonce: Uses the
- Session Keys:
- Absolute Expiry: Sessions are valid until a strict absolute slot height
expires_at(u64).
- Absolute Expiry: Sessions are valid until a strict absolute slot height
- Modules:
program/src/auth/secp256r1 - Mechanism:
- Reconstructs
clientDataJsonon-chain dynamically based on the current context (challengeandorigin). - Verifies
authenticatorDataflags (User Presence/User Verification). - Uses
Secp256r1SigVerifyprecompile via Sysvar Introspection (load_current_index_param). - Abstraction: Implements the
Authoritytrait for unified verification logic across both key types.
- Reconstructs
#[repr(u8)]
pub enum AccountDiscriminator {
Wallet = 1,
Authority = 2,
Session = 3,
}Anchor for the identity.
- Seeds:
[b"wallet", user_seed]
Represents a single authorized user (Owner, Admin, or Spender). Multi-signature schemas allow deploying multiple Authority PDAs per Wallet.
- Seeds:
[b"authority", wallet_pubkey, id_hash] - Data Structure:
#[repr(C)] #[derive(NoPadding)] pub struct AuthorityAccountHeader { pub discriminator: u8, pub authority_type: u8, // 0=Ed25519, 1=Secp256r1 pub role: u8, // 0=Owner, 1=Admin, 2=Spender pub bump: u8, pub wallet: Pubkey, }
- Type 1 (Secp256r1) adds padding to reach 8-byte alignment:
[ u32 padding ] + [ credential_id_hash (32) ] + [ pubkey (64) ].
- Type 1 (Secp256r1) adds padding to reach 8-byte alignment:
Temporary sub-key for automated agents (like a session token).
- Seeds:
[b"session", wallet_pubkey, session_key] - Data Structure:
#[repr(C, align(8))] #[derive(NoPadding)] pub struct SessionAccount { pub discriminator: u8, pub bump: u8, pub _padding: [u8; 6], pub wallet: Pubkey, pub session_key: Pubkey, pub expires_at: u64, // Absolute Slot Height }
- Initializes
WalletAccount,Vault, and the firstAuthority(Owner). - Follows the Transfer-Allocate-Assign pattern to prevent pre-funding DoS attacks.
- Authentication:
- Ed25519: Standard Instruction Introspection.
- Secp256r1:
- Verify
SlotHasheshistory to ensure the signedcurrent_slotis within 150 blocks of the exact current network slot. - Reconstruct
clientDataJsonusing thatcurrent_slot. - Verify Signature against
sha256(clientDataJson + authData).
- Verify
- Session:
- Verify
session.wallet == wallet. - Verify
current_slot <= session.expires_at. - Verify
session_keyis a valid Ed25519 signer on the transaction.
- Verify
- Decompression: Expands
CompactInstructionsand callsinvoke_signedwith Vault seeds across all requested target programs.
- Auth: Requires
Role::AdminorRole::Owner. - Action: Derives the correct Session PDA and sets
expires_atto a future slot height (u64).
program/src/
├── auth/
│ ├── ed25519.rs # Native signer verification
│ ├── secp256r1/
│ │ ├── mod.rs # Passkey entrypoint
│ │ ├── nonce.rs # SlotHashes verification logic
│ │ ├── slothashes.rs# Sysvar memory-parsing
│ │ └── webauthn.rs # ClientDataJSON reconstruction
├── processor/ # Handlers: create_wallet, manage_authority, etc.
├── state/ # NoPadding definitions (Wallet, Authority, Session)
├── utils.rs # Protections (stack_height, dos_prevention)
└── lib.rs # Entrypoint & routing