Skip to main content

Object Model in IOTA

The fundamental unit of storage on IOTA is the object. Unlike many blockchains that focus on accounts containing key-value stores, IOTA's storage model centers around objects, each of which is addressable on-chain by a unique ID. In IOTA, a smart contract is an object known as a package, and these smart contracts interact with other objects on the IOTA network:

  • IOTA Move Package: A collection of IOTA Move bytecode modules. Each module has a unique name within its containing package. The combination of the package's on-chain ID and the module name uniquely identifies the module. When you publish smart contracts on IOTA, the package is the unit of publication. Once published, a package object can only be upgraded with the appropriate permissions. A package object may depend on other package objects previously published on IOTA.
  • IOTA Move Object: Typed data managed by a specific IOTA Move module from an IOTA Move package. Each object value is a struct with fields that can include primitive types (such as integers and addresses), other objects, and non-object structs.

Object Metadata

Each IOTA object comes with the following metadata:

  • ID: A 32-byte globally unique identifier derived from the digest of the transaction that created the object and a counter that encodes the number of IDs generated by the transaction.
  • Version: An 8-byte unsigned integer that increases monotonically with every transaction that modifies the object (see Object and Package Versioning).
  • Transaction Digest: A 32-byte digest indicating the last transaction that included this object as an output.
  • Owner Field: A 33-byte field that determines how the object can be accessed. For more details, refer to Object Ownership.

Beyond the common metadata, objects have a category-specific, variable-sized contents field that contains a Binary Canonical Serialization (BCS)-encoded payload.

  • Move Objects include their Move type, transferability status via public_transfer, and their fields, all encoded in BCS.
  • Move Packages contain the bytecode modules in the package, a table that identifies which versions of a package introduced each type (the type origin table), and a table mapping each of its transitive dependencies to a specific version of that package (the linkage table).

Referring to Objects

There are several ways to concisely refer to an object without specifying its entire contents and metadata, each suitable for different use cases:

  • ID: The globally unique ID of the object. It is a stable identifier over time, useful for querying the current state of an object or identifying which object was transferred between two addresses.
  • Versioned ID: A pair consisting of an (ID, version). This reference describes the state of the object at a particular point in its history and is useful for querying the value of the object at a specific time or determining the freshness of the object's state.
  • Object Reference: A triple consisting of an (ID, version, object digest). 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 specific point in its history. Transactions require object inputs to be specified via object references to ensure that both the transaction sender and the validator processing the transaction agree on the object's contents and metadata.

The Transaction-Object DAG: Relating Objects and Transactions

Transactions in IOTA take objects as input, modify these inputs, and produce new or updated objects as output. Each object records the hash of the last transaction that produced it as an output. This relationship between objects and transactions can be represented as a directed acyclic graph (DAG), where:

  • Nodes represent transactions.
  • Directed edges connect transaction A to transaction B if an output object of A is used as an input for B. These edges are labeled with the reference of the object, specifying the exact version created by A and used by B.

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 been consumed and issuing a new transaction that takes these outputs (and optionally, immutable transaction outputs) as inputs.

The set of objects available as inputs to a transaction are the live objects, and the global state maintained by IOTA consists of all such objects. The live objects for a specific IOTA address A include all objects owned by A, along with all shared and immutable objects in the system.

When this DAG encompasses all committed transactions, it forms a complete and cryptographically auditable view of the system's state and history. Additionally, you can construct a DAG of the relevant history for a subset of transactions or objects, such as those owned by a single address.

Limits on Transactions, Objects, and Data

IOTA imposes certain limits on transactions and the data used within them, including maximum sizes and the number of objects involved.

The ProtocolConfig struct in the iota-protocol-config crate itemizes these limits. Expand the following code to see the ProtocolConfig struct and the comments that explain each parameter.

Question 1/4

What is the fundamental unit of storage on IOTA?