Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Meta-Non-Fungible Token

Meta-Non-Fungible Token

Non-fungible tokens (NFTs) are all the rage these days, but their current manifestation (ERC721) is inefficient. It is not possible to move multiple tokens at the same time or package multiple tokens for e.g. deposit into a plasma child chain.

Contract pseudocode

The following is a new design for an NFT token that allows aggregation of assets. The rest of the functionality can be inherited from ERC721.

contract NFT {
  tokens mapping(address => mapping(bytes32 => uint));
  
  transfer (bytes32 id, uint n, address to) {
    assert(tokens[msg.sender][id] >= n);
    tokens[msg.sender][id] -= n;
    tokens[to][id] += n;
  }
  
  transferBundle(address to, bytes data) {
    for (uint i = 0; i < data.length; i += 64) {
      uint n = data.slice(i, i+32);
      uint token = data.slice(i+32, i+64);
      transfer(token, n, to);
    }
  }
}

Note that we are representing tokens in a different construction than ERC721. Each token has an id, which is a hash of its metadata (this should be unique) and any user may own any number of each unique token.

Users can transfer one or more of a single token via transfer() or move several tokens to a recipient via transferBundle()

NFT UTXOs

This design enables us to package tokens reasonably efficiently and transfer them off chain to e.g. a plasma child chain.

Interestingly, these NFTs can also be represented as UTXOs:

{
  id: <string>   // keccak256(prevId, to, n, data)
  to: <string>   // new owner of this token
  n: <int>       // number of tokens in this UTXO
  data: <string> // token metadata. This should be unique to the token (e.g. for a card in a trading card game)
}

The only difference between this and fungible token UTXOs is the presence of the data field, which is simply hashed into the id and never changes as tokens move through the system.

Such tokens can then be traded off-chain (via UTXO signing) and withdrawn later onto the root chain via a submission of the UTXO's provenance. (for example, if Bob got a card from Alice, he would need to submit her signed transaction in order to withdraw his new card).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.