Skip to main content

Random number generation

Generating random numbers is a common task in many projects. While you may have seen the random() function in FunC documentation, note that its result can be easily predicted unless you use additional techniques.

How can someone predict a random number?

Computers struggle to generate truly random information because they strictly follow user instructions. To address this, developers have created methods for generating pseudorandom numbers.

These algorithms typically require a seed value to produce a sequence of pseudorandom numbers. You will always get the same result if you run the same program with the same seed multiple times. In TON, the seed varies for each block.

To predict the result of the random() function in a smart contract, one would need to know the current seed of the block, which is impossible for non-validators before block production.

There are multiple approaches to generate random values, each offering different trade-offs between speed, security, and decentralization guarantees.

Below, we outline three fundamental approaches:


Approach 1: randomize_lt()

Mechanism: generates randomness using transaction logical time (lt) and blockchain entropy.

Security model:

  • ✅ Safe against user manipulation
  • ❌ Vulnerable to colluding validators (could predict/influence values)

Speed: fast (single-block operation)

Use cases:

  • Non-critical applications, for example, gaming and NFTs
  • Scenarios where validator trust is assumed

Approach 2: block skipping

Mechanism: uses entropy from skipped blocks in blockchain history (see also guidance).

Security model:

  • ✅ Resistant to user manipulation
  • ⚠️ Not fully secure against determined validators (may influence block inclusion timing)

Speed: slow (requires multiple blocks to finalize)

Use cases:

  • Medium-stakes applications, for example, lottery systems
  • Scenarios with partial trust in a validator set

Approach 3: commit‑reveal scheme

Mechanism:

  1. Commit phase: participants submit hashed secrets
  2. Reveal phase: secrets are disclosed and combined to generate final randomness

Security model:

  • ✅ Cryptographically secure when properly implemented
  • ✅ More resilient to user manipulation; validators may still influence via timing or censorship—no method is perfectly unpredictable on TON.
  • ⚠️ Requires smart-contract (on-chain) verification of commitments and incentives/penalties for non-reveals.

Speed: very slow (multi-phase, multi-block process)

Use cases:

  • High-value applications, for example, decentralized auctions
  • Systems requiring Byzantine fault tolerance

Key considerations

Factorrandomize_ltBlock skippingCommit-reveal
SpeedFastSlowVery slow
Resistance to user manipulationHighHighHighest
Resistance to validator manipulationLowMediumHigh
Implementation complexityLowMediumHigh

caution

Single-block randomness (for example, randomize_lt()) is not secure against validators who can influence or predict values. For stronger guarantees, consider multi-phase schemes such as commit–reveal.

When choosing an approach, weigh:

  • Value-at-risk in your application
  • Required time-to-finality
  • Trust assumptions about validators

Always audit implementations through formal verification where possible.

Was this article useful?