문서

컨트랙트: 어떻게, 왜 이렇게 작동하는가

FAIRDRUM의 모든 자금과 모든 규칙은 Solana 네트워크의 프로그램 하나, 즉 스마트 컨트랙트 안에 있습니다. 사이트는 컨트랙트에 명령을 보내고 응답을 보여 줄 뿐입니다. 아래에서는 컨트랙트가 무엇을 보관하는지, 어떤 명령을 이해하는지, 난수에서 결과가 어떻게 나오는지, 관리자가 무엇을 할 수 있고 무엇을 할 수 없는지 설명합니다.

컨트랙트란 무엇이며 어디에 있는가

스마트 컨트랙트는 프로젝트의 서버가 아니라 Solana 네트워크의 노드들이 실행하는 프로그램입니다. 코드는 모두에게 같고, 모든 동작은 공개 트랜잭션입니다. FAIRDRUM 컨트랙트는 Rust와 Anchor 라이브러리로 작성되었으며 소스 코드는 공개되어 있습니다.

사이트가 컨트랙트에 연결되면 프로그램 주소가 여기에 표시됩니다.

중요한 귀결: fairdrum.to 사이트가 사라지더라도 플레이어의 자금은 컨트랙트에 남으며, 내 지갑의 서명과 함께 출금 명령을 보낼 수 있는 프로그램이라면 무엇으로든 출금할 수 있습니다.

컨트랙트가 보관하는 것

  • 금고. 래핑된 SOL로 된 계정 하나이며, 프로그램 자신만 처분할 수 있습니다. 플레이어 잔액, 상금 뱅크, 잭팟, 예비금, 관리자가 아직 가져가지 않은 몫까지 모든 것이 여기에 있습니다.
  • 게임 공통 계정. 금고의 금액이 어떻게 나뉘어 있는지에 대한 기록입니다. 상금 뱅크, 잭팟, 미니 잭팟, 슈퍼 잭팟, 시드 예비금, 관리자 몫, 잭팟 시작 금액, 게임별 라운드 카운터.
  • 플레이어 계정. register 명령으로 만들어지며, 사이트가 이 명령을 첫 충전과 함께 보냅니다. 지갑 주소에 연결되어 있습니다. 게임 잔액, 마지막 충전 시각, 완료되지 않은 라운드, 잭팟의 미지급분.
  • 세션 계정(«서명 없는 플레이»를 켠 경우): 임시 키, 기한, 베팅 한도.

회계는 모든 잔액과 저금통의 합이 금고의 금액과 같도록 짜여 있습니다. 테스트는 수만 번의 무작위 작업 하나하나가 끝날 때마다 이 등식을 검사합니다.

컨트랙트가 처리하는 명령

명령호출할 수 있는 사람하는 일
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관리자관리자가 가디언을 지정합니다. 가디언은 지킴이 서비스의 키로, 할 수 있는 일은 하나뿐입니다. 오라클이 응답을 멈추면 새 베팅 접수를 일시 중지하는 것입니다. 일시 중지는 관리자만 해제할 수 있습니다.
propose_dev_authority / accept_dev_authority관리자관리자 권한을 다른 키로 두 단계에 걸쳐 넘깁니다. 현재 키가 새 키를 지정하고, 새 키가 직접 승인합니다.
roll_epoch / checkin누구나서비스용: 주간 통계와 날짜 표시를 갱신합니다. 자금은 움직이지 않습니다.
claim_dev관리자쌓인 관리자 몫을 가져갑니다. 가져갈 수 있는 것은 그것뿐입니다.
initialize / fund_pools관리자한 번뿐인 시작. initialize는 계정들을 만듭니다(프로그램 업그레이드 권한 보유자가 서명합니다). fund_pools는 넣은 시작 뱅크를 한 번만 저금통별로 기록하고, 그것을 넘는 초과분은 별도 항목에 기록합니다. 관리자는 이 초과분을 promo_pay 명령으로 가져갈 수 있습니다.

상금 뱅크, 잭팟 또는 플레이어 잔액을 관리자에게 보내는 명령은 코드에 없습니다.

라운드 단계

  1. 베팅. spin_commit 명령이 내 잔액에서 라운드 금액을 차감하고, 같은 트랜잭션 안에서 ORAO 오라클에 난수 요청을 만듭니다. 요청 주소는 내 지갑과 라운드 번호로 계산되므로 다른 사람의 요청으로 바꿔치기할 수 없습니다.
  2. 숫자. ORAO의 여러 독립 노드가 난수에 서명하고 네트워크에 기록합니다. 기록되기 전에는 나도, 프로젝트도, 개별 노드도, 아무도 그 숫자를 알지 못합니다.
  3. 정산. spin_settle 명령이 오라클의 기록에서 숫자를 읽고, 그것이 바로 내 라운드의 요청인지 확인한 뒤 지급액을 계산합니다. 이 명령은 사이트가 직접 보냅니다. 페이지가 닫혀 있으면 프로젝트의 당직 프로그램이 보내거나, 다음에 접속했을 때 내가 보냅니다.
  4. 표시. 카드, 지뢰, 로켓, 보석은 이미 계산된 지급액을 보여 주는 방식입니다. 게임에서 무엇을 누르든 지급액에는 영향을 주지 않습니다.

