What move-based programming solves

Move is a Rust-based language designed for safe asset management on blockchains like Sui and Aptos. It prevents common vulnerabilities by treating digital assets as unique resources.

Move-based programming addresses the fundamental security gaps found in traditional smart contract languages. While older systems often treat digital assets as simple numbers that can be duplicated or lost, Move treats them as unique, scarce resources. This shift in perspective is critical for building secure applications where ownership and value must be strictly enforced.

Originally developed by Meta for the Diem project, Move is built on Rust, inheriting its memory safety guarantees while adding blockchain-specific features. The language enforces scarcity by default: structs representing assets cannot be accidentally duplicated or dropped. This means that once a token or NFT is created, it cannot simply appear out of thin air or vanish without a trace, preventing entire classes of financial exploits common in other ecosystems.

This resource-oriented model allows developers to write programs that flexibly manage and transfer assets with a higher degree of confidence. By ensuring that access control and scarcity are baked into the language itself, Move reduces the cognitive load on developers and minimizes the risk of human error. For more details on the language's design principles, see The Move Book.

The result is a programming environment where security is not an afterthought but a structural necessity. This approach enables safer logic, rich composability, and scalable design, making it the foundation for next-generation blockchain applications on networks like Sui and Aptos.

Set up the move-based programming environment

Move is a strongly typed, resource-oriented language designed for smart contracts on Sui and Aptos. It prioritizes safety by treating assets as unique resources. To start move-based programming, you need the official Move CLI and a supported blockchain network.

The following steps guide you through installing the CLI and initializing your first project.

move-based programming
1
Install the Move CLI

The Move CLI is the primary tool for compiling and testing Move smart contracts. It is available as a Rust crate, so you must have Rust installed on your system first. Run the following command to install the latest stable version:

Shell
Shell
cargo install --git https://github.com/move-language/move move-cli

Verify the installation by checking the version. This ensures the tool is correctly linked to your system path.

Shell
Shell
move --version
Move-Based Programming in
2
Choose your target chain

Move runs on multiple blockchains, primarily Sui and Aptos. Each chain uses a slightly different version of the Move language and has its own package manager. You must choose one to proceed. Sui uses the sui CLI, while Aptos uses the aptos CLI. For this guide, we will focus on the general Move project structure, which is compatible with both once configured.

Move-Based Programming in
3
Initialize a new project

Create a new directory for your smart contract. Move projects follow a standard layout with a sources folder for code and a Move.toml configuration file. Use the CLI to scaffold this structure automatically:

Shell
Shell
move init my_first_move_project

This command generates the necessary directory structure and a default Move.toml file. The Move.toml file defines your package dependencies and the Move version you are targeting.

Move-Based Programming in
4
Write your first module

Inside the sources directory, create a new file named my_first_module.move. This file will contain your first smart contract. Move code is organized into modules, which are units of code that can be published to the blockchain.

MOVE
MOVE
module my_first_move_project::my_first_module {
    use std::string;

    public fun hello(): String {
        string::utf8(b"Hello, Move!")
    }
}

This simple module defines a function that returns a string. It demonstrates the basic syntax and structure of Move code.

5
Compile and test the code

Before deploying, compile your code to check for syntax errors. Use the move check command to verify the code compiles correctly:

Shell
Shell
move check

If the code compiles without errors, you can run unit tests. Move includes a built-in testing framework. Create a test file in the tests directory and use the move test command to execute it. This ensures your smart contract behaves as expected before it goes live.

Write your first resource contract

To start with move-based programming, you need to understand how Move handles assets differently than other smart contract languages. In Ethereum-based EVM chains, copying a token balance is a simple arithmetic operation. Move enforces strict ownership rules: an asset cannot be duplicated or discarded accidentally. This is achieved through the resource type, which acts as a unique identifier for digital objects.

Think of a resource like a physical key. You can transfer it from one person to another, but you cannot photocopy it to create two working keys. If you try to duplicate the struct representing the resource, the Move compiler will reject the code. This built-in scarcity is what makes Move secure for financial applications.

Move-Based Programming in

Define the resource struct

The first step in writing a basic smart contract is defining the data structure. In Move, you use the struct keyword, but you must also attach the key and resource abilities to the struct. The key ability allows the struct to be stored in accounts, while resource ensures it cannot be copied.

MOVE
module my_project::my_token {
    use std::string;
    use std::option;

    struct MyToken has key, resource {
        id: UID,
        balance: u64
    }
}

By adding has key, resource, you tell the Move VM that this struct is a unique asset. The UID (Unique Identifier) is a special type provided by the Move standard library that guarantees each instance of the resource is distinct. Without these abilities, the struct would just be regular data that could be copied freely.

Implement the minting function

Once the resource is defined, you need a way to create it. In Move, you cannot simply instantiate a struct; you must use the create_uid function to generate a new unique identifier. This process ties the resource to the caller's account.

MOVE
public fun mint(ctx: &mut TxContext) {
    let token = MyToken {
        id: object::new(ctx),
        balance: 100
    };
    // Transfer to sender
    transfer::public_transfer(token, tx_context::sender(ctx));
}

