This repository contains two Solana programs that implement two different market-maker models:
- AMM (
scale_amm): a standard on-chain automated market maker (Uniswap/Raydium-style). - VMM (
scale_vmm): a “pre-graduation” virtual market maker (pump.fun pre-graduation-style) that maintains pair-level ledger state without provisioning discrete liquidity pools, and graduates pairs to the AMM after a liquidity threshold is met.
This document tells Codex agents how to reason about the codebase, terminology, fee mechanics, and required update workflow.
A pair is the trading relationship between two mints:
tokenA_mintandtokenB_mint
Pairs exist in both AMM and VMM. A pair is the conceptual “market.”
A pool is an on-chain account/state bundle that holds reserves (liquidity) for a given pair inside the AMM program.
- AMM: pairs are realized as pools that hold real reserves and price is determined by the AMM invariant.
- VMM: there are no discrete pools; state is maintained at the pair level (ledger-style) and swap math derives from that state.
Rule of thumb:
- If you see reserves in token vaults / pool accounts → AMM pool.
- If you see pair-level counters/ledgers with no “pool vaults” semantics → VMM pair state.
What it is:
A typical on-chain DEX AMM program. Think Uniswap/Raydium.
Key properties:
- Independent program: it can create and manage pairs/pools on its own.
- Has pool-specific state & accounts (vaults/reserves).
- Swaps/liquidity operations are executed against pool reserves.
Pair creation paths:
- Direct AMM creation: create pairs/pools directly in AMM via AMM
create*methods. - VMM graduation helper:
create_from_vmm()can create an AMM pool from an existing VMM pair state.
What it is:
A “pre-graduation” market maker where there are no pools. It tracks pair state (ledger maintenance) and computes pricing/execution from that state.
Key properties:
- Dependent program: pairs are meant to graduate to AMM after threshold conditions.
- Maintains pair-level state rather than pool reserves.
- Graduation is a first-class lifecycle step.
A VMM pair graduates to an AMM pool when a liquidity threshold is met.
- The threshold is purely a liquidity number, e.g.
tokenA balance,reservesA, or similar numeric metric in VMM state. - Graduation results in creating an AMM pool/pair, typically via the AMM helper
create_from_vmm()(or equivalent graduation flow).
Agent requirement: when editing graduation logic, confirm:
- which exact numeric field constitutes the threshold metric,
- where it is updated,
- who is allowed to trigger graduation,
- how state is migrated/initialized in the AMM.
There are two fee types on both programs:
- Distributed to a single beneficiary wallet (the protocol owner beneficiary).
- The beneficiary can be changed independently for AMM and VMM.
- Changes are performed via the Authority wallet.
Agent requirement:
- Treat platform-fee recipient as privileged configuration.
- Ensure authority checks exist and are tested.
- Keep AMM/VMM config separation explicit (do not accidentally share config unless intentionally designed).
- Distributed to the individual pair/pool creator(s).
- The creator sets:
- fee bps,
- distribution across up to 5 wallets.
Agent requirement:
- Validate constraints (bps bounds, max wallet count = 5).
- Validate distribution totals (if applicable) and recipient uniqueness rules (if defined).
- Ensure fee calculations are deterministic and safe from rounding exploits.
When changing any behavior in either program:
-
Model correctness
- AMM changes must respect pool/reserve invariants and vault accounting.
- VMM changes must respect ledger-style state transitions and graduation conditions.
-
Fee correctness
- Confirm both platform and creator fees are applied exactly once.
- Confirm fee bps interpretation and rounding behavior.
- Confirm fee recipients are correct for the program (AMM vs VMM).
-
Security & safety
- Check signer/authority constraints.
- Check overflow/underflow, rounding, and edge-cases (0 liquidity, tiny swaps, max bps).
- Add explicit negative tests for unauthorized calls and invalid configs.
- Consider common Solana program risks (account spoofing, incorrect PDA derivations, missing ownership checks).
README.md(root): protocol-wide overview, repo usage, contributing, testing, SDK, scripts pointers.scale_amm/README.md: AMM-specific instructions, methods, accounts, invariants, fee behavior.scale_vmm/README.md: VMM-specific instructions, methods, state model, graduation, fee behavior.test/README.md: how tests are executed, checklist, and execution report conventions.../sdk/README.md: TypeScript SDK usage, dependencies, exported methods, minimal snippets for every function.../utils/scripts/README.md: deployment/config scripts usage + required environment variables.AGENTS.md(this file): agent-specific guidance; keep it up to date.
Whenever implementing a new feature, changing behavior, or removing functionality:
Update all relevant guides where applicable:
-
Root
README.md- protocol-wide guides
- repo layout / “what’s where”
- contribution + testing + SDK + scripts overview
-
Program README(s)
scale_amm/README.md: program methods, behaviors, features, fee rules, invariantsscale_vmm/README.md: program methods, pair ledger model, graduation threshold, fee rules
-
test/README.md- how tests are run
- latest checklist
- execution report (keep current)
-
../sdk/README.md- TS SDK dependencies
- exposed methods list
- minimal usage snippet for every function
-
../utils/scripts/README.md- deployment/config scripts
- required env vars
- operational steps and caveats
- Before finalizing changes, re-read
AGENTS.mdand update any outdated agent guidance to match the new reality.
- Read through the entire test suite relevant to the change.
- Add/update tests for:
- positive flows,
- negative cases (unauthorized, invalid inputs),
- edge cases (0/1 amounts, max bps, rounding),
- potential attack paths.
- Run tests repeatedly until all tests pass.
- Aim for maximum practical coverage around new/modified logic.
- Update deployment/config/helper scripts to accommodate new state, new instructions, migrations, or new methods.
- AMM independence: AMM must remain usable without VMM.
- VMM dependence: VMM pairs are expected to graduate to AMM and should not accidentally become “AMM-like pools.”
- Graduation threshold: must remain a numeric liquidity metric; do not introduce implicit thresholds without documenting and testing them.
- Fee separation: platform fee configuration must remain separable between AMM and VMM.
- Prefer explicit naming in code/docs:
- Use “pair” for the conceptual market.
- Use “pool” only for AMM on-chain reserve state.
- When touching fee logic, update both:
- on-chain program logic
- SDK helper functions + docs
- tests (including negative and rounding tests)
- If you change any instruction layouts / account schemas:
- update program README(s)
- update SDK typing and usage snippets
- update scripts and env var docs
- add migration notes if needed
If a prompt is ambiguous, resolve these before implementing:
- Which program is being modified: AMM, VMM, or both?
- For VMM changes: does it affect graduation threshold or migration?
- Which numeric field defines “liquidity threshold” for graduation?
- Any changes to:
- platform fee beneficiary authority,
- creator fee wallet list constraints,
- fee bps bounds,
- rounding rules?
If the prompt does not specify these and the change depends on them, ask targeted questions rather than guessing.