This document specifies the complete mechanics and economics of Gacha Wars: what a spin does, where every lamport goes, what the game returns to players in expectation, and why none of it requires trusting the operator. Everything below is a property of the on-chain program, not of this website — each claim comes with the means to check it.
Gacha Wars is a game of chance on Solana with one deliberate property: nothing about it is private except the operator's infrastructure. A spin costs 0.3 SOL and wins a seat on a shared 100-seat board with probability exactly ½, decided by a verifiable random function rather than by anything we run. Seats earn a share of every subsequent spin. When the board is full, each new winner takes over one seat chosen at random; the outgoing player is paid automatically — their escrowed exit plus everything the seat accrued.
Three claims distinguish the design, and each is a theorem about the program rather than a promise from a team. First, the odds are exact: a 50/50 whose outcome anyone can recompute from public data (§05). Second, the economics are total: every parameter is a compile-time constant, and the aggregate return to players — 84.405% of all SOL wagered — is published along with the operator's complement of 15.595% (§04). Third, the pool is self-funding and players are structurally senior: the game launched with zero operator capital, and whenever player claims exceed pool cash, one hundred percent of the house's fees are permanently redirected to close the gap — the house is paid last, after every player, every time (§06).
A spin is not one event but three, and the separation is what makes the game verifiable end to end.
Your wallet sends request_spin. The program collects 0.3 SOL, derives a unique seed from the request account, your public key, and a nonce, and asks an on-chain verifiable random function (MagicBlock's ephemeral-vrf) for the bytes that will decide the outcome. The request joins a strict first-in, first-out queue: no spin can be settled out of order, reordered by the operator, or skipped.
The oracle answers by delivering 32 bytes of randomness together with the proof that they were generated correctly. The proof is an RFC 9381 ECVRF verified by the randomness program itself, on-chain, and the delivery is authenticated: only that program's identity may write an outcome onto your spin, and once written it can never be revised — not by us, not by the oracle. Typical delivery is under a second. Neither we nor you can influence the value; both of us can check it.
Anyone — our keepers, you, a stranger — may settle the queue head once its randomness is fulfilled. The outcome is one line of arithmetic: interpret the first eight bytes as an unsigned integer, little-endian; even wins, odd doesn't.
Settlement takes exactly one of three paths:
If the oracle fails to respond within 300 seconds, anyone may expire the request and the player reclaims the full 0.3 SOL. A queued spin therefore has exactly two futures: settled by the rules, or refunded in full.
The program moves money along fixed rails. There are no discretionary flows, and the rails are compile-time constants — changing any of them is a source-code change that produces a different, publicly visible program.
| Event | Movement | Amount |
|---|---|---|
| Spin without a seat | to the pool (funds drip and exits) | 0.210 SOL |
| to the treasury (operator) | 0.090 SOL | |
| Spin that wins a seat | to the pool | 0.300 SOL |
| escrowed at once for that seat's exit | 0.357 SOL | |
| Every settled spin | released as drip, split equally across occupied seats | 0.0765 SOL |
| Seat takeover | to the outgoing player (escrow, net of 1% fee) | 0.35343 SOL |
| takeover fee to the treasury | 0.00357 SOL |
At a full board the per-seat drip is exact: 0.0765 ÷ 100 = 0.000765 SOL per seat per spin. The outgoing player additionally receives every lamport of drip their seat accrued and had not yet claimed — leaving is always a payout, never a forfeiture.
These flows are not merely documented; they are enforced against each other. The program refuses to compile unless the following identities hold:
The last two lines say something worth pausing on: a winning spin and a non-winning spin move the pool's equity by the same magnitude in opposite directions — the game is a fair-odds martingale over a published house margin, not a curve someone tuned.
Most games of chance publish their odds reluctantly, if at all. Here the full expectation is short enough to derive by hand, so we do it in front of you. Figures assume the steady state — a full board — which is where the game spends nearly all of its life.
Each spin takes over a given seat with probability ½ × 1⁄100 = 0.5%. Seat lifetime is therefore geometric: 200 spins on average, with a median of ln 2 ÷ 0.005 ≈ 139 spins — half of all seats rotate out before their 139th spin, and long tenures are exponentially rare rather than impossible.
The floor deserves emphasis: because the exit is escrowed at the moment a seat is won, the worst possible outcome of a winning spin is +17.81%. Drip can only improve it.
The aggregate return to players is 84.405% of all SOL wagered; the operator retains 15.595%. As a check, compute the house side independently: the treasury collects 0.09 on half of all spins and the 0.00357 takeover fee on the other half — 0.5 × 0.09 + 0.5 × 0.00357 = 0.046785 = 15.595% of 0.3. The same number arrives from opposite directions, which is what it means for an economy to be closed.
Every claim about odds reduces to one question: where do the deciding bytes come from? Here they come from MagicBlock's ephemeral-vrf — an RFC 9381 elliptic-curve VRF whose proof is verified on-chain by the randomness program itself, in the open, before your outcome can exist. The program is open source and independently audited.
The binding works like this. The seed is derived deterministically from the spin request account, your wallet's public key, and a nonce, and it is recorded on-chain the moment you pay — before any randomness exists. The oracle then delivers the bytes back into that exact spin. The operator cannot shop for outcomes, and neither can you.
Two properties make the delivery trustworthy without trusting anyone. First, only the randomness program's own identity may deliver: the game rejects an outcome signed by anything else, so a forged result is not merely detected, it is unconstructible. Second, randomness is write-once — once an outcome is recorded it can never be revised, by us or by the oracle. And a spin whose randomness never arrives is refundable in full by anyone after 300 seconds, so there is no state in which a paid spin simply disappears.
Verification requires no cooperation from us. Every settled spin publishes its randomness in an on-chain event alongside the seed it was bound to, so any observer can replay the whole history — yours or a stranger's — and recompute each outcome with one line of arithmetic:
For the aggregate rather than the individual view, the verification page recomputes the published totals — spins settled, SOL paid out, realized return to player — from raw chain events and reconciles them against an independent RPC read, live, in your browser.
The catastrophic failure of games like this one is a payout the pool cannot cover. Gacha Wars answers it without a single lamport of operator capital: the pool launched empty and funds itself from play, with the house's own fee subordinated to every player claim.
Define the pool's backing gap as everything it owes — every recorded exit and every lamport of accrued, unclaimed drip — minus its cash. Exits only ever come due when the board is full, and filling the board pours roughly two hundred spins of revenue into the pool first, so the gap is an accounting number, not missing payout money. Whenever it is positive, the program permanently redirects one hundred percent of the house's fees into the pool until it closes:
A miss repairs the gap by 0.2235 SOL against 0.1335 of damage per win, so closure is fast in expectation, and the treasury reads zero income for the entire life of any gap — the house is paid only when every player claim is fully cash-backed. Exits themselves pay in the same transaction as the winning spin in every reachable state; in the astronomically remote alternative (odds on the order of 10⁻⁴⁵), the exact amount becomes a numbered claim, first in line ahead of all fees, paid from the very next revenue. Nothing is ever reduced, cancelled, or renegotiated. The invariant suite asserts all of this after every instruction, in every test, under both denominations.
A fair game you cannot exit is not fair. The design therefore treats the operator as a convenience, never a dependency, and enumerates exactly what we can and cannot do.
| Action | Who can perform it |
|---|---|
| Settle a fulfilled spin | Anyone. Our keepers run for liveness; a stranger's transaction settles identically. |
| Expire a stalled request (after 300 s) for a full refund | Anyone. |
| Trigger an outgoing player's payout | Anyone — it is part of settlement itself. |
| Pause the game | The operator — new spins only. Settlement, payouts, refunds and exits can never be paused, by anyone, including us. |
| Change the odds, prices, or fees | No one. They are compile-time constants; changing them means deploying visibly different code. |
The asymmetry is deliberate: every power that protects players is permissionless, and the one power reserved to the operator can only stop money from coming in — never stop it from going out.
The operator's revenue has exactly two sources, both visible in §03: 0.09 SOL from each spin that doesn't win a seat, and the 1% fee (0.00357 SOL) on each exit escrow at takeover. In expectation this totals 15.595% of turnover — the exact complement of the published return to player, because the economy has nowhere else for a lamport to go.
Treasury funds accrue in a program account and are withdrawn to the operations multisig. They fund what you would expect: oracle fees, infrastructure, and audits. Both fees are subordinated to players (§06): during any backing gap they are permanently forfeited into the pool instead — so the operator's realized take is provably at or below the published 15.595%, forever.
Before a wallet's first spin, the program requires an on-chain attestation: that the player is of legal age in their jurisdiction and accepts the current terms of service (version 1). The interface additionally gates play by jurisdiction. A wallet-level self-exclusion registry is enforced by the program itself — an excluded wallet's spins are refused at the door, by code, not by customer support.
The complete economic surface of the game. Names are the actual constants in the program source; a build in which any identity of §03 fails does not compile.
| Parameter | Constant | Value |
|---|---|---|
| Spin price | SPIN_PRICE | 0.3 SOL |
| Win probability | WIN_MODULUS = 2 | exactly ½ |
| Board size | BOARD_SIZE | 100 seats |
| Non-winning spin → pool | MISS_TO_POOL | 0.21 SOL |
| Non-winning spin → treasury | MISS_TO_TREASURY | 0.09 SOL |
| Winning spin → pool | WIN_TO_POOL | 0.30 SOL |
| Exit escrow (gross) | EXIT_ESCROW_GROSS | 0.357 SOL |
| Takeover fee (1% of escrow) | KICK_FEE | 0.00357 SOL |
| Exit paid, net | EXIT_PAID_NET | 0.35343 SOL |
| Drip per spin (all seats) | DRIP_PER_SPIN | 0.0765 SOL |
| Drip per seat, full board | — derived | 0.000765 SOL |
| Equity swing per settled spin | NET_EQUITY_DELTA | ±0.1335 SOL |
| Randomness timeout → refund | REQUEST_TIMEOUT_SECS | 300 s |
| Launch float | LAUNCH_FLOAT | 30 SOL |
| Return to player | — derived, §04 | 84.405% |
| Operator margin | — derived, §04 | 15.595% |
Program: 5f1F3YFDnJsYqbcju31Mv2yNYtA3RnGidSMX2YggbavR. For the full formal treatment — proofs, event schemas, and the verification guide — read the whitepaper.