mirror of https://github.com/status-im/EIPs.git
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:
parent
79bd95f017
commit
41a70423cf
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue