Choosing an NFT Contract: Do you own Fungible Non-Fungibles?

Sam Casey
Charged Particles
Published in
8 min readJan 13, 2022

Abstract

Thousands of different tokens exist on the Ethereum blockchain, but most follow one of three common standards. Most fungible tokens follow the ERC-20 standard, and most non-fungible tokens (NFTs) follow the ERC-721 or ERC-1155 standard.

NFTs are indivisible digital assets that represent one-of-a-kind items such as artworks, music, game characters, memes, and domain names. An NFT can only have one owner at a time, and ownership is managed by a unique ID and metadata that no other token can replicate.

The ERC-1155 standard is a multi-token standard — it has unique features that combine the ERC-721 and ERC-20 standards. The ERC-1155 standard supports the creation of fungible and non-fungible tokens in a single smart contract, batch token transfers, prevention of accidental token loss, and localization of languages for all metadata, as opposed to the ERC-721, which is limited to only NFTs and doesn’t support batch transfers or language localization.

Despite the ERC-1155’s simplicity, efficiency, and security, it is not an outright improvement on top of the ERC-721 standard. Extra care must be taken to avoid mistakes during implementation due to the fact that it is a multi-token standard. Many implementations of the ERC-1155 standard are not actually NFTs, but rather fungible tokens.

This article outlines the difference between the three most popular types of Ethereum contracts — the ERC-20, ERC-721, and ERC-1155 standards. Specifically, it touches on the pros and cons of each contract type, the impact on developers and creators when choosing a contract type, and the correct way to make an NFT with an ERC-1155 contract.

Conceptual Overview

Smart Contracts

Smart contracts are computerized transaction protocols that execute contract conditions. It’s a set of code (its functions) and data (its state) stored at a specific address on the blockchain. All tokens on Ethereum and other Ethereum-compatible blockchains (e.g. Polygon) are smart contracts under the hood. This includes both fungible ERC-20 tokens like USDC, as well as NFTs like Cryptopunks. The ERC-721 and ERC-1155 standards are the most common templates that developers use when creating NFTs.

Types of Contracts

There are various token standards on the Ethereum blockchain, but the three most prevalent token contracts are ERC-20, ERC-721, and the ERC-1155. Each of these token contracts has unique characteristics, and your preferences and goals for your project dictate which standard you should follow.

ERC-20

The ERC-20 was the first token contract type to be released on the Ethereum blockchain. The ERC-20 standard only keeps track of fungible tokens. A fungible item is one that can be replaced by another identical item; fungible items are not unique. This makes ERC-20 tokens useful for things like a medium of currency exchange, similar to US Dollars but on a blockchain. While the ERC-20 standard is great for fungible assets, it cannot be used to represent unique digital assets.

ERC-721

Due to the fungible nature of the ERC-20, it is not a good fit for tracking items that require uniqueness like collectibles, digital art, or physical property. The ERC-721 token contract exists for exactly this purpose — to represent ownership of non-fungible assets. In order to follow the ERC-721 standard, all ERC-721 contracts must include the standard function ownerOf to keep track of this 1-to-1 owner-to-token relationship.

ERC-1155

The ERC-1155 is a multi-token standard. The Enjin team created it in 2018 with game development in mind and was designed to capitalize on the strengths of both the ERC-20 and ERC-721 standards. In contrast to the ERC-721 and ERC-20 standards, which are limited to a single type of token (non-fungible and fungible, respectively) the ERC-1155 standard allows for the creation of non-fungible (NFTs) and fungible tokens in a single smart contract. This is ideal for game development, as outlined in this video from the Moralis team.

Developers planning to implement the ERC-1155 protocol should exercise caution as it is possible to use a fungible implementation rather than a non-fungible token implementation with respect to NFTs due to the fact that ERC-1155 supports both. If you create an NFT with a unique token ID, and that token has multiple identical copies associated with the same token ID, then it is not a Non-Fungible token, but rather a Fungible one.

In addition, it’s difficult to track the owner of an ERC-1155 NFT without adding functions to the standard. For example, ERC-721 has the ownerOf function that takes a non-fungible token's id and returns the owner’s address. A standard ERC-1155 implementation does not include this ownerOf function, but rather a balanceOf function that keeps track of the number of copies of an NFT that an address holds since it’s possible that there are multiple copies of each NFT in the ERC-1155 standard. When using the ERC-1155 contract to create NFTs, it should be considered best practice to include an ownerOf function in the contract.

Technical Details

ERC-721

The ownerOf function in the ERC-721 standard returns the address of a given tokenId’s owner.

/// @notice Find the owner of an NFT
/// @dev NFTs assigned to zero address are considered invalid, and queries
/// about them do throw.
/// @param _tokenId The identifier for an NFT
/// @return The address of the owner of the NFT
function ownerOf(uint256 _tokenId) external view returns (address);

ERC-1155

In contrast to the ERC-721 standard, the ERC-1155 standard uses the balanceOf function to track how many of a specific token type (_id) a given address holds. This is not a one-to-one relationship with an NFT, but rather a one-to-many relationship.

