# 公平性验证

## 概述

MemeDice 内置了公平性验证工具，允许任何人独立验证游戏结果的随机性和公正性。验证方式取决于游戏使用的随机数模式：**Oracle 模式** 或 **Prevrandao 模式**。

***

## 如何访问验证工具

1. 访问任意 MemeDice 游戏（如 `xxx.dapp.meme`）
2. 点击顶部导航栏的 **「📋 日志」** 标签
3. 切换到 **「🔍 验证」** 标签页

<figure><img src="/files/8DXDg1ncanOoCASdWnd1" alt=""><figcaption></figcaption></figure>

***

## Oracle 模式验证

Oracle 模式使用 **commit-reveal** 机制生成随机数，这是一种经过密码学验证的公平随机数方案。

### 验证原理

```mermaid
sequenceDiagram
    participant Player as 玩家
    participant Contract as 游戏合约
    participant Oracle as Oracle 服务

    Note over Oracle: 1. 生成随机数 R
    Note over Oracle: 2. 计算 commitHash = keccak256(R)
    Oracle->>Player: 返回 commitHash + 签名
    Player->>Contract: 提交下注 + commitHash
    Note over Contract: 锁定 commitHash
    Oracle->>Contract: 揭示随机数 R
    Note over Contract: 3. 验证 keccak256(R) == commitHash ✅
    Note over Contract: 4. 使用 R 决定结果
```

### 验证步骤

1. **获取下注信息**：在下注记录中找到要验证的下注，记录其 `requestId`
2. **查看 commitHash**：下注交易中包含了 Oracle 预先提交的 `commitHash`
3. **查看揭示的随机数**：Oracle 后续提交的随机数 `R`
4. **独立验证**：计算 `keccak256(R)` 是否等于 `commitHash`

```
验证公式：keccak256(randomNumber) == commitHash
```

如果等式成立，说明：

* Oracle 在玩家下注 **之前** 就已经确定了随机数（通过 commitHash 锁定）
* Oracle **无法** 在看到玩家下注后修改随机数
* 随机数是公平的

### 使用验证工具

在验证标签页中：

1. 输入要验证的 **Request ID** 或 **交易哈希**
2. 工具会自动获取 `commitHash` 和 `randomNumber`
3. 自动计算并显示验证结果：✅ 通过 / ❌ 失败

<figure><img src="/files/vBPvfrcXo43wr0xrhe9w" alt=""><figcaption></figcaption></figure>

***

## Prevrandao 模式验证

Prevrandao 模式使用以太坊的 `block.prevrandao` 值作为随机数源。

### 验证原理

```
随机数 = block.prevrandao（下注交易所在区块的 prevrandao 值）
```

### 验证步骤

1. **获取下注交易哈希**：在下注记录中找到交易哈希
2. **查看区块号**：通过区块浏览器查看该交易所在的区块号
3. **获取 prevrandao**：查看该区块的 `prevrandao` 值
4. **验证结果**：确认合约使用的随机数与区块的 `prevrandao` 一致

### 通过区块浏览器验证

1. 在 [Etherscan](https://etherscan.io/) 中搜索交易哈希
2. 点击区块号进入区块详情
3. 查看 `Difficulty` 字段（在 PoS 后即为 `prevrandao`）
4. 对比合约事件中记录的随机数

<figure><img src="/files/XlUkUsTWTUivbC5h5ECs" alt=""><figcaption></figcaption></figure>

***

## 结果判定验证

无论使用哪种随机数模式，结果判定逻辑都是相同的：

```
阈值 = 10000 - winRateParam

如果押大（betOnBig = true）：
  随机数 % 10000 >= 阈值 → 赢
  随机数 % 10000 <  阈值 → 输

如果押小（betOnBig = false）：
  随机数 % 10000 <  winRateParam → 赢
  随机数 % 10000 >= winRateParam → 输
```

### 验证示例

| 参数           | 值         |
| ------------ | --------- |
| 随机数          | 123456789 |
| winRateParam | 5000（50%） |
| 方向           | 押大        |

```
阈值 = 10000 - 5000 = 5000
随机数 % 10000 = 123456789 % 10000 = 6789
6789 >= 5000 → ✅ 赢！
```

***

## 为什么可以信任？

### Oracle 模式的安全保证

| 保证       | 说明                                    |
| -------- | ------------------------------------- |
| **不可预测** | 随机数在 commitHash 提交时已确定，玩家无法预测         |
| **不可篡改** | Oracle 无法在看到下注后修改随机数（commitHash 已锁定）  |
| **可验证**  | 任何人都可以验证 `keccak256(R) == commitHash` |
| **超时保护** | 如果 Oracle 不揭示随机数，超时后Oracle自动回退资金      |

### Prevrandao 模式的安全保证

| 保证              | 说明                        |
| --------------- | ------------------------- |
| **链上原生**        | 随机数来自以太坊协议层，不依赖第三方        |
| **不可预测**（对普通用户） | 普通用户无法预测下一个区块的 prevrandao |
| **可验证**         | 任何人都可以通过区块浏览器验证           |
| **EOA 限制**      | 合约无法调用，防止闪电贷攻击            |

***

## 常见验证问题

### Q: 验证失败怎么办？

验证失败意味着 `keccak256(randomNumber) != commitHash`，这在正常情况下不应该发生。如果遇到验证失败：

1. 确认你输入的 Request ID 或交易哈希是否正确
2. 确认网络是否正确（BSC / Ethereum）
3. 如果确认无误但验证失败，请联系平台团队

### Q: 批量下注如何验证？

批量下注使用同一个随机数，但通过不同的计算方式为每注生成不同的结果：

```
第 1 注结果 = randomNumber % 10000
第 2 注结果 = (randomNumber / 10000) % 10000
第 3 注结果 = (randomNumber / 10000^2) % 10000
...
```

### Q: 为什么有些下注没有 commitHash？

使用 **Prevrandao 模式** 的下注不需要 commitHash，因为随机数直接来自区块的 `prevrandao` 值。

***

## 相关链接

* ⬅️ 返回 [排行榜与日志概览](/pai-xing-bang-yu-ri-zhi/pai-xing-bang-yu-ri-zhi-gai-lan.md)
* 🎲 了解 [Oracle vs Prevrandao](/ji-shu-gai-lan/oracle-vs-prevrandao.md)
* 🔒 了解 [Prevrandao 安全性](file:///7303089/deep-dive/prevrandao-security.md)
* 🛡️ 了解 [游戏安全性](/ji-shu-gai-lan/you-xi-an-quan-xing.md)


---

# Agent Instructions: 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:

```
GET https://docs.dapp.meme/pai-xing-bang-yu-ri-zhi/gong-ping-xing-yan-zheng.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
