Ownership, Moves & Copies

Every value has exactly one owner — a local variable, a struct field, or a storage location.

17.1 Move semantics

Every value has exactly one owner — a local variable, a struct field, or a storage location. Assigning or passing a value moves it unless the type has copy:

public struct Ticket has store { seat: u64 }   // no copy, no drop

fun demo(t: Ticket): Ticket {
    let a = t;          // move
    // let b = t;       // ERROR: t was moved
    a                   // move out to caller
}

17.2 Explicit copy and move

The compiler infers copy or move for local variable uses; explicit annotations are rarely needed.

let x = 5;
let y = copy x;     // explicit copy (x still usable)
let z = move x;     // explicit move (x no longer usable)
let w = y;          // implicit: copied or moved, inferred by the compiler

17.3 Consuming resources

A value without drop must be consumed. Ways to consume:

Pass it by value to a function.

Store it in a struct / storage (move_to, transfer::*, dynamic field).

Destructure it inside its module (let Ticket { seat: _ } = t;).

public fun burn(t: Ticket) {
    let Ticket { seat: _ } = t;   // only possible inside the defining module
}

17.4 Ownership vs storage ownership

Language-level ownership: which variable holds the value right now.

On-chain ownership: Sui objects have an owner (address, object, shared, immutable); Aptos resources live under an address. A resource leaving a function must end up in one of these places — Move guarantees no asset is lost or duplicated in between.