通常のWitnessは型の所有権を静的に証明する優れた方法ですが、Witnessが一度だけインスタンス化されることを保証する必要がある場合があります。これがOne Time Witness(OTW)の目的です。
OTWは一度だけ使用できる特別な種類のWitnessです。手動で作成することはできず、モジュールごとに一意であることが保証されています。Sui Adapterは、以下のルールに従う型をOTWとして扱います:
drop
能力のみを持つ。以下はOTWの例です:
module book::one_time {
/// `book::one_time`モジュールのOTW。
/// `drop`のみ、フィールドなし、ジェネリックなし、すべて大文字。
public struct ONE_TIME has drop {}
/// `ONE_TIME`のインスタンスを最初の引数として受け取る。
fun init(otw: ONE_TIME, ctx: &mut TxContext) {
// OTWを使って何かを行う
}
}
OTWは手動で構築することはできず、そのような試みはコンパイルエラーになります。OTWはモジュール初期化子(Module Initializer)の最初の引数として受け取ることができます。そして、init
関数はモジュールごとに一度だけ呼び出されるため、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オブジェクトの基礎を築きます。
The Move Book へ戻る