Skip to main content

Confidential Transfers on Solana: A Developer's Guide

Updated on
Apr 08, 2025

10 min read

Overview

Solana's Token-2022 program introduced several powerful extensions that enhance token functionality beyond the standard SPL token program. Among these, the Confidential Transfer extension stands out by enabling privacy-preserving token transfers on Solana. This guide explores how this extension works, the components that make it possible, and the workflow for conducting private token operations.

Prefer a video walkthrough? Follow along with Sahil and learn the basics of Confidential Transfers on Solana.
Subscribe to our YouTube channel for more videos!

What You Will Do

In this guide, we will:

  • Explain the basics of the Confidential Transfer Extension and how Confidential Balances work.
  • Take a high-level look at an example confidential transaction flow.
  • Walk through the account structs enabling the transaction.
  • Take a look at the actual instructions required to make the transfer happen.

What You Will Need

What is the Confidential Transfer Extension?

The Confidential Transfer extension enables token transfers with hidden balances and amounts on Solana. Using cryptographic techniques like homomorphic encryption and zero-knowledge proofs, this extension allows users to:

  • Keep their account balances discrete
  • Transfer tokens without revealing the amounts
  • Maintain verifiable transactions that can't be tampered with
  • Optionally allow 3rd party auditors to view transaction amounts and token account balances

This extension combines the transparency and security of blockchain with the privacy features users expect from traditional financial systems. It is important to note that the confidential balances and amounts do not mean complete anonymity. Transactions between two parties remain publicly visible on-chain. Only the amounts are encrypted.

Under the Hood: Privacy Protection

Just like all token extensions, mint/token accounts with the confidential transfer extension enabled retain all original respective functions. A user can hold a token balance that is publicly visible and transfer tokens to anyone publicly. The privacy protections in this system come from several key mechanisms:

1. Account-Specific Encryption

At the heart of confidential tokens lies a powerful combination of encryption and mathematical proofs. Rather than storing balances as visible numbers, the extension uses "homomorphic encryption" -- a special type of encryption that allows mathematical operations to be performed directly on encrypted values. When you send tokens, the program doesn't see "subtract 10 from Alice, add 10 to Bob." Instead, it sees "subtract this encrypted value from Alice's encrypted balance, add this encrypted value to Bob's encrypted balance." The encryption allows the blockchain to process transactions without knowing the exact amounts.

