# MRC-20

MRC-20 是基于 MetaID 的一个 Fungible Token 发行协议，用户可以通过 MRC-20 协议发行资产并制定铸造方式。与其他资产发行协议相比，MRC-20 协议最大的特点是其发行方式能够与个人链数据以及 MetaID 协议紧密结合，从而满足各种链上活动的资产发行需求。简单来说，MRC-20 是一种为满足日后各种 Web3 活动而制定的 Fungible Token 发行协议。

### 协议格式

#### 部署

**PIN 路径**：`/ft/mrc20/deploy`

后端索引器应只对符合路径的 PIN 做验证和索引。

* 该路径下的 PIN 不接受 `modify` 和 `revoke` 操作。

#### 协议格式

```json
{
  "tick": "satoshi", // 2-24 字符
  "amtPerMint": "1000", // 每次铸造获得的总代币数量 [1, 1e12]
  "mintCount": "100", // 最大允许铸造次数 [1, 1e12]
  "tokenName": "SatoshiTheLegend", // 选填，代币全名，0-48 字符
  "decimals": "8", // 选填，小数位数 0 至 12，默认值为 8
  "premineCount": "60", // 选填，部署时预先铸造的次数，默认值为 0，[0, mintCount]
  "beginHeight": "851235", // 选填，铸造事件开始的区块高度
  "endHeight": "851781", // 选填，铸造事件结束的区块高度
  "metadata": "Arbitrary Data", // 选填，可以包含额外数据如代币描述、图示等，无格式要求
  "payCheck": { // 选填，检查付款以验证铸造资格
    "payTo": "address", // 检查输出是否匹配指定地址
    "payAmount": "" // 以 satoshi 为单位，检查是否支付了指定数量的 satoshi
  },
  "pinCheck": { // 选填，检查 PIN 以验证铸造资格
    "creator": "", // 创建 PIN 的人，使用完整的 MetaID
    "path": "/", // PIN 的路径
    "count": "1", // 0~n，所需的 PIN 数量
    "lvl": "6" // PIN 的最低等级
  }
}
```

### 要点说明

* 合法的创始交易后，该 `tick` 将被分配一个唯一的 ID，该 ID 用于标识该 MRC-20 代币。该 ID 用 `pinid` 表示。
* `tick` 为全局唯一，不可重复，`tick` 的有效判定采用先见原则。
* 总供应量 = `amtPerMint` \* `mintCount`
* `metadata` 为自定义数据项，可绑定代币相关数据，可以包含简介、图片等。
* `beginHeight` 和 `endHeight` 决定了铸造时间的有效时间范围。`beginHeight` 如未指定有效区块高度，则为 Deploy 该 PIN 确认高度；`endHeight` 如未指定有效区块高度，则代表无结束时间限制。

#### `premineCount` 说明

* 部署者可设置预挖参数，数值为在 deploy 交易中直接挖取指定次数的代币。
* 预挖的 Token 在 Deploy 交易确认时直接预挖到 Deploy 使用者地址上。
* 预挖总量 = `amtPerMint` \* `premineCount`
* `premineCount` 为选项，默认值为 0，取值范围为 `0~mintCount`，范围之外的赋值视为无效。
* **例子**：一个 deploy 中设置为 `amtPerMint = 10000`, `mintCount = 100`, `premineCount = 60`，则视为 100 次的总挖取次数中预挖了 60 次，只有剩余 40 次为公开的可铸造次数。

#### `payCheck` 说明

* 如果部署者设置了 `payCheck` 项目，则每次铸造时均会检查铸造交易是否向指定地址支付了指定的 satoshi，如不符合要求则铸造无效。
* `payTo` 项目为铸造时需向指定的地址转入；`payAmount` 为铸造时需向 `payTo` 地址转移指定数量的 satoshi。

#### `pinCheck` 说明

如果部署者设置了 `pinCheck` 项目，则每次铸造时均会检查铸造交易中是否带了指定条件的 PIN，如不符合要求则铸造无效。

* `creator` 为检查 PIN 创建者是否为指定 MetaID。
* `path` 为检查 PIN 所在路径是否为指定的路径。
  * `path` 的格式请详细查看 MetaID 协议关于 `path` 的说明。
  * `path` 支持该 `path payload` 的内容匹配：
    * `/path['payload']` 匹配指定 path 位置下 payload 的全部内容。
    * `/path['key'='value']` 匹配指定 path 位置下 payload 里的 key 和 value 值。
* `count` 为检查符合条件的 PIN 的数量，默认值为 1。
* `lvl` 为检查 PIN 的等级是否符合要求。`lvl` 由 PIN 的 PoP 值决定，请详细查看 PoP 值和 `lvl` 值说明。

