Demystifying ERC Token Standards in Ethereum

Tokens are the most important and mostly used interfaces on the Ethereum platform and web3 environment. It is for this reason they are standardized to ensure smart contracts remain composable(which means when a new project issues a token, that it remains compatible with existing decentralized exchanges).

Types of Ethereum token standards

ERC-20

It is a standard interface for Fungible(interchangeable) tokens such as virtual currencies. This standard allows developers to build token applications that are interoperable with other products and services.

ERC-721

It is a standard interface for Non-Fungible Tokens(NFT) which may include artwork or songs. Used to identify something or someone uniquely.

ERC-777

Allows developers to build extra functionality on top of tokens for improved transactions privacy or emergency recovery options.

ERC-115

Allows for more efficient trades and bundling of transactions thus saving costs.

A Deep Dive Into the standards

Now with a brief introduction on the types of tokens on the Ethereum protocol, let`s do a deep dive into each of them and look at their nitty gritty details.

Note: This are not the actual details on how to create the token but an explanation on the engineering used to create the token.
Things only get interesting onwards😀.

ERC-20 Token Standard

This standard defines methods and events that should be implemented on a smart contract. A contract implementing these standards is called an ERC-20 Token Contract. It will create, monitor and perform operations on the token on the Ethereum protocol. This standard specifies the following methods:

///returns the name of the token which may or may not be present.
function name() public view returns (string)
///returns the symbol of the token which also may or may not be present.
function symbol() public view returns (string)
///returns the number of decimals which determines the lowest possible unit the token can accept.
///[Wei(18 decimal places) - Eth(1 decimal place)]
function decimals() public view returns (uint8)
///returns the total token supply defined during creation.
function totalSupply() public view returns (uint256)
///returns the number of tokens a given address has.
function balanceOf(address _owner) public view returns (uint256 balance)
///transfers _value amount of tokens to address _to, and fires the Transfer event. 
function transfer(address _to, uint256 _value) public returns (bool success)
///transfers _value amount of tokens from an address to another address and fires the Transfer event.
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success)
///approves an address to withdraw from your account multiple times, up to the maximum _value amount ///specified.
function approve(address _spender, uint256 _value) public returns (bool success)
///returns the remaining amount to which an address can still withdraw from your account.
function allowance(address _owner, address _spender) public view returns (uint256 remaining)

The standard also defines events which are triggered when certain operations occur.

///triggered when tokens are transferred, including zero value transfers.
event Transfer(address indexed _from, address indexed _to, uint256 _value)
///triggered on any successful call to approve method.
event Approval(address indexed _owner, address indexed _spender, uint256 _value)

ERC-721 Token Standard

This standard defines methods and events that should be implemented on a smart contract. A contract implementing these standards is called an ERC-721 Non-Fungible Token Contract. It will create, monitor and perform operations on the token on the Ethereum protocol.

All NFTs have a uint256 variable called tokenId which must be globally unique. This standard specifies the following methods:

///Count all NFTs assigned to the owner`s address.
function balanceOf(address _owner) external view returns (uint256);
///returns the owner`s address of an NFT.
function ownerOf(uint256 _tokenId) external view returns (address);
///transfers the ownership of an NFT from one address to another address
function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data) external payable;
///transfers the ownership of an NFT from one address to another address
///This works identically to the other function with an extra data parameter,
///  except this function just sets data to "".
function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable;
///Transfer ownership of an NFT
function transferFrom(address _from, address _to, uint256 _tokenId) external payable;
///Change or reaffirm the approved address for an NFT
function approve(address _approved, uint256 _tokenId) external payable;
///Enable or disable approval for a third party address ("operator") to manage an NFT.
function setApprovalForAll(address _operator, bool _approved) external;
///Get the approved address for the specified NFT.
function getApproved(uint256 _tokenId) external view returns (address);
///Query if an address is an authorized operator for another address.
///True if `_operator` is an approved operator for `_owner`, false otherwise.
function isApprovedForAll(address _owner, address _operator) external view returns (bool);

The standard also defines events which are triggered when certain operations occur.

///Triggered when ownership of NFT changes by any mechanism.
event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);
///Triggered when the approved address for any NFT is changed or reaffirmed.
event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId);
///Triggered when an operator address is enabled or disabled for an owner.
event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);

ERC-777 Token Standard

It is a Fungible token standard which improves the existing ERC-20 token standard. The ERC-777 provides the following improvements over ERC-20:

1. Hooks

