> For the complete documentation index, see [llms.txt](https://docs.seismic.systems/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.seismic.systems/clients/alloy/precompiles/rng.md).

# rng

Generate cryptographically secure random bytes on-chain using Mercury EVM's RNG precompile.

## Overview

The RNG precompile at address `0x64` generates random bytes directly on the Seismic node using the Strobe128 construction. The random value is returned as raw bytes (padded to 32 bytes).

## Precompile Address

```
0x0000000000000000000000000000000000000064
```

## Input Encoding

| Field             | Size                     | Description                                    |
| ----------------- | ------------------------ | ---------------------------------------------- |
| `num_bytes`       | 4 bytes (big-endian u32) | Number of random bytes to generate (1--32)     |
| `personalization` | Variable (optional)      | Optional personalization bytes to seed the RNG |

The input is the concatenation of `num_bytes` followed by the optional `personalization` bytes.

## Output Format

| Field          | Size     | Description                                    |
| -------------- | -------- | ---------------------------------------------- |
| `random_bytes` | 32 bytes | Random output (padded to 32 bytes, big-endian) |

## Parameters

| Parameter         | Type    | Required | Description                                                      |
| ----------------- | ------- | -------- | ---------------------------------------------------------------- |
| `num_bytes`       | `u32`   | Yes      | Number of random bytes to generate (1--32)                       |
| `personalization` | `&[u8]` | No       | Optional personalization string to domain-separate random values |

## Examples

### Basic Usage

```rust
use alloy_provider::Provider;
use alloy_primitives::{Address, Bytes, U256};
use alloy_rpc_types_eth::TransactionRequest;
use seismic_prelude::client::*;
use seismic_alloy_provider::precompiles;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let url = "https://testnet-1.seismictest.net/rpc".parse()?;
    let provider = SeismicProviderBuilder::new().connect_http(url);

    // Using convenience helpers
    let random = precompiles::call::rng(&provider, 32, b"").await?;
    let random_value = U256::from_be_slice(&random);
    println!("Random value (convenience): {random_value}");

    // Manual approach
    let rng_address: Address =
        "0x0000000000000000000000000000000000000064".parse()?;

    // Request 32 random bytes
    let num_bytes: u32 = 32;
    let input = Bytes::from(num_bytes.to_be_bytes().to_vec());

    let result = provider
        .call(
            &TransactionRequest::default()
                .to(rng_address)
                .input(input.into()),
        )
        .await?;

    let random_value = U256::from_be_slice(&result);
    println!("Random value: {random_value}");

    Ok(())
}
```

### With Personalization

```rust
use alloy_provider::Provider;
use alloy_primitives::{Address, Bytes, U256};
use alloy_rpc_types_eth::TransactionRequest;
use seismic_prelude::client::*;
use seismic_alloy_provider::precompiles;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let url = "https://testnet-1.seismictest.net/rpc".parse()?;
    let provider = SeismicProviderBuilder::new().connect_http(url);

    let rng_address: Address =
        "0x0000000000000000000000000000000000000064".parse()?;

    // Request 16 random bytes with personalization
    let num_bytes: u32 = 16;
    let pers = b"my-app-seed";

    let mut input_bytes = num_bytes.to_be_bytes().to_vec();
    input_bytes.extend_from_slice(pers);
    let input = Bytes::from(input_bytes);

    let result = provider
        .call(
            &TransactionRequest::default()
                .to(rng_address)
                .input(input.into()),
        )
        .await?;

    let random_value = U256::from_be_slice(&result);
    println!("Random (with pers): {random_value}");

    Ok(())
}
```

### Generate Multiple Random Values

```rust
use alloy_provider::Provider;
use alloy_primitives::{Address, Bytes, U256};
use alloy_rpc_types_eth::TransactionRequest;
use seismic_prelude::client::*;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let url = "https://testnet-1.seismictest.net/rpc".parse()?;
    let provider = SeismicProviderBuilder::new().connect_http(url);

    let rng_address: Address =
        "0x0000000000000000000000000000000000000064".parse()?;

    let num_bytes: u32 = 32;
    let input = Bytes::from(num_bytes.to_be_bytes().to_vec());

    for i in 0..5 {
        let result = provider
            .call(
                &TransactionRequest::default()
                    .to(rng_address)
                    .input(input.clone().into()),
            )
            .await?;

        let random_value = U256::from_be_slice(&result);
        println!("Random {i}: {random_value}");
    }

    Ok(())
}
```

### Convert to Fixed-Size Array

```rust
use alloy_provider::Provider;
use alloy_primitives::{Address, Bytes};
use alloy_rpc_types_eth::TransactionRequest;
use seismic_prelude::client::*;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let url = "https://testnet-1.seismictest.net/rpc".parse()?;
    let provider = SeismicProviderBuilder::new().connect_http(url);

    let rng_address: Address =
        "0x0000000000000000000000000000000000000064".parse()?;

    let num_bytes: u32 = 32;
    let input = Bytes::from(num_bytes.to_be_bytes().to_vec());

    let result = provider
        .call(
            &TransactionRequest::default()
                .to(rng_address)
                .input(input.into()),
        )
        .await?;

    // Convert to a [u8; 32] array
    let mut random_bytes = [0u8; 32];
    random_bytes.copy_from_slice(&result[..32]);
    println!("Random bytes: 0x{}", hex::encode(random_bytes));

    Ok(())
}
```

## How It Works

1. **Encode parameters** — `num_bytes` is encoded as a 4-byte big-endian integer, followed by optional `personalization` bytes
2. **Call precompile** — Issues an `eth_call` to address `0x64` with estimated gas
3. **Generate randomness** — The precompile uses Strobe128 internally for cryptographic security
4. **Decode result** — Result bytes are padded to 32 bytes and returned as big-endian

## Gas Cost

The gas cost is calculated as:

```
init_cost = 3500 + (len(pers) / 136) * 5
fill_cost = (num_bytes / 136) * 5
total_gas = init_cost + fill_cost
```

The base cost is **3500 gas**, with 5 gas per 136-byte block for personalization and output.

## Notes

* `num_bytes` must be between 1 and 32 (inclusive)
* The RNG uses Strobe128 internally for cryptographic security
* Each call generates independent random values
* The personalization string can be used to domain-separate random values
* The result is padded to 32 bytes and returned as a big-endian value

## Warnings

* **Range validation** — `num_bytes` outside 1--32 will cause the precompile to revert
* **Node connectivity** — Requires a working connection to a Seismic node
* **Not for consensus** — Results may differ across nodes due to timing

## See Also

* [Precompiles Overview](/clients/alloy/precompiles.md) — All precompile reference
* [ecdh](/clients/alloy/precompiles/ecdh.md) — On-chain ECDH key exchange
* [hkdf](/clients/alloy/precompiles/hkdf.md) — On-chain HKDF key derivation


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.seismic.systems/clients/alloy/precompiles/rng.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
