【Sui】Derived Objects検証部屋

公式ドキュメント

Derived Objects(派生オブジェクト)とは
-
特徴
- オブジェクトのIDを 決定的に(予測可能に) 計算できる仕組み。
parent_id と key を組み合わせてhash(parent_id || key)
で生成される。
生成前でも オフチェーンでIDを計算 できる。
- オブジェクトのIDを 決定的に(予測可能に) 計算できる仕組み。
-
作り方
- claim を呼んで、親オブジェクトに「この key は使われた」とマークする。
以降、その Derived Object は独立したオブジェクトとして存在する。
- claim を呼んで、親オブジェクトに「この key は使われた」とマークする。
-
利点
- ミントを待たずに 事前にアドレスを用意 できる。
-
例:
- ゲーム → ガチャの報酬を事前に割り当て、ユーザーに即表示できる。
- エアドロップ → 先に100万人分のアドレスを計算してトークン送付、ユーザーは後から受け取り可能。
- マーケット → 存在前のNFTを出品可能。
- ファイルシステム → 親IDをフォルダ、keyをファイル名のように扱える。
👉 要するに、Derived Objectsは「事前に計算できる住所を持つオブジェクト」で、スケーラブルな設計や新しいUXを可能にする仕組み

ここでは実際の挙動を確認するために、以下の流れで検証をしていく
- NFTとミントを管理するレジストリを例にする
- スマートコントラクトをデプロイ
- オフチェーンでミント前のNFTのアドレスを計算
- ミント前に計算されたアドレスにTokenを送ってみる
- 実際にNFTをミントし、オフチェーンで計算したアドレスとNFTオブジェクトIDが一致するかを確認する
- Receiveを呼んでオブジェクトからTokenを受け取れるか検証する
- おまけ
- もう一度Claimするとエラーになるか確認する
- 親レジストリの動的フィールドを確認する

NFTとミントを管理するレジストリを例にする
まずはMoveでスマートコントラクトを書く
module derived_objects::derived_objects;
use sui::derived_object;
use sui::transfer::{Receiving};
public struct Registry has key { id: UID }
public struct OnigiriNFT has key, store { id: UID }
fun init(ctx: &mut TxContext) {
transfer::share_object(Registry { id: object::new(ctx) });
}
public fun mint(registry: &mut Registry, ctx: &mut TxContext) {
let nft = OnigiriNFT {
// id: object::new(ctx), // 従来の方法
id: derived_object::claim(&mut registry.id, ctx.sender()), // Derived Objectsの場合
};
transfer::transfer(nft, ctx.sender());
}
public fun receive_from_vault<T: key + store>(
nft: &mut OnigiriNFT,
receiving: Receiving<T>,
ctx: &TxContext
) {
let obj = transfer::public_receive(&mut nft.id, receiving);
transfer::public_transfer(obj, ctx.sender());
}
いままでと異なるのは、 UID の生成方法
- 従来:
id: object::new(ctx)
- Derived Objectsの場合:
id: derived_object::claim(&mut registry.id, ctx.sender())
- 親(Parent)としてRegistryのIDを指定し、キー(Key)としてSenderを指定

