Dokumenty

Kontrakt: jak i dlaczego to działa

Wszystkie środki i wszystkie zasady FAIRDRUM znajdują się w jednym programie w sieci Solana — smart kontrakcie. Strona tylko wysyła mu polecenia i pokazuje odpowiedź. Poniżej: co kontrakt przechowuje, jakie polecenia rozumie, jak z liczby losowej powstaje wynik oraz co może, a czego nie może administrator.

Czym jest kontrakt i gdzie się znajduje

Smart kontrakt to program wykonywany przez węzły sieci Solana, a nie na serwerze projektu. Jego kod jest taki sam dla wszystkich, a każde działanie to publiczna transakcja. Kontrakt FAIRDRUM jest napisany w Rust z biblioteką Anchor; jego kod źródłowy jest otwarty.

Adres programu pojawi się tutaj, gdy strona zostanie podłączona do kontraktu.

Ważny wniosek: jeśli strona fairdrum.to zniknie, środki graczy zostaną w kontrakcie i będzie można je wypłacić dowolnym programem, który potrafi wysłać polecenie wypłaty z podpisem twojego portfela.

Co kontrakt przechowuje

  • Skarbiec. Jedno konto w opakowanym SOL, którym dysponuje wyłącznie sam program. Leży w nim wszystko: salda graczy, bank nagród, jackpoty, rezerwa i jeszcze nieodebrany udział administratora.
  • Wspólne konto gry. Zapis tego, jak podzielona jest kwota w skarbcu: bank nagród, jackpot, mini-jackpot, superjackpot, rezerwa na kwoty startowe, udział administratora, kwoty startowe jackpotów, liczniki rund w poszczególnych grach.
  • Konto gracza. Tworzy je polecenie register, które strona wysyła razem z pierwszą wpłatą; jest powiązane z adresem portfela: saldo gry, czas ostatniej wpłaty, niedokończona runda, niewypłacona część jackpota.
  • Konto sesji (jeśli włączono „grę bez podpisów”): tymczasowy klucz, termin i limit stawek.

Księgowanie jest zbudowane tak, że suma wszystkich sald i pul równa się kwocie w skarbcu. Test sprawdza tę równość po każdej z dziesiątek tysięcy losowych operacji.

Jakie polecenia rozumie kontrakt

PolecenieKto może wywołaćCo robi
registergraczTworzy konto gracza. Strona wysyła je razem z pierwszą wpłatą.
depositgraczWpłata na saldo gry. Zapamiętuje czas: od niego liczy się 12 godz. do wypłaty.
withdrawgraczWypłata na własny portfel. Jest odrzucana, dopóki od ostatniej wpłaty nie minęło 12 godz.
spin_commitgracz lub jego klucz sesjiStawka: pobiera rundę z salda, zapamiętuje grę i obowiązujące szanse, prosi wyrocznię o liczbę losową.
spin_settlekażdyRozliczenie: odczytuje liczbę wyroczni, oblicza wypłatę i zapisuje ją na saldo gracza. Wywołać może każdy — wynik od tego nie zależy.
spin_expirekażdyZamyka rundę, której nie rozliczono w ciągu 20 minut. Jeśli wyrocznia nie odpowiedziała, stawka wraca do gracza w całości. Jeśli wyrocznia odpowiedziała, a runda jest przypieczętowana, wypłaca zwykłe nagrody bez losowania jackpotów.
spin_sealkażdyPieczętuje rundę: zapisuje hash bloku stawki, dopóki jest dostępny (około 3,5 minuty). Jest potrzebna tylko wtedy, gdy wyrocznia odpowiada dłużej; zwykle wywołuje ją usługa dyżurna. Runda, której nie rozliczono ani nie przypieczętowano na czas, zamyka się bez wyniku.
skip_noncegraczPrzesuwa numer następnego zapytania o losowość, jeśli adres zapytania okazał się zajęty.
session_open / session_closegraczPozwala tymczasowemu kluczowi stawiać w granicach terminu i limitu; klucz nie może ani wypłacać, ani wpłacać.
donatekażdyWnosi SOL do rezerwy na kwoty startowe jackpotów. Polecenia odwrotnego nie ma.
set_jackpot_startsadministratorUstala nowe kwoty startowe jackpota i superjackpota; zaczynają obowiązywać po 24 godz.
rescale_poolsadministratorPrzenosi część rezerwy na kwoty startowe do banku nagród gier. Tylko w tę stronę; do jackpotów przenosić nie można — uzupełniają się z rezerwy same, po wygranej.
set_pausedadministratorWstrzymuje lub wznawia przyjmowanie nowych stawek — na wypadek awarii wyroczni. Postawione już stawki są rozliczane, wypłaty nagród i wypłata środków działają jak zwykle.
set_guardian / guard_pauseadministratorAdministrator wyznacza strażnika — klucz usługi dyżurnej, który potrafi tylko jedno: wstrzymać przyjmowanie nowych stawek, jeśli wyrocznia przestała odpowiadać. Pauzę może zdjąć tylko administrator.
propose_dev_authority / accept_dev_authorityadministratorPrzekazanie uprawnień administratora innemu kluczowi w dwóch krokach: obecny klucz wskazuje nowy, a nowy sam to potwierdza.
roll_epoch / checkinkażdyPolecenia pomocnicze: aktualizują statystykę tygodniową i znacznik dnia. Nie przenoszą środków.
claim_devadministratorOdbiera zgromadzony udział administratora — i tylko jego.
initialize / fund_poolsadministratorJednorazowe uruchomienie. initialize tworzy konta (podpisuje posiadacz uprawnienia do aktualizacji programu); fund_pools jeden raz rozpisuje wniesiony bank startowy na pule, a nadwyżkę ponad niego — do osobnej pozycji, którą administrator może odebrać poleceniem promo_pay.

