前章で説明したストレージ操作はデフォルトで制限されており、オブジェクトを定義するモジュール内でのみ呼び出せる。言い換えれば、タイプはモジュール内部にあり、ストレージ操作で使用される必要がある。この制限はSui Verifierにおいて実装されており、バイトコードレベルで強制される。

ただし、オブジェクトを他のモジュールでトランスファーおよび保存できるようにするためには、これらの制限を緩和することができる。sui::transferモジュールは、他のモジュールでのストレージ操作の呼び出しを許可する一連のpublic_*関数を提供している。その関数はpublic_でプレフィックスされ、すべてのモジュールおよびトランザクションが利用できる。

公開ストレージ操作

sui::transferモジュールは次の公開関数を与える。これらは既に説明したものとほぼ同じだが、任意のモジュールから呼び出すことができる。

// File: sui-framework/sources/transfer.move
/// Public version of the `transfer` function.
public fun public_transfer<T: key + store>(object: T, to: address) {}

/// Public version of the `share_object` function.
public fun public_share_object<T: key + store>(object: T) {}

/// Public version of the `freeze_object` function.
public fun public_freeze_object<T: key + store>(object: T) {}

これらの関数の使い方を説明するために、次の例を考えよう。:モジュールAはキー(key)アビリティを持つオブジェクトKとキー+ストア(key + store)アビリティを持つオブジェクトKSを定義し、モジュールBはこれらのオブジェクトに対してトランスファー(transfer)関数を実装しようとする。

<aside> 💡 この例ではtransfer::transferを使うが、動作についてはshare_objectfreeze_object関数でも同じである。

</aside>

/// Defines `ObjectK` and `ObjectKS` with `key` and `key + store`
/// abilities respectively
module book::transfer_a {
    public struct ObjectK has key { id: UID }
    public struct ObjectKS has key, store { id: UID }
}

/// Imports the `ObjectK` and `ObjectKS` types from `transfer_a` and attempts
/// to implement different `transfer` functions for them
module book::transfer_b {
    // types are not internal to this module
    use book::transfer_a::{ObjectK, ObjectKS};

    // Fails! ObjectK is not `store`, and ObjectK is not internal to this module
    public fun transfer_k(k: ObjectK, to: address) {
        sui::transfer::transfer(k, to);
    }

    // Fails! ObjectKS has `store` but the function is not public
    public fun transfer_ks(ks: ObjectKS, to: address) {
        sui::transfer::transfer(ks, to);
    }

    // Fails! ObjectK is not `store`, `public_transfer` requires `store`
    public fun public_transfer_k(k: ObjectK) {
        sui::transfer::public_transfer(k);
    }

    // Works! ObjectKS has `store` and the function is public
    public fun public_transfer_ks(y: ObjectKS, to: address) {
        sui::transfer::public_transfer(y, to);
    }
}

上の例を拡大すると、

ストアの意味合い

ストア(store)アビリティをタイプに追加するかどうかの判断は慎重に行った方が良い。一方では、他のアプリケーションで型を使用可能にするため、それは事実上必要なものである。もう一方では、意図されたストレージモデルをラップして変更することを可能とする。 例えば、キャラクターはアカウントにより所有されることを意図しているかもしれないが、ストア(store)アビリティによって凍結されてしまう(共有不可であり、この変更は制限される)可能性がある。

The Move Book へ戻る