> ## Documentation Index
> Fetch the complete documentation index at: https://companyname-a7d5b98e-v2-pagination.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Random number generation

export const Aside = ({type = "note", title = "", icon = "", iconType = "regular", children}) => {
  const asideVariants = ["note", "tip", "caution", "danger"];
  const asideComponents = {
    note: {
      outerStyle: "border-sky-500/20 bg-sky-50/50 dark:border-sky-500/30 dark:bg-sky-500/10",
      innerStyle: "text-sky-900 dark:text-sky-200",
      calloutType: "note",
      icon: <svg width="14" height="14" viewBox="0 0 14 14" fill="currentColor" xmlns="http://www.w3.org/2000/svg" className="w-4 h-4 text-sky-500" aria-label="Note">
          <path fill-rule="evenodd" clip-rule="evenodd" d="M7 1.3C10.14 1.3 12.7 3.86 12.7 7C12.7 10.14 10.14 12.7 7 12.7C5.48908 12.6974 4.0408 12.096 2.97241 11.0276C1.90403 9.9592 1.30264 8.51092 1.3 7C1.3 3.86 3.86 1.3 7 1.3ZM7 0C3.14 0 0 3.14 0 7C0 10.86 3.14 14 7 14C10.86 14 14 10.86 14 7C14 3.14 10.86 0 7 0ZM8 3H6V8H8V3ZM8 9H6V11H8V9Z"></path>
        </svg>
    },
    tip: {
      outerStyle: "border-emerald-500/20 bg-emerald-50/50 dark:border-emerald-500/30 dark:bg-emerald-500/10",
      innerStyle: "text-emerald-900 dark:text-emerald-200",
      calloutType: "tip",
      icon: <svg width="11" height="14" viewBox="0 0 11 14" fill="currentColor" xmlns="http://www.w3.org/2000/svg" className="text-emerald-600 dark:text-emerald-400/80 w-3.5 h-auto" aria-label="Tip">
          <path d="M3.12794 12.4232C3.12794 12.5954 3.1776 12.7634 3.27244 12.907L3.74114 13.6095C3.88471 13.8248 4.21067 14 4.46964 14H6.15606C6.41415 14 6.74017 13.825 6.88373 13.6095L7.3508 12.9073C7.43114 12.7859 7.49705 12.569 7.49705 12.4232L7.50055 11.3513H3.12521L3.12794 12.4232ZM5.31288 0C2.52414 0.00875889 0.5 2.26889 0.5 4.78826C0.5 6.00188 0.949566 7.10829 1.69119 7.95492C2.14321 8.47011 2.84901 9.54727 3.11919 10.4557C3.12005 10.4625 3.12175 10.4698 3.12261 10.4771H7.50342C7.50427 10.4698 7.50598 10.463 7.50684 10.4557C7.77688 9.54727 8.48281 8.47011 8.93484 7.95492C9.67728 7.13181 10.1258 6.02703 10.1258 4.78826C10.1258 2.15486 7.9709 0.000106649 5.31288 0ZM7.94902 7.11267C7.52078 7.60079 6.99082 8.37878 6.6077 9.18794H4.02051C3.63739 8.37878 3.10743 7.60079 2.67947 7.11294C2.11997 6.47551 1.8126 5.63599 1.8126 4.78826C1.8126 3.09829 3.12794 1.31944 5.28827 1.3126C7.2435 1.3126 8.81315 2.88226 8.81315 4.78826C8.81315 5.63599 8.50688 6.47551 7.94902 7.11267ZM4.87534 2.18767C3.66939 2.18767 2.68767 3.16939 2.68767 4.37534C2.68767 4.61719 2.88336 4.81288 3.12521 4.81288C3.36705 4.81288 3.56274 4.61599 3.56274 4.37534C3.56274 3.6515 4.1515 3.06274 4.87534 3.06274C5.11719 3.06274 5.31288 2.86727 5.31288 2.62548C5.31288 2.38369 5.11599 2.18767 4.87534 2.18767Z"></path>
        </svg>
    },
    caution: {
      outerStyle: "border-amber-500/20 bg-amber-50/50 dark:border-amber-500/30 dark:bg-amber-500/10",
      innerStyle: "text-amber-900 dark:text-amber-200",
      calloutType: "warning",
      icon: <svg className="flex-none w-5 h-5 text-amber-400 dark:text-amber-300/80" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" aria-label="Warning">
          <path stroke-linecap="round" stroke-linejoin="round" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"></path>
        </svg>
    },
    danger: {
      outerStyle: "border-red-500/20 bg-red-50/50 dark:border-red-500/30 dark:bg-red-500/10",
      innerStyle: "text-red-900 dark:text-red-200",
      calloutType: "danger",
      icon: <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor" className="text-red-600 dark:text-red-400/80 w-4 h-4" aria-label="Danger">
          <path d="M17.1 292c-12.9-22.3-12.9-49.7 0-72L105.4 67.1c12.9-22.3 36.6-36 62.4-36l176.6 0c25.7 0 49.5 13.7 62.4 36L494.9 220c12.9 22.3 12.9 49.7 0 72L406.6 444.9c-12.9 22.3-36.6 36-62.4 36l-176.6 0c-25.7 0-49.5-13.7-62.4-36L17.1 292zm41.6-48c-4.3 7.4-4.3 16.6 0 24l88.3 152.9c4.3 7.4 12.2 12 20.8 12l176.6 0c8.6 0 16.5-4.6 20.8-12L453.4 268c4.3-7.4 4.3-16.6 0-24L365.1 91.1c-4.3-7.4-12.2-12-20.8-12l-176.6 0c-8.6 0-16.5 4.6-20.8 12L58.6 244zM256 128c13.3 0 24 10.7 24 24l0 112c0 13.3-10.7 24-24 24s-24-10.7-24-24l0-112c0-13.3 10.7-24 24-24zM224 352a32 32 0 1 1 64 0 32 32 0 1 1 -64 0z"></path>
        </svg>
    }
  };
  let variant = type;
  let gotInvalidVariant = false;
  if (!asideVariants.includes(type)) {
    gotInvalidVariant = true;
    variant = "danger";
  }
  const iconVariants = ["regular", "solid", "light", "thin", "sharp-solid", "duotone", "brands"];
  if (!iconVariants.includes(iconType)) {
    iconType = "regular";
  }
  return <>
      <div className={`callout my-4 px-5 py-4 overflow-hidden rounded-2xl flex gap-3 border ${asideComponents[variant].outerStyle}`} data-callout-type={asideComponents[variant].calloutType}>
        <div className="mt-0.5 w-4" data-component-part="callout-icon">
          {}
          {icon === "" ? asideComponents[variant].icon : <Icon icon={icon} iconType={iconType} size={14} />}
        </div>
        <div className={`text-sm prose min-w-0 w-full ${asideComponents[variant].innerStyle}`} data-component-part="callout-content">
          {gotInvalidVariant ? <p>
              <span className="font-bold">
                Invalid <code>type</code> passed!
              </span>
              <br />
              <span className="font-bold">Received: </span>
              {type}
              <br />
              <span className="font-bold">Expected one of: </span>
              {asideVariants.join(", ")}
            </p> : <>
              {title && <p className="font-bold">{title}</p>}
              {children}
            </>}
        </div>
      </div>
    </>;
};