Polecenia, które przekazywałoby administratorowi bank nagród, jackpoty lub salda graczy, w kodzie nie ma.

Runda krok po kroku

  1. Stawka. Polecenie spin_commit pobiera rundę z twojego salda i w tej samej transakcji tworzy u wyroczni ORAO zapytanie o liczbę losową. Adres zapytania jest wyliczany z twojego portfela i numeru rundy, dlatego nie da się podstawić cudzego zapytania.
  2. Liczba. Kilka niezależnych węzłów ORAO podpisuje liczbę losową i zapisuje ją w sieci. Do chwili tego zapisu nie zna jej nikt: ani ty, ani projekt, ani pojedynczy węzeł.
  3. Rozliczenie. Polecenie spin_settle odczytuje liczbę z zapisu wyroczni, sprawdza, czy to zapytanie właśnie twojej rundy, i oblicza wypłatę. Strona wysyła je sama; jeśli strona jest zamknięta, zrobi to program dyżurny projektu albo ty przy następnej wizycie.
  4. Prezentacja. Karty, miny, rakieta, kamienie to sposób pokazania już obliczonej wypłaty. Kliknięcia w grze na nią nie wpływają.

Dlaczego wyniku nie da się poznać z góry ani sfałszować. Ostateczna liczba rundy to liczba wyroczni zmieszana z hashem bloku, w którym zapisano stawkę. W chwili stawki ten hash jeszcze nie istnieje, a liczba wyroczni przychodzi później i od strony trzeciej: wyniku nie może z góry obliczyć nikt — ani gracz, ani projekt, ani sama wyrocznia. Gra, kwoty startowe jackpotów i limit nagrody są zapisywane w chwili stawki, a wzór rozliczenia jest w otwartym kodzie. Spóźnione rozliczenie nigdy nie jest korzystniejsze od terminowego. Zasady można zmienić tylko przez wymianę kodu programu, a to widzą wszyscy (zob. część o administratorze).

Jak z liczby losowej powstaje wynik

Runda to od 1 do 100 stawek po 0,01 SOL (na bębnie do 1000). Liczba wyroczni jest rozwijana w niezależną wartość losową dla każdej stawki i dla każdej z nich kontrakt po kolei odpowiada na pytania:

  1. Superjackpot, jackpot, mini-jackpot? Szansa każdej puli równa się wkładowi stawki do niej podzielonemu przez kwotę startową puli. Pula jest losowana tylko wtedy, gdy jest w niej co najmniej 25% kwoty startowej.
  2. Nagroda gry? Każda gra ma własną szansę na nagrodę i własną tabelę sześciu stopni z wagami. Na przykład na bębnie nagroda wypada w 10% stawek. Tabele wszystkich gier są pokazane na ich stronach.
  3. „Jeszcze raz”? Z szansą 11,6% stawka jest powtarzana bezpłatnie na koszt banku nagród.
  4. W przeciwnym razie stawka jest bez nagrody. Dzieli się ją tak samo jak każdą inną: bank nagród, jackpoty i udział administratora.

Tabele gier są różne, a oczekiwana wypłata jest w nich taka sama (z dokładnością do setnych części procenta; przy banku nagród od 40 SOL, gdy nagrody nie dochodzą do limitu): około 77,5% stawki w zwykłych nagrodach, a razem z powtórkami „Jeszcze raz” — około 88% opłaconych stawek. Równość sprawdza kompilator: jeśli w którejś grze wartość oczekiwana okaże się wyższa niż na bębnie albo niższa o więcej niż pół procenta, program się nie zbuduje.

Gdzie kontrakt odkłada każdą stawkę

DokądUdział w opłaconej stawcePo co
Bank nagród≈88%zwykłe nagrody wszystkich gier
Jackpot, mini-jackpot, superjackpot i kwota startowa2%trzy wspólne pule
Administrator10%dochód projektu; innego nie ma

W kodzie udziały są zapisane od każdej wykonanej stawki, łącznie z bezpłatnymi powtórkami, dlatego widnieje tam 8,84% i 1,77%: w przeliczeniu na opłacone stawki to średnio 10% i 2%.

