Skip to content
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
230 lines (164 sloc) 12.5 KB
FATIP Title Status Category Author Requires Created
1 Non-Fungible Token Standard Draft Token Standard Devon Katz <> - 2018-07-27


This document describes the functionality, datastructures, validation rules of the FAT-1 token standard: A non-fungible data only token standard built on Factom chains and entries. It's functionality is most alike the ERC-721 token standard of Ethereum.


Extend upon the FAT-0 standard by offering non-fungible token functionality for unique, indivisible, and traceable assets.

Applications include tokenized equity, commodities, financial instruments, and digital goods.


Token ID extends FATIP-100

Addresses extends FATIP-0

Token Issuance Chain

Unlike FAT-0, the issuance chain can contain multiple entries. FAT-1 allows the ongoing issuance of unique tokens over time up to a maximum supply.

Issuance Chain ID Derivation extends FATIP-100

Token Issuance Entry extends FATIP-101

FAT-1 token issuance entries include a additional tokens field, which is an array of unique token objects, each signed by the issuing identity .

Every token in the issuance must be valid for the issuance entry to be valid. Issuing a token does not place the token into the circulating supply. Once issued the token can be sent via coinbase transaction by ID to it's initial bearer.

Individual FAT-1 Tokens extends FATIP-101

Each token in the tokens field must contain a unique ID with respect to this FAT-1 token. I.e having two greple tokens with the ID 0 is illegal. However, having a greple token with ID 0 and a testfat0token with ID 0 is legal. It's best to choose short IDs since doing so maximizes the amount of tokens that can be issued in a single issuance. As with any Factom entry, it's maximum size can be 10KB in content.