Generating random numbers is a common smart contract task for applications such as gaming, trait generation for non-fungible tokens (NFTs), and decentralized lotteries. TON provides built-in functions like [`random.uint256()`](/tolk/features/standard-library#random-uint256), but their results can be predicted by validators unless additional techniques are used.

## Why on-chain randomness is challenging

Smart contracts on TON use pseudorandom number generators (PRNGs) seeded with values derived from the blockchain state, such as block seeds generated by validators. While this prevents regular users from predicting random values before block production, validators themselves can influence randomness in two ways:

1. Generate different seeds when creating blocks.
2. Choose which blocks to include external messages in.

This limitation means all approaches to on-chain randomness involve trade-offs between speed, security, and decentralization guarantees.

## Comparison of approaches

| Factor                               | [Single-block](#single-block-randomness) | [Block skipping](#multi-block-randomness-via-block-skipping) | [Commit-reveal](#external-randomness-via-the-commit-reveal-scheme) |
| ------------------------------------ | ---------------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------------ |
| Speed                                | Fast                                     | Slow                                                         | Very slow                                                          |
| Implementation complexity            | Low                                      | Medium                                                       | High                                                               |
| Resistance to user manipulation      | High                                     | High                                                         | High                                                               |
| Resistance to validator manipulation | Low                                      | Medium                                                       | High                                                               |
| Cost (gas + storage)                 | Low                                      | Medium                                                       | High                                                               |

<Aside type="tip">
  When choosing an approach, consider the value at risk and required time-to-finality. For high-stakes applications such as lotteries with significant funds, use commit-reveal. Audit implementations through formal verification when possible.
</Aside>

## Single-block randomness

The [`random.initialize()`](/tolk/features/standard-library#random-initialize) function mixes the transaction's logical time into the current random seed. This provides basic entropy from blockchain state.

### How it works

Call `random.initialize()` once before using [`random.uint256()`](/tolk/features/standard-library#random-uint256) or [`random.range()`](/tolk/features/standard-library#random-range-limit) functions. The logical time adds variability to the seed, making it harder for observers to predict the outcome without executing the transaction.

```tolk title="Tolk" theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
random.initialize();
// Generates values from 0 to 99
val randomNumber = random.range(100);
```

### Security model

The single-block approach prevents attacks from regular users who cannot predict logical time.

However, it is **vulnerable to colluding validators** who can generate seeds or choose message inclusion blocks.

### Speed

The single-block approach is fast, as it executes inside a single transaction.

### Use cases

* Non-critical applications like gaming or cosmetic features.
* NFT trait randomization.
* Scenarios where validator trust is assumed.

<Aside type="caution">
  Validators can predict single-block randomness. Do not use `random.initialize()` for high-value applications such as financial lotteries or significant asset distribution.
</Aside>

## Multi-block randomness via block skipping

Instead of using randomness from the current block, the contract waits for several blocks to pass before using their entropy. This approach sends messages across multiple blocks, making it harder for a single validator to control the final outcome.

### How it works

The contract initiates an operation, then waits for responses that arrive several blocks later. The random seed from future blocks, which the initiating validator does not control, determines the result.

### Security model

Block skipping is resistant to attacks from regular users and more resistant to single validators than single-block randomness.

However, it is still **vulnerable to a determined validator** who represents a significant portion of the network, as they can still choose optimal timing to influence outcomes in blocks they generate.

### Speed

Block skipping is significantly slower than single-block randomness, as it requires waiting for multiple blocks to be produced and finalized.

### Use cases

* Medium-stakes applications like lottery systems with moderate value.
* Scenarios requiring better security than single-block randomness.

## External randomness via the commit-reveal scheme

Multiple participants commit to secret values by publishing hashes, then reveal those values in a later phase. The final randomness is derived from combining all revealed values, ensuring no single party can determine the outcome alone. When properly implemented, this approach provides cryptographically secure randomness suitable for high-value applications.

### How it works

1. **Commit phase**: Each participant generates a secret off-chain and submits a domain-separated hash that binds the secret to the participant, contract, and round identifier.
2. **Reveal phase**: After all commitments are received, participants disclose their original secrets.
3. **Combination**: The contract verifies each reveal against its commitment, rejects duplicates or mismatches, builds a deterministic transcript (e.g., sorted by participant address or commit order), and hashes that transcript to produce the final random value.

### Security model

The commit-reveal scheme is the most secure on-chain randomness approach, as it relies on cryptographic commitments and multiple independent participants. It prevents any single participant from unilaterally determining the final value.

**Validators can still influence timing or censor messages**, but they cannot determine the final random value without colluding with participants.

Commit-reveal schemes require careful incentive design. Participants may refuse to reveal if the outcome is unfavorable. Use penalties or collateral to enforce honest behavior.

### Speed

The commit-reveal scheme is very slow compared to other approaches, as it involves multiple phases and requires waiting for several blocks to complete the process. The time to finality can range from minutes to hours depending on the number of participants and block times.

### Implementation requirements

* On-chain verification of commitments.
* Penalty mechanisms for non-reveals or invalid reveals.
* Timeout handling for missing participants.

### Use cases

* High-value applications like lotteries or auctions with significant funds at stake.
* Decentralized gaming with financial stakes.
* Systems requiring Byzantine fault tolerance.

## Best practices

* Always call `random.initialize()` before using `random.uint256()` or `random.range()`. This prevents users from predicting values but does not protect against validators who control the block seed.
* Keep randomness out of external message receivers. Because external messages do not transfer funds, an attacker can resubmit them for free until the random outcome is favorable - so `random.initialize()` does not protect external entry points.
* Use hybrid or off-chain entropy for critical applications. Combine on-chain randomness with off-chain entropy, like external randomness oracles, when significant value is at risk.
* Test randomness behavior across different blocks on testnet. Verify that contracts behave correctly when randomness is manipulated within validator capabilities.

## How block random seeds work

Understanding the underlying mechanism helps evaluate security trade-offs.

### Seed generation by validators

Each block's random seed is generated by the validator (or [collator](/ecosystem/nodes/cpp/mytonctrl/collator)) creating that block. The [validator node code](https://github.com/ton-blockchain/ton/blob/f59c363ab942a5ddcacd670c97c6fbd023007799/validator/impl/collator.cpp#L1590) generates 32 random bytes using cryptographically secure primitives:

```cpp title="C++" theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
prng::rand_gen().strong_rand_bytes(rand_seed->data(), 32);
```

A single validator generates this seed when creating a block, giving them control over the seed value. This is why single-block randomness is vulnerable to validator manipulation.

### Per-contract randomization

The block seed is not used directly in contracts. Instead, it is [hashed with the contract address](https://github.com/ton-blockchain/ton/blob/f59c363ab942a5ddcacd670c97c6fbd023007799/crypto/block/transaction.cpp#L876) to produce a per-contract seed:

```text theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
contract_seed = SHA256(block_seed || contract_address)
```

This ensures each contract in the same block receives its own random seed, preventing cross-contract randomness correlation.

### Random number generation

The [`RANDU256`](/tvm/instructions#f810-randu256) TVM instruction implements the actual random number generation.

1. Take the current seed `r` (32 bytes).
2. Compute a hash with `SHA512(r)`.
3. Use the first 32 bytes as the new seed.
4. Return the remaining 32 bytes as the random number.

Subsequent calls continue this chain, producing a deterministic sequence from the initial seed.

<Aside type="caution">
  The random sequence is deterministic once the initial seed is known, so anyone who knows both the block seed and contract address can predict random values generated during a transaction. Regular users cannot predict these values before block production, but validators generating the block can, since they control the block seed.
</Aside>
