Why Move matters for 2026

Move is the programming language powering Sui, designed specifically to handle high-stakes financial logic with a security model that prevents common blockchain vulnerabilities. Unlike general-purpose smart contract languages, Move treats digital assets as "resources"—objects that cannot be copied or discarded by accident. This fundamental shift ensures that value moves exactly as intended, making it the standard for serious DeFi applications in 2026.

The second pillar of Move’s value is parallel execution. Traditional blockchains process transactions sequentially, creating bottlenecks during high demand. Move’s object-centric model allows the Sui network to process independent transactions simultaneously. This means faster finality and lower costs, critical factors for traders and developers building scalable financial infrastructure.

By 2026, Move-powered networks have matured from experimental prototypes into robust ecosystems with clear design priorities: security, speed, and composability. For developers, this means choosing a language where correctness is enforced by the compiler, not just by post-deployment audits. As noted in official documentation, Move enables "safer logic, rich composability, and scalable design," positioning it as the backbone of the next generation of decentralized finance.

"Move is a secure and efficient smart contract programming language designed to enable safer logic, rich composability, and scalable design." — Sui Documentation

Set up your Sui development environment

Move-Based Programming works best as a sequence, not a scramble through settings. Do the minimum first: confirm compatibility, connect the core hardware, update only when needed, and test the result before adding optional features. That order keeps the task understandable and makes failures easier to isolate.

move-based programming
1
Confirm prerequisites
Check compatibility, account access, firmware, network, and physical access before changing the Move-Based Programming setup.
move-based programming
2
Make one change at a time
Apply the setup steps in order so any connection, pairing, or permission failure is easy to isolate.
3
Verify the result
Test the final state from the app and from the physical device before adding automations or optional settings.

Write your first Move smart contract

Start by defining a simple asset, such as a token or collectible, to understand Move’s Object Data Model (ODM). Unlike other blockchains where tokens are just balances in a global ledger, Move treats assets as first-class objects. This means every token is a distinct entity with its own unique identifier, allowing for richer logic and composability.

Move’s resource-oriented type system is the foundation of this security. Resources are types that cannot be copied or dropped implicitly. If you try to compile code that loses a resource or duplicates it without explicit permission, the Move compiler rejects it. This prevents common vulnerabilities like inflation bugs or accidental loss of assets.

Define the Resource

In Move, you define an asset using the struct keyword with the key and store abilities. The key ability makes the struct unique within an account, and store allows it to be placed inside other containers (like another object).

MOVE
module my_package::my_token {
    use sui::object::{Self, UID};
    use std::string;

    struct MyToken has key, store {
        id: UID,
        name: string::String,
        value: u64,
    }
}

Here, MyToken is a resource. The id field is inherited from UID and ensures every instance is unique. The name and value fields hold the data. Because MyToken has the store ability, it can be moved around the blockchain as a complete object.

Initialize the Object

To create an instance of this asset, you use the object::new function. This function takes the current context and returns a new UID, which you pass into your struct constructor.

MOVE
public fun mint(ctx: &mut TxContext) {
    let token = MyToken {
        id: object::new(ctx),
        name: string::utf8(b"My Coin"),
        value: 100,
    };
    // The token is now an object on-chain
}

This code creates a new MyToken object with a value of 100. The object is now part of the Sui state tree. You can transfer it, modify it, or destroy it using Move’s object management functions.

Transfer and Modify

Moving an object is straightforward. You pass the object ID and the recipient address to the transfer::transfer function. This atomic operation ensures the asset leaves one account and arrives in another without intermediate states.

MOVE
public fun transfer(token: MyToken, recipient: address, ctx: &mut TxContext) {
    transfer::transfer(token, recipient);
}

Modifying an object requires "breaking" it apart, changing the data, and repackaging it. This ensures that any changes are explicit and verifiable. For example, to increase the value:

MOVE
public fun add_value(mut token: MyToken, amount: u64, ctx: &mut TxContext) {
    token.value = token.value + amount;
    transfer::transfer(token, tx_context::sender(ctx));
}

By treating assets as objects with clear lifecycles, Move provides a safer and more flexible framework for building smart contracts. This model reduces the attack surface for common blockchain exploits and makes the behavior of your code more predictable.

move-based programming

Test with Programmable Transaction Blocks

Programmable Transaction Blocks (PTBs) allow you to bundle multiple operations into a single atomic unit. Instead of sending separate transactions that might fail or leave the state inconsistent, you define a sequence of actions that execute together. If any part fails, the entire block reverts, ensuring your Sui account remains in a valid state. This approach is essential for complex logic like atomic swaps, multi-step token transfers, or nested contract calls.