`checkPin` 里的 4 个参数可相互组合，形成可适应多场景的铸造要求。

#### `pinCheck` 示例

* **不限制路径和难度及创建者，任意一个 PIN 均有铸造资格**

  ```json
  "pinCheck": {
    "count": "1"
  }
  ```
* **需要一个 simplebuzz 协议的 PIN**

  ```json
  "pinCheck": {
    "path": "/protocols/simplebuzz"
  }
  ```
* **需要关注过特定 metaid 的 PIN**

  ```json
  "pinCheck": {
    "path": "/follow['metaid_of_me']"
  }
  ```
* **需要点赞过某个 PIN 的 PIN**

  ```json
  "pinCheck": {
    "path": "/protocols/paylike['liketo'='abcdefgh...']"
  }
  ```
* **/protocols 下的任意协议的 PIN（2 个）均有铸造资格**

  ```json
  "pinCheck": {
    "path": "/protocols/*",
    "count": 2
  }
  ```
* **需要拥有我的 PIN 才有铸造资格**

  ```json
  "pinCheck": {
    "creator": "abcdef0123457" // 需要 metaid 为 "abcdef0123457" 所创造的 pin
  }
  ```

### 铸造

**PIN 路径**：`/ft/mrc20/mint`

后端索引器应只对符合路径的 mint 数据做验证和索引。

* 该路径下的 PIN 不接受 `modify` 和 `revoke` 操作。

#### 协议格式

```json
{
  "id": "479f8579e5dcdbef868a61541f0d55efccfee1704c8a03f07fb1d97577104d53i0" // tokenID，这个 tokenID 是 deploy 交易的 PINID
}
```

### 要点说明

* 协议只有一个参数，就是 `id`，代表了要铸造的 `tokenid`，`tokenid` 为 Deploy PIN 对应的 PINID。
* 铸造的 token 总量由 Deploy 的 `amtPerMint` 参数决定。如成功铸造，该次铸造的 token 总量会转移到 Mint 交易的第一个 output 的第一个 satoshi 上。
* 铸造有效性由 `indexer` 服务决定，`indexer` 根据 Deploy 中的相关条件和约束规则验证该铸造交易是否合法。判断的规则全都是链上数据，所以即便不同开发者开发的 indexer 的校验结果也应该是一致的。
* 如果 Deploy 文件有 pinCheck 要求时，Mint 交易的 input 需要指向一个或多个有效的 PIN 以完成 PIN 校验。
* 一个 PIN 在同一个 token 的 mint event 中，只能使用一次。
* 如果 Deploy PIN 有 payCheck 要求时，Mint 交易需要有一个 output 符合 payCheck 的地址和金额要求。
* Mint 不支持跨链铸造，也就是说 Mint 交易必须和其对应的 Deploy 交易处于同一链中。

#### Mint 交易构建例子

<figure><img src="/files/p4QDvwbFNlpuztL6LYQx" alt=""><figcaption><p>使用 Taproot 信封铸造，该 MRC20 的铸造条件中需要 3 个 PIN（count: 3），payCheck 条件为向地址 xxx 支付 100000 聪 BTC。</p></figcaption></figure>

### Transfer 转账

转账有两种形式：原生转账和数据转账。

#### 原生转账（直接转账）

原生转账是一种简易的、Layer 1 的转账方式，不需要依靠写入转账数据的方式，以纯粹的 UTXO 转移方式完成。

原生转账适用于不需要 MRC20 代币找零的场景，如：

1. Alice 将自己的某种 MRC20 代币 **全部** 转移给 Bob。
2. Alice 需要给 Bob 转移的某种 MRC20 代币的数量刚好是其中一个或几个 MRC20 UTXO 的数量之和。

**原生转账交易构造**

当 `input` 中带有 MRC20 UTXO，且交易中没有指明转账数据（如 OPRETURN 或 Taproot 数据），则所有 MRC20 余额将转入第一个非 OPRETURN 输出中。

<figure><img src="/files/dzKOXY0s8dFCXVsUcVbS" alt=""><figcaption><p>Native transfer</p></figcaption></figure>

### 数据转账 (MRC20 Allocation)

