Overview
Privacy Cash supports both native SOL and a curated list of SPL tokens. Each supported SPL token has its own dedicated Merkle tree for privacy-preserving transactions.Token Support Configuration
The protocol uses two mechanisms to control which tokens are supported:Environment-Based Configuration
Token Allowlist
In production and devnet environments, only tokens in theALLOWED_TOKENS constant are permitted.
Supported SPL Tokens
Mainnet Tokens
The following tokens are supported on Solana mainnet:| Token | Symbol | Mint Address |
|---|---|---|
| USD Coin | USDC | EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v |
| Tether USD | USDT | Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB |
| Ore | ORE | oreoU2P8bN6jkk3jbaiVxYnG1dCXcYxwhwyK9jSybcp |
| Zcash | ZEC | A7bdiYdS5GjqGFtxf17ppRHtDKPkkRqbKtR27dxvQXaS |
| Staked Ore | stORE | sTorERYB6xAZ1SSbwpK3zoK2EEwbBrc7TZAzg1uCGiH |
| Jupiter USDC | jlUSDC | 9BEcn9aPEmhSPbPQeFGjidRiEKki46fVQDyPpSQXPA2D |
| Jupiter Wrapped SOL | jlWSOL | 2uQsyo1fXXQkDtcpXnLofWy88PxcvnfH2L8FPSE62FVU |
lib.rs:52-60
Devnet Tokens
The following test tokens are supported on Solana devnet:| Token | Symbol | Mint Address |
|---|---|---|
| USD Coin (Devnet) | USDC | 4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU |
| Tether USD (Devnet) | USDT | EcFc2cMyZxaKBkFK1XooxiyDyCPneLXiMwSJiVY6eTad |
| Ore (Devnet) | ORE | 6zxkY8UygHKBf64LJDXnzcYr9wdvyqScmj7oGPBFw58Z |
| Zcash (Devnet) | ZEC | Vu3Lcx3chdCHmy9KCCdd19DdJsLejHAZxm1E1bTgE16 |
| Staked Ore (Devnet) | stORE | 5MvqBFU5zeHaEfRuAFW2RhqidHLb7Ejsa6sUwPQQXcj1 |
| Jupiter USDC (Devnet) | jlUSDC | Fv7iYNEmq277whRwAFbCqNY3Qz9r73gwDRLrw5yiNmtf |
| Jupiter Wrapped SOL (Devnet) | jlWSOL | 8wBeZG358JQxdsPUVaRJY1viRPkx8Auoh8NvpFscbQka |
lib.rs:41-49
Native SOL Support
In addition to SPL tokens, Privacy Cash natively supports SOL transactions. The SOL mint address is represented as:utils.rs:14
Token Validation
Before processing SPL token transactions, the protocol validates that the token is allowed:During Tree Initialization
lib.rs:161-163
During Transactions
lib.rs:395-397
If validation fails, the transaction reverts with:
“Invalid mint address: mint address is not allowed”
Adding Support for New Tokens
Mainnet Token Addition
To add a new token to mainnet:- Update the
ALLOWED_TOKENSconstant inlib.rs:
-
Initialize a tree for the token using the
initialize_tree_account_for_spl_tokeninstruction - Deploy the updated program with the new token list
Devnet Token Addition
Follow the same process for devnet tokens:Initializing Token Trees
Each supported SPL token requires its own Merkle tree initialization.Function Signature
Requirements
- Only the protocol authority can initialize token trees
- Token mint must be in
ALLOWED_TOKENS(unlessALLOW_ALL_SPL_TOKENSis enabled) - Each token gets a separate Merkle tree with seed:
[b"merkle_tree", mint.key().as_ref()]
Tree Properties
Each SPL token tree is initialized with:- Height: 26 (supports 67,108,864 commitments)
- Root History Size: 100 previous roots
- Deposit Limit: Configurable per token (specified during initialization)
lib.rs:151-185
Token Account Management
Associated Token Accounts (ATAs)
For each supported token, the protocol manages:-
Tree ATA: The protocol’s token account that holds deposited tokens
- Authority:
global_configPDA - Created automatically on first deposit
- Authority:
-
Fee Recipient ATA: Where protocol fees are collected
- Must exist for supported tokens
- Validated during transactions
lib.rs:744-756
Token Transfer Operations
Deposits
Tokens are transferred from the user’s token account to the tree’s ATA:lib.rs:442-452
Withdrawals
Tokens are transferred from the tree’s ATA to the recipient’s token account:lib.rs:464-476
Testing on Localnet
For local development and testing, all SPL tokens are automatically allowed:Token Metadata
USDC (USD Coin)
- Decimals: 6
- Use Case: Stablecoin pegged to US Dollar
- Privacy Use: Private payments, remittances
USDT (Tether USD)
- Decimals: 6
- Use Case: Stablecoin pegged to US Dollar
- Privacy Use: Private transfers, trading
ORE (Ore)
- Use Case: Mining token on Solana
- Privacy Use: Private mining rewards, transfers
ZEC (Zcash)
- Use Case: Privacy-focused cryptocurrency bridge
- Privacy Use: Cross-chain privacy transactions
stORE (Staked Ore)
- Use Case: Liquid staking derivative of ORE
- Privacy Use: Private staking positions
jlUSDC (Jupiter USDC)
- Use Case: Jupiter DEX liquidity token
- Privacy Use: Private liquidity provision
jlWSOL (Jupiter Wrapped SOL)
- Use Case: Jupiter DEX liquidity token
- Privacy Use: Private SOL positions
Security Considerations
Token Validation
- Allowlist enforcement: Only approved tokens can be used in production
- Mint verification: Every transaction validates the token mint address
- Authority control: Only protocol authority can add new token trees
Account Validation
During SPL token transactions, the protocol validates:lib.rs:376-383
Error Codes
InvalidMintAddress
“Invalid mint address: mint address is not allowed”Thrown when attempting to use an unsupported token.
InvalidTokenAccount
“Invalid token account: account is not owned by the token program”Thrown when the provided token account is invalid.
InvalidTokenAccountMintAddress
“Invalid token account mint address”Thrown when the token account’s mint doesn’t match the expected mint.
Code References
- Mainnet token list:
lib.rs:52-60 - Devnet token list:
lib.rs:41-49 - Token validation (initialization):
lib.rs:161-163 - Token validation (transactions):
lib.rs:395-397 - SOL address constant:
utils.rs:14 - Tree initialization:
lib.rs:151-185 - SPL token transactions:
lib.rs:371-520