결과를 미리 알 수도 조작할 수도 없는 이유. 라운드의 최종 숫자는 오라클의 숫자에 베팅이 기록된 블록의 해시를 섞은 것입니다. 베팅 시점에는 이 해시가 아직 존재하지 않고, 오라클의 숫자는 그 뒤에 제3자에게서 옵니다. 따라서 결과는 누구도 미리 계산할 수 없습니다. 플레이어도, 프로젝트도, 오라클 자신도 할 수 없습니다. 게임, 잭팟 시작 금액, 상금 상한은 베팅 시점에 기록되고, 계산 공식은 공개된 코드에 있습니다. 늦은 정산이 제때 한 정산보다 유리한 경우는 결코 없습니다. 규칙은 프로그램 코드를 교체해야만 바꿀 수 있으며, 이는 모두에게 보입니다(관리자에 관한 절 참조).

난수에서 결과가 어떻게 나오는가

라운드는 0.01 SOL 베팅 1~100개입니다(휠에서는 최대 1000개). 오라클의 숫자는 베팅마다 독립적인 무작위 값으로 펼쳐지며, 컨트랙트는 베팅 하나하나에 대해 다음 질문에 차례로 답합니다.

  1. 슈퍼 잭팟, 잭팟, 미니 잭팟인가? 각 저금통의 확률은 베팅이 그 저금통에 넣는 금액을 저금통의 시작 금액으로 나눈 값과 같습니다. 저금통은 그 안에 시작 금액의 25% 이상이 있을 때만 추첨됩니다.
  2. 게임 상금인가? 게임마다 고유한 상금 확률과 가중치가 붙은 여섯 단계의 표가 있습니다. 예를 들어 휠에서는 베팅의 10%에서 상금이 나옵니다. 모든 게임의 표는 각 게임 페이지에 표시됩니다.
  3. «한 번 더»인가? 11.6%의 확률로 상금 뱅크의 부담으로 베팅이 무료로 반복됩니다.
  4. 그렇지 않으면 상금 없는 베팅입니다. 이 베팅도 다른 베팅과 똑같이 상금 뱅크, 잭팟, 관리자 몫으로 나뉩니다.

게임마다 표는 다르지만, 표에 따른 기대 지급액은 같습니다(백분의 몇 퍼센트 이내의 정확도로. 상금 뱅크가 40 SOL 이상이어서 상금이 상한에 걸리지 않을 때). 일반 상금으로 베팅의 약 77.5%, «한 번 더» 반복을 합치면 유료 베팅의 약 88%입니다. 이 동등성은 컴파일러가 검사합니다. 어떤 게임의 기댓값이 휠보다 높거나 0.5퍼센트 넘게 낮으면 프로그램이 빌드되지 않습니다.

컨트랙트가 각 베팅을 어디에 넣는가

용도유료 베팅 대비 비율이유
상금 뱅크≈88%모든 게임의 일반 상금
잭팟, 미니 잭팟, 슈퍼 잭팟과 시드2%세 개의 공통 저금통
관리자10%프로젝트의 수입. 다른 수입은 없음

코드에서 비율은 무료 반복을 포함해 실행된 베팅 하나하나를 기준으로 적혀 있어서 8.84%와 1.77%로 되어 있습니다. 유료 베팅 기준으로 환산하면 평균 10%와 2%입니다.

제한 규칙과 그 필요성

  • 상금 하나는 상금 뱅크의 4분의 1 이하. 컨트랙트는 가진 것보다 많이 약속할 수 없고, 큰 당첨 하나가 다른 플레이어 몫의 뱅크를 비우지도 않습니다. 덜 지급된 금액은 뱅크에 남습니다.
  • 출금은 마지막 충전 후 12시간 뒤. 이 규칙은 모두에게 같고 상수로 기록되어 있습니다. 프로그램의 새 버전으로만 바꿀 수 있습니다.
  • 잭팟 시작 금액은 24시간의 지연을 두고 바뀝니다. 라운드의 확률은 베팅 시점에 고정되므로 «이미 한 베팅에 맞춰» 바꿀 수 없습니다.
  • 정산 기한 20분. 오라클이 응답하지 않았다면 베팅은 플레이어에게 전액 반환됩니다. 숫자가 나오기 전에는 누구도 결과를 알 수 없으므로, 이 방법으로 진 베팅을 무를 수는 없습니다. 오라클이 응답했지만 정산이 늦었다면 일반 상금은 지급되고, 이 라운드에서 잭팟 추첨은 진행되지 않습니다. 금고 보호. 컨트랙트는 매번 지급 전과 정산 후에 금고의 금액이 플레이어와 저금통에 지급해야 할 금액보다 적지 않은지 확인하며, 그렇지 않으면 작업을 거부합니다. 가디언. 오라클이 응답을 멈추면 새 베팅 접수가 자동으로 일시 중지됩니다. 정산과 출금은 계속 작동합니다.
  • 잭팟은 나누어 지급됩니다. 당첨자의 몫은 저금통의 95%이며, 그중 20%는 즉시, 이후 매주 8%씩입니다. 미지급분은 당첨자의 계정에 기록됩니다.
  • 플레이어당 완료되지 않은 라운드는 하나. 라운드가 정산되기 전에는 새 베팅을 받지 않습니다.

