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
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,24 @@ All notable changes to this repository are documented here.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).

## [2026-07-11] - Discoverability and FAQ pass

### Fixed

- Quasar CI broke repo-wide when `quasar-svm`'s HEAD (`c63afd2`, "sbpf v3") moved to `solana-program-runtime` 4.1 / `solana-address` 2.6, which cannot co-resolve with the pinned `quasar-lang` rev `623bb70` (needs `solana-address` <2.6). Pinned `quasar-svm` to `cb7565d` (the last rev before the bump) in every Quasar example that pins `quasar-lang`, matching the pin `prop-amm` already carried. `basics/pyth` and the three `compression` Quasar examples float both dependencies and are left as-is.

### Added

- FAQ sections, written as the questions people actually ask, in the root README and every finance example's `anchor/` README.
- `llms.txt` at the repository root: a summary and link manifest for LLM crawlers and answer engines.
- `docs/example-readme-template.md`, the example-README template that `CONTRIBUTING.md` referenced but which did not exist. It documents the H1 convention and the definition-first opener.

### Changed

- Every finance example README now titles itself `# Solana <Example> (<Framework>)` (e.g. `# Solana Escrow (Anchor)`) and opens with a self-contained definition that names Solana, so each example page stands alone in search results.
- The root README states its toolchain currency explicitly (Anchor 1.1, LiteSVM, July 2026) with a pointer to this changelog.
- `CONTRIBUTING.md` style rules now include the README H1 naming convention and the no-em-dash rule.

## [2026-07-10] - Failed fundraisers can be retired

### Added
Expand Down
3 changes: 2 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ Also update [CHANGELOG.md](./CHANGELOG.md) when you ship user-visible changes.

Write American English in prose (e.g. "behavior", "initialize", "favor"). Code identifiers stay as-is.

