Automatically merged updates to draft EIP(s) 777

Hi, I'm a bot! This change was automatically merged because:

 - It only modifies existing draft EIP(s)
 - The PR was approved or written by at least one author of each modified EIP
 - The build is passing
This commit is contained in:
Jacques Dafflon 2018-05-26 13:20:51 +02:00 committed by EIP Automerge Bot
parent 79bd95f017
commit 41a70423cf
1 changed files with 30 additions and 32 deletions

View File

@ -14,17 +14,17 @@ requires: 820
This EIP defines a standard interface for token contracts.
*The repository for this standard containing the reference implementation can be found at [jacquesd/ERC777](https://github.com/jacquesd/ERC777) and installed via npm with: `npm install erc777`.*
*The repository containing the reference implementation for this standard can be found at [jacquesd/ERC777](https://github.com/jacquesd/ERC777) and installed via npm with: `npm install erc777`.*
## Abstract
This standard defines a new way to interact with a Token Contract.
It defines operators to send tokens on behalf of another address contract or regular account. It takes advantage of [ERC820](https://github.com/ethereum/EIPs/issues/820) to find out whether and where to notify contracts and regular addresses when they receive tokens as well as to allow compatibility with old contracts.
It defines operators to send tokens on behalf of another address contract or regular account. It takes advantage of [ERC820](https://eips.ethereum.org/EIPS/eip-820) to find out whether and where to notify contracts and regular addresses when they receive tokens as well as to allow compatibility with old contracts.
## Motivation
This standard tries to improve the widely used [ERC20](https://github.com/ethereum/EIPs/issues/20) token standard. The main advantages of this standard are:
This standard tries to improve the widely used [ERC20](https://eips.ethereum.org/EIPS/eip-20) token standard. The main advantages of this standard are:
1. Uses the same philosophy as Ether in that tokens are sent with `send(dest, value, data)`.
2. Both contracts and regular address can control and reject which token they send by registering a `tokensToSend` function rejection is done by throwing in the function.
@ -32,7 +32,7 @@ This standard tries to improve the widely used [ERC20](https://github.com/ethere
4. The `tokensReceived` function also avoids the double call needed in the ERC20 standard (`approve` / `transferFrom`).
5. The token holder can "authorize" and "revoke" operators who can send tokens on their behalf. These operators are intended to be verified contracts such as an exchange, a cheque processor or an automatic charging system.
6. Every token transaction contains a `userData` bytes field and a similar `operatorData` in case of an operator transaction to be used freely by the user (token holder) and the operator respectively to pass data to the recipient.
7. It is backwards compatible way with wallets that do not contain the `tokensReceived` function by deploying a proxy contract for the wallet.
7. It is backward compatible with wallets that do not contain the `tokensReceived` function by deploying a proxy contract for the wallet.
## Specification
@ -46,7 +46,6 @@ interface ERC777Token {
function granularity() public constant returns (uint256);
function balanceOf(address owner) public constant returns (uint256);
function send(address to, uint256 amount) public;
function send(address to, uint256 amount, bytes userData) public;
function authorizeOperator(address operator) public;
@ -69,7 +68,7 @@ interface ERC777Token {
}
```
The token-contract MUST register the `ERC777Token` interface via ERC820.
The token-contract MUST register the `ERC777Token` interface with its own address via ERC820. If the contract has a switch to enable or disable ERC777 methods, every time the switch is triggered, the token MUST register or unregister its own address accordingly the `ERC777Token` interface via ERC820. (Unregistering implies setting the address to `0x0`.)
The basic unit token MUST be 10<sup>18</sup>.
@ -112,7 +111,7 @@ Most of the tokens SHOULD be fully partitionable, i.e. this function SHOULD retu
*NOTE*: `granularity` MUST be greater or equal to `1`.
> **returns:** The smallest non divisible part of the token.
> **returns:** The smallest non-divisible part of the token.
<br/>
@ -145,15 +144,14 @@ Get the balance of the account with address `tokenHolder`.
##### send
``` solidity
function send(address to, uint256 amount) public
function send(address to, uint256 amount, bytes userData) public
```
Send `amount` of tokens to address `to`.
This call MUST:
- call the `tokensToSend` method on the contract implementing `ERC777TokensSender` as returned by a ERC820 lookup on the `from` address regardless if `from` is a regular address or a contract.
- call the `tokensReceived` method on the address implementing `ERC777TokensRecipient` as returned by a ERC820 lookup on the `to` address regardless if `to` is a regular address or a contract.
- call the `tokensToSend` method on the contract implementing `ERC777TokensSender` as returned by an ERC820 lookup on the `from` address regardless if `from` is a regular address or a contract.
- call the `tokensReceived` method on the address implementing `ERC777TokensRecipient` as returned by an ERC820 lookup on the `to` address regardless if `to` is a regular address or a contract.
- fire the `Sent` event.
If `to` is a contract which is not prepared to receive tokens. Specifically, it is a contract which does not register an address (its own or another) via ERC820 implementing the `ERC777TokensRecipient` interface. Then `send` MUST throw.
@ -178,9 +176,9 @@ function authorizeOperator(address operator) public
Authorize a third party `operator` to send tokens on behalf of `msg.sender`.
A `AuthorizedOperator` event MUST be fired on a successful call to this function.
An `AuthorizedOperator` event MUST be fired on a successful call to this function.
*NOTE*: The token holder (`msg.sender`) is always an operator for himself. That is, he can call `operatorSend` on himself. This right cannot be revoked. Therefore if this function is called to set the token holder (`msg.sender`) as operator, then the function MUST throw.
*NOTE*: The token holder (`msg.sender`) is always an operator for himself. That is, he CAN call `operatorSend` on himself. This right cannot be revoked. Therefore if this function is called to set the token holder (`msg.sender`) as operator, then the function MUST throw.
*NOTE*: A token holder CAN authorize multiple operators at the same time.
@ -199,7 +197,7 @@ Revoke a third party `operator`'s rights to send tokens on behalf of `msg.sende
A `RevokedOperator` event MUST be fired on a successful call to this function.
*NOTE*: The token holder (`msg.sender`) is always an operator for himself. That is, he can call `operatorSend` on himself. This right cannot be revoked. Therefore if this function is called to set the token holder (`msg.sender`) as operator, then the function MUST throw.
*NOTE*: The token holder (`msg.sender`) is always an operator for himself. That is, he CAN call `operatorSend` on himself. This right cannot be revoked. Therefore if this function is called to set the token holder (`msg.sender`) as operator, then the function MUST throw.
> **parameters**
> - `operator`: Address which whose rights to manage the tokens will be revoked.
@ -231,8 +229,8 @@ Send `amount` of tokens on behalf of the address `from` to the address `to`.
`msg.sender` MUST be an authorized operator or the owner for the `from` address.
This call MUST:
- call the `tokensToSend` method on the contract implementing `ERC777TokensSender` as returned by a ERC820 lookup on the `from` address
- call the `tokensReceived` method on the contract implementing `ERC777TokensRecipient` as returned by a ERC820 lookup on the `to` address
- call the `tokensToSend` method on the contract implementing `ERC777TokensSender` as returned by an ERC820 lookup on the `from` address
- call the `tokensReceived` method on the contract implementing `ERC777TokensRecipient` as returned by an ERC820 lookup on the `to` address
- fire the `Sent` event
If `to` is a contract which is not prepared to receive tokens. Specifically, it is a contract which does not register an address (its own or another) via ERC820 implementing the `ERC777TokensRecipient` interface. Then `operatorSend` MUST throw.
@ -250,7 +248,7 @@ The method MUST throw if:
> - `userData`: information attached to the transaction, previously provided by the sender (`from` address).
> - `operatorData`: information attached to the transaction by the operator
*NOTE*: The operator is free to pass any data via the `operatorData` parameter but the `userData` parameter is reserved for data provided by the user (token holder). The token holder should provide this data to the operator beforehand.
*NOTE*: The operator is free to pass any data via the `operatorData` parameter but the `userData` parameter is reserved for data provided by the user (token holder). The token holder SHOULD provide this data to the operator beforehand.
<br/>
@ -296,7 +294,7 @@ However, this event MUST be fired every time tokens are minted and credited to a
###### `tokensReceived` for minting
Every mint MUST call `tokensReceived` on the address implementing `ERC777TokensRecipient` for the `to` address as returned by a ERC820 lookup.
Every mint MUST call `tokensReceived` on the address implementing `ERC777TokensRecipient` for the `to` address as returned by an ERC820 lookup.
Minting MUST follow the same rules as `send`/`operatorSend` with the exception that `tokensToSend` MUST NOT be called in any case on any address. In addition, if `to` is a contract which is not prepared to receive tokens. Specifically, it is a contract which does not register an address (its own or another) via ERC820 implementing the `ERC777TokensRecipient` interface. Then the minting MUST throw.
@ -325,7 +323,7 @@ However, this event MUST be fired every time tokens are burned and taken from a
###### `tokensToSend` for burning
Every burn MUST call `tokensToSend` on the address implementing `ERC777TokensSender` for the `from` address as returned by a ERC820 lookup.
Every burn MUST call `tokensToSend` on the address implementing `ERC777TokensSender` for the `from` address as returned by an ERC820 lookup.
Burning MUST follow the same rules as `send`/`operatorSend` with the exception that `tokensReceived` MUST NOT be called in any case on any address. But if the `from` address register an address via ERC820 implementing the `ERC777TokensSender` interface, `tokensToSend` MUST be called.
@ -367,7 +365,7 @@ This event MUST be fired on a successful call to `revokeOperator`.
### ERC777TokensSender
Any address (contract or regular account) CAN register a contract (itself or an other) implementing the `ERC777TokensSender` interface via the ERC820 registry.
Any address (contract or regular account) CAN register a contract (itself or another) implementing the `ERC777TokensSender` interface via the ERC820 registry.
``` solidity
interface ERC777TokensSender {
@ -417,7 +415,7 @@ When tokens are sent as a result of sending (`send` or `operatorSend`):
### ERC777TokensRecipient
Any address (contract or regular account) CAN register a contract (itself or an other) implementing the `ERC777TokensRecipient` interface via the ERC820 registry.
Any address (contract or regular account) CAN register a contract (itself or another) implementing the `ERC777TokensRecipient` interface via the ERC820 registry.
``` solidity
interface ERC777TokensRecipient {
@ -466,35 +464,35 @@ If it is a direct `send` (i.e. not an `operatorSend`) the `operator` MUST be the
The logo MUST NOT be used to advertise, promote or associate in any way technology such as tokens which is not ERC777 compliant.
The logo for the standard can be found in the `/assets/eip-777/logo` folder in `svg` and `png` formats. The `png` version of the logo offers a few sizes in pixel. If needed, other sizes CAN be created by converting from `svg` into `png`.
The logo for the standard can be found in the `/assets/eip-777/logo` folder in `svg` and `png` formats. The `png` version of the logo offers a few sizes in pixels. If needed, other sizes CAN be created by converting from `svg` into `png`.
ERC777 token contract authors CAN create a specific logo for their token based on this logo.
## Rationale
This standard solves some of the problems of the [EIP223](https://github.com/ethereum/EIPs/issues/223) and goes an step further by allowing operators (generally contracts) that can manage the tokens in the same way that the ERC20 with infinite `approve` was allowed.
This standard solves some of the problems of the [EIP223](https://github.com/ethereum/EIPs/issues/223) and goes a step further by allowing operators (generally contracts) that can manage the tokens in the same way that the ERC20 with infinite `approve` was allowed.
Also the usage of ERC820 allows backwards compatibility with wallets and proxy contracts without having to be redeployed.
Also, the usage of ERC820 allows backward compatibility with wallets and proxy contracts without having to be redeployed.
## Backwards Compatibility (ERC20Token)
## Backward Compatibility (ERC20Token)
This EIP does not introduce backward incompatibilities and is compatible with the older ERC20 token standard.
This EIP does not uses `transfer` and `transferFrom` and uses `send` and `operatorSend` to avoid mistakes in knowing which interface you are using.
This EIP does not use `transfer` and `transferFrom` and uses `send` and `operatorSend` to avoid mistakes in knowing which interface you are using.
This standard allows the implementation of ERC20 functions `transfer`, `transferFrom`, `approve` and `allowance` alongside to make a token compatible with ERC20.
The token can implement `decimals()` for backwards compatibility. If implemented, it MUST always return `18`.
The token CAN implement `decimals()` for backward compatibility. If implemented, it MUST always return `18`.
Therefore a token contract can implement both ERC20 and ERC777 in parallel. Read-only functions (such as `name`, `symbol`, `balanceOf`, `totalSupply`) and internal data (such as the mapping of balances) overlap without problem. Note however that the following functions are mandatory in ERC777 and MUST be implemented: `name`, `symbol` `balanceOf` and `totalSupply` (`decimal` is not part of the ERC777 standard).
Therefore a token contract CAN implement both ERC20 and ERC777 in parallel. Read-only functions (such as `name`, `symbol`, `balanceOf`, `totalSupply`) and internal data (such as the mapping of balances) overlap without problems. Note however that the following functions are mandatory in ERC777 and MUST be implemented: `name`, `symbol` `balanceOf` and `totalSupply` (`decimal` is not part of the ERC777 standard).
The write methods from both standards are decoupled and can operate independently from each other. Note that ERC20 functions SHOULD be limited to only being called from old contracts.
If the token implements ERC20, it MUST be register the `ERC20Token` interface via ERC820. If the contract has a switch to enable or disable ERC20 methods, every time the switch is triggered, the token MUST register or unregister accordingly the `ERC20Token` interface via ERC820.
If the token implements ERC20, it MUST register the `ERC20Token` interface with its own address via ERC820. If the contract has a switch to enable or disable ERC20 methods, every time the switch is triggered, the token MUST register or unregister its own address accordingly the `ERC20Token` interface via ERC820. (Unregistering implies setting the address to `0x0`.)
The only difference for new contracts implementing ERC20 is that registration of `ERC777TokensSender` and `ERC777TokensRecipient` via ERC820 takes precedence over ERC20. This means that even with a ERC20 `transfer` call, the token contract MUST check via ERC820 if the `from` / `to` address implements `tokensToSend` / `tokensReceived` and call it if available. Note that when calling ERC20 `transfer` on a contract, if the contract does not implement `tokensReceived`, the `transfer` call SHOULD still be accepted even if this means the tokens will probably be locked.
The only difference for new contracts implementing ERC20 is that registration of `ERC777TokensSender` and `ERC777TokensRecipient` via ERC820 takes precedence over ERC20. This means that even with an ERC20 `transfer` call, the token contract MUST check via ERC820 if the `from` / `to` address implements `tokensToSend` / `tokensReceived` and call it if available. Note that when calling ERC20 `transfer` on a contract, if the contract does not implement `tokensReceived`, the `transfer` call SHOULD still be accepted even if this means the tokens will probably be locked.
The table below summarize the different actions the token contract must take when sending, minting and transferring token via ERC777 and ERC20:
The table below summarizes the different actions the token contract must take when sending, minting and transferring token via ERC777 and ERC20:
<table>
<tr>
@ -533,11 +531,11 @@ There is no particular action to take if `tokensToSend` is not implemented. The
## Test Cases
The [repository with the reference implementation](https://github.com/jacquesd/ERC777) contains all the [tests](https://github.com/jacquesd/ERC777/blob/master/test/ReferenceToken-test.js).
The [repository with the reference implementation](https://github.com/jacquesd/ERC777) contains all the [tests](https://github.com/jacquesd/ERC777/blob/master/test/ReferenceToken.test.js).
## Implementation
The repository at [/jacquesd/ERC777](https://github.com/jacquesd/ERC777) contains the [reference implementation](https://github.com/jacquesd/ERC777/blob/master/contracts/ReferenceToken.sol).
The repository at [jacquesd/ERC777](https://github.com/jacquesd/ERC777) contains the [reference implementation](https://github.com/jacquesd/ERC777/blob/master/contracts/examples/ReferenceToken.sol).
## Copyright