[EN] My First Impression of Sui Move — (1) Introduction & Minting a simple NFT

Sigrid Jin
DSRV
Published in
11 min readJul 11, 2022

DSRV Research publishes in-depth blockchain-related content with the aim of safely onboarding more people to Web3.

Disclaimer: This article is for informational purposes only and should not be taken as financial advice. No information contained within this article is a recommendation to invest in any of the assets mentioned. All investors are advised to thoroughly conduct their own research before making any financial decisions.

[Series on My First Impression of Sui Move]

  1. Introduction & Minting a simple NFT
  2. Building a Simple Sword Example
  3. Building a Simple Tic-tac-toe Example with Frontend

What got me interested in the Web3 scene in 2019 was reading Facebook’s (now Meta) much-awaited Libra whitepaper. Libra was Facebook’s new venture into blockchain technology, the far-reaching goals of which were to enable a simple global currency and financial infrastructure for billions of users.

I lived in Nonce, the Seoul-based co-living/working community for blockchain developers, where developers at the time of the last crypto winter were eagerly awaiting the Libra whitepaper. And I, along with them, was ready to rush into Facebook’s crypto venture.

Meanwhile, the digital currency had elicited a mixed reaction both from the crypto world and regulatory bodies worldwide. When the project was initially announced, it boasted a long list of major partners from the payment scene which definitely guaranteed its success.

And yet, the participants in the Libra Associations are threatened to face a high level of scrutiny from various regulator bodies. In addition to the wider crypto bear markets, the entire Libra project collapsed, as we all know to date.

Although Facebook restructured the renamed Diem Association and wound down the project, the Menlo Park-based tech giant’s mission to explore the Metaverse and Web3 world was not in vain. The ex-engineers have founded Layer 1 blockchains to continue to develop their ideas!

There are a plethora of Move-powered L1 blockchains that trying to introduce themselves to the crypto scene, but noticeably the industry is now paying attention to is Aptos and Mysten Lab’s Sui. They both run the Move VM underneath the protocol. I am recently interested in Sui Network since it claims to be the attractive L1 smart contract platform with high throughput via horizontal scaling.

Move — “A language with scarcity.”

The common point of the self-proclaimed successors of the Libra blockchain is using the Move programming language, originally developed by the Libra team at Facebook. Solidity is now the dominant player in the blockchain languages field. Solidity was created as one of the first blockchain languages to implement core programming language principles utilizing well-known data types and data structures.

And while the language is naturally all about asset transfers, it has no native support for assets. If the primary goal of blockchain languages is digital asset activity, then the primary feature is security.

If you are familiar with writing codes in modern language, the concept of first-class citizens should catch your attention. Functions in JavaScript are first-class objects. All functions are objects in JavaScript, and they inherit from the Object prototype and be assigned key-value pairs. The objects can be assigned to variables and passed around as an argument.

The presentation from Sam Blackshear, prev Novi Research, now Mysten Lab’s CTO

The Move programming language claims to be designed to address those problems. The Move has the principle to uphold digital assets to be first-class citizens, which are expressively designed for managing digital assets represented on the blockchain.

Technically, variables in contracts that are used to store, assign, and become parameters or return values for functions and processes might be digital assets. The compiler can evaluate most resource issues during compilation and before deployment thanks to the static type of the Move, which increases the security of smart contracts.

When scrutinizing the difference in Data Models between EVM and the Move, EVM assets are encoded inside a dynamically indexed mapping like owner_address -> <bytes assets>. Any arbitrary assets are represented as entries in HashMap, which implies that updating the state is just changing the values of entries in the collection.

The digital assets are not able to escape from the contract that defines them. Meanwhile, they are arguably first-class citizens in a Web3 domain and are entitled to be represented with a dedicated type on a language level.

What makes the Move language interesting is that the Move assets are arbitrary user-defined types. The assets are leveraged by Move objects which could be changed its state by a set of transactions. The documentation also claims that the language provides built-in resource safety to allow digital assets to easily flow across contract borders while keeping their integrity.

