Skip to main content

Account Structures

The program maintains state across multiple Program Derived Addresses (PDAs).

Account Summary

AccountPDA SeedsSizePurpose
RootAccount["root"]~560 bytesGlobal configuration & state
RoundPage["round_page", tier_id, page_index]~23.5 KBPaged round storage
RoundPlayer["rp", tier_id, round_id, player]86 bytesMembership proof
PlayerStats["ps", season_id, player]129 bytesPer-season statistics
Vault["vault", tier_id, round_id]~165 bytesPrize pool escrow
SeasonSnapshot["season_snapshot", season_id]59 bytesFrozen season data

RootAccount

Global configuration and state for the entire program.

struct RootAccount {
// Authority
authority: Pubkey,
dev_wallet: Pubkey,
orb_mint: Pubkey,

// Season tracking
season_id: u64,
season_rounds_total: u64,
season_rounds_played: u64,
current_season_total_points: u128,
season_pool_orb: u128,

// Genesis state
genesis_done: bool,
conversion_open: bool,
lp_accum_sol: u64,
genesis_threshold_lamports: u64,
genesis_orb_cap: u64,
orbs_minted_from_conversion: u64,
points_per_orb_effective: u64,

// Emission state
total_minted_orb: u128,
emission_budget_cap: u128,
total_rounds_since_genesis: u64,
last_emission_round: u64,
epoch_index: u32,
epoch_rounds: u64,
decay_bps: u16,
hazard_cap_rounds: u64,
emit_base: u128,

// Tier configuration
tier_configs: Vec<TierConfig>,
tier_states: Vec<TierState>,

// Fee configuration
dev_fee_bps: u16,
}

PDA Derivation: ["root"]

RoundPage

Paged storage for round metadata. Each page holds 120 rounds.

struct RoundPage {
tier_id: u8,
page_index: u32,
rounds: [RoundMeta; 120], // zero-copy
}

PDA Derivation: ["round_page", tier_id.to_le_bytes(), page_index.to_le_bytes()]

RoundMeta

Individual round data within a page:

#[repr(C, packed)]
struct RoundMeta {
id: u64, // Unique identifier
season_id: u16, // Season this round belongs to
tier_id: u8, // Associated tier
status: u8, // 0=Open, 1=Countdown, 2=Settled
countdown_start_ts: i64, // Unix timestamp
entry_lamports: u64, // Entry fee
min_players: u16, // Minimum players
max_players: u16, // Maximum capacity
countdown_secs: u32, // Duration
seed_hex: [u8; 32], // Cryptographic seed
seed_hex_present: u8, // Flag: 1 if seed set
joined_count: u16, // Current players
created_ts: i64, // Creation timestamp
did_emit: u8, // Emission flag
}
// Size: 195 bytes per round

RoundPlayer

Membership proof that a player joined a specific round.

struct RoundPlayer {
tier_id: u8,
round_id: u64,
player: Pubkey,
payout_processed: bool,
stats_applied: bool,
account_index: u16, // Join order
referrer: Option<Pubkey>,
}

PDA Derivation: ["rp", tier_id.to_le_bytes(), round_id.to_le_bytes(), player]

PlayerStats

Per-season statistics for a player.

struct PlayerStats {
season_id: u64,
player: Pubkey,
season_points: u64,
total_points: u64,
rounds_played: u32,
wins: u32,
kills: u32,
sol_earned_lamports: u64,
orb_earned_atoms: u64,
season_pool_claimed: bool,
}

PDA Derivation: ["ps", season_id.to_le_bytes(), player]

Vault

Prize pool escrow for a specific round.

struct Vault {
tier_id: u8,
round_id: u64,
balance: u64,
}

PDA Derivation: ["vault", tier_id.to_le_bytes(), round_id.to_le_bytes()]

SeasonSnapshot

Frozen state at season end for claiming.

struct SeasonSnapshot {
season_id: u64,
total_points: u128,
pool_orb_atoms: u128,
orbs_claimed: u128,
finalized: bool,
}

PDA Derivation: ["season_snapshot", season_id.to_le_bytes()]

TierConfig

Configuration for a competition tier:

struct TierConfig {
tier_id: u8,
entry_lamports: u64,
min_players: u16,
max_players: u16,
countdown_secs: u32,
take_profit: u64,
points_multiplier: u16,
}

TierState

Runtime state for a tier:

struct TierState {
tier_id: u8,
last_settled_round_id: u64,
current_page_index: u32,
}

Storage Optimization

Paged Rounds

Rounds are stored in pages to manage Solana's account size limits:

Page Index = floor(round_id / 120)
Slot Index = round_id % 120

PDA-Based Membership

Instead of storing rosters on-chain, membership is proven via RoundPlayer PDAs:

  • Reduces transaction size
  • Enables efficient RPC filtering via memcmp
  • No array size limits

Next Steps