スマートコントラクトをデプロイ
スマコンをデプロイする
sui client publish
ログ
Transaction Digest: A5AFfKDT6Ep976oUKMdr9vAizdd3HDpyo6x5D9H56f51
╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Transaction Data │
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Sender: 0x7babb4543f2d93b99bc231134ebddc57f15416b38874834c7652c85cb01a0222 │
│ Gas Owner: 0x7babb4543f2d93b99bc231134ebddc57f15416b38874834c7652c85cb01a0222 │
│ Gas Budget: 12845200 MIST │
│ Gas Price: 1000 MIST │
│ Gas Payment: │
│ ┌── │
│ │ ID: 0xa6f17cc33669a2a77a47671389af4893306fdd6139e431670298c1bf248525f1 │
│ │ Version: 584426633 │
│ │ Digest: 9yWGq2rjnizrqng5KF4zon1PxMusr3cSjGz7bHP6t8rn │
│ └── │
│ │
│ Transaction Kind: Programmable │
│ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │
│ │ Input Objects │ │
│ ├──────────────────────────────────────────────────────────────────────────────────────────────────────────┤ │
│ │ 0 Pure Arg: Type: address, Value: "0x7babb4543f2d93b99bc231134ebddc57f15416b38874834c7652c85cb01a0222" │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────╯ │
│ ╭─────────────────────────────────────────────────────────────────────────╮ │
│ │ Commands │ │
│ ├─────────────────────────────────────────────────────────────────────────┤ │
│ │ 0 Publish: │ │
│ │ ┌ │ │
│ │ │ Dependencies: │ │
│ │ │ 0x0000000000000000000000000000000000000000000000000000000000000001 │ │
│ │ │ 0x0000000000000000000000000000000000000000000000000000000000000002 │ │
│ │ └ │ │
│ │ │ │
│ │ 1 TransferObjects: │ │
│ │ ┌ │ │
│ │ │ Arguments: │ │
│ │ │ Result 0 │ │
│ │ │ Address: Input 0 │ │
│ │ └ │ │
│ ╰─────────────────────────────────────────────────────────────────────────╯ │
│ │
│ Signatures: │
│ 0/l7UhEmfPkupI7+uGbnfjGV09AjKzw7iTD0OHldn7qUK3cx05vH9SN3aBYP7W4TDjTBZHm6a+ZCfMtdjQdNAw== │
│ │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
╭───────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Transaction Effects │
├───────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Digest: A5AFfKDT6Ep976oUKMdr9vAizdd3HDpyo6x5D9H56f51 │
│ Status: Success │
│ Executed Epoch: 870 │
│ │
│ Created Objects: │
│ ┌── │
│ │ ID: 0x268e2cced2ca098f3632432061553305ec806a774b1b6688cfa1db526b2f4ff9 │
│ │ Owner: Account Address ( 0x7babb4543f2d93b99bc231134ebddc57f15416b38874834c7652c85cb01a0222 ) │
│ │ Version: 584426634 │
│ │ Digest: 7bZtddS3f152ErhYZg2TjohJfPxzFchhCmsHpBwvQDm5 │
│ └── │
│ ┌── │
│ │ ID: 0xa998461a61867e7aa50f503c8191755ebe527c4cc42c7288fea630af229b01d2 │
│ │ Owner: Immutable │
│ │ Version: 1 │
│ │ Digest: 6u2jgymRJLaWgTTat2bf9PVKREUYN7JUuEdsBQpK3k29 │
│ └── │
│ ┌── │
│ │ ID: 0xf86b48f75dfd571b79ecf5e6dbb5bec43a798c72d21c40e0984542f448174d04 │
│ │ Owner: Shared( 584426634 ) │
│ │ Version: 584426634 │
│ │ Digest: 43kwc2VLo3poLGzG6G6fgC7WJ2xLzWUG8j6U6rFiUwe7 │
│ └── │
│ Mutated Objects: │
│ ┌── │
│ │ ID: 0xa6f17cc33669a2a77a47671389af4893306fdd6139e431670298c1bf248525f1 │
│ │ Owner: Account Address ( 0x7babb4543f2d93b99bc231134ebddc57f15416b38874834c7652c85cb01a0222 ) │
│ │ Version: 584426634 │
│ │ Digest: 5Efz9ZmGbsz9nQcMHFYJxfaKa6sKdQ7qVciM5rsjLYRD │
│ └── │
│ Gas Object: │
│ ┌── │
│ │ ID: 0xa6f17cc33669a2a77a47671389af4893306fdd6139e431670298c1bf248525f1 │
│ │ Owner: Account Address ( 0x7babb4543f2d93b99bc231134ebddc57f15416b38874834c7652c85cb01a0222 ) │
│ │ Version: 584426634 │
│ │ Digest: 5Efz9ZmGbsz9nQcMHFYJxfaKa6sKdQ7qVciM5rsjLYRD │
│ └── │
│ Gas Cost Summary: │
│ Storage Cost: 10845200 MIST │
│ Computation Cost: 1000000 MIST │
│ Storage Rebate: 978120 MIST │
│ Non-refundable Storage Fee: 9880 MIST │
│ │
│ Transaction Dependencies: │
│ 2dkJtqsoQcyCZJvjZnskNVPQeynwVtwCcA9goAru6tTi │
│ DKsNfdAJdSqvHaWmBTMaAWny7kjj7B9mA7GUdLib7dBT │
│ Dd9pn1zFcSJjinxQewFd2gQdR4XKsHxFioD5MYnwLZQz │
╰───────────────────────────────────────────────────────────────────────────────────────────────────╯
╭─────────────────────────────╮
│ No transaction block events │
╰─────────────────────────────╯
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Object Changes │
├───────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Created Objects: │
│ ┌── │
│ │ ObjectID: 0x268e2cced2ca098f3632432061553305ec806a774b1b6688cfa1db526b2f4ff9 │
│ │ Sender: 0x7babb4543f2d93b99bc231134ebddc57f15416b38874834c7652c85cb01a0222 │
│ │ Owner: Account Address ( 0x7babb4543f2d93b99bc231134ebddc57f15416b38874834c7652c85cb01a0222 ) │
│ │ ObjectType: 0x2::package::UpgradeCap │
│ │ Version: 584426634 │
│ │ Digest: 7bZtddS3f152ErhYZg2TjohJfPxzFchhCmsHpBwvQDm5 │
│ └── │
│ ┌── │
│ │ ObjectID: 0xf86b48f75dfd571b79ecf5e6dbb5bec43a798c72d21c40e0984542f448174d04 │
│ │ Sender: 0x7babb4543f2d93b99bc231134ebddc57f15416b38874834c7652c85cb01a0222 │
│ │ Owner: Shared( 584426634 ) │
│ │ ObjectType: 0xa998461a61867e7aa50f503c8191755ebe527c4cc42c7288fea630af229b01d2::derived_objects::Registry │
│ │ Version: 584426634 │
│ │ Digest: 43kwc2VLo3poLGzG6G6fgC7WJ2xLzWUG8j6U6rFiUwe7 │
│ └── │
│ Mutated Objects: │
│ ┌── │
│ │ ObjectID: 0xa6f17cc33669a2a77a47671389af4893306fdd6139e431670298c1bf248525f1 │
│ │ Sender: 0x7babb4543f2d93b99bc231134ebddc57f15416b38874834c7652c85cb01a0222 │
│ │ Owner: Account Address ( 0x7babb4543f2d93b99bc231134ebddc57f15416b38874834c7652c85cb01a0222 ) │
│ │ ObjectType: 0x2::coin::Coin<0x2::sui::SUI> │
│ │ Version: 584426634 │
│ │ Digest: 5Efz9ZmGbsz9nQcMHFYJxfaKa6sKdQ7qVciM5rsjLYRD │
│ └── │
│ Published Objects: │
│ ┌── │
│ │ PackageID: 0xa998461a61867e7aa50f503c8191755ebe527c4cc42c7288fea630af229b01d2 │
│ │ Version: 1 │
│ │ Digest: 6u2jgymRJLaWgTTat2bf9PVKREUYN7JUuEdsBQpK3k29 │
│ │ Modules: derived_objects │
│ └── │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
╭───────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Balance Changes │
├───────────────────────────────────────────────────────────────────────────────────────────────────┤
│ ┌── │
│ │ Owner: Account Address ( 0x7babb4543f2d93b99bc231134ebddc57f15416b38874834c7652c85cb01a0222 ) │
│ │ CoinType: 0x2::sui::SUI │
│ │ Amount: -10867080 │
│ └── │
╰───────────────────────────────────────────────────────────────────────────────────────────────────╯
ログからPackageIDとRegistry IDをメモしておく
PackageID: 0xa998461a61867e7aa50f503c8191755ebe527c4cc42c7288fea630af229b01d2
│ │ ObjectID: 0xf86b48f75dfd571b79ecf5e6dbb5bec43a798c72d21c40e0984542f448174d04 │
│ │ Sender: 0x7babb4543f2d93b99bc231134ebddc57f15416b38874834c7652c85cb01a0222 │
│ │ Owner: Shared( 584426634 ) │
│ │ ObjectType: 0xa998461a61867e7aa50f503c8191755ebe527c4cc42c7288fea630af229b01d2::derived_objects::Registry

