onchain-randomness

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Onchain Randomness

链上随机性

MCP tool: When available in your environment, also query the Sui documentation MCP server (
https://sui.mcp.kapa.ai
) for up-to-date answers. Use it for verification and for details not covered by these reference files.
Source constraint: All information in this skill is sourced exclusively from docs.sui.io/sui-stack/on-chain-primitives/randomness-onchain. When extending or updating this skill, only pull from this source. Do not use third-party blogs, tutorials, or unofficial documentation.
Sui provides native onchain randomness through the
Random
shared object at address
0x8
. Move functions create
RandomGenerator
instances from
Random
and use them to produce unpredictable values. This skill covers the API, usage patterns, security considerations, and attack mitigations for onchain randomness.

MCP 工具: 如果你的环境中提供了该工具,还应查询 Sui 文档 MCP 服务器 (
https://sui.mcp.kapa.ai
) 以获取最新答案。使用它进行验证,并获取这些参考文件未涵盖的详细信息。
来源约束: 此 skill 中的所有信息均仅来自 docs.sui.io/sui-stack/on-chain-primitives/randomness-onchain。扩展或更新此 skill 时,只能从此来源提取内容。不要使用第三方博客、教程或非官方文档。
Sui 通过位于地址
0x8
的
Random
shared object 提供原生链上随机性。Move 函数从
Random
创建
RandomGenerator
实例,并使用它们生成不可预测的值。本 skill 介绍链上随机性的 API、使用模式、安全注意事项和攻击缓解措施。

Reference files

参考文件

usage -- API and Usage Patterns

usage -- API 与使用模式

Path:
usage.md
Load when: generating random values in Move, creating a
RandomGenerator
, calling
new_generator
, using
generate_u128
,
generate_u8_in_range
, passing the
Random
object from TypeScript, or writing basic randomness-consuming functions. Covers: the
Random
object (address
0x8
),
RandomGenerator
, the
random.move
API (full function list including
new_generator
, value generation, range generation,
shuffle
,
generate_bytes
), basic implementation examples, TypeScript integration.
路径:
usage.md
加载条件: 在 Move 中生成随机值、创建
RandomGenerator
、调用
new_generator
、使用
generate_u128
、使用
generate_u8_in_range
、从 TypeScript 传入
Random
对象,或编写基础的随机性消费函数时。 涵盖内容:
Random
对象(地址
0x8
)、
RandomGenerator
、
random.move
API(完整函数列表,包括
new_generator
、值生成、范围生成、
shuffle
、
generate_bytes
)、基础实现示例和 TypeScript 集成。

security -- Security and Attack Vectors

security -- 安全与攻击向量

Path:
security.md
Load when: securing randomness-consuming functions, preventing composition attacks, mitigating PTB attacks, avoiding
RandomGenerator
state leakage, implementing commit-reveal patterns, balancing gas across winning and losing paths, or choosing function visibility for randomness functions. Covers: composition attacks (abort-filtering via public functions), PTB attacks (command chaining after
MoveCall
consuming
Random
),
RandomGenerator
state leakage via
bcs::to_bytes
, compiler lints on public functions accepting
Random
or
RandomGenerator
, two-step commit-reveal pattern, balanced gas usage, entry function restrictions.

路径:
security.md
加载条件: 保护随机性消费函数、防止组合攻击、缓解 PTB 攻击、避免
RandomGenerator
状态泄漏、实现 commit-reveal 模式、平衡中奖与未中奖路径的 gas 消耗,或选择随机性函数的可见性时。 涵盖内容: 组合攻击(通过 public 函数实施 abort-filtering)、PTB 攻击(在消费
Random
的
MoveCall
之后链接命令)、通过
bcs::to_bytes
引发
RandomGenerator
状态泄漏、针对接受
Random
或
RandomGenerator
参数的 public 函数的编译器 lint、两步 commit-reveal 模式、gas 消耗均衡以及 entry 函数限制。

Routing guide

路由指南

TaskLoad
Generating random values in Moveusage
Creating a RandomGeneratorusage
Calling random API functionsusage
Passing Random from TypeScriptusage
Securing a randomness-consuming functionsecurity
Preventing composition or abort-filtering attackssecurity
Mitigating PTB-based attackssecurity
Avoiding RandomGenerator state leakagesecurity
Implementing commit-reveal for randomnesssecurity
Balancing gas across execution pathssecurity
Choosing function visibility for randomnesssecurity
Writing a complete randomness featureusage + security
Reviewing randomness code for vulnerabilitiesusage + security
任务加载
在 Move 中生成随机值usage
创建 RandomGeneratorusage
调用 random API 函数usage
从 TypeScript 传入 Randomusage
保护随机性消费函数security
防止组合攻击或 abort-filtering 攻击security
缓解基于 PTB 的攻击security
避免 RandomGenerator 状态泄漏security
为随机性实现 commit-revealsecurity
平衡各执行路径的 gas 消耗security
选择随机性函数的可见性security
编写完整的随机性功能usage + security
审查随机性代码中的漏洞usage + security

