suideveloper
All questions
Objects

What kinds of object ownership does Sui have?

November 8, 2026

Sui has five kinds of object ownership: address-owned, shared, immutable, wrapped, and party (also called consensus-address owned). Ownership decides who can use an object in a transaction. It also decides whether the object is versioned on the fastpath, with no consensus ordering, or through consensus. Objects can also be owned by another object, through dynamic fields or transfer to object.

The five types

Ownership Who can use it Sequenced by Created with
Address-owned Only the owning address Fastpath transfer::transfer / public_transfer
Shared Anyone (your Move code must check permissions) Consensus transfer::share_object / public_share_object
Immutable Anyone, read-only Not versioned after freezing transfer::freeze_object / public_freeze_object
Wrapped Only through the object that contains it Depends on the wrapper Store it in another object's field
Party One address Consensus transfer::party_transfer / public_party_transfer

The public_* variants need the object's type to have store and can be called from any module. The plain variants work only inside the module that defines the type, which is how you enforce custom transfer rules.

Address-owned

The owner is a 32-byte address: either an account address or an object ID. Only transactions signed by that address can use the object. The sender names the exact version, so there's no contention and latency is lowest. Coins, NFTs and capability objects such as AdminCap are typically address-owned. If the owner is an object ID, the object is received through transfer to object.

Shared

Anyone can include a shared object in a transaction, and many users can work on the same state. Pools, order books, marketplaces and game boards are shared objects. Consensus orders the writes, and the runtime does no access control for you. Sharing is permanent, and an object can only be shared in the transaction that creates it.

Immutable

Frozen objects can't be changed, transferred or deleted, and they have no owner. Anyone can read them concurrently. Published packages are immutable objects. Freezing can't be undone.

Wrapped

An object stored as a field of another object (directly, in an Option, or in a vector) is wrapped. It keeps its ID, but you can't pass it as a transaction input or look it up by ID. You reach it only through its wrapper. Unwrapping it makes it accessible by ID again.

Party

A party object belongs to a single address, like an owned object, but consensus sequences it, like a shared object. That lets you have several transactions in flight against it. You build a party with sui::party::single_owner(addr). Multi-member parties are on the roadmap but aren't supported yet. A party Coin<SUI> can't pay for gas. APIs show this owner as ConsensusAddressOwner.

Example

Move
module example::ownership;

public struct Config has key, store { id: UID, fee_bps: u64 }
public struct AdminCap has key { id: UID }
public struct Pool has key { id: UID, total: u64 }

fun init(ctx: &mut TxContext) {
    // Address-owned: only the publisher can use it.
    transfer::transfer(AdminCap { id: object::new(ctx) }, ctx.sender());
    // Shared: anyone can pass it to `deposit`.
    transfer::share_object(Pool { id: object::new(ctx), total: 0 });
    // Immutable: readable by everyone, never changes.
    transfer::public_freeze_object(Config { id: object::new(ctx), fee_bps: 30 });
}

public fun deposit(pool: &mut Pool, amount: u64) {
    pool.total = pool.total + amount;
}

Checking an object's owner

sui client object <ID> prints the Owner field. In TypeScript, client.getObject({ objectId }) returns object.owner with a $kind of AddressOwner, ObjectOwner, Shared, Immutable or ConsensusAddressOwner. Wrapped objects don't appear at their ID at all. Children held in dynamic fields show an ObjectOwner owner (see What are dynamic fields on Sui?).

Sources

More on objects