Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).

### Added

- End-to-end vitest tests for session-action enforcement (`tests-sdk/tests/12-actions.test.ts`, 9 cases): `programWhitelist` allow + reject (3021), `programBlacklist` allow + reject (3022), `solMaxPerTx` allow at-cap + reject over-cap (3023), `solLimit` lifetime budget exhaustion (3024), and combined-rules enforcement. Runs against a live `solana-test-validator` with the foundation binary loaded and uses `@lazorkit/sdk-legacy`'s `Actions` builder to dogfood the full encode → on-chain enforce path.
- `docs/audit/` artifacts for an Accretion delta-audit follow-up: `DELTA_BRIEF.md` summarises the changes from the previous audited baseline by phase with explicit audit asks; `program-src.diff` is the full unified diff of `program/`; `program-src.diff.stat` is a per-file changed-line summary; `upstream-parity.txt` reports byte-identity vs the already-audited `lazorkit-protocol` per file (13/19 changed files identical).
- Local git tags `audit-baseline-2026-02-accretion` (previous Accretion-audited state, commit `d1eaaeb`) and `audit-pending-v1` (the current consolidated state ready for delta review).
- Session action permissions: 8 immutable permission rules attachable at session creation — `SolLimit`, `SolRecurringLimit`, `SolMaxPerTx`, `TokenLimit`, `TokenRecurringLimit`, `TokenMaxPerTx`, `ProgramWhitelist`, `ProgramBlacklist`. Action discriminators (1, 2, 3, 4, 5, 6, 10, 11) and the 11-byte header layout match `lazorkit-protocol` so the unified SDK can encode actions identically for both builds.
- `SessionAccount` is now variable-size: a session can carry a trailing action buffer (max 16 actions, ≤ 2048 bytes) validated at creation time.
- `CreateSession` instruction data accepts the new `[actions_len: u16][actions: N]` extension after the legacy 40-byte args; old 40-byte clients continue to work via the legacy parser branch.
Expand Down Expand Up @@ -52,7 +55,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
- Odometer counter replay protection for Secp256r1 (monotonic u32 per authority)
- program_id included in challenge hash (cross-program replay prevention)
- rpId stored on authority account at creation (saves ~14 bytes per transaction)
- TypeScript SDK (`sdk/solita-client`) with Solita code generation
- TypeScript SDK: standardised on `@lazorkit/sdk-legacy` (lives in sibling `lazorkit-protocol` repo); the in-tree `sdk/solita-client` has been removed
- Integration + security test suite (`tests-sdk/`) with 56 tests across 11 files
- Benchmark script for CU and transaction size measurements
- CompactInstructions accounts hash for anti-reordering protection
Expand All @@ -67,6 +70,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).

### Changed

- Secp256r1 auth payload format: replaces the older `typeAndFlags` byte at `auth_payload[13]` with full raw `clientDataJSON` embedded in the payload. The on-chain auth verifier now parses the JSON directly rather than reconstructing it from `typeAndFlags + rpId`. Aligns with `lazorkit-protocol` byte-for-byte and is required for binary-swap compatibility at the shared mainnet slot.
- Secp256r1 authority on-chain layout: replaces the previously stored variable-length raw `rpId` with a precomputed 32-byte `rpIdHash` (SHA-256 digest computed at registration). New layout: `header(48) + cred_hash(32) + pubkey(33) + rpIdHash(32) = 145 bytes`. Saves one `sol_sha256` syscall per `Execute`. Existing wallets created on the upstream commercial binary remain readable after binary swap.
- Shank IDL declarations on the `ProgramIx` enum (account metadata: `writable` modifiers, account positions, descriptions) resynced with `lazorkit-protocol`. Five fee-related variants (disc 10–14: `InitializeProtocol`, `UpdateProtocol`, `RegisterPayer`, `WithdrawTreasury`, `InitializeTreasuryShard`) stripped — `program-v2` keeps disc 0–9 only. Runtime not affected (`@lazorkit/sdk-legacy` uses hand-written builders rather than the generated IDL).
- SDK API: unified all methods via discriminated unions (breaking: removed `createWalletEd25519`, `createWalletSecp256r1`, `addAuthoritySecp256r1`, `removeAuthoritySecp256r1`, `executeEd25519`, `executeSecp256r1`, `executeSession`, `createSessionSecp256r1`, `transferOwnershipSecp256r1`, `authorizeSecp256r1`)
- SDK API: all methods now return `{ instructions: TransactionInstruction[]; ...extraPdas }` consistently
- SDK API: `createSession` now takes `sessionKey: PublicKey` instead of `Uint8Array`
Expand All @@ -87,6 +93,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).

