Skip to main content

一次性見證 (One Time Witness)

雖然一般的 見證 (Witness) 是靜態證明類型所有權的一種絕佳方式,但在某些情況下,我們需要確保見證僅被實例化一次。這就是「一次性見證 (One Time Witness, OTW)」的用途。

定義

OTW 是一種特殊的見證類型,只能使用一次。它無法手動建立,且保證在每個模組中都是唯一的。如果一個類型遵循以下規則,Sui 適配器 (Adapter) 就會將其視為 OTW:

  1. 僅具有 drop 能力。
  2. 沒有任何欄位。
  3. 不是泛型類型。
  4. 名稱與模組名稱相同,但全為大寫字母。

以下是 OTW 的範例:

module book::one_time;

/// `book::one_time` 模組的 OTW。
/// 僅 `drop`,沒有欄位,沒有泛型,全部大寫。
public struct ONE_TIME has drop {}

/// 以 OTW 實例作為第一個引數接收。
fun init(otw: ONE_TIME, ctx: &mut TxContext) {
// 對 OTW 進行某些操作
}

OTW 無法手動建構,任何嘗試建構它的程式碼都會導致編譯錯誤。OTW 可以作為 模組初始化器 (module initializer) 的第一個參數接收。由於 init 函式在每個模組中僅被呼叫一次,因此保證了 OTW 僅被實例化一次。

強制執行 OTW

要檢查一個類型是否為 OTW,Sui 框架sui::types 模組提供了一個特殊的函式 is_one_time_witness,可以用來驗證該類型是否為 OTW。

use sui::types;

const ENotOneTimeWitness: u64 = 1;

/// 以 OTW 作為引數,如果類型不是 OTW 則中止。
public fun takes_witness<T: drop>(otw: T) {
assert!(types::is_one_time_witness(&otw), ENotOneTimeWitness);
}

總結

OTW 模式是確保某種類型僅被使用一次的絕佳方式。大多數開發人員應該理解如何定義和接收 OTW,而 OTW 的檢查和強制執行主要出現在函式庫和框架中。例如,sui::coin 模組在 coin::create_currency 方法中要求傳入 OTW,從而強制確保 coin::TreasuryCap 僅被建立一次。

OTW 是一個強大的工具,它為 發佈者 (Publisher) 物件奠定了基礎,我們將在下一節中介紹。