Non-Fungible vs Re-Fungible Tokens in Solidity
What is the next evolution of NFTs, and how do we implement it? Behold, the RFT …
NFTs exist on top of an existing blockchain protocol, with its own native currency. NFTs are not just native to Ethereum, although the specification was created as an Ethereum Request for Comment, otherwise known as an ERC. ERC721-like implementations exist on several other chains that do not run on the Ethereum Virtual Machine (EVM). Nonetheless, as the NFT space continues to boom, there has been a sleeping giant awaiting adoption (IMO).
You may have an understanding of a Non-fungible Token, so I will skip the bare fundamentals about what they can be used for — this is not a buzzword-fest 😎
The key concept of a vanilla ERC721 contract is to understand that each token minted to a contract has a unique ID, thus making each token unique in at least that property. NFTs are also associated with a Base URL (this can be centralized (a server) or decentralized (IPFS, etc). To retrieve the attributes of the token, a user can simply invoke the Base URL, concatenated with the Token ID.
NFTs have a subtle, but important feature, to which some may refer as a “limitation” — this is the concept of single-address ownership. This means that each NFT can only have one owner, a single address. If you look at the ERC721 specification, each token minted using a single ERC721 contract has an associated token ID, and an associated address.
If a new NFT is minted without a specific receiving address, the NFT is owned by the zero address by default. Every time an NFT has its ownership exchanged, the owning address is the variable being changed. If the zero address owns the token, the contract itself can then transfer ownership of the token.
However, this can introduce a limitation to real world applications. Intuitively, we don’t typically see a single Pokemon card being owner by several people, but it can be. If we wanted a group of people to own a single Pokemon card, we can form a company, and provide ownership in the company to the proposed owners of the card. This structure still adheres to the single-ownership requirement of ERC721 specification, but it adds a layer of organization for the owners of the card.
This is where the RFT comes in. Intuitively, an RFT is result when you merge the non-fungibility from an ERC721 token, with concepts from an ERC 20 Token.
Instead of the minted ERC721 tokens being owned by a user’s address. Each Minted Token is now owned by the smart contract itself — although this is still a single address owning the token, this slight difference allows us to take one more step towards fractional ownership.
With the NFT being owned by the smart contract, we can now write into the contract that it should represent ownership of the owned token by issuing ERC20 tokens to addresses. Users can then buy those ERC20 tokens, which will be representation of fractional ownership in the NFT.
Combining these concepts together extends the application of NFTs. There is a lot of talk about NFTs being used in real estate, and publishing. However, these applications cannot thrive with single-owned NFTs — given the use cases themselves. Re-fungible Tokens, RFTs, or fractionally-owned NFTs (whatever you want to call them) is a natural progression of the NFT — maybe we call them NFT v2? NFT 2.0?…
Let us look at the source code for a vanilla Re-Fungible Token:
The first two variables on lines 10 and 13 are set in the constructor. These variables define the price of each share, and the amount of token supply.
Line 16 defines the static NFT Identifier. In the ERC721 specification, this is equivalent to the Token ID representing each minted token — similar to the common NFT implementation, the Token ID is static. In the actual ERC Specification for NFTs, it was rightfully stated by Deiter Shirley:
This identifying number MUST NOT change for the life of the contract.
Line 17 & 18 are where the magic happens. Line 17, the “NFT” variable, stores the actual ERC721 token itself. This is the token represented by the contract. The ERC20 token defined on line 18 is the token representing the fractional shares of the NFT. In this contract, the token is DAI. However, any ERC20 Compliant token can be used here.
Now, let us look at the constructor for this implementation. Typically, NFT implementations define a name, and symbol upon contract creation. However, as mentioned above, sometimes an implementation may include a base URL, of which is used to reference the Metadata for each token minted under the same tracking contract.
However, this implementation of an RFT defines a few arguments in its constructor on lines 24–29.
- Name of the RFT
- Symbol of the token
- NFT Address: The contract address of the NFT tracking contract
- Static Token ID of the NFT being represented by the RFT
- Share Price
- Supply of Shares
Since this RFT example inherits from the ERC20 contract, Line 32 invokes the ERC20 constructor, and passes the Name, and Symbol as arguments. In the constructor, we simply assign our variables. This including the administrator’s address, of which is the sender of the contract creation transaction.
The “start()” function can only be called by the administrator.
This function is also responsible for transferring the NFT, with the defined identifier, from the administrator, to the contract.
As I mentioned before, the RFT contract is in possession of the NFT — once the administrator invokes the start() function.
Finally, when an account wants to purchase shares of the token, we first ensure there are enough shares to be purchased if we take the current total supply plus the proposed amount of shares (since we mint shares to the purchaser). If so, we multiply the share price (in the chosen ERC20 token), by the amount of shares requested by the transaction. Finally, we transfer the amount of the ERC20 tokens, from the address, to the contract, and then mint the amount of shares to the sending address.
The ellipses in the code snippet above, represent obvious places of customization. However, this is code (obviously). So, all of it is customizable. This Vanilla version of an RFT contract is not designed for production, but serves as an initial starting place for experimental implementations.
It is referred to as a Refungible Token because we are taking something that is Non-Fungible, and making it Fungible again ¯\_(ツ)_/¯
Our goal here is to demonstrate the potential RFTs can have if applied creatively, and I hope you understand the differences this implementation has when compared to a standard ERC721 contract — and how an RFT uses both the ERC721, and ERC20 token standards.