1. Define the Transaction Structure

Start by importing the necessary Move modules and defining the entry points for your transaction. You need to specify the inputs, such as object IDs, coin types, and addresses. Use the Sui TypeScript SDK to construct the PTB object, which acts as a container for your sequence of commands. This structure ensures that all dependencies are resolved before execution begins.

2. Add Object Dependencies

Explicitly declare the objects your transaction will read or modify. In Move, you must pass object references as arguments to ensure the Move VM can verify ownership and permissions. Use getDynamicFieldObject or direct object IDs to reference existing assets. This step prevents runtime errors caused by missing or inaccessible resources during execution.

3. Sequence the Operations

Order your operations logically within the PTB. Common patterns include transferring objects, calling smart contract functions, and splitting or merging coins. Each operation depends on the output of the previous one. For example, you might split a large coin into smaller denominations before sending them to multiple recipients. Ensure the data flow between steps is clear and type-safe.

4. Simulate the Transaction

Before signing and broadcasting, simulate the transaction to verify its behavior. Use the devInspectTransactionBlock method to preview the results without committing changes to the blockchain. This allows you to catch logic errors, insufficient balance issues, or permission violations early. Simulation is a critical safety net for complex PTBs.

5. Sign and Execute

Once simulation confirms the transaction works as intended, sign it with the appropriate private key and execute it. The Sui network will process all operations atomically. If any step fails, the entire block is rolled back. Monitor the transaction digest to confirm successful completion or debug any issues that arise during execution.

Deploy to the Sui Devnet

Before pushing code to mainnet, you must validate your Move-based smart contracts on the Sui Devnet. This test environment mirrors mainnet’s finality and consensus mechanisms, allowing you to catch resource leaks, access control errors, and gas inefficiencies without risking real capital.

1
Configure your Sui CLI for Devnet

Install the latest version of the Sui CLI and switch your network context to devnet. Verify connectivity by running sui client envs. This ensures your local environment is talking to the correct testnet endpoints rather than the simulation or mainnet networks.

2
Build and publish the package

Compile your Move sources with sui move build. Once compiled successfully, publish the package using sui client publish --gas-budget 50000000. This transaction assigns a unique Object ID to your contract, which you will need for all subsequent interactions. Note the published package ID in the transaction output.

3
Run unit tests and PTB simulations

Execute your Move unit tests locally first. Then, simulate the deployment transaction using sui client dry-run to verify the state changes. Pay close attention to the gas_used field; if it exceeds your budget, refactor your code for efficiency. A successful dry-run confirms your Move logic executes as intended without reverting.

4
Verify object ownership and access control

Interact with your deployed module using sui client call. Test all entry functions with different signers to ensure only authorized addresses can trigger sensitive actions. Check that any shared objects are correctly configured with the shared flag and initial ownership parameters to prevent unauthorized transfers.

5
Review gas limits and finalize

After successful devnet deployment, review the on-chain transaction history. Ensure that the gas costs are predictable and do not spike unexpectedly under load. This step is critical for mainnet readiness, as gas estimation on mainnet is stricter and more costly.

Check your work against this pre-deployment checklist:

  • Unit tests passed with 100% coverage on critical modules
  • PTB (Programmable Transaction Block) simulation succeeded without reverts
  • Gas limits reviewed and optimized for mainnet constraints
  • Ownership rules verified for all shared objects

Common Move programming mistakes

Even with Move’s type system, logic errors slip through. The most frequent issues involve resource management and access control. Treat resources like physical assets: if you don’t hand them off or destroy them, they stay locked in your code.

Leaking Resources

Move requires every resource to be explicitly destroyed or stored. Forgetting to destroy a resource or failing to transfer it causes compilation errors or, worse, silent logic bugs where assets become inaccessible. Always trace your resource’s lifecycle from creation to final destination.

Weak Access Control

Using public instead of public(script) or omitting access modifiers can expose internal state to unintended callers. Audit every function’s visibility. If a function shouldn’t be callable by external scripts, remove the script access or restrict it to internal module use.

Ignoring Type Safety

Move’s strength is its strict typing. Bypassing it with unsafe casts or ignoring type constraints leads to runtime failures. Let the compiler guide you; if you need to bypass a check, you likely have a design flaw.

Forgetting to Transfer Ownership

Resources are unique. You cannot copy them. If you try to duplicate a resource without proper transfer mechanisms, the code fails. Ensure every resource move is explicit and accounted for in your transaction flow.