Issuance Entry Content Example

  "type": "FAT-1",
  "issuer": "888888dd9e60c1f0216f753caf5c9b5be4c9ca69db27a6c33d30dce3fe5ee709",
  "supply": 1000,
  "name": "Test FAT-1 NGUP",
  "symbol": "NGUP",

  "tokens": [
      "id": "0",
      "salt": "1bbd0b1dca170056f498106b3333f6e8891487de9b8a7cb0faac57b5d2ab6429",
    //From FATIP-101
      "idSignature": "711eb6b9c0c04583decb76ef73fd2cb420696dfdc7489cb8588768acce7b0687a2fa0dc083dfe2bf912633c90ccdd71d8bd072061e5f3fc8195a5309fd9a5f0f"
      "id": "1",
      "salt": "fbd805f0b791ef29fe6db3bf8a0cc38a152524ced99c1f29875e129fc3df5247",
      "idSignature": "5922682c069b20090add4ea068e9527ec19c4ae1f92c4c2da436b4b5501d1e64059d5bda48deb7b4881ad083ebf63ab3d8b46a215fc20b85a5ff97abbea28207"

//From FATIP-101
  "salt": "ff4f10ff769ba2d185d5d3a276f87481a0ebf7b49339c3c4bff3a6ddc37290b5",
  "idSignature": "8122b4c0a26e82100ff2583c3d200e9a731b9d5a7ca8674e57589b353348a5df89625e64a23758b71e83ba89ff6fb0e6b7913924554141a25523d8180f022802"

Issuance Field Summary & Validation

Name Type Description Validation Required
type string The type of this token issuance Must equal 'FAT-0' Y
issuer string The Root Chain ID of the Issuing Identity Identity must exist Y
supply number The maximum possible number tokens that can be in circulation. -1 means unlimited Must be -1 (inf), or greater than 0 Y
name string The display name of the token none N
symbol string The display symbol of the token must be A-Z, and 1-4 characters in length N
tokens array An array of the tokens being issued 0 or more valid token objects Y
tokens[n] object The token object N
tokens[n].id string The unique ID of the token length > 0. Unique among other tokens within this asset Y
tokens[n].salt string Random string to be hashed into token idNonce(sha256d(tokenID + salt)) Y
tokens[n].idSignature string ed25519 signature from issuing identity's SK1 key ed25519 signature validation (idKey, idNonce, idSignature) Y
tokens[n].metadata any Optional user defined metadata JSON object N
salt string Random string to be hashed into nonce to be signed. user defined. Optional Y
idSignature string ed25519 signature from issuing identity's SK1 key ed25519 signature validation (idKey, sha256d(tokenID + salt), signature) Y

Token Transaction Chain

Inherits directly from the FATIP-0 standard.

Transaction Chain ID extends FATIP-100

Identifier: <tokenid>:transactions

Token Transaction Entry extends* FATIP-101

Transaction entries of FAT-1 tokens contain a tokenIds field, which is an array of the tokenIds being sent in the transaction. Since the [input|output].amount field is not relevant in the same way as FAT-0, it is used as a means to secure the tokenIds field via djb2a hashing. With an overwhelming probability this results in a transaction that has an unfeasibly large integer amount to transfer on Factom for replaying a Factoid transaction. This is in addition to the nonce which is a random integer used as the timestamp in the signed Factoid transaction.

Transaction Entry Content Example

  "input": {
    "address": "FA1zT4aFpEvcnPqPCigB3fvGu4Q4mTXY22iiuV69DqE1pNhdF2MC",
    "amount": 238493715
  "output": {
    "address": "FA3aECpw3gEZ7CMQvRNxEtKBGKAos3922oqYLcHQ9NqXHudC6YBM",
    "amount": 238493715
  "tokenIds": [
  "txSalt": "60bf97df8a615315",
  "rcd": "013b6a27bcceb6a42d62a3a8d02a6f0d73653215771de243a63ac048a18b59da29",
  "marshalBinarySig": "023d7a1c8ef284010100f1dcc013031cce24bcc43b596af105167de2c03603c20ada3314a7cfb47befcad4883e6ff1dcc013d381a44afa76ad5ab8f0d82adb27d6ffa031302cc3bb281c86b1b3dfabde395e",
  "signature": "18422fffc1d99db80df0869f1f12115565660bf97df8a6153159b1d586dece420e0ecdde4e4b12613bab461f1862fc40a90287a6c37393bb74b8fad142b74800",

  //Coinbase Transaction Fields
  "salt": "84da89ac622af0d09100dd1d3baaab12455ca1ffa2fcb46aaaef2669fb38bde0",
  "idSignature": "ddf140cc2a6fe27979ac8e4625f7f1cb911e00a631f1dde08626ab9f3f9f09dbd2d04c82359d6255c50446e0799e6b1c0a739e25598c1f50e838894ad8ac2206"

Transaction Field Summary & Validation

Name Type Description Validation Required
input object The input parameters of this tx Y
input.address string The Factoid address to send tokens from Valid public Factoid address Y
input.rcdHash string Redeem condition hash of the input address & Amount sha256d validation Y
input.amount number the djb2a hash of the token IDS being transferred djb2a hash verification, Must be an integer Y
output object The output parameters of this tx Y
output.address string The Factoid address to send tokens from Valid public Factoid address Y
output.amount integer the djb2a hash of the token IDS being transferred. must match input.amount Y
txSalt string Random string nonce Non-empty string with random data. Used to calculate djb2a hash of tokenID + txSalt to prevent replay. Used as FCT tx timestamp (FAT has no internal timestamp enforcement) Y
rcd string RCD of the input Factoid Transaction Validation Y
signature string ed25519 signature of the transaction Factoid Transaction Validation Y
salt string Random bytes to be hashed into nonce User defined, optional N*
idSignature string ed25519 signature from issuing identity's SK1 key ed25519 signature validation (idKey, sha256d(tokenID + salt), idSignature) N*

* = required for coinbase transaction

Contextual Tansaction Validation

FAT-1 Tansactions must be validated in context of their order within the transaction history to applied to an address's balance, just as in FAT-0. Alternate and additional validation criteria is required to support non-fungible functionality:

  • Must meet and pass all applicable validation criteria specified in the above field table
  • signature may not be reused for any transaction
  • IF: The transaction is a coinbase transaction (From FA1zT4aFpEvcnPqPCigB3fvGu4Q4mTXY22iiuV69DqE1pNhdF2MC):
    • idSignature may not be reused for any coinbase transaction, issuance entry (issuance.idSignature), or token issuance signature (issuance.tokens[n].idSignature)
    • Issuing tokenIds's amount of tokens must not push the circulating supply of the token over it's maximum ( If the supply is unlimited, this is ignored.
  • ELSE IF: The transaction is a normal transaction:
    • All tokens in tokenIds must reside in the balance of input.address.

Assuming these criteria are met, the tokens specified in input.tokenIds are deducted from input.address and credited to output.address. In the case of a coinbase transaction, the deduction does not occur for input.address.

This filtering and balance application process is repeated for all transactions in chronological order to reach the current state of the token.

Implementation extends FATIP-0


Since issuances are ongoing, this standard requires syncing and listening to chains instead of one.


Copyright and related rights waived via CC0.

You can’t perform that action at this time.