Constants
Every Voidcash constant and default, with its value and where it is set.
Parameters marked as such are set by the admin and can change; read the live values from the Config account's
params. Every other value here is fixed by the program, the circuit or a service's defaults. Lamports: 1 SOL is
1,000,000,000.
Fees
| Name | Value | Meaning | Where |
|---|---|---|---|
| Shield fee | 0 at launch | Taken on top of the deposit. A parameter | Config account (params.shield_fee_bps) |
| Exit fee | 50 (0.5%) at launch | Taken from every unshield. A parameter | Config account (params.exit_fee_bps) |
| Buyback share | 5_000 (50%) at launch | The buyback's share of every fee; the treasury gets the rest. A parameter | Config account (params.buyback_share_bps) |
MAX_FEE_BPS | 100 (1%) | The highest shield or exit fee the admin can set | Program limit |
BPS | 10_000 | Basis points in a whole; also the highest buyback share | Program limit |
| Private transfer fee | 0 | Private transfers pay no pool fee, only the relayer's | Program rule |
A fee is amount × fee_bps / 10,000, rounded down. The buyback's part is fee × buyback_share_bps / 10,000,
rounded down, so rounding favours the treasury.
Amounts and sizes
| Name | Value | Meaning | Where |
|---|---|---|---|
| Minimum deposit | 10_000_000 lamports (0.01 SOL) at launch | The smallest shield. A parameter, always above zero | Config account (params.min_deposit) |
MAX_AMOUNT | 1 << 60 lamports | The most any ext_amount or relayer fee can be, so the circuit's field sum cannot wrap | Program limit |
CIPHERTEXT_LEN | 88 bytes | One note ciphertext: an ephemeral x25519 key (32), the encrypted note (40) and its tag (16) | transact instruction data |
| Proof | 256 bytes | A Groth16 proof as the program verifies it: A, B, C | transact instruction data |
transact instruction data | 595 bytes | Discriminator, proof, root index, nullifiers, commitments and ExtData | transact instruction |
CONFIG_RESERVED | 128 bytes | Zero bytes at the end of Config for parameters a later version adds | Config account |
Config size | 280 bytes | The config account | Config account |
| Buyback state size | 450 bytes | The buyback state account | Buyback state account |
| Nullifier account | 8 bytes | An Anchor account with no data; its rent is paid on every spend and kept | Nullifier accounts |
The note tree
| Name | Value | Meaning | Where |
|---|---|---|---|
LEVELS | 26 | The tree's depth: 2^26 leaves, two per transaction | Tree account, circuit |
ROOT_HISTORY | 192 | Roots kept, one per slot that had an insert: about 77 s of continuous activity | Tree account |
MAGIC | voidtree | The tree account's first 8 bytes | Tree account |
TREE_SIZE | 9,400 bytes | The tree account | Tree account |
| Empty leaf | 0 | Tree account, the app |
Keys and addresses
| Name | Value | Meaning | Where |
|---|---|---|---|
| Root | 32 random bytes | The vault, from which every key derives | The app |
| Spending key | HKDF-SHA256(root, info voidcash/v1/spend, 64 bytes) mod r | The app | |
| Viewing key | HKDF-SHA256(root, info voidcash/v1/view, 32 bytes), an x25519 secret | The app | |
| PBKDF2 rounds | 600_000 | PBKDF2-SHA256 rounds that turn the passphrase into the AES-256-GCM key sealing the root | The app |
| Address prefix | void | Every private address starts with it | Private addresses |
| Address version | 1 | The version byte of a private address | Private addresses |
| Recovery version | 0x81 | The version byte of a recovery key | Recovery keys |
| Checksum | 4 bytes | The first 4 bytes of SHA-256(SHA-256(payload)), on addresses and recovery keys | Private addresses, recovery keys |
| Note encryption | XChaCha20-Poly1305, zero nonce, key HKDF-SHA256(shared secret, salt = ephemeral key, info voidcash/v1/note) | Each key is used once | Note ciphertexts |
| Ext-data domain | voidcash/transact/v1 | The first part of the ext-data hash | Program, the app |
The buyback
| Name | Value | Meaning | Where |
|---|---|---|---|
OBS_INTERVAL | 30 slots | At most one observation per interval, about 12 s | Program limit |
MAX_OBS_AGE | 90 slots (3 × OBS_INTERVAL) | A longer gap between observations restarts the ring; a buy needs an observation this recent | Program limit |
BUY_INTERVAL | 150 slots | At most one buy per interval, about a minute | Program limit |
N_OBS | 15 | Observations in the ring; the reference is their median | Buyback state account |
CHUNK_MAX | 1_000_000_000 lamports (1 SOL) | The largest chunk | Program limit |
CHUNK_MIN | 10_000_000 lamports (0.01 SOL) | Below this, no buy | Program limit |
CHUNK_RESERVE_BPS | 50 (0.5%) | A chunk is at most this share of the pool's SOL reserve | Program limit |
SQRT_BAND_BPS | 50 (0.5%) | The band above the reference, on the square-root price (about 1% on the price) | Program limit |
MAX_LOSS_BPS | 200 (2%) | The minimum output is what the reference price gives, less this | Program limit |
ROOM_USE_BPS | 9_000 (90%) | The share of the room left in the band one chunk may use | Program limit |
Pause flags
Bits of Config.paused.
| Name | Value | What it stops |
|---|---|---|
PAUSE_DEPOSITS | 1 | Shields |
PAUSE_TRANSFERS | 2 | Private transfers |
PAUSE_EXITS | 4 | Unshields and every relayer fee |
PAUSE_BUYBACK | 8 | The buyback |
PAUSE_ALL | 15 | All four |
The relayer
Defaults of the relayer service.
| Name | Default | Meaning |
|---|---|---|
| HTTP port | 8788 | The port the HTTP server listens on |
| Priority fee | 50000 micro-lamports | Priority fee per compute unit |
| Fee margin | 100000 lamports | Added to every quote |
| Deadline limit | 900 slots | How far ahead a request's deadline may be |
| Address lookup tables | none | Lookup tables used to build transactions |
| Allowed browser origins | none | Origins allowed by CORS |
| Buyback crank | on | The crank that calls observe and buyback |
| Crank interval | 4000 ms | How often the crank looks |
| Request body limit | 16 KiB | Larger bodies get 413 |
transact compute budget | 400_000 units | Also the units the quote prices |
observe, buyback compute budgets | 20_000, 200_000 units | The crank's transactions |
| Transaction size limit | 1232 bytes | Larger transactions are refused |
| Base fee in the quote | 5_000 lamports | Per transaction |
The indexer
Defaults of the indexer service.
| Name | Default | Meaning |
|---|---|---|
| HTTP port | 8789 | The port the HTTP server listens on |
| Poll interval | 2000 ms | How often the writer polls |
| Single-exit alert | 200 (2%) | One exit above this share of the vault alerts |
| Window alert | 500 (5%) | Exits within the window above this share alert |
| Alert window | 9000 slots | The window, about an hour |
| Page size | 5_000 | Most leaves or nullifiers per request |
| Activity page | 100 | Most activity entries per request |
The app
| Name | Value | Meaning |
|---|---|---|
| Deadline | current slot + 150 | The deadline slot the app sets on every transaction |
| Shield compute budget | 400_000 units, at 50_000 micro-lamports per unit | The shield transaction the wallet signs |
The circuit
| Name | Value |
|---|---|
| Template | Transaction(26, 2, 2): depth 26, two inputs, two outputs |
| Constraints | 15,494, as compiled |
| Public inputs | 7: root, publicAmount, extDataHash, two nullifiers, two output commitments (nPublic in the verifying key) |
| Amount range | 64 bits, on every input and output amount |
| Asset | 0, native SOL, a constant in every note's commitment |
| Proving key | 9,789,307 bytes, SHA-256 34b15fb1a334f8a053ebecfd85377eecb85cf891161a4d705ffc6962e384b0ec, served under /circuit/ |
| Circuit WASM | 3,133,689 bytes, SHA-256 fbed2c0ce5d0ea4cbaac65289c387ca8240071592a27edf1d22d2f48a3fd4985, served under /circuit/ |
Addresses
| Name | Address |
|---|---|
| Pool program | HjQyQZ3xewjsBb3w8JFGJSh2ztauV4f6X4o5CrZTobZm |
| Meteora DAMM v2 (cp-amm) | cpamdpZCGKUy5JxQXB4dcpGPiikHawvSWAd6mEn1sGG |
| cp-amm pool authority | HLnpSz9h2S4hiLQ43rnSD9XkcUThA7B8hQMKmDaiTLcC |
| SPL Token program | TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA |
| Wrapped SOL mint | So11111111111111111111111111111111111111112 |