The language also has the benefit of data composability. It is always feasible to make a new asset that contains another asset. It is also feasible to define a generic wrapper Z(T) capable of wrapping any asset, offering, or combining new attributes to a wrapped object.

Not to mention, Move offers an appealing testing tool that is integrated into a language level. The unit testing framework is designed to be utilized anytime, anywhere if you come from a traditional web development background (also known as “Web2”).

Contrary to what you would have hoped, smart contract languages lack a defined structure for unit testing or E2E testing. Meanwhile, the Move’s built-in testing framework guarantees type and asset safety at the compile level, much as the testing framework for Rust or the JUnit framework for Java.

Let us see the following Sandwich example for digging into the data composability. The code defines struct (asset) Ham, Bread, Sandwich, and Grocery. GreceryOwnerCapability struct allows the owner to withdraw any profits.

The struct for Grocery is on the following code snippet, which has profits and balance within the struct. After declaring the price for Ham and Bread, the module init does the creation of a Grocery and then transfers the GroceryOwnerCapability to the transaction sender.

The following code exchanges a hypothetical coin C to purchase some Hams 🍖 and pieces of bread 🍞 and then combines the Ham and Bread into a sandwich 🥪. Albeit deleting the existing two foods, creating a delicious sandwich instead!

It is apparent from the above that the Grocery struct receives money when customers buy ham or bread. The proprietor can benefit by providing his grocery capabilities. It appears to be similar to the PDA idea commonly seen on Solana.

Let’s do the test. Remind the fact the price of Ham is 10, and that of Bread is 2. The net profit is 12. On test, the code purchases one slice of Ham and Bread. Should check whether the grocery has 12 profits; and after collecting profits from the owner, the balance goes to zero.

Sui Move is a framework while Core Move is a language

Fireside Chat with Sam Blackshear, Mysten Labs Co-Founder & CTO and Creator of the Move Language

The core difference is that Sui uses its own object-centric global storage that works as a pool of objects. When you publish a module, it is saved in a newly created module address. When a new resource is generated, it is saved into the address of some account. On-chain storage is both costly and restricted so there is no global storage in Sui Move. Sui Move does not permit any global storage-related actions. When publishing a module, it is saved in Sui storage. Newly produced items are kept in Sui storage.

In addition, Sui does not require the address type to represent accounts in Sui since it doesn’t offer global storage in Move. Instead, the address type is used to represent the Object ID where anyone can create, be copied, and be dropped. When creating a new sword object from the module, for example, each object has a different address which plays a role of an identifier.

As each object with key ability, globally unique IDs pave a way for differentiating between items on internal Move objects that cross over Move-Sui borders, the key ability also plays a pivotal role to serve as a key for global storage operations. It gates all global storage operations, the type must have the key ability. Each object must have a unique ID.

Sui redesigns internal Move to rule out the use of global storage; the ID type comprises the Object ID as well as the sequence number, to ensure that the ID field is immutable and cannot be moved to other objects. Each transaction is essentially passing in an object, then the contract mutates, destroys, or creates new objects.

As Move modules are published to Sui storage, the Sui runtime executes once a custom initializer function is optionally defined in a module upon its publishing for the purpose of pre-initializing module-specific data, like creating singleton objects. It works like a constructor in other object-oriented languages like Java, to create an instance from the class metadata.

Lastly, Entry points take object references as input as being a somewhat similar concept to that of CosmWasm, or Controller in the Spring MVC pattern. Sui provides entry functions that may be called straight from the SUI module, as well as functions that are callable from other functions. One of the simplest entry functions is defined to handle gas object transfer between address that represents specific users.

Minting a simple NFT

Without further ado, getting your hands dirt would help to appreciate the concept of Sui’s Move much clearer. This article is going to build two sample examples; minting a simple NFT and Forging a Sword.

To begin with, install Sui binaries by running the following commands. You are expected to install the Rust and Cargo toolchain prior to installing Sui.

At the time of writing (July 9, 2022), the devnet is the only available network option to Sui. Find your address by entering the following command.

As did on other protocols, you are required to request test SUI tokens on the #devnet-faucet of Discord. Join the channel here if you’ve not already, request test SUI tokens then check your transaction hash on the Sui Explorer.

