Set up the Sui development environment

Move-based programming on Sui relies on a unique resource model where assets are strictly typed and cannot be accidentally duplicated or dropped. This design provides a higher level of security for smart contracts compared to traditional EVM-style languages. To start building, you need a local environment capable of compiling and testing this code.

Follow these steps to install the Sui CLI, initialize a new project, and verify your setup.

move-based programming
1
Install the Sui CLI

The Sui CLI is the primary tool for interacting with the Sui blockchain. Install it using the official installer script. This command downloads the latest stable version of the CLI and adds it to your system path.

Shell
Shell
curl https://get.sui.io -sSfL | sh

After installation, verify the setup by checking the version. This ensures the binary is accessible and correctly installed.

Shell
Shell
sui --version
move-based programming
2
Install the Sui Move Compiler

Move code requires a specific compiler to translate into bytecode that the Sui Virtual Machine can execute. Install the Sui Move compiler using Cargo, Rust's package manager. If you do not have Rust installed, you can get it from rustup.rs.

Shell
Shell
cargo install --git https://github.com/MystenLabs/sui.git --branch devnet sui-move

This step ensures you have the latest compiler features compatible with the current Sui network version.

3
Initialize a new Move project

Create a new directory for your project and initialize it as a Move package. This command sets up the standard directory structure, including the sources folder where your Move modules will live.

Shell
Shell
sui move new my_first_move_app
cd my_first_move_app

The sources directory is where you will write your Move code. The tests directory is reserved for integration tests.

4
Verify the installation

Compile the project to ensure there are no syntax errors and that the environment is correctly configured. This command checks the Move code and generates the bytecode.

Shell
Shell
sui move build

If the build succeeds, you will see a success message. If it fails, review the error output to fix any syntax or type issues. This step confirms your local environment is ready for development.

Write your first resource-based contract

Move-based programming differs from other smart contract languages because it treats digital assets as first-class citizens. In standard Solidity, an ERC-20 token is just a number in a mapping that can be copied or deleted. In Move, an asset is a resource. This means the language enforces two strict rules by default: a resource cannot be copied, and it cannot be dropped. If you try to duplicate a Coin or let a function end without returning it, the compiler rejects the code. This prevents accidental inflation and lost funds at the language level.

To see this in action, we will define a simple Treasury resource. This struct holds a balance and a name. Because it is marked as key, it can be stored in the blockchain's global storage. We also define a deposit function to add funds. Notice that the function takes &mut self. This mutable reference allows the function to modify the state of the specific treasury instance being addressed, ensuring that only the owner or authorized party can change the balance.

MOVE
module my_package::treasury {
    use std::string;
    use sui::object::{Self, UID};
    use sui::transfer;
    use sui::tx_context::{Self, TxContext};

    /// A resource representing a treasury with a name and balance
    struct Treasury has key, store {
        id: UID,
        name: string::String,
        balance: u64
    }

    /// Create a new treasury
    public fun new(name: string::String, ctx: &mut TxContext): Treasury {
        Treasury {
            id: object::new(ctx),
            name,
            balance: 0
        }
    }

    /// Deposit funds into the treasury
    public fun deposit(treasury: &mut Treasury, amount: u64) {
        treasury.balance = treasury.balance + amount;
    }

    /// Transfer the treasury to another address
    public fun transfer(treasury: Treasury, recipient: address, ctx: &mut TxContext) {
        transfer::transfer(treasury, recipient);
    }
}

The transfer function demonstrates how ownership moves. In Move, you don't send tokens to an address; you send the entire Treasury object. The transfer::transfer function moves the resource from the sender's context to the recipient's. Once transferred, the original sender no longer has access to that specific Treasury instance. This explicit ownership model makes it impossible to accidentally spend someone else's funds or create duplicate assets, which is the core advantage of move-based programming for secure asset management.

Test logic with the Sui Move framework

Before deploying to mainnet, you must verify that your resource logic holds up under test conditions. The Move programming language enforces scarcity by default, meaning structs representing assets cannot be accidentally duplicated or dropped. However, complex transaction flows can still introduce subtle bugs in ownership transfers or access control.

Testing ensures that your smart contracts behave exactly as intended when handling these unique resource constraints. You will use the Sui Move framework to simulate on-chain interactions locally, catching errors before they become expensive mistakes.

move-based programming
1
Set up the local testing environment

Install the Sui CLI and initialize a new project if you haven't already. This environment allows you to compile and run unit tests against your Move modules without connecting to a live network. Ensure your local Sui node is running to simulate transaction execution accurately.

2
Write unit tests for resource creation

Focus on the init function and any entry functions that create new resources. Write tests that verify the resource is created with the correct initial state and that it is properly tagged as a resource struct. Check that the creator receives the object and that no other account can access it prematurely.

move-based programming
3
Simulate ownership transfers

Test the transfer logic by sending resources between different test accounts. Verify that the sender loses ownership and the receiver gains it. Move's linear type system should prevent any attempt to duplicate the resource during this process; your tests should confirm that such attempts fail compilation or execution.

4
Verify destruction and burn logic

Write tests for functions that destroy or burn resources. Ensure that once a resource is destroyed, it cannot be accessed again. This is critical for preventing value leaks in your protocol. Confirm that the destruction is irreversible and that any associated events are emitted correctly.

5
Run the full test suite

Execute sui move test to run all your unit tests. Review the output for any failures or warnings. If all tests pass, you have confidence that your resource logic is sound. If any test fails, debug the specific function and re-run until the suite is clean.

Deploy and verify on the Sui network

Publishing your Move module moves your code from a local environment onto the Sui blockchain. This process creates a new package that other accounts can import and use. Because Move enforces strict resource safety, your assets are protected by default, ensuring that logic behaves predictably once live.

Publish the module

Use the Sui CLI to compile and publish your module. This command uploads the bytecode to the network and creates a package object. The transaction includes the module source and the necessary gas payment. You can specify a package name to make imports cleaner for future developers.

Shell
sui client publish --gas-budget 100000000

The CLI returns a transaction digest and confirms the package ID. Save this ID; you will need it to call functions from your module. The package is now immutable and available for any Sui account to interact with.

Verify the bytecode

Verification ensures that the on-chain code matches your source files. While Sui does not have a single centralized block explorer for source code like Etherscan, you can verify integrity by comparing the published bytecode hash with your local build. This step is critical for security audits and public transparency.

You can view the transaction details on a Sui explorer to confirm the package ID and module names. Cross-reference this with your Move.toml configuration. If the bytecode matches your local compilation, your module is verified and ready for integration.

Checklist for move-based programming

Before deploying your smart contract on Sui, use this checklist to verify your implementation. Move’s resource model prevents accidental duplication or loss of assets, but you must enforce these rules explicitly in your code.

Common questions about Move

Developers often ask how Move differs from other smart contract languages. The core distinction lies in its handling of digital assets through the resource model, which enforces strict scarcity and access control.