Blockchain crash game development

We design and develop full-cycle blockchain solutions: from smart contract architecture to launching DeFi protocols, NFT marketplaces and crypto exchanges. Security audits, tokenomics, integration with existing infrastructure.
Showing 1 of 1 servicesAll 1306 services
Blockchain crash game development
Medium
~5 business days
FAQ
Blockchain Development Services
Blockchain Development Stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1221
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1163
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    855
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1063
  • image_logo-advance_0.png
    B2B Advance company logo design
    561
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    829

Blockchain Crash Game Development

Crash—gambling game where multiplier grows from 1x upward and "crashes" at random moment. Player must withdraw stake before crash. Longer wait—higher potential win, higher risk of losing everything.

Key blockchain Crash difference from traditional online casino: result must be provably fair. Player doesn't trust server—can mathematically verify multiplier wasn't determined after their bet via commitment scheme + Chainlink VRF or RANDAO.

Provably Fair Crash Architecture

Commitment + Reveal Scheme

Operator publishes hash of next seed beforehand, reveals seed after bet phase:

contract CrashGame {
    struct Round {
        bytes32 seedHash;     // hash(seed)—published before bets
        bytes32 seed;         // revealed after bets
        uint64 crashPoint;    // result (in basis points: 150 = 1.5x)
        uint256 totalBets;
        uint256 startTime;
        RoundStatus status;
    }
    
    enum RoundStatus { ACCEPTING_BETS, IN_PROGRESS, CRASHED, CASHOUT_PHASE }
    
    function commitNextRound(bytes32 seedHash) external onlyOperator {
        require(rounds[nextRoundId].status == RoundStatus.CRASHED);
        rounds[nextRoundId + 1].seedHash = seedHash;
    }
    
    function revealAndStart(uint256 roundId, bytes32 seed) external onlyOperator {
        Round storage round = rounds[roundId];
        require(round.status == RoundStatus.ACCEPTING_BETS);
        require(keccak256(abi.encodePacked(seed)) == round.seedHash, "Seed mismatch");
        
        round.seed = seed;
        round.crashPoint = _calculateCrashPoint(seed, roundId);
        round.status = RoundStatus.IN_PROGRESS;
        round.startTime = uint64(block.timestamp);
    }
}

Chainlink VRF V2 Plus

function closeAndRequestRandom(uint256 roundId) external onlyOperator {
    Round storage round = rounds[roundId];
    require(round.status == RoundStatus.ACCEPTING_BETS);
    
    round.status = RoundStatus.IN_PROGRESS;
    
    uint256 requestId = s_vrfCoordinator.requestRandomWords(
        VRFV2PlusClient.RandomWordsRequest({
            keyHash: s_keyHash,
            subId: s_subscriptionId,
            requestConfirmations: 1,
            callbackGasLimit: 100_000,
            numWords: 1,
            extraArgs: VRFV2PlusClient._argsToBytes(
                VRFV2PlusClient.ExtraArgsV1({nativePayment: false})
            )
        })
    );
    
    roundToVrfRequest[roundId] = requestId;
}

function fulfillRandomWords(
    uint256 requestId,
    uint256[] calldata randomWords
) internal override {
    uint256 roundId = vrfRequestToRound[requestId];
    Round storage round = rounds[roundId];
    
    round.crashPoint = _calculateCrashPoint(randomWords[0]);
    emit RoundActive(roundId, round.startTime = uint64(block.timestamp));
}

Crash Point Formula

function _calculateCrashPoint(uint256 rand) internal pure returns (uint64) {
    uint256 h = rand % 1_000_000_000;
    
    // P(crash >= X) = 0.99/X → X = 990_000_000/h
    if (h < 10_000_000) return 100; // 1.00x—instant crash (house edge)
    
    uint256 crashPoint = 990_000_000 * 100 / h;
    
    if (crashPoint < 100) return 100;
    if (crashPoint > 100_000) return 100_000;
    
    return uint64(crashPoint);
}

Anyone can verify: take VRF randomWords[0] from on-chain data, reproduce formula, get same crash point.

Betting and Cashout Mechanics

struct Bet {
    address player;
    uint256 amount;
    uint64 autoCashoutAt; // 0 = manual, >0 = auto cashout at multiplier
    bool cashedOut;
    uint64 cashoutMultiplier;
}

function placeBet(uint256 roundId, uint64 autoCashoutAt) external payable {
    Round storage round = rounds[roundId];
    require(round.status == RoundStatus.ACCEPTING_BETS);
    require(msg.value >= MIN_BET && msg.value <= MAX_BET);
    
    bets[roundId][msg.sender] = Bet({
        player: msg.sender,
        amount: msg.value,
        autoCashoutAt: autoCashoutAt,
        cashedOut: false,
        cashoutMultiplier: 0
    });
}

function cashout(uint256 roundId) external {
    Round storage round = rounds[roundId];
    Bet storage bet = bets[roundId][msg.sender];
    
    require(round.status == RoundStatus.IN_PROGRESS);
    require(bet.amount > 0 && !bet.cashedOut);
    
    uint64 currentMultiplier = _getCurrentMultiplier(round.startTime);
    require(currentMultiplier <= round.crashPoint, "Already crashed");
    
    bet.cashedOut = true;
    bet.cashoutMultiplier = currentMultiplier;
    
    uint256 payout = bet.amount * currentMultiplier / 100;
    payable(msg.sender).transfer(payout);
}

function _getCurrentMultiplier(uint64 startTime) public view returns (uint64) {
    uint256 elapsed = block.timestamp - startTime;
    uint256 multiplier = 100 + (elapsed * elapsed * 2); // quadratic growth
    return uint64(multiplier > 100_000 ? 100_000 : multiplier);
}

Problem: manual cashout on-chain has latency. Player clicks → transaction in mempool → included in block (10–12 sec Ethereum). Round can crash. On L2 more acceptable but not ideal.

Low-latency solution: hybrid. Off-chain cashout: player signs request → game server saves signed timestamp → on-chain settlement game server proves player requested before crash. Requires trusting server but with cryptographic accountability.

Risk Management

function maxAllowedBet() public view returns (uint256) {
    return address(this).balance * maxBetPercent / 10_000;
}

function availableCapacity(uint256 roundId) public view returns (uint256) {
    uint256 maxExposure = address(this).balance * 500 / 10_000; // 5%
    uint256 currentExposure = rounds[roundId].totalBets;
    return currentExposure < maxExposure ? maxExposure - currentExposure : 0;
}

Timeline

MVP (Chainlink VRF, manual cashout, basic UI): 4–6 weeks. Production (hybrid cashout, batch settlement, bankroll management, regulatory compliance): 10–14 weeks.