One thing that attracts me is that minting a simple NFT example using Sui CLI is native support. Run the following command to create an NFT.

The output would resemble the following. The terminal prints the newly created objectId that could be confirmed on the Sui Explorer. A single objectId represents a single NFT, so you just have minted a single NFT instance, not publishing the ERC721-alike contract module. This sounds more natural according to the concept of NFT, doesn’t it?

The above command created an object with an ID 0xe69e7257310c5054eda27ff474e827616c7c0b89.

You may easily customize the name, description, or image of the NFT upon creation.

The result would resemble the following.

The Sui Explorer shows the details of the NFT object when searching by objectId.

Check your transaction hash on Sui Explorer. The terminal prints out the transaction hash under the Previous Transaction. The mine was XuzYR05wQOfztKyYvpwIXN1IONiGn3SnVwZByhAxluM.

Intriguingly, your SUI object is paid for the transaction fee so that the explorer prints the SUI object as Mutated above. The amount of your airdropped SUI object has been diminished, which means that some gas was charged. The initial gas value was 50000, but now it is 39063 from my own side. (I have already sent some transactions beforehand)

You might be able to check the list of objects that your address now holds as the following. Sui Explorer also visualizes data for you.

wallet objects --address YOUR_ADDRESS_HERE

💡 DSRV’s Tip — Reusing the bytecode when instantiating a new object

The Sui’s Move does indeed support reusing the bytecode already published modules like CosmWasm.
For example, every time you write a line like use sui::coin::Coin, you can use 0x45aacd9ed90a5a8e211502ac3fa898a3819f23b2::module_name in your Move code.

Data Models — EVM vs Move

What one would notice from the aforementioned example is that NFT expressed on Sui is totally different from that of Ethereum. Ethereum has the ERC721 which is a token standard for non-fungible tokens. Minting NFT requires instantiating contracts by deploying ERC721 contracts.

Your digital asset is only locked in the condition of the contract that declares it, as was briefly stated before. Your NFT or digital assets cannot validly cross the contract boundary on their own. In Sui, however, each address possesses objects that were originally stored only within the smart contract on Ethereum. Move liberates digital assets to be a first-class citizen for the first time.

Viva La Vida! Photo: Wikimedia Commons

A Move module is different in that the contract does not have its own storage. The Move has global storage — or blockchain state instead, which is indexed by addresses. Under each address, there are Move modules and resources. The global storage is expressed in Rust like the following.

The resource of each address has a map from types to values which is a native mapping that is readily indexed by addresses. When it comes to BasicCoin modules corresponding to ERC20 of Ethereum, there is a struct Balance that represents the balance of each address.

The Move blockchain state should roughly like the following.

Reference: https://github.com/move-language/move/tree/main/language/documentation/tutorial

You can notice a stark difference between the Ethereum state on the diagram below. The balance of each address is often saved in a state variable of type mapping(address => uint256) in Ethereum ERC-20 contracts. This state variable is kept in a specific smart contract's storage.

Reference: https://github.com/move-language/move/tree/main/language/documentation/tutorial

What’s next?

Once having learned Spring Boot in the Java scene, which piqued my curiosity in Object-oriented programming, I recognized that in the web3 landscape, all digital assets should be represented as an object since they are the primary players in the business logic.

Meanwhile, they are only detained inside the contract that defines them. When it comes to Solidity, all digital assets are solely represented by an objectId. This leads me to believe that the present smart contract language is incompatible with the idea of object-oriented programming. Given that the Move language seeks to tackle the problem by making digital assets first-class citizens, I’ve developed an interest in constructing contracts using Sui’s Move.

In subsequent posts, I will go over Sui’s documentation, which is currently lacking in terms of updating the most recent developments and improvements to Sui’s Move. Then I’ll create some Move tutorials — building a simple Forging a Sword example and creating tic-tac-toe with connecting to frontend.

Author
Sigrid Jin of DSRV, Software Engineer & Technical Writer (Twitter @sigridjin_eth)

Reviewed By
Tilly of DSRV, Communications Manager

--

--