コントラクト:仕組みとその理由
FAIRDRUMのすべての資金とすべてのルールは、Solanaネットワーク上の1つのプログラム、つまりスマートコントラクトの中にあります。サイトはコマンドを送り、応答を表示するだけです。以下では、コントラクトが何を保管し、どのコマンドを受け付け、乱数からどのように結果が得られ、管理者に何ができて何ができないのかを説明します。
コントラクトとは何か、どこにあるのか
スマートコントラクトは、プロジェクトのサーバーではなく、Solanaネットワークのノードが実行するプログラムです。コードは誰に対しても同じで、すべての操作は公開トランザクションです。FAIRDRUMのコントラクトはRustとAnchorライブラリで書かれており、ソースコードは公開されています。
サイトがコントラクトに接続されると、プログラムのアドレスがここに表示されます。
重要な帰結:fairdrum.toのサイトがなくなっても、プレイヤーの資金はコントラクトに残り、あなたのウォレットの署名を付けて出金コマンドを送れるプログラムであれば、どれを使っても出金できます。
コントラクトが保管するもの
- 保管庫。ラップドSOL建ての1つのアカウントで、動かせるのはプログラム自身だけです。プレイヤーの残高、賞金バンク、ジャックポット、準備金、管理者がまだ受け取っていない取り分のすべてがここにあります。
- ゲームの共通アカウント。保管庫の額がどう分かれているかの記録です。賞金バンク、ジャックポット、ミニジャックポット、スーパージャックポット、シード準備金、管理者の取り分、ジャックポットの初期額、ゲームごとのラウンドカウンター。
- プレイヤーアカウント。registerコマンドで作成され、サイトがこのコマンドを最初の入金と一緒に送信します。ウォレットのアドレスに紐づいており、ゲーム残高、最後の入金時刻、未完了のラウンド、ジャックポットの未払い分を記録します。
- セッションアカウント(「署名なしプレイ」が有効な場合):一時キー、有効期限、ベット上限。
会計は、すべての残高とポットの合計が保管庫の額と等しくなるように作られています。テストでは、数万回のランダムな操作の1回ごとにこの等式を検査します。
コントラクトが受け付けるコマンド
| コマンド | 呼び出せる人 | 内容 |
|---|---|---|
register | プレイヤー | プレイヤーアカウントを作成します。サイトが最初の入金と一緒に送信します。 |
deposit | プレイヤー | ゲーム残高への入金。時刻を記録し、そこから出金までの12時間を数えます。 |
withdraw | プレイヤー | 自分のウォレットへの出金。最後の入金から12時間が経過するまでは拒否されます。 |
spin_commit | プレイヤーまたはそのセッションキー | ベット:ラウンドの額を残高から差し引き、ゲームとその時点で有効な確率を記録し、オラクルに乱数を要求します。 |
spin_settle | 誰でも | 精算:オラクルの数値を読み取り、支払いを計算してプレイヤーに入金します。誰でも呼び出せますが、それで結果が変わることはありません。 |
spin_expire | 誰でも | 20分以内に精算されなかったラウンドを閉じます。オラクルが応答しなかった場合、ベットは全額プレイヤーに返還されます。オラクルが応答し、ラウンドがロックされている場合は、ジャックポットの抽選なしで通常の賞金を支払います。 |
spin_seal | 誰でも | ラウンドをロックします。ベットが記録されたブロックのハッシュを、取得できるうち(約3.5分間)に記録します。必要になるのはオラクルの応答がそれより遅い場合だけで、通常は番人サービスが呼び出します。時間内に精算もロックもされなかったラウンドは、結果なしで閉じられます。 |
skip_nonce | プレイヤー | 要求のアドレスがすでに使われていた場合に、次の乱数要求の番号をずらします。 |
session_open / session_close | プレイヤー | 一時キーに、期限と上限の範囲内でベットすることを許可します。このキーでは出金も入金もできません。 |
donate | 誰でも | ジャックポットのシード準備金にSOLを入れます。逆方向のコマンドはありません。 |
set_jackpot_starts | 管理者 | ジャックポットとスーパージャックポットの新しい初期額を設定します。24時間後に有効になります。 |
rescale_pools | 管理者 | シード準備金の一部をゲームの賞金バンクに移します。この方向のみで、ジャックポットに移すことはできません。ジャックポットは当選のあと、準備金から自動的に補充されます。 |
set_paused | 管理者 | 新しいベットの受け付けを一時停止または再開します。オラクルの障害に備えたものです。すでに行われたベットは精算され、支払いと出金は通常どおり動きます。 |
set_guardian / guard_pause | 管理者 | 管理者がガーディアンを指定します。これは番人サービスの鍵で、できることは1つだけです。オラクルが応答しなくなったときに、新しいベットの受け付けを一時停止することです。一時停止を解除できるのは管理者だけです。 |
propose_dev_authority / accept_dev_authority | 管理者 | 管理者権限を別の鍵へ2段階で移します。現在の鍵が新しい鍵を指名し、新しい鍵が自ら承認します。 |
roll_epoch / checkin | 誰でも | サービス用:週次の統計と日付の記録を更新します。資金は動かしません。 |
claim_dev | 管理者 | 蓄積された管理者の取り分を受け取ります。受け取れるのはそれだけです。 |
initialize / fund_pools | 管理者 | 一度きりの起動。initializeがアカウントを作成します(プログラムのアップグレード権限の保有者が署名します)。fund_poolsは、拠出された初期バンクを一度だけ各ポットに記帳し、それを超える余剰分は別の行に記帳します。この余剰分は管理者がpromo_payコマンドで受け取れます。 |
賞金バンク、ジャックポット、プレイヤーの残高を管理者に送るコマンドは、コードにありません。
ラウンドの流れ
- ベット。spin_commitコマンドがラウンドの額をあなたの残高から差し引き、同じトランザクションの中でORAOオラクルに乱数の要求を作成します。要求のアドレスはあなたのウォレットとラウンド番号から計算されるため、他人の要求にすり替えることはできません。
- 数値。ORAOの複数の独立したノードが乱数に署名し、ネットワークに記録します。記録されるまでは、あなたも、プロジェクトも、個々のノードも、誰もその数値を知りません。
- 精算。spin_settleコマンドがオラクルの記録から数値を読み取り、それがまさにあなたのラウンドの要求であることを確認して、支払いを計算します。このコマンドはサイトが自動で送信します。ページが閉じられている場合は、プロジェクトの当番プログラムが送信するか、次回アクセスしたときにあなたが送信します。
- 表示。カード、地雷、ロケット、宝石は、すでに計算された支払いを見せるための手段です。ゲーム内でどこを押しても支払いには影響しません。
結果を事前に知ることも偽造することもできない理由。ラウンドの最終的な数値は、オラクルの数値に、ベットが記録されたブロックのハッシュを混ぜ合わせたものです。ベットの時点ではこのハッシュはまだ存在せず、オラクルの数値はそのあとで第三者から届きます。そのため、結果を事前に計算することは誰にもできません。プレイヤーにも、プロジェクトにも、オラクル自身にもできません。ゲーム、ジャックポットの初期額、賞金の上限はベットの時点で記録され、計算式は公開されたコードの中にあります。遅れた精算が、期限内の精算より有利になることは決してありません。ルールを変えるにはプログラムのコードを置き換えるしかなく、それは全員に見えます(管理者についての節を参照)。
乱数からどのように結果が決まるのか
1ラウンドは0.01 SOLのベット1〜100回分です(ホイールでは最大1000回)。オラクルの数値はベットごとに独立したランダムな値に展開され、コントラクトはベット1回ごとに次の問いに順番に答えます。
- スーパージャックポット、ジャックポット、ミニジャックポットか?各ポットの確率は、そのポットへのベットの拠出額をポットの初期額で割った値に等しくなります。ポットが抽選されるのは、中身が初期額の25%以上あるときだけです。
- ゲームの賞金か?ゲームごとに、賞金の確率と、重み付きの6段階の表があります。たとえばホイールでは、ベットの10%で賞金が出ます。すべてのゲームの表は各ゲームのページに表示されています。
- 「もう一度」か?11.6%の確率で、賞金バンクの負担によりベットが無料で繰り返されます。
- どれでもなければ、賞金なしのベットです。配分はほかのベットと同じで、賞金バンク、ジャックポット、管理者の取り分に分かれます。
ゲームごとに表は異なりますが、表による期待支払いは同じです(100分の数パーセントの精度で。賞金バンクが40 SOL以上あり、賞金が上限に達しない場合)。通常の賞金でベットの約77.5%、「もう一度」の繰り返しを合わせると有料ベットの約88%です。この等しさはコンパイラが検査します。いずれかのゲームの期待値がホイールより高い場合、または0.5パーセントを超えて低い場合、プログラムはビルドできません。
コントラクトが各ベットをどこに入れるか
| 行き先 | 有料ベットに対する割合 | 目的 |
|---|---|---|
| 賞金バンク | ≈88% | すべてのゲームの通常の賞金 |
| ジャックポット、ミニジャックポット、スーパージャックポット、シード | 2% | 3つの共通ポット |
| 管理者 | 10% | プロジェクトの収入。ほかにはありません |
コードでは、割合は無料の繰り返しを含む実行されたベット1回ごとに対して書かれているため、8.84%と1.77%となっています。有料ベットに換算すると、平均で10%と2%です。
制限ルールとその目的
- 1回の賞金は賞金バンクの4分の1まで。コントラクトは持っている以上の額を約束できず、1回の高額当選でほかのプレイヤーの分のバンクが空になることもありません。支払われなかった分はバンクに残ります。
- 出金は最後の入金から12時間後。このルールは全員に同じで、定数として書かれています。変更できるのはプログラムの新しいバージョンだけです。
- ジャックポットの初期額は24時間の遅延を経て変更されます。ラウンドの確率はベットの時点で固定されるため、「すでに行われたベットに合わせて」変更することはできません。
- 精算の期限は20分。オラクルが応答しなかった場合、ベットは全額プレイヤーに返還されます。数値が出るまでは誰も結果を知らないため、この方法で負けを取り消すことはできません。オラクルが応答したものの精算が遅れた場合、通常の賞金は支払われますが、そのラウンドではジャックポットの抽選は行われません。保管庫の保護。支払いの前と精算の後に毎回、コントラクトは、保管庫の額がプレイヤーとポットに対する債務を下回っていないことを確認します。下回っている場合、操作は拒否されます。ガーディアン。オラクルが応答しなくなると、新しいベットの受け付けが自動的に一時停止されます。精算と出金は引き続き動きます。
- ジャックポットは分割で支払われます。当選者が受け取るのはポットの95%で、そのうち20%はすぐに、その後は週に8%ずつです。未払い分は当選者のアカウントに記録されます。
- 未完了のラウンドはプレイヤー1人につき1つ。ラウンドが精算されるまで、新しいベットは受け付けられません。
管理者にできること、できないこと
できること
- 自分の取り分(有料ベットの10%)を受け取ること。
- 準備金にSOLを入れ、準備金から賞金バンクへ移すこと。
- 起動時に保管庫に入っていた、初期バンクを超える余剰分を受け取ること。
- ジャックポットの初期額を変更すること。遅延があり、定められた範囲内に限ります。
- オラクルが応答しない場合に新しいベットの受け付けを一時停止すること、および自分の権限を別の鍵に移すこと。
できないこと
- 賞金バンク、ジャックポット、準備金、プレイヤーの残高を引き出すこと(プレイヤーとしては、ほかの人と同じ条件で当選します)。
- 賞金表、ゲームの賞金の確率、ベットの配分割合を変更すること。これらはコードの定数です。
- ラウンドの乱数をベットの前に知ること、または選ぶこと。
- 行われたベットの精算や出金を止めること。一時停止の対象は新しいベットだけです。
正直な但し書き。プログラムにはアップグレード権限があります。これが破棄されるまでは、保有者がコードを新しいバージョンに置き換えることができ、その場合、上に述べたことはすべて新しいコードについての話になります。この権限の状態とすべてのアップグレードは、Solanaエクスプローラーで確認できます。コントラクトの独立した監査はありません。
何によって検証されているか
- コントラクトのテスト:どのゲームでも管理者の取り分が10%であること、バンクが50 SOLのときに全ゲームの還元率が近いこと、バンクの4分の1ルールとベット時点での賞金の上限、出金ロック、初期額の遅延変更、遅れた精算が期限内の精算より有利にならないこと。
- 資金保存の検査:数万回のランダムな操作を行い、その都度、保管庫の額を残高とポットの合計と照合します。
- 長時間の実行:ゲームごとに200万回のベットを行い、プレイヤーにいくら支払われ、管理者がいくら受け取ったかを確かめます。
- ローカルのSolanaノードでの実際のトランザクション:入金、期限前の出金の拒否、準備金への拠出、初期額の変更。
- サイトのテスト:サイトはコントラクトと同じ計算式で確率を計算し、コントラクトが記録したサンプルと照合します。
検証されていないこと、行われていないことは、「なぜFAIRDRUMか」のページに飾らずに列挙しています。任意のラウンドを自分で検証する方法は、「ラウンドを検証」のページにあります。
コントラクトのパラメータ一覧
- 単発ベット
- 0.01 SOL
- ラウンド
- ゲームでは最大100ベット、ホイールでは最大1,000
- ゲーム(モード)数
- 16
- 「もう一度」の確率
- 11.6%
- 1回の賞金の上限
- 賞金バンクの1/4
- 最小の初期額
- ジャックポット 0.2 SOL、スーパージャックポット 2 SOL
- ミニジャックポット
- ジャックポットの1/10から開始
- ジャックポットの当選者へ
- 95% · 5%はスーパージャックポットへ
- スーパージャックポットの当選者へ
- 90%
- 出金ロック
- 最後の入金から12時間
- ラウンドの精算期限
- ネットワークの3,000スロット、約20分
- ネットワークとオラクルの手数料
- 1ラウンドあたり0.005 SOL。プロジェクトが取るものではありません