All articles
solanarustanchorquasar

Rust + Anchor + Quasar: the standard Solana program stack in 2026

Solana programs are Rust. Anchor handles boilerplate. Quasar is the in-test cluster harness. Here's the canonical workflow from cargo new to mainnet deploy.

New Solana program authors invariably converge on the same stack within a week: Rust for the program, Anchor for the ergonomic layer, and a fast test harness for the integration tests that would otherwise be unbearable against solana-test-validator. The harness used to be Mocha + solana-test-validator; increasingly it's LiteSVM or Quasar.

This article is the opinionated path through the standard stack — cargo new through mainnet deploy.

The shape of a project

text
my-program/
├── Anchor.toml              # programs, cluster, wallet, scripts
├── Cargo.toml               # workspace
├── programs/
│   └── my-program/
│       ├── Cargo.toml
│       └── src/
│           ├── lib.rs       # entrypoint + #[program] module
│           ├── instructions/
│           │   ├── mod.rs
│           │   ├── initialize.rs
│           │   └── transfer.rs
│           ├── state/
│           │   ├── mod.rs
│           │   └── vault.rs
│           └── errors.rs
├── tests/
│   └── my-program.ts        # Mocha/Anchor TS tests
├── target/
│   ├── deploy/
│   │   ├── my_program.so    # compiled BPF binary
│   │   └── my_program-keypair.json
│   └── idl/
│       └── my_program.json  # generated IDL

The minimum Anchor program

rust
use anchor_lang::prelude::*;

declare_id!("My111111111111111111111111111111111111111");

#[program]
pub mod my_program {
    use super::*;

    pub fn initialize(ctx: Context<Initialize>, name: String) -> Result<()> {
        let vault = &mut ctx.accounts.vault;
        vault.owner = ctx.accounts.payer.key();
        vault.name = name;
        vault.balance = 0;
        Ok(())
    }

    pub fn deposit(ctx: Context<Deposit>, amount: u64) -> Result<()> {
        ctx.accounts.vault.balance = ctx
            .accounts.vault.balance
            .checked_add(amount)
            .ok_or(MyError::Overflow)?;
        Ok(())
    }
}

#[derive(Accounts)]
#[instruction(name: String)]
pub struct Initialize<'info> {
    #[account(init, payer = payer, space = 8 + Vault::INIT_SPACE,
              seeds = [b"vault", payer.key().as_ref(), name.as_bytes()], bump)]
    pub vault: Account<'info, Vault>,
    #[account(mut)]
    pub payer: Signer<'info>,
    pub system_program: Program<'info, System>,
}

#[derive(Accounts)]
pub struct Deposit<'info> {
    #[account(mut, has_one = owner)]
    pub vault: Account<'info, Vault>,
    pub owner: Signer<'info>,
}

#[account]
#[derive(InitSpace)]
pub struct Vault {
    pub owner: Pubkey,
    #[max_len(32)]
    pub name: String,
    pub balance: u64,
}

#[error_code]
pub enum MyError {
    #[msg("arithmetic overflow")]
    Overflow,
}

Anchor generates: the discriminator-based dispatcher, account validation (has_one, seeds, init rent payment), serialization, the IDL JSON, and the TypeScript client.

Building

sh
anchor build
# Compiles programs/* to target/deploy/*.so + emits target/idl/*.json

anchor idl init -f target/idl/my_program.json <program_id>
# (Optional) writes the IDL to the on-chain IDL account so explorers can decode txs

anchor test
# Spins up solana-test-validator, deploys the program, runs tests/*.ts against it

Tests — the slow vs fast options

Default (Anchor): Mocha + solana-test-validator. Each anchor test takes ~10-30s to spin up the validator. Fine for a couple of tests, painful at 100+.

Fast (LiteSVM): in-process SVM, no validator. Same instruction dispatch, microsecond-fast. The default for unit and integration tests in 2026:

typescript
import { LiteSVM } from "litesvm"
import { PublicKey } from "@solana/web3.js"

const svm = new LiteSVM()
svm.addProgramFromFile(programId, "target/deploy/my_program.so")
svm.airdrop(payer.publicKey, 1_000_000_000n)

const ix = /* build your instruction */
const result = svm.sendTransaction(new Transaction().add(ix).sign(payer))

expect(result.err).toBeNull()
const vault = svm.getAccount(vaultPda)
// assertions on vault.data ...

Mainnet-realistic (Surfpool): when you need real Mainnet state in the test (real USDC mint, real oracle accounts), use Surfpool with a fork. Slower than LiteSVM, far more realistic than vanilla solana-test-validator. See the Surfpool article.

Deploying to devnet → mainnet

sh
# Switch CLI to devnet, deploy
solana config set --url https://api.devnet.solana.com
anchor deploy --provider.cluster devnet
# Output: program deployed at <program_id>

# Run your tests against the devnet deploy
anchor test --skip-deploy --provider.cluster devnet

# Once happy, switch to mainnet
solana config set --url https://api.mainnet-beta.solana.com
# Pre-fund the deploy wallet (~3 SOL for a moderate program)
solana airdrop 3   # only works on devnet; transfer SOL in for mainnet

anchor deploy --provider.cluster mainnet
# Or for explicit upgrade authority:
solana program deploy target/deploy/my_program.so \
  --program-id target/deploy/my_program-keypair.json \
  --upgrade-authority <your-multisig-or-key>

Upgrade authority — set it carefully

First-time deploys default to making the deploy wallet the upgrade authority. Production programs should hand this off immediately:

sh
# Transfer upgrade authority to a Squads multisig
solana program set-upgrade-authority <program_id> \
  --new-upgrade-authority <squads_vault_pda> \
  --skip-new-upgrade-authority-signer-check

# Or freeze the program (irrevocable!)
solana program set-upgrade-authority <program_id> --final

See the Squads article for the recommended pattern.

Where Quasar fits

quasar in this stack name historically refers to rapid in-memory cluster harnesses for testing — the lineage runs through bankrun → LiteSVM → newer derivatives. The constant is: skip solana-test-validator for anything past basic smoke tests; use an in-process SVM for speed.

The opinionated stack, summarised

text
Language:        Rust (stable channel, edition 2021)
Framework:       Anchor 0.31+ (or Pinocchio for hot paths)
Local tests:     LiteSVM for fast, Surfpool for Mainnet-realistic
Devnet tests:    anchor test --provider.cluster devnet
TS client:       codama-generated against @solana/kit
Frontend:        gill (Next.js / React) or kit-squared (SvelteKit)
Deploy auth:     Squads V4 multisig
CI:              GitHub Actions → cargo test + anchor test (LiteSVM)

References

Rust + Anchor + a fast SVM harness is the path 90% of Solana program authors land on. Layer in Pinocchio for hot paths, Squads for upgrade authority, and the stack scales to production.