Skip to main content

Overview

The initialize instruction sets up the Privacy Cash program for the first time. It creates the main merkle tree for SOL transactions, initializes the tree token account, and establishes global fee configuration.
This instruction can only be called once per program deployment and requires admin authorization on mainnet.

Function Signature

pub fn initialize(ctx: Context<Initialize>) -> Result<()>

Accounts

tree_account
AccountLoader<MerkleTreeAccount>
required
The main merkle tree account for SOL transactions. PDA derived from ["merkle_tree"].
  • Mutable: Yes
  • Initialized: Yes (created by this instruction)
tree_token_account
Account<TreeTokenAccount>
required
Account that holds deposited SOL tokens. PDA derived from ["tree_token"].
  • Mutable: Yes
  • Initialized: Yes (created by this instruction)
global_config
Account<GlobalConfig>
required
Global configuration account containing fee rates. PDA derived from ["global_config"].
  • Mutable: Yes
  • Initialized: Yes (created by this instruction)
authority
Signer
required
The authority that can initialize the program. Must match the admin pubkey on mainnet.
  • Mutable: Yes (pays for account creation)
  • Signer: Yes
system_program
Program<System>
required
The Solana system program.

Default Configuration

The instruction initializes the following default values:
  • Merkle Tree Height: 26 levels (67,108,864 maximum commitments)
  • Root History Size: 100 historical roots
  • Max Deposit Amount: 1,000 SOL (1,000,000,000,000 lamports)
  • Deposit Fee Rate: 0% (free deposits)
  • Withdrawal Fee Rate: 0.25% (25 basis points)
  • Fee Error Margin: 5% (500 basis points)

Code Example

import * as anchor from "@coral-xyz/anchor";
import { Program } from "@coral-xyz/anchor";
import { PublicKey } from "@solana/web3.js";

const program = anchor.workspace.Zkcash as Program<Zkcash>;
const authority = anchor.web3.Keypair.generate();

// Derive PDAs
const [treeAccountPDA] = PublicKey.findProgramAddressSync(
  [Buffer.from("merkle_tree")],
  program.programId
);

const [treeTokenAccountPDA] = PublicKey.findProgramAddressSync(
  [Buffer.from("tree_token")],
  program.programId
);

const [globalConfigPDA] = PublicKey.findProgramAddressSync(
  [Buffer.from("global_config")],
  program.programId
);

// Initialize the program
await program.methods
  .initialize()
  .accounts({
    treeAccount: treeAccountPDA,
    treeTokenAccount: treeTokenAccountPDA,
    globalConfig: globalConfigPDA,
    authority: authority.publicKey,
    systemProgram: anchor.web3.SystemProgram.programId
  })
  .signers([authority])
  .rpc();

console.log("Privacy Cash initialized successfully");

State Changes

MerkleTreeAccount

  • authority: Set to the signer’s public key
  • next_index: Initialized to 0
  • root_index: Initialized to 0
  • max_deposit_amount: Set to 1,000,000,000,000 lamports
  • height: Set to 26
  • root_history_size: Set to 100
  • bump: PDA bump seed
  • root: Initialized to the empty tree root

TreeTokenAccount

  • authority: Set to the signer’s public key
  • bump: PDA bump seed

GlobalConfig

  • authority: Set to the signer’s public key
  • deposit_fee_rate: Set to 0 (0% - free deposits)
  • withdrawal_fee_rate: Set to 25 (0.25%)
  • fee_error_margin: Set to 500 (5%)
  • bump: PDA bump seed

Authorization

No authorization required. Any account can initialize.

Errors

Unauthorized
Error
Thrown when the signer is not the authorized admin (mainnet/devnet only).

See Also

Build docs developers (and LLMs) love