Blockchain Casino Development with Provably Fair: Transparency and Audit

Players doubt the fairness of online casinos when results are hidden in a 'black box'. We develop blockchain casinos with provably fair, publishing every result on the blockchain with cryptographic proof. Our team delivers turnkey projects—from smart contract audit to implementation and ongoing support.

Blockchain Development Services

Frequently Asked Questions

Latest works

  • Development of a web application for FEEDME
    Development of a web application for FEEDME
    1335
  • Development of an online store for the company FURNORO
    Development of an online store for the company FURNORO
    1293
  • B2B Advance company logo design
    B2B Advance company logo design
    738
  • Development of a web application for Enviok
    Development of a web application for Enviok
    1031
  • AIDER company logo development
    AIDER company logo development
    978
  • CRM development for Chasseurs
    CRM development for Chasseurs
    1087

In traditional online casinos, random number generators (RNG) remain a black box—players have to trust the operator blindly. This undermines trust and raises doubts about payout fairness. Provably fair solves this: every game outcome is published on the blockchain with cryptographic proof. Players can independently reproduce the calculation and verify that a dice roll, spin, or crash result wasn't rigged. We have been implementing provably fair since the technology emerged and have delivered over 30 projects in on-chain gambling. Our stack: smart contracts on Solidity 0.8.x, off-chain engine on Node.js, and verification UI on React. Assess your project—contact us to discuss.

How Provably Fair Works in Practice

There are two main approaches: on-chain VRF and off-chain commit-reveal. We choose based on load, gas cost, and required trust level.

Chainlink VRF — On-Chain Verifiable Randomness

VRF generates a random number together with a cryptographic proof. The contract requests randomness, the oracle returns a number and proof, the contract verifies the proof and accepts the number. The result is published in an event—anyone can verify: requestId → blockHash → randomness. In one project we used Chainlink VRF with subscription ID, reducing gas costs by 30% compared to 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 for Off-Chain Casinos

The classic scheme: the casino publishes hash(server_seed) before the game, the player adds client_seed, after the game the casino reveals server_seed. Result = HMAC-SHA256(server_seed, client_seed + nonce). Anyone can reproduce. Chainlink VRF is faster for verification time, but commit-reveal saves gas.

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);
  }
}

Player-Side Verification

Every player can verify the result using a public verifier. We embed a React UI that, given serverSeedHash and the revealed serverSeed, reproduces the calculation and compares it with the result. Metrics supported: totalBetsCount, totalWagered, actualRTP. Bankroll transparency provides an additional level of trust. The verification UI allows players to export history for their own audit.

What's Included in Turnkey Development

Component Details
Smart contracts Solidity 0.8.x, Chainlink VRF v2.5, ERC-20 payout
Off-chain engine Node.js + TypeScript, PostgreSQL, AES-256-GCM
Verification UI React component for result verification
Audit Internal audit + gas optimization recommendations
Documentation API, data schema, player instructions
Deployment VRF subscription setup, contract deployment
Team training 2-3 sessions on system maintenance

We also deliver source code, test scripts, and a dashboard for RTP monitoring. We guarantee support for 6 months after launch.

Why Choose VRF Over Commit-Reveal?

Comparison of approaches:

Criteria Chainlink VRF Commit-reveal
Verification On-chain, trustless Off-chain, requires trust in seed reveal
Gas cost Medium (call + callback) Low (only hashes)
Speed 2-3 blocks Instant
Transparency Full High, but depends on server honesty
Auditability Easy (events) Medium (logs)

For projects with strict transparency requirements — VRF. For fast games with low fees — commit-reveal.

Development Timeline

  • Basic games with VRF (Dice, Coinflip, Crash): 4-6 weeks
  • Commit-reveal off-chain engine: 3-4 weeks
  • Verification UI: 2-3 weeks
  • Scaling to 5-8 games: +4-8 weeks
  • Security audit: 4-6 weeks (recommended)
  • Total: 3-5 months turnkey

Timelines may vary depending on game logic complexity and payment system integration.

Common Mistakes in Provably Fair Implementation

  1. Weak server_seed entropy: generate with crypto.randomBytes(32), never with Math.random.
  2. Unpublished seed hash before the game: otherwise players cannot verify the seed wasn't changed post factum.
  3. Lack of verification UI: without it, provably fair is an empty marketing phrase.
  4. Insufficient bankroll protection: use a pool with bet limits and public RTP metrics.
  5. Ignoring gas optimization: every bet is a transaction; optimize variables and use packed storage.

Contact us to discuss your project—we'll assess the architecture and propose the optimal solution. The concept of provably fair is described on Wikipedia. More about Chainlink VRF in the Chainlink VRF documentation.