Skip to main content


Step-By-Step Guide

The lifecycle of integrating Ephemeral Rollups in your program is as follows:
1

Write your program

Write your Solana program as you normally would.
2

Add delegation and undelegation hooks in your program

Add CPI hooks to delegate, commit and undelegate state accounts through Ephemeral Rollup sessions.
3

Deploy your program on Solana.

Deploy your program directly on Solana using Anchor or Solana CLI.
4

Ready to execute transactions for delegation and real-time speed

Send transactions without modifications on-chain and off-chain that also comply with the SVM RPC specification.

Counter Example

Counter GIF The following software packages may be required, other versions may also be compatible:
SoftwareVersionInstallation Guide
Solana2.1.21Install Solana
Rust1.82.0Install Rust
Anchor0.31.1Install Anchor
Node22.17.0Install Node

Quick Access

Find the full basic counter example with Anchor framework implementation, or check out the Rust Native implementation:

Code Snippets

  • 1. Write program
  • 2. Delegate
  • 3. Deploy
  • 4. Test
The program implements two main instructions:
  1. initialize: Sets the counter to 0
  2. increment: Increments the counter by 1
The program implements specific instructions for delegating and undelegating the counter:
  1. Delegate: Delegates counter from Base Layer to ER (called on Base Layer)
  2. CommitAndUndelegate: Schedules sync of counter from ER to Base Layer, and undelegates counter on ER (called on ER)
  3. Commit: Schedules sync of counter from ER to Base Layer (called on ER)
  4. Undelegate: Undelegates counter on the Base Layer (called on Base Layer through validator CPI)
#[ephemeral]
#[program]
pub mod anchor_counter {
    use super::*;

    /// Initialize the counter.
    pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
        let counter = &mut ctx.accounts.counter;
        counter.count = 0;
        Ok(())
    }

    /// Increment the counter.
    pub fn increment(ctx: Context<Increment>) -> Result<()> {
        let counter = &mut ctx.accounts.counter;
        counter.count += 1;
        Ok(())
    }

    /// Delegate the account to the delegation program
    /// Set specific validator based on ER, see https://docs.magicblock.gg/pages/get-started/how-integrate-your-program/local-setup
    pub fn delegate(ctx: Context<DelegateInput>) -> Result<()> {
    // ...
    }

    /// Increment the counter and manually commit the account in the Ephemeral Rollup session.
    pub fn increment_and_commit(ctx: Context<IncrementAndCommit>) -> Result<()> {
    // ...
    }

    /// Undelegate the account from the delegation program
    pub fn undelegate(ctx: Context<IncrementAndCommit>) -> Result<()> {
    // ...
    }
}

/// Context for initializing counter
#[derive(Accounts)]
pub struct Initialize<'info> {
    #[account(init_if_needed, payer = user, space = 8 + 8, seeds = [TEST_PDA_SEED], bump)]
    pub counter: Account<'info, Counter>,
    #[account(mut)]
    pub user: Signer<'info>,
    pub system_program: Program<'info, System>,
}


/// Context for incrementing counter
#[derive(Accounts)]
pub struct Increment<'info> {
    #[account(mut, seeds = [TEST_PDA_SEED], bump)]
    pub counter: Account<'info, Counter>,
}

/// Counter struct
#[account]
pub struct Counter {
    pub count: u64,
}

/// Other context for delegation


Nothing special here, just a simple Anchor program that increments a counter. The only difference is that we’re adding the ephemeral macro for undelegation and delegate macro to inject some useful logic to interact with the delegation program.⬆️ Back to Top


Solana Explorer

Get insights about your transactions and accounts on Solana:

Solana RPC Providers

Send transactions and requests through existing RPC providers:

Solana Validator Dashboard

Find real-time updates on Solana’s validator infrastructure:

Server Status

Subscribe to Solana’s and MagicBlock’s server status:

MagicBlock Products