Skip to content

Protocol Stack

The on-chain foundation of VelaPay: Anchor programs, Token-2022 transfer hooks, and Arcium encrypted compute.


Core Toolchain

PieceChoiceVersionWhy
FrameworkAnchor0.32.1Account validation, IDL generation, client ergonomics. Last stable release before Anchor 1.0 breaking changes.
LanguageRust1.89.0+Required by Anchor 0.32 for Span::local_file stabilization in IDL building.
Token layerToken-2022 (spl-token-2022)10.0.0Transfer hooks, transfer fees, metadata pointer, non-transferable extension. Solana-native — no EVM equivalent.
Transfer hook interfacespl-transfer-hook-interface0.10.0Defines the Execute instruction discriminator and format that Token-2022 CPIs into.
Extra account resolutionspl-tlv-account-resolution0.11.1Resolves additional accounts for the hook's Execute instruction via ExtraAccountMetaList PDA.
Anchor SPL helpersanchor-spl0.32.1Token-2022 instruction helpers, CPI wrappers, extension constraints. Must match Anchor version.
Privacy computeArcium MXE0.9.3 clientEncrypted billing validation, usage metering, analytics. Circuits in encrypted-ixs/, artifacts in build/.
Solana CLIAgave2.3.0+Recommended by Anchor 0.32 release notes. Use agave-install, not deprecated solana-install.
JS client compat@coral-xyz/anchor0.32.1Generated from Anchor IDL. Must match program version.
Web3.js compat@solana/web3.jsv1.xAnchor TS client only supports v1. Kit migration at Anchor 1.0.

Why This Stack Matters (Piece by Piece)

Anchor gives account validation through #[account] constraints, IDL generation for the TypeScript client, and CPI ergonomics that would require significantly more unsafe code in native (Pinocchio) programs. The PDA schema for mandates, plans, and credentials is complex enough that Anchor's validation macros are essential.

Token-2022 transfer hooks are the enforcement mechanism. When a subscriber's USDC is transferred, the Token-2022 program calls the Vela transfer hook program. The hook reads the mandate PDA and validates amount, timing, and authority. An unauthorized pull fails at the validator level — the transfer literally cannot happen. This is structurally different from an allowance wrapper where a relayer can misbehave and the blockchain doesn't stop it.

Arcium MXE runs the billing logic on encrypted data. All billing decisions — balance checks, usage computation, tier evaluation — route through Arcium MPC clusters. No single Arx node sees plaintext. The merchant's dashboard decrypts analytics with their key; nobody else sees business metrics. This is what makes on-chain billing commercially viable for B2B SaaS.

LiteSVM replaces the deprecated bankrun/solana-bankrun. It provides an in-process Solana VM that runs orders of magnitude faster than solana-test-validator. This keeps the protocol test loop fast enough for iterative shipping.


Repo Shape

vela-protocol/
├── programs/
│   ├── vela-protocol/         # Main billing program (Anchor)
│   │   ├── src/
│   │   │   ├── lib.rs         # Program entry, instruction routing
│   │   │   ├── state/         # Account structs (Mandate, Plan, Credential, ProtocolConfig)
│   │   │   └── instructions/  # create_plan, subscribe, execute_pull, cancel, etc.
│   │   └── Cargo.toml
│   └── vela-transfer-hook/    # Dedicated transfer hook validator
│       ├── src/
│       │   └── lib.rs         # handler_transfer_hook — reads PullApproval, validates
│       └── Cargo.toml
├── encrypted-ixs/             # Arcium circuit source
│   └── billing/               # Encrypted mandate validation circuits
├── build/                     # Generated Arcium artifacts (not disposable)
├── tests/                     # Rust-side protocol tests (LiteSVM)
├── ts-tests/                  # TypeScript integration tests
│   └── *.test.ts              # E2E flows using anchor-litesvm 0.2.1 + litesvm 0.6.0
├── scripts/                   # Deploy, IDL management
├── Anchor.toml                # Program IDs, cluster, test config
├── Arcium.toml                # Arcium MXE configuration
└── Cargo.toml                 # Workspace root

Arcium Integration Details

The privacy layer is not a future feature — it's integrated from v1.1 onward.

Circuit Architecture

  • Source circuits live in encrypted-ixs/. These define the MPC computation: encrypted mandate validation (balance ≥ charge on ciphertext), usage metering, tier evaluation.
  • Build artifacts in build/ are the compiled Arcium outputs. These are part of the protocol delivery shape, not disposable build output. They should be version-controlled because they represent the integration surface with the Arcium MXE network.

Two-Phase Billing Pattern

