diff --git a/tips/TIP-0043/tip-0043.md b/tips/TIP-0043/tip-0043.md new file mode 100644 index 000000000..b1e6bf009 --- /dev/null +++ b/tips/TIP-0043/tip-0043.md @@ -0,0 +1,757 @@ +--- +tip: 43 +title: Non-Fungible Token Output Type +description: Support for layer 1 native non-fungible tokens +author: + Philipp Gackstatter (@PhilippGackstatter) , Roman Overko (@roman1e2f5p8s) + , Levente Pap (@lzpap) +discussions-to: TODO +status: Draft +type: Standards +layer: Core +created: 2023-05-03 +requires: TIP-21, TIP-22, TIP-38, TIP-45 and TIP-47 +replaces: TIP-18 +--- + +# Summary + +This document defines the NFT output type and transaction validation rules for the IOTA protocol to support Layer 1 +native **non-fungible tokens** (unique tokens with attached metadata). It was originally introduced in +[TIP-18](../TIP-0018/tip-0018.md) and the functionality defined in this document is an extension of the NFT Output of +TIP-18. + +## Summary of changes compared to TIP-18 + +- Add `Mana` field. +- Remove `Native Tokens` field. See [TIP-38 (Native Token Migration)](../TIP-0038/tip-0038.md#native-token-migration) + for migration details. + +# Motivation + +The aim of this TIP is to define an NFT output type for the use cases of seamless interoperability between layer 1 and +layer 2 tokenization concepts. Such non-fungible tokens on layer 1 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. + +In combination with the other layer 1 output types, 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. + +The proposal in this TIP makes it possible for tokens that originate from layer 2 smart contract chains to also be +wrapped into their layer 1 representation. Smart contract chains may transfer tokens between themselves through this +mechanism, and they can also post requests to other chains. + +# Building Blocks + +## Data Types & Subschema Notation + +Data types and subschemas used throughout this TIP are defined in [TIP-21](../TIP-0021/tip-0021.md). + +## Protocol Parameters + +Protocol parameters used throughout this TIP are defined in [TIP-49](../TIP-0049/tip-0049.md). + +## Transaction Payload + +[TIP-45](../TIP-0045/tip-0045.md) is the basis for output validation in this TIP. + +# 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-anchor 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.
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Name + + Type + + Description +
Output Typeuint8Set to value 4 to denote an NFT Output.
Amountuint64The amount of IOTA coins held by the output.
Manauint64The amount of Stored Mana held by the output.
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 +
Defines the Address that owns this output. It can unlock the output with the proper Unlock in a transaction. Defined in TIP-38 (Address Unlock Condition).
+ + + + + + + + + + + + + + + +
+ Name + + Type + + Description +
Unlock Condition Typeuint8Set to value 0 to denote an Address Unlock Condition.
Address oneOf +
+ Ed25519 Address +
An Address derived from an Ed25519 Public Key. Defined in TIP-38 (Ed25519 Address).
+
+
+ Account Address +
An Address derived from an Account ID which can be unlocked by unlocking the corresponding Account. Defined in TIP-38 (Account Address).
+
+
+ NFT Address +
An Address derived from an NFT ID which can be unlocked by unlocking the corresponding NFT. Defined in TIP-38 (NFT Address).
+
+
+ Anchor Address +
An Address derived from an Anchor ID which can be unlocked by unlocking the corresponding Anchor. Defined in TIP-38 (Anchor Address).
+
+
+ Multi Address +
Defines a Multi Address that consists of addresses with weights and a threshold value. The Multi Address can be unlocked if the cumulative weight of all unlocked addresses is equal to or exceeds the threshold. Defined in TIP-52 (Multi Address).
+
+
+ Restricted Address +
An address that contains another address and allows for configuring its capabilities. Defined in TIP-50 (Restricted Address).
+
+
+
+
+ Storage Deposit Return Unlock Condition +
Defines the amount of IOTAs used as storage deposit that have to be returned to Return Address. Defined in TIP-38 (Storage Deposit Return Unlock Condition).
+ + + + + + + + + + + + + + + + + + + + +
+ Name + + Type + + Description +
Unlock Condition Typeuint8Set to value 1 to denote a Storage Deposit Return Unlock Condition.
Return Address oneOf +
+ Ed25519 Address +
An Address derived from an Ed25519 Public Key. Defined in TIP-38 (Ed25519 Address).
+
+
+ Account Address +
An Address derived from an Account ID which can be unlocked by unlocking the corresponding Account. Defined in TIP-38 (Account Address).
+
+
+ NFT Address +
An Address derived from an NFT ID which can be unlocked by unlocking the corresponding NFT. Defined in TIP-38 (NFT Address).
+
+
+ Anchor Address +
An Address derived from an Anchor ID which can be unlocked by unlocking the corresponding Anchor. Defined in TIP-38 (Anchor Address).
+
+
+ Multi Address +
Defines a Multi Address that consists of addresses with weights and a threshold value. The Multi Address can be unlocked if the cumulative weight of all unlocked addresses is equal to or exceeds the threshold. Defined in TIP-52 (Multi Address).
+
+
+ Restricted Address +
An address that contains another address and allows for configuring its capabilities. Defined in TIP-50 (Restricted Address).
+
+
Return Amountuint64Amount of IOTA coins the consuming transaction should deposit to the address defined in Return Address.
+
+
+ Timelock Unlock Condition +
Defines a slot index until which the output can not be unlocked. Defined in TIP-38 (Timelock Unlock Condition).
+ + + + + + + + + + + + + + + + +
+ Name + + Type + + Description +
Unlock Condition Typeuint8Set to value 2 to denote a Timelock Unlock Condition.
Slot Indexuint32Slot index starting from which the output can be consumed.
+
+
+ Expiration Unlock Condition +
Defines a slot index until which only the Address defined in the Address Unlock Condition is allowed to unlock the output. After the slot index is reached/passed, only the Return Address can unlock it. Defined in TIP-38 (Expiration Unlock Condition).
+ + + + + + + + + + + + + + + + + + + + +
+ Name + + Type + + Description +
Unlock Condition Typeuint8Set to value 3 to denote an Expiration Unlock Condition.
Return Address oneOf +
+ Ed25519 Address +
An Address derived from an Ed25519 Public Key. Defined in TIP-38 (Ed25519 Address).
+
+
+ Account Address +
An Address derived from an Account ID which can be unlocked by unlocking the corresponding Account. Defined in TIP-38 (Account Address).
+
+
+ NFT Address +
An Address derived from an NFT ID which can be unlocked by unlocking the corresponding NFT. Defined in TIP-38 (NFT Address).
+
+
+ Anchor Address +
An Address derived from an Anchor ID which can be unlocked by unlocking the corresponding Anchor. Defined in TIP-38 (Anchor Address).
+
+
+ Multi Address +
Defines a Multi Address that consists of addresses with weights and a threshold value. The Multi Address can be unlocked if the cumulative weight of all unlocked addresses is equal to or exceeds the threshold. Defined in TIP-52 (Multi Address).
+
+
+ Restricted Address +
An address that contains another address and allows for configuring its capabilities. Defined in TIP-50 (Restricted Address).
+
+
Slot Indexuint32Before this slot index, 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. Defined in TIP-38 (Sender Feature).
+ + + + + + + + + + + + + + + +
+ Name + + Type + + Description +
Feature Typeuint8Set to value 0 to denote a Sender Feature.
Sender oneOf +
+ Ed25519 Address +
An Address derived from an Ed25519 Public Key. Defined in TIP-38 (Ed25519 Address).
+
+
+ Account Address +
An Address derived from an Account ID which can be unlocked by unlocking the corresponding Account. Defined in TIP-38 (Account Address).
+
+
+ NFT Address +
An Address derived from an NFT ID which can be unlocked by unlocking the corresponding NFT. Defined in TIP-38 (NFT Address).
+
+
+ Anchor Address +
An Address derived from an Anchor ID which can be unlocked by unlocking the corresponding Anchor. Defined in TIP-38 (Anchor Address).
+
+
+ Multi Address +
Defines a Multi Address that consists of addresses with weights and a threshold value. The Multi Address can be unlocked if the cumulative weight of all unlocked addresses is equal to or exceeds the threshold. Defined in TIP-52 (Multi Address).
+
+
+ Restricted Address +
An address that contains another address and allows for configuring its capabilities. Defined in TIP-50 (Restricted Address).
+
+
+
+
+ Metadata Feature +
Defines a map of key-value pairs that is stored in the output. Defined in TIP-38 (Metadata Feature).
+ + + + + + + + + + + + + + + + + + + + +
+ Name + + Type + + Description +
Feature Typeuint8Set to value 2 to denote a Metadata Feature.
Entries Countuint8The number of entries in the map.
Entries anyOf +
+ Metadata Entry +
A map entry consisting of a string key and an arbitrary byte value.
+ + + + + + + + + + + + + + + + +
+ Name + + Type + + Description +
Key(uint8)ByteArrayA string which may only consist of printable ASCII characters. A leading uint8 denotes its length.
Value(uint16)ByteArrayAn array of arbitrary binary data. A leading uint16 denotes its length.
+
+
+
+
+ Tag Feature +
Defines an indexation tag to which the output can be indexed by additional node plugins. Defined in TIP-38 (Tag Feature).
+ + + + + + + + + + + + + + + + +
+ Name + + Type + + Description +
Feature Typeuint8Set to value 4 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. Defined in TIP-38 (Issuer Feature).
+ + + + + + + + + + + + + + + +
+ Name + + Type + + Description +
Feature Typeuint8Set to value 1 to denote a Issuer Feature.
Issuer oneOf +
+ Ed25519 Address +
An Address derived from an Ed25519 Public Key. Defined in TIP-38 (Ed25519 Address).
+
+
+ Account Address +
An Address derived from an Account ID which can be unlocked by unlocking the corresponding Account. Defined in TIP-38 (Account Address).
+
+
+ NFT Address +
An Address derived from an NFT ID which can be unlocked by unlocking the corresponding NFT. Defined in TIP-38 (NFT Address).
+
+
+ Anchor Address +
An Address derived from an Anchor ID which can be unlocked by unlocking the corresponding Anchor. Defined in TIP-38 (Anchor Address).
+
+
+ Multi Address +
Defines a Multi Address that consists of addresses with weights and a threshold value. The Multi Address can be unlocked if the cumulative weight of all unlocked addresses is equal to or exceeds the threshold. Defined in TIP-52 (Multi Address).
+
+
+ Restricted Address +
An address that contains another address and allows for configuring its capabilities. Defined in TIP-50 (Restricted Address).
+
+
+
+
+ Metadata Feature +
Defines a map of key-value pairs that is stored in the output. Defined in TIP-38 (Metadata Feature).
+ + + + + + + + + + + + + + + + + + + + +
+ Name + + Type + + Description +
Feature Typeuint8Set to value 2 to denote a Metadata Feature.
Entries Countuint8The number of entries in the map.
Entries anyOf +
+ Metadata Entry +
A map entry consisting of a string key and an arbitrary byte value.
+ + + + + + + + + + + + + + + + +
+ Name + + Type + + Description +
Key(uint8)ByteArrayA string which may only consist of printable ASCII characters. A leading uint8 denotes its length.
Value(uint16)ByteArrayAn array of arbitrary binary data. A leading uint16 denotes its length.
+
+
+
+
+ +## Additional Transaction Syntactic Validation Rules + +### Output Syntactic Validation + +- 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 is being burned. Funds and + assets inside the burned NFT output must be redistributed to other outputs in the burning transaction. + - The transaction is invalid if an NFT is burned and the _Can destroy NFT Outputs_ flag in the _Transaction + Capabilities_ is **unset**. + +| :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 Account Address or NFT + Address, their corresponding outputs (defined by `Account 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. + +## NFT Locking & Unlocking + +The `NFT ID` field is functionally equivalent to `Account ID` of an account output. It is generated the same way, but it +can only exist in NFT outputs. Following the same analogy as for account 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 Account 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.
+
+ + + + + + + + + + + + + + + + +
+ Name + + Type + + Description +
Unlock Typeuint8Set to value 4 to denote an NFT Unlock.
NFT Reference Unlock Indexuint16Index 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 - 1`. + +### 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. + +# Test Vectors + +The protocol parameters used in the following test vectors are the same as in +[TIP-49 (Protocol Parameters Hash)](../TIP-0049/tip-0049.md#protocol-parameters-hash). + +## Storage Score + +The following test vector shows the calculation of the storage score according to [TIP-47](../TIP-0047/tip-0047.md). + +NFT Output (json-encoded): + +```json +{ + "type": 4, + "amount": "421000000", + "mana": "0", + "nftId": "0x3163482ff326658dd1bfead468a609bc6b3e74cb2e5094e0da9b63eae7e0166c", + "unlockConditions": [ + { + "type": 0, + "address": { + "type": 8, + "accountId": "0x17432c5a7a672503480241125e3952414a7a320441080c624c264b004e09614a" + } + }, + { + "type": 1, + "returnAddress": { + "type": 0, + "pubKeyHash": "0xed1484f4d1f7d8c037087fed661dd92faccae1eed3c01182d6fdd6828cea144a" + }, + "amount": "4000000" + } + ], + "features": [ + { + "type": 2, + "entries": { + "iota": "0x322e30" + } + } + ], + "immutableFeatures": [ + { + "type": 2, + "entries": { + "nft": "0x696f7461" + } + } + ] +} +``` + +NFT Output (hex-encoded binary serialization): + +``` +0x0440f317190000000000000000000000003163482ff326658dd1bfead468a609bc6b3e74cb2e5094e0da9b63eae7e0166c02000817432c5a7a672503480241125e3952414a7a320441080c624c264b004e09614a0100ed1484f4d1f7d8c037087fed661dd92faccae1eed3c01182d6fdd6828cea144a00093d000000000001020104696f74610300322e30010201036e66740400696f7461 +``` + +NFT Output Storage Score: `240`. + +# Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).