### Fixed

- `tests-sdk` integration tests now pass `PROGRAM_ID` explicitly to the `LazorKitClient` constructor. `@lazorkit/sdk-legacy`'s URL-based program-ID inference defaulted localhost to the commercial devnet ID (`4h3X…`); against a local validator loading the foundation binary at the keypair's pubkey this caused all txs to fail with "Attempt to load a program that does not exist". `tests/common.ts` now resolves `PROGRAM_ID` from (1) `PROGRAM_ID` env override, (2) the keypair file at `target/deploy/lazorkit_program-keypair.json`, or (3) the foundation devnet fallback `FLb7…`.
- `tests-sdk/tests/08-deferred.test.ts` builds the `Authorize` `signed_payload` as `instructions_hash || accounts_hash || expiry_offset (u16 LE)` to match what the on-chain verifier hashes. The test code was missing the 2-byte expiry buffer at all 6 sign sites, causing all 7 deferred tests to fail with `InvalidMessageHash` (3005). After the fix, all 65 vitest E2E tests pass against a live validator.
- Authorize signed payload now includes `expiry_offset` (66 bytes total), preventing relayers from modifying the expiry window
- `sol_assert_bytes_eq` now uses the `len` parameter instead of `left.len()` (latent OOB read on-chain)
- `reclaim_deferred` uses `checked_add` for lamports (consistent with `execute_deferred` and `manage_authority`)
Expand Down
27 changes: 20 additions & 7 deletions DEVELOPMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,17 @@ This document outlines the standard procedures for building, deploying, and test

```
/program Rust smart contract (pinocchio, zero-copy)
/sdk/solita-client TypeScript SDK (Solita-generated + hand-written utils)
/tests-sdk Integration tests (vitest, @solana/web3.js v1)
/tests-sdk Integration tests (vitest, @lazorkit/sdk-legacy)
/scripts Build/deploy automation
/audits Audit reports
/no-padding Custom NoPadding derive macro
/assertions Custom assertion helpers

The TypeScript SDK lives in the sibling `lazorkit-protocol` repo at
`sdk/sdk-legacy/` and is published to npm as `@lazorkit/sdk-legacy`. The
same SDK transparently handles both this build (program-v2, no fees) and
the commercial build — it probes ProtocolConfig on first use and
conditionally appends fee accounts.
```

## Core Workflows
Expand All @@ -38,8 +43,9 @@ cargo build-sbf --features devnet
cargo build-sbf --features mainnet
```

The convenience script `./scripts/build-all.sh <devnet|mainnet>` builds, generates
the IDL, and regenerates the SDK in one shot.
The convenience script `./scripts/build-all.sh <devnet|mainnet>` builds and
regenerates the IDL in one shot. SDK regeneration is no longer needed —
`@lazorkit/sdk-legacy` is hand-written and lives in the sibling repo.

### B. Run Rust Tests

Expand All @@ -60,13 +66,20 @@ PROGRAM_ID=$(solana-keygen pubkey ../target/deploy/lazorkit_program-keypair.json
shank idl -o . --out-filename idl.json -p "$PROGRAM_ID"
```

### D. SDK Generation (using Solita)
### D. SDK

`@lazorkit/sdk-legacy` is hand-written (no codegen) and lives in the
sibling `lazorkit-protocol` repo at `sdk/sdk-legacy/`. To use it locally:

```bash
cd sdk/solita-client && node generate.mjs
# In a sibling checkout: /Users/.../lazorkit-protocol/sdk/sdk-legacy
npm install && npm run build

# Then in this repo's tests-sdk (already configured via `file:` link):
cd tests-sdk && npm install
```

The generate.mjs script reads the Shank IDL, enriches it with accounts/errors/types, and runs Solita to produce TypeScript code in `src/generated/`.
Once published to npm, consumers do `npm install @lazorkit/sdk-legacy`.

### E. Running Integration Tests

