suideveloper
All questions
Sui Move

How is Sui Move different from Aptos Move and core Move?

November 4, 2026

The biggest difference is storage. Core Move (from Diem) and Aptos Move keep data as resources under account addresses and use global storage operators such as move_to and borrow_global. Sui Move removes global storage entirely: data lives in objects with an id: UID, every transaction lists the objects it uses, and functions receive those objects as arguments. The three share the type system, abilities and modules, but their storage models, frameworks and language editions have diverged, so contracts don't port between them without a rewrite.

Storage: accounts vs objects

Core Move and Aptos. A struct with key is a resource that you publish under an address. A &signer authorizes writes:

Move
// Aptos-style
struct Counter has key { value: u64 }

public entry fun create(account: &signer) {
    move_to(account, Counter { value: 0 });
}

public entry fun increment(addr: address) acquires Counter {
    let c = borrow_global_mut<Counter>(addr);
    c.value = c.value + 1;
}

Aptos has since added its own object model. Objects get their own address, and you place resources in them with move_to using a signer generated from a ConstructorRef. The design is still built on global storage.

Sui. key means "this is an object", the first field must be id: UID, and the global storage operators don't exist. You transfer, share or freeze the object, and later receive it as a parameter:

Move
// Sui Move 2024
public struct Counter has key { id: UID, value: u64 }

public fun create(ctx: &mut TxContext) {
    transfer::share_object(Counter { id: object::new(ctx), value: 0 })
}

public fun increment(c: &mut Counter) {
    c.value = c.value + 1;
}

Because transactions declare their inputs up front, Sui can run transactions that touch different objects in parallel, and transactions that only use owned objects skip consensus ordering.

Other differences

Core Move (Diem) Aptos Move Sui Move
Unit of storage Resource under an account Resource under an account or object address Object with a UID
Storage access move_to, borrow_global, exists Same, plus acquires (inference optional since Move 2.2) Objects passed as arguments; no global storage
Address size 16 bytes 32 bytes 32 bytes
Authorization &signer &signer Object ownership, capability objects, ctx.sender()
Transfers Recipient must accept a resource Framework object::transfer and coin/FA APIs transfer::transfer / public_transfer to any address
Module setup — init_module init(ctx), optionally with a one-time witness
Language versions Original Move Move 2.0–2.4 Move 2024 edition
Dynamic storage — Tables Dynamic fields, Table, Bag

Rows for Aptos are summarized from Aptos' own docs, and Aptos changes independently, so check its documentation for current details.

Language editions diverged

Both projects added similar features under different names and syntax. Aptos' Move 2 releases added enums, receiver-style calls (v.len()), compound assignment and, in 2.3, signed integers. Sui's Move 2024 edition added public struct, let mut, method syntax, enums, public(package) and macros, along with Sui-specific rules. Code written for one compiler often fails to compile on the other even when it looks similar. See What changed in the Move 2024 edition?.

Sui-specific concepts with no direct equivalent

  • One-time witness and the Publisher object, for proving package authority.
  • Dynamic fields and dynamic object fields, attached to an object's UID.
  • Owned, shared, immutable and object-owned objects; see What kinds of object ownership does Sui have?.
  • Programmable transaction blocks, which chain calls on the client instead of writing script modules.

Porting advice

Don't translate line by line. Start from the data model: work out which resources become owned objects, which become shared objects, and which capabilities replace signer checks. Then rewrite the entry points to take those objects as arguments.

Sources

More on sui move