Improving Move Comprehension(2): Move Design Pattern

verse2
verse2
Published in
8 min readApr 22, 2024

Move Design Pattern: Key takeaways

  1. Move incorporates various design patterns for secure Web3 asset management.
  2. Aptos Move ensures rigorous resource control and employs an object model to surpass resource model limitations.
  3. Move focuses on crafting secure contracts by mitigating developer errors with programming language level constraints.

Intro

Many of the Web3 hacks have resulted from a few lines of developer error or bugs, causing damages worth millions of dollars. Move, from its design phase, aimed to prevent developer errors at the language level by focusing on the three core purposes of smart contracts: asset creation, transfer, and utilization. When developing contracts using Move, developers naturally follow the logic of real-world asset exchanges, asking questions like “Who owns this asset?” and “Do they have authority over the asset?” This article will explore which design patterns in Move contribute to fostering this flow of consciousness.

Pattern #1. Scarcity & Access control

Move is a Web3-specific smart contract that uses the concepts of scarcity and access control to ensure its reliability. First, we need to understand how assets are represented in Move contracts: all assets represented in Move are basically stored in the form of resources, which are represented as structs. The scarcity of Move makes it essentially impossible for this resource to be replicated. The only way to replicate a resource is to explicitly mark it as copyable.

In addition, abilities such as drop, key, and store must be specified on the resource to perform the desired function. Here are the roles for the four abilities that exist in Move

  • copy: allows values of types with this ability to be copied.
  • drop: allows values of types with this ability to be popped/dropped.
  • store: allows values of types with this ability to exist inside a struct in global storage.
  • key: allows the type to serve as a key for global storage operations.

The abilities are explained in detail in Aptos Move: Struct and its Abilities Explained — has Drop, Copy, Key, Store, which is a must-read for anyone interested in learning more.

In addition to scarcity, Move provides a strong way to control access to accounts and modules through access control. In Move, a module is a program that creates, stores, and transfers assets, and modules are only externally accessible as public functions, strictly limiting the ability to change the values stored in them. By explicitly expressing the constraints on external calls, Aptos prevents vulnerabilities inherent in EVM-based smart contracts, such as re-entrancy attacks. In addition, the Aptos core code implemented in Rust checks access to resources through a type called AccessPath, which checks whether the address is an account that has authorization to the resource through the argument, and checks whether the path is an appropriate path by comparing the module’s ID value and Struct Tag through the argument.

types/src/access_path.rs

In particular, when executing a module’s functions through a transaction, you can take as an argument the signer who signed the transaction, which can be utilized to manage access to the module’s resources. For example, to execute a function called transfer, the asset held by the sender with the &signer type is fetched from a resource called FungibleStore through the withdraw function, and access to the resource is authorized by checking the value of the account that signed the transaction that calls the transfer function. In other words, by automatically including information about the account that calls the transaction as an argument to the function, access to a specific resource is checked at the code level. This constant checking of access permissions is essential when developing smart contracts with Move.

aptos-move/framework/aptos-framework/sources/coin.move

Tip. Move strictly controls changes to and access to resources that are values in contract.

Pattern #2. Global Storage

In summary, resources are specific data values represented in Move. To understand how and where resources are stored, we need to understand global storage. Global storage is persistent storage implemented as a tree-shaped structure composed of resources and modules. The role of the Move contract is to implement the business logic for storing or reading values from this global storage.

As you can see from the code for GlobalStorage written above, resources and modules are mapped to a value called address to store their values, which again shows that we are controlling access through a specific address. In order to create, remove, or update resources in global storage, we must use global storage operations like the ones below. What’s interesting here is that Move’s implementation is inspired by Rust’s ownership model, as evidenced by keywords like borrow.

Each operation has a generic type parameterized as <T>, which must be a resource type that currently exists within the Move module. This also allows for compile-time checking of permissions to change values, with constraints imposed to ensure that resources can only be manipulated within the module that defined them. Operations like move_to take &signer as an argument, which means that in order to deploy a particular resource to a particular account, you must have the permissions of that account. Operations that simply require an address argument can be called regardless of the account’s permissions.

Tip. The &signer type is the account that signed the transaction and has the highest privileges on the resources that account has.

Pattern #3. Object Model

In August 2023, Aptos released new standards for Digital Assets and Fungible Assets with AIP-10 and 11. This was an introduction to a new design pattern called the Object Model, and it brought many changes to Aptos Move. While the resource model helps develop secure contracts based on ownership, it has a number of limitations. Here are some of the issues with the resource model

  1. Low data availability: The resource model does not guarantee access to data. The values that users store in their account’s custom repository are very hard to retrieve externally. It’s difficult to reference the data directly, and if you do, it’s a complicated process. For example, token issuance based on the resource model requires users to register the information that they own coins in the token contract.
  2. Difficulty distinguishing data types: In the resource model, multiple types of data can be stored in one data using any type, which requires a separate deserialization process, and it is cumbersome for contract developers to handle any type.
  3. Data structure inefficiency: Aptos Move has a type called resource group that groups related resources together to provide efficiency when dealing with complex data structures, which is difficult to leverage in the resource model. Resource groups can increase the locality of data and reduce storage costs, which is not possible with a resource model that only allows access to values through a global store.

Other problems include the difficulty of expressing recursive types and the difficulty of raising events in contracts. To overcome these problems, the proposed object model can be represented as the following figure.

In the case of Token v1, the data can only be tracked by registering the assets owned by the user, but in an object model such as Token v2, a new object account address is created as soon as the token is issued, and the value is stored in that object account. This is defined as a resource called ObjectCore as shown below, and objects are distinguished through the guid value assigned to them when they are created, and have the information of the owner who created the object. The objects created in this way can be accessed through a global address, making data processing more intuitive and simple.

To summarize the effects of the object model, here’s how it works.

1. accessibility of data: not always accessible → use reference to ensure accessibility

2. Type of data: generic typing with any type → use explicit Object storage addresses

3. Scalability of data: limited APIs by module → global access regardless of module

4. Efficiency of data: Overhead when loading resources → No need to load individual resources

While some may argue that the object model violates Move’s philosophy of ensuring the reliability of contracts based on a resource model, the development benefits are clear, and we believe it’s a necessary design pattern for Move to grow as a programming language.

Wrapping up

In this article, we’ve seen that the design patterns presented in the Move language and the Aptos platform can significantly improve the reliability and development efficiency of asset management in Web3 environments. Patterns such as scarcity , access control, global storage, and object models provide a more secure environment for developers to design and implement smart contracts. More than just technical, these patterns are playing a big role in laying the groundwork for developers to have a deeper understanding of their assets, make fewer mistakes, and build more robust and secure applications. Of particular note are the various attempts to make data more accessible, type-safe, scalable, and efficient, such as the introduction of the object model. We believe this gives developers using Move the opportunity to explore a wider range of applications and use cases.

Reference

  1. Why the New Aptos Token Object Is a Game Changer
  2. Aptos Move: Struct and its Abilities Explained — has Drop, Copy, Key, Store

Author : Harvey
Reviewer : Ryan

verse2 is a team that specializes in the development of Web3 products, and an incubator for potential Web3 projects. The team consists of skilled experts who have deep knowledge and experience in the field of Cryptofinance.

verse2 [Homepage | Twitter | Medium]

--

--

verse2
verse2
Editor for

Build, incubate, invest — Making all possible in the crypto. / verse2.io