Expand Down
17 changes: 7 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,7 @@ program/src/ Rust smart contract (pinocchio, zero-copy)
auth/ Ed25519 + Secp256r1/WebAuthn authentication
processor/ 9 instruction handlers
state/ Account data structures (NoPadding)
sdk/solita-client/ TypeScript SDK (Solita-generated + hand-written utils)
src/generated/ Auto-generated instructions, accounts, errors
src/utils/ Instruction builders, PDA helpers, signing utils
tests-sdk/ Integration tests (vitest, 56 tests)
tests-sdk/ Integration tests (vitest, 56 tests, uses @lazorkit/sdk-legacy)
docs/ Architecture, cost analysis
audits/ Audit reports
```
Expand All @@ -120,14 +117,14 @@ cargo build-sbf
### Install SDK

```bash
npm install @lazorkit/solita-client
npm install @lazorkit/sdk-legacy
```

### Create a Wallet

```typescript
import { Connection } from '@solana/web3.js';
import { LazorKitClient } from '@lazorkit/solita-client';
import { LazorKitClient } from '@lazorkit/sdk-legacy';
import * as crypto from 'crypto';

const connection = new Connection('https://api.devnet.solana.com');
Expand All @@ -148,7 +145,7 @@ const { instructions, walletPda, vaultPda } = client.createWallet({
### Transfer SOL

```typescript
import { secp256r1 } from '@lazorkit/solita-client';
import { secp256r1 } from '@lazorkit/sdk-legacy';

// Just payer, wallet, signer, recipient, amount -- nothing else
const { instructions } = await client.transferSol({
Expand All @@ -174,7 +171,7 @@ const { instructions } = await client.execute({
});
```

See [sdk/solita-client/README.md](sdk/solita-client/README.md) for full API reference.
See the [@lazorkit/sdk-legacy README](https://github.com/lazor-kit/lazorkit-protocol/tree/main/sdk/sdk-legacy) for full API reference. The same SDK transparently handles both this build (program-v2, no fees) and the commercial build (lazorkit-protocol, with fees) — it probes ProtocolConfig on first use and conditionally appends fee accounts.

---

Expand All @@ -199,7 +196,7 @@ See [DEVELOPMENT.md](DEVELOPMENT.md) for full development workflow.

## Security

LazorKit V2 has been audited by **Accretion** (Solana Foundation funded).
LazorKit V2 has been audited by **Accretion**.

**Status**: 17/17 security issues resolved

Expand All @@ -222,7 +219,7 @@ Report vulnerabilities via [SECURITY.md](SECURITY.md).
|---|---|
| [Architecture](docs/Architecture.md) | Account structures, security mechanisms, instruction reference |
| [Costs](docs/Costs.md) | CU benchmarks, rent costs, transaction size analysis |
| [SDK API](sdk/solita-client/README.md) | TypeScript SDK reference |
| [@lazorkit/sdk-legacy](https://github.com/lazor-kit/lazorkit-protocol/tree/main/sdk/sdk-legacy) | TypeScript SDK reference |
| [Development](DEVELOPMENT.md) | Build, test, deploy workflow |
| [Contributing](CONTRIBUTING.md) | How to contribute |
| [Security](SECURITY.md) | Vulnerability reporting |
Expand Down
4 changes: 2 additions & 2 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ If you discover a security vulnerability in LazorKit, please report it responsib
The following are in scope:

- On-chain Solana program (`program/src/`)
- TypeScript SDK (`sdk/solita-client/`)
- TypeScript SDK (`@lazorkit/sdk-legacy`, lives in sibling `lazorkit-protocol` repo)
- PDA derivation and signature verification logic
- Replay protection mechanisms

Expand All @@ -31,7 +31,7 @@ The following are out of scope:

## Audit Status

LazorKit V2 has been audited by Accretion (Solana Foundation funded).
LazorKit V2 has been audited by Accretion.

**Status**: 17/17 security issues resolved

Expand Down
18 changes: 5 additions & 13 deletions docs/Architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -335,18 +335,10 @@ program/
utils.rs PDA initialization, stack_height check
error.rs AuthError enum (3001-3018)
entrypoint.rs Instruction routing
sdk/solita-client/
src/
generated/ Solita-generated instructions, accounts, errors
utils/
instructions.ts Low-level instruction builders
client.ts LazorKitClient high-level API (unified)
types.ts Discriminated union signer types + helper constructors
signing.ts Secp256r1 signing utilities
compact.ts CompactInstruction layout builder
pdas.ts PDA derivation helpers
secp256r1.ts Challenge hash + auth payload builders
packing.ts CompactInstruction packing
errors.ts Error code mapping
tests-sdk/ Integration + security tests (vitest, 56 tests)
```

The TypeScript SDK lives outside this repo: `@lazorkit/sdk-legacy` (in
sibling `lazorkit-protocol` repo at `sdk/sdk-legacy/`). Same SDK works
against this build (foundation, no fee) and the commercial build —
probes ProtocolConfig at runtime and conditionally appends fee accounts.
Loading
Loading