Documentation

The contract: how and why it works

All of FAIRDRUM's funds and all of its rules live in one program on the Solana network — a smart contract. The site only sends it commands and shows the reply. Below: what the contract stores, which commands it understands, how a random number becomes a result, and what the administrator can and cannot do.

What the contract is and where it lives

A smart contract is a program executed by the nodes of the Solana network, not on the project's server. Its code is the same for everyone, and every action is a public transaction. The FAIRDRUM contract is written in Rust with the Anchor library; its source code is open.

The program address will appear here once the site is connected to the contract.

An important consequence: if the fairdrum.to site disappears, players' funds stay in the contract, and they can be withdrawn with any program able to send the withdraw command signed by your wallet.

What the contract stores

  • The vault. A single wrapped-SOL account that only the program itself controls. It holds everything: players' balances, the prize bank, the jackpots, the reserve and the administrator's share that has not been collected yet.
  • The shared game account. A record of how the amount in the vault is divided: prize bank, jackpot, mini jackpot, super jackpot, seed reserve, administrator's share, jackpot start amounts, per-game round counters.
  • The player account. Created by the register command, which the site sends together with the first top-up, and tied to the wallet address: game balance, time of the last top-up, unfinished round, unpaid part of a jackpot.
  • The session account (if “signature-free play” is on): a temporary key, an expiry time and a bet limit.

The bookkeeping is built so that the sum of all balances and pots equals the amount in the vault. A test checks this equality after each of tens of thousands of random operations.

Which commands the contract understands