Arcium computation is asynchronous and cannot run inside a transfer hook CPI. Vela uses a two-phase pattern:

  1. Phase 1 — Arcium pre-validation: Encrypted mandate data is sent to the MXE cluster. The cluster computes on ciphertext (is balance sufficient? is timing correct? is amount within bounds?) and stores a PullApproval PDA via callback.
  2. Phase 2 — Transfer hook consumption: When execute_pull triggers a Token-2022 transfer_checked, the hook reads the PullApproval PDA. If it exists and is valid, the transfer proceeds. If not, the transfer fails.

This is architecturally unique — no other project in the Colosseum corpus (5,400+ projects) combines Arcium with transfer hooks.

Fail-Closed Behavior

When Arcium is unavailable, pulls are blocked entirely. No fallback to plaintext. This is a deliberate design decision: privacy is the default, not a toggle. When the privacy layer is down, the system degrades to "safe" (no pulls), not to "transparent" (plaintext pulls).


Testing Infrastructure

Rust Tests (LiteSVM)

  • cargo test runs in-process VM tests
  • Tests individual instructions: create_plan, subscribe, execute_pull, cancel
  • Validates account constraints, PDA derivation, error cases
  • Orders of magnitude faster than solana-test-validator

TypeScript Integration Tests

  • bun test in ts-tests/
  • Uses anchor-litesvm 0.2.1 + litesvm 0.6.0 (npm packages)
  • LitesvmProvider as a drop-in replacement for AnchorProvider
  • Tests E2E flows: subscribe → credential minted → keeper pulls → cancel → credential burned
  • Runs against the same IDL that the SDK exports

When to Use What

Test TypeWhen to UseSpeed
cargo test (LiteSVM Rust)Unit testing individual instructionsSub-second
bun test (LiteSVM TS)Integration testing with Anchor clientSeconds
solana-test-validatorFinal E2E, devnet simulationMinutes (use sparingly)

Operational Note: Build Artifacts

The checked-in build artifacts under build/ are not disposable output. They are the compiled Arcium circuit artifacts that the protocol deployment depends on. Deleting them and regenerating requires the Arcium CLI and access to the correct MXE cluster configuration.

Treat them as part of the integration surface for the privacy layer. They should be version-controlled and included in any protocol deployment checklist.


Key Program Instructions

InstructionWhat It DoesAccounts
create_planMerchant registers a subscription plan (price, frequency, terms)Plan PDA, merchant signer
subscribeUser approves a Vela Mandate — scoped, time-limited, amount-capped authorizationMandate PDA, credential mint, subscriber signer
execute_pullKeeper or merchant triggers a billing pullMandate PDA, PullApproval PDA, token accounts
cancelSubscriber or merchant cancels a mandateMandate PDA, credential token
wrap_usdcConvert SPL USDC to Token-2022 wrapped USDCWrapped mint ATA, source ATA
unwrap_usdcConvert Token-2022 wrapped USDC back to SPLReverse of wrap

Token-2022 Extensions Used

ExtensionWherePurpose
Transfer HookWrapped USDC mint + Vela transfer hook programValidates every pull against mandate rules
Metadata PointerVela Credential NFTStores plan tier, start date, features on-chain
Non-TransferableVela Credential NFTSoulbound subscription proof (optional: merchant can enable transferable)
Transfer FeeWrapped USDC mint (planned)Built-in platform fee on every subscription payment

USDC Wrapping Strategy

Circle's USDC on Solana is the original SPL token, not Token-2022. Vela's mandate enforcement requires a Token-2022 mint because transfer hooks only fire on Token-2022 transfers. The solution:

  1. Wrapped USDC mint — a Token-2022 mint backed 1:1 by SPL USDC
  2. wrap_usdc instruction — user deposits SPL USDC, receives wrapped USDC
  3. unwrap_usdc instruction — user burns wrapped USDC, receives SPL USDC back
  4. SDK helper: wrapAndSubscribe() — combines wrap + subscribe in a single user flow

Early adopters should target protocols already issuing Token-2022 tokens (PYUSD, USDY, new stablecoin issuers defaulting to Token-2022) rather than assuming USDC compatibility. The medium-term bet is that new stablecoin issuers will default to Token-2022.


Deployment Checklist

StepCommandNotes
Build programanchor buildProduces .so bytecode in target/
Generate IDLanchor idlCopied to vela-sdk/idl/ for SDK consumption
Deploy to devnetanchor deploy --provider.cluster devnetProgram ID must match Anchor.toml
Verify on-chainvela status --network devnetCheck program ID and data accounts
Run integration testsbun test in ts-tests/Full E2E against devnet
Build Arcium artifactsArcium CLIOutputs to build/ — version-controlled

Internal knowledge base for the Vela Labs workspace.