# Shared Objects

*[Documentation index](/llms.txt) · [Full index](/llms-full.txt)*

A shared object is a public, mutable object that is accessible to anyone on the network. They are designed such that multiple users or smart contracts can interact with the same object concurrently.

## Create shared objects

Use the [`sui::transfer::share_object`](/references/framework/sui_sui/transfer#sui_transfer_share_object) function to create a shared object, making it publicly accessible on the network. Extended functionality and accessibility of shared objects requires additional effort by securing access, if needed.

Shared objects require the `key` ability.

```move
public struct Donut has key { id: UID }

fun init(ctx: &mut TxContext) {
    transfer::transfer(ShopOwnerCap {
        id: object::new(ctx)
    }, ctx.sender());

    transfer::share_object(DonutShop {
        id: object::new(ctx),
        price: 1000,
        balance: balance::zero()
    })
```

## When to use shared objects

Shared objects are ideal for things like marketplaces, games, or other scenarios where global state needs to be accessed or modified by multiple parties.

## Interact with shared objects

The following example creates a shop to sell digital donuts. Everyone needs access to the shop to purchase donuts from it, so the example creates the shop as a shared object using [`sui::transfer::share_object`](/references/framework/sui_sui/transfer#sui_transfer_share_object).

```move
module examples::donuts;

use sui::sui::SUI;
use sui::coin::{Self, Coin};
use sui::balance::{Self, Balance};

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

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

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

/// A shared object. `key` ability is required.
public 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)
    }, ctx.sender());

    // 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 paid = payment.balance_mut.split(shop.price);

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

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

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

/// 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 = shop.balance.value();
    let profits = shop.balance.split(amount).into_coin(ctx);

    transfer::public_transfer(profits, ctx.sender())
}
```
