Skip to main content
Callback accounts define additional accounts used by a computation callback. Use them when a computation result needs to modify an onchain account. Prerequisites: Before diving into callback accounts, make sure you’ve read: When to use callback accounts:
  • Storing computation results in persistent accounts
  • Updating game state, user balances, or protocol data
  • Writing results that exceed transaction size limits

Complete example

Expanding on our basic example, let’s say we want to save the result of our addition in an account for later use. We’ll walk through the complete implementation step by step.

Step 1: Define the account structure

First, define an account to store our computation result:

Step 2: Modify the queue function

There are two ways to specify callback instructions in your queue_computation call: The callback_ix() helper method is the preferred approach because it automatically handles all required standard accounts and is less error-prone. What callback_ix() does automatically:
  • Creates a CallbackInstruction with the proper instruction data
  • Automatically includes standard accounts: arcium_program, comp_def_account, mxe_account, computation_account, cluster_account, instructions_sysvar
  • Accepts custom accounts through the &[CallbackAccount] parameter
  • Eliminates boilerplate and prevents errors

Understanding what happens: manual CallbackInstruction

For educational purposes, here’s what callback_ix() generates under the hood. This manual approach is functionally equivalent but more verbose and error-prone:
Key point: Both approaches are functionally equivalent. The callback_ix() method automatically generates the exact same CallbackInstruction structure as the manual approach, but with less code and reduced chance for errors. Important: We added the account to the callback (either via callback_ix() parameter or CallbackInstruction.accounts) but didn’t include it in the AddTogether accounts struct because we don’t read or write to it during the queue function - only during the callback.

Step 3: Implement the callback function

The callback instruction receives the accounts in the exact order specified in the queue function:

Key requirements & constraints

Account ordering

The accounts in your callback struct must match exactly the order in CallbackInstruction.accounts:
  1. Standard accounts are always required first: arcium_program, comp_def_account, mxe_account, computation_account, cluster_account, instructions_sysvar
  2. Custom accounts follow in the exact sequence you specified

Account creation rules

  • Can create accounts in the queue computation function (user pays rent)
  • Cannot create accounts during callback execution (would require nodes to pay)
  • Accounts must exist before the callback executes
  • Account size cannot change during callback

Writability requirements

  • Set is_writable: true in CallbackAccount to tell nodes to mark the account as writable
  • The account must have #[account(mut)] in the callback struct
  • Without proper writability flags, mutations will fail

Troubleshooting

Account not found: Ensure the account exists before callback execution. Initialize it in the queue function or a separate instruction. Order mismatch errors: Double-check that your callback struct accounts are in the exact same order as the CallbackInstruction.accounts vector. Cannot modify account: Verify both is_writable: true in CallbackAccount and #[account(mut)] in the callback struct are set. Size errors: Callback accounts cannot be resized. Allocate sufficient space when creating the account.

Understanding callback_ix() in detail

The callback_ix() method you see throughout these examples is a convenient helper that’s automatically generated by the #[callback_accounts] macro.

How callback_ix() works

When you define a callback struct with #[callback_accounts("instruction_name")], the macro automatically generates a callback_ix() method that:
  1. Takes required parameters: computation_offset and &mxe_account for proper context
  2. Creates a CallbackInstruction with the proper instruction data
  3. Automatically includes standard accounts that every callback needs:
    • arcium_program: The Arcium program that will invoke your callback
    • comp_def_account: The computation definition account for your encrypted instruction
    • mxe_account: Your MXE’s metadata and configuration
    • computation_account: The computation being processed
    • cluster_account: The MPC cluster processing the computation
    • instructions_sysvar: Solana’s instructions sysvar for transaction validation
  4. Accepts custom accounts through the &[CallbackAccount] parameter

Usage patterns

Basic usage (no custom accounts):
The empty array indicates no custom accounts needed beyond the standard ones. Advanced usage (with custom accounts):

Why use callback_ix()?

The callback_ix() helper is the recommended approach because it:
  • Eliminates boilerplate: No need to manually construct CallbackInstruction
  • Prevents errors: Automatically includes all required standard accounts
  • Maintains consistency: Ensures your callback instructions follow the correct format
  • Simplifies maintenance: Changes to callback requirements are handled by the macro

Going further

This guide covered the advanced patterns for working with callback accounts. To understand the fundamentals of callback instructions, see our basic program invocation guide. For handling different types of encrypted data inputs and outputs, see Arcis inputs/outputs.

What’s next?

Type generation

Understand how output types like AddTogetherOutput are automatically generated.

Client callbacks

Track computation completion from your TypeScript client.