tip | title | description | author | discussions-to | status | type | layer | created | requires | replaces |
---|---|---|---|---|---|---|---|---|---|---|
43 |
Non-Fungible Token Output Type |
Support for layer 1 native non-fungible tokens |
Philipp Gackstatter (@PhilippGackstatter) <philipp.gackstatter@iota.org>, Roman Overko (@roman1e2f5p8s) <roman.overko@iota.org>, Levente Pap (@lzpap) <levente.pap@iota.org> |
TODO |
Draft |
Standards |
Core |
2023-05-03 |
TIP-21, TIP-22, TIP-38, TIP-45 and TIP-47 |
TIP-18 |
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 and the functionality defined in this document is an extension of the NFT Output of TIP-18.
- Add
Mana
field. - Remove
Native Tokens
field. See TIP-38 (Native Token Migration) for migration details.
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.
Data types and subschemas used throughout this TIP are defined in TIP-21.
Protocol parameters used throughout this TIP are defined in TIP-49.
TIP-45 is the basis for output validation in this TIP.
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 Type | uint8 | Set to value 4 to denote an NFT Output. | ||||||||||||||||||||||||||||||||||||||||||
Amount | uint64 | The amount of IOTA coins held by the output. | ||||||||||||||||||||||||||||||||||||||||||
Mana | uint64 | The amount of Stored Mana held by the output. | ||||||||||||||||||||||||||||||||||||||||||
NFT ID | ByteArray[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 Count | uint8 | The number of unlock conditions following. | ||||||||||||||||||||||||||||||||||||||||||
Unlock Conditions atMostOneOfEach |
Address Unlock ConditionDefines 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).
Storage Deposit Return Unlock ConditionDefines 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).
Timelock Unlock ConditionDefines a slot index until which the output can not be unlocked. Defined in TIP-38 (Timelock Unlock Condition).
Expiration Unlock ConditionDefines 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).
|
|||||||||||||||||||||||||||||||||||||||||||
Features Count | uint8 | The number of features following. | ||||||||||||||||||||||||||||||||||||||||||
Features atMostOneOfEach |
Sender FeatureIdentifies the validated sender of the output. Defined in TIP-38 (Sender Feature).
Metadata FeatureDefines a map of key-value pairs that is stored in the output. Defined in TIP-38 (Metadata Feature).
Tag FeatureDefines an indexation tag to which the output can be indexed by additional node plugins. Defined in TIP-38 (Tag Feature).
|
|||||||||||||||||||||||||||||||||||||||||||
Immutable Features Count | uint8 | The 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 FeatureIdentifies the validated issuer of the UTXO state machine. Defined in TIP-38 (Issuer Feature).
Metadata FeatureDefines a map of key-value pairs that is stored in the output. Defined in TIP-38 (Metadata Feature).
|
- 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 inFeatures
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 inImmutable 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 inFeatures
andImmutable 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 fromNFT ID
.
- Explicit
NFT ID
:NFT ID
is taken as the value of theNFT ID
field in the NFT output. - Implicit
NFT ID
: When an NFT output is consumed as an input in a transaction andNFT ID
field is zeroed out, take the BLAKE2b-256 hash of theOutput ID
of the input asNFT 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 implicitNFT ID
equal to that of the NFT on the output side.
- 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.
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.
- When
Issuer Feature
is present in an output and explicitNFT ID
is zeroed out, an input withAddress
field that corresponds toIssuer
must be unlocked in the transaction. IfAddress
is either Account Address or NFT Address, their corresponding outputs (defined byAccount ID
andNFT 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.
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 Type | uint8 | Set to value 4 to denote an NFT Unlock. |
NFT Reference Unlock Index | uint16 | 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.
- It must hold that 0 ≤
NFT Reference Unlock Index
<Max Inputs Count - 1
.
- 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 withNFT ID
that refers to the NFT Address being unlocked.
The protocol parameters used in the following test vectors are the same as in TIP-49 (Protocol Parameters Hash).
The following test vector shows the calculation of the storage score according to TIP-47.
NFT Output (json-encoded):
{
"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 and related rights waived via CC0.