オフチェーンでミント前のNFTのアドレスを計算
いよいよ、オフチェーンでミント前のNFTのオブジェクトIDを計算していくよ!わくわく
ちなみに、@mysten/sui/utils"
のSDKを使えば超簡単!
今回計算するのに必要なのはRegistory IDとミントするウォレットアドレスだけ。
import { bcs } from "@mysten/sui/bcs"
import { deriveObjectID } from "@mysten/sui/utils"
const REFISTRY_ID = "0xf86b48f75dfd571b79ecf5e6dbb5bec43a798c72d21c40e0984542f448174d04"
const WALLET_ADDRESS = "0x7babb4543f2d93b99bc231134ebddc57f15416b38874834c7652c85cb01a0222"
console.log(deriveObjectID(REFISTRY_ID, "address", bcs.Address.serialize(WALLET_ADDRESS).toBytes()))
実行結果
$ bun derived_objects.ts
0x11f3e872150c419b4e01ec89ff31aab53b5f6b9b1c4ac5acb7c2e876bbba96e7
0x11f3e872150c419b4e01ec89ff31aab53b5f6b9b1c4ac5acb7c2e876bbba96e7
これが、ミント前にオフチェーンで計算したアドレス!

ミント前に計算されたアドレスにTokenを送ってみる
すぐにNFTミントしたいけど、
エアドロップ → 先に100万人分のアドレスを計算してトークン送付、ユーザーは後から受け取り可能。
を検証したいので、オフチェーンで計算したNFTアドレスにTokenを送ってみる。今回は単純にSuiトークンを送る
ちなみにNFTなどのオブジェクトにトークンを送ることを、 Transfer to Obejctsって言うよ
Prime MachineやRootletsなどのNFTを持っている人にはお馴染みの概念だね!NFTがトークンや他のNFTを所有できたりするよ
ミント前のNFTアドレスにトークンを送る
Validと表示された!送れそう!なんかすごい
では実際に送ってみる!
送金成功!(ちなみに最初Mainnetで送ってしまい無事GOX。死にたい)
SuiVisionでアドレスを入れると、Accountのみ表示された!
実際に 0.1 SUI 着金している👍