* 数据转账指通过在 MetaID 规范的 Taproot 信封中显式写入转账说明数据进行转账的方式。使用 JSON 格式，通过指定的规则，规定交易中传入的 `input` 中的 MRC20 余额分别分配到哪些 `output` 中。
* 数据转账适用于所有复杂的、需要有多个 `output` 分配的，或是需要进行余额找零的交易类型。
* 数据转账使用的 PIN Path 为 `/ft/mrc20/transfer`。
* 数据转账使用与 PIN 类似的数据结构，其中 `operation` 使用 `hide` 类型，不生成对应的 UTXO，不带有 `pinId`。
* 如果分配方案超过了 `input` 中包含的 MRC20 数量的总额，则该分配视为无效（invalid），退回到缺省的直接转账机制，即当前交易中所有 MRC20 余额转入第一个非 `OPRETURN` 输出中。
* `input` 中未被分配完的余额，使用缺省的直接转账机制，自动赋予第一个非 `OP_RETURN` 的输出。可以将该机制看作自动找零的行为，默认将未分配的余额部分找零到第一个输出。
* 其他未被认可的数据转账写法被视为非法，使用缺省的直接转账机制，此交易中的 MRC20 余额将转入第一个输出。

#### 示例代码

```javascript
const allocation = [
  {
    "amount": "100",
    "vout": 0,
    "id": "479f8579e5dcdbef868a61541f0d55efccfee1704c8a03f07fb1d97577104d53i0", // 'token1'
  },
  {
    "amount": "256",
    "vout": 3,
    "id": "bcccd98a7a1250f26b57d47cfdd36a95866d4bee59c32c9d4e71a6cc1f3429a5i0", // 'token2'
  },
  {
    "amount": "300",
    "vout": 3,
    "id": "479f8579e5dcdbef868a61541f0d55efccfee1704c8a03f07fb1d97577104d53i0", // 'token1'
  },
];

const pinData = {
  metaidFlag: 'metaid',
  operation: 'hide',
  path: '/ft/mrc20/transfer',
  contentType: 'application/json',
  payload: JSON.stringify(allocation) // 将分配数据进行 JSON 序列化放入 payload 字段
};
```

以上的转账交易中：

* 100 个 `token1` 分配给 `index:0` 输出。
* 256 个 `token2` 分配给 `index:3` 输出。
* 300 个 `token1` 分配给 `index:3` 输出。

<figure><img src="/files/cXHXG8rsJnerovmwHCDs" alt=""><figcaption><p>完全分配</p></figcaption></figure>

<figure><img src="/files/3FwfKY8KfYD48rk4KKqD" alt=""><figcaption><p>部分分配，未被指定分配的余额将自动找零归入第一个 output。</p></figcaption></figure>

<figure><img src="/files/7KPOL4bxkDWAu49ETWvC" alt=""><figcaption><p>无效分配：分配方案超过输入中的余额，此时将忽略分配方案，退回到默认的直接转账机制。</p></figcaption></figure>

## Teleport 跨链

### 跨链示例

```javascript
const allocation: MRC20Allocation = [
  {
    amount: '100',
    id: '479f8579e5dcdbef868a61541f0d55efccfee1704c8a03f07fb1d97577104d53i0', // 'token1'
    coord: 'bcccd98a7a1250f26b57d47cfdd36a95866d4bee59c32c9d4e71a6cc1f3429a5i2', // 跨链坐标，使用 pinId 结构定位 utxo
    type: 'teleport',
  },
]

const pinData = {
  metaidFlag: 'metaid',
  operation: 'hide',
  path: '/ft/mrc20/transfer',
  contentType: 'application/json',
  payload: JSON.stringify(allocation) // 将分配数据进行 JSON 序列化放入 payload 字段
}
```

### 功能说明

Teleport 实现了 MRC-20 的跨链功能，可以视为 transfer 的扩展版本。

* **transfer**：将 MRC-20 余额分配到本交易的 output 中。
* **teleport**：将余额分配到其他链的 output 中。

#### coord（坐标）

* **格式**：使用另外链中的 `${txid}i${vout}` 格式来定位目标 utxo。
* **链识别**：coord 指向的 utxo 由 indexer 识别所在链，无需在数据中直接表述。

#### 错误处理

如果 coord 指向的 utxo 不存在（indexer 无法找到），此交易依然视为有效，而 teleport 分配的余额部分视为燃烧。

#### 与 transfer 的关系

* teleport 可以与 transfer 并列于一个交易内。
* **优先级**：分配优先级高于 transfer。

<figure><img src="/files/9j7y5thGjh2JbCLzWKJT" alt=""><figcaption><p>跨链示例</p></figcaption></figure>

### Teleport 与 Transfer 可以同层

<figure><img src="/files/DWoBQsTBz5UAEUWGBGW9" alt=""><figcaption><p>跨链和转账可以同时存在</p></figcaption></figure>


---

# 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.metaid.io/zh/zi-chan-xie-yi/mrc-20.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.
