> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/magicblock-labs/magicblock-engine-examples/llms.txt
> Use this file to discover all available pages before exploring further.

# Delegation Instructions

> Learn how to delegate accounts to Ephemeral Rollups using the #[delegate] macro and native Rust instructions

## Overview

Delegation instructions transfer account ownership to the MagicBlock delegation program, enabling accounts to be processed on Ephemeral Rollups (ER). This page documents delegation patterns across Anchor and native Rust programs.

## Anchor Delegation Pattern

### Using the #\[delegate] Macro

The `#[delegate]` macro automatically generates the required delegation accounts and helper methods.

```rust anchor-counter/programs/anchor-counter/src/lib.rs theme={null}
use ephemeral_rollups_sdk::anchor::{delegate};
use ephemeral_rollups_sdk::cpi::DelegateConfig;

#[delegate]
#[derive(Accounts)]
pub struct DelegateInput<'info> {
    pub payer: Signer<'info>,
    /// CHECK The pda to delegate
    #[account(mut, del)]
    pub pda: AccountInfo<'info>,
}
```

### Delegate Instruction Implementation

The delegate instruction uses the generated `delegate_pda` method:

```rust anchor-counter/programs/anchor-counter/src/lib.rs theme={null}
pub fn delegate(ctx: Context<DelegateInput>) -> Result<()> {
    ctx.accounts.delegate_pda(
        &ctx.accounts.payer,
        &[COUNTER_SEED],
        DelegateConfig {
            // Optionally set a specific validator from the first remaining account
            validator: ctx.remaining_accounts.first().map(|acc| acc.key()),
            ..Default::default()
        },
    )?;
    Ok(())
}
```

### DelegateInput Accounts

<ParamField path="payer" type="Signer" required>
  The account paying for delegation buffer and record creation
</ParamField>

<ParamField path="pda" type="AccountInfo" required>
  The PDA account to delegate. Must be marked with `#[account(mut, del)]`
</ParamField>

