Move Concepts
Move is an open source language for writing safe packages to manipulate on-chain objects (sometimes referred to as "smart contracts"). Move is a platform-agnostic language to enable common libraries, tooling, and developer communities across blockchains with vastly different data and execution models. Move is adaptable to meet the needs of the blockchain the code operates on, see Move on Sui to review enahancements made to Move for optimization on the Sui blockchain.
You can use Move to define, create, and manage programmable Sui objects representing user-level assets. Sui's object system is implemented by adding new functionality to Move while also imposing additional restrictions. See Object Model for more details.
Move on Sui
The Move language on the Sui blockchain contains some important differences from Move on other blockchain frameworks. Sui takes advantage of Move's security and flexibility and enhances it with the features described in the following sections to vastly improve throughput, reduce delays in finality, and make Move programming more approachable. For full details, see the Sui Smart Contracts Platform white paper.
Where the Sui documentation refers to the Move language, the content is documenting the specific Move implementation on the Sui blockchain. If relevant, the documentation expressly refers to the original use case for the Move language as Diem-style Move.
In general, Diem-style Move code written for other systems works in Sui with these exceptions:
Key differences
Key differences with Move on Sui include:
- Sui uses its own object-centric global storage
- Addresses represent Object IDs
- Sui objects have globally unique IDs
- Sui has module initializers (init)
- Sui entry points take object references as input
Object-centric global storage
In Diem-style Move, global storage is part of the programming model that you can access through special operations, such as move_to
, move_from
, and more global storage operators. Core Move stores both resources and modules in global storage. When you publish a module, it's stored into a newly generated module address inside Move. When you create a new object (resource), it's usually stored into some address, as well. This approach creates a problem, however, as on-chain storage is expensive and limited (not optimized for storage and indexing). Current blockchains cannot scale effectively to handle storage-heavy applications, such as marketplaces and social apps.
Move on Sui addresses the scaling issue by not having global storage. Consequently, Move doesn't allow any of the global storage-related operations (there is a bytecode verifier to detect violations for this). Instead, storage happens exclusively within Sui. When you publish a module, the newly published module is stored in Sui storage, instead of Move storage. Similarly, newly created objects are stored in Sui storage.
When you need to read an object in Move, you cannot rely on global storage operations. Instead, Sui must explicitly pass all objects that you need to access into Move.
Addresses represent Object IDs
In Move, there is a special address type. This type is used to represent addresses in Diem-style Move. Core Move needs to know the address of an account when dealing with the global storage. The address type is 16 bytes, which is sufficient for the Diem-style Move security model.
In Sui, because it doesn't support the global storage that's in Diem-style Move, the address type is repurposed to represent a unique, 32-byte ID of either an object or an account. You can access the address of the sender of a transaction from the transaction context. Object IDs also have their address values wrapped in the structs ID
and UID
. Refer to the object.move file in Sui framework for an understanding of address use.
Object with key ability, globally unique IDs
In Diem-style Move, the key
ability is used to tell that the type can be used as a key for global storage. In Sui, this ability has been repurposed to declare a struct as an object. Objects owned by an account are passed in as arguments to transactions, and other objects (using the dynamic fields API dynamic_fields.move) can be accessed dynamically during the transaction. Sui requires that any struct with key ability must start with an id
field with the UID type. The UID type contains both the ObjectID
. Other metadata (such as the sequence number) is managed by the Sui network outside of Move. Sui has a bytecode verifier in place to make sure that the UID field cannot be transferred to other objects (the IDs of objects cannot be re-used once the object is destructured).
Module initializers
As described in Object-centric global storage, you publish Move modules into Sui storage. The Sui runtime executes a special initializer function you optionally define in a module only once at the time of module publication to pre-initialize module-specific data (for example, creating singleton objects).
Entry points take object references as input
You can call public functions from Sui transactions (called programmable transaction blocks). These functions can take objects by value, by immutable reference, or by mutable reference. If taken by value, you can destroy the object, wrap it (in another object), or transfer it (to a Sui ID specified by an address). If taken by mutable reference, the modified version of the object saves to storage without any change in ownership. In any case, the Sui network authenticates the object and declares it's usage as a part of the transaction.
In addition to calling public functions, you can call a function that is marked entry
even if it is private. As long as other public functions have not used its inputs.
Explore concepts
Some of the features of Move are defined in this section using commented code examples.
Init
The init
function is a special function that executes only once - when you publish the associated module. See Init for details.
Entry functions
The entry
modifier for functions enables safe and direct invocation of module functions, much like scripts. See Entry for details.
Strings
Move does not have a native type for strings, but it has a useful wrapper. See Strings for examples.
One-time witness
A one-time witness (OTW) is a special instance of a type created in the module initializer and guaranteed to be unique with only one instance. See One-Time Witness for an example.
Patterns
Move coding patterns, or techniques, solve logic problems you encounter when developing Move packages for the Sui blockchain. See the Patterns section for a list of documented coding patterns.