A few months ago I decided to learn Solidity, the programming language used for writing smart contracts for the Ethereum blockchain.
This article isn’t an intro to Solidity, so I’m going to assume you know what a blockchain is, what Ethereum is, and the very basics of Solidity. *(See footnotes if you are a beginner).
Over the next few posts, I’ll be exploring the ERC721 Standard, how it works, its variants, and writing a scalable implementation that you are free to use. In this post, we won’t be starting any coding. I’ll be introducing you to Non-Fungible Tokens, and ERC Standards, in general, to begin with.
What is the ERC721 Standard?
The ERC721 Standard is a (draft) standard for creating Non-Fungible Token (NFT) contracts. Non-fungible means not completely interchangeable. A dollar coin is fungible, because if I give you a dollar coin and you give me a dollar coin, neither of us are better or worse off — a dollar is a dollar. However, if I give you my pet cat and you give me your pet cat, we may not be happy, because pet cats are not completely interchangeable — they are non-fungible.
In 2017, the game Cryptokitties demonstrated how non-fungible assets can be made and traded on the Ethereum blockchain. In this game, players can breed and trade Kitties — but crucially, all the Kitties exist on the blockchain, and can only be bred or traded by the player who owns them. Contrast this to a traditional online game where the data is stored on a central server, and game admins are able to make changes as they see fit. In Cryptokitties, players buy and sell their Kitties on a decentralised and trustless network, with ownership of their Kitties being irrefutably provable. If you own a Kitty, the blockchain proves that it’s yours and nobody else’s.
You may be thinking, “So what? It’s just a game with pretend cats!”
The goal of Cryptokitties was to show that non-fungible assets can be made and traded on the blockchain. Suppose that instead of representing a pretend cat, your NFT could represent the deed to a house. You could sell that token to someone else, and ownership of the token and payment (in ETH) could be exchanged without the need for any expensive lawyers or any other middlemen.
And so, through Crpytokitties, the idea for an NFT standard was introduced to the Ethereum community. That idea became a proposal, and that proposal became a draft for a standard, which is what we have today, the ERC721 (draft) Standard. The number 721 isn’t particularly meaningful, it was just the 721st Ethereum improvement proposal on Github.
So what actually is it?
An ERC standard is basically a set of rules which enables your contract play to well with other developers’ contracts (or DApp, website, other software, etc). By providing some guidelines for required functions, and some restrictions on how they should behave, other programmers can write code that interacts with yours without having to know your entire codebase.
To pick one example, the
balanceOf function is defined by the standard:
function balanceOf(address _owner) external view returns (uint256);
The standard says that your ERC721 contract must include this function. It must take one argument (an address), and must return the number of tokens that address owns (a uint — these are non-fungible tokens so they can’t be divided).
The standard doesn’t really care how your function works. It could be as simple as returning the value of a mapping, or some complex series of equations and internal function calls. The only thing the standard cares about is that when someone calls
balanceOf on an address they get a uint with the balance of that address.
I say the standard doesn’t really care about how your function works, because in some cases there will be extra instructions or restrictions. For the above
balanceOf function, the standard has the following restriction:
/// @dev NFTs assigned to the zero address are considered invalid, and this function throws for queries about the zero address.
So, if someone calls
your function must throw an error. When writing your ERC721 compliant contract, you must make sure all your functions adhere to their respective rules. I’ll address these as they come up.
Some things to note
The standard doesn’t prevent you from adding extra functions, or extra rules to your contract. As long as your additions don’t conflict with the rules laid out by the standard, they’re perfectly acceptable.
I’ve seen many questions on Stack Exchange where people have thought a particular contract or interface file they found online was the standard, either for ERC721 or ERC20 (the Fungible token standard). They worry that their contract isn’t identical to a particular implementation, and often try to “fix” something that isn’t a problem. This is why returning to the ERC721 standard is always a good idea when writing your own contract from scratch. It says in clear English (and Solidity) what is and is not allowed.
So if you follow all the rules set out by ERC721, then regardless of what else is going on in your NFT contract, it will be compliant. Compliance is a good thing, because it means it will be easier for other people to use your token. If it’s easier to use, then people are more likely to adopt it.
I hope this has been a useful introduction to the ERC721 standard. In my next post we’ll take a look at some code for the standard’s interfaces, and I’ll cover some aspects of the ERC721 standard that I found confusing in the beginning.
- If you’re new to Solidity, there are plenty of excellent resources out there, but be careful because Solidity is rapidly evolving so a lot of the online resources may be out of date. At the time of writing, we’re up to Solidity 0.4.21, and any resources that cover versions below about 0.4.16 may not be useful. I found this Udemy course particularly helpful as an entry point.