Skip to main content

Overview

The update_deposit_limit_for_spl_token instruction allows the program authority to modify the maximum deposit amount for a specific SPL token’s merkle tree. Each SPL token has its own separate merkle tree with its own deposit limit.
Only the program authority can call this instruction.

Function Signature

pub fn update_deposit_limit_for_spl_token(
    ctx: Context<UpdateDepositLimitForSplToken>,
    new_limit: u64
) -> Result<()>
Source: lib.rs:191-206

Parameters

new_limit
u64
required
New maximum deposit amount in the token’s smallest unit. The value depends on the token’s decimals:USDC (6 decimals):
  • 1,000 USDC: 1_000_000_000
  • 10,000 USDC: 10_000_000_000
  • 1,000,000 USDC: 1_000_000_000_000
USDT (6 decimals):
  • Similar to USDC
SOL-wrapped tokens (9 decimals):
  • 100 tokens: 100_000_000_000
  • 1,000 tokens: 1_000_000_000_000

Accounts

tree_account
AccountLoader<MerkleTreeAccount>
required
The SPL token-specific merkle tree account to update.PDA Seeds: ["merkle_tree", mint.key()]
  • Mutable: Yes
  • Authority check: Must be owned by the signer
mint
Account<Mint>
required
The SPL token mint account. Used to derive the correct tree PDA.
  • Mutable: No
  • Validation: Must be in the allowed tokens list (see supported tokens)
authority
Signer
required
The program authority. Must match the tree’s authority field.
  • Signer: Yes
  • Validation: Checked via has_one = authority constraint

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();

// USDC Mainnet mint
const usdcMint = new PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v");

// Derive SPL token tree PDA
const [splTreePDA] = PublicKey.findProgramAddressSync(
  [Buffer.from("merkle_tree"), usdcMint.toBuffer()],
  program.programId
);

// Update to 10 million USDC (6 decimals)
const newLimit = new anchor.BN(10_000_000_000_000);

await program.methods
  .updateDepositLimitForSplToken(newLimit)
  .accounts({
    treeAccount: splTreePDA,
    mint: usdcMint,
    authority: authority.publicKey
  })
  .signers([authority])
  .rpc();

console.log(`USDC deposit limit updated to ${newLimit.toString()}`);

Common Use Cases

Increase USDC deposit limit to 1 million:
const usdcMint = new PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v");
const [splTreePDA] = PublicKey.findProgramAddressSync(
  [Buffer.from("merkle_tree"), usdcMint.toBuffer()],
  program.programId
);

// 1,000,000 USDC with 6 decimals
const newLimit = new anchor.BN(1_000_000_000_000);

await program.methods
  .updateDepositLimitForSplToken(newLimit)
  .accounts({
    treeAccount: splTreePDA,
    mint: usdcMint,
    authority: authority.publicKey
  })
  .signers([authority])
  .rpc();
Set limit to 0 to prevent new deposits of a specific token:
const oreMint = new PublicKey("oreoU2P8bN6jkk3jbaiVxYnG1dCXcYxwhwyK9jSybcp");
const [oreTreePDA] = PublicKey.findProgramAddressSync(
  [Buffer.from("merkle_tree"), oreMint.toBuffer()],
  program.programId
);

// Disable ORE deposits
const newLimit = new anchor.BN(0);

await program.methods
  .updateDepositLimitForSplToken(newLimit)
  .accounts({
    treeAccount: oreTreePDA,
    mint: oreMint,
    authority: authority.publicKey
  })
  .signers([authority])
  .rpc();
Update limits for multiple tokens in sequence:
const tokens = [
  { mint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", limit: 1_000_000_000_000 }, // USDC
  { mint: "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB", limit: 1_000_000_000_000 }, // USDT
  { mint: "oreoU2P8bN6jkk3jbaiVxYnG1dCXcYxwhwyK9jSybcp", limit: 500_000_000_000 }    // ORE
];

for (const token of tokens) {
  const mint = new PublicKey(token.mint);
  const [treePDA] = PublicKey.findProgramAddressSync(
    [Buffer.from("merkle_tree"), mint.toBuffer()],
    program.programId
  );
  
  await program.methods
    .updateDepositLimitForSplToken(new anchor.BN(token.limit))
    .accounts({
      treeAccount: treePDA,
      mint: mint,
      authority: authority.publicKey
    })
    .signers([authority])
    .rpc();
  
  console.log(`Updated ${token.mint}: ${token.limit}`);
}

State Changes

MerkleTreeAccount (for the specific SPL token)

  • max_deposit_amount: Updated to new_limit
All other fields remain unchanged. Other tokens’ merkle trees are not affected.

Behavior

  1. Verifies the signer is the tree’s authority
  2. Loads the SPL token-specific tree account (derived from mint address)
  3. Updates the max_deposit_amount field
  4. Emits a program log message with the mint address
  5. The new limit applies immediately to all subsequent deposits of that token
This only affects the specified SPL token. Each token has its own independent deposit limit.

Implementation

pub fn update_deposit_limit_for_spl_token(
    ctx: Context<UpdateDepositLimitForSplToken>,
    new_limit: u64
) -> Result<()> {
    let tree_account = &mut ctx.accounts.tree_account.load_mut()?;
    
    tree_account.max_deposit_amount = new_limit;
    
    msg!(
        "Deposit limit updated to: {} for mint: {}",
        new_limit,
        ctx.accounts.mint.key()
    );
    
    Ok(())
}
Source: lib.rs:191-206

Account Constraints

#[derive(Accounts)]
pub struct UpdateDepositLimitForSplToken<'info> {
    #[account(
        mut,
        seeds = [b"merkle_tree", mint.key().as_ref()],
        bump = tree_account.load()?.bump,
        has_one = authority @ ErrorCode::Unauthorized
    )]
    pub tree_account: AccountLoader<'info, MerkleTreeAccount>,
    
    /// SPL Token mint account
    pub mint: Account<'info, Mint>,
    
    /// The authority account that can update the deposit limit
    pub authority: Signer<'info>,
}
Source: lib.rs:857-872

Errors

Unauthorized
Error (6000)
Thrown when the signer is not the tree’s authority.
InvalidMintAddress
Error (6018)
Thrown if the mint is not in the allowed tokens list (on non-localnet environments).

Program Log Output

When successful, the instruction logs:
Deposit limit updated to: {new_limit} for mint: {mint_address}
Example:
Deposit limit updated to: 1000000000000 for mint: EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v

Monitoring

Monitor limit changes for specific tokens:
// Check current limit for USDC
const usdcMint = new PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v");
const [usdcTreePDA] = PublicKey.findProgramAddressSync(
  [Buffer.from("merkle_tree"), usdcMint.toBuffer()],
  program.programId
);

const treeAccount = await program.account.merkleTreeAccount.fetch(usdcTreePDA);
console.log(`USDC deposit limit: ${treeAccount.maxDepositAmount.toString()}`);

Network Differences

  • Mainnet/Devnet: Only allowed tokens can have their limits updated
  • Localnet: Any SPL token mint can be used for testing

See Also

Build docs developers (and LLMs) love