Skip to main content

Crate alea_sdk

Crate alea_sdk 

Source
Expand description

§alea-sdk

CPI crate for Alea — the first production drand BN254 BLS verifier on Solana. Any Anchor program can receive verified on-chain randomness with a single CPI call.

§Quick Start

Add the mandatory constraints to your Accounts struct and call cpi::verify:

use alea_sdk::{self, AleaVerifier};
use anchor_lang::solana_program::sysvar::clock::Clock;

const MAX_BEACON_AGE_SECONDS: u64 = 30;

#[derive(Accounts)]
pub struct SettleMatch<'info> {
    pub alea_program: Program<'info, AleaVerifier>,
    #[account(
        seeds = [b"config"],
        bump,
        seeds::program = alea_program.key(),   // ← MANDATORY (ADR 0034)
    )]
    pub alea_config: Account<'info, alea_sdk::Config>,
    pub payer: Signer<'info>,
    pub clock: Sysvar<'info, Clock>,
}

pub fn settle_match(ctx: Context<SettleMatch>, round: u64, sig: [u8; 64]) -> Result<()> {
    // MANDATORY: reject stale beacons before CPI
    require!(
        alea_sdk::is_round_recent(round, &ctx.accounts.alea_config, &ctx.accounts.clock, MAX_BEACON_AGE_SECONDS),
        YourError::StaleBeacon,
    );
    // One-line CPI. Returns VerifiedRandomness (must_use wrapper).
    let randomness = alea_sdk::cpi::verify(
        ctx.accounts.alea_program.to_account_info(),
        ctx.accounts.alea_config.to_account_info(),
        ctx.accounts.payer.to_account_info(),
        round, sig,
    )?.into_inner();
    // Read IMMEDIATELY — Solana return data is overwritten by any subsequent CPI
    let random_value = u64::from_le_bytes(randomness[0..8].try_into().unwrap());
    // … use randomness …
    Ok(())
}

§Security: Mandatory Constraints

Two constraints are MANDATORY for ANY consumer (omitting either ships an exploitable program):

  1. seeds::program = alea_program.key() on the alea_config account. Without this, an attacker can substitute a fake Config PDA owned by a different program and feed attacker-controlled public keys to the pairing check. This is total compromise for any randomness consumer. (ADR 0034)

  2. is_round_recent() before trusting randomness. Without recency enforcement, an attacker can replay an old drand round whose randomness they already know to bias resolution.

§CPI Return Data Ordering Warning

Solana’s return data is single-slot — each CPI call overwrites the previous value. Read cpi::verify’s result into a local variable IMMEDIATELY, before any other CPI calls (token transfers, etc.).

§Compute Budget

Every transaction calling Alea MUST include a compute budget instruction of at least 900,000 CU (Solana default is 200K; Alea needs up to 454K + consumer headroom). The TypeScript SDK injects this automatically.

§Program IDs

ClusterProgram ID
DevnetALEAydzHd4cN2EWcdHKp4hehAE4B88b16gqVtVqsck2U
MainnetPending Phase 5 (same vanity ID — cluster binding is identical)

Devnet-verified; mainnet deployment pending Phase 5. Cluster binding identical (vanity ID usable on both), mainnet traffic begins Phase 5.

§Maturity

See CAVEATS.md for maturity disclosures before integrating.

Re-exports§

pub use cpi::VerifiedRandomness;

Modules§

accounts
Account type re-exports for Alea CPI consumers.
cpi
CPI wrapper for Alea’s verify instruction.
errors
Error type re-exports for Alea CPI consumers.

Structs§

AleaVerifier
Type representing the program.
Config
drand evmnet configuration account.

Enums§

AleaError
Alea error codes. Codes 6000-6009 are assigned in declaration order and are part of the v1 CPI interface per ADR 0028 — never renumber, never remove (reserved even if unreachable, see NoSquareRoot).

Constants§

PROGRAM_ID
Canonical Alea program ID. Vanity, frozen for the lifetime of the mainnet deployment per ADR 0028. Same ID used across localnet / devnet / mainnet by design — consumer SDKs do not need to branch per cluster.

Functions§

config_pda
Derive the Alea Config PDA for a given program ID.
is_round_recent
Check that a drand round is recent relative to the current on-chain clock. Returns true if the round’s emission timestamp is within max_age_seconds of the current slot’s unix_timestamp.