実際にNFTをミントし、オフチェーンで計算したアドレスとNFTオブジェクトIDが一致するかを確認する
Sui Client PTB CLIで、実際にNFTをミントしてみるよ!
sui client ptb \
--move-call \
0xa998461a61867e7aa50f503c8191755ebe527c4cc42c7288fea630af229b01d2::derived_objects::mint \
@0xf86b48f75dfd571b79ecf5e6dbb5bec43a798c72d21c40e0984542f448174d04
ログ
Transaction Digest: DAkZC52Z3tNjiuLuWD7vShMYEjUr8emoTNGCQpgJx8gw
╭─────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Transaction Data │
├─────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Sender: 0x7babb4543f2d93b99bc231134ebddc57f15416b38874834c7652c85cb01a0222 │
│ Gas Owner: 0x7babb4543f2d93b99bc231134ebddc57f15416b38874834c7652c85cb01a0222 │
│ Gas Budget: 6877680 MIST │
│ Gas Price: 1000 MIST │
│ Gas Payment: │
│ ┌── │
│ │ ID: 0xa6f17cc33669a2a77a47671389af4893306fdd6139e431670298c1bf248525f1 │
│ │ Version: 584426635 │
│ │ Digest: 2ABcyh57B9aXWcthfjiPTSE6BEzWBg6EN44FrL25hg9E │
│ └── │
│ │
│ Transaction Kind: Programmable │
│ ╭─────────────────────────────────────────────────────────────────────────────────────────────╮ │
│ │ Input Objects │ │
│ ├─────────────────────────────────────────────────────────────────────────────────────────────┤ │
│ │ 0 Shared Object ID: 0xf86b48f75dfd571b79ecf5e6dbb5bec43a798c72d21c40e0984542f448174d04 │ │
│ ╰─────────────────────────────────────────────────────────────────────────────────────────────╯ │
│ ╭──────────────────────────────────────────────────────────────────────────────────╮ │
│ │ Commands │ │
│ ├──────────────────────────────────────────────────────────────────────────────────┤ │
│ │ 0 MoveCall: │ │
│ │ ┌ │ │
│ │ │ Function: mint │ │
│ │ │ Module: derived_objects │ │
│ │ │ Package: 0xa998461a61867e7aa50f503c8191755ebe527c4cc42c7288fea630af229b01d2 │ │
│ │ │ Arguments: │ │
│ │ │ Input 0 │ │
│ │ └ │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────╯ │
│ │
│ Signatures: │
│ FF1b8EmMvSyjVwAVfmYV3bwPtCvmdY6SBlZZXCmBKaaV02k8CeXdLTzAx0O5x1/lNruI0z+D7rU1rC+2FGZkBg== │
│ │
╰─────────────────────────────────────────────────────────────────────────────────────────────────╯
╭───────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Transaction Effects │
├───────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Digest: DAkZC52Z3tNjiuLuWD7vShMYEjUr8emoTNGCQpgJx8gw │
│ Status: Success │
│ Executed Epoch: 870 │
│ │
│ Created Objects: │
│ ┌── │
│ │ ID: 0x11f3e872150c419b4e01ec89ff31aab53b5f6b9b1c4ac5acb7c2e876bbba96e7 │
│ │ Owner: Account Address ( 0x7babb4543f2d93b99bc231134ebddc57f15416b38874834c7652c85cb01a0222 ) │
│ │ Version: 584426636 │
│ │ Digest: 6sXeLFZf3NFQe8w7dTvegjWEbh5mumgUBostDXoWccSh │
│ └── │
│ ┌── │
│ │ ID: 0xc255ca1b86523c911c7031752245c5c63e8b2033941083b599c9a9c13b3f4052 │
│ │ Owner: Object ID: ( 0xf86b48f75dfd571b79ecf5e6dbb5bec43a798c72d21c40e0984542f448174d04 ) │
│ │ Version: 584426636 │
│ │ Digest: 83xx613dbJypgkaBsoMEcwTFvjJXSoTuzynTskiKZBFJ │
│ └── │
│ Mutated Objects: │
│ ┌── │
│ │ ID: 0xa6f17cc33669a2a77a47671389af4893306fdd6139e431670298c1bf248525f1 │
│ │ Owner: Account Address ( 0x7babb4543f2d93b99bc231134ebddc57f15416b38874834c7652c85cb01a0222 ) │
│ │ Version: 584426636 │
│ │ Digest: 5vCSiUytJYXSVsNWjCik49Hmo2XgAUnidRFLtSRstrjS │
│ └── │
│ ┌── │
│ │ ID: 0xf86b48f75dfd571b79ecf5e6dbb5bec43a798c72d21c40e0984542f448174d04 │
│ │ Owner: Shared( 584426634 ) │
│ │ Version: 584426636 │
│ │ Digest: 7EtbtqLeNGaUgP3y8runDRRZH6r2XsVxNtcMFfdn89KB │
│ └── │
│ Shared Objects: │
│ ┌── │
│ │ ID: 0xf86b48f75dfd571b79ecf5e6dbb5bec43a798c72d21c40e0984542f448174d04 │
│ │ Version: 584426634 │
│ │ Digest: 43kwc2VLo3poLGzG6G6fgC7WJ2xLzWUG8j6U6rFiUwe7 │
│ └── │
│ Gas Object: │
│ ┌── │
│ │ ID: 0xa6f17cc33669a2a77a47671389af4893306fdd6139e431670298c1bf248525f1 │
│ │ Owner: Account Address ( 0x7babb4543f2d93b99bc231134ebddc57f15416b38874834c7652c85cb01a0222 ) │
│ │ Version: 584426636 │
│ │ Digest: 5vCSiUytJYXSVsNWjCik49Hmo2XgAUnidRFLtSRstrjS │
│ └── │
│ Gas Cost Summary: │
│ Storage Cost: 6232000 MIST │
│ Computation Cost: 1000000 MIST │
│ Storage Rebate: 2332440 MIST │
│ Non-refundable Storage Fee: 23560 MIST │
│ │
│ Transaction Dependencies: │
│ 7b3rRPQQv4FZaEJfjsopUfyEzjQLAWyJEfbkZtnzVrBo │
│ A5AFfKDT6Ep976oUKMdr9vAizdd3HDpyo6x5D9H56f51 │
╰───────────────────────────────────────────────────────────────────────────────────────────────────╯
╭─────────────────────────────╮
│ No transaction block events │
╰─────────────────────────────╯
╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Object Changes │
├─────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Created Objects: │
│ ┌── │
│ │ ObjectID: 0x11f3e872150c419b4e01ec89ff31aab53b5f6b9b1c4ac5acb7c2e876bbba96e7 │
│ │ Sender: 0x7babb4543f2d93b99bc231134ebddc57f15416b38874834c7652c85cb01a0222 │
│ │ Owner: Account Address ( 0x7babb4543f2d93b99bc231134ebddc57f15416b38874834c7652c85cb01a0222 ) │
│ │ ObjectType: 0xa998461a61867e7aa50f503c8191755ebe527c4cc42c7288fea630af229b01d2::derived_objects::OnigiriNFT │
│ │ Version: 584426636 │
│ │ Digest: 6sXeLFZf3NFQe8w7dTvegjWEbh5mumgUBostDXoWccSh │
│ └── │
│ ┌── │
│ │ ObjectID: 0xc255ca1b86523c911c7031752245c5c63e8b2033941083b599c9a9c13b3f4052 │
│ │ Sender: 0x7babb4543f2d93b99bc231134ebddc57f15416b38874834c7652c85cb01a0222 │
│ │ Owner: Object ID: ( 0xf86b48f75dfd571b79ecf5e6dbb5bec43a798c72d21c40e0984542f448174d04 ) │
│ │ ObjectType: 0x2::dynamic_field::Field<0x2::derived_object::Claimed, 0x2::derived_object::ClaimedStatus> │
│ │ Version: 584426636 │
│ │ Digest: 83xx613dbJypgkaBsoMEcwTFvjJXSoTuzynTskiKZBFJ │
│ └── │
│ Mutated Objects: │
│ ┌── │
│ │ ObjectID: 0xa6f17cc33669a2a77a47671389af4893306fdd6139e431670298c1bf248525f1 │
│ │ Sender: 0x7babb4543f2d93b99bc231134ebddc57f15416b38874834c7652c85cb01a0222 │
│ │ Owner: Account Address ( 0x7babb4543f2d93b99bc231134ebddc57f15416b38874834c7652c85cb01a0222 ) │
│ │ ObjectType: 0x2::coin::Coin<0x2::sui::SUI> │
│ │ Version: 584426636 │
│ │ Digest: 5vCSiUytJYXSVsNWjCik49Hmo2XgAUnidRFLtSRstrjS │
│ └── │
│ ┌── │
│ │ ObjectID: 0xf86b48f75dfd571b79ecf5e6dbb5bec43a798c72d21c40e0984542f448174d04 │
│ │ Sender: 0x7babb4543f2d93b99bc231134ebddc57f15416b38874834c7652c85cb01a0222 │
│ │ Owner: Shared( 584426634 ) │
│ │ ObjectType: 0xa998461a61867e7aa50f503c8191755ebe527c4cc42c7288fea630af229b01d2::derived_objects::Registry │
│ │ Version: 584426636 │
│ │ Digest: 7EtbtqLeNGaUgP3y8runDRRZH6r2XsVxNtcMFfdn89KB │
│ └── │
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
╭───────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Balance Changes │
├───────────────────────────────────────────────────────────────────────────────────────────────────┤
│ ┌── │
│ │ Owner: Account Address ( 0x7babb4543f2d93b99bc231134ebddc57f15416b38874834c7652c85cb01a0222 ) │
│ │ CoinType: 0x2::sui::SUI │
│ │ Amount: -4899560 │
│ └── │
╰───────────────────────────────────────────────────────────────────────────────────────────────────╯
│ Created Objects: │
│ ┌── │
│ │ ObjectID: 0x11f3e872150c419b4e01ec89ff31aab53b5f6b9b1c4ac5acb7c2e876bbba96e7 │
│ │ Sender: 0x7babb4543f2d93b99bc231134ebddc57f15416b38874834c7652c85cb01a0222 │
│ │ Owner: Account Address ( 0x7babb4543f2d93b99bc231134ebddc57f15416b38874834c7652c85cb01a0222 ) │
│ │ ObjectType: 0xa998461a61867e7aa50f503c8191755ebe527c4cc42c7288fea630af229b01d2::derived_objects::OnigiriNFT │
キターーーー 0x11f3e872150c419b4e01ec89ff31aab53b5f6b9b1c4ac5acb7c2e876bbba96e7
オフチェーン計算と一致した!
SuiVisionで検索してみると...
さっきはAccoutのみだったのに Object も増えてる!
ちゃんと 0x11f3e872150c419b4e01ec89ff31aab53b5f6b9b1c4ac5acb7c2e876bbba96e7
としてオブジェクトが生成されている。ちょっと感動

