Skip to main content

共享对象

共享对象是使用 sui::transfer::share_object 函数共享的对象,可以被所有人访问。与拥有的对象不同,任何人都可以在网络上访问共享对象。这种类型的对象的扩展功能和可访问性需要额外的努力来确保访问安全,如果需要的话。

共享对象需要 key 能力。

示例

以下示例创建了一个销售数字甜甜圈的商店。每个人都需要访问商店才能从中购买甜甜圈,因此示例使用 sui::transfer::share_object 创建商店作为共享对象。

module examples::donuts {
use sui::transfer;
use sui::sui::SUI;
use sui::coin::{Self, Coin};
use sui::object::{Self, UID};
use sui::balance::{Self, Balance};
use sui::tx_context::{Self, TxContext};

/// For when Coin balance is too low.
const ENotEnough: u64 = 0;

/// Capability that grants an owner the right to collect profits.
struct ShopOwnerCap has key { id: UID }

/// A purchasable Donut. For simplicity's sake we ignore implementation.
struct Donut has key { id: UID }

/// A shared object. `key` ability is required.
struct DonutShop has key {
id: UID,
price: u64,
balance: Balance<SUI>
}

/// Init function is often ideal place for initializing
/// a shared object as it is called only once.
fun init(ctx: &mut TxContext) {
transfer::transfer(ShopOwnerCap {
id: object::new(ctx)
}, tx_context::sender(ctx));

// Share the object to make it accessible to everyone!
transfer::share_object(DonutShop {
id: object::new(ctx),
price: 1000,
balance: balance::zero()
})
}

/// Entry function available to everyone who owns a Coin.
public fun buy_donut(
shop: &mut DonutShop, payment: &mut Coin<SUI>, ctx: &mut TxContext
) {
assert!(coin::value(payment) >= shop.price, ENotEnough);

// Take amount = `shop.price` from Coin<SUI>
let coin_balance = coin::balance_mut(payment);
let paid = balance::split(coin_balance, shop.price);

// Put the coin to the Shop's balance
balance::join(&mut shop.balance, paid);

transfer::transfer(Donut {
id: object::new(ctx)
}, tx_context::sender(ctx))
}

/// Consume donut and get nothing...
public fun eat_donut(d: Donut) {
let Donut { id } = d;
object::delete(id);
}

/// Take coin from `DonutShop` and transfer it to tx sender.
/// Requires authorization with `ShopOwnerCap`.
public fun collect_profits(
_: &ShopOwnerCap, shop: &mut DonutShop, ctx: &mut TxContext
) {
let amount = balance::value(&shop.balance);
let profits = coin::take(&mut shop.balance, amount, ctx);

transfer::public_transfer(profits, tx_context::sender(ctx))
}
}