/// @notice Get the balance of an account's tokens
/// @param _owner The address of the token holder
/// @param _id ID of the token
/// @return The _owner's balance of the token type requested
function balanceOf(address _owner, uint256 _id) external view returns (uint256);

This also requires the caller to provide the owner’s address in the function call, making it very difficult to find the owner of an NFT with just the NFT’s token ID alone.

As per the specification, the ERC-1155 standard provides strategies of how you MAY mix fungible and non-fungible tokens together in the same contract. The standard does NOT mandate how an implementation must do this. The 2 strategies that are suggested include the “Split ID bits” strategy and the “Natural” strategy.

The “Natural” strategy is pretty simple, and very similar to ERC-721 — only allow a maximum value of 1 for each NFT minted, and keep track of the current owner in a TokenID to Address mapping. This is essentially a contract that contains many NFTs of a single “type”, like CryptoKitties or CryptoPunks.

mapping (uint256 => address) internal _tokenOwner;// ...function ownerOf(uint256 tokenId) external view returns (address) {
return _tokenOwner[tokenId];
}
// ...function mint(address receiver) external returns (uint256 newTokenId) {
_tokenCount.increment();
newTokenId = _tokenCount.current();
// Maximum Value of 1 for each NFT
_mint(receiver, newTokenId, 1, "");
// Store the owner of the NFT
_tokenOwner[newTokenId] = receiver;
}

The “Split ID bits” strategy is a bit more involved, but the idea is simple. It is like having multiple “types” of NFTs in a single contract, as if CryptoKitties and CryptoPunks were both defined and contained within. The Token ID basically gets split in half, the first half of the ID is the NFT “Type”, and the second half is the unique ID of the individual NFT. CryptoKitties would be Type 1, and CryptoPunks would be Type 2. Each CryptoKitty would have its own unique ID, as would each CryptoPunk. There would never be two NFTs with the exact same ID.

For an example of “Split ID bits” you can view the reference implementation from Enjin, found here: https://github.com/enjin/erc-1155/tree/master/contracts Specifically, the contracts ERC1155MixedFungible & ERC1155MixedFungibleMintable.

A very popular reference implementation of the ERC-1155 standard seems to be the OpenZeppelin Contracts, and their implementation, being non-opinionated, tends to promote a Fungible approach with respect to the balanceOf function and lack of an ownerOf function. While they adhere to the specification, it is left to developers to decide which way to implement their own contracts, and if the default implementation is not adapted with either the “Natural” strategy, or the “Split ID bits” strategy, it ends up becoming a Fungible Non-Fungible (NFTs with a balanceOf, implying a one-to-many relationship).

For a more detailed explanation, please see the section on Non-Fungible Tokens in the EIP found here: https://eips.ethereum.org/EIPS/eip-1155

There is also a Third strategy, and that is the “Fungible Non-Fungible” strategy itself. This is an acceptable approach in certain scenarios, such as large role-playing games where each item (helmet, sword, etc.) is represented by an NFT type, of which there are many copies available to all of the players. Each item may be unique (Helmet A vs Helmet B), but many players may have a copy of this item in their inventory. In this scenario, the Fungible Non-Fungible strategy makes sense, however, it is important to recognize which strategy is needed and which strategy is being implemented. This is how the default reference contracts are implemented — a single NFT “type” with a balanceOf function, and associated storage.

In order to make truly non-fungible tokens in an 1155 contract, developers should ensure that their NFTs are unique, and always include an “ownerOf” function in their code, for both backward compatibility with ERC-721 and to create a truly 1-to-1 relationship with an NFT and its owner.

Conclusion

As an artist or developer, you may be wondering which token contract to use after reading this article. Each contract has its own distinct pros and cons, and there is no one-size-fits-all solution.

For a medium of exchange, the ERC-20 standard is the way to go. If your work is designed to be truly unique, like a piece of fine art, you should probably favor the ERC-721 standard. If transaction efficiency is your main aim and you are less concerned with uniqueness, like the case of character assets in video games, the ERC-1155 standard may be the better fit.

At Charged Particles, we are of the belief that developers planning to implement the ERC-1155 for NFTs should add an ownerOf function to the contract and ensure that the tokens they’re creating are truly unique if they are going to market them as NFTs. As a collector or creator, you should conduct thorough research before creating or purchasing any NFT in order to assess the contract type and the uniqueness of the digital asset. If you’re not sure whether the 1155 you’re about to purchase is truly unique, ask questions of the developers or platform you’re buying it from in order to gain certainty.

About Charged Particles

Charged Particles is a protocol that allows users to deposit ERC-20, ERC-721, and ERC-1155 tokens into NFTs. A scarce NFT (e.g. Art, Collectible, Virtual Real Estate, In-Game Item, etc.) can now be transformed into a basket holding a number of other tokens. The Principal amount can be time-locked inside the NFT, and through integration with Aave’s aTokens, the programmable yield from these DeFi yield-generating assets is just a few clicks away.

Stay in touch with Charged Particles

Website | Docs | Telegram | Twitter | Instagram | Discord | LinkedIn | YouTube | Reddit | TikTok

--

--