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.

Share
devrels.xyz/a/76short link

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.

Keep reading

Get new articles in your inbox

Technical deep-dives on Solana tooling, infrastructure, and ecosystem. No noise.

Rust + Anchor + Quasar: the standard Solana program stack in 2026 | devrels.xyz