The Hitchhiker's Guide to Move, Vol2

May 15, 2025
Key Points

Resource Oriented Programming

Rust’s Ownership Meets Move’s Resources: A Love Story

In previous articles we described the Move’s ownership model focuses on managing memory safety, while Move’s resource model focuses on managing digital assets.

Checkpoint!

We learn more about Move's history, rust differences and the architecture of Move and the Move Prover. To recall it we will present the fundamentals to understand how to develop a raffle system in move for the sui blockchain, that is our case!

  • In a raffle an admin can mint tickets, and set the number of tickets and price in a preparing phase.
  • The Buyers can buy a ticket number.
  • The tickets can be transferred to the Ticket Vault.
  • Each participant can buy one ticket.
  • The prize is awarded to a random participant, once all tickets are sold.
  • The winner can claim the price
  • Exist refunds in sui token

In our case:

  • If you give me a coin , i will give you a ticket
  • If you show me your ticket, i will show you the winner

Ownership

In Move we simplified the ownership model with this asset semantics:

Struct and data, cannot contain references, or multiple &&T references
Move’s borrow checker enforces strict rules on references to ensure safety and prevent misuse. Specifically, references cannot be used after they have been moved or invalidated

In Move, assets are protected by the type system to prevent duplication, double spending or loss, this behaviour mimics bitcoin properties of being a hard money.

  • Resources cannot be copied
  • Resources cannot be implicitly discarded
  • Resources can only be moved between storage locations

Module System

Move's module system serves as both a code organization unit and a security boundary, the smart contract is the module itself and takes the concept from rust

  • Modules: Encapsulate code functions and resource definitions
  • Abilities: Control how types can be used and composed.
  • Visibility: Define access control for module functions
  • Capability Pattern: Enable fine-grained access control through resource capabilities

Abilities

Smart contract , with secure semantics

Move introduces abilities that specify which operations are permitted on resource types. These abilities use concepts from linear logic, enabling the creation of linear types with distinct properties and constraints. By composing these abilities, developers can define precise behaviors and permissions for each asset.

The available Sui abilities are:

  • Key: The resource can be stored in a global storage.
  • Copy: The resource can be duplicated.
  • Drop: The resource can be discarded.
  • Store: The resource can be saved

Copy

It gates the ability to copy values out of local variables with the copy operator and to copy values via references with dereference *e.

Drop

The drop ability enables values of certain types to be discarded. Dropping a value means it is not transferred elsewhere and is effectively destroyed during the execution of the Move program it gates the ability to ignore values in a multitude of locations, including:

  • not using the value or sequence in a local variable or parameter
  • overwriting values via references when writing *e1 = e2.

Store

This is the only ability that does not directly gate an operation. Instead it gates the existence in global storage when used in combination with the key ability.

Key

When a key-enabled object is created, it becomes part of the global storage and remains there until explicitly moved or destroyed.

In this case a pair can be stored and deleted, but not owned by a key.

Generics

Another interesting feature of the language is the generics types who also can use and combine abilities in the type declaration, generics can be used to define functions and structs over different input data types, also known as parametric polymorphism 

This is useful when you want to write a function which can be used with different types, or when you want to define a type that can hold any other type.

Thinking about our ticket application, an example of this is the Raffle State:

We use the Option type to hold an address by specifying it within angle brackets (<address>). The std::option module is implicitly imported in every Move module, so there’s no need for an explicit import. The standard library also provides other generic containers like vector<T> for storing multiple items of a given type vector.

Visibility

The entry keyword indicates that a function can be called directly from a transaction. To simplify this model, we should decide whether we want the function to be invoked from a transaction or not, and whether it should be callable from any module or only within the current module.Friend means call the function from a module in the same package, deprecated

Capabilities and One Time Witness (OTW)

A capability is a design pattern that grants the owner the right to perform a specific action. We use it to enforce access control over resources and operations. In the case of the EVM, we represent it as objects similar to Ownable.

A common approach is to create an AdminCap when the package is published and pair it with a one-time witness (OTW). The OTW is a special, single-use resource that ensures unique, singleton initialization. 

It must be dropped after use and cannot be manually created, enforcing that only one AdminCap is ever initialized per module.

TICKET will be passed as a parameter and dropped immediately once the package assumes ownership. Let’s explore these concepts in detail by examining the init and mint functions.

Putting it All Together: init and mint functions

In this example, we declare a constructor-like function where the package claims the OTW resource, simulating a one-time execution flow. The function enforces that initialization can only happen once by ensuring the OTW resource is valid, claiming it, and transferring ownership of newly created resources to the admin:

  • Checks that the resource is a valid one-time witness (OTW).
  • Claims and transforms it into a publisher resource.
  • Creates a new AdminCap resource.
  • Transfers ownership of both publisher and AdminCap to the admin address.

This pattern ensures a unique initialization flow:

  • TICKET prevents multiple invocations, enforcing a strict, single-run constructor.
  • AdminCap grants privileged rights to the admin, enabling further operations within the module.

Mint function

In the minting function , we pass the capability AdminCap first, to ensure that the minting function can be executed only for the admin. We also pass a mutable reference of the TxContext, and the function will return the type Ticket.

  • To create a new object in the object store, we call the new object.
  • To get any UID, universal identifier , we call the uid_to_inner with the reference of the object (only read).

By emitting a TicketMinted event during the mint process, each state transition becomes part of an event-driven workflow. 

Whenever a new ticket is created, emit_new_tickets logs the ticket’s ID and index, providing easy tracking and observability throughout the system.

Conclusions 

In this article, we explored the language features, explained the simplified ownership model with examples, and described what a resource is, how to use it, and how to compose it. We also provided code snippets from our real-life raffle system.

Macarena López Morillo
Head of People @ Rather Labs
Get the Full Picture
For an in-depth understanding of this topic, don't miss out. Learn more here and elevate your knowledge.
right arrow

Featured Resources

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.