A decentralized lottery program on Solana with verifiable randomness.
- Participants can buy multiple tickets
- Each ticket has a unique number
- At the end of the lottery, a winning ticket is drawn using Switchboard VRF
- The owner of the winning ticket receives the prize pool
┌─────────────┐ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────────┐
│ Users │ │ Solana │ │ Keeper │ │ Switchboard Oracle │
│ │ │ │ │ (CLI/Bot) │ │ (TEE) │
└──────┬──────┘ └────────┬────────┘ └────────┬────────┘ └──────────┬──────────┘
│ │ │ │
│ enter_ticket │ │ │
├────────────────────>│ (Open Lotto) │ │
│ │ │ │
│ │ (when pot ends) │ │
│ │ │ │
│ │ randomnessInit │ │
│ │<──────────────────────┤ │
│ │ (Switchboard program) │ │
│ │ │ │
│ │ randomnessCommit │ │
│ │<──────────────────────┤ │
│ │ (Switchboard program) │ │
│ │ │ │
│ │ draw_lottery │ │
│ │<──────────────────────┤ │
│ │ (Open Lotto) │ │
│ │ │ │
│ │ randomnessReveal │ (watches chain, │
│ │<────────────────────────────────────────────────┤
│ │ (Switchboard program) │ reveals when ready) │
│ │ │ │
│ │ settle_lottery │ │
│ │<──────────────────────┤ │
│ │ (Open Lotto) │ │
│ │ │ │
│ claim_prize │ │ │
├────────────────────>│ (Open Lotto) │ │
│ │ │ │
Located in programs/open-lotto/. Handles:
- Pot Manager: Controls lottery configuration and rolling pots
- Pots: Time-bounded lottery rounds with ticket sales
- Tickets: Individual entries linked to participants
- Treasury: Collects fees (10% of ticket price)
Located in cli/. A Rust CLI that can act as a keeper bot:
init- Initialize pot manager with rolling potsdraw- Request randomness and call draw_lotterysettle- Wait for reveal and settle the winnerdraw-and-settle- Full cycle in one command
Uses Switchboard On-Demand for verifiable randomness:
- randomnessInit - Create randomness account with LUT
- randomnessCommit - Lock in slot, oracle signs commitment
- Oracle reveals - TEE computes and writes random value
- Program reads - settle_lottery picks winner from revealed value
PotManager (PDA: ["manager", authority, name])
├── authority: Pubkey
├── treasury: Pubkey
├── timestamps: (current_pot_end, next_pot_end)
└── pot_duration: u64
Pot (PDA: ["pot", pot_manager, end_timestamp])
├── total_participants: u64
├── start_timestamp: u64
├── end_timestamp: u64
├── winning_slot: u64
└── randomness_account: Pubkey
Ticket (PDA: ["ticket", pot, index])
├── participant: Pubkey
└── index: u64
Treasury (PDA: ["treasury", authority])
└── (holds 10% fees)
Escrow (PDA: ["stateEscrow"])
└── (holds 90% prize pool)
- Setup: Keeper calls
initto create pot manager + first two pots - Ticket Sales: Users call
enter_ticketduring pot's time window - Draw: When pot ends, keeper calls
draw(creates randomness, commits) - Reveal: Switchboard oracle reveals random value (~5-10 seconds)
- Settle: Keeper calls
settleto determine winner - Claim: Winner calls
claim_prizeto collect the pot
# Build program
anchor build
# Run tests (uses LiteSVM with mocked randomness)
cargo test
# Build CLI
cd cli && cargo build
# Run CLI (uses Solana CLI config)
./target/debug/open-lotto init --name daily --duration 86400- Program: Deployed to devnet at
GMECsoFXBjDcsA7GuVUq1vFmCM27qJumw4Y1rGsxseui - CLI: Complete
- Switchboard: Blocked on devnet (oracle keys expired)
| Operation | Cost |
|---|---|
| Deploy program | ~2 SOL |
| Init pot manager | ~0.02 SOL |
| Buy ticket | 0.01 SOL + rent |
| Draw + Settle | ~0.01 SOL |