ERC721 Non Fungible Standard

Simple-explanantion

ERC20 is fungible token = tradeable ERC721 is non fungible token = collectible For physical coins, a gold coin is not fungible with a copper coin, because their differing characteristics give them different values to collectors. This standard can't scale

**ERC721 tokens can be used in any exchange, but their value is a result of the uniqueness and rareness associated with each token. The standard defines the functions name , symbol , totalSupply , balanceOf , ownerOf , approve , takeOwnership , transfer , tokenOfOwnerByIndex , and tokenMetadata . It also defines two events: Transfer and Approval .

Source for this part: https://medium.com/crypto-currently/the-anatomy-of-erc721-e9db77abfc24

Functions-simplified

ERC721 standard allows each unit to be unique collectible item with its own serial number ID ERC20 Functions Functions of token standard makes it easier for existing wallets to display simple information about the token. These functions let the smart contract that fits this standard act like a common cryptocurrency such as Bitcoin or Ethereum by defining functions that let users perform actions such as sending tokens to others and checking balances of accounts.

  • name - tell outside contracts and apps the name of the token

  • symbol - helps in providing compatibility with the ERC720 token standard. Provides outside programs with the token's shorter name or symbol

  • totalSupply - returns the total number of coins available on blockchain

  • balanceOf - find the numbers of tokens that a given address owns

Ownership Functions Define how contract will handle token ownership and how it can be transferred. The most notable are takeOwnership = withdraw and Transfer = send functions. Both are essential for letting users transfer tokens.

  • ownerOf - returns the address of the owner of a token. We can determine the owner of a token using its ID which this function gives

  • approve - approves and gives another entity permission to transfer a token on the owners behalf

  • takeOwnership - acts like withdraw function, can be used when a user has been approved to own certain amount of tokens and wish to withdraw X amount of tokens from someone else balanace

  • Transfer - transferring tokens, lets the owner send to another user, can be initiated after the receiving account has been approved to own the token by sending account

  • tokenOfOwnerByIndex (optional but recommended) - this contract keep a record of every unique ID of the token as the user may own more tokens, user can be retrieved by its index in the list of tokens owned

Metadata Functions Storing data on blockchain that tells the defining characteristic of each token is expensive and not recommended. We can store references like IPFS hash or HTTPS link (URL) to each token attribute on the chain in order for the dapp outside of the chain to execute logic and find the information about the token. These data are metadata [[tokenMetadata]] (optional but recommended) - discover the tokens metadata or link to them

Events Fired whenevenr a contract calls them, are broadcasted to any listening programs - dapps once they ve been fired. Dapps are listening those events so they can execute the logic once the event is fired.

  • Transfer- functions and broadcasted when the token ownership changes, details which account sent the token and received by token ID

  • approval - when user approves another user to take the ownership of a token, shows which account owns the token by ID, which is approoved to have its ownership transferred

Find snippets of code here: https://medium.com/crypto-currently/the-anatomy-of-erc721-e9db77abfc24

History of the standard

Ethereum Request for Comments 721, or ERC721, is an Ethereum Improvement Proposal introduced by Dieter Shirley in late 2017. It’s a proposed standard that would allow smart contracts to operate as tradeable tokens similar to ERC20. ERC721 tokens are unique in that the tokens are non-fungible.

ERC721 = non fungible token that can hold metadata

ERC-721 Non Fungible Token Standard

Token standard that is used to identify something or someone in a unique way. Perfect for being used as collectible item, access keys, lottery standards...

This standard has [[uinit26]] = tokenId. The [[contract-address]], uint26 tokenId must be unique. dApp usually have "converter" that uses the tokenId as input and outputs image - the NFT itself.

Token Standards are summarised and compared in the following ways:

  1. Ownership - How is the token ownership handled?

  2. Creation - How are tokens created?

  3. Transfer & Allowance - How tokens are transferred, how do we allow other addresses (contracts or extrnally owned accounts) transfer capability?

  4. Burn - How do we burn or destroy a token?

Token Ownership

token-ownership mapping(address => uint256) balances uint256 = record of how many tokens each address of the ERC721 Contract holds

If you want to transfer ERC721 then the balance is verified through balance mapping so you don’t send more than you have

Functionalities