Rules

规则

  • The
    Random
    object lives at reserved address
    0x8
    and is immutable for transactions. Any attempt to modify it causes transaction failure.
  • Always create
    RandomGenerator
    locally within the consuming function using
    r.new_generator(ctx)
    . Never pass
    RandomGenerator
    as a
    public
    function parameter. Passing it to
    public(package)
    or private functions is acceptable for testing and in-package logic.
  • Define randomness-consuming functions as private
    entry
    functions. The Move compiler lints against
    public
    functions that accept
    Random
    or
    RandomGenerator
    as parameters.
  • Sui rejects PTBs containing commands other than
    TransferObjects
    or
    MergeCoins
    following a
    MoveCall
    that consumes
    Random
    . In other words, a call accepting
    Random
    must be the last
    MoveCall
    in a PTB.
  • Ensure winning and losing execution paths consume approximately equal total gas (both compute and storage) to prevent attackers from inferring outcomes from gas consumption. Measure gas carefully and test in each published environment before going live.
  • Use the two-step commit-reveal pattern when the outcome of randomness must not be observable before a follow-up action completes.
  • Random
    对象位于保留地址
    0x8
    ,并且在交易中不可变。任何修改尝试都会导致交易失败。
  • 始终在随机性消费函数内部使用
    r.new_generator(ctx)
    在本地创建
    RandomGenerator
    。绝不将
    RandomGenerator
    作为
    public
    函数参数传递。将其传递给
    public(package)
    或 private 函数对于测试和 package 内部逻辑是可接受的。
  • 将随机性消费函数定义为 private
    entry
    函数。Move 编译器会对接受
    Random
    或
    RandomGenerator
    参数的 public 函数发出 lint 警告。
  • Sui 会拒绝在消费
    Random
    的
    MoveCall
    之后包含除
    TransferObjects
    或
    MergeCoins
    之外命令的 PTB。换言之,接受
    Random
    的调用必须是 PTB 中最后一个
    MoveCall
    。
  • 确保中奖和未中奖的执行路径消耗大致相同的总 gas(计算和存储),以免攻击者通过 gas 消耗推断结果。上线前,应在每个发布环境中仔细测量 gas 并进行测试。
  • 如果必须在后续操作完成前隐藏随机性结果,请使用两步 commit-reveal 模式。

Common mistakes

常见错误

  • Making randomness functions
    public
    instead of private
    entry
    .
    This is a fatal security flaw, not just a mistake. Public functions accepting
    Random
    enable abort-filtering attacks where an attacker wraps the function and reverts unfavorable outcomes. The compiler lints against this.
  • Accepting
    RandomGenerator
    as a
    public
    function parameter.
    Callers can predict outputs by serializing the generator's internal state with
    bcs::to_bytes(&generator)
    . The compiler lints against
    public
    functions with
    RandomGenerator
    parameters. Using
    RandomGenerator
    as a parameter in
    public(package)
    or private functions is acceptable for testing and in-package logic.
  • Unbalanced gas consumption between branches. If winning and losing paths consume significantly different total gas (compute + storage), attackers can infer outcomes from gas usage. The success path should cost equal or more gas than the failure path. To achieve this, either perform a simple standard update (e.g., set a bool flag) and claim the result in a follow-up function, or create an equally sized object (e.g., a dynamic field) in the failure path. Gas values must be measured carefully and tested in each published environment before going live.
  • Skipping commit-reveal when outcomes influence subsequent user actions. If a user can observe and act on a random outcome in the same transaction, they can abort unfavorable results.
  • 将随机性函数设为
    public
    ,而不是 private
    entry
    。
    这是致命的安全缺陷,而不只是一个小错误。接受
    Random
    的 public 函数会启用 abort-filtering 攻击,攻击者可以包装该函数,并对不利结果执行 revert。编译器会对此发出 lint 警告。
  • 将
    RandomGenerator
    作为 public 函数参数接受。
    调用者可以通过
    bcs::to_bytes(&generator)
    序列化生成器的内部状态,从而预测输出结果。编译器会对带
    RandomGenerator
    参数的 public 函数发出 lint 警告。在测试和 package 内部逻辑中,可以将
    RandomGenerator
    作为
    public(package)
    或 private 函数的参数使用。
  • 分支之间的 gas 消耗不均衡。 如果中奖和未中奖路径消耗的总 gas(计算和存储)存在显著差异,攻击者便可以通过 gas 使用量推断结果。成功路径的 gas 成本应等于或高于失败路径。要实现这一点,可以执行简单的标准更新(例如,设置 bool 标志),并在后续函数中领取结果;或者在失败路径中创建一个大小相同的对象(例如 dynamic field)。上线前,必须在每个发布环境中仔细测量并测试 gas 数值。
  • 在结果会影响后续用户操作时跳过 commit-reveal。 如果用户可以在同一交易中观察并作用于随机结果,那么他们便能中止对自己不利的结果。