Science | What is the ERC-777 token contract?
ERC-777 is a new token contract standard that addresses some of the security issues of ERC-20, allowing contract creators, token holders and audiences to extend their functionality without changing tokens. ERC-777 draws on many ideas from standards such as ERC-20 and ERC-223, and has evolved into a new generation of standards that provide developers and users with many powerful features.
This article mainly introduces the token contract and explains the features, functions and uses of the ERC-777 token contract. Please note that this article does not cover ERC-20. If you want to know more about the ERC-20 token contract, you can take a look at another article (Editor's Note: Chinese translation at the end of the article, "Understanding the ERC-20 token contract").
What is a token contract?
A token contract refers to a smart contract that contains a set of account addresses and their corresponding balances, as shown in the following figure. The balance represents a value defined by the contract creator: the token contract can use the balance to represent the physical, currency or holder's reputation. The balance of a unit is what we usually call a token.
– Figure 1: Address and its token balance table –
It should be noted that an end user may have as many addresses as you want. There are many reasons for this. For example, users want to spread the tokens they hold into different logical accounts (savings, taxes, expenses, etc.) or use different accounts to represent different sources (ICO, Investment, service fee payment, etc.).
Whenever a token is transferred from one account to another, the token contract will update the balance of the two accounts. For example, after transferring 10 tokens from 0x2299…3ab7 to 0x1f59…3492, the balance update is as shown in the following table:
– Figure 2: After transferring 10 tokens from 0x2299…3ab70 to 0x1f59…3492, the balance changes as indicated by the red mark –
It is possible to increase the total supply (usually the function of the token contract owner) by casting new tokens. For example, if 100 tokens are cast in 0x4ba5..ae22, the balance is updated as shown in the following table:
– Figure 3: Casting 100 tokens in 0x4ba5..ae22, the balance changes as shown in the red mark –
The total supply of tokens can be reduced by destroying existing tokens (any token holder can destroy tokens if the contract allows). For example, after 0x4919…413d destroyed 50 tokens, the balance changes as shown in the following table:
– Figure 4: After destroying 50 tokens in 0x4919…431d, the balance changes as indicated by the red mark –
A simple token contract will save the above information in the mapping table of addresses and balances. If it is in a more complex scenario, such as dividends, etc., a more powerful structure is usually adopted. However, regardless of the specific implementation details, the token balance is always as shown in the chart above.
Operator of the ERC-777 Token Contract
The ERC-777 token contract introduces the concept of an operator. The operator is a third party operating on behalf of the token holder and can transfer the token from the holder's address. Please note that due to the operator's great power, it should be added with caution.
Each address contains an authorized list of operators, as shown in the above table:
– Figure 5: Operator of the token holding address –
As shown in the above table, the token holding address 0x1f59…3492 has two operators, and the other two addresses each have an operator. Of course, no operator's address is valid.
A simple example of using an operator is that the user has tokens on multiple address tokens that must be managed separately. In general, before sending a token from one address to another, make sure that there is an ETH in the sender's address that is sufficient to cover the gas charge. Therefore, when sending ETH from one account to another, the sender needs to complete several transactions first, as shown in the following figure:
– Figure 6: Pay money to your account before sending tokens –
As shown in the figure above, the address 0x93f1…1b09 sends ETH to the address 0x1f59…3492 first. After the transaction is completed, the address 0x1f59…3492 sends the token to 0x4ba5…ae22. Such a multitude of steps reduces the user experience and increases network load.
With the operator, as long as there is ETH in one account and other tokens in other accounts, the money transfer can be performed by the account holding ETH. Looking at the previous example, if 0x93f1…1b09 is used as the operator of 0x1f59…3492, the process of sending tokens from 0x1f59…3492 to 0x4ba5…ae22 can be simplified to:
– Figure 7: Sending tokens on behalf of another account –
This greatly reduces the burden on the user. In addition, this allows users to control their ETH funds through an operator account while ensuring that their tokens are spread across multiple currency holding accounts.
The operator may also be in the form of a contract (ie, "token operator contract"), and the token operator contract can be pre-defined for all the holders when the token contract is created. In this way, the operator can provide services to all the money-holding users, and its functions are limited to the function of the smart contract. The token contract can provide more functions to the holder without any effort. The powers of the token contract operators will be explained in detail later.
Definition of ERC-777 Token Contract
Each ERC-777 token contract deployed to Ethereum will be assigned an address, the token address. This token contract will contain some parameters that define the contract operation.
The first thing to understand is that because the token contract lacks a centralized registry, there is no guarantee that the name or symbol will be unique. In this way, the best way to get and retain your unique identity is to open your token contract. Once you've created a token contract, you should add it to popular websites like Etherscan, MyEtherWallet, MyCrypto, CoinMarketCap, etc., but be sure to follow the requirements of each site so that your submission is accepted. Only the biggest.
The name of the token contract is used to refer to the long name of the contract itself, such as "My token". There is no limit to the length of the name, but some wallet apps may truncate long names, so keep the length of the name within a short range.
The symbol of a token contract is a short symbol used to refer to the contract itself, such as "MYT". This symbol is similar to the stock code. Although there is no length limit, it is usually around 3 to 4 characters.
Solidity (the programming language used primarily by Ethereum) does not support decimals, but severability is a common requirement for tokens. The solution adopted by the ERC-777 is that the amounts shown internally for all tokens are expressed as an integer multiple of 1018 of their actual amount. For example, the 1.2345 token seen by the end user is actually represented internally by 1.2345×1018. In this way, even if a token is split into 0.000000000000000001, it is still represented internally as an integer, as shown in the following table:
– Figure 8: The amount shown inside the token is 1018 – the amount seen by the end user –
The creators of some token contracts may not want their tokens to be so fine. For example, if a user creates a software license token contract, he may not want to see a complete license split. Or, if a user creates a gold token contract with 1 token for 1 Kg of gold, he may want to limit the transfer amount to 0.01 Kg and above.
The granularity of the token contract is the smallest divisible unit of the amount shown inside the token. Following the example above, the granularity of the license token should be 1018 (because 1018/ 1018 = 1), while the granularity of the gold token should be 1016 (because 1016/1018 = 0.01).
It can be expected that the vast majority of tokens have a granularity of 1, which means that the token can be split into 1/1018 or 0.000000000000000001. According to the example given above, if there are specific requirements for the severability of the token, different granularities can be selected.
Let's explore the difference between the granularity of ERC-777 and the fraction of ERC-20. Although both can achieve the severability of tokens, ERC-20 is based on specific values to move the position of the decimal point, while the decimal point position of ERC-777 is fixed. In this way, the value of the ERC-777 token is easier to display on the user interface, because the position of the decimal point is always fixed, except that a series of 0s are removed.
ERC-777 token contract function
The ERC-777 Token Contract has many features that allow users to find account balances and transfer tokens from one account to another under different conditions. The details of these functions are as follows.
The totalSupply() function specifies the total amount of tokens held by all addresses. If a new token is cast, this value will increase, and if the existing token is destroyed, the value will decrease.
The balanceOf() function specifies the number of tokens held by a particular address. It is important to note that anyone can ask for the balance of any address because all data on the blockchain is public.
The send() function transfers a certain amount of tokens from the sender's address to another address. Compared to the ERC-20 token, the ERC-777 token is more fully functional. See below for details.
The burn() function destroys a portion of the tokens held by the sender of the message. Compared to the ERC-20 token, the destruction function of the ERC-777 token is more complete, as described later.
The authorizeOperator() function allows the sender of the message to authorize his own token to another address (Translator's Note: Authorize the operator).
The revokeOperator() function can revoke the permissions of the existing operator control message sender token.
isOperatorFor() Describes whether an address is the operator of a token holder.
As long as the sender has operator rights to an account, a certain amount of tokens can be sent from that account to another account via the operatorSend() function.
The defaultOperators() function provides a list of token operator contracts, and the operators in the list have all the permissions for all tokens; for this feature, see the “Token Operator Contracts” section below.
Events involved in the ERC-777 token contract
ERC-777 defines events that can be used to track individual and overall information about a token contract.
Once a new token has been cast, the Minted() event is fired. The event contains information on the number of new casting tokens and their destination addresses.
The Burned() event is fired once the existing token is destroyed. This event contains information on the number of destroyed tokens and the source address.
Once a token has been transferred from one address to another, the Sent() event is fired. The event contains the number of transferred tokens, as well as information about the holder's address and the recipient's address.
In addition to the above events, the ERC-777 token standard also includes two managed events. Once the user has added an operator to their own address, the AuthorizedOperator() event is fired. The RevokedOperator() event is fired once the user removes an operator from their own address. It is important to note that these events do not contain information about the amount of tokens and changes in ownership.
Explain the sending function of the ERC-777 token contract
Sending ERC-777 tokens from one address to another takes a few steps to complete. In this process, the ERC-777 token standard has demonstrated its superiority in terms of functionality and security.
The common token sending process is shown below:
– Figure 9: Common token delivery process –
Specific steps are as follows:
- Verification: Ensure that the input parameters are valid, verify that the address has sufficient tokens to send, and that the amount sent is a multiple of the token size
- Authorization: Ensure that the sender has the right to send tokens, the sender must be the holder of these tokens or the operator with the corresponding address authority
- Send: Perform token transfer to update the currency information of each address on the token contract
- Log: Send an event with all operational details
ERC-777 adds two new steps based on the above steps, as shown in the following figure:
– Figure 10: ERC-777's token delivery process –
As you can see, ERC-777 adds two steps, tokensToSend() and tokensReceived(), to the common process. The call to tokensToSend() is placed after verifying the transaction information and completing the authorization, but before updating the currency information of the contract address. The call to tokensReceived() is placed after the currency information of the update contract address. At first glance, the new steps don't seem to make the whole process complicated. However, the strength of tokensToSend() and tokensReceived() is that they are not defined by the contract address, but are located in the contract between the sender and receiver of the token. As a result, the sender and the receiver have the right to decide whether or not to complete the transaction, and can also implement more advanced functions.
– Figure 11: tokensToSend() and TokensReceived() in different contracts –
tokensToSend() allows the holder to provide conditions and actions in the form "before the token leaves the account." tokensReceived() allows the token recipient to provide conditions and actions in the form of "when the token arrives at the account…".
The purpose of tokensToSend()
Imagine a scene. Suppose a company's chief financial officer has developed a transfer rule for multiple monetary funds. This CFO allows the finance manager to use the funds while complying with the company's rules, while retaining control over the rules and funds, as shown below:
If the funds are in the form of ERC-777 tokens, the settings in the above figure can be easily achieved. The following steps are required:
- The rules set by the CFO are coded into a token control contract and the contract is applied to the company’s currency holding address.
- The chief financial officer authorizes the financial manager to become the operator of the company's currency holding address
- Finance manager uses operatorSend() to send funds
What rules can the CFO make? Almost all rules can be coded into smart contracts. Here are a few examples:
- Only allow operators to spend a certain amount of money (tokens)
- Set daily/weekly/monthly spending limits for operators
- Operators can only send funds to a group of authorized payees
- The operator can only spend the funds if a reference to the invoice approved by the chief financial officer is provided.
- and many more
One thing to keep in mind is that you can set up multiple sets of rules for different types of ERC-777 tokens held by the company, as well as the same set of rules for multiple ERC-777 tokens. In this way, the CFO can make rules that suit his company's situation, and the financial manager can only follow these rules.
The same address can also have multiple operators. Therefore, if the financial manager has an agent, as long as his agent follows the same rules (or other rules), he has the right to access the funds.
tokensToSend() is designed to control the transfer of funds in one or more accounts by making rules on transactions. To put it bluntly, tokensToSend() is to let the user complete the sentence "Before the token leaves my account…". These rules are defined in the token control contract. The same token control contract can be used for multiple ERC-777 token contracts, as well as between multiple accounts, thus ensuring uniformity of rules between accounts.
The purpose of tokensReceived()
Similar to tokensToSend(), tokensReceived() will receive a notification that the token has been transferred to the account. Following the example above, the company has an accounting department responsible for payment. Every time you receive a payment, you need to check whether it matches the invoice and assign it to the company's internal department. After receiving this funding, the accounting department needs to perform the following steps:
- If the funds received have an invoice reference number, they are checked against the invoice and credited to the appropriate department.
- If the funds received are from a known sender, they are credited directly to the appropriate department.
- In addition to the above, deposit the funds into the holder of the money and investigate
In the case of tokensToSend(), the above procedure is just an instance, and it actually describes all the rules. For example, early payment can be discounted (additional charges for deferred payment), only which currencies are accepted, and so on. This only requires one step:
1. The department's process is programmed into a token control contract and the contract is applied to the company's collection address
In general, tokensReceived() is not as complicated as tokensToSend() for two reasons. First, tokensReceived() usually contains only one participant (receipt address), while tokensToSend() will involve the operator. Second, users are generally more concerned about payments than payments. Still, tokensReceived() is a very powerful feature that helps large organizations like exchanges manage the funds they have received.
tokensReceived() is designed to control the flow of funds into one or more accounts by making rules on transactions. To put it bluntly, tokensReceived() is to let the user complete the phrase "contemporary coins enter my account…". These rules are defined in the token control contract. The same token control contract can be used for multiple ERC-777 token contracts, as well as between multiple accounts, thus ensuring uniformity of rules between accounts.
Requirements for tokensToSend() and tokensReceived()
tokensToSend() is optional; if not selected, tokens are sent according to common procedures. tokensReceived() is also optional unless the receiving account is a contract, which is mandatory in this case. Forcing all token-receiving contracts to execute tokensReceived() ensures that tokens will only be sent to contracts that proactively handle these tokens. This is the main goal of ERC-223. In addition, ERC-777 has implemented other safeguards, which is to force the recipient to register whether it can receive ERC-777 tokens and ERC-1820 tokens.
Token operator contract
As mentioned above, the token operator contract is the contract that calls operatorSend() on the ERC-777 token contract. The strength of this type of contract is that they can extend the capabilities of ERC-777 without changing the ERC-777 token contract itself.
When the holder of the currency wants to send the token to another address, he will call send() directly on the token contract, as shown below:
– Figure 13: Sending tokens directly –
However, any user can also send tokens by calling a token operator contract. Through this contract, any user can send tokens on behalf of the holder, as shown below:
– Figure 14: Sending tokens via token operator contract –
At the time of the creation of the token contract, the token operator contract (ie default operator) can be enabled for all holders or, if necessary, enabled for individual holders.
The token holder contract can provide additional functionality to the token holder. For example, sending tokens in bulk is a common requirement, but it is not noted in the ERC-777 standard. Before deploying the ERC-777 token contract, it is possible to add a bulk send function, but this will introduce custom attributes for the token contract, so it is more prone to errors.
Another solution is to write a separate token operator contract that enables bulk delivery and deploy it separately. The token operator contract can accept transactions from the holders and send the tokens repeatedly by calling operatorSend() based on the details of which tokens are sent to the payee as recorded in the transaction.
In order to implement the bulk transfer function, a standard ERC-777 token contract will be deployed along with a batch delivery operator contract as the default operator. Now, any holder can call the send() function on a token operator contract to send multiple tokens from their own account with just one transaction. If the token contract does not indicate that the bulk carrier contract is to be used as the default operator contract, the holder can customize the account for the account.
Note that as shown in the figure above, the token operator contract has only one send() function, but a complex token operator contract can have multiple send() functions. For example, a bulk delivery token operator contract may have the ability to send the same number of tokens to multiple payees, send different amounts of tokens to multiple payees, and so on.
In addition to the functions mentioned in the above examples, the user who invokes the token operator contract may also be a person other than the holder. Allowing outsiders to send tokens instead of holders may sound dangerous, but it is actually very useful in many scenarios. By separating the holder and the user who requested the transfer, more functions can be implemented, such as:
- Send tokens with the authorization of the holder (“free transfer”)
- Exchange tokens for other tokens (eg ICO, distributed transactions)
- Once the specific conditions are met, the tokens are sent immediately (performance-based rewards, time-locked tokens)
In short, the token operator contract can modify the rules to specify when the token can be transferred from one account to another. This is a very powerful feature that requires the user to fully trust the token operator contract. It is conceivable that some well-known token operator contracts will be deployed on the Ethereum main network to achieve specific functions. Token contract creators and individual holders can extend the functionality by selecting the token operator contract they want, thereby increasing the efficiency and security of token transfers.
In the next article, we'll delve deeper into the token operator contract.
Difference between token operator contract and token control contract
At first glance, the token operator contract is not much different from the tokensToSend() in the token control contract. In fact, there are some differences between the two.
The token operator contract is optional; any holder can ignore this feature and call send() directly. The token control contract is mandatory and cannot be ignored.
Anyone can call the token operator contract. The token control contract is invoked as part of the send() and operatorSend() operations and can therefore only be called by the holder (or the holder of the holder).
In general, the token operator contract focuses on expanding the functionality of the token contract. The token control contract focuses on controlling the token flow from the account.
The following table summarizes the differences between token operator contracts and token control contracts:
Compatibility with ERC-20
A keen reader may have noticed that although the functions provided by ERC-20 and ERC-777 are similar, the names of these functions are different; the name used by ERC-20 is transfer()/approve()/transferFrom (), and the name used by ERC-777 is send()/operatorSend(). This means that the same token contract is likely to offer the same ERC-20 and ERC-777 capabilities. Specific operating modes and trigger events are detailed in the ERC-777 standard.
The ERC-777 comes with a reference implementation that also includes a version that is compatible with the ERC-20 standard. Samples of token operator contracts and token control contracts are available separately.
More about ERC-777
There is also an article that also provides an in-depth analysis of the ERC-777 token operator contract, which mentions many examples of how to use the contract to extend the functionality of the basic ERC-777 token contract.
Author: Jim McDonald
Translation & Proofreading: Min Min & A Jian
(This article is from the EthFans of Ethereum fans, and it is strictly forbidden to reprint without the permission of the author.