balanceOf(address _owner)= external view returns (uint256) **ownerOf(uint256_tokenId) ** = external view returns (address)safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data) external payablesafeTransferFrom(address _from, address _to, uint256 _tokenId) external payabletransferFrom(address _from, address _to, uint256 _tokenId) external payableapprove(address _approved, uint256 _tokenId) external payable function setApprovalForAll(address _operator, bool _approved) external function getApproved(uint256 _tokenId) external view returns (address; function isApprovedForAll(address _owner, address _operator) external view returns (bool)

Fuctions

Events simplified

  • transfer token between accounts

  • get (display) current balance of an account

  • get specific token

  • total supply of the token available on the network

  • approve amount of token from an account can be moved by 3rd party account

Events of this standard

  • Transfer(address indexed_from, address indexed _to, uint256 indexed _tokenId); event

  • Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId); event

  • ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved)

Source for this part: https://ethereum.org/en/developers/docs/standards/tokens/erc-721/

ERC-721 Security

TL:DR just misleading name of the function

Intro

The ERC-721 was supposed to have a transfer security function to ensure tokens wouldn’t be stuck in recipient contracts that weren't designed to handle them. Safe functions prevent tokens from getting stuck that's why we call them safeTransfer. This function may cause reentrancy vulnerabilities which means the safeTransfer function in code is not making the contract safe - preventing it from other vulnerabilities it's actually unsafeTransfer. This function was initially named as transfer

Full disclosure

"When the ERC-721 standard was being drafted, back in the beginning of 2018, a suggestion was made to implement transfer security to ensure that tokens wouldn't be stuck in recipient contracts that weren't designed to handle them. To do this, the proposal authors modified the behavior of the transfer function to check the recipient for whether they were capable of supporting the token transfer. They also introduced the unsafeTransfer function which would bypass this check, should the sender so desire.

However, due to concerns about backward compatibility, the functions were renamed in a subsequent commit. This made the transfer function behave the same for both an ERC-20 and an ERC-721 token. However, now the recipient checking needed to be moved elsewhere. As such, the safe class of functions was introduced: safeTransfer and safeTransferFrom.

This was a solution for a legitimate problem, as there have been numerous examples of ERC-20 tokens being accidentally transferred to contracts that never expected to receive tokens (one particularly common mistake was to transfer tokens to the token contract itself, locking it forever). It's no surprise then that when the ERC-1155 standard was being drafted, it took inspiration from the ERC-721 standard by including recipient checks not only on transfer but on mint as well.

These standards mostly sat dormant for the next few years while ERC-20 maintained its popularity, but recently a spike in gas costs, as well as interest in NFTs, means that the ERC-721 and ERC-1155 standards have seen a spike in developer usage. With all this renewed interest, it sure is fortunate that these standards were designed with safety in mind, right?" -Samczsun

Source: https://www.paradigm.xyz/2021/08/the-dangers-of-surprising-code Code: https://github.com/ethereum/EIPs/commit/74dadccc858545aa89edaf6ec1cb5857cd261083

ERC721 Benchmark

"The standard enforces to emit Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId) every time a token is transferred. Events can be used to get the list of tokens owned by a user. This approach queries the Transfer events emitted by the smart contract that holds the tokens. As we will see later, querying for events is a slow operation that might fail.

ERC721 describes an optional enumeration extension to make the list of tokens fully discoverable. The ERC721Enumerable interface defines a new method tokenOfOwnerByIndex(address _owner, uint256 _index). This combined with balanceOf allow us to iterate over a user's tokens to get the token ids. This approach is much faster and reliable." Link: https://vrde.github.io/erc721-benchmark/

Further reading

  • Walking Through the ERC721 Full Implementation - A Deep Dive into Managing ERC721 Assets https://medium.com/blockchannel/walking-through-the-erc721-full-implementation-72ad72735f3c

  • OpenZeppelin implementation https://docs.openzeppelin.com/contracts/3.x/api/token/erc721#IERC721Metadata

  • OpenZeppelin Contract https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/ERC721.sol

  • Full implementation https://eips.ethereum.org/EIPS/eip-721

  • Exploring Non-Fungible Token with Zeppelin Library (ERC721) https://medium.com/coinmonks/exploring-non-fungible-token-with-zeppelin-library-erc721-399cb180cfaf

  • A Simple ERC-721 Example https://medium.com/coinmonks/a-simple-erc-721-example-c3f72b5aa19

  • ERC-721 Token - Reference Implementation by 0xCert https://github.com/0xcert/ethereum-erc721

  • ERC-721 Solmate https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC721.sol

  • Optimising ERC-721 Solmate walkthrough https://mirror.xyz/0x3fcAf7DDf64E6e109B1e2A5CC17875D4a5993F39/B3PKWKWZTk_lgLRS9oLY2sYCcYLHKdFQPyVrzDg0hZo

Last updated