Розробка блокчейн-казино з provably fair: прозорість та аудит

У традиційних онлайн-казино генератори випадкових чисел (RNG) залишаються «чорною скринькою» — гравець змушений вірити оператору на слово. Це підриває довіру та викликає сумніви у чесності виплат. Provably fair вирішує проблему: кожен результат гри публікується на блокчейні з криптографічним доказом

Напрямки блокчейн-розробки

Часті запитання

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1441
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1301
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    998
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1267
  • image_logo-advance_0.webp
    Розробка логотипу компанії B2B Advance
    713
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    1003

У традиційних онлайн-казино генератори випадкових чисел (RNG) залишаються «чорною скринькою» — гравець змушений вірити оператору на слово. Це підриває довіру та викликає сумніви у чесності виплат. Provably fair вирішує проблему: кожен результат гри публікується на блокчейні з криптографічним доказом. Гравець може самостійно відтворити розрахунок і переконатися, що кидок костей, спін або результат crash не підтасований. Ми впроваджуємо provably fair з моменту появи технології та реалізували понад 30 проєктів у ончейн-гемблінгу. Наш стек: смарт-контракти на Solidity 0.8.x, off-chain двигун на Node.js та верифікаційний UI на React. Оцінимо ваш проєкт — зв'яжіться для обговорення.

Як працює provably fair на практиці?

Існує два основні підходи: on-chain VRF та off-chain commit-reveal. Обираємо залежно від навантаження, вартості газу та необхідного рівня довіри.

Chainlink VRF — on-chain верифікована випадковість

VRF генерує випадкове число разом із криптографічним proof. Контракт запитує randomness, oracle повертає число та proof, контракт верифікує proof і приймає число. Результат публікується в event — будь-хто може перевірити: requestId → blockHash → randomness. В одному з проєктів ми використовували Chainlink VRF із subscription ID, що знизило газові витрати на 30% порівняно з pay-as-you-go.

// SPDX-License-Identifier: MIT pragma solidity ^0.8.19; import {VRFConsumerBaseV2Plus} from "@chainlink/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol"; import {VRFV2PlusClient} from "@chainlink/contracts/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol"; contract ProvablyFairCasino is VRFConsumerBaseV2Plus { struct BetRecord { address player; uint256 amount; uint8 gameId; bytes betParams; uint256 vrfRequestId; uint256 randomResult; bool settled; uint256 payout; } mapping(uint256 => BetRecord) public betRecords; event BetPlaced( uint256 indexed requestId, address indexed player, uint8 gameId, uint256 amount, bytes betParams ); event BetSettled( uint256 indexed requestId, uint256 randomness, uint256 payout, bool isWin ); function placeBet(uint8 gameId, bytes calldata betParams) external payable returns (uint256 requestId) { require(msg.value >= MIN_BET[gameId], "Below minimum"); require(msg.value <= MAX_BET[gameId], "Above maximum"); require(msg.value <= getMaxBet(), "Exceeds bankroll limit"); requestId = s_vrfCoordinator.requestRandomWords( VRFV2PlusClient.RandomWordsRequest({ keyHash: KEY_HASH, subId: SUBSCRIPTION_ID, requestConfirmations: 3, callbackGasLimit: 200_000, numWords: 1, extraArgs: VRFV2PlusClient._argsToBytes( VRFV2PlusClient.ExtraArgsV1({nativePayment: false}) ) }) ); betRecords[requestId] = BetRecord({ player: msg.sender, amount: msg.value, gameId: gameId, betParams: betParams, vrfRequestId: requestId, randomResult: 0, settled: false, payout: 0 }); emit BetPlaced(requestId, msg.sender, gameId, msg.value, betParams); } function fulfillRandomWords( uint256 requestId, uint256[] calldata randomWords ) internal override { BetRecord storage bet = betRecords[requestId]; require(!bet.settled, "Already settled"); bet.randomResult = randomWords[0]; bet.settled = true; uint256 payout = _resolveGame(bet.gameId, bet.amount, bet.betParams, randomWords[0]); bet.payout = payout; bool isWin = payout > 0; if (isWin) { payable(bet.player).transfer(payout); } emit BetSettled(requestId, randomWords[0], payout, isWin); } } 

Commit-reveal для off-chain казино

Класична схема: казино публікує hash(server_seed) до гри, гравець додає client_seed, після гри казино розкриває server_seed. Результат = HMAC-SHA256(server_seed, client_seed + nonce). Будь-хто може відтворити. Chainlink VRF швидший за часом верифікації, але commit-reveal економить газ.

class ProvablyFairEngine { async createSession(userId: string): Promise<Session> { const serverSeed = crypto.randomBytes(32).toString("hex"); const serverSeedHash = crypto .createHash("sha256") .update(serverSeed) .digest("hex"); const session = await db.createSession({ userId, serverSeed: this.encrypt(serverSeed), serverSeedHash, nonce: 0, createdAt: new Date(), }); return { sessionId: session.id, serverSeedHash }; } async resolve( sessionId: string, clientSeed: string, gameType: string, betAmount: number ): Promise<GameResult> { const session = await db.getSession(sessionId); const serverSeed = this.decrypt(session.serverSeed); const nonce = ++session.nonce; const combinedSeed = `${serverSeed}:${clientSeed}:${nonce}`; const hashHex = crypto .createHmac("sha256", serverSeed) .update(`${clientSeed}-${nonce}`) .digest("hex"); const rawResult = parseInt(hashHex.slice(0, 8), 16); const gameResult = this.applyGameLogic(gameType, rawResult); await db.updateSession(sessionId, { nonce }); await db.saveGameRecord({ sessionId, nonce, clientSeed, serverSeedHash: session.serverSeedHash, gameType, result: gameResult.outcome, betAmount, payout: gameResult.payout, }); return gameResult; } async rotateSession(sessionId: string): Promise<void> { const session = await db.getSession(sessionId); const serverSeed = this.decrypt(session.serverSeed); await db.revealServerSeed(sessionId, serverSeed); await this.createSession(session.userId); } } 

Верифікація на стороні гравця

Кожен гравець може перевірити результат через публічний verifier. Ми вбудовуємо UI на React, який за serverSeedHash і розкритим serverSeed відтворює розрахунок та порівнює з результатом. Підтримка метрик: totalBetsCount, totalWagered, actualRTP. Прозорість банкролу — додатковий рівень довіри. Верифікаційний UI дозволяє гравцеві експортувати історію для власного аудиту.

Що входить у розробку під ключ?

Компонент Деталі
Смарт-контракти Solidity 0.8.x, Chainlink VRF v2.5, ERC-20 payout
Off-chain двигун Node.js + TypeScript, PostgreSQL, AES-256-GCM
Верифікаційний UI React-компонент для перевірки результатів
Аудит Internal аудит + рекомендації з gas optimization
Документація API, схема даних, інструкція для гравця
Розгортання Налаштування VRF subscription, деплой контрактів
Навчання команди 2-3 сесії з підтримки системи

Ми також передаємо вихідні коди, тестові скрипти та dashboard для моніторингу RTP. Гарантуємо підтримку 6 місяців після запуску.

Чому варто обрати VRF замість commit-reveal?

Порівняння підходів:

Критерій Chainlink VRF Commit-reveal
Верифікація On-chain, без довіри Off-chain, потребує довіри до розкриття seed
Вартість газу Середня (call + callback) Низька (тільки хеші)
Швидкість 2-3 блоки Миттєво
Прозорість Повна Висока, але залежить від чесності сервера
Аудованість Проста (events) Середня (логи)

Для проєктів із жорсткими вимогами до прозорості — VRF. Для швидких ігор з низькою комісією — commit-reveal.

Строки розробки

  • Базові ігри з VRF (Dice, Coinflip, Crash): 4-6 тижнів
  • Commit-reveal off-chain engine: 3-4 тижні
  • Верифікаційний UI: 2-3 тижні
  • Розширення до 5-8 ігор: +4-8 тижнів
  • Security audit: 4-6 тижнів (рекомендовано)
  • Разом: 3-5 місяців під ключ

Строки можуть варіюватися залежно від складності game logic та інтеграції з платіжними системами.

Типові помилки при реалізації provably fair

  1. Слабка ентропія server_seed: генеруйте через crypto.randomBytes(32), ніколи через Math.random.
  2. Неопублікований hash seed’а до гри: інакше гравець не може перевірити, що seed не був змінений post factum.
  3. Відсутність верифікаційного UI: без нього provably fair — порожня маркетингова фраза.
  4. Недостатній захист bankroll: використовуйте пул з лімітом ставок і публічні метрики RTP.
  5. Ігнорування gas optimization: кожна ставка — транзакція, оптимізуйте змінні та використовуйте зібране storage.

Зв'яжіться з нами, щоб обговорити ваш проєкт — оцінимо архітектуру та запропонуємо оптимальне рішення. Поняття provably fair описано в Wikipedia. Детальніше про Chainlink VRF — у документації Chainlink VRF.