Awards via staking & multisig
The goal is custody with no custodian - a prize pool no single party can seize, freeze, or skim. This is the plumbing that gets there: a per-match vault, a roster frozen before the dice, a settlement anyone can recompute, and payouts bound to their winners. The crypto is deliberately boring, in service of one idea - the operator should be replaceable, and eventually removable entirely.
The point of all this plumbing is one idea: custody with no custodian. A prize pool no single party can seize, freeze, or skim - held by rules and a signer set instead of a person. The escrow below is deliberately boring; what matters is that every step is bounded by math and contestable by anyone.
#The per-match escrow vault
The ricochet_escrow program opens a token vault per match, folds each joining wallet into an on-chain roster accumulator, then freezes the roster and commits a randomness root - so nobody can pick who's playing after the dice are known. It's an escrow and a notary; it holds no game logic. A match walks a small state machine:
OPEN → PLAYING → COMMITTED → SETTLED- program
- ricochet_escrow · devnet Gm1CjXJAor3sYy2ZvSCxmZSZqj9Q7Wy9NtZp7PuSfEgc
- join
- SPL transfer_checked into the match vault; wallet folded into roster_root.
- lock_match
- operator freezes the roster and commits the randomness root + leaf count.
- commit_codex
- stores the codex root + an IPFS pointer; rejects a roster that disagrees.
#Reserve-then-charge buy-in
Buy-ins move into the vault only as the match actually forms; abort and refund paths exist before commitment, so funds aren't captured for a game that never starts. And a circuit breaker can pause the obligation-creating paths while never blocking the exits - refund, abort and withdraw always stay open. A pause can freeze the game; it can't freeze anyone's money.
#Settlement by Merkle root
At settle, the deterministic result produces a settlement root. Payouts split by score and by loot weight using exact integer (largest-remainder) math - the same code the public auditor runs - and the chain checks the arithmetic: money pot plus top-3 pot plus rake must equal the pot, and the vault must physically hold at least the pot before anything pays out. The randomness seed is revealed here, and a claim deadline is stamped.
- Conservation
- = pot
- money + top-3 + rake must equal the pot, on-chain.
- Collateral check
- ≥ pot
- the vault must cover the pot before any claim.
- Seed
- commit-reveal
- randomness seed committed at lock, revealed at settle.
#Recipient-bound claims
Each winner claims against a Merkle leaf of their standing, paid into an account they own. The operator can neither over-allocate leaves (a remaining-balance counter and a one-shot disbursed flag prevent it) nor redirect a payout (the destination must be authority-owned by the claiming signer):
leaf = settlement_leaf( 0x00 || u16 player_index || wallet32 || u64 amount )
verify(leaf, proof, settlement_root) // must pass
Entry PDA has_one = player // your entry, your claim
player_ata.authority == player (the signer) // paid only to you#Governed by a multisig
This is the "multisig" backstop, and it's a shipped hard requirement, not a nice idea. The program's cold authority is required to be a Squads multisig before mainnet, alongside the program's BPF upgrade authority. A governance check reads both keys on-chain and fails the launch unless each equals the expected multisig; the hot operator key that can forfeit funds can be pinned the same way. Authority itself hands off in two steps (propose, then accept) so it can never be bricked.
#A hard fee ceiling
A protocol constant caps every match and player-claim schedule at a 5% service fee - the code literally cannot configure a rake above it. There is no discretionary house cut hiding in a config somewhere; the ceiling is enforced in the program.
#Toward staked, decentralized custody
Where does staking come in? Today's on-chain co-stake time-locks a slice of the rake - not player winnings - as a public "we're not dumping our rake" signal, on a schedule from no-lock out to three months, with early exit always priced worse than never locking. It's a credibility mechanism, not an emission.