The object::new(ctx) call creates the unique ID. The transfer::public_transfer function moves the resource from the contract's temporary storage into the sender's account. This explicit transfer is crucial. In Move, resources don't exist in a void; they must always be owned by an account or another resource. This prevents "orphaned" assets that no one can access.

Verify ownership and scarcity

The power of move-based programming lies in how it prevents common vulnerabilities like reentrancy or accidental duplication. Because MyToken has the resource ability, you cannot write a function that copies token.balance to create a second token. The compiler will throw an error if you try to copy a struct with the resource ability.

This safety guarantee means you don't need complex external checks to ensure an asset isn't duplicated. The language itself enforces the rules. As you build more complex contracts, you will rely on these built-in protections to secure user funds without writing extensive manual validation logic.

Avoid common move-based programming mistakes

Move’s type system is designed to enforce scarcity and ownership rules at compile time, but beginners often trip over these constraints. The language treats resources like physical objects: you cannot copy them without explicit permission, and you cannot discard them unless the code explicitly allows it. Ignoring these rules leads to compilation errors or, worse, silent logic bugs that compromise contract security.

Mishandling resource ownership

The most frequent error is treating a resource struct like a standard data type. In Move, resources are unique. If you try to pass a resource into a function that doesn’t accept it, or if you attempt to duplicate it without the copy capability, the compiler will reject the code. Think of resources as keys to a vault: you can transfer the key, but you cannot photocopy it to open two doors simultaneously.

To avoid this, always ensure your function signatures explicitly declare resource parameters. Use the @ annotation to indicate that a parameter is a resource being transferred, not just borrowed. This makes the ownership flow clear and prevents accidental duplication.

Ignoring access control modifiers

Another common pitfall is leaving functions public when they should be private. Move allows you to control who can call specific functions using public, public(script), and private modifiers. A beginner might expose an internal helper function as public, allowing anyone to call it and potentially bypass intended logic.

Always start with the most restrictive access level. Only make a function public if it is part of the contract’s intended interface. Use public(script) for entry points that users can execute directly in transactions, and keep internal logic private or public(friend) for trusted modules only.

Overlooking type safety

Move is strongly typed, but it’s easy to ignore type mismatches when dealing with complex structures. For example, passing a u64 where a u128 is expected will cause a compile-time error. While this seems obvious, it often happens when refactoring code or mixing values from different sources.

Use explicit type annotations when initializing variables, especially when dealing with numeric types. This helps the compiler catch errors early and makes your code easier to read. Remember, Move prioritizes safety over convenience, so lean into its strict typing rather than working around it.

Test and deploy your smart contract

Before sending move-based programming logic to mainnet, you must verify that resources behave exactly as intended. Move’s ownership model prevents accidental duplication, but it also requires rigorous testing to ensure assets move correctly between accounts.

Run local unit tests

Start by executing unit tests against your local Move node. This environment mimics the blockchain state without risking real assets. Focus on testing the core resource lifecycle: creation, transfer, and destruction. Use the Move CLI to run tests and check for any assertion failures or gas limit violations.

move-based programming
1
Initialize local test environment

Ensure your local Move node is running and your wallet is funded with test tokens. This provides the necessary infrastructure to simulate blockchain interactions locally.

Move-Based Programming in
2
Execute unit tests for resource logic

Run your test suite to verify that resources are created, transferred, and dropped according to Move’s scarcity rules. Look for any errors related to access control or invalid state transitions.

Move-Based Programming in
3
Deploy to a testnet

Push your compiled bytecode to a public testnet like Sui Testnet. This step validates your contract in a live, albeit non-production, network environment with real consensus mechanics.

Verify on testnet

After deployment, interact with the contract on the testnet using a testnet wallet. Confirm that the contract ID is correct and that functions execute as expected. This step catches network-specific issues that local tests might miss.

  • Run unit tests for all resource paths
  • Verify resource ownership and access control
  • Check gas limits for complex transactions
  • Confirm network compatibility and contract ID

Final security check

Before mainnet launch, consider a formal verification or audit. Move’s type system helps, but external review ensures no logical flaws remain. Once verified, your move-based programming contract is ready for production.

Frequently asked questions about move-based programming

What is Move programming?

Move is a safe and secure programming language for Web3 that emphasizes scarcity and access control. Unlike other smart contract languages, Move treats digital assets as "resources." This means assets cannot be accidentally duplicated or dropped, enforcing scarcity by default. This structural safety makes it ideal for building secure smart contracts where asset integrity is paramount.

What programming language is Move based on?

Move is a platform-neutral, Rust-based programming language. It was originally developed for Meta's Diem project and has since been adopted by networks like Aptos and Sui. Developers familiar with Rust will find Move’s syntax and type system intuitive, but Move adds specific features designed to optimize the safety of objects in a blockchain environment.

Is Move the same as Rust?

No. While Move shares syntactic similarities with Rust, it is a distinct language designed specifically for blockchain execution. Rust focuses on general systems programming, whereas Move focuses on the secure representation and transfer of digital assets. Move enforces stricter rules around resource handling to prevent common smart contract vulnerabilities like reentrancy attacks.