It is a function described on the smart contract and gets called when tokens are sent or received through the contract. It allows smart contracts to react to incoming or outgoing tokens. The hook can perform the following operations:

  • Hooks can reject transactions.

  • Hooks allow sending tokens to a contract and notifying the contract in a single transaction, unlike ERC-20 which requires a double call (approve & transferFrom) to achieve this.

2. Decimals

It solves the confusion around decimals caused in ERC-20 token standards.

The ERC-777 standard adds the following methods to an ERC-20 contract:

/// returns the granularity (smallest amount of tokens) which may be minted, sent or burned at any time.
function granularity() external view returns (uint256)
///returns the list of default operators as defined by the token contract.
function defaultOperators() external view returns (address[] memory)
///sets a third party address as an operator of (msg.sender) to send and burn tokens on its behalf.
function authorizeOperator(address operator) external
///removes the right of the operator address to send and burn tokens.
function revokeOperator(address operator) external
///Indicates whether the operator address is an operator of the holder address.
function isOperatorFor(address operator,address holder) external view returns (bool)
///Send the amount of tokens from the address msg.sender to the address to.
function send(address to, uint256 amount, bytes calldata data) external
///Sends the amount of tokens on behalf of the address.
function operatorSend(address from,address to,uint256 amount,bytes calldata data,
bytes calldata operatorData) external
///Burn the amount of tokens from the address (msg.sender).
function burn(uint256 amount, bytes calldata data) external
///Burn the amount of tokens on behalf of the address from.
function operatorBurn(address from, uint256 amount,bytes calldata data,
    bytes calldata operatorData) external

The standard also defines events which are triggered when certain operations occur.

///Indicates the authorization of operator as an operator for holder.
event AuthorizedOperator(address indexed operator, address indexed holder)
///Indicates the revocation of operator as an operator for holder.
event RevokedOperator(address indexed operator, address indexed holder)
///Indicates a send of amount of tokens by the operator address.
event Sent(address indexed operator,address indexed from,address indexed to,
    uint256 amount, bytes data, bytes operatorData)
///Indicate the minting of amount of tokens to an address by the operator address.
event Minted(address indexed operator,address indexed to,uint256 amount,
    bytes data,bytes operatorData)
///Indicate the burning of amount of tokens from an address by the operator address.
event Burned(address indexed operator,address indexed from, uint256 amount,
    bytes data,bytes operatorData)

The hooks functions implemented are:

///Notify a request to send or burn an amount tokens from an address to another address by the ///operator address.
function tokensToSend(address operator,address from, address to,uint256 amount,
    bytes calldata userData,bytes calldata operatorData) external
///Notify a receival of tokens from an address by the operator address.
function tokensReceived(address operator,address from,address to,uint256 amount,
    bytes calldata data,bytes calldata operatorData) external

ERC-1155 Token Standard

It is a standard interface for contracts that manage multiple token types. May include combinations of fungible tokens, non-fungible tokens or other configurations. (e.g semi-fungible tokens). The ERC-1155 token can do the same functions as an ERC-20 and ERC-721 token, and even both at the same time while improving efficiency.

The standard introduces the following functions:

///similar to regular ERC-20 transferFrom but passes arrays for 
///_values and _ids
function safeBatchTransferFrom(address _from,address _to,uint256[] calldata _ids,
    uint256[] calldata _values,bytes calldata _data) external;
///we can retrieve multiple balances in a single call by passing arrays in
///_owners and _ids
function balanceOfBatch(address[] calldata _owners,uint256[] calldata _ids)
 external view returns (uint256[] memory);
///Explicitly approve an address to operate on any amount of tokens
function setApprovalForAll(address _operator,bool _approved) external;
///Check if an address is approved to operate on any amount of tokens
function isApprovedForAll(address _owner,address _operator) external view returns (bool);

The standard also implements receive hooks for smart contracts which must return a magic predefined bytes4 value. When the receiving contract returns this value, it is assumed the contract accepts the transfer and knows how to handle the ERC-1155 tokens thus no more stuck tokens in a contract.

function onERC1155BatchReceived(address _operator,address _from,uint256[] calldata _ids,
uint256[] calldata _values,bytes calldata _data) external returns(bytes4);

The standard also introduces Safe Transfer Rules which include:

  1. In ERC-1155 we only have transferFrom, no transfer. To use it like a regular transfer, just set the from address to the address that's calling the function
  2. The caller must be approved to spend the tokens for the _from address or the caller must equal _from.

3.The transfer call must revert if:

  • _to address is 0.

  • length of _ids is not the same as length of _values.

  • any of the balance(s) of the holder(s) for token(s) in _ids is lower than the respective amount(s) in _values sent to the recipient.

  • any other error occurs.

That`s a wrap guys

Goodbye👋👋 and Happy Coding😃😃