This Anchor program is a modified version of the Death.fun a provably-fair single-player game. It follows the original commit–reveal fairness model while moving gameplay actions on-chain so any third party can verify a full playthrough. Low Solana fees make recording each move practical.
Primary goals and properties:
- Provable fairness via commit–reveal seeds (public and private).
- All player actions are recorded on-chain (
record_action), enabling public verification. - Isolated player deposits for recoverability.
- Censorship-resistant settlement flows: fast admin-signed payouts, player-mark fallback + admin settlement, and a default reclaim path for unresponsiveness.
Prerequisites:
- Rust and Solana toolchain installed
- Anchor CLI
Build:
# build program
anchor build
No tests have been added to the program yet
The program uses a commit–reveal scheme that lets the system commit to game configuration before play while keeping private details secret until reveal.
Notation:
RS— pre-game random seed (off-chain, generated by server).HRS = HASH(RS)— private config seed (secret during play).HPHRS = HASH("public" + HRS)— public config seed (committed at creation).
Per-round derivations (round index r, 0-indexed):
- Move Type Count For Round (MTCFR) — the number of allowed move types (tiles) in round
r:
MTCFR = (LSB( HASH([r] + HPHRS) ) % (MAX_MOVE_TYPE_COUNT - 1)) + 2
- This yields values in the inclusive range
[2 .. MAX_MOVE_TYPE_COUNT]. LSB(...)denotes the least-significant byte of the hash output.
- Fail Move For Round (FMFR) — which move index causes immediate failure:
FMFR = (LSB( HASH([r] + HRS) ) % MTCFR)
FMFRis in the exclusive range[0 .. MTCFR]and is derived from the private seed, so it is unknown to the player while playing.- When
HRSis revealed after game end, anyone can recomputeHPHRS,MTCFR, andFMFRfor each round and verify recorded moves.
This program introduces several settlement flows to improve availability and verifiability compared with an off-chain move model. These flows are described with their trade-offs.
- Player obtains admin-signed authorization off-chain (signed payload bound to session and deadline).
- Player calls
finalize_game_as_wonwith the admin signature. - Program verifies signature, pays the player, and closes the session.
- If the admin is temporarily unresponsive, the player calls
mark_game_as_wonto publicly mark the session as won (no funds moved). - The admin later calls
finalize_game_as_won_for_playerto effect payout and refund deposit; The rent for the accounts used during the game is deducted to cover the const of the transaction for the admin - This makes winning claims publicly visible nudging an unresponsive admin to cooperation.
- If a session is idle beyond
DEFAULT_OFFSET, the player callsdefault_gameand reclaims their original deposit from the per-session vault. - This protects players against permanent loss of funds if the admin never finalizes a payout.
- The offset is added due to the possibilty of the player trying to game the admin by attempting to refund(in the case where no wait time was added) when they realize their previous action was a fail, this leaves room for the admin to mark the game as lost
The additions that were made to the program are only meaningful if the program has no upgrade authority that would allow for this logic to be changed