# MRC-20

{% hint style="warning" %}
請注意該協議仍在測試網測試中,我們會在充分測試後在比特幣主網合適的區塊高度啟動該協議
{% endhint %}

MRC-20 是基於 MetaID 的一個 Fungible Token 發行協議，使用者可以透過 MRC-20 協議發行資產並制定鑄造方式。與其他資產發行協議相比，MRC-20 協議最大的特點是其發行方式能夠與各人鏈數據以及 MetaID 協議緊密結合，從而能夠滿足各種鏈上活動的資產發行方式。簡單來說，MRC-20 是一種為滿足日後各種 Web3 活動而制定的 Fungible Token 發行協議。

## 協議格式

### 部署

#### PIN路徑：`/ft/mrc20/deploy`

後端索引器應只對符合路徑的 PIN做驗證和索引

該路徑下的 PIN 不接受 modify 和 revoke操作

#### 協議格式：

```jsx
{
  "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` 說&#x660E;**：**

• 部署者可設置預挖參數，數值為在 deploy 交易中直接挖取指定次數的代幣

• 預挖的 Token 在 Deploy 交易確認時直接預挖到 Deploy 使用者地址上。

• 預挖總量 = `amtPerMint` \* `premineCount`

• `premineCount` 為選項，默認值為 0，取值範圍為 0\~mintCount，範圍之外的賦值視為無效

• 例子：一個 deploy 中設置為 `amtPerMint` = 10000, `mintCount` = 100, `premineCount` = 60，則視為 100 次的總挖取次數中預挖了 60 次，只有剩餘 40 次為公開的可鑄造次數

#### `payCheck` 說&#x660E;**：**

• 如果部署者設置了 `payCheck` 項目，則每次鑄造時均會檢查鑄造交易是否向指定地址支付了指定的 satoshi，如不符合要求則鑄造無效

• `payTo` 項目為鑄造時需向指定的地址轉入；`payAmount` 為鑄造時需向 `payTo` 地址轉移指定數量的 satoshi

#### `pinCheck` 說明

* 如果部署者設置了 `pinCheck` 項目，則每次鑄造時均會檢查鑄造交易中是否帶了指定條件的 PIN，如不符合要求則鑄造無效
* `creator` 為檢查 PIN 創建者是否為指定 MetaID&#x20;
* `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示例**

```json
// 不限制路徑和難度及創建者，任意一個 PIN 均有鑄造資格
"pinCheck": {
  "count": "1"
}

// 需要一個 simplebuzz 協議的 PIN
"pinCheck": {
  "path": "/protocols/simplebuzz"
}

// 需要關注過特定 metaid 的 PIN
"pinCheck": {
  "path": "/follow['metaid_of_me']"
}

// 需要點贊過某個 PIN 的 PIN
"pinCheck": {
  "path": "/protocols/paylike['liketo'='abcdefgh...']"
}

// /protocols 下的任意協議的 PIN（2 個）均有鑄造資格
"pinCheck": {
  "path": "/protocols/*",
  "count": 2
}

// 需要擁有我的 PIN 才有鑄造資格
"pinCheck": {
  "creator": "abcdef0123457" // 需要 metaid 為“abcdef0123457”所創造的 pin
}
```

### 鑄造

#### PIN 路徑：`/ft/mrc20/mint`

後端索引器應只對符合路徑的 mint 資料做驗證和索引

該路徑下的 PIN 不接受 `modify` 和 `revoke`操作

#### 協議格式：

```tsx
{
  "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/W1QbyKw8RWTipgI3jsoc" alt=""><figcaption><p>使用 Taproot 信封鑄造，該 mrc20 的鑄造條件中需要 3 個 pin（count: 3)，payCheck 條件為給 address xxx 地址支付 100000 聰 BTC。</p></figcaption></figure>

### Transfer 轉帳

{% hint style="info" %}
轉帳有兩種形式：原生轉帳和數據轉帳
{% endhint %}

#### 原生轉帳（直接轉帳）

原生轉帳是一種簡易的、Layer 1 的轉帳方式，不需要依靠寫入轉帳數據的方式，以純粹的 utxo 轉移方式完成。