Unlike standard tokens where balances are stored as plaintext (e.g., u64), confidential balances are encrypted using:

  • Homomorphic encryption, allowing mathematical operations on encrypted values. This means even validators processing transactions can't see actual token amounts.
  • Account-specific encryption keys (not the owner's keys)

Configuring confidential transfer token accounts differ from standard token account creation because they require the owner-provided encryption keys. Confidential token accounts should only be configured by the token account owner/admin to avoid compromising encryption.

2. Zero-Knowledge Proofs

To ensure everything works correctly without revealing values, the system uses "zero-knowledge proofs." These are mathematical proofs that verify statements like "I have enough tokens to make this transfer" or "these encrypted numbers equal the same value" without exposing the actual numbers. When transferring or withdrawing tokens, the sender must provide zero-knowledge proofs that:

  • Verify they have sufficient funds.
  • Ensure the transaction is consistent (the amount deducted from your account equals the amount added to the receiver)

These proofs mathematically demonstrate that rules are being followed without revealing any actual amounts.

3. Pending/Available Balance Model

Confidential transfers employ a two-stage system ("pending" balances and "available" balances) to protect against front-running attacks:

  • Incoming transfers go to the pending balance
  • Only the account owner can move tokens from pending to available
  • Outgoing transfers only draw from the available balance

This prevents other users from disrupting your transactions (and therefore your ZK Proofs/Validations) by manipulating your balance immediately before you make a transfer.

4. Optional Auditor Oversight

Token Mints configured with the confidential transfer extension can optionally be configured with an auditor public key that:

  • Allows a designated party to decrypt balances and transfer amounts
  • Provides a compliance mechanism without compromising general user privacy

Privacy In Practice

This combination of encrypted balances and mathematical proofs enables privacy while maintaining the security and integrity of the blockchain. In practice, this is achieved through:

  • Advanced account structs that store encyrption public keys, "available" and "pending" confidential balances, and other pending balance change counters for validating proofs.
  • A new Native Program, the Solana ZK ElGamal Proof program (ZkE1Gama1Proof11111111111111111111111111111) for creating and verifying proofs on-chain.
  • ElGamal Encrypted user account keys for enabling users and auditors to reveal encrypted balances and transfer amounts.

For more information on the Protocol, Encryption Methodology, or ZK Proofs, check out the Confidential Token Extension Protocol Official Documentation:

How it Works: Account State

Confidential tokens introduce new data structures for both mint and token accounts. Let's examine how these differ from standard tokens.

The Confidential Mint Account

The confidential mint configuration is added to a Token-2022 mint account and contains:

pub struct ConfidentialTransferMint {
pub authority: OptionalNonZeroPubkey,
pub auto_approve_new_accounts: PodBool,
pub auditor_elgamal_pubkey: OptionalNonZeroElGamalPubkey,
}

Source: github.com/solana-program/token-2022

Key differences from standard mints:

  • A dedicated authority for managing confidential transfers
  • An approval setting for new accounts (auto-approve or require authority approval for token accounts to participate in the mint's confidential transfers)
  • An optional auditor public key that can decrypt transaction amounts. The public key should be an ElGamal public key, which allows the auditor to decrypt the encrypted amounts without compromising the overall privacy of the transactions.

The Confidential Token Account

Token accounts with the confidential extension have a significantly more complex structure than standard token accounts:

pub struct ConfidentialTransferAccount {
pub approved: PodBool,
pub elgamal_pubkey: PodElGamalPubkey,
pub pending_balance_lo: EncryptedBalance,
pub pending_balance_hi: EncryptedBalance,
pub available_balance: EncryptedBalance,
pub decryptable_available_balance: DecryptableBalance,
pub allow_confidential_credits: PodBool,
pub allow_non_confidential_credits: PodBool,
pub pending_balance_credit_counter: PodU64,
pub maximum_pending_balance_credit_counter: PodU64,
pub expected_pending_balance_credit_counter: PodU64,
pub actual_pending_balance_credit_counter: PodU64,
}

Source: github.com/solana-program/token-2022

Key differences from standard token accounts:

  • Uses an ElGamal public key for encryption (separate from the owner's key)
  • Contains encrypted balances rather than plaintext amounts
  • Splits balances into "pending" and "available" portions
  • Includes credit counters to track and limit pending operations (used in ZK Proofs to ensure we can clearly associate pre and post balances with the correct incoming transfer)
  • Can be configured to accept or reject different types of transfers

The most distinctive feature is the separation of balances into:

  1. Pending balance: Where newly received tokens are initially stored
  2. Available balance: Tokens that can be spent or withdrawn

Confidential Transfer Flow

Before we dig into the account structs and instruction details, let's walk through how tokens move through this system at a high level:

Confidential Token Flow


  • When a user wants to interact with confidential balances and transfers, they must first Deposit to a confidential token account's "pending" balance. As we have discussed, Confidential Token accounts, store two different encrypted balances in state: a "Pending" balance, and an "Available" balance.
  • To convert "pending" balance to "available" balance, the account owner must Apply the pending balance to their account.
  • Users can Withdraw "avaialble" balances to their public account or Transfer them to other users. These transfers are validated using ZK Proofs.
  • Mints can optionally be configured with an "Auditor" account that has the ability to decrypt transfer amounts for the token.

There's a lot happening under the hood here, let's walk through the entire transaction flow.

1. Initialize Mint

Before using confidential tokens, we must initialize our mint with the confidential token transfer extensions:

Initializing a Confidential Mint: Include a ConfidentialTransferInstruction::InitializeMint instruction in the same transaction as the standard mint initialization using Token 2022, which:

  • Configures auditor keys
  • Sets approval/modification authority
  • Sets whether or not to auto approve token accounts

2. Set Up Token Account

Next we must create a token account to use and prepare it for confidential transfers.

Create Token Account: Execute a TokenInstruction::InitializeAccount and TokenInstruction::Reallocate, specifying the ExtensionType::ConfidentialTransferAccount.

For more information on initializing token accounts with extensions, check our Guide: What are Solana SPL Token Extensions and How to Get Started?

Configuring a Token Account: Execute a transaction that configures the account for use ConfidentialTransferInstruction::ConfigureAccount

  • Verifies the ElGamal encryption key specific to this account
  • Requires proof that the encryption key is valid
  • Requires approval from the mint authority if auto-approve is disabled
  • Initializes confidential balances with an encrypted zero balance

2. Get Tokens into the System

Mint: First, you will need to mint tokens to your token account by calling TokenInstruction::MintTo.

For more information on minting fungible tokens, check our Guide: How to Create a Fungible SPL Token on Solana?

Deposit: The ConfidentialTransferInstruction::Deposit instruction will migrate tokens from the user's public token account balance into their confidential pending balance. The instruction:

  • Encrypts the token amount using the account's encryption key
  • Adds the encrypted amount to the pending balance
  • Updates the pending balance credit counter
  • Reduces the public token balance (e.g., if 100% of a users tokens are deposited, the user's public token balance will be 0)

Apply Pending Balance: Move tokens from pending to available balance by executing a ConfidentialTransferInstruction::ApplyPendingBalance instruction.

  • Transfers encrypted tokens from pending to available balance
  • Can only be executed by the account owner
  • Updates counters to track applied operations

You can see in the example below, the account shows some "Encrypted Balance":

Applied Token Account Explorer

3. Transferring Tokens Confidentially

To send tokens to another confidential account, your wallet or application needs to generate zero-knowledge proofs that verify the transaction is valid without revealing the actual amounts. This requires several steps:

Generate Required Zero-Knowledge Proofs: You will need to create three specific proofs off-chain that are each verified and stored in an on-chain account:

Execute Transfer: Execute the actual transfer by passing all three proof accounts into the ConfidentialTransferInstruction::Transfer instruction. This instruction:

  • Checks that the required proofs were verified (using the context state accounts)
  • Subtracts the encrypted amount from the sender's available balance
  • Adds the encrypted amount to the receiver's pending balance

In the example below, you will see a transfer on Solana explorer but with no visible transfer amounts!

Explorer - Confidential Transfer

Clean Up Context State: Finally, we can call ProofInstruction::CloseContextState for each ZK Proof account to close the accounts that stored the ZK proofs and reclaim the rent.


Transaction Size Limitations

At the time of this writing, Solana has a strict 1,232 byte limit on transaction size (Source: github.com/solana-labs). Due to the parameter size of several of these instructions that include proof data, these instructions are often going to need to be processed across multiple, sequential transactions. This can be achieved by sending multiple transactions in sequence or utilizing Jito Bundles.

Check out our Guide: How to Use Solana Lookup Tables for an example on how to evaluate/compare the byte size of raw transaction data.

4. Withdrawing Tokens

To convert confidential tokens back to public tokens, you must first ensure the balance is in your "available" balance, then create a withdrawal transaction with the necessary proofs:

Apply Pending Balance (if needed): Move tokens from pending to available balance by executing a ConfidentialTransferInstruction::ApplyPendingBalance instruction.

Generate Required Zero-Knowledge Proofs: You will need to create two specific proofs off-chain that are each verified and stored in an on-chain account (this is similar to the transfer process, however, because the withdrawal results in a public balance, we do not need to verify an encrypted transfer amount):

Execute Withdrawal: Execute the withdrawal by passing both proof accounts into the ConfidentialTransferInstruction::Withdraw instruction. This instruction:

  • Checks that the required proofs were verified (using the context state accounts)
  • Subtracts the encrypted amount from the sender's available balance
  • Adds the plaintext amount to your public token balance

Clean Up Context State: Finally, we can call ProofInstruction::CloseContextState for each ZK Proof account to close the accounts that stored the ZK proofs and reclaim the rent.

Best Practices and Considerations

  1. Balance Management

    • Regularly apply pending balances to make funds available for use
  2. Key Security

    • Protect your encryption keys as carefully as your wallet keys
    • Lost encryption keys mean permanent loss of ability to decrypt confidential balances
  3. Privacy Limitations

    • Transaction metadata (sender, receiver, timestamp) remains visible
    • Only the amounts are encrypted and private
    • Pattern analysis might still reveal insights about balances or transfer amounts
  4. Production Audits

    • Ensure all code is thoroughly tested and audited before using in production

Wrap Up

The Confidential Transfer extension represents a significant advancement in configurable privacy for Solana tokens. By combining zero-knowledge proofs with homomorphic encryption, it offers a compelling balance between the speed, security, and cost of Solana, as well as the privacy expected in financial transactions.

Whether you're developing a privacy-focused application or simply want to understand how Solana is expanding its token capabilities, the confidential transfer extension provides powerful tools for building the next generation of financial applications.

Ready to Start Building?

Sign up for a free QuickNode account to start experimenting with the Confidential Token Extension today. If you are an enterprise looking to utilize confidential tokens, contact our team to discuss your confidential specific requirements.

Here are a few sample projects to get you started:

If you have a question or idea you want to share, drop us a line on Discord or Twitter!

We ❤️ Feedback!

Let us know if you have any feedback or requests for new topics. We'd love to hear from you.

Additional Resources

Share this guide