Receiveを呼んでオブジェクトからトークンを受け取れるか検証する
ミント前に送った(エアドロした) 0.1 SUI を実際に受け取れるか確認する
public fun receive_from_vault<T: key + store>(
nft: &mut OnigiriNFT,
receiving: Receiving<T>,
ctx: &TxContext
) {
let obj = transfer::public_receive(&mut nft.id, receiving);
transfer::public_transfer(obj, ctx.sender());
}
スマコンだとここでreceiveを定義している。ミントしたNFTのIDと、受け取りたいトークン(今回はSUI)のIDを指定する
PTBはこんな感じ
sui client ptb \
--move-call \
0xa998461a61867e7aa50f503c8191755ebe527c4cc42c7288fea630af229b01d2::derived_objects::receive_from_vault \
"<0x2::coin::Coin<0x2::sui::SUI>>" \
@0x11f3e872150c419b4e01ec89ff31aab53b5f6b9b1c4ac5acb7c2e876bbba96e7 @0x34feaeb836b9638877a4fabe994ca7f6749941e2d67a0316940b2c67c408bd32
ログ
Transaction Digest: 2wXTz4Hq24AusdrhfcxfFYWVQtteH5uhdcHDMre8wGaM
╭─────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Transaction Data │
├─────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Sender: 0x7babb4543f2d93b99bc231134ebddc57f15416b38874834c7652c85cb01a0222 │
│ Gas Owner: 0x7babb4543f2d93b99bc231134ebddc57f15416b38874834c7652c85cb01a0222 │
│ Gas Budget: 3011712 MIST │
│ Gas Price: 1000 MIST │
│ Gas Payment: │
│ ┌── │
│ │ ID: 0xa6f17cc33669a2a77a47671389af4893306fdd6139e431670298c1bf248525f1 │
│ │ Version: 584426637 │
│ │ Digest: AkD6VDNZRqbW7pma99hhi2SvLhZSx7NKJeoea4CmGtXc │
│ └── │
│ │
│ Transaction Kind: Programmable │
│ ╭─────────────────────────────────────────────────────────────────────────────────────────────╮ │
│ │ Input Objects │ │
│ ├─────────────────────────────────────────────────────────────────────────────────────────────┤ │
│ │ 0 Imm/Owned Object ID: 0x11f3e872150c419b4e01ec89ff31aab53b5f6b9b1c4ac5acb7c2e876bbba96e7 │ │
│ │ 1 Receiving Object ID: 0x34feaeb836b9638877a4fabe994ca7f6749941e2d67a0316940b2c67c408bd32 │ │
│ ╰─────────────────────────────────────────────────────────────────────────────────────────────╯ │
│ ╭──────────────────────────────────────────────────────────────────────────────────╮ │
│ │ Commands │ │
│ ├──────────────────────────────────────────────────────────────────────────────────┤ │
│ │ 0 MoveCall: │ │
│ │ ┌ │ │
│ │ │ Function: receive_from_vault │ │
│ │ │ Module: derived_objects │ │
│ │ │ Package: 0xa998461a61867e7aa50f503c8191755ebe527c4cc42c7288fea630af229b01d2 │ │
│ │ │ Type Arguments: │ │
│ │ │ 0x2::coin::Coin<0x2::sui::SUI> │ │
│ │ │ Arguments: │ │
│ │ │ Input 0 │ │
│ │ │ Input 1 │ │
│ │ └ │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────╯ │
│ │
│ Signatures: │
│ ehMqlOFcBvPsGH4KA8XqRrA4TRk3ffavQCexCQ11THQpFiheVOrLtqbaZlPUlPax+FZVcdLdYXYecpv2SgfZDg== │
│ │
╰─────────────────────────────────────────────────────────────────────────────────────────────────╯
╭───────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Transaction Effects │
├───────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Digest: 2wXTz4Hq24AusdrhfcxfFYWVQtteH5uhdcHDMre8wGaM │
│ Status: Success │
│ Executed Epoch: 870 │
│ Mutated Objects: │
│ ┌── │
│ │ ID: 0x11f3e872150c419b4e01ec89ff31aab53b5f6b9b1c4ac5acb7c2e876bbba96e7 │
│ │ Owner: Account Address ( 0x7babb4543f2d93b99bc231134ebddc57f15416b38874834c7652c85cb01a0222 ) │
│ │ Version: 584426638 │
│ │ Digest: 6rGp8oB1fmY6KDDZHNqwuHRuY2xmUi5u6mcvNjZngFCT │
│ └── │
│ ┌── │
│ │ ID: 0x34feaeb836b9638877a4fabe994ca7f6749941e2d67a0316940b2c67c408bd32 │
│ │ Owner: Account Address ( 0x7babb4543f2d93b99bc231134ebddc57f15416b38874834c7652c85cb01a0222 ) │
│ │ Version: 584426638 │
│ │ Digest: 46RTUhgUPWZteDVCC2hGaJsr43nFGkFtmd2yFWD7tgkB │
│ └── │
│ ┌── │
│ │ ID: 0xa6f17cc33669a2a77a47671389af4893306fdd6139e431670298c1bf248525f1 │
│ │ Owner: Account Address ( 0x7babb4543f2d93b99bc231134ebddc57f15416b38874834c7652c85cb01a0222 ) │
│ │ Version: 584426638 │
│ │ Digest: 125H21hQUuUy1Yypus4Gh6sR5nMNxxHTLXr8ZBT1dwm3 │
│ └── │
│ Gas Object: │
│ ┌── │
│ │ ID: 0xa6f17cc33669a2a77a47671389af4893306fdd6139e431670298c1bf248525f1 │
│ │ Owner: Account Address ( 0x7babb4543f2d93b99bc231134ebddc57f15416b38874834c7652c85cb01a0222 ) │
│ │ Version: 584426638 │
│ │ Digest: 125H21hQUuUy1Yypus4Gh6sR5nMNxxHTLXr8ZBT1dwm3 │
│ └── │
│ Gas Cost Summary: │
│ Storage Cost: 3359200 MIST │
│ Computation Cost: 1000000 MIST │
│ Storage Rebate: 3325608 MIST │
│ Non-refundable Storage Fee: 33592 MIST │
│ │
│ Transaction Dependencies: │
│ 2dkJtqsoQcyCZJvjZnskNVPQeynwVtwCcA9goAru6tTi │
│ 7b3rRPQQv4FZaEJfjsopUfyEzjQLAWyJEfbkZtnzVrBo │
│ 9tTvGUstD1wxNGTi9NoAnLv5NMAk9aKP5cyjkcMoJumS │
│ A5AFfKDT6Ep976oUKMdr9vAizdd3HDpyo6x5D9H56f51 │
│ DAkZC52Z3tNjiuLuWD7vShMYEjUr8emoTNGCQpgJx8gw │
╰───────────────────────────────────────────────────────────────────────────────────────────────────╯
╭─────────────────────────────╮
│ No transaction block events │
╰─────────────────────────────╯
╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Object Changes │
├─────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Mutated Objects: │
│ ┌── │
│ │ ObjectID: 0x11f3e872150c419b4e01ec89ff31aab53b5f6b9b1c4ac5acb7c2e876bbba96e7 │
│ │ Sender: 0x7babb4543f2d93b99bc231134ebddc57f15416b38874834c7652c85cb01a0222 │
│ │ Owner: Account Address ( 0x7babb4543f2d93b99bc231134ebddc57f15416b38874834c7652c85cb01a0222 ) │
│ │ ObjectType: 0xa998461a61867e7aa50f503c8191755ebe527c4cc42c7288fea630af229b01d2::derived_objects::OnigiriNFT │
│ │ Version: 584426638 │
│ │ Digest: 6rGp8oB1fmY6KDDZHNqwuHRuY2xmUi5u6mcvNjZngFCT │
│ └── │
│ ┌── │
│ │ ObjectID: 0x34feaeb836b9638877a4fabe994ca7f6749941e2d67a0316940b2c67c408bd32 │
│ │ Sender: 0x7babb4543f2d93b99bc231134ebddc57f15416b38874834c7652c85cb01a0222 │
│ │ Owner: Account Address ( 0x7babb4543f2d93b99bc231134ebddc57f15416b38874834c7652c85cb01a0222 ) │
│ │ ObjectType: 0x2::coin::Coin<0x2::sui::SUI> │
│ │ Version: 584426638 │
│ │ Digest: 46RTUhgUPWZteDVCC2hGaJsr43nFGkFtmd2yFWD7tgkB │
│ └── │
│ ┌── │
│ │ ObjectID: 0xa6f17cc33669a2a77a47671389af4893306fdd6139e431670298c1bf248525f1 │
│ │ Sender: 0x7babb4543f2d93b99bc231134ebddc57f15416b38874834c7652c85cb01a0222 │
│ │ Owner: Account Address ( 0x7babb4543f2d93b99bc231134ebddc57f15416b38874834c7652c85cb01a0222 ) │
│ │ ObjectType: 0x2::coin::Coin<0x2::sui::SUI> │
│ │ Version: 584426638 │
│ │ Digest: 125H21hQUuUy1Yypus4Gh6sR5nMNxxHTLXr8ZBT1dwm3 │
│ └── │
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
╭───────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Balance Changes │
├───────────────────────────────────────────────────────────────────────────────────────────────────┤
│ ┌── │
│ │ Owner: Account Address ( 0x11f3e872150c419b4e01ec89ff31aab53b5f6b9b1c4ac5acb7c2e876bbba96e7 ) │
│ │ CoinType: 0x2::sui::SUI │
│ │ Amount: -100000000 │
│ └── │
│ ┌── │
│ │ Owner: Account Address ( 0x7babb4543f2d93b99bc231134ebddc57f15416b38874834c7652c85cb01a0222 ) │
│ │ CoinType: 0x2::sui::SUI │
│ │ Amount: 98966408 │
│ └── │
╰───────────────────────────────────────────────────────────────────────────────────────────────────╯
成功したっぽいので、SuiVisionを確認する
NFT側のSUIはなくなっていて、
NFTのオーナー側でSUIを受け取ることができた!
これは例えばPrimeMachinにエアドロされた $BLUB トークンを、 PrimeMachinオーナーのウォレットアドレス宛にClaimした、みたいなのと一緒だよ