Reguły ograniczające i po co są

  • Jedna nagroda — nie więcej niż ćwierć banku nagród. Kontrakt nie może obiecać więcej, niż ma, a jedna duża wygrana nie opróżnia banku dla pozostałych. Niedopłacona kwota zostaje w banku.
  • Wypłata po 12 godz. od ostatniej wpłaty. Reguła jest jednakowa dla wszystkich i zapisana jako stała: zmienić ją można tylko nową wersją programu.
  • Kwoty startowe jackpotów zmieniają się z opóźnieniem 24 godz. Szanse rundy są ustalane w chwili stawki, dlatego nie da się ich zmienić „pod już postawioną stawkę”.
  • 20 minut na rozliczenie. Jeśli wyrocznia nie odpowiedziała, stawka wraca do gracza w całości: dopóki nie ma liczby, nikt nie zna wyniku, więc nie da się w ten sposób uchylić od przegranej. Jeśli odpowiedziała, ale rozliczenie się spóźniło, zwykłe nagrody są wypłacane, a jackpoty nie są w tej rundzie losowane. Ochrona skarbca. Przed każdą wypłatą i po każdym rozliczeniu kontrakt sprawdza, czy w skarbcu jest nie mniej, niż jest winien graczom i pulom; w przeciwnym razie operacja zostaje odrzucona. Strażnik. Jeśli wyrocznia przestała odpowiadać, przyjmowanie nowych stawek zostaje automatycznie wstrzymane; rozliczenia i wypłata środków działają dalej.
  • Jackpot jest wypłacany w ratach: zwycięzcy należy się 95% puli, z tego 20% od razu i po 8% tygodniowo. Niewypłacona część jest zapisana na koncie zwycięzcy.
  • Jedna niedokończona runda na gracza. Dopóki runda nie jest rozliczona, nowa stawka nie jest przyjmowana.

Co może, a czego nie może administrator

Może

  • odbierać swój udział — 10% opłaconych stawek;
  • wnosić SOL do rezerwy i przenosić je z rezerwy do banku nagród;
  • odebrać nadwyżkę, która przy uruchomieniu znalazła się w skarbcu ponad bank startowy;
  • zmieniać kwoty startowe jackpotów — z opóźnieniem i w określonych granicach;
  • wstrzymać przyjmowanie nowych stawek, jeśli wyrocznia nie odpowiada, oraz przekazać swoje uprawnienia innemu kluczowi.

Nie może

  • wypłacić banku nagród, jackpotów, rezerwy ani sald graczy (jako gracz wygrywa na ogólnych zasadach);
  • zmieniać tabel nagród, szansy na nagrodę w grach ani udziałów stawki: to stałe w kodzie;
  • poznać liczby losowej rundy przed stawką ani jej wybrać;
  • zatrzymać rozliczenia postawionych stawek ani wypłaty: pauza dotyczy tylko nowych stawek.

Uczciwe zastrzeżenie. Program ma uprawnienie do aktualizacji: dopóki nie zostało odwołane, jego posiadacz może zastąpić kod nową wersją i wtedy wszystko, co napisano wyżej, będzie dotyczyć już nowego kodu. Stan tego uprawnienia i każdą aktualizację widać w eksploratorze Solana. Niezależnego audytu kontraktu nie ma.

Jak to sprawdzono

  • Testy kontraktu: udział administratora 10% w każdej grze, zbliżony zwrot wszystkich gier przy banku 50 SOL, reguła ćwierci banku i limit nagrody z chwili stawki, blokada wypłaty, odroczona zmiana kwot startowych, późne rozliczenie nie jest korzystniejsze od terminowego.
  • Sprawdzenie zachowania środków: dziesiątki tysięcy losowych operacji, po każdej kwota w skarbcu jest porównywana z sumą sald i pul.
  • Długie przebiegi: po dwa miliony stawek na każdą grę — ile wypłacono graczom, ile otrzymał administrator.
  • Prawdziwe transakcje na lokalnym węźle Solana: wpłata, odmowa wypłaty przed terminem, wniesienie do rezerwy, zmiana kwot startowych.
  • Testy strony: strona liczy szanse tymi samymi wzorami co kontrakt i porównuje wyniki z wzorcami zapisanymi przez kontrakt.

Co nie zostało sprawdzone ani zrobione, wymieniono bez upiększeń na stronie „Dlaczego FAIRDRUM”. Jak samodzielnie sprawdzić dowolną rundę — na stronie „Sprawdź rundę”.

Parametry kontraktu w jednej tabeli

Pojedyncza stawka
0,01 SOL
Runda
do 100 stawek w grach, do 1000 na bębnie
Gier (trybów)
16
Szansa na „Jeszcze raz”
11,6%
Limit jednej nagrody
1/4 banku nagród
Najmniejsza kwota startowa
jackpot 0,2 SOL, superjackpot 2 SOL
Mini-jackpot
startuje od 1/10 jackpota
Dla zwycięzcy jackpota
95% · 5% trafia do superjackpota
Dla zwycięzcy superjackpota
90%
Blokada wypłaty
12 godz. po ostatniej wpłacie
Termin rozliczenia rundy
3000 slotów sieci, około 20 minut
Opłata sieci i wyroczni
0,005 SOL za rundę, nie pobiera jej projekt