관리자가 할 수 있는 일과 할 수 없는 일

할 수 있는 일

  • 자신의 몫인 유료 베팅의 10%를 가져가는 것;
  • 예비금에 SOL을 넣고, 예비금에서 상금 뱅크로 옮기는 것;
  • 시작할 때 금고에 시작 뱅크를 넘어 들어 있던 초과분을 가져가는 것;
  • 잭팟의 시작 금액을 바꾸는 것 — 지연을 거쳐, 정해진 범위 안에서만;
  • 오라클이 응답하지 않을 때 새 베팅 접수를 일시 중지하는 것, 그리고 자신의 권한을 다른 키로 넘기는 것.

할 수 없는 일

  • 상금 뱅크, 잭팟, 예비금 또는 플레이어 잔액을 인출하는 것(플레이어로서는 모두와 같은 조건으로 당첨됩니다);
  • 상금표, 게임의 상금 확률, 베팅 분배 비율을 바꾸는 것: 이것들은 코드의 상수입니다;
  • 라운드의 난수를 베팅 전에 알아내거나 고르는 것;
  • 이루어진 베팅의 정산이나 출금을 멈추는 것: 일시 중지는 새 베팅에만 적용됩니다.

솔직한 단서. 프로그램에는 업그레이드 권한이 있습니다. 이 권한이 철회되기 전까지는 그 보유자가 코드를 새 버전으로 교체할 수 있으며, 그러면 위에서 말한 모든 것은 새 코드에 대한 이야기가 됩니다. 이 권한의 상태와 모든 업그레이드는 Solana 익스플로러에서 볼 수 있습니다. 컨트랙트에 대한 독립적인 감사는 없습니다.

무엇으로 검증했는가

  • 컨트랙트 테스트: 모든 게임에서 관리자 몫 10%, 뱅크가 50 SOL일 때 모든 게임의 환수율이 비슷함, 뱅크 4분의 1 규칙과 베팅 시점의 상금 상한, 출금 잠금, 시작 금액의 지연 변경, 늦은 정산이 제때 한 정산보다 유리하지 않음.
  • 자금 보존 검사: 수만 번의 무작위 작업을 실행하고, 매번 금고의 금액을 잔액과 저금통의 합과 대조합니다.
  • 장기 실행: 게임마다 베팅 200만 번씩, 플레이어에게 얼마가 지급되었고 관리자가 얼마를 받았는지 확인합니다.
  • 로컬 Solana 노드에서의 실제 트랜잭션: 충전, 기한 전 출금 거부, 예비금 납입, 시작 금액 변경.
  • 사이트 테스트: 사이트는 컨트랙트와 같은 공식으로 확률을 계산하고, 컨트랙트가 기록한 샘플과 대조합니다.

검증되지 않은 것과 하지 않은 것은 «왜 FAIRDRUM인가» 페이지에 꾸밈없이 나열되어 있습니다. 어떤 라운드든 직접 검증하는 방법은 «라운드 검증» 페이지에 있습니다.

컨트랙트 매개변수 한눈에 보기

단일 베팅
0.01 SOL
라운드
게임에서는 최대 100개 베팅, 휠에서는 최대 1,000개
게임(모드) 수
16
«한 번 더» 확률
11.6%
상금 하나의 상한
상금 뱅크의 1/4
최소 시작 금액
잭팟 0.2 SOL, 슈퍼 잭팟 2 SOL
미니 잭팟
잭팟의 1/10에서 시작
잭팟 당첨자에게
95% · 5%는 슈퍼 잭팟으로
슈퍼 잭팟 당첨자에게
90%
출금 잠금
마지막 충전 후 12시간
라운드 정산 기한
네트워크 슬롯 3,000개, 약 20분
네트워크와 오라클 수수료
라운드당 0.005 SOL, 프로젝트가 받는 것이 아님