The basic unit of storage in Sui is the object. In contrast to many other blockchains where storage is centered around accounts containing key-value stores, Sui's storage is centered around objects addressable on-chain by unique IDs. A smart contract is an object (called a Sui Move package), and these smart contracts manipulate objects on the Sui network:
- Sui Move Package: a set of Sui Move bytecode modules. Each module has a name that's unique within the containing package. The combination of the package's on-chain ID and the name of a module uniquely identify the module. When you publish smart contracts to Sui, a package is the unit of publishing. After you publish a package object, it is immutable and can never be changed or removed. A package object can depend on other package objects that were previously published to Sui.
- Sui Move Object: typed data governed by a particular Sui Move module from a Sui Move package. Each object value is a struct with fields that can contain primitive types (such as integers and addresses), other objects, and non-object structs.
Each Sui object has the following metadata:
- A 32-byte globally unique ID. An object ID is derived from the digest of the transaction that created the object and from a counter encoding the number of IDs generated by the transaction.
- An 8-byte unsigned integer version that monotonically increases with every transaction that modifies it (see Object and package versioning).
- A 32-byte transaction digest indicating the last transaction that included this object as an output.
- A 33-byte owner field that indicates how this object can be accessed. See Object Ownership for more information.
In addition to common metadata, objects have a category-specific, variable-sized contents field containing a Binary Canonical Serialization (BCS)-encoded payload.
- Move Objects contain their Move type, whether the object can be transferred using
public_transfer, and its fields, again encoded as BCS.
- Move Packages contain the bytecode modules in the package, a table identifying which versions of a package introduced each of its types (the type origin table), and a table mapping each of its transitive dependencies to a specific version of that package to use (the linkage table).
Referring to objects
There are a few different ways to concisely refer to an object without specifying its entire contents and metadata, each with slightly different use cases:
- ID: the globally unique ID of the object mentioned above. ID is a stable identifier for the object across time and is useful for querying the current state of an object or describing which object was transferred between two addresses.
- Versioned ID: an (ID, version) pair. Versioned ID describes the state of the object at a particular point in the object's history and is useful for asking what the value of the object was at some point in the past or determining how fresh some view of an object is now.
- Object Reference: an (ID, version, object digest) triple. The object digest is the hash of the object's contents and metadata. An object reference provides an authenticated view of the object at a particular point in the object's history. Transactions require object inputs to be specified via object references to ensure the transaction's sender and a validator processing the transaction agree on the contents and metadata of the object.
The transaction-object DAG: Relating objects and transactions
Transactions take objects as input, read/write/mutate these inputs, and produce mutated or freshly created objects as output. Each object knows the (hash of the) last transaction that produced it as an output. Thus, a natural way to represent the relationship between objects and transactions is a directed acyclic graph (DAG) where:
- Nodes are transactions.
- Directed edges go from transaction
Bif an output object of
Ais an input object of
B. They are labeled by the reference of the object in question (which specifies the exact version of the object created by
Aand used by
The root of this DAG is a genesis transaction that takes no inputs and produces the objects that exist in the system's initial state. The DAG can be extended by identifying mutable transaction outputs that have not yet been consumed by any committed transaction and sending a new transaction that takes these outputs (and optionally, immutable transaction outputs) as inputs.
The set of objects that are available to be taken as input by a transaction are the live objects, and the global state maintained by Sui consists of the totality of such objects. The live objects for a particular Sui address A are all objects owned by A, along with all shared and immutable objects in the system.
When this DAG contains all committed transactions in the system, it forms a complete (and cryptographically auditable) view of the system's state and history. In addition, you can use the scheme above to construct a DAG of the relevant history for a subset of transactions or objects (for example, the objects owned by a single address).
Limits on transactions, objects, and data
Sui has some limits on transactions and data used in transactions, such as a maximum size and number of objects used.