Enums
Enums (enumerations) define a type with a fixed set of named values. They’re perfect for representing states, choices, or categories.
Source: User-defined types
Declaring an Enum
Use the enum keyword followed by the type name and variant names:
enum GameState { waiting, playing, finished }
Variants are separated by commas. A trailing comma is allowed but not required.
enum Direction {
north,
east,
south,
west,
}
Accessing Enum Variants
Use dot notation to access enum variants:
enum GameState { waiting, playing, finished }
enum Direction { north, east, south, west }
export pure circuit variants(): GameState {
const state = GameState.waiting;
const dir = Direction.north;
return state;
}
Source: User-defined types
Note: Use dot notation to access enum variants:
GameState.waiting
Comparing Enums
Compare enum values with == and !=:
enum Status { pending, approved, rejected }
export pure circuit isApproved(status: Status): Boolean {
return status == Status.approved;
}
export pure circuit notRejected(status: Status): Boolean {
return status != Status.rejected;
}
Source: Writing a contract
Enums in Control Flow
Enums work naturally in conditionals:
enum GameState { waiting, playing, finished }
export pure circuit canJoin(state: GameState): Boolean {
if (state == GameState.waiting) {
return true;
}
return false;
}
export pure circuit getStateMessage(state: GameState): Uint<8> {
if (state == GameState.waiting) {
return 0; // "Waiting for players"
}
if (state == GameState.playing) {
return 1; // "Game in progress"
}
return 2; // "Game finished"
}
Default Values
The default value of an enum is its first variant:
enum Status { pending, approved, rejected }
export pure circuit defaultStatus(): Status {
const s = default<Status>; // Status.pending (first variant)
return s;
}
Source: Default values
Enums in Ledger State
Enums can be stored directly in ledger fields:
enum ContractState { initialized, active, paused, terminated }
export ledger state: ContractState;
Source: Declaring public state
Enums in Structs
Enums work well as struct fields:
enum OrderStatus { pending, processing, shipped, delivered, cancelled }
struct Order {
orderId: Uint<64>,
customerId: Bytes<32>,
amount: Uint<64>,
status: OrderStatus
}
export ledger orders: Map<Uint<64>, Order>;
Source: User-defined types
Casting Enums to Field
Enums can be cast to Field type:
enum Choice { rock, paper, scissors }
export pure circuit paperIndex(): Field {
// Enum to Field (by variant index: rock=0, paper=1, scissors=2)
const choiceField = Choice.paper as Field; // 1
return choiceField;
}
Note: Enums also cast to
Uint<n>(conversion, yielding the variant index), and integers cast back to enums as a checked cast — it compiles and runs, but fails at runtime if the value exceeds the last variant index (e.g.,5 is greater than maximum enum value 2). Verified with toolchain 0.31.1.
Source: Type casts
Exporting Enums
To use an enum from TypeScript, you must export it:
// ✅ Accessible from TypeScript
export enum GameState { waiting, playing, finished }
// ❌ Not accessible from TypeScript (internal only)
enum InternalState { a, b, c }
Source: Top-level exports
TypeScript Representation
Enum values are represented as numbers at runtime in JavaScript/TypeScript:
// Compact
export enum GameState {
waiting,
playing,
finished,
}
// TypeScript runtime representation - numeric values
// waiting = 0, playing = 1, finished = 2
Source: Contract constructor
Common Patterns
State Machine
Enums are ideal for representing state machines:
enum AuctionState { open, closed, finalized }
export ledger auctionState: AuctionState;
// Check state in pure circuits
export pure circuit isOpen(state: AuctionState): Boolean {
return state == AuctionState.open;
}
export pure circuit isClosed(state: AuctionState): Boolean {
return state == AuctionState.closed;
}
Multiple Choice
enum Vote { yes, no, abstain }
struct Ballot {
voter: Bytes<32>,
choice: Vote
}
export ledger ballots: Map<Bytes<32>, Ballot>;
// Pure circuit to check vote
export pure circuit isYesVote(vote: Vote): Boolean {
return vote == Vote.yes;
}
export pure circuit isNoVote(vote: Vote): Boolean {
return vote == Vote.no;
}
Complete Example
pragma language_version >= 0.16;
// Game states
export enum GamePhase { setup, betting, reveal, payout }
// Player choices
export enum Choice { rock, paper, scissors }
// Game result
export enum Result { player1Wins, player2Wins, draw }
// Determine winner based on choices
export pure circuit determineWinner(p1: Choice, p2: Choice): Result {
// Draw if same choice
if (p1 == p2) {
return Result.draw;
}
// Rock beats scissors
if (p1 == Choice.rock) {
if (p2 == Choice.scissors) {
return Result.player1Wins;
}
return Result.player2Wins;
}
// Paper beats rock
if (p1 == Choice.paper) {
if (p2 == Choice.rock) {
return Result.player1Wins;
}
return Result.player2Wins;
}
// Scissors beats paper
if (p2 == Choice.paper) {
return Result.player1Wins;
}
return Result.player2Wins;
}
// Check if game is in specific phase
export pure circuit isSetupPhase(phase: GamePhase): Boolean {
return phase == GamePhase.setup;
}
export pure circuit isBettingPhase(phase: GamePhase): Boolean {
return phase == GamePhase.betting;
}
Exercises
Complete exercises/05_user_types/02_enums/.