Skip to main content

接收物件 (Receiving as Object)

地址擁有的 物件狀態支援兩種類型的擁有者:帳戶和另一個物件。如果一個物件被轉移到另一個物件,Sui 提供了一種透過其擁有者的 UID 來「接收 (receive)」此物件的方法。

此功能也被稱為「轉移至物件 (Transfer to Object)」或 TTO。

定義

接收功能在 sui::transfer 模組中實作。它包含一個特殊的類型 Receiving(透過特殊的交易參數實例化),以及接收函式 receive(接收父物件的 UID)。

目前,transfer::receive 中的 T 受限於 內部約束 (Internal Constraint)receive 的公開版本稱為 public_receive,與其他 [存儲函式 (storage functions)][storage-funs] 一樣,它要求 T 具有 store

module sui::transfer;

// 基於 `Receiving` 參數的臨時封裝器。在交易區塊中作為特殊輸入提供。
// 注意:此類型必須明確匯入才能使用!
public struct Receiving<phantom T: key> has drop {
id: ID,
version: u64,
}

/// 從父物件 `UID` 透過特殊類型 `Receiving` 接收 `T`。
public fun receive<T: key>(parent: &mut UID, to_receive: Receiving<T>): T;

由於對 UID 類型的要求,接收操作無法在不提供存取權限或特殊接收實作的任意物件上執行。此功能應謹慎使用,並在受控環境下進行。

範例

作為「轉移」與「接收」的說明,考慮一個範例:PostOffice 允許註冊郵政信箱 (Post Box) 並向帳戶的郵政信箱發送物件。

module book::receiving;

use sui::derived_object;
use sui::transfer::Receiving; // 預設未匯入!

/// 用於建立衍生 `PostBox` 的基礎衍生物件。
public struct PostOffice has key { id: UID }

/// 具有衍生 UID 的物件,接收發送到某個位址的物件。
public struct PostBox has key { id: UID, owner: address }

/// 轉移功能。任何人都可以來 PostOffice 並發送到特定
/// 收件者的 PostBox。收件者可以從 `PostBox` 接收項目。
public fun send<T: key + store>(office: &PostOffice, parcel: T, recipient: address) {
let postbox = derived_object::derive_address(office.id.to_inner(), recipient);
transfer::public_transfer(parcel, postbox)
}

/// 接收包裹。需要發送者是 `PostBox` 的擁有者!
public fun receive<T: key + store>(
box: &mut PostBox,
to_receive: Receiving<T>,
ctx: &TxContext
): T {
assert!(box.owner == ctx.sender());

// 從 `PostBox` 接收 `to_receive`。
let parcel = transfer::public_receive(&mut box.id, to_receive);
parcel
}

/// 如果使用者還沒有宣告他們的 `PostBox`,就建立它。
/// 注意:這不是轉移資產的要求!
/// 甚至可以將包裹發送到未註冊的郵箱,詳見 `send` 實現。
public fun register_address(office: &mut PostOffice, ctx: &mut TxContext) {
transfer::share_object(PostBox {
id: derived_object::claim(&mut office.id, ctx.sender()),
owner: ctx.sender()
})
}

// 在模組發佈時建立一個 PostOffice。
fun init(ctx: &mut TxContext) {
transfer::share_object(PostOffice { id: object::new(ctx) });
}

使用場景

轉移至物件是一項強大的功能,它允許物件充當其他物件的擁有者。使用它的原因之一是可以在接收時執行額外的授權,例如上述範例中的 PostOffice 可以收取接收費用。

  • 允許並行執行對多個物件的轉移,而無需在交易中引用它們;
  • 父物件也可以被轉移,充當容器;
  • 分類似於郵政信箱的應用程式,使用者只有在啟動帳戶後才能獲得資產;
  • 帳戶抽象 (Account Abstraction) 類的應用程式,其中一個物件在模擬一個帳戶。

相關連結