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.
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.
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.
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.
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.


No comments yet. Be the first to share your thoughts!