From 8de9a3c47f38c0e65ce05800f3759bc323a9c813 Mon Sep 17 00:00:00 2001 From: Levente Pap Date: Thu, 8 Sep 2022 11:42:08 +0200 Subject: [PATCH] TIP-18 Multi-Asset Ledger and ISC Support (#38) * Adds output types RFC * Formatting fixes * Polishing text * Polishing text vol2 * Minor edit * Add RFC number * Add link to dust protection RFC * Formatting updates * Update output type bytes Do not use reserved output type numbers from chpt2. * Update text/0038-output-types-for-tokenization-and-sc/0038-output-types-for-tokenization-and-sc.md Co-authored-by: Thoralf-M <46689931+Thoralf-M@users.noreply.github.com> * One sig per unlock block * Clarify timelock condition Output can be unlocked if time is equal or past the timelock. * Add note about NFT burning * Change Indexation Tag Length to uint8 * Update Blocks Count to uint8 * Rename `Return Amount Block` to `Dust Deposit Return Block` The block should only be used to get back dust deposits. * Move new tx layout & validation to Transaction Payload RFC Update the original RFC with the new protocol rules, refernce them here. * Add Sender Block to alias, add missing NFTAddress to the block * Add white background to chain figure * Remove last ref to BLS * Clarify Indexation Block The ID of the output is indexed with the indexation tag. * Lift spending constraints when output is expired * Remove SimpleOutput * Add ref to RFC-41 for types and subschemas * Fix section link * Add alias & NFT unlock validation Unlock validation has two stages: - syntactic validation - semantic validation in transaction context * Sort native tokens in lexicographical order * Add native token uniqueness criteria Native tokens in outputs must be sorted in lexicographical order and must not contain duplicate Token IDs. * Fix typos * Sender Block of Alias can be changed by both transitions * Transform RFC-38 into TIP-18 * Update ref to protocol constants * Replaces occurences of RFC with TIP * Refactor outputs with unlock conditions * Merge time based unlock conditions, use Return Address * Fix typo * Fix unlock count validation rule for nft * Require Return Amount != 0 in DDRUC * Fix typos * Add Amount != 0 check to native token syntactic validation * Update address defs * Add amount checks to output validation * Add allowed block list to foundry * Unlock ref index < Max Inputs Count * Require Amount != 0 of any output * Polish alias/nft unlock blocks * Update table of content * Native Tokens Count is uint8 * Change data length from uint32 to uint16 * Refactor, addded: * Immutable Alias Address Unlock Condition for foundries * Immutable Blocks for UTXO state machines * Rename Extended Output to Basic Outpu * Rename inner `Address` fields of addresses The address digest is: * PubKeyHash for Ed25519 Addresses * Alias ID for Alias Addresses * NFT ID for NFT Adresses * Fix small typo * Rename Dust Deposit -> Storage Deposit * Add Amount <= Max Supply syntactic check * Update Storage Deposit Return UC syntactic validation * Make native tokens burnable by holders - Burning by users is equivalent to sending the tokens to the zero address, but without the need to cover the storage deposit. - Melting is the token burning operation performed by the foundry. - Foundry output can only be destroyed when it melts all previously minted tokens. - The update of the `Melted Tokens` field of the foundry determines whether the destroyed tokens are burned or melted. * Fix typo * Update tips/TIP-0018/tip-0018.md Co-authored-by: Sam Chen * Refactor some foundry fields into Token Scheme field - Validation logic does not change, but separated into Token Scheme validation steps * Clarifiy SDRUC semantic rules Return amount on the output side may be in one or more basic outputs with only an address UC. * Update to new dynamic byte array serializaiton primitives * Simplify SDRUC syntactic validation rules * Return payment can be more than `Return Amount` when consuming SDRUC outputs * Fix typo * Change Alias ID and NFT ID to 32 bytes length * Remove TokenTag from foundry and Token ID * Update ref to "Message" to "Block" to align with IOTA 2.0 terminology * Rename "feature blocks" to "features", "unlock blocks" to "unlocks" * Fix small typo * Use IOTA coins consistently * Reformat table * Add outcome table to Expiration Unlock Condition * Minor edit * Editing minor edit * Remove Milestone Index based timelocking, rely on Unix Timestamp * Update tips/TIP-0018/tip-0018.md Fix extra space Co-authored-by: Luca Moser * Update tips/TIP-0018/tip-0018.md Co-authored-by: Luca Moser * Update tips/TIP-0018/tip-0018.md Co-authored-by: Luca Moser * Update tips/TIP-0018/tip-0018.md Co-authored-by: Luca Moser * Update tips/TIP-0018/tip-0018.md Co-authored-by: Luca Moser * Update tips/TIP-0018/tip-0018.md Co-authored-by: Luca Moser * Update tips/TIP-0018/tip-0018.md Co-authored-by: Luca Moser * Update tips/TIP-0018/tip-0018.md Co-authored-by: Luca Moser * Update tips/TIP-0018/tip-0018.md Co-authored-by: Luca Moser * Update tips/TIP-0018/tip-0018.md Co-authored-by: Luca Moser * Update tips/TIP-0018/tip-0018.md Co-authored-by: Luca Moser * Update tips/TIP-0018/tip-0018.md Co-authored-by: Luca Moser * Update tips/TIP-0018/tip-0018.md Co-authored-by: Luca Moser * Update tips/TIP-0018/tip-0018.md Co-authored-by: Luca Moser * Update tips/TIP-0018/tip-0018.md Co-authored-by: Luca Moser * Update tips/TIP-0018/tip-0018.md Co-authored-by: Thoralf-M <46689931+Thoralf-M@users.noreply.github.com> * Add clarification for SDRUC refund outputs * Add definition of "Unlocked Address" for Sender and Issuer features * Fix table for expirration unlocks Table had reverse logic Co-authored-by: Thoralf-M <46689931+Thoralf-M@users.noreply.github.com> Co-authored-by: Sam Chen Co-authored-by: Luca Moser --- tips/TIP-0018/chain-constraint.png | Bin 0 -> 35766 bytes tips/TIP-0018/tip-0018.md | 3839 ++++++++++++++++++++++++++++ 2 files changed, 3839 insertions(+) create mode 100644 tips/TIP-0018/chain-constraint.png create mode 100644 tips/TIP-0018/tip-0018.md diff --git a/tips/TIP-0018/chain-constraint.png b/tips/TIP-0018/chain-constraint.png new file mode 100644 index 0000000000000000000000000000000000000000..4b854f3b287349c8dfbbee3f5e3b7765ccb92008 GIT binary patch literal 35766 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 literal 0 HcmV?d00001 diff --git a/tips/TIP-0018/tip-0018.md b/tips/TIP-0018/tip-0018.md new file mode 100644 index 000000000..068244084 --- /dev/null +++ b/tips/TIP-0018/tip-0018.md @@ -0,0 +1,3839 @@ +--- +tip: 18 +title: Multi-Asset Ledger and ISC Support +description: Transform IOTA into a multi-asset ledger that supports running IOTA Smart Contracts +author: Levente Pap (@lzpap) +discussions-to: https://github.com/iotaledger/tips/pull/38 +status: Draft +type: Standards +layer: Core +created: 2021-11-04 +requires: TIP-19, TIP-20, TIP-21 and TIP-22 +--- + +# Summary + +This document proposes new output types and transaction validation rules for the IOTA protocol to support **native +tokenization** and **smart contract** features. + +Native tokenization refers to the capability of the IOTA ledger to **track the ownership and transfer of user defined +tokens, so-called native tokens**, thus making it a **multi-asset ledger**. The scalable and feeless nature of IOTA +makes it a prime candidate for tokenization use cases. + +The **IOTA Smart Contract Protocol (ISCP)** is a **layer 2 extension** of the IOTA protocol that adds smart contract +features to the Tangle. Many so-called **smart contract chains**, which anchor their state to the base ledger, can be +run in parallel. Users wishing to interact with smart contract chains can send **requests to layer 1 chain accounts +either as regular transactions or directly to the chain**, but **chains may also interact with other chains** in a +trustless manner through the Tangle. + +This TIP presents output types that realize the required new features: +- Smart contract chains have a new account type, called alias account, represented by an **alias output.** +- Requests to smart contract chains can be carried out using the configurable new output type called + **basic output.** +- Native tokens have their own **supply control policy** enforced by **foundry outputs.** +- Layer 1 native **non-fungible tokens** (unique tokens with attached metadata) are introduced via **NFT outputs.** + +# Motivation + +IOTA transitioned from an account based ledger model to an unspent transaction output (UTXO) model with the upgrade to +[Chrysalis phase 2](../TIP-0007/tip-0007.md). In this model, transactions explicitly +reference funds produced by previous transactions to be consumed. This property is desired for scalability: transaction +validation does not depend on the shared global state and, as such, transactions can be validated in parallel. +Double-spends can easily be detected as they spend the very same output more than once. + +The UTXO model becomes even more powerful when unlocking criteria (validation) of outputs is extended as demonstrated +by the [EUTXO model (Chakravarty et al., 2020)](https://fc20.ifca.ai/wtsc/WTSC2020/WTSC20_paper_25.pdf): instead of +requiring only a valid signature for the output's address to unlock it, additional unlocking conditions can be +programmed into outputs. This programmability of outputs is the main idea behind the new output types presented in this +document. + +Today, outputs in the IOTA protocol are designed for one specific use case: the single asset cryptocurrency. The aim of +this TIP is to design several output types for the use cases of: +- Native Tokenization Framework, +- ISCP style smart contracts, +- seamless interoperability between layer 1 and layer 2 tokenization concepts. + +Users will be able to mint their own native tokens directly in the base ledger, which can then be transferred without +any fees just like regular IOTA coins. Each native token has its own supply control policy enforced by the protocol. +These policies are transparent to all network participants. Issuers will be able to store metadata about their tokens +on-ledger, accessible to anyone. + +Non-fungible tokens can be minted and transferred with zero fees. The validated issuers of such NFTs are immutably +attached to the tokens, making it impossible to counterfeit them. + +Users will be able to interact with smart contracts by posting requests through the Tangle. Requests can carry commands +to smart contracts and can additionally also transfer native tokens and NFTs. By depositing native tokens to smart +contracts, their features can be greatly enhanced and programmed to specific use cases. + +The proposal in this TIP not only makes it possible to transfer native tokens to layer 2 smart contracts, but tokens +that originate from layer 2 smart contract chains can also be wrapped into their respective layer 1 representation. +Smart contract chains may transfer tokens between themselves through this mechanism, and they can also post requests to +other chains. + +Composability of smart contracts extends the realm of one smart contract chain, as smart contracts residing on +different chains can call each other in a trustless manner. + +In conclusion, the IOTA protocol will become a scalable general purpose multi-asset DLT with the addition of smart +contracts and native tokenization frameworks. The transition is motivated by the ever-growing need for a scalable and +affordable decentralized application platform. + +# Detailed Design + +Outputs in the UTXO model are essential, core parts of the protocol. The new output types introduce new validation and +unlocking mechanisms, therefore the protocol needs to be adapted. The structure of the remaining sections is as follows: +1. [Introduction to ledger programmability](#ledger-programmability) +2. [Data types, subschemas and protocol constants](#data-types--subschema-notation) +3. [Transaction Payload changes compared to Chrysalis Part 2](#transaction-payload-changes) +4. [New concepts of output design](#new-concepts) + - [Native tokens](#native-tokens-in-outputs) + - [Unlock Conditions](#unlock-conditions) + - [Features](#features) + - [Chain constraint](#chain-constraint-in-utxo) +5. [Detailed design of new output types](#output-design) + - [Basic Output](#basic-output) + - [Alias Output](#alias-output) + - [Foundry Output](#foundry-output) + - [NFT Output](#nft-output) +6. [New unlocking mechanisms](#unlocking-chain-script-locked-outputs) +7. [Discussion](#drawbacks) + +## Ledger Programmability + +The current UTXO model only provides support to transfer IOTA coins. However, the UTXO model presents a unique +opportunity to extend the range of possible applications by programming outputs. + +Programming the base ledger of a DLT is not a new concept. Bitcoin uses the UTXO model and attaches small executables +(scripts) that need to be executed during transaction validation. The bitcoin script language is however not +[Turing-complete](https://en.wikipedia.org/wiki/Turing_completeness) as it can only support a small set of instructions +that are executed in a stack based environment. As each validator has to execute the same scripts and arrive at the +same conclusion, such scripts must terminate very quickly. Also, as transaction validation happens in the context of +the transaction and block, the scripts have no access to the global shared state of the system (all unspent transaction +outputs). + +The novelty of Ethereum was to achieve quasi Turing-completeness by employing an account based model and gas to limit +resource usage during program execution. As the amount of gas used per block is limited, only quasi Turing-completeness +can be achieved. The account based model of Ethereum makes it possible for transactions to have access to the global +shared state of the system, furthermore, transactions are executed one-after-the-other. These two properties make +Ethereum less scalable and susceptible to high transaction fees. + +Cardano achieves UTXO programmability by using the EUTXO model. This makes it possible to represent smart contracts in +a UTXO model as state machines. In EUTXO, states of the machine are encoded in outputs, while state transition rules +are governed by scripts. Just like in bitcoin, these scripts may only use a limited set of instructions. + +It would be quite straightforward to support EUTXO in IOTA too, except that IOTA transactions are feeless. There is no +reward to be paid out to validators for validating transactions, as all nodes in the network validate all transactions. +Due to the unique data structure of the Tangle, there is no need for miners to explicitly choose which transactions are +included in the ledger, but there still has to be a notion of objective validity of transactions. Since it is not +possible without fees to penalize scripts that consume excessive network resources (node CPU cycles) during transaction +validation, IOTA has to be overly restrictive about what instructions are supported on layer 1. + +It must also be noted that UTXO scripts are finite state machines with the state space restricted by the output and +transaction validation rules. It makes expressiveness of UTXO scripts inherently limited. In the context of complicated +application logic required by use cases such as modern DeFi, this leads to unconventional and complicated architectures +of the application, consisting of many interacting finite state machines. Apart from complexity and UX costs, it also +has performance and scalability penalties. + +For the reason mentioned above, **IOTA chooses to support configurable yet hard-coded scripts for output and +transaction validation on layer 1.** The general full-scale quasi Turing-complete programmability of the IOTA ledger is +achieved by extending the ledger state transition function with layer 2 smart contract chains. This not only makes it +possible to keep layer 1 scalable and feeless, but also allows to support any type of virtual machine on layer 2 to +program advanced business logic and features. + +Below, several new output types are discussed that implement their own configurable script logic. They can be viewed as +UTXO state machines in which the state of the machine is encoded as data inside the output. The state transition rules +are defined by the output type and by the parameters chosen upon deployment. + +## Data Types & Subschema Notation + +Data types and subschemas used throughout this TIP are defined in [draft TIP-21](https://github.com/iotaledger/tips/pull/41). + +## Global Protocol Parameters + +Global protocol parameters used throughout this TIP are defined in [draft TIP-22](https://github.com/iotaledger/tips/pull/43). + +## Transaction Payload Changes + +The new output types and unlocking mechanisms require new transaction validation rules, furthermore some protocol rules +have been modified compared to +Chrysalis Part 2 Transaction Payload [TIP-7](../TIP-0007/tip-0007.md). + +[Draft TIP-20](https://github.com/iotaledger/tips/pull/40) replaces aforementioned +TIP-7 with the new transaction layout and validation rules. The updated version is the basis for +output validation in this TIP. + +### Summary of Changes + +- Deprecating SigLockedSingleOutput and SigLockedDustAllowanceOutput. + - The new dust protection mechanism does not need a distinct output type, therefore + SigLockedDustAllowanceOutput will be deprecated. One alternative is that during migration to the new + protocol version, all dust outputs sitting on an address will be merged into a Basic Output together + with their respective SigLockedDustAllowanceOutputs to create the snapshot for the updated protocol. + The exact migration strategy will be decided later. +- Adding new [output types](#output-design) to _Transaction Payload_. +- Adding new [unlock types](#unlocking-chain-script-locked-outputs) to _Transaction Payload_. +- Inputs and Outputs of a transaction become a list instead of a set. Binary duplicate inputs are not + allowed as they anyway mean double-spends, but binary duplicate outputs are allowed. +- There can be many outputs created to the same address in the transaction. +- Confirming milestone supplies notion of time to semantic transaction validation. + +## New Concepts + +New output types add new features to the protocol and hence new transaction validation rules. While some of these new +features are specifically tied to one output type, some are general, LEGO like building blocks that may be put in +several types of outputs. + +Below is a summary of such new features and the validation rules they introduce. + +### Native Tokens in Outputs + +Outputs are records in the UTXO ledger that track ownership of funds. Thus, each output must be able to specify which +funds it holds. With the addition of the Native Tokenization Framework, outputs may also carry user defined native +tokens, that is, tokens that are not IOTA coins but were minted by foundries and are tracked in the very same ledger. +Therefore, **every output must be able to hold not only IOTA coins, but also native tokens**. + +Dust protection applies to all outputs, therefore it is not possible for outputs to hold only native tokens, the +storage deposit requirements must be covered via IOTA coins. + +User defined tokens are called Native Tokens on protocol level. The maximum supply of a particular native token +is defined by the representation chosen on protocol level for defining their amounts in outputs. Since native tokens +are also a vehicle to wrap layer 2 tokens into layer 1 tokens, the chosen representation must take into account the +maximum possible supply of layer 2 tokens. Solidity, the most popular smart contract language defines the +maximum supply of an ERC-20 token as `MaxUint256`, therefore it should be possible to represent such huge amount of +assets on layer 1. + +Outputs must have the following fields to define the balance of native tokens they hold: + + + + + + + + + + + + + + + + +
NameTypeDescription
Native Tokens Countuint8The number of native tokens present in the output.
Native Tokens optAnyOf +
+ Native Token + + + + + + + + + + + + + + + + +
NameTypeDescription
Token IDByteArray[38] + Identifier of the native token. Derivation defined here. +
Amountuint256 + Amount of tokens. +
+
+
+ +#### Additional syntactic output validation rules: + +- `Native Tokens` must be lexicographically sorted based on `Token ID`. +- Each Native Token must be unique in the set of `Native Tokens` based on its `Token ID`. No duplicates are + allowed. +- `Amount` of any Native Token must not be `0`. + +#### Additional semantic transaction validation rules: + +- The transaction is balanced in terms of native tokens, that is, the sum of native token balances in consumed outputs + equals that of the created outputs. +- When the transaction is **imbalanced** and there is a surplus of native tokens on the: + - **output side of the transaction:** the foundry outputs controlling outstanding native token balances must be present in the transaction. The validation of the foundry output(s) determines if the minting operations are valid. + - **input side of the transaction:** the transaction destroys tokens. The presence and validation of the foundry outputs of the native tokens determines whether the tokens are burned (removed from the ledger) or melted in the foundry. + +### New Functionalities in Outputs + +The programmability of outputs opens the door for implementing new functionalities for the base protocol. While some outputs +were specifically designed for such new features, some are optional additions that may be used with any outputs that +support them. + +These new functionalities are grouped into two categories: + - **Unlock Conditions** and + - simple **Features**. + +The [Output Design](#output-design) section lists all supported Unlock Conditions and Features for +each output type. + +#### Unlock Conditions + +New output features that introduce unlocking conditions, that is, they define constraints on how the output can +be unlocked and spent, are grouped under the field Unlock Conditions. + +Each output **must not contain more than one unlock condition of each type** and not all unlock condition types are +supported for each output type. + +##### Address Unlock Condition + +It is merely a layout change that the previously defined `Address` field of outputs ([TIP-7](../TIP-0007/tip-0007.md)) +is represented as an Address Unlock Condition. Unlocking an Ed25519 Address doesn't change, it has to +be performed via a Signature Unlock in a transaction by signing the hash of the transaction essence. +Transaction validation rules are detailed in [draft TIP-20](https://github.com/iotaledger/tips/pull/40). + +New additions are the Alias Address and NFT Address types, which have to be unlocked with their +corresponding unlocks, as defined in [Unlocking Chain Script Locked Outputs](#unlocking-chain-script-locked-outputs). + +
+Address Unlock +
+ Defines the Address that owns this output, that is, it can unlock it with the proper Unlock in a + transaction. +
+
+ + + + + + + + + + + + + + + + +
NameTypeDescription
Unlock Condition Typeuint8 + Set to value 0 to denote an Address Unlock Condition. +
Address +
+ Ed25519 Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 0 to denote an Ed25519 Address. +
PubKeyHashByteArray[32]The raw bytes of the Ed25519 address which is a BLAKE2b-256 hash of the Ed25519 public key.
+
+
+ Alias Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 8 to denote an Alias Address. +
Alias IDByteArray[32]The raw bytes of the Alias ID which is the BLAKE2b-256 hash of the outputID that created it.
+
+
+ NFT Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 16 to denote an NFT Address. +
NFT IDByteArray[32]The raw bytes of the NFT ID which is the BLAKE2b-256 hash of the outputID that created it.
+
+
+ +| :information_source: Good to know about address format | +|---------------------------------------------------------| + +The Address Type byte of a raw address has an effect on the starting character of the bech32 encoded address, +which is the recommended address format for user facing applications. + +A usual bech32 encoded mainnet address starts with `iota1`, and continues with the bech32 encoded bytes of the address. +By choosing Address Type as a multiple of 8 for different address types, the first character after the `1` +separator in the bech32 address will always be different. + +| Address | Type Byte as `uint8` | Bech32 Encoded | +|---------|----------------------|----------------| +| Ed25519 | 0 | iota1**q**... | +| Alias | 8 | iota1**p**... | +| NFT | 16 | iota1**z**... | + +A user can identify by looking at the address whether it is a signature backed address, a smart contract chain account +or an NFT address. + +##### Storage Deposit Return Unlock Condition + +This unlock condition is employed to achieve conditional sending. An output that has +Storage Deposit Return Unlock Condition specified can only be consumed in a transaction that deposits +`Return Amount` IOTA coins into `Return Address`. When several of such outputs are consumed, their return amounts per +`Return Addresses` are summed up and the output side must deposit this total sum per `Return Address`. + +###### Additional syntactic transaction validation rule: + +- `Minimum Storage Deposit` is the storage deposit in the base currency required for a Basic Output that only + has an Address Unlock Condition, no additional unlock conditions, no features and + no native tokens. +- It must hold true, that `Minimum Storage Deposit` ≤ `Return Amount` ≤ `Amount`. + +###### Additional semantic transaction validation rule: + +- An output that has Storage Deposit Return Unlock Condition specified must only be consumed and unlocked in a + transaction that deposits `Return Amount` IOTA coins to `Return Address` via one or more outputs that: + - are of type [Basic Output](#basic-output), + - have only an [Address Unlock Condition](#address-unlock-condition) defined, + - have no [Native Tokens](#native-tokens-in-outputs), and + - have no [Features](#features). +- When several outputs with Storage Deposit Return Unlock Condition and the same `Return Address` are consumed, + their return amounts per `Return Addresses` are summed up and the output side of the transaction must deposit + _at least_ this total sum per `Return Address` via output(s) that satisfy the previous condition. + +
+Storage Deposit Return Unlock Condition +
+ Defines the amount of IOTAs used as storage deposit that have to be returned to Return Address. +
+
+ + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
Unlock Condition Typeuint8 + Set to value 1 to denote a Storage Deposit Return Unlock Condition. +
Return AddressoneOf +
+ Ed25519 Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 0 to denote an Ed25519 Address. +
PubKeyHashByteArray[32]The raw bytes of the Ed25519 address which is a BLAKE2b-256 hash of the Ed25519 public key.
+
+
+ Alias Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 8 to denote an Alias Address. +
Alias IDByteArray[32]The raw bytes of the Alias ID which is the BLAKE2b-256 hash of the outputID that created it.
+
+
+ NFT Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 16 to denote an NFT Address. +
NFT IDByteArray[32]The raw bytes of the NFT ID which is the BLAKE2b-256 hash of the outputID that created it.
+
+
Return Amountuint64 + Amount of IOTA coins the consuming transaction should deposit to Return Address. +
+ +This unlock condition makes it possible to send small amounts of IOTA coins or native tokens to addresses without having +to lose control of the required storage deposit. It is also a vehicle to send on-chain requests to ISCP chains that do not +require fees. To prevent the receiving party from blocking access to the storage deposit, it is advised to be used +together with the [Expiration Unlock Conditions](#expiration-unlock-conditions). The receiving party then has a sender-defined +time window to agree to the transfer by consuming the output, or the sender regains total control after expiration. + +##### Timelock Unlock Condition + +The notion of time in the Tangle is introduced via milestones. Each milestone +[carries the current unix timestamp](../TIP-0008/tip-0008.md#structure) +corresponding to that milestone index. Whenever a new milestone appears, nodes perform the white-flag ordering and transaction +validation on its past cone. The timestamp of the confirming milestone provide the time as an input parameter to +transaction validation. + +An output that contains a Timelock Unlock Condition can not be unlocked before the specified timelock has +expired. The timelock is expired when the timestamp of the confirming milestone is equal or past the timestamp defined +in the Timelock Unlock Condition. + +###### Additional syntactic transaction validation rules: +- `Unix Time` field of a Timelock Unlock Condition must be > `0`. +###### Additional semantic transaction validation rules: +- An output that has Timelock Unlock Condition specified must only be consumed and unlocked in a + transaction, if the timestamp of the confirming milestone is equal or past the `Unix Time` specified in the unlock + condition. + +
+Timelock Unlock Condition +
+ Defines a unix timestamp until which the output can not be unlocked. +
+
+ + + + + + + + + + + + + + + + + +
NameTypeDescription
Unlock Condition Typeuint8 + Set to value 2 to denote a Timelock Unlock Condition. +
Unix Timeuint32 + Unix time (seconds since Unix epoch) starting from which the output can be consumed. +
+ +##### Expiration Unlock Condition + +The expiration feature of outputs makes it possible for the return address to reclaim an output after a given expiration +time has been passed. The expiration can be specified as a unix timestamp. + +The expiration feature can be viewed as an opt-in receive feature, because the recipient loses access to the received +funds after the output expires, while the return address specified by the sender regains control over them. This feature +is a big help for on-chain smart contract requests. Those that have expiration set and are sent to dormant smart contract +chains can be recovered by their senders. Not to mention the possibility to time requests by specifying both a +timelock and an expiration unlock condition. + +###### Additional syntactic transaction validation rules: +- `Unix Time` field of an Expiration Unlock Condition must be > `0`. + +###### Additional semantic transaction validation rules: +- An output that has Expiration Unlock Condition set must only be consumed and + unlocked by the target `Address` (defined in Address Unlock Condition) in a transaction that has a confirming + milestone timestamp earlier than the `Unix Time` defined in the unlock condition. +- An output that has Expiration Unlock Condition set must only be consumed and unlocked by the `Return Address` + in a transaction that has a confirming milestone timestamp same or later than the `Unix Time` defined in the unlock + condition. +- Semantic validation of an output that has Expiration Unlock Condition set and is unlocked by the + `Return Address` must ignore: + - [Semantic validation of Storage Deposit Return Unlock Condition](#storage-deposit-return-unlock-condition) if present. + +The following table summarizes the outcome of syntactic and semantic validation rules with respect to which account +is allowed to unlock the output containing the Expiration Unlock Condition: + +| Milestone Unix Timestamp Condition | Outcome | +|-----------------------------------------------------|-----------------------------------------------| +| `Unix Time` = `0` | Output and containing transaction is invalid. | +| `Unix Time` > `Confirming Milestone Unix Timestamp` | Unlockable by `Address` | +| `Unix Time` ≤ `Confirming Milestone Unix Timestamp` | Unlockable by `Return Address` | + +
+Expiration Unlock Condition +
+ Defines a unix time until which only Address, defined in Address Unlock Condition, is allowed to + unlock the output. After the unix time is reached/passed, only Return Address can unlock it. +
+
+ + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
Unlock Condition Typeuint8 + Set to value 3 to denote a Expiration Unlock Condition. +
Return Address oneOf +
+ Ed25519 Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 0 to denote an Ed25519 Address. +
PubKeyHashByteArray[32]The raw bytes of the Ed25519 address which is a BLAKE2b-256 hash of the Ed25519 public key.
+
+
+ Alias Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 8 to denote an Alias Address. +
Alias IDByteArray[32]The raw bytes of the Alias ID which is the BLAKE2b-256 hash of the outputID that created it.
+
+
+ NFT Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 16 to denote an NFT Address. +
NFT IDByteArray[32]The raw bytes of the NFT ID which is the BLAKE2b-256 hash of the outputID that created it.
+
+
Unix Timeuint32 + Before this unix time, Address Unlock Condition is allowed to unlock the output, after that only the address defined in Return Address. +
+ +##### State Controller Address Unlock Condition + +An unlock condition defined solely for Alias Output. It is functionally equivalent to an +Address Unlock Condition, however there are additional transition constraints defined for the Alias UTXO state +machine that can only be carried out by the `State Controller Address`, hence the distinct unlock condition type. + +
+State Controller Address Unlock +
+ Defines the State Controller Address that owns this output, that is, it can unlock it with the proper Unlock in a + transaction that state transitions the alias output. +
+
+ + + + + + + + + + + + + + + + +
NameTypeDescription
Unlock Condition Typeuint8 + Set to value 4 to denote an State Controller Address Unlock Condition. +
Address +
+ Ed25519 Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 0 to denote an Ed25519 Address. +
PubKeyHashByteArray[32]The raw bytes of the Ed25519 address which is a BLAKE2b-256 hash of the Ed25519 public key.
+
+
+ Alias Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 8 to denote an Alias Address. +
Alias IDByteArray[32]The raw bytes of the Alias ID which is the BLAKE2b-256 hash of the outputID that created it.
+
+
+ NFT Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 16 to denote an NFT Address. +
NFT IDByteArray[32]The raw bytes of the NFT ID which is the BLAKE2b-256 hash of the outputID that created it.
+
+
+ +The additional constraints are defined in [Alias Output Design](#alias-output) section. + +##### Governor Address Unlock Condition + +An unlock condition defined solely for Alias Output. It is functionally equivalent to an +Address Unlock Condition, however there are additional transition constraints defined for the Alias UTXO state +machine that can only be carried out by the `Governor Address`, hence the distinct unlock condition type. + +
+Governor Address Unlock +
+ Defines the Governor Address that owns this output, that is, it can unlock it with the proper Unlock in a + transaction that governance transitions the alias output. +
+
+ + + + + + + + + + + + + + + + +
NameTypeDescription
Unlock Condition Typeuint8 + Set to value 5 to denote an Governor Address Unlock Condition. +
Address +
+ Ed25519 Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 0 to denote an Ed25519 Address. +
PubKeyHashByteArray[32]The raw bytes of the Ed25519 address which is a BLAKE2b-256 hash of the Ed25519 public key.
+
+
+ Alias Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 8 to denote an Alias Address. +
Alias IDByteArray[32]The raw bytes of the Alias ID which is the BLAKE2b-256 hash of the outputID that created it.
+
+
+ NFT Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 16 to denote an NFT Address. +
NFT IDByteArray[32]The raw bytes of the NFT ID which is the BLAKE2b-256 hash of the outputID that created it.
+
+
+ +The additional constraints are defined in [Alias Output Design](#alias-output) section. + +##### Immutable Alias Address Unlock Condition + +An unlock condition defined for chain constrained UTXOs that can only be unlocked by a permanent Alias Address. + +Output unlocking is functionally equivalent to an Address Unlock Condition with an Alias Address, +however there are additional transition constraints: the next state of the UTXO machine must have the same +Immutable Alias Address Unlock Condition. + +
+Immutable Alias Address Unlock Condition +
+ Defines the permanent Alias Address that owns this output. +
+
+ + + + + + + + + + + + + + + + +
NameTypeDescription
Unlock Condition Typeuint8 + Set to value 6 to denote an Immutable Alias Address Unlock Condition. +
Address +
+ Alias Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 8 to denote an Alias Address. +
Alias IDByteArray[32]The raw bytes of the Alias ID which is the BLAKE2b-256 hash of the outputID that created it.
+
+
+ +###### Additional semantic transaction validation rules: + - The output must be unlocked with an [Alias Unlock](#alias-unlock-semantic-validation). + - The next state of the UTXO state machine must have the same Immutable Alias Address Unlock Condition defined. + +### Features + +New output features that do not introduce unlocking conditions, but rather add new functionality and add constraints on +output creation are grouped under Features. + +Each output **must not contain more than one feature of each type** and not all feature types are supported for each output +type. + +##### Sender Feature + +Every transaction consumes several elements from the UTXO set and creates new outputs. However, certain applications +(smart contracts) require to associate each output with exactly one sender address. Here, the sender feature is used to +specify the validated sender of an output. + +Outputs that support the Sender Feature may specify a `Sender` address which is validated by the protocol during +transaction validation. + +###### Additional semantic transaction validation rule: +- The Sender Feature, and hence the output and transaction that contain it, is valid, if and only if `Sender` address is unlocked in the transaction. Based on the `Address Type`, an address is unlocked in the transaction, if and only if: + - Ed25519 Address: + - The Unlock of the first output in the transaction that contains the address is a valid Signature Unlock with respect to the address. + - Alias Address: + - The Alias Output that defines the address is **state transitioned** in the transaction. A governance transition does not unlock the address. + - NFT Address: + - The NFT Output that defines the address is consumed as input in the transaction. + +
+Sender Feature +
+ Identifies the validated sender of the output. +
+
+ + + + + + + + + + + + + + + + +
NameTypeDescription
Feature Typeuint8 + Set to value 0 to denote a Sender Feature. +
Sender oneOf +
+ Ed25519 Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 0 to denote an Ed25519 Address. +
PubKeyHashByteArray[32]The raw bytes of the Ed25519 address which is a BLAKE2b-256 hash of the Ed25519 public key.
+
+
+ Alias Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 8 to denote an Alias Address. +
Alias IDByteArray[32]The raw bytes of the Alias ID which is the BLAKE2b-256 hash of the outputID that created it.
+
+
+ NFT Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 16 to denote an NFT Address. +
NFT IDByteArray[32]The raw bytes of the NFT ID which is the BLAKE2b-256 hash of the outputID that created it.
+
+
+ +##### Issuer Feature + +The issuer feature is a special case of the sender feature that is only supported by outputs that implement a UTXO state +machine with [chain constraint](#chain-constraint-in-utxo) (alias, NFT). +Only when the state machine is created (e.g. minted) it is checked during transaction validation that an output +corresponding to the `Issuer` address is consumed. In every future transition of the state machine, it is instead +checked that the issuer feature is still present and unchanged. + +###### Additional semantic transaction validation rule: +- When an Issuer Feature is present in an output representing the initial state of an UTXO state machine, the + transaction that contains this output is valid, if and only if `Issuer` address is unlocked in the transaction. Based on the `Address Type`, an address is unlocked in the transaction, if and only if: + - Ed25519 Address: + - The Unlock of the first output in the transaction that contains the address is a valid Signature Unlock with respect to the address. + - Alias Address: + - The Alias Output that defines the address is **state transitioned** in the transaction. A governance transition does not unlock the address. + - NFT Address: + - The NFT Output that defines the address is consumed as input in the transaction. + +The main use case is proving authenticity of NFTs. Whenever an NFT is minted as an NFT output, the creator (issuer) can +fill the Issuer Feature with their address that they have to unlock in the transaction. Issuers then can publicly +disclose their addresses to prove the authenticity of the NFT once it is in circulation. + +
+Issuer Feature +
+ Identifies the validated issuer of the UTXO state machine. +
+
+ + + + + + + + + + + + + + + + +
NameTypeDescription
Feature Typeuint8 + Set to value 1 to denote an Issuer Feature. +
Issuer oneOf +
+ Ed25519 Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 0 to denote an Ed25519 Address. +
PubKeyHashByteArray[32]The raw bytes of the Ed25519 address which is a BLAKE2b-256 hash of the Ed25519 public key.
+
+
+ Alias Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 8 to denote an Alias Address. +
Alias IDByteArray[32]The raw bytes of the Alias ID which is the BLAKE2b-256 hash of the outputID that created it.
+
+
+ NFT Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 16 to denote an NFT Address. +
NFT IDByteArray[32]The raw bytes of the NFT ID which is the BLAKE2b-256 hash of the outputID that created it.
+
+
+ +Whenever a chain account mints an NFT on layer 1 on behalf of some user, the `Issuer` field can only contain the +chain's address, since user does not sign the layer 1 transaction. As a consequence, artist would have to mint NFTs +themselves on layer 1 and then deposit it to chains if they want to place their own address in the `Issuer` field. + +##### Metadata Feature + +Outputs may carry additional data with them that is interpreted by higher layer applications built on the Tangle. The +protocol treats this metadata as pure binary data, it has no effect on the validity of an output except that it +increases the required storage deposit. ISC is a great example of a higher layer protocol that makes use of +Metadata Feature: smart contract request parameters are encoded in the metadata field of outputs. + +###### Additional syntactic transaction validation rules: +- An output with Metadata Feature is valid, if and only if 0 < `length(Data)` ≤ `Max Metadata Length`. + +
+Metadata Feature +
+ Defines metadata (arbitrary binary data) that will be stored in the output. +
+
+ + + + + + + + + + + + + + + + + +
NameTypeDescription
Feature Typeuint8 + Set to value 2 to denote a Metadata Feature. +
Data(uint16)ByteArrayBinary data. A leading uint16 denotes its length.
+ +#### Tag Feature + +A Tag Feature makes it possible to tag outputs with an index, so they can be retrieved through an indexer API not +only by their address, but also based on the the `Tag`. **The combination of a Tag Feature, a +Metadata Feature and a Sender Feature makes it possible to retrieve data associated to an address and stored +in outputs that were created by a specific party (`Sender`) for a specific purpose (`Tag`).** + +An example use case is voting on the Tangle via the [participation](https://github.com/iota-community/treasury/blob/main/specifications/hornet-participation-plugin.md) plugin. + +Storing indexed data in outputs however incurs greater storage deposit for such outputs, because they create look-up +entries in nodes' databases. + +##### Additional syntactic transaction validation rules: +- An output with Tag Feature is valid, if and only if 0 < `length(Tag)` ≤ + `Max Tag Length`. + +
+Tag Feature +
+ Defines an indexation tag to which the output can be indexed by additional node plugins. +
+
+ + + + + + + + + + + + + + + + + +
NameTypeDescription
Feature Typeuint8 + Set to value 3 to denote a Tag Feature. +
Tag(uint8)ByteArrayBinary indexation tag. A leading uint8 denotes its length.
+ +### Chain Constraint in UTXO + +Previously created transaction outputs are destroyed when they are consumed in a subsequent transaction as an input. +The chain constraint makes it possible to **carry the UTXO state machine state encoded in outputs across transactions.** +When an output with chain constraint is consumed, that transaction has to create a single subsequent output that +carries the state forward. The **state can be updated according to the transition rules defined for the given type of +output and its current state**. As a consequence, each such output has a unique successor, and together they form a path +or *chain* in the graph induced by the UTXO spends. Each chain is identified by its globally unique identifier. + +![](chain-constraint.png) + +Alias outputs, foundry outputs and NFT outputs all use this chain constraint concept and define their own unique +identifiers. + +## Output Design + +In the following, we define four new output types. They are all designed with specific use cases in mind: +- **Basic Output**: transfer of funds with attached metadata and optional spending restrictions. Main use cases are + on-ledger ISC requests, native asset transfers and indexed data storage in the UTXO ledger. +- **Alias Output**: representing ISC chain accounts on L1 that can process requests and transfer funds. +- **Foundry Output**: supply control of user defined native tokens. A vehicle for cross-chain asset transfers and asset + wrapping. +- **NFT Output**: an output that represents a Non-fungible token with attached metadata and proof-of-origin. A NFT is + represented as an output so that the token and metadata are transferred together, for example as a smart contract + requests. NFTs are possible to implement with native tokens as well, but then ownership of the token does not mean + ownership of the foundry that holds its metadata. + +The validation of outputs is part of the transaction validation process. There are two levels of validation for +transactions: syntactic and semantic validation. The former validates the structure of the transaction (and outputs), +while the latter validates whether protocol rules are respected in the semantic context of the transaction. Outputs +hence are validated on both levels: +1. **Transaction Syntactic Validation**: validates the structure of each output created by the transaction. +2. **Transaction Semantic Validation**: + - **For consumed outputs**: validates whether the output can be unlocked in a transaction given the semantic + transaction context. + - **For created outputs**: validates whether the output can be created in a transaction given the semantic + transaction context. + +Each new output type may add its own validation rules which become part of the transaction validation rules if the +output is placed inside a transaction. Unlock Conditions and Features described previously also add +constraints to transaction validation when they are placed in outputs. + +## Basic Output + +Basic Output can hold native tokens and might have several unlock conditions and optional features. The +combination of several features provide the base functionality for the output to be used as an on-ledger smart contract +request: +- Verified `Sender`, +- Attached `Metadata` that can encode the request payload for layer 2, +- `Return Amount` to get back the storage deposit, +- `Timelock` to be able to time requests, +- `Expiration` to recover funds in case of chain inactivity. + +Besides, the Tag Feature is a tool to store arbitrary, indexed data with verified origin in the ledger. + +Note, that a Basic Output in its simplest possible form with only an Address Unlock Condition and +without features or native tokens is functionally equivalent to a SigLockedSingleOutput: it has an address +and an IOTA balance. Therefore, +aforementioned output type, that was [introduced for Chrysalis Part 2 via TIP-7](../TIP-0007/tip-0007.md) +is deprecated with the replacement of the [draft TIP-20 Transaction Payload](https://github.com/iotaledger/tips/pull/40). + + +
+ Basic Output +
+ Describes a basic output with optional features. +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
Output Typeuint8 + Set to value 3 to denote a Basic Output. +
Amountuint64The amount of IOTA coins to held by the output.
Native Tokens Countuint8The number of native tokens held by the output.
Native Tokens optAnyOf +
+ Native Token + + + + + + + + + + + + + + + + +
NameTypeDescription
Token IDByteArray[38] + Identifier of the native token. +
Amountuint256 + Amount of native tokens of the given Token ID. +
+
+
Unlock Conditions Countuint8The number of unlock conditions following.
Unlock Conditions atMostOneOfEach +
+ Address Unlock Condition + + + + + + + + + + + + + + + +
NameTypeDescription
Unlock Condition Typeuint8 + Set to value 0 to denote an Address Unlock Condition. +
Address +
+ Ed25519 Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 0 to denote an Ed25519 Address. +
PubKeyHashByteArray[32]The raw bytes of the Ed25519 address which is a BLAKE2b-256 hash of the Ed25519 public key.
+
+
+ Alias Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 8 to denote an Alias Address. +
Alias IDByteArray[32]The raw bytes of the Alias ID which is the BLAKE2b-256 hash of the outputID that created it.
+
+
+ NFT Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 16 to denote an NFT Address. +
NFT IDByteArray[32]The raw bytes of the NFT ID which is the BLAKE2b-256 hash of the outputID that created it.
+
+
+
+
+ Storage Deposit Return Unlock Condition +
+ Defines the amount of IOTAs used as storage deposit that have to be returned to Return Address. +
+ + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
Unlock Condition Typeuint8 + Set to value 1 to denote a Storage Deposit Return Unlock Condition. +
Return Address oneOf +
+ Ed25519 Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 0 to denote an Ed25519 Address. +
PubKeyHashByteArray[32]The raw bytes of the Ed25519 address which is a BLAKE2b-256 hash of the Ed25519 public key.
+
+
+ Alias Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 8 to denote an Alias Address. +
Alias IDByteArray[32]The raw bytes of the Alias ID which is the BLAKE2b-256 hash of the outputID that created it.
+
+
+ NFT Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 16 to denote an NFT Address. +
NFT IDByteArray[32]The raw bytes of the NFT ID which is the BLAKE2b-256 hash of the outputID that created it.
+
+
Return Amountuint64 + Amount of IOTA coins the consuming transaction should deposit to the address defined in Return Address. +
+
+
+ Timelock Unlock Condition +
+ Defines a unix timestamp until which the output can not be unlocked. +
+ + + + + + + + + + + + + + + + +
NameTypeDescription
Unlock Condition Typeuint8 + Set to value 2 to denote a Timelock Unlock Condition. +
Unix Timeuint32 + Unix time (seconds since Unix epoch) starting from which the output can be consumed. +
+
+
+ Expiration Unlock Condition +
+ Defines a unix time until which only Address, defined in Address Unlock Condition, is allowed to + unlock the output. After the unix time is reached or passed, only Return Address can unlock it. +
+ + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
Unlock Condition Typeuint8 + Set to value 3 to denote a Expiration Unlock Condition. +
Return Address oneOf +
+ Ed25519 Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 0 to denote an Ed25519 Address. +
PubKeyHashByteArray[32]The raw bytes of the Ed25519 address which is a BLAKE2b-256 hash of the Ed25519 public key.
+
+
+ Alias Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 8 to denote an Alias Address. +
Alias IDByteArray[32]The raw bytes of the Alias ID which is the BLAKE2b-256 hash of the outputID that created it.
+
+
+ NFT Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 16 to denote an NFT Address. +
NFT IDByteArray[32]The raw bytes of the NFT ID which is the BLAKE2b-256 hash of the outputID that created it.
+
+
Unix Timeuint32 + Before this unix time, Address Unlock Condition is allowed to unlock the output, after that only the address defined in Return Address. +
+
+
Features Countuint8The number of features following.
Features atMostOneOfEach +
+ Sender Feature +
+ Identifies the validated sender of the output. +
+ + + + + + + + + + + + + + + +
NameTypeDescription
Feature Typeuint8 + Set to value 0 to denote a Sender Feature. +
Sender oneOf +
+ Ed25519 Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 0 to denote an Ed25519 Address. +
PubKeyHashByteArray[32]The raw bytes of the Ed25519 address which is a BLAKE2b-256 hash of the Ed25519 public key.
+
+
+ Alias Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 8 to denote an Alias Address. +
Alias IDByteArray[32]The raw bytes of the Alias ID which is the BLAKE2b-256 hash of the outputID that created it.
+
+
+ NFT Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 16 to denote an NFT Address. +
NFT IDByteArray[32]The raw bytes of the NFT ID which is the BLAKE2b-256 hash of the outputID that created it.
+
+
+
+
+ Metadata Feature +
+ Defines metadata (arbitrary binary data) that will be stored in the output. +
+ + + + + + + + + + + + + + + + +
NameTypeDescription
Feature Typeuint8 + Set to value 2 to denote a Metadata Feature. +
Data(uint16)ByteArrayBinary data. A leading uint16 denotes its length.
+
+
+ Tag Feature +
+ Defines an indexation tag to which the output can be indexed by additional node plugins. +
+ + + + + + + + + + + + + + + + +
NameTypeDescription
Feature Typeuint8 + Set to value 3 to denote a Tag Feature. +
Tag(uint8)ByteArrayBinary indexation data. A leading uint8 denotes its length.
+
+
+ + + +### Additional Transaction Syntactic Validation Rules + +- `Amount` field must fulfill the dust protection requirements and must not be `0`. +- `Amount` field must be ≤ `Max IOTA Supply`. +- `Native Tokens Count` must not be greater than `Max Native Tokens Count`. +- `Native Tokens` must be lexicographically sorted based on `Token ID`. +- Each Native Token must be unique in the set of `Native Tokens` based on its `Token ID`. No duplicates are + allowed. +- `Amount` of any Native Token must not be `0`. +- It must hold true that `1` ≤ `Unlock Conditions Count` ≤ `4`. +- `Unlock Condition Type` of an Unlock Condition must define one of the following types: + - Address Unlock Condition + - Storage Deposit Return Unlock Condition + - Timelock Unlock Condition + - Expiration Unlock Condition +- Unlock Conditions must be sorted in ascending order based on their `Unlock Condition Type`. +- Syntactic validation of all present unlock conditions must pass. +- Address Unlock Condition must be present. +- It must hold true that `0` ≤ `Features Count` ≤ `3`. +- `Feature Type` of a Feature must define one of the following types: + - Sender Feature + - Metadata Feature + - Tag Feature +- Features must be sorted in ascending order based on their `Feature Type`. +- Syntactic validation of all present features must pass. + +### Additional Transaction Semantic Validation Rules + +#### Consumed Outputs + +- The unlock of the input must correspond to `Address` field in the Address Unlock Condition and the + unlock must be valid. +- The unlock is valid if and only if all unlock conditions and features present in the output validate. + +#### Created Outputs + +- All Unlock Condition imposed transaction validation criteria must be fulfilled. +- All Feature imposed transaction validation criteria must be fulfilled. + +## Alias Output + +The Alias Output is a specific implementation of a UTXO state machine. `Alias ID`, the unique identifier of an +instance of the deployed state machine, is generated deterministically by the protocol and is not allowed to change in +any future state transitions. + +Alias Output represents an alias account in the ledger with two control levels and a permanent +Alias Address. The account owns other outputs that are locked under Alias Address. The account keeps +track of state transitions (`State Index` counter), controlled foundries (`Foundry Counter`) and anchors the layer 2 +state as metadata into the UTXO ledger. + + +
+ Alias Output +
+ Describes an alias account in the ledger that can be controlled by the state and governance controllers. +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
Output Typeuint8 + Set to value 4 to denote a Alias Output. +
Amountuint64The amount of IOTA coins held by the output.
Native Tokens Countuint8The number of native tokens held by the output.
Native Tokens optAnyOf +
+ Native Token + + + + + + + + + + + + + + + + +
NameTypeDescription
Token IDByteArray[38] + Identifier of the native token. +
Amountuint256 + Amount of native tokens of the given Token ID. +
+
+
Alias IDByteArray[32]Unique identifier of the alias, which is the BLAKE2b-256 hash of the Output ID that created it. Alias Address = Alias Address Type || Alias ID
State Indexuint32A counter that must increase by 1 every time the alias is state transitioned.
State Metadata(uint16)ByteArrayMetadata that can only be changed by the state controller. A leading uint16 denotes its length.
Foundry Counteruint32A counter that denotes the number of foundries created by this alias account.
Unlock Conditions Countuint8The number of unlock conditions following.
Unlock Conditions atMostOneOfEach +
+ State Controller Address Unlock Condition + + + + + + + + + + + + + + + +
NameTypeDescription
Unlock Condition Typeuint8 + Set to value 4 to denote an State Controller Address Unlock Condition. +
Address +
+ Ed25519 Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 0 to denote an Ed25519 Address. +
PubKeyHashByteArray[32]The raw bytes of the Ed25519 address which is a BLAKE2b-256 hash of the Ed25519 public key.
+
+
+ Alias Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 8 to denote an Alias Address. +
Alias IDByteArray[32]The raw bytes of the Alias ID which is the BLAKE2b-256 hash of the outputID that created it.
+
+
+ NFT Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 16 to denote an NFT Address. +
NFT IDByteArray[32]The raw bytes of the NFT ID which is the BLAKE2b-256 hash of the outputID that created it.
+
+
+
+
+ Governor Address Unlock Condition + + + + + + + + + + + + + + + +
NameTypeDescription
Unlock Condition Typeuint8 + Set to value 5 to denote an Governor Address Unlock Condition. +
Address +
+ Ed25519 Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 0 to denote an Ed25519 Address. +
PubKeyHashByteArray[32]The raw bytes of the Ed25519 address which is a BLAKE2b-256 hash of the Ed25519 public key.
+
+
+ Alias Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 8 to denote an Alias Address. +
Alias IDByteArray[32]The raw bytes of the Alias ID which is the BLAKE2b-256 hash of the outputID that created it.
+
+
+ NFT Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 16 to denote an NFT Address. +
NFT IDByteArray[32]The raw bytes of the NFT ID which is the BLAKE2b-256 hash of the outputID that created it.
+
+
+
+
Features Countuint8The number of features following.
Features atMostOneOfEach +
+ Sender Feature +
+ Identifies the validated sender of the output. +
+ + + + + + + + + + + + + + + +
NameTypeDescription
Feature Typeuint8 + Set to value 0 to denote a Sender Feature. +
Sender oneOf +
+ Ed25519 Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 0 to denote an Ed25519 Address. +
PubKeyHashByteArray[32]The raw bytes of the Ed25519 address which is a BLAKE2b-256 hash of the Ed25519 public key.
+
+
+ Alias Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 8 to denote an Alias Address. +
Alias IDByteArray[32]The raw bytes of the Alias ID which is the BLAKE2b-256 hash of the outputID that created it.
+
+
+ NFT Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 16 to denote an NFT Address. +
NFT IDByteArray[32]The raw bytes of the NFT ID which is the BLAKE2b-256 hash of the outputID that created it.
+
+
+
+
+ Metadata Feature +
+ Defines metadata (arbitrary binary data) that will be stored in the output. +
+ + + + + + + + + + + + + + + + +
NameTypeDescription
Feature Typeuint8 + Set to value 2 to denote a Metadata Feature. +
Data(uint16)ByteArrayBinary data. A leading uint16 denotes its length.
+
+
Immutable Features Countuint8The number of immutable features following. Immutable features are defined upon deployment of the UTXO state machine and are not allowed to change in any future state transition.
Immutable Features atMostOneOfEach +
+ Issuer Feature +
+ Identifies the validated issuer of the UTXO state machine. +
+ + + + + + + + + + + + + + + +
NameTypeDescription
Feature Typeuint8 + Set to value 1 to denote an Issuer Feature. +
Issuer oneOf +
+ Ed25519 Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 0 to denote an Ed25519 Address. +
PubKeyHashByteArray[32]The raw bytes of the Ed25519 address which is a BLAKE2b-256 hash of the Ed25519 public key.
+
+
+ Alias Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 8 to denote an Alias Address. +
Alias IDByteArray[32]The raw bytes of the Alias ID which is the BLAKE2b-256 hash of the outputID that created it.
+
+
+ NFT Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 16 to denote an NFT Address. +
NFT IDByteArray[32]The raw bytes of the NFT ID which is the BLAKE2b-256 hash of the outputID that created it.
+
+
+
+
+ Metadata Feature +
+ Defines metadata (arbitrary binary data) that will be stored in the output. +
+ + + + + + + + + + + + + + + + +
NameTypeDescription
Feature Typeuint8 + Set to value 2 to denote a Metadata Feature. +
Data(uint16)ByteArrayBinary data. A leading uint16 denotes its length.
+
+
+ + + +### Additional Transaction Syntactic Validation Rules + +#### Output Syntactic Validation + +- `Amount` field must fulfill the dust protection requirements and must not be `0`. +- `Amount` field must be ≤ `Max IOTA Supply`. +- `Native Tokens Count` must not be greater than `Max Native Tokens Count`. +- `Native Tokens` must be lexicographically sorted based on `Token ID`. +- Each Native Token must be unique in the set of `Native Tokens` based on its `Token ID`. No duplicates are + allowed. +- `Amount` of any Native Token must not be `0`. +- It must hold true that `Unlock Conditions Count` = `2`. +- `Unlock Condition Type` of an Unlock Condition must define one of the following types: + - State Controller Address Unlock Condition + - Governor Address Unlock Condition +- Unlock Conditions must be sorted in ascending order based on their `Unlock Condition Type`. +- Syntactic validation of all present unlock conditions must pass. +- It must hold true that `0` ≤ `Features Count` ≤ `2`. +- `Feature Type` of a Feature in `Features` must define one of the following types: + - Sender Feature + - Metadata Feature +- It must hold true that `0` ≤ `Immutable Features Count` ≤ `2`. +- `Feature Type` of a Feature in `Immutable Features` must define on of the following types: + - Issuer Feature + - Metadata Feature +- Features must be sorted in ascending order based on their `Feature Type` both in `Features` and `Immutable Features` + fields. +- Syntactic validation of all present features must pass. +- When `Alias ID` is zeroed out, `State Index` and `Foundry Counter` must be `0`. +- `length(State Metadata)` must not be greater than `Max Metadata Length`. +- `Address` of State Controller Address Unlock Condition and `Address` of + Governor Address Unlock Condition must be different from the alias address derived from `Alias ID`. + +### Additional Transaction Semantic Validation Rules + +- Explicit `Alias ID`: `Alias ID` is taken as the value of the `Alias ID` field in the alias output. +- Implicit `Alias ID`: When an alias output is consumed as an input in a transaction and `Alias ID` field is zeroed out + while `State Index` and `Foundry Counter` are zero, take the BLAKE2b-256 hash of the `Output ID` of the input as + `Alias ID`. +- For every non-zero explicit `Alias ID` on the output side there must be a corresponding alias on the input side. The + corresponding alias has the explicit or implicit `Alias ID` equal to that of the alias on the output side. + +#### Consumed Outputs + +Whenever an alias output is consumed in a transaction, it means that the alias is transitioned into its next state. The +**current state** is defined as the **consumed alias output**, while the **next state** is defined as the **alias +output with the same explicit `AliasID` on the output side**. There are two types of transitions: `state transition` +and `governance transition`. +- State transition: + - A state transition is identified by an incremented `State Index`. + - The `State Index` must be incremented by 1. + - The unlock must correspond to the `Address` of State Controller Address Unlock Condition. + - State transition can only change the following fields in the next state: + - `IOTA Amount`, + - `Native Tokens`, + - `State Index`, + - `State Metadata`, + - `Foundry Counter` and + - `Sender Feature` in `Features`. + - `Foundry Counter` field must increase by the number of foundry outputs created in the transaction that map to + `Alias ID`. The `Serial Number` fields of the created foundries must be the set of natural numbers that cover the + open-ended interval between the previous and next values of the `Foundry Counter` field in the alias output. + - The created foundry outputs must be sorted in the list of outputs by their `Serial Number`. Note, that any + foundry that maps to `Alias ID` and has a `Serial Number` that is less or equal to the `Foundry Counter` of the + input alias is ignored when it comes to sorting. + - Newly created foundries in the transaction that map to different aliases can be interleaved when it comes to + sorting. +- Governance transition: + - A governance transition is identified by an unchanged `State Index` in next state. If there is no alias output on + the output side with a corresponding explicit `Alias ID`, the alias is being destroyed. The next state is the + empty state. + - The unlock must correspond to the `Address` of Governor Address Unlock Condition. + - Governance transition must only change the following fields: + - `Address` of State Controller Address Unlock Condition, + - `Address` of Governor Address Unlock Condition, + - `Metadata Feature` and `Sender Feature` in `Features`. + - The `Metadata Feature` is optional, the governor can put additional info about the chain here, for example chain + name, fee structure, supported VMs, list of access nodes, etc., anything that helps clients to fetch info (i.e. + account balances) about the layer 2 network. +- When a consumed alias output has Features defined in `Immutable Features` and a corresponding alias output on the + output side, `Immutable Features` is not allowed to change. + +#### Created Outputs + +- When Issuer Feature is present in an output and explicit `Alias ID` is zeroed out, an input with `Address` field + that corresponds to `Issuer` must be unlocked in the transaction. + +### Notes +- Governor Address Unlock Condition field is made mandatory for now to help formal verification. When the same + entity is defined for state and governance controllers, the output is self governed. Later, for compression reasons, + it is possible to make the governance controller optional and define a self-governed alias as one that does not have + the governance Governor Address Unlock Condition set. +- Indexers and node plugins shall map the alias address of the output derived with `Alias ID` to the regular + address -> output mapping table, so that given an Alias Address, its most recent unspent alias output + can be retrieved. + +## Foundry Output + +A foundry output is an output that **controls the supply of user defined native tokens.** It can mint and melt tokens +according to the **policy** defined in the `Token Scheme` field of the output. Foundries can only be created and +controlled by aliases. + +**The concatenation of `Address` || `Serial Number` || `Token Scheme Type` fields defines the unique identifier of the +foundry, the `Foundry ID`.** + +Upon creation of the foundry, the alias defined in the `Address` field of the +Immutable Alias Address Unlock Condition must be unlocked in the same transaction, and its `Foundry Counter` +field must increment. This incremented value defines `Serial Number`, while the `Token Scheme` can be chosen freely. + +`Foundry ID` is not allowed to change after deployment, therefore neither `Address`, nor `Serial Number` or +`Token Scheme` can change during the lifetime of the foundry. + +Foundries control the supply of tokens with unique identifiers, so-called `Token IDs`. The **`Token ID` of tokens +controlled by a specific foundry is the same as the **`Foundry ID`**. + + +
+ Foundry Output +
+ Describes a foundry output that is controlled by an alias. +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
Output Typeuint8 + Set to value 5 to denote a Foundry Output. +
Amountuint64The amount of IOTA coins to held by the output.
Native Tokens Countuint8The number of different native tokens held by the output.
Native Tokens optAnyOf +
+ Native Token + + + + + + + + + + + + + + + + +
NameTypeDescription
Token IDByteArray[38] + Identifier of the native tokens. +
Amountuint256Amount of native tokens of the given Token ID.
+
+
Serial Numberuint32The serial number of the foundry with respect to the controlling alias.
Token Scheme oneOf +
+ Simple Token Scheme + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
Token Scheme Typeuint8 + Set to value 0 to denote an Simple Token Scheme. +
Minted Tokensuint256Amount of tokens minted by this foundry.
Melted Tokensuint256Amount of tokens melted by this foundry.
Maximum Supplyuint256Maximum supply of tokens controlled by this foundry.
+
+
Unlock Conditions Countuint8The number of unlock conditions following.
Unlock Conditions atMostOneOfEach +
+ Immutable Alias Address Unlock Condition + + + + + + + + + + + + + + + +
NameTypeDescription
Unlock Condition Typeuint8 + Set to value 6 to denote an Immutable Alias Address Unlock Condition. +
Address +
+ Alias Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 8 to denote an Alias Address. +
Alias IDByteArray[32]The raw bytes of the Alias ID which is the BLAKE2b-256 hash of the outputID that created it.
+
+
+
+
Features Countuint8The number of features following.
Features atMostOneOfEach +
+ Metadata Feature +
+ Defines metadata (arbitrary binary data) that will be stored in the output. +
+ + + + + + + + + + + + + + + + +
NameTypeDescription
Feature Typeuint8 + Set to value 2 to denote a Metadata Feature. +
Data(uint16)ByteArrayBinary data. A leading uint16 denotes its length.
+
+
Immutable Features Countuint8The number of immutable features following. Immutable features are defined upon deployment of the UTXO state machine and are not allowed to change in any future state transition.
Immutable Features atMostOneOfEach +
+ Metadata Feature +
+ Defines metadata (arbitrary binary data) that will be stored in the output. +
+ + + + + + + + + + + + + + + + +
NameTypeDescription
Feature Typeuint8 + Set to value 2 to denote a Metadata Feature. +
Data(uint16)ByteArrayBinary data. A leading uint16 denotes its length.
+
+
+ + + +### Additional Transaction Syntactic Validation Rules + +#### Output Syntactic Validation + +- `Amount` field must fulfill the dust protection requirements and must not be `0`. +- `Amount` field must be ≤ `Max IOTA Supply`. +- `Native Tokens Count` must not be greater than `Max Native Tokens Count`. +- `Native Tokens` must be lexicographically sorted based on `Token ID`. +- Each Native Token must be unique in the set of `Native Tokens` based on its `Token ID`. No duplicates are + allowed. +- `Amount` of any Native Token must not be `0`. +- It must hold true that `Unlock Conditions Count` = `1`. +- `Unlock Condition Type` of an Unlock Condition must define one of the following types: + - Immutable Alias Address Unlock Condition +- Syntactic validation of all present unlock conditions must pass. +- It must hold true that `0` ≤ `Features Count` ≤ `1`. +- `Feature Type` of a Feature in `Features` must define one of the following types: + - Metadata Feature +- It must hold true that `0` ≤ `Immutable Features Count` ≤ `1`. +- `Feature Type` of a Feature in `Immutable Features` must define one of the following types: + - Metadata Feature +- Syntactic validation of all present features must pass. +- `Token Scheme` must define one of the following types: + - Simple Token Scheme + +##### Simple Token Scheme Syntactic Validation +- `Token Scheme Type` of a Simple Token Scheme must be `0`. +- `Minted Tokens` - `Melted Tokens` must not be greater than `Maximum Supply`. +- `Melted Tokens` must not be greater than `Minted Tokens`. +- `Maximum Supply` must be larger than zero. + +### Additional Transaction Semantic Validation Rules + +A foundry is essentially a UTXO state machine. A transaction might either create a new foundry with a unique +`Foundry ID`, transition an already existing foundry or destroy it. The current and next states of the state machine +are encoded in inputs and outputs respectively. + +- The **current state of the foundry** with `Foundry ID` `X` in a transaction is defined as the consumed foundry output + where `Foundry ID` = `X`. +- The **next state of the foundry** with `Foundry ID` `X` in a transaction is defined as the created foundry output + where `Foundry ID` = `X`. +- `Foundry Diff` is the pair of the **current and next state** of the foundry output in the transaction. + +| A transaction that... | Current State | Next State | +|-------------------------|-------------------------|--------------------------| +| Creates the foundry | Empty | Output with `Foundry ID` | +| Transitions the foundry | Input with `Foundry ID` | Output with `Foundry ID` | +| Destroys the foundry | Input with `Foundry ID` | Empty | + +- The foundry output must be unlocked like any other output type where the Address Unlock Condition defines an + Alias Address, by transitioning the alias in the very same transaction. See section + [alias unlocking](#unlocking-chain-script-locked-outputs) for more details. +- When the current state of the foundry with `Foundry ID` is empty, it must hold true for `Serial Number` in the next + state, that: + - `Foundry Counter(InputAlias) < Serial Number <= Foundry Counter(OutputAlias)` + - An alias can create several new foundries in one transaction. It was written for the alias output that freshly + created foundry outputs must be sorted in the list of outputs based on their `Serial Number`. No duplicates are + allowed. + - The two previous rules make sure that each foundry output produced by an alias has a unique `Serial Number`, + hence each `Foundry ID` is unique. +- Native tokens present in a transaction are all native tokens present in inputs and outputs of the transaction. Native + tokens of a transaction must be a set based on their `Token ID`. +- There must be at most one `Token ID` in the native token set of the transaction that maps to a specific `Foundry ID`. +- When neither `Current State` nor `Next State` is empty: + - Immutable Alias Address Unlock Condition must not change. + - `Serial Number` must not change. + - `Token Scheme Type` must not change. + - Features in `Immutable Features` must not change. +- [Token Scheme Semantic Validation Rules](#token-scheme-semantic-validation-rules) must be fulfilled. + +#### Token Scheme Semantic Validation Rules +`Token Scheme Validation` takes `Token Diff` and `Foundry Diff` and validates if the scheme constraints are respected. + +##### Simple Token Scheme Validation Rules +- Let `Token Diff` denote the **difference between native token balances of the input and the output side** of the + transaction of the single `Token ID` that maps to the `Foundry ID`. Minting results in excess of tokens on the output + side (positive diff), melting results in excess on the input side (negative diff). Now, the following conditions must + hold for `Token Diff`: + 1. When `Token Diff` > 0 + - `Current State(Minted Tokens) + Token Diff = Next State(Minted Tokens)`. + - `Current State(Melted Tokens) = Next State(Melted Tokens)` + 2. When `Token Diff` < 0, it must hold true that: + - `Current State(Melted Tokens) <= Next State(Melted Tokens)` + - `[Next State(Melted Tokens) - Current State(Melted Tokens)] <= |Token Diff|`. + - When `Current State(Melted Tokens) != Next State(Melted Tokens)`, it must be true that `Current State(Minted Tokens) = Next State(Minted Tokens)` + 3. When `Current State` is empty, `Current State(Minted Tokens) = 0` and `Current State(Melted Tokens) = 0`. + 4. When `Next State` is empty, condition `1` and `2` are ignored. It must hold true, that + `Current State(Minted Tokens) + Token Diff = Current State(Melted Tokens)` +- When neither `Current State` nor `Next State` is empty: + - `Maximum Supply` field must not change. + +### Notes + +- A token scheme is a list of hard coded constraints. It is not feasible at the moment to foresee the future + needs/requirements of hard coded constraints, so it is impossible to design token schemes as any possible combination + of those constraints. A better design would be to have a list of possible constraints (and their related fields) from + which the user can choose. The chosen combination should still be encoded as a bitmask inside the `Token ID`. +- Additional token schemes will be defined that make use of the `Foundry Diff` as well, for example validating that + a certain amount of tokens can only be minted/melted after a certain date. +- For now, only token scheme `0` is supported. Additional token schemes will be designed iteratively when the need arises. +- The `Foundry ID` of a foundry output should be queryable in indexers, so that given a `Foundry ID`, the + `Output ID` of the foundry output can be retrieved. `Foundry ID` behaves like an address that can't unlock anything. + While it is not necessarily needed for the protocol, it is needed for client side operations, such as: + - Retrieving the current state of the foundry. + - Accessing token metadata in foundry based on `Foundry ID`/`Tokend ID`. + +## NFT Output + +Non-fungible tokens in the ledger are implemented with a special output type, the so-called NFTOutput. + +Each NFT output gets assigned a unique identifier `NFT ID` upon creation by the protocol. `NFT ID` is BLAKE2b-256 hash +of the Output ID that created the NFT. The address of the NFT is the concatenation of `NFT Address Type` || +`NFT ID`. + +The NFT may contain immutable metadata set upon creation, and a verified `Issuer`. The output type supports all +non-alias specific (state controller, governor) unlock conditions and optional features so that the output can be +sent as a request to smart contract chain accounts. + + +
+ NFT Output +
+ Describes an NFT output, a globally unique token with metadata attached. +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
Output Typeuint8 + Set to value 6 to denote a NFT Output. +
Amountuint64The amount of IOTA coins held by the output.
Native Tokens Countuint8The number of native tokens held by the output.
Native Tokens optAnyOf +
+ Native Token + + + + + + + + + + + + + + + + +
NameTypeDescription
Token IDByteArray[38] + Identifier of the native token. +
Amountuint256 + Amount of native tokens of the given Token ID. +
+
+
NFT IDByteArray[32]Unique identifier of the NFT, which is the BLAKE2b-256 hash of the Output ID that created it. NFT Address = NFT Address Type || NFT ID
Unlock Conditions Countuint8The number of unlock conditions following.
Unlock Conditions atMostOneOfEach +
+ Address Unlock Condition + + + + + + + + + + + + + + + +
NameTypeDescription
Unlock Condition Typeuint8 + Set to value 0 to denote an Address Unlock Condition. +
Address +
+ Ed25519 Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 0 to denote an Ed25519 Address. +
PubKeyHashByteArray[32]The raw bytes of the Ed25519 address which is a BLAKE2b-256 hash of the Ed25519 public key.
+
+
+ Alias Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 8 to denote an Alias Address. +
Alias IDByteArray[32]The raw bytes of the Alias ID which is the BLAKE2b-256 hash of the outputID that created it.
+
+
+ NFT Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 16 to denote an NFT Address. +
NFT IDByteArray[32]The raw bytes of the NFT ID which is the BLAKE2b-256 hash of the outputID that created it.
+
+
+
+
+ Storage Deposit Return Unlock Condition +
+ Defines the amount of IOTAs used as storage deposit that have to be returned to Return Address. +
+ + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
Unlock Condition Typeuint8 + Set to value 1 to denote a Storage Deposit Return Unlock Condition. +
Return Address oneOf +
+ Ed25519 Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 0 to denote an Ed25519 Address. +
PubKeyHashByteArray[32]The raw bytes of the Ed25519 address which is a BLAKE2b-256 hash of the Ed25519 public key.
+
+
+ Alias Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 8 to denote an Alias Address. +
Alias IDByteArray[32]The raw bytes of the Alias ID which is the BLAKE2b-256 hash of the outputID that created it.
+
+
+ NFT Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 16 to denote an NFT Address. +
NFT IDByteArray[32]The raw bytes of the NFT ID which is the BLAKE2b-256 hash of the outputID that created it.
+
+
Return Amountuint64 + Amount of IOTA coins the consuming transaction should deposit to the address defined in Return Address. +
+
+
+ Timelock Unlock Condition +
+ Defines a unix timestamp until which the output can not be unlocked. +
+ + + + + + + + + + + + + + + + +
NameTypeDescription
Unlock Condition Typeuint8 + Set to value 2 to denote a Timelock Unlock Condition. +
Unix Timeuint32 + Unix time (seconds since Unix epoch) starting from which the output can be consumed. +
+
+
+ Expiration Unlock Condition +
+ Defines a unix time until which only Address, defined in Address Unlock Condition, is allowed to + unlock the output. After the unix time is reached or passed, only Return Address can unlock it. +
+ + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
Unlock Condition Typeuint8 + Set to value 3 to denote a Expiration Unlock Condition. +
Return Address oneOf +
+ Ed25519 Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 0 to denote an Ed25519 Address. +
PubKeyHashByteArray[32]The raw bytes of the Ed25519 address which is a BLAKE2b-256 hash of the Ed25519 public key.
+
+
+ Alias Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 8 to denote an Alias Address. +
Alias IDByteArray[32]The raw bytes of the Alias ID which is the BLAKE2b-256 hash of the outputID that created it.
+
+
+ NFT Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 16 to denote an NFT Address. +
NFT IDByteArray[32]The raw bytes of the NFT ID which is the BLAKE2b-256 hash of the outputID that created it.
+
+
Unix Timeuint32 + Before this unix time, Address Unlock Condition is allowed to unlock the output, after that only the address defined in Return Address. +
+
+
Features Countuint8The number of features following.
Features atMostOneOfEach +
+ Sender Feature +
+ Identifies the validated sender of the output. +
+ + + + + + + + + + + + + + + +
NameTypeDescription
Feature Typeuint8 + Set to value 0 to denote a Sender Feature. +
Sender oneOf +
+ Ed25519 Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 0 to denote an Ed25519 Address. +
PubKeyHashByteArray[32]The raw bytes of the Ed25519 address which is a BLAKE2b-256 hash of the Ed25519 public key.
+
+
+ Alias Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 8 to denote an Alias Address. +
Alias IDByteArray[32]The raw bytes of the Alias ID which is the BLAKE2b-256 hash of the outputID that created it.
+
+
+ NFT Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 16 to denote an NFT Address. +
NFT IDByteArray[32]The raw bytes of the NFT ID which is the BLAKE2b-256 hash of the outputID that created it.
+
+
+
+
+ Metadata Feature +
+ Defines metadata (arbitrary binary data) that will be stored in the output. +
+ + + + + + + + + + + + + + + + +
NameTypeDescription
Feature Typeuint8 + Set to value 2 to denote a Metadata Feature. +
Data(uint16)ByteArrayBinary data. A leading uint16 denotes its length.
+
+
+ Tag Feature +
+ Defines an indexation tag to which the output can be indexed by additional node plugins. +
+ + + + + + + + + + + + + + + + +
NameTypeDescription
Feature Typeuint8 + Set to value 3 to denote a Tag Feature. +
Tag(uint8)ByteArrayBinary indexation data. A leading uint8 denotes its length.
+
+
Immutable Features Countuint8The number of immutable features following. Immutable features are defined upon deployment of the UTXO state machine and are not allowed to change in any future state transition.
Immutable Features atMostOneOfEach +
+ Issuer Feature +
+ Identifies the validated issuer of the UTXO state machine. +
+ + + + + + + + + + + + + + + +
NameTypeDescription
Feature Typeuint8 + Set to value 1 to denote an Issuer Feature. +
Issuer oneOf +
+ Ed25519 Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 0 to denote an Ed25519 Address. +
PubKeyHashByteArray[32]The raw bytes of the Ed25519 address which is a BLAKE2b-256 hash of the Ed25519 public key.
+
+
+ Alias Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 8 to denote an Alias Address. +
Alias IDByteArray[32]The raw bytes of the Alias ID which is the BLAKE2b-256 hash of the outputID that created it.
+
+
+ NFT Address + + + + + + + + + + + + + + + + +
NameTypeDescription
Address Typeuint8 + Set to value 16 to denote an NFT Address. +
NFT IDByteArray[32]The raw bytes of the NFT ID which is the BLAKE2b-256 hash of the outputID that created it.
+
+
+
+
+ Metadata Feature +
+ Defines metadata (arbitrary binary data) that will be stored in the output. +
+ + + + + + + + + + + + + + + + +
NameTypeDescription
Feature Typeuint8 + Set to value 2 to denote a Metadata Feature. +
Data(uint16)ByteArrayBinary data. A leading uint16 denotes its length.
+
+
+ + + +### Additional Transaction Syntactic Validation Rules + +#### Output Syntactic Validation + +- `Amount` field must fulfill the dust protection requirements and must not be `0`. +- `Amount` field must be ≤ `Max IOTA Supply`. +- `Native Tokens Count` must not be greater than `Max Native Tokens Count`. +- `Native Tokens` must be lexicographically sorted based on `Token ID`. +- Each Native Token must be unique in the set of `Native Tokens` based on its `Token ID`. No duplicates are + allowed. +- `Amount` of any Native Token must not be `0`. +- It must hold true that `1` ≤ `Unlock Conditions Count` ≤ `4`. +- `Unlock Condition Type` of an Unlock Condition must define one of the following types: + - Address Unlock Condition + - Storage Deposit Return Unlock Condition + - Timelock Unlock Condition + - Expiration Unlock Condition +- Unlock Conditions must be sorted in ascending order based on their `Unlock Condition Type`. +- Syntactic validation of all present unlock conditions must pass. +- Address Unlock Condition must be present. +- It must hold true that `0` ≤ `Features Count` ≤ `3`. +- `Feature Type` of a Feature in `Features` must define one of the following types: + - Sender Feature + - Metadata Feature + - Tag Feature +- It must hold true that `0` ≤ `Immutable Features Count` ≤ `2`. +- `Feature Type` of a Feature in `Immutable Features` must define one of the following types: + - Issuer Feature + - Metadata Feature +- Features must be sorted in ascending order based on their `Feature Type` both in `Features` and `Immutable Features` + fields. +- Syntactic validation of all present features must pass. +- `Address` field of the Address Unlock Condition must not be the same as the NFT address derived from `NFT ID`. + +### Additional Transaction Semantic Validation Rules + +- Explicit `NFT ID`: `NFT ID` is taken as the value of the `NFT ID` field in the NFT output. +- Implicit `NFT ID`: When an NFT output is consumed as an input in a transaction and `NFT ID` field is zeroed out, take + the BLAKE2b-256 hash of the `Output ID` of the input as `NFT ID`. +- For every non-zero explicit `NFT ID` on the output side there must be a corresponding NFT on the input side. The + corresponding NFT has the explicit or implicit `NFT ID` equal to that of the NFT on the output side. + +#### Consumed Outputs +- The unlock of the input corresponds to `Address` field of the Address Unlock Condition and the unlock is + valid. +- The unlock is valid if and only if all unlock conditions and features present in the output validate. +- When a consumed NFT output has a corresponding NFT output on the output side, `Immutable Features` field must not + change. +- When a consumed NFT output has no corresponding NFT output on the output side, the NFT it is being burned. Funds + and assets inside the burned NFT output must be redistributed to other outputs in the burning transaction. + +| :bangbang: Careful with NFT burning :bangbang: | +|-------------------------------------------------| + +_Other outputs in the ledger that are locked to the address of the NFT can only be unlocked by including the NFT itself +in the transaction. If the NFT is burned, such funds are locked forever. It is strongly advised to always check and +sweep what the NFT owns in the ledger before burning it._ + +#### Created Outputs +- When `Issuer Feature` is present in an output and explicit `NFT ID` is zeroed out, an input with `Address` field that + corresponds to `Issuer` must be unlocked in the transaction. If `Address` is either Alias Address or + NFT Address, their corresponding outputs (defined by `Alias ID` and `NFT ID`) must be unlocked in the transaction. +- All Unlock Condition imposed transaction validation criteria must be fulfilled. +- All Feature imposed transaction validation criteria must be fulfilled. + +### Notes +- It would be possible to have two-step issuer verification: First NFT is minted, and then metadata can be immutably + locked into the output. The metadata contains an issuer public key plus a signature of the unique `NFT ID`. This way + a smart contract chain can mint on behalf of the user, and then push the issuer signature in a next step. + +## Unlocking Chain Script Locked Outputs + +Two of the introduced output types ([Alias](#alias-output), [NFT](#nft-output)) implement the so-called UTXO chain +constraint. These outputs receive their unique identifiers upon creation, generated by the protocol, and carry it +forward with them through transactions until they are destroyed. These unique identifiers (`Alias ID`, `NFT ID`) also +function as global addresses for the state machines, but unlike Ed25519 Addresses, they are not backed by private +keys that could be used for signing. The rightful owners who can unlock these addresses are defined in the outputs +themselves. + +Since such addresses are accounts in the ledger, it is possible to send funds to these addresses. The unlock mechanism +of such funds is designed in a way that **proving ownership of the address is reduced to the ability to unlock the +corresponding output that defines the address.** + +### Alias Locking & Unlocking + +A transaction may consume a (non-alias) output that belongs to an Alias Address by state transitioning the alias output with the matching `Alias ID`. This serves the exact same purpose as providing a signature +to unlock an output locked under a private key backed address, such as Ed25519 Addresses. + +On protocol level, alias unlocking is done using a new unlock type, called **Alias Unlock**. + +
+Alias Unlock +
+ Points to the unlock of a consumed alias output. +
+
+ + + + + + + + + + + + + + + + + +
NameTypeDescription
Unlock Typeuint8 + Set to value 2 to denote a Alias Unlock. +
Alias Reference Unlock Indexuint16 + Index of input and unlock corresponding to an alias output. +
+ +This unlock is similar to the Reference Unlock. However, it is valid if and only if the input of the +transaction at index `Alias Reference Unlock Index` is an alias output with the same `Alias ID` as the one derived from +the `Address` field of the to-be unlocked output. + +Additionally, the Alias Unlocks must also be ordered to prevent circular dependencies: + +If the i-th *Unlock* of a transaction is an *Alias Unlock* and has `Alias Reference Unlock Index` set to k, +it must hold that i > k. Hence, an Alias Unlock can only reference an *Unlock* (unlocking the +corresponding alias) at a smaller index. + +For example the scenario where `Alias A` is locked to the address of `Alias B` while `Alias B` is in locked to the +address of `Alias A` introduces a circular dependency and is not well-defined. By requiring the *Unlocks* to be +ordered as described above, a transaction consuming `Alias A` as well as `Alias B` can never be valid as there would +always need to be one *Alias Unlock* referencing a greater index. + +#### Alias Unlock Syntactic Validation + + - It must hold that 0 ≤ `Alias Reference Unlock Index` < `Max Inputs Count`. + +#### Alias Unlock Semantic Validation + + - The address of the unlocking condition of the input being unlocked must be an Alias Address. + - The index `i` of the Alias Unlock is the index of the input in the transaction that it unlocks. + `Alias Reference Unlock Index` must be < `i`. + - `Alias Reference Unlock Index` defines a previous input of the transaction and its unlock. This input must + be an Alias Output with `Alias ID` that refers to the Alias Address being unlocked. + - The referenced Alias Output must be unlocked for state transition. + +### NFT Locking & Unlocking + +`NFT ID` field is functionally equivalent to `Alias ID` of an alias output. It is generated the same way, but it can +only exist in NFT outputs. Following the same analogy as for alias addresses, NFT addresses are iota addresses that are +controlled by whoever owns the NFT output itself. + +Outputs that are locked under `NFT Address` can be unlocked by unlocking the NFT output in the same transaction that +defines `NFT Address`, that is, the NFT output where `NFT Address Type Byte || NFT ID = NFT Address`. + +An NFT Unlock looks and behaves like an Alias Unlock, but the referenced input at the index must +be an NFT output with the matching `NFT ID`. + +
+NFT Unlock +
+ Points to the unlock of a consumed NFT output. +
+
+ + + + + + + + + + + + + + + + + +
NameTypeDescription
Unlock Typeuint8 + Set to value 3 to denote a NFT Unlock. +
NFT Reference Unlock Indexuint16 + Index of input and unlock corresponding to an NFT output. +
+ +An *NFT Unlock* is only valid if the input in the transaction at index `NFT Reference Unlock Index` is the NFT +output with the same `NFT ID` as the one derived from the `Address` field of the to-be unlocked output. + +If the i-th *Unlock* of a transaction is an *NFT Unlock* and has `NFT Reference Unlock Index` set to k, it +must hold that i > k. Hence, an NFT Unlock can only reference an *Unlock* at a smaller index. + +#### NFT Unlock Syntactic Validation + +- It must hold that 0 ≤ `NFT Reference Unlock Index` < `Max Inputs Count`. + +#### NFT Unlock Semantic Validation + + - The address of the input being unlocked must be an NFT Address. + - The index `i` of the NFT Unlock is the index of the input in the transaction that it unlocks. + `NFT Reference Unlock Index` must be < `i`. + - `NFT Reference Unlock Index` defines a previous input of the transaction and its unlock. This input must + be an NFT Output with `NFT ID` that refers to the NFT Address being unlocked. + +# Drawbacks +- New output types increase transaction validation complexity, however it is still bounded. +- Outputs take up more space in the ledger, UTXO database size might increase. +- It is possible to intentionally deadlock aliases and NFTs, however client side software can notify users when they + perform such action. Deadlocked aliases and NFTs can not be unlocked, but this is true for any funds locked into + unspendable addresses. +- Time based output locking conditions can only be evaluated after attachment to the Tangle, during milestone + confirmation. +- IOTA ledger can only support hard-coded scripts. Users can not write their own scripts because there is no way + currently to charge them based on resource usage, all IOTA transactions are feeless by nature. +- Aliases can be destroyed even if there are foundries alive that they control. Since only the controlling alias can + unlock the foundry, such foundries and the supply of the tokens remain forever locked in the Tangle. +- Token schemes and needed supply control rules are unclear. + +# Rationale and alternatives + +The feeless nature of IOTA makes it inherently impossible to implement smart contracts on layer 1. A smart contract +platform shall not only be capable of executing smart contracts, but also to limit their resource usage and make users +pay validators for the used resources. IOTA has no concept of validators, neither fees. While it would technically be +possible to run EUTXO smart contracts on the layer 1 Tangle, it is not possible to properly charge users for executing +them. + +The current design aims to combine the best of both worlds: Scalable and feeless layer 1 and Turing-complete smart +contracts on layer 2. Layer 1 remains scalable because of parallel transaction validation, feeless because the bounded +hard-coded script execution time, and layer 2 can offer support for all kinds of virtual machines, smart contracts and +advanced tokenization use cases. + +# Unresolved questions + +- List of supported Token Schemes is not complete. + - Deflationary token scheme + - Inflationary token scheme with scheduled minting + - etc. +- Adapt the current congestion control, i.e. *Block PoW*, to better match the validation complexity of the different + outputs and types. + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).