> ## Documentation Index
> Fetch the complete documentation index at: https://docs.monad.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# 预编译

> 如何使用 Monad 的预编译合约

预编译是位于预定义地址的合约,提供以原生方式(而非 EVM 字节码)实现的加密和实用函数。
它们可以通过 `CALL` 或 `STATICCALL` 像任何其他合约一样调用。

Monad 支持截至 Fusaka 分叉的所有以太坊预编译(`0x01` 到 `0x11`),
以及三个额外的预编译:

* **`0x0100`** - [P256 签名验证](#p256-signature-verification) ([EIP-7951](https://eips.ethereum.org/EIPS/eip-7951))
* **`0x1000`** - [质押预编译](#staking-precompile)
* **`0x1001`** - [储备余额预编译](#reserve-balance-precompile)

## 以太坊预编译

### 加密和哈希

| 地址     | 名称          | Gas                     | 描述              |
| ------ | ----------- | ----------------------- | --------------- |
| `0x01` | `ecRecover` | `6000`                  | ECDSA 公钥恢复      |
| `0x02` | `sha256`    | `60 + 12 * word_size`   | SHA-256 哈希函数    |
| `0x03` | `ripemd160` | `600 + 120 * word_size` | RIPEMD-160 哈希函数 |
| `0x09` | `blake2f`   | `rounds * 2`            | BLAKE2 压缩函数 F   |

### 算术和实用

| 地址     | 名称         | Gas                                               | 描述       |
| ------ | ---------- | ------------------------------------------------- | -------- |
| `0x04` | `identity` | `15 + 3 * word_size`                              | 原样返回输入   |
| `0x05` | `modexp`   | [参见 evm.codes](https://www.evm.codes/precompiled) | 任意精度模幂运算 |

### 椭圆曲线 alt\_bn128

| 地址     | 名称          | Gas       | 描述                   |
| ------ | ----------- | --------- | -------------------- |
| `0x06` | `ecAdd`     | `300`     | alt\_bn128 上的点加法     |
| `0x07` | `ecMul`     | `30,000`  | alt\_bn128 上的标量乘法    |
| `0x08` | `ecPairing` | `225,000` | alt\_bn128 上的双线性配对检查 |

### KZG 承诺

| 地址     | 名称           | Gas       | 描述                                                                                         |
| ------ | ------------ | --------- | ------------------------------------------------------------------------------------------ |
| `0x0a` | `point_eval` | `200,000` | KZG 承诺验证 ([EIP-4844](https://eips.ethereum.org/EIPS/eip-4844#point-evaluation-precompile)) |

### BLS12-381

这些预编译根据 [EIP-2537](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2537.md) 提供对 BLS12-381 曲线的操作。

| 地址     | 名称                    | Gas                                                                          | 描述                 |
| ------ | --------------------- | ---------------------------------------------------------------------------- | ------------------ |
| `0x0b` | `bls12_g1_add`        | `375`                                                                        | G1 中的点加法           |
| `0x0c` | `bls12_g1_msm`        | [参见 EIP-2537](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2537.md) | G1 中的多标量乘法         |
| `0x0d` | `bls12_g2_add`        | `600`                                                                        | G2 中的点加法           |
| `0x0e` | `bls12_g2_msm`        | [参见 EIP-2537](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2537.md) | G2 中的多标量乘法         |
| `0x0f` | `bls12_pairing_check` | [参见 EIP-2537](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2537.md) | 对 (G1, G2) 点对的配对检查 |
| `0x10` | `bls12_map_fp_to_g1`  | `5500`                                                                       | 将基域元素映射到 G1 点      |
| `0x11` | `bls12_map_fp2_to_g2` | `23800`                                                                      | 将扩展域元素映射到 G2 点     |

## P256 签名验证

地址 `0x0100` 根据 [EIP-7951](https://eips.ethereum.org/EIPS/eip-7951) 验证 `secp256r1`(P256)椭圆曲线上的签名。

<Note>
  EIP-7951 取代了 [RIP-7212](https://github.com/ethereum/RIPs/blob/master/RIPS/rip-7212.md)。
  如果您正在从使用 `0x100` 处的 RIP-7212 的链迁移,请注意地址和接口是相同的 —— 只是 EIP 名称发生了变化。
</Note>

P256 曲线被 WebAuthn、Apple Secure Enclave、Android Keystore 和硬件安全模块使用。
借助此预编译,您可以在链上验证 passkey 签名,从而为智能账户启用生物识别身份验证流程,
而无需依赖链下签名验证。

### 输入和输出

预编译接受恰好 **160 字节**:

| 偏移量 | 大小    | 参数     | 描述      |
| --- | ----- | ------ | ------- |
| 0   | 32 字节 | `hash` | 消息哈希    |
| 32  | 32 字节 | `r`    | 签名分量 r  |
| 64  | 32 字节 | `s`    | 签名分量 s  |
| 96  | 32 字节 | `qx`   | 公钥 x 坐标 |
| 128 | 32 字节 | `qy`   | 公钥 y 坐标 |

所有值都以大端序编码为 256 位无符号整数。

**返回:**

* 签名有效时返回 `0x0000...0001`(32 字节)
* 签名无效或输入格式错误时返回空字节

**Gas 成本:** 6900

### Solidity 示例

```solidity theme={null}
address constant P256_VERIFY = address(0x0100);

function verifyP256Signature(
    bytes32 hash,
    uint256 r,
    uint256 s,
    uint256 qx,
    uint256 qy
) internal view returns (bool) {
    (bool success, bytes memory result) = P256_VERIFY.staticcall(
        abi.encodePacked(hash, r, s, qx, qy)
    );
    return success && result.length == 32 && abi.decode(result, (uint256)) == 1;
}
```

有关 Monad 上的 passkey 基础设施和嵌入式钱包提供商,请参见
[嵌入式钱包](/zh/tooling-and-infra/wallet-infra/embedded-wallets)。

## 质押预编译

地址 `0x1000` 提供验证者委托、取消委托、领取奖励和质押查询的接口。Gas 成本因函数而异。

* [质押概述](/zh/reference/staking/overview) —— 关键概念、常见操作和约束
* [质押 API 参考](/zh/reference/staking/api) —— 完整的方法签名、参数、gas 成本、事件和 ABI

## 储备余额预编译

地址 `0x1001` 公开了一个方法 `dippedIntoReserve()`(选择器 `0x3a61584e`,gas 成本 `100`),
该方法返回一个 `bool`,指示当前执行状态是否处于[储备余额](/zh/developer-essentials/reserve-balance)违规状态。
它在 [MIP-4](https://mips.monad.xyz/MIPs/MIP-4) 中规定。

`dippedIntoReserve()` 必须通过 `CALL` 调用。通过 `STATICCALL`(或通过 `DELEGATECALL` 或 `CALLCODE`)调用它会回滚。
虽然它读取状态并返回值,但它有意不是 `view` 函数,以便 Solidity 调用点编译为 `CALL` 而不是 `STATICCALL`。

## Gas 定价差异

一些预编译(`0x01`、`0x06`、`0x07`、`0x08`、`0x09`、`0x0a`)相对于以太坊被重新定价,
以反映其在 Monad 执行环境中的相对成本。上表中的 gas 值反映了 Monad 的定价。
参见 [Opcode 定价](/zh/developer-essentials/opcode-pricing#precompiles) 以进行对比。

## 源代码

参见[预编译实现](https://github.com/category-labs/monad/blob/main/category/execution/ethereum/precompiles.cpp)。
