Smart Contract
The on-chain program powering trustless rock-paper-scissors duels on Solana.
Program Address
jkNTeh1BrczeEZdJWYbVDBjgso7rfKZBVACNgvPk5utOverview
The Janken program is deployed on Solana and implements a trustless, commit-reveal based rock-paper-scissors game. The contract guarantees fairness through cryptographic commitments and enforces deterministic settlement logic on-chain.
All game state is stored in program-derived accounts (PDAs) with transparent, auditable transitions. Token transfers are handled via Solana's SPL Token program, ensuring atomic execution.
Instructions
The program exposes five core instructions that manage the complete game lifecycle.
create_game
CoreInitializes a new game instance. The creator stakes tokens and submits a cryptographic commitment hash of their move. Creates a game account and associated treasury PDA to hold staked funds.
Arguments
stake_amount: u64
Amount of tokens to stake (must meet minimum)commitment_hash: [u8; 32]
keccak256 hash of (move || nonce || salt)
Key Accounts
- • game (writable, signer)
- • creator (writable, signer)
- • creator_token (writable)
- • game_treasury (writable, PDA)
join_game
CoreAllows a second player to join an existing game. Stakes an equal amount and submits their own commitment hash. After this instruction, the game transitions to the reveal phase.
Arguments
commitment_hash: [u8; 32]
keccak256 hash of joiner's (move || nonce || salt)
Key Accounts
- • game (writable)
- • joiner (writable, signer)
- • joiner_token (writable)
- • game_treasury (writable, PDA)
reveal
CorePlayers reveal their actual moves by providing the plaintext move and salt. The program verifies the reveal against the stored commitment. Once both players reveal, the game is settled automatically with funds distributed according to the outcome.
Arguments
move_choice: Move
Rock | Paper | Scissorssalt: string
Random nonce used in commitment
Key Accounts
- • game (writable)
- • player (signer)
- • player0_token (writable)
- • player1_token (writable)
- • platform_fee_account (writable)
Settlement Logic: Win (90% to winner), Loss (0%), Tie (100% refund, no burn). The 10% burn is sent to the platform fee account on decisive outcomes.
claim_on_timeout
TimeoutAllows the revealing player to claim the full pot if their opponent fails to reveal within the deadline. Prevents griefing by penalizing non-revealing players. No burn occurs—winner takes all.
Requirements
- • Reveal deadline must have passed
- • Caller must have already revealed
- • Opponent must not have revealed
Key Accounts
- • game (writable)
- • caller (signer)
- • player0_token (writable)
- • player1_token (writable)
close_game
CleanupCloses a finished game account and reclaims rent. Can only be called after the game is fully settled. Transfers any remaining SOL rent to the closer.
Key Accounts
- • game (writable)
- • closer (writable, signer)
- • game_treasury (writable, PDA)
Account Structures
Game
The primary account type storing all game state.
Type Definitions
GameState (Enum)
- WaitingForPlayerInitial state, awaiting second player
- WaitingForRevealBoth players committed, awaiting reveals
- FinishedGame settled, ready for cleanup
Move (Enum)
- RockBeats Scissors
- PaperBeats Rock
- ScissorsBeats Paper
Error Codes
The program defines custom errors for precise failure handling.
6000
InvalidGameState
Operation not valid for current game state6001
RevealTimeout
Reveal deadline exceeded6002
NotAPlayer
Caller is not a player in this game6003
InvalidReveal
Reveal does not match commitment hash6004
NotTimedOut
Timeout claim invalid, deadline not reached6005
CallerNotRevealed
Caller must reveal before claiming timeout6006
InvalidPlatformWallet
Platform fee account invalid6007
InvalidGameToken
Token mint does not match expected6008
InvalidTimeoutClaim
Timeout claim conditions not metSecurity Guarantees
The contract enforces fairness through a two-phase commit-reveal scheme. Commitments are validated using keccak256, providing collision resistance and preimage security.
Timeout mechanisms prevent griefing: if a player refuses to reveal, their opponent can claim the full pot after the deadline. All state transitions are atomic and deterministic, eliminating race conditions.
The program uses PDAs for treasury accounts, ensuring only the program can authorize token transfers. No external authority can drain funds or manipulate outcomes.
Technical Specifications
0.1.0
0.1.0
5
1
9