おまけ1: もう一度Claimするとエラーになるか確認する
Deribed Objectでアドレスを計算して生成することを Claim
という。
これは Parent + Key の組み合わせで1回しかClaimできないようになっている
id: derived_object::claim(&mut registry.id, ctx.sender())
つまり、今回書いた mint 関数の場合、特に何か assert はしていないけど、 Derived Objectsによって1アドレス1ミント を強制することができる!
これは想定していなかったちょっとした発見であった
public fun mint(registry: &mut Registry, ctx: &mut TxContext) {
let nft = OnigiriNFT {
id: derived_object::claim(&mut registry.id, ctx.sender()),
};
transfer::transfer(nft, ctx.sender());
}
試しに同じウォレットからmintを呼ぶと、エラーになる
エラー内容: 'EObjectAlreadyExists' -- 'Derived object is already claimed.'
sui client ptb \
--move-call \
0xa998461a61867e7aa50f503c8191755ebe527c4cc42c7288fea630af229b01d2::derived_objects::mint \
@0xf86b48f75dfd571b79ecf5e6dbb5bec43a798c72d21c40e0984542f448174d04
Error executing transaction 'ZuuMD2XAC7erXMjuNX8MjHgDKv9xsRFThCiUuk7kwf1': 1st command aborted within function '0x0000000000000000000000000000000000000000000000000000000000000002::derived_object::claim' at line 41. Aborted with error code 0 --'EObjectAlreadyExists' -- 'Derived object is already claimed.'

おまけ2: 親レジストリの動的フィールドを確認する
0xa998461a61867e7aa50f503c8191755ebe527c4cc42c7288fea630af229b01d2::derived_objects::Registry
がどうなっているか確認する
先ほど生成したNFTアドレスが、Registryの動的フィールドとして格納されている。
おまけ1ではここの動的フィールドを確認して、Claim済みかどうかをチェックし、Claim済みであれば 'EObjectAlreadyExists' -- 'Derived object is already claimed.'
エラーを投げるようになっている