On-chain overview
Protocol15's on-chain surface is four Anchor programs on devnet. Mainnet is not enabled. This section documents each one as it is deployed: its purpose, PDAs, accounts, instructions, and how to call it. The SDK builds these instructions for you (see @p15/blind-mode); this section is the ground truth underneath.
The programs
| Program | Id | Role |
|---|---|---|
| note-vault | 7gtXhpwEaYHKJ9XpAX7Z4BNjXU3cFCq4CNyzMQpFaQZ2 | The shielded pool. Holds deposits, verifies private transfers, releases withdrawals. |
| transfer verifier | 14C9wbz3Eg6nx6A4GNNE2DqkgdZGKnxhp4TLMJkD7Pw3 | Groth16 verifier for the 1-in/2-out transfer circuit. Called by note-vault via CPI. |
| psol-wrapper | 5LQUmd355dcXkETDheBXavpaBzJq4JFWLb9mfkku31ZR | Legacy 1:1 SOL to pSOL wrapper. Not on the active path (the dApp uses native wSOL). |
| stealth-vault | 7oFAWawZCxDivMSa73hGh5V4XnhukLbrZQTA9Sq2r2pk | Non-revocable custody for one-time Token-2022 CT accounts. Tied to the disabled CT path. |
| policy | 3B8sqPfgKYvxffwCvPx76Syu4R6MzQr7wkiTmvfjEzLR | Optional on-chain allowlist and per-transaction limit. Not wired into the dApp. |
A note on the token program
Protocol15 does not use Token-2022 Confidential Transfers or ZK ElGamal. That
path is disabled. Privacy comes entirely from the Noir/Groth16 note model in
note-vault, on top of plain SPL transfer_checked. The active token program is
the legacy SPL Token program: SOL is handled as native wrapped SOL
(So111…112), and USDC is legacy SPL too. note-vault uses Anchor's
TokenInterface, so it can hold a Token-2022 mint as well, but nothing on the
active path requires Token-2022. The two programs that do use Token-2022
(psol-wrapper and stealth-vault) belong to the disabled CT design.
How they fit together
The active amount-privacy engine is note-vault: a shielded pool where every
balance is a hidden note. A blind transfer is one spend on note-vault, gated by
a Groth16 proof the transfer verifier checks. SOL enters and leaves the pool as
native wrapped SOL on the legacy Token program (wrap = create the wSOL ATA,
transfer lamports, SyncNative; unwrap = CloseAccount).
make private: SOL --wrap (native wSOL, legacy Token)--> wSOL --note-vault.deposit--> private note
blind send: private note --note-vault.spend (proof)--> recipient note + change
withdraw: private note --note-vault.withdraw--> wSOL --unwrap (CloseAccount)--> SOLpsol-wrapper is a separate, program-minted SOL wrapper (pSOL, a Token-2022 CT mint) from the earlier CT design. The current note-model dApp wraps SOL natively instead, so psol-wrapper is documented but not on the active flow.
stealth-vault is the alternative custody design for the Token-2022 Confidential
Transfer path. That path is disabled in favour of the note model, so the program is
deployed but not on the active flow. It is documented because the recipient-only
ownership gate it pioneered (R = spend_pub + t*G as a required signer) is the
same gate note-vault uses.
policy is an optional escalation a deployer can prepend or CPI into the make-private boundary. The active screening path is the off-chain screening provider; policy is for unskippable on-chain enforcement.
Conventions used across these pages
- PDAs are derived with
Pubkey.findProgramAddress(seeds, programId). Each program page lists its seeds. - Amounts are
u64base units. pSOL and wrapped SOL use 9 decimals, so base units equal lamports. - Recipient-only ownership. note-vault and stealth-vault both require the
recipient-only key
Ras a transaction signer. The sender can computeRbut cannot sign as it, which is what makes payments final. - Field encoding. Commitments and owners are BN254 field elements,
big-endian, to match the gnark public witness. The SDK's
noteCommitment,assetField, andpubkeyToFieldmirror the program's Poseidon encoding exactly.
Trust assumptions
- The programs' upgrade authorities (flagged for a multisig and burn before any real mainnet use).
- The per-circuit Groth16 trusted setup behind the transfer verifier.
- Everything else is structural: there is no admin or operator key that can move
pooled funds. Tokens leave note-vault only through
withdraw, gated on a recipient signature, a recomputed commitment, and a live note marker.