CommandWho can call itWhat it does
registerplayerCreates the player account. The site sends it together with the first top-up.
depositplayerTops up the game balance. Records the time: the 12 hours until withdrawal are counted from it.
withdrawplayerWithdrawal to your own wallet. Rejected until 12 hours have passed since the last top-up.
spin_committhe player or their session keyThe bet: deducts the round from the balance, records the game and the odds in effect, and requests a random number from the oracle.
spin_settleanyoneSettlement: reads the oracle's number, computes the payout and credits it to the player. Anyone can call it — the result does not depend on who does.
spin_expireanyoneCloses a round that was not settled within 20 minutes. If the oracle did not respond, the bet is refunded to the player in full. If the oracle responded and the round is sealed, it pays the regular prizes without a jackpot draw.
spin_sealanyoneSeals the round: records the hash of the bet's block while it is still available (about 3.5 minutes). It is needed only if the oracle takes longer to respond; usually the keeper service calls it. A round that was not settled or sealed in time is closed without a result.
skip_nonceplayerShifts the number of the next randomness request if the request address turns out to be taken.
session_open / session_closeplayerAllows a temporary key to place bets within a time limit and a bet limit; the key can neither withdraw nor top up.
donateanyonePuts SOL into the jackpot seed reserve. There is no reverse command.
set_jackpot_startsadministratorSets new start amounts for the jackpot and the super jackpot; they take effect after 24 hours.
rescale_poolsadministratorMoves part of the seed reserve into the games' prize bank. Only in this direction; it cannot be moved into the jackpots — they are refilled from the reserve on their own, after a win.
set_pausedadministratorPauses or resumes the acceptance of new bets — in case the oracle fails. Bets already placed are settled, and payouts and withdrawals work as usual.
set_guardian / guard_pauseadministratorThe administrator appoints a guardian — a key of the keeper service that can do only one thing: pause the acceptance of new bets if the oracle has stopped responding. Only the administrator can lift the pause.
propose_dev_authority / accept_dev_authorityadministratorTransfer of the administrator's rights to another key in two steps: the current key names the new one, and the new one confirms it itself.
roll_epoch / checkinanyoneHousekeeping: they update the weekly statistics and the day marker. They do not move funds.
claim_devadministratorCollects the administrator's accumulated share — and only that.
initialize / fund_poolsadministratorOne-time launch. initialize creates the accounts (signed by the holder of the program's upgrade authority); fund_pools records, once, the deposited starting bank across the pots, and any surplus above it in a separate line that the administrator can collect with the promo_pay command.

There is no command in the code that would transfer the prize bank, the jackpots or players' balances to the administrator.

A round step by step

  1. The bet. The spin_commit command deducts the round from your balance and, in the same transaction, creates a random-number request with the ORAO oracle. The request address is derived from your wallet and the round number, so someone else's request cannot be substituted.
  2. The number. Several independent ORAO nodes sign the random number and write it to the network. Until it is written, nobody knows it: not you, not the project, not any single node.
  3. Settlement. The spin_settle command reads the number from the oracle's record, checks that the request is the one for your round, and computes the payout. The site sends it itself; if the page is closed, the project's keeper program will do it, or you will on your next visit.
  4. Display. Cards, mines, the rocket, gems are ways of showing a payout that has already been computed. Your taps in the game do not affect it.

Why the result cannot be known in advance or forged. The final number of a round is the oracle's number mixed with the hash of the block in which the bet is recorded. At the moment of the bet this hash does not yet exist, and the oracle's number arrives later and from a third party: nobody can compute the outcome in advance — not the player, not the project, not the oracle itself. The game, the jackpot start amounts and the prize cap are recorded at the moment of the bet, and the settlement formula is in open code. A late settlement is never more favourable than a timely one. The rules can be changed only by replacing the program's code, and that is visible to everyone (see the section on the administrator).

How a random number becomes a result

A round is 1 to 100 bets of 0.01 SOL each (up to 1000 on the wheel). The oracle's number is expanded into an independent random value for each bet, and for each one the contract answers these questions in turn:

  1. Super jackpot, jackpot, mini jackpot? The chance of each pot equals the bet's contribution to it divided by the pot's start amount. A pot is drawn only when it holds at least 25% of its start amount.
  2. A game prize? Each game has its own prize chance and its own table of six tiers with weights. For example, on the wheel a prize lands in 10% of bets. The tables of all games are shown on their pages.
  3. “Spin again”? With a 11.6% chance the bet is repeated for free at the expense of the prize bank.
  4. Otherwise the bet wins no prize. It is split the same way as any other: prize bank, jackpots and the administrator's share.

The games' tables differ, but the expected payout from them is the same (to within hundredths of a percent; with a prize bank of 40 SOL or more, when prizes do not hit the cap): about 77.5% of the bet in regular prizes, and together with “Spin again” repeats about 88% of paid bets. The compiler checks this equality: if any game's expectation turns out higher than the wheel's, or lower by more than half a percent, the program will not build.

Where the contract puts each bet

Goes toShare of a paid betPurpose
Prize bank≈88%regular prizes of all games
Jackpot, mini jackpot, super jackpot and the seed2%three shared pots
Administrator10%the project's income; there is no other

In the code the shares are written per executed bet, including free repeats, which is why it says 8.84% and 1.77% there: in terms of paid bets this averages 10% and 2%.

The limiting rules and why they are needed

  • A single prize is at most a quarter of the prize bank. The contract cannot promise more than it has, and one big win does not empty the bank for everyone else. Whatever is not paid out stays in the bank.
  • Withdrawal 12 hours after the last top-up. The rule is the same for everyone and is written as a constant: it can only be changed by a new version of the program.
  • Jackpot start amounts change with a 24-hour delay. A round's odds are fixed at the moment of the bet, so they cannot be changed “to fit a bet already placed”.
  • 20 minutes to settle. If the oracle has not responded, the bet is refunded to the player in full: until the number exists, nobody knows the outcome, so a loss cannot be avoided this way. If it responded but the settlement was late, the regular prizes are paid, and the jackpots are not drawn in that round. Vault protection. Before every payout and after every settlement the contract checks that the vault holds no less than it owes to players and pots; otherwise the operation is rejected. Guardian. If the oracle has stopped responding, the acceptance of new bets is paused automatically; settlements and withdrawals keep working.
  • A jackpot is paid in installments: the winner is owed 95% of the pot, of which 20% at once and 8% per week. The unpaid part is recorded on the winner's account.
  • One unfinished round per player. Until the round is settled, a new bet is not accepted.

What the administrator can and cannot do

Can

  • collect his share — 10% of paid bets;
  • put SOL into the reserve and move it from the reserve to the prize bank;
  • collect the surplus that ended up in the vault at launch above the starting bank;
  • change the jackpot start amounts — with a delay and within set bounds;
  • pause the acceptance of new bets if the oracle is not responding, and hand its rights over to another key.

Cannot

  • withdraw the prize bank, the jackpots, the reserve or players' balances (as a player he wins on the same terms as everyone else);
  • change the prize tables, the games' prize chance or the bet shares: these are constants in the code;
  • learn a round's random number before the bet, or choose it;
  • stop the settlement of placed bets or withdrawals: the pause applies only to new bets.

An honest caveat. The program has an upgrade authority: until it is revoked, its holder can replace the code with a new version, and then everything said above will apply to the new code. The state of this authority and every upgrade are visible in a Solana explorer. There is no independent audit of the contract.

How this is tested

  • Contract tests: a 10% administrator share in every game, a closely matching return across all games with a 50 SOL bank, the quarter-of-the-bank rule and the prize cap as of the moment of the bet, the withdrawal lock, the delayed change of start amounts, a late settlement being no more favourable than a timely one.
  • Conservation-of-funds check: tens of thousands of random operations, and after each one the amount in the vault is compared with the sum of the balances and pots.
  • Long runs: two million bets for each game — how much was paid to players and how much the administrator received.
  • Real transactions on a local Solana node: a top-up, a withdrawal refused before the lock expires, a contribution to the reserve, a change of start amounts.
  • Site tests: the site computes the odds with the same formulas as the contract and checks itself against samples recorded by the contract.

What has not been tested or done is listed plainly on the “Why FAIRDRUM” page. How to verify any round yourself is on the “Verify a round” page.

The contract's parameters in one table

Unit bet
0.01 SOL
Round
up to 100 bets in the games, up to 1,000 on the wheel
Games (modes)
16
“Spin again” chance
11.6%
Cap on a single prize
1/4 of the prize bank
Minimum start amount
jackpot 0.2 SOL, super jackpot 2 SOL
Mini jackpot
starts at 1/10 of the jackpot
To the jackpot winner
95% · 5% goes to the super jackpot
To the super jackpot winner
90%
Withdrawal lock
12 hours after the last top-up
Round settlement deadline
3,000 network slots, about 20 minutes
Network and oracle fee
0.005 SOL per round, not taken by the project