Set up the Move development environment
To start building with Move in 2026, you need to install the official command-line interface (CLI) and generate a starter project. This setup gives you the compiler, test runner, and package manager required to compile and deploy smart contracts on the Sui network.
The process is straightforward and mirrors standard Node.js or Rust workflows. Once installed, you can initialize a project structure that separates your Move source code from the build artifacts.
Define resources with the move keyword
In Move-based programming, data isn't just a blob of bytes; it's a first-class citizen with strict ownership rules. The move keyword is the tool you use to declare these special data structures, known as resources. Unlike regular structs, which can be copied or dropped at will, a resource is unique, non-duplicable, and must be explicitly moved or destroyed. This prevents common smart contract bugs like double-spending or accidental data loss.
Think of a resource like a physical key. You can hold it, pass it to someone else, or throw it away, but you can't clone it while you still have the original. If you try to use the key twice without moving it first, the compiler stops you. This enforcement happens at compile time, giving you a safety net that traditional smart contract languages often lack.
To declare a resource, you add the move keyword before the struct definition. This tells the Move compiler that instances of this struct are unique and must follow resource semantics. Here is how that looks in practice compared to a standard data structure.
Notice the has key capability in the resource examples. This is a requirement for any resource in Move, indicating that the struct can be stored inside other resources or the global storage. Without it, the compiler will reject the definition. The move keyword is the primary signal that you are building secure, predictable state for your blockchain application.
Write a programmable transaction block
A programmable transaction block (PTB) lets you bundle multiple operations into a single atomic unit. Instead of sending separate transactions for each step—like transferring tokens, updating a ledger, and minting an NFT—you group them together. This ensures that either every step succeeds or the entire block fails, preventing partial states.
In Move, PTBs are the standard way to handle complex logic. They are efficient because they share a single execution context, reducing gas costs and network congestion. You write the logic in Move, and the block executes it as one cohesive action.
Set up the transaction builder
Start by initializing a new PTB object. This object acts as a container for your sequence of instructions. You will add operations to it one by one, defining the order of execution.
use std::string;
use sui::coin;
use sui::tx_context::TxContext;
public fun create_ptb(ctx: &mut TxContext) {
let ptb = ptb::new(ctx);
// Add operations here
}
Add operations to the block
Once the PTB is initialized, you can chain operations. For example, you might first transfer some SUI tokens to a recipient, then use those tokens to mint a new resource. Each operation is added to the block in the order you write it.
// Transfer 100 SUI to recipient
ptb::add_transfer(&mut ptb, recipient, 100);
// Mint a new item
let item = mint_item(ptb::address(&ptb));
ptb::add_publish(&mut ptb, item);
Execute the block
Finally, you commit the PTB. The blockchain executes all added operations in sequence. If any operation fails, the entire block is rolled back, ensuring consistency. This atomicity is critical for maintaining data integrity in complex decentralized applications.
// Execute the block
ptb::execute(&mut ptb);
By using PTBs, you simplify your smart contract logic and improve performance. This approach is central to building efficient applications in Move-based programming 2026.
Verify security with static analysis
Before you deploy, use Move’s built-in static analysis tools to catch resource leaks or misuse. Think of this step as a spell-checker for your smart contract logic. It scans your code for structural issues that could lead to lost funds or broken state, long before a malicious actor sees it.
Run the Move Prover
The Move Prover is your primary defense against logical errors. It verifies that your code adheres to specific safety properties, such as ensuring that resources are never duplicated or destroyed improperly.
- Add assertions to your code where safety is critical. For example, assert that a token balance cannot be negative.
- Run
move checkin your terminal. This command compiles your code and runs the prover against your assertions. - Review the output. If the prover succeeds, you have a mathematical guarantee that the property holds. If it fails, the tool provides a counterexample showing exactly how the violation occurs.
Check for Resource Leaks
Move’s type system is designed to make resource leaks nearly impossible, but static analysis catches subtle misuses. Ensure that every resource created in a function is either returned or consumed within the same execution path.
Use the move check command to scan for unused resources. If the analyzer flags a resource that is created but never moved or destroyed, it means that resource is effectively lost to the blockchain state. This is a common mistake for developers new to Move’s ownership model.
By integrating these tools into your daily workflow, you shift security from an afterthought to a foundational step. Catching these issues early saves time and ensures your contract is robust from day one.
Common Move Programming Mistakes
Even with Move’s strong type system, developers can still introduce bugs that lead to lost value or security vulnerabilities. The most frequent errors involve mishandling resources and ignoring access control rules. Understanding these pitfalls early prevents costly audits and runtime failures.
Dropping Resources
Move resources are first-class values that cannot be implicitly discarded. If you forget to store, transfer, or explicitly destroy a resource, the compiler will reject the code. However, accidental drops can still occur if you lose the handle to a resource before using it.
fun example() {
let my_coin = init_coin();
// Error: my_coin is dropped here without being used or destroyed
}
Always ensure every resource is accounted for. Use the destroy function only when you intend to burn the resource, or store it in a struct that persists.
Violating Access Control
Move’s access control rules restrict who can read or write to private fields. A common mistake is trying to access a private field from outside its module. This breaks encapsulation and prevents the module from managing its state securely.
module MyModule {
struct MyStruct has key {
value: u64
}
fun create() {
MyStruct { value: 10 }
}
// Error: cannot access private field `value` here
fun read_value(s: &MyStruct): u64 {
s.value
}
}
Pre-Deployment Checklist
Before deploying your Move contract, verify the following:
-
All resources are either stored, transferred, or explicitly destroyed.
-
No private fields are accessed from outside their defining module.
-
Event emissions are used for all state changes.
-
Tests cover edge cases for resource lifecycles.

Watch a Move language demo
See how Move code executes in a real environment. This video by Sam Blackshear, a core contributor to the Move language, provides a practical walkthrough of Move's resource semantics and smart contract structure. It is the best visual reference for understanding how Move handles ownership and security in 2026.
Frequently asked questions about Move
Here are answers to common questions about building with Move-based programming in 2026.

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