<ParamField path="system_program" type="Program">
  System program (auto-generated by #\[delegate] macro)
</ParamField>

<ParamField path="owner_program" type="Program">
  The program that owns the PDA (auto-generated by #\[delegate] macro)
</ParamField>

<ParamField path="delegation_buffer" type="AccountInfo">
  Buffer account for storing delegated account data (auto-generated)
</ParamField>

<ParamField path="delegation_record" type="AccountInfo">
  Record tracking the delegation state (auto-generated)
</ParamField>

<ParamField path="delegation_metadata" type="AccountInfo">
  Metadata about the delegation (auto-generated)
</ParamField>

<ParamField path="delegation_program" type="Program">
  The MagicBlock delegation program (auto-generated)
</ParamField>

## DelegateConfig Parameters

### pda\_seeds

<ParamField path="pda_seeds" type="&[&[u8]]" required>
  The seeds used to derive the PDA. Required for the delegation program to verify PDA ownership.

  ```rust theme={null}
  &[COUNTER_SEED]  // Example: &[b"counter"]
  ```
</ParamField>

### validator

<ParamField path="validator" type="Option<Pubkey>">
  Optional validator public key to specify which Ephemeral Rollup validator should process this account.

  * If `None`, uses the default validator
  * Can be provided via `remaining_accounts` in Anchor

  ```rust theme={null}
  validator: ctx.remaining_accounts.first().map(|acc| acc.key())
  ```
</ParamField>

### commit\_frequency\_ms

<ParamField path="commit_frequency_ms" type="Option<u32>">
  Optional commit frequency in milliseconds. Controls how often the ER automatically commits account state back to the base layer.

  * If `None`, uses default commit frequency
  * Specified in milliseconds

  ```rust theme={null}
  DelegateConfig {
      commit_frequency_ms: Some(5000), // Commit every 5 seconds
      ..Default::default()
  }
  ```
</ParamField>

## Native Rust Delegation Pattern

### Delegate Account Function

For native Rust programs, use the `delegate_account` function from the SDK:

```rust rust-counter/src/processor.rs theme={null}
use ephemeral_rollups_sdk::cpi::{
    delegate_account, DelegateAccounts, DelegateConfig,
};

pub fn process_delegate(_program_id: &Pubkey, accounts: &[AccountInfo]) -> ProgramResult {
    // Get accounts
    let account_info_iter = &mut accounts.iter();
    let initializer = next_account_info(account_info_iter)?;
    let system_program = next_account_info(account_info_iter)?;
    let pda_to_delegate = next_account_info(account_info_iter)?;
    let owner_program = next_account_info(account_info_iter)?;
    let delegation_buffer = next_account_info(account_info_iter)?;
    let delegation_record = next_account_info(account_info_iter)?;
    let delegation_metadata = next_account_info(account_info_iter)?;
    let delegation_program = next_account_info(account_info_iter)?;
    let validator_account = account_info_iter.next();

    // Optional: client-provided validator or default validator
    let validator_pubkey: Option<Pubkey> = validator_account.map(|acc_info| acc_info.key.clone());

    // Prepare counter pda seeds
    let seed_1 = b"counter";
    let seed_2 = initializer.key.as_ref();
    let pda_seeds: &[&[u8]] = &[seed_1, seed_2];

    let delegate_accounts = DelegateAccounts {
        payer: initializer,
        pda: pda_to_delegate,
        owner_program,
        buffer: delegation_buffer,
        delegation_record,
        delegation_metadata,
        delegation_program,
        system_program,
    };

    let delegate_config = DelegateConfig {
        validator: validator_pubkey,
        ..Default::default()
    };

    delegate_account(delegate_accounts, pda_seeds, delegate_config)?;

    Ok(())
}
```

### Native Rust Required Accounts

<ParamField path="initializer" type="Signer" required>
  The payer and signer for the delegation transaction
</ParamField>

<ParamField path="system_program" type="AccountInfo" required>
  The Solana system program
</ParamField>

<ParamField path="pda_to_delegate" type="AccountInfo" required>
  The PDA account being delegated
</ParamField>

<ParamField path="owner_program" type="AccountInfo" required>
  The program that owns the PDA being delegated
</ParamField>

<ParamField path="delegation_buffer" type="AccountInfo" required>
  Buffer account for storing the delegated account's data
</ParamField>

<ParamField path="delegation_record" type="AccountInfo" required>
  Record account tracking the delegation state
</ParamField>

<ParamField path="delegation_metadata" type="AccountInfo" required>
  Metadata account for the delegation
</ParamField>

<ParamField path="delegation_program" type="AccountInfo" required>
  The MagicBlock delegation program
</ParamField>

<ParamField path="validator_account" type="AccountInfo">
  Optional validator account for specifying the ER validator
</ParamField>

## Pinocchio Delegation Pattern

### Using Pinocchio SDK

The Pinocchio framework provides its own delegation function:

```rust pinocchio-counter/src/processor.rs theme={null}
use ephemeral_rollups_pinocchio::instruction::delegate_account;
use ephemeral_rollups_pinocchio::types::DelegateConfig;

pub fn process_delegate(
    _program_id: &Address,
    accounts: &[AccountView],
    bump: u8,
) -> ProgramResult {
    let [initializer, pda_to_delegate, owner_program, delegation_buffer, 
         delegation_record, delegation_metadata, _delegation_program, 
         system_program, rest @ ..] = accounts
    else {
        return Err(ProgramError::NotEnoughAccountKeys);
    };
    
    let validator = rest.first().map(|account| *account.address());

    let seed_1 = b"counter";
    let seed_2 = initializer.address().as_ref();
    let seeds: &[&[u8]] = &[seed_1, seed_2];

    let delegate_config = DelegateConfig {
        validator,
        ..Default::default()
    };

    delegate_account(
        &[
            initializer,
            pda_to_delegate,
            owner_program,
            delegation_buffer,
            delegation_record,
            delegation_metadata,
            system_program,
        ],
        seeds,
        bump,
        delegate_config,
    )?;

    Ok(())
}
```

<Note>
  The Pinocchio pattern requires an explicit `bump` parameter for PDA derivation.
</Note>

## Best Practices

1. **Always validate PDA seeds** - Ensure the PDA can be properly derived before delegation
2. **Specify validator when needed** - Use the validator parameter for targeting specific ER nodes
3. **Use remaining\_accounts for flexibility** - Pass optional validator through remaining accounts
4. **Set appropriate commit frequency** - Balance between data freshness and transaction costs

## Related Instructions

* [Commit Instructions](/api/commit-instructions) - Manual commit and undelegation
* Program Instructions - Other program-specific operations
