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.
|
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
|
## Abstract
|
||||||
|
|
||||||
This standard defines a new way to interact with a Token Contract.
|
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
|
## 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)`.
|
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.
|
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`).
|
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.
|
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.
|
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
|
## Specification
|
||||||
|
|
||||||
|
@ -46,7 +46,6 @@ interface ERC777Token {
|
||||||
function granularity() public constant returns (uint256);
|
function granularity() public constant returns (uint256);
|
||||||
function balanceOf(address owner) 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 send(address to, uint256 amount, bytes userData) public;
|
||||||
|
|
||||||
function authorizeOperator(address operator) 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>.
|
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`.
|
*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/>
|
<br/>
|
||||||
|
|
||||||
|
@ -145,15 +144,14 @@ Get the balance of the account with address `tokenHolder`.
|
||||||
##### send
|
##### send
|
||||||
|
|
||||||
``` solidity
|
``` solidity
|
||||||
function send(address to, uint256 amount) public
|
|
||||||
function send(address to, uint256 amount, bytes userData) public
|
function send(address to, uint256 amount, bytes userData) public
|
||||||
```
|
```
|
||||||
|
|
||||||
Send `amount` of tokens to address `to`.
|
Send `amount` of tokens to address `to`.
|
||||||
|
|
||||||
This call MUST:
|
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 `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 a ERC820 lookup on the `to` address – regardless if `to` 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.
|
- 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.
|
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`.
|
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.
|
*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.
|
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**
|
> **parameters**
|
||||||
> - `operator`: Address which whose rights to manage the tokens will be revoked.
|
> - `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.
|
`msg.sender` MUST be an authorized operator or the owner for the `from` address.
|
||||||
|
|
||||||
This call MUST:
|
This call MUST:
|
||||||
- call the `tokensToSend` method on the contract implementing `ERC777TokensSender` as returned by a ERC820 lookup on the `from` 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 a ERC820 lookup on the `to` address
|
- call the `tokensReceived` method on the contract implementing `ERC777TokensRecipient` as returned by an ERC820 lookup on the `to` address
|
||||||
- fire the `Sent` event
|
- 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.
|
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).
|
> - `userData`: information attached to the transaction, previously provided by the sender (`from` address).
|
||||||
> - `operatorData`: information attached to the transaction by the operator
|
> - `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/>
|
<br/>
|
||||||
|
|
||||||
|
@ -296,7 +294,7 @@ However, this event MUST be fired every time tokens are minted and credited to a
|
||||||
|
|
||||||
###### `tokensReceived` for minting
|
###### `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.
|
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
|
###### `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.
|
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.
|
||||||
|
|
||||||
|
@ -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 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.
|
ERC777 token contract authors CAN create a specific logo for their token based on this logo.
|
||||||
|
|
||||||
## Rationale
|
## 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 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.
|
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.
|
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>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -533,11 +531,11 @@ There is no particular action to take if `tokensToSend` is not implemented. The
|
||||||
|
|
||||||
## Test Cases
|
## 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
|
## 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
|
## Copyright
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue