Разработка блокчейн-казино с 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.