Aptos MOVE demystified part 1 — HelloWorld module

Monethic.io
5 min readMay 20, 2024

--

Currently, MOVE language is supported by Movement, Sui and Aptos

Initially we wanted to create some article about Move security and vulnerabilities, but in the middle we felt that it won’t be complete unless we explain how Move language works. So we are starting with explaining Move language basics, and the security topics will follow later… in the meantime, if you ever wondered how to start learning Move, you’re in the right place.

What is Move

Move is a rust based language originating from project Diem Blockchain, in short while Diem is discontinued, Move language is still in use as a smart contract language in some blockchains. Those blockchains are: Aptos, Sui and Movement.

Aside of blockchain parameters, Move has some unique security related features, which will be discussed in depth in further parts of this article.

Since the best way is to learning by doing, let’s try to deploy a sample smart contract and all explanation will follow along the way. In this article we’ll focus on Aptos move, and for Sui maybe similar article will appear in the future — but fear not, they are quite similar to each other!

We’ll start with deploying a contract and setting up an environment.

Getting started

Let’s simply download latest aptos cli from https://github.com/aptos-labs/aptos-core/releases/

And add it to PATH to make it usable on your system. You might also want to install MOVE language in Visual Studio to benefit from syntax highlighting

Let’s create a directory named aptos-hello (or whatever else)

aptos init
aptos move init --name hello

When you do aptos init, a path is being created — .aptos/config.yaml, where your private key is stored. Unless you have your own, it will be auto generated. Note, that this may become a security risk if it happens this is uploaded e.g. to GitHub — as long if that’s a real key, and not a development-only one. After using the above command some directories are created:

my_move_project/
├── Move.toml
├── README.md
├── sources/
│ └── <YourModule>.move
├── tests/
│ └── <YourModule>_test.move
└── build/

· Move.toml — main configuration file

· Sources — scripts and modules

· Tests — unit tests

· Build — compile time artifacts will be stored there

The smart contracts code will be located in sources/.

WTF is Module and script?

In Move there are two kinds of pieces of source code: Modules and Scripts.

Modules in Move essentially smart contracts in Solidity. They contain persistent state (resources) and functions that operate on that state. Modules are deployed on the blockchain and can be reused by other modules and scripts.

Aside modules, Move offers something named Scripts. They are transaction payloads that execute a sequence of operations. Unlike modules, scripts do not maintain state; instead, they invoke functions from modules to perform actions. We won’t be covering them in depth, but if you’re interested, read on here.

In essence, modules define reusable logic and state, while scripts may execute that logic through transactions.

So knowing that, most likely we are interested in creating a module, which will be our first smart contract — accompanied by a simple unit test.

The code

Below code is used to deploy a HelloWorld module. Note to change

[addresses]
sender = "your address from .aptos/config.yaml"

in Move.toml — our is 0x120faaaa8517b0b155c3aa5f1ffed804449e7541543053f7896dc9cc8f54e2a1 and will be used throughout the example. Below is the code of Hello.move:

module 0x120faaaa8517b0b155c3aa5f1ffed804449e7541543053f7896dc9cc8f54e2a1::Hello {
use std::debug; //for testing purposes
use std::string;

fun hello_output() {
let a: vector<u8> = b"Hello from Move module";
debug::print(&string::utf8(a)); //for testing purposes
}

public entry fun say_hello() {
hello_output();
}

}

Upgradeability

As in similar languages, contracts (modules) in Move can be upgradeable or not. Important note: in Move, they are upgradeable by default. If you want to change that behavior, you should restrict immutability. In Move.toml, we can add a line:

[package]
name = "any"
version = "1.2.3"
authors = []
upgrade_policy = "immutable"

Which will cause that once deployed, the module cannot be upgraded. Another option of upgrade_policy is compatible, which we won’t cover here, but you can read more about upgradeability here. There’s another important context though — if you are to create an immutable module, and it depends on other modules, it should be ensured that the dependencies are immutable, and reverse — if you were to call an external, upgradeable module, your module should also be upgradeable.

Compiling

Compilation and deployment to devnet. We do it by issuing following commands:

aptos move compile
aptos move publish --package-dir . --named-addresses Hello=0x120faaaa8517b0b155c3aa5f1ffed804449e7541543053f7896dc9cc8f54e2a1
Deployment of hello world module

However, if you chose the immutable package, and try to redeploy, you’re going to see something like this:

Immutable package cannot be upgraded, as expected

And finally we can call on-chain our function - note this is an on-chain call, so the debug output from unit test wont work here. We reference it by module address::name::function. We’ll explain this convention in second part of the article, which is currently in progress. Once done, the link will appear here.

aptos move run --function-id '120faaaa8517b0b155c3aa5f1ffed804449e7541543053f7896dc9cc8f54e2a1::Hello::say_hello'

Testing

When assessing security of a move module, it is often necessary to create some unit tests (e.g. to write a PoC). The unit test may as well be written in the module file itself, but for clarity of the code, we’ll place it in a file named tests/HelloTest.move

module 0x120faaaa8517b0b155c3aa5f1ffed804449e7541543053f7896dc9cc8f54e2a1::HelloTest {
use 0x120faaaa8517b0b155c3aa5f1ffed804449e7541543053f7896dc9cc8f54e2a1::Hello;

#[test]
public fun test_hello() {
Hello::hello_output();
}
}

Running it with:

aptos move test
Test executed — notice the debug output appeared in the console

We can see that now the debug output was evaluated — this might be useful during local debugging of a PoC.

This is just a sample unit test, to show how it works. You can find more extensive guide to Move unit tests here.

In the next part, we’ll cover more in details what happened here — how the modules are stored in storage, why they are referenced by an address and other features.

--

--

Monethic.io

We are providing security services for smart contracts & web3. Find us on twitter https://twitter.com/Monethic_io