原生轉帳適合於不需要 MRC20 代幣找零 的場景，如

1\. Alice 將自己的某種 MRC20 代幣 全部 轉移給 Bob。

2\. Alice 需要給 Bob 轉移的某種 MRC20 代幣的 數量剛好是其中一個或幾個 MRC20 UTXO 的數量之和。

#### 原生轉帳交易構造

當 input 中帶有 MRC20 UTXO，且交易中沒有指明轉帳數據（OPRETURN 或 taproot 數據），則所有 MRC 餘額轉入第一個非 OPRETURN 輸出中

<figure><img src="/files/nDfNMh0tZATM1EHgEVVM" 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，退回到缺省的直接轉帳機制，即當前交易中所有 MRC 餘額轉入第一個非 OPRETURN 輸出。

• input 中未被分配完的餘額，使用缺省的直接轉帳機制，自動賦予第一個非 OP\_RETURN 的輸出。可將該機制看作自動找零的行為，默認將未分配的餘額部份找零到第一個 output。

• 其他未被認可的數據轉帳寫法被視為非法，使用缺省的直接轉帳機制，此交易中的 MRC20 餘額將轉入第一個輸出。

#### 數據轉帳格式

數據轉帳寫在 MetaID 信封的 payload 中，以數組的形式存在。

```tsx
type MRC20AllocationItem = {
	id: string
	amount: string
	type?: 'transfer' | 'teleport' = 'transfer'
	vout?: number
	coord?: string
}

type MRC20Allocation = MRC20AllocationItem[]
```

#### 數據轉帳字段說明

* **`id`**: 分配的 MRC20 的 MRC20ID
* **`amount`**: 分配的 MRC20 數量
* **`type`**: 操作類型。有兩種類型：
  * **`transfer`**: （默認）轉帳，指該部份餘額轉到當前交易的某個輸出中。當類型為 transfer 時，需指定 vout
  * **`teleport`**：躍遷，指該部份餘額轉到非本鏈的某個 已存在 的 UTXO 中。當類型為 teleport 時，需指定 coord。躍遷的詳情請參考下一部份。
* **`vout`**: MRC20 分配到的 output index。
* **`coord`**：躍遷時 MRC20 分配到的非本鏈的 UTXO 的位置，以 ${txid}i${vout} 的形式表達。

#### 數據轉帳示例

* 以下 JSON 實例為 MetaID 協議規範中的 payload 項，外層需遵循 MetaID 信封規範。

```tsx
const allocation: MRC20Allocation = [
  {
    "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/ZVG1BjekU0R7m00RFZsJ" alt=""><figcaption><p>完全分配</p></figcaption></figure>

<figure><img src="/files/dDDgzaA0sZkCW5RstLgJ" alt=""><figcaption><p>部分分配，未被指定分配的餘額將自動找零歸入第一個output</p></figcaption></figure>

<figure><img src="/files/H6MBpoajXaasoUbehhFW" alt=""><figcaption><p>無效分配，分配方案大於輸入中的餘額；此時無視分配方案，退回到缺省的直接轉帳機制</p></figcaption></figure>

## Teleport 躍遷（跨鏈）

### 躍遷示例

```tsx
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 字段
}
```

* 躍遷實現了 MRC-20 的跨鏈功能；可以視為是 transfer 的擴維版本。transfer 將 MRC-20 餘額分配到本交易的 output 中，teleport 將餘額分配到其他鏈的 output 中。
* `coord`（坐標）使用另外鏈中的 `${txid}i${vout}` 格式來定位目標 utxo
* `coord` 指向的 utxo 由 indexer 來識別所在的鏈，無需在數據中表達
* 如果 `coord` 指向的 utxo 不存在（indexer 無法尋得），此交易依然視為有效，而 teleport 分配的餘額部份視為燃燒。
* teleport 可以同 transfer 並列於一個交易內，分配優先級高於 transfer

<figure><img src="/files/GjQuYdJeFLmxrcnvzI7f" alt=""><figcaption><p>躍遷示例</p></figcaption></figure>

### Teleport 同 Transfer 可以同層

<figure><img src="/files/PVXdHJAYPsU64tMuDkzj" 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-hk/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.