- One H1 per markdown file.
- One H1 per markdown file. Example READMEs title it `# Solana <Example> (<Framework>)`, e.g. `# Solana Escrow (Anchor)`.
- No em-dashes in prose. Use a colon, comma, or a new sentence.
- Fenced code blocks include a language tag (` ```rust `, ` ```typescript `, ` ```bash `, ` ```toml `).
- Link canonical Solana terms to the [terminology page](https://solana.com/docs/references/terminology) on first mention in READMEs.

Expand Down
32 changes: 29 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

_Solana program examples ('smart contracts') in Anchor, Quasar, Pinocchio, native Rust, and sBPF assembly. Focused on financial software ('DeFi'), plus the basics, tokens, Token Extensions, state compression, and more._

Working, tested, up-to-date examples of common Solana programs (what other chains call smart contracts), maintained by [Quicknode](https://www.quicknode.com/chains/solana). Every example builds and passes CI on a current toolchain — **Anchor 1.1**, the current multi-file program layout (one file per instruction handler, account type, etc), and [LiteSVM](https://github.com/LiteSVM/litesvm) tests rather than the older `solana-test-validator` / web3.js stack.
Working, tested, up-to-date examples of common Solana programs (what other chains call smart contracts), maintained by [Quicknode](https://www.quicknode.com/chains/solana). Current as of July 2026 (see [CHANGELOG.md](./CHANGELOG.md)): every example builds and passes CI on **Anchor 1.1**, the current multi-file program layout (one file per instruction handler, account type, etc), and [LiteSVM](https://github.com/LiteSVM/litesvm) tests rather than the older `solana-test-validator` / web3.js stack.

[![Anchor](../../actions/workflows/anchor.yml/badge.svg)](../../actions/workflows/anchor.yml) [![Quasar](../../actions/workflows/quasar.yml/badge.svg)](../../actions/workflows/quasar.yml) [![Pinocchio](../../actions/workflows/pinocchio.yml/badge.svg)](../../actions/workflows/pinocchio.yml) [![Native](../../actions/workflows/native.yml/badge.svg)](../../actions/workflows/native.yml) [![ASM](../../actions/workflows/solana-asm.yml/badge.svg)](../../actions/workflows/solana-asm.yml)

Expand Down Expand Up @@ -59,7 +59,7 @@ An exchange with no order book: swaps fill instantly against a shared liquidity

### Prop AMM

A **proprietary AMM**: a market-making firm funds a venue with its own capital and quotes both sides of it, selling the base token at the oracle price plus a spread and buying it back at the oracle price minus the spread. No pricing curve, no liquidity providers, no pool shares the operator is the only capital in the market, can re-quote or pull its quotes at will, and earns the spread instead of a fee. Because the price comes from an oracle rather than the pool's balances, trades have no price impact and nothing to sandwich. This is the design behind venues like Lifinity, SolFi, and HumidiFi, which fill most Solana swap volume through Jupiter routing.
A **proprietary AMM**: a market-making firm funds a venue with its own capital and quotes both sides of it, selling the base token at the oracle price plus a spread and buying it back at the oracle price minus the spread. No pricing curve, no liquidity providers, no pool shares: the operator is the only capital in the market, can re-quote or pull its quotes at will, and earns the spread instead of a fee. Because the price comes from an oracle rather than the pool's balances, trades have no price impact and nothing to sandwich. This is the design behind venues like Lifinity, SolFi, and HumidiFi, which fill most Solana swap volume through Jupiter routing.

[⚓ Anchor](./finance/prop-amm/anchor) [💫 Quasar](./finance/prop-amm/quasar)

Expand All @@ -77,7 +77,7 @@ Parimutuel (pooled) prediction market - an admin opens an event with multiple ou

### Perpetual Futures

A perpetual futures exchangea venue for making leveraged bets on an asset's price without ever owning the asset. Traders post collateral and open a **long** (betting the price rises) or **short** (betting it falls) sized up to several times their collateral; their profit or loss tracks the price move and is paid in the collateral token. Rather than matching buyers to sellers, every trade is against a shared **liquidity pool** that other users fund and that is the counterparty to all of it the pool pays winners and keeps losers' collateral, and its providers earn the trading and funding fees in return. The price comes from an oracle, positions accrue a funding fee over time, and anyone can **liquidate** a position whose collateral can no longer cover its loss. This is the design behind venues like Jupiter Perpetuals and GMX.
A perpetual futures exchange: a venue for making leveraged bets on an asset's price without ever owning the asset. Traders post collateral and open a **long** (betting the price rises) or **short** (betting it falls) sized up to several times their collateral; their profit or loss tracks the price move and is paid in the collateral token. Rather than matching buyers to sellers, every trade is against a shared **liquidity pool** that other users fund and that is the counterparty to all of it: the pool pays winners and keeps losers' collateral, and its providers earn the trading and funding fees in return. The price comes from an oracle, positions accrue a funding fee over time, and anyone can **liquidate** a position whose collateral can no longer cover its loss. This is the design behind venues like Jupiter Perpetuals and GMX.

[⚓ Anchor](./finance/perpetual-futures/anchor) [💫 Quasar](./finance/perpetual-futures/quasar)

Expand Down Expand Up @@ -385,6 +385,32 @@ Generate an IDL from a native Rust program with [Shank](https://github.com/metap

[🦀 Native](./tools/shank-and-codama/native)

## FAQ

### Is a Solana program the same as a smart contract?

Yes. "Program" is Solana's term for what other chains call a smart contract: code deployed onchain that holds state in accounts and executes instructions. Everything in this repository is a Solana program.

### How do I build an escrow on Solana?

Start with the [escrow example](./finance/escrow/anchor/), the best first finance program to learn: one state PDA, one vault, and three instruction handlers that swap two tokens atomically. There is also a [30-minute video walkthrough](https://www.youtube.com/watch?v=B5eBWWQfQuM) building it from scratch.

### How do I test a Solana program without running a validator?

Use [LiteSVM](https://www.anchor-lang.com/docs/testing/litesvm): Rust integration tests that run the program in-process, orders of magnitude faster than `solana-test-validator`. Every example in this repository tests this way, and `anchor init` scaffolds it by default since Anchor 1.0.

### What is the difference between Anchor, Quasar, Pinocchio, and native Rust?

[Anchor](https://www.anchor-lang.com/) is the most popular Solana framework, generating account validation and serialization from declarative constraints. [Quasar](https://quasar-lang.com/docs) offers Anchor-like ergonomics with zero-copy, `no_std` performance and smaller binaries. [Pinocchio](https://github.com/anza-xyz/pinocchio) is a zero-allocation library for hand-rolled programs, and native Rust uses Solana's crates directly with no framework. Most examples here ship several variants of the same program so you can compare.

### What is the best way to learn Solana finance programming?

Work through the [finance examples](#financial-software-defi) in order of complexity: [escrow](./finance/escrow/anchor/), then [token swap AMM](./finance/token-swap/anchor/), [order book](./finance/order-book/anchor/), [lending](./finance/lending/anchor/), and [perpetual futures](./finance/perpetual-futures/anchor/). Each README explains the financial mechanics in plain terms before the code.

### Are these examples production-ready?

They are teaching examples: every one builds and passes CI, and the finance programs additionally carry [Kani](https://github.com/model-checking/kani) formal-verification proofs of their money math. None are audited or deployed to mainnet, so treat them as reference implementations to learn from, not code to deploy as-is.

## Acknowledgements

Big thanks to Joe Caulfield and Solana Foundation for originally creating this repository.
Expand Down
6 changes: 5 additions & 1 deletion basics/account-data/quasar/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,11 @@ solana-instruction = { version = "3.2.0" }
[dev-dependencies]
# Not using the generated client: it depends on quasar_lang::client::DynBytes
# which isn't in the published crate yet. Tests build instruction data manually.
quasar-svm = { git = "https://github.com/blueshift-gg/quasar-svm" }
# Pinned: quasar-svm HEAD (c63afd2, "sbpf v3") moved to solana-program-runtime
# 4.1 / solana-address 2.6, which cannot co-resolve with the quasar-lang rev
# pinned above (needs solana-address <2.6). cb7565d is the last rev before the
# bump. Unpin together with the quasar-lang pin once upstream is consistent again.
quasar-svm = { git = "https://github.com/blueshift-gg/quasar-svm", rev = "cb7565d" }
solana-account = { version = "3.4.0" }
solana-address = { version = "2.2.0", features = ["decode"] }
solana-instruction = { version = "3.2.0", features = ["bincode"] }
Expand Down
6 changes: 5 additions & 1 deletion basics/checking-accounts/quasar/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ solana-instruction = { version = "3.2.0" }

[dev-dependencies]
quasar-checking-accounts-client = { path = "target/client/rust/quasar-checking-accounts-client" }
quasar-svm = { git = "https://github.com/blueshift-gg/quasar-svm" }
# Pinned: quasar-svm HEAD (c63afd2, "sbpf v3") moved to solana-program-runtime
# 4.1 / solana-address 2.6, which cannot co-resolve with the quasar-lang rev
# pinned above (needs solana-address <2.6). cb7565d is the last rev before the
# bump. Unpin together with the quasar-lang pin once upstream is consistent again.
quasar-svm = { git = "https://github.com/blueshift-gg/quasar-svm", rev = "cb7565d" }
solana-account = { version = "3.4.0" }
solana-address = { version = "2.2.0", features = ["decode"] }
solana-instruction = { version = "3.2.0", features = ["bincode"] }
Expand Down
6 changes: 5 additions & 1 deletion basics/close-account/quasar/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,11 @@ quasar-lang = { git = "https://github.com/blueshift-gg/quasar", rev = "623bb70"
solana-instruction = { version = "3.2.0" }

[dev-dependencies]
quasar-svm = { git = "https://github.com/blueshift-gg/quasar-svm" }
# Pinned: quasar-svm HEAD (c63afd2, "sbpf v3") moved to solana-program-runtime
# 4.1 / solana-address 2.6, which cannot co-resolve with the quasar-lang rev
# pinned above (needs solana-address <2.6). cb7565d is the last rev before the
# bump. Unpin together with the quasar-lang pin once upstream is consistent again.
quasar-svm = { git = "https://github.com/blueshift-gg/quasar-svm", rev = "cb7565d" }
solana-account = { version = "3.4.0" }
solana-address = { version = "2.2.0", features = ["decode"] }
solana-instruction = { version = "3.2.0", features = ["bincode"] }
Expand Down
6 changes: 5 additions & 1 deletion basics/counter/quasar/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ solana-instruction = { version = "3.2.0" }

[dev-dependencies]
quasar-counter-client = { path = "target/client/rust/quasar-counter-client" }
quasar-svm = { git = "https://github.com/blueshift-gg/quasar-svm" }
# Pinned: quasar-svm HEAD (c63afd2, "sbpf v3") moved to solana-program-runtime
# 4.1 / solana-address 2.6, which cannot co-resolve with the quasar-lang rev
# pinned above (needs solana-address <2.6). cb7565d is the last rev before the
# bump. Unpin together with the quasar-lang pin once upstream is consistent again.
quasar-svm = { git = "https://github.com/blueshift-gg/quasar-svm", rev = "cb7565d" }
solana-account = { version = "3.4.0" }
solana-address = { version = "2.2.0", features = ["decode"] }
solana-instruction = { version = "3.2.0", features = ["bincode"] }
Expand Down
6 changes: 5 additions & 1 deletion basics/create-account/quasar/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ solana-instruction = { version = "3.2.0" }

[dev-dependencies]
quasar-create-account-client = { path = "target/client/rust/quasar-create-account-client" }
quasar-svm = { git = "https://github.com/blueshift-gg/quasar-svm" }
# Pinned: quasar-svm HEAD (c63afd2, "sbpf v3") moved to solana-program-runtime
# 4.1 / solana-address 2.6, which cannot co-resolve with the quasar-lang rev
# pinned above (needs solana-address <2.6). cb7565d is the last rev before the
# bump. Unpin together with the quasar-lang pin once upstream is consistent again.
quasar-svm = { git = "https://github.com/blueshift-gg/quasar-svm", rev = "cb7565d" }
solana-account = { version = "3.4.0" }
solana-address = { version = "2.2.0", features = ["decode"] }
solana-instruction = { version = "3.2.0", features = ["bincode"] }
Expand Down
6 changes: 5 additions & 1 deletion basics/cross-program-invocation/quasar/hand/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@ quasar-lang = { git = "https://github.com/blueshift-gg/quasar", rev = "623bb70"
solana-instruction = { version = "3.2.0" }

[dev-dependencies]
quasar-svm = { git = "https://github.com/blueshift-gg/quasar-svm" }
# Pinned: quasar-svm HEAD (c63afd2, "sbpf v3") moved to solana-program-runtime
# 4.1 / solana-address 2.6, which cannot co-resolve with the quasar-lang rev
# pinned above (needs solana-address <2.6). cb7565d is the last rev before the
# bump. Unpin together with the quasar-lang pin once upstream is consistent again.
quasar-svm = { git = "https://github.com/blueshift-gg/quasar-svm", rev = "cb7565d" }
solana-account = { version = "3.4.0" }
solana-address = { version = "2.2.0", features = ["decode"] }
solana-instruction = { version = "3.2.0", features = ["bincode"] }
Expand Down
6 changes: 5 additions & 1 deletion basics/cross-program-invocation/quasar/lever/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@ quasar-lang = { git = "https://github.com/blueshift-gg/quasar", rev = "623bb70"
solana-instruction = { version = "3.2.0" }

[dev-dependencies]
quasar-svm = { git = "https://github.com/blueshift-gg/quasar-svm" }
# Pinned: quasar-svm HEAD (c63afd2, "sbpf v3") moved to solana-program-runtime
# 4.1 / solana-address 2.6, which cannot co-resolve with the quasar-lang rev
# pinned above (needs solana-address <2.6). cb7565d is the last rev before the
# bump. Unpin together with the quasar-lang pin once upstream is consistent again.
quasar-svm = { git = "https://github.com/blueshift-gg/quasar-svm", rev = "cb7565d" }
solana-account = { version = "3.4.0" }
solana-address = { version = "2.2.0", features = ["decode"] }
solana-instruction = { version = "3.2.0", features = ["bincode"] }
Expand Down
6 changes: 5 additions & 1 deletion basics/favorites/quasar/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,11 @@ quasar-lang = { git = "https://github.com/blueshift-gg/quasar", rev = "623bb70"
solana-instruction = { version = "3.2.0" }

[dev-dependencies]
quasar-svm = { git = "https://github.com/blueshift-gg/quasar-svm" }
# Pinned: quasar-svm HEAD (c63afd2, "sbpf v3") moved to solana-program-runtime
# 4.1 / solana-address 2.6, which cannot co-resolve with the quasar-lang rev
# pinned above (needs solana-address <2.6). cb7565d is the last rev before the
# bump. Unpin together with the quasar-lang pin once upstream is consistent again.
quasar-svm = { git = "https://github.com/blueshift-gg/quasar-svm", rev = "cb7565d" }
solana-account = { version = "3.4.0" }
solana-address = { version = "2.2.0", features = ["decode"] }
solana-instruction = { version = "3.2.0", features = ["bincode"] }
Expand Down
6 changes: 5 additions & 1 deletion basics/hello-solana/quasar/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ solana-instruction = { version = "3.2.0" }

[dev-dependencies]
quasar-hello-solana-client = { path = "target/client/rust/quasar-hello-solana-client" }
quasar-svm = { git = "https://github.com/blueshift-gg/quasar-svm" }
# Pinned: quasar-svm HEAD (c63afd2, "sbpf v3") moved to solana-program-runtime
# 4.1 / solana-address 2.6, which cannot co-resolve with the quasar-lang rev
# pinned above (needs solana-address <2.6). cb7565d is the last rev before the
# bump. Unpin together with the quasar-lang pin once upstream is consistent again.
quasar-svm = { git = "https://github.com/blueshift-gg/quasar-svm", rev = "cb7565d" }
solana-account = { version = "3.4.0" }
solana-address = { version = "2.2.0", features = ["decode"] }
solana-instruction = { version = "3.2.0", features = ["bincode"] }
Expand Down
6 changes: 5 additions & 1 deletion basics/pda-rent-payer/quasar/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ solana-instruction = { version = "3.2.0" }

[dev-dependencies]
quasar-pda-rent-payer-client = { path = "target/client/rust/quasar-pda-rent-payer-client" }
quasar-svm = { git = "https://github.com/blueshift-gg/quasar-svm" }
# Pinned: quasar-svm HEAD (c63afd2, "sbpf v3") moved to solana-program-runtime
# 4.1 / solana-address 2.6, which cannot co-resolve with the quasar-lang rev
# pinned above (needs solana-address <2.6). cb7565d is the last rev before the
# bump. Unpin together with the quasar-lang pin once upstream is consistent again.
quasar-svm = { git = "https://github.com/blueshift-gg/quasar-svm", rev = "cb7565d" }
solana-account = { version = "3.4.0" }
solana-address = { version = "2.2.0", features = ["decode"] }
solana-instruction = { version = "3.2.0", features = ["bincode"] }
Expand Down
6 changes: 5 additions & 1 deletion basics/processing-instructions/quasar/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,11 @@ quasar-lang = { git = "https://github.com/blueshift-gg/quasar", rev = "623bb70"
solana-instruction = { version = "3.2.0" }

[dev-dependencies]
quasar-svm = { git = "https://github.com/blueshift-gg/quasar-svm" }
# Pinned: quasar-svm HEAD (c63afd2, "sbpf v3") moved to solana-program-runtime
# 4.1 / solana-address 2.6, which cannot co-resolve with the quasar-lang rev
# pinned above (needs solana-address <2.6). cb7565d is the last rev before the
# bump. Unpin together with the quasar-lang pin once upstream is consistent again.
quasar-svm = { git = "https://github.com/blueshift-gg/quasar-svm", rev = "cb7565d" }
solana-account = { version = "3.4.0" }
solana-address = { version = "2.2.0", features = ["decode"] }
solana-instruction = { version = "3.2.0", features = ["bincode"] }
Expand Down
6 changes: 5 additions & 1 deletion basics/program-derived-addresses/quasar/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ solana-instruction = { version = "3.2.0" }

[dev-dependencies]
quasar-program-derived-addresses-client = { path = "target/client/rust/quasar-program-derived-addresses-client" }
quasar-svm = { git = "https://github.com/blueshift-gg/quasar-svm" }
# Pinned: quasar-svm HEAD (c63afd2, "sbpf v3") moved to solana-program-runtime
# 4.1 / solana-address 2.6, which cannot co-resolve with the quasar-lang rev
# pinned above (needs solana-address <2.6). cb7565d is the last rev before the
# bump. Unpin together with the quasar-lang pin once upstream is consistent again.
quasar-svm = { git = "https://github.com/blueshift-gg/quasar-svm", rev = "cb7565d" }
solana-account = { version = "3.4.0" }
solana-address = { version = "2.2.0", features = ["decode"] }
solana-instruction = { version = "3.2.0", features = ["bincode"] }
Expand Down
Loading
Loading