Move Towards Rust: The Evolution of Sui Move in 2024

Thouny
Building on Sui
Published in
5 min readJan 15, 2024

If you have read this article (and the subsequent ones), you should know that I’m extremely bullish about the future of Move and its potential to become the mainstream language for programming smart contracts.

However, it’s not perfect. Move is still maturing and currently lacks many basic features familiar to Rust developers. While its design is inspired by certain Rust concepts, such as the ownership system, Move is not built on top of Rust like some other domain-specific languages (e.g., Scrypto, Sway…). Instead, it’s developed from scratch and doesn’t compile into wasm, but into Move Bytecode, which enables new security features like the bytecode verifier. Although the language is still developing, this year promises the release of some exciting new features!

Updated with dates and upcoming Sui features!

Syntax

Today, to call a function, we typically write sui::coin::withdraw(&mut c, 10);. With the new method syntax, we’ll be able to write c.withdraw(10); as we usually do in other languages.

In a type’s declaring module, the compiler will automatically create a method alias for any function declaration when the type is the first argument in the function (fun foo(x: &X) { ... } will implicitly be callable with X.foo()). Developers could also manually define method aliases this way:

  • use fun a::m::f as X.g; creates an alias local to the scope
  • public use fun a::m::f as X.g; creates a global alias (only declarable in the module that defines the X type)

Building on Method syntax, syntax for index accesses will be added depending on the type of access:

  • &x[i] expands to x.borrow(i)
  • &mut x[i] expands to x.borrow_mut(i)
  • x[i] expands to *x.borrow(i)
  • x[i] = v expands to x.assign(i, v)

Because new keywords are being added in the 2024 edition, a new syntax is provided to help with migrations. Any keyword can be used as an identifier by escaping it in backticks, `. Target Release: Late February.

Macro Functions

Move doesn’t have lambdas (or closures), so macro functions will be used to replicate the behavior of higher-order functions (such as map, filter, fold, for_each, etc). A “lambda” can be provided and will be substituted as the macro is expanded. For example:

  • let v2 = v.map!(|x| x + 1);
  • v.for_each!(|x| foo(x));

Those “lambdas” additionally will support control flow through break, continue, and return. Target Release: Late February.

Enums

Those of you who are used to Rust have probably been surprised by the absence of Enums. They allow programmers to define a single type with multiple variants such as enum Option<T> { None, Some(T) }.

Move enums will be made up of zero or more variants that can hold data or not, with named or positional fields.

public enum Temperature {
Fahrenheit(u16), // positional field
Celsius { temp: u16 }, // named field
Unknown // no field
}

Pattern matching will also be introduced. It consists in a sequence of match statements that include a pattern and optionally a guard (condition returning a boolean). A pattern can consist of literals (e.g., 0, true), references to enum variants or structs (e.g., Temperature::Fahrenheit or SomeStruct, bindings (e.g., x, y), wildcards _, and or-patterns pattern | pattern.

match (t) {
Temperature::Fahrenheit(temp) => *temp >= 212, // binding pattern
Temperature::Celsius { temp } if (*temp >= 100) => true, // with guard
Temperature::Unknown => false, // enum variant pattern
_ => true, // wildcard
}

Unfortunately fields will be private only, just like for structs. And like structs, enums will have abilities, except key because they can’t be objects.

Targte Release in Q2 2024. Read more about Enums in Move in this issue.

Small Improvements

public(package) will replace public(friends) because there can only be friends within a common package.

Positional fields will be added for Structs (similar to Enums I mentioned above). For better readability, abilities declaration can be written after the fields: struct Number(u64) has copy, drop, store;

Type inference will be added: dynamic_field::borrow_mut<_, Coin<SUI>>(&mut id, owner). _ is inferred as address here.

Within a loop, break will be able to take a value.

let mut i = 0;
loop {
if (v[i] > 10) break i;
i = i + 1;
}

Block naming will be supported, helping developers to write more concise code. Possible with any block, here is an example with a loop.

let mut terminate_loop = false;

while (...loop_condition...) 'outer: {
while (...inner_condition...) {
...
if (...break_condition...) {
terminate_loop = true;
}
...
if (terminate_loop) {
break 'outer; // immediately breaks to the outer loop
}
}
}

Breaking Changes

At the moment, Structs can only be public. But to anticipate the future, structs will have to be declared as public in the 2024 edition.

To improve readability and understandability in the presence of method calls, mut annotations will be required to be added to all local variables if they are assigned or mutably borrowed.

Framework

Shared object deletion is already live on testnet and should be available on mainnet in early February.

A new token standard has been added to the framework recently. Closed Loop Tokens were initially built to manage centralized stablecoins. But things have changed, RegulatedCoinMetadata and DenyList have been added to the Coin standard to enable regulated Coins. Closed Loop Tokens will be used for loyalty points, regulatory-compliant tokens, or in-game currencies for instance. In Q2 2024, more support across RPCs, fullnodes, indexers, and SDK will be released for this standard.

At the moment, user identities, bids, transactions, and other information including the content of NFTs are public. This restricts the scope of successful NFT categories to those which are exclusively privacy-insensitive, and also introduces the possibility of shill bidding, wash trading, and even unauthorized copying of digital assets. A protocol for a private NFT exchange between a seller and a buyer that uses zero-knowledge proofs will be introduced in March 2024.

Developer Tooling

An auto formatter is finally in the works! This will allow developers to make their code prettier (wink) with no effort. Linting is also being enhanced.

Currently, the only way to test PTBs is to use a sdk. From mid February, Sui CLI will support PTBs.

Toolchain versioning will facilitate building packages with dependencies (that have been published with a previous version). During Q1, the Rust sdk will be refreshed.

RPC 2.0, the new GraphQL RPC API is fully available.

The good news is that you can try all those features today by adding edition = "2024.alpha" under the [package] section in your Move.toml. It will then evolve into edition = "2024.beta" and finally edition = "2024" .

These changes concern Sui Move only and will not be merged back into core Move (except perhaps into Sui’s own branch over there). As far as compatibility goes, Sui has had its own development stream of Move for some time now, as do all other deployments.

This article is highly inspired by this github issue and the developer roadmap. Feel free to join the discussion and provide feedback there or in comments. Don’t forget to join me on X to learn more about Move and Web3 overall!

--

--

Thouny
Building on Sui

Blockchain developer crafting educational and technical content on Web3 techs and philosophies. Digressions on life trying to make sense of it.