⚠ Educational only — not an inducement to gamble. Gambling carries real financial risk & can be addictive. 18+/21+. Get help →
📜 Smart Contracts

How Smart Contract Casinos Work

Inside the architecture of on-chain casinos: how the bankroll contract, betting functions, randomness oracles, and non-custodial fund flows actually operate.

StakeRated Editorial· January 12, 2026· 9 min read· intermediate

A traditional online casino is a web application sitting in front of a database. Your balance is a number in that database, and you trust the company not to change it dishonestly. A smart contract casino replaces the database and business logic with on-chain code. The bankroll is held in a contract address. The rules are enforced by the Ethereum Virtual Machine (or an equivalent). The payout math is readable by anyone. Understanding the architecture tells you both what these platforms genuinely offer and where the risks still live.

The Bankroll Contract

At the core of every on-chain casino is a bankroll contract — a smart contract that holds the house’s funds. When players deposit ETH (or tokens), those funds flow into this contract. When a player wins, the contract transfers funds back. When a player loses, the contract keeps them.

Liquidity providers — sometimes called LPs or “the house” — deposit capital into the bankroll in exchange for a share of the expected long-run profit. This is similar to investing in a casino’s operating fund, except the terms are written in code rather than a shareholder agreement.

// Illustrative bankroll contract (simplified)
contract Bankroll {
    mapping(address => uint256) public lpShares;
    uint256 public totalShares;
    uint256 public totalFunds;

    function deposit() external payable {
        uint256 newShares = (totalFunds == 0)
            ? msg.value
            : (msg.value * totalShares) / totalFunds;
        lpShares[msg.sender] += newShares;
        totalShares += newShares;
        totalFunds += msg.value;
    }

    function withdraw(uint256 shares) external {
        uint256 payout = (shares * totalFunds) / totalShares;
        lpShares[msg.sender] -= shares;
        totalShares -= shares;
        totalFunds -= payout;
        payable(msg.sender).transfer(payout);
    }
}

In this model, LPs take on the variance of gambling outcomes. A bad run for the house means LPs lose money; a good run means they earn. The expected return is positive for LPs over time — that is the house edge, now distributed among liquidity providers rather than collected by a single company.

Placing a Bet: The Transaction Flow

When a player places a bet, they send a transaction to the game contract. This transaction includes the bet amount (as ETH or token value) and the game parameters (chosen number, selected outcome, bet type). The contract validates the inputs — checks that the bet is within allowed limits, that the bankroll can cover the maximum payout — and records the bet.

function placeBet(uint8 chosenNumber) external payable {
    require(msg.value >= MIN_BET && msg.value <= MAX_BET, "Bet out of range");
    require(bankroll.canCover(msg.value * MAX_MULTIPLIER), "Bankroll too low");

    pendingBets[msg.sender] = Bet({
        amount: msg.value,
        choice: chosenNumber,
        blockNumber: block.number
    });

    emit BetPlaced(msg.sender, msg.value, chosenNumber);
}

Notice that the bet is stored as “pending.” The result cannot be determined in the same transaction because the random number does not yet exist. This is why randomness handling is its own architectural challenge.

The Randomness Problem

This is the hardest part of smart contract casino design. Blockchains are deterministic: every node must reach the same result. That means “true” randomness — unpredictable to everyone, including the miner or validator — cannot be generated natively inside a contract without help.

Block hash randomness (using the hash of a future block as a seed) was an early approach. It is manipulable: a miner/validator who is also a player can withhold a block if its hash would make them lose.

Commit-reveal schemes require the player to commit a secret value first, then reveal it later so it is XORed with block data to produce the result. This prevents miner manipulation but introduces player manipulation — a player can refuse to reveal if the result would make them lose. See commit-reveal and randomness schemes for the full mechanics.

Verifiable Random Functions (VRFs) via oracle networks like Chainlink VRF are the current industry standard. The oracle generates a cryptographically provable random number off-chain and delivers it to the contract with a proof that it was not manipulated. The game contract verifies the proof before settling the bet.

// Chainlink VRF callback — simplified
function fulfillRandomWords(
    uint256 requestId,
    uint256[] memory randomWords
) internal override {
    Bet storage bet = pendingBets[requestIdToBettor[requestId]];
    uint8 result = uint8(randomWords[0] % 6) + 1; // dice 1–6
    settleBet(bet, result);
}

The oracle dependency is a meaningful architectural risk. If the oracle network is manipulated, delayed, or goes offline, the game halts or produces bad results. “Decentralized” oracles are more resilient than a single data feed, but not immune.

Non-Custodial Fund Flow

The non-custodial design is what separates on-chain casinos from custodial crypto casinos (which are just traditional casinos that accept crypto payments). In a non-custodial casino:

  • You never deposit funds to a company-controlled wallet. Your ETH goes directly to the contract.
  • You interact with the contract yourself (or via a frontend that constructs transactions for you).
  • Payouts flow from the contract directly to your wallet address — no withdrawal request, no KYC hold.

This means the casino operator cannot freeze your funds, confiscate your winnings, or require documentation before paying out. It also means there is no customer support to call if something goes wrong. If the contract has a bug that swallows your bet, that money is gone.

The House Edge Is Still There

On-chain transparency means you can read the house edge directly from the contract. A typical dice game might pay 98 cents on the dollar over time — a 2% house edge baked permanently into the payout formula. Unlike traditional casinos, the operator cannot secretly change this. But it also cannot be negotiated away. The house always wins in expectation, and the code ensures it.

Liquidity provider returns depend on player volume and variance. A poorly funded bankroll relative to maximum bet sizes is a risk to both LPs (ruin from an unlikely big win) and players (the contract may not be able to cover a payout, though well-designed contracts prevent bets the bankroll cannot cover).

Upgradability and Admin Keys

Many production contracts use proxy patterns to allow bug fixes and upgrades. This is a meaningful trade-off: upgradability enables fixing vulnerabilities post-launch, but it also means someone controls an admin key that can alter the contract logic. If that key is compromised or used dishonestly, the non-custodial guarantees can be broken.

Responsible platforms use timelocks on upgrades (changes take 24–72 hours to take effect, giving users time to withdraw) and multisig admin keys requiring multiple signatories. Check whether the casino you are evaluating has these protections before depositing.

For a deeper look at what audits actually check and where they fall short, see smart contract audits explained. For an overview of the risks beyond contract architecture, visit risks and harms or responsible gambling.

#smart-contracts#on-chain-casino#randomness#oracle#bankroll#non-custodial