diff --git a/EIPS/eip-1.md b/EIPS/eip-1.md index 79df47c82ccc8..73390cd5ca375 100644 --- a/EIPS/eip-1.md +++ b/EIPS/eip-1.md @@ -44,7 +44,7 @@ Each EIP must have a champion - someone who writes the EIP using the style and f Vetting an idea publicly before going as far as writing an EIP is meant to save the potential author time. Asking the Ethereum community first if an idea is original helps prevent too much time being spent on something that is guaranteed to be rejected based on prior discussions (searching the Internet does not always do the trick). It also helps to make sure the idea is applicable to the entire community and not just the author. Just because an idea sounds good to the author does not mean it will work for most people in most areas where Ethereum is used. Examples of appropriate public forums to gauge interest around your EIP include [the Ethereum subreddit], [the Issues section of this repository], and [one of the Ethereum Gitter chat rooms]. In particular, [the Issues section of this repository] is an excellent place to discuss your proposal with the community and start creating more formalized language around your EIP. -Once the champion has asked the Ethereum community whether an idea has any chance of acceptance a draft EIP should be presented as a [pull request]. +Once the champion has asked the Ethereum community whether an idea has any chance of acceptance a draft EIP should be presented as a [pull request]. If the EIP collaborators approve, the EIP editor will assign the EIP a number (generally the issue or PR number related to the EIP) and merge your pull request. The EIP editor will not unreasonably deny an EIP. Reasons for denying EIP status include duplication of effort, being technically unsound, not providing proper motivation or addressing backwards compatibility, or not in keeping with the Ethereum philosophy. @@ -64,7 +64,7 @@ EIPs can also be superseded by a different EIP, rendering the original obsolete. The possible paths of the status of EIPs are as follows: -![EIP Process](eip-1/process.png) +![EIP Process](../assets/eip-1/process.png) Some Informational and Process EIPs may also have a status of “Active” if they are never meant to be completed. E.g. EIP 1 (this EIP). @@ -114,7 +114,8 @@ Each EIP should have the following parts: EIP Formats and Templates ------------------------- -EIPs should be written in [markdown] format. Image files should be included in a subdirectory for that EIP. +EIPs should be written in [markdown] format. +Image files should be included in a subdirectory of the `assets` folder for that EIP as follow: `assets/eip-X` (for eip **X**). When linking to an image in the EIP, use relative links such as `../assets/eip-X/image.png`. EIP Header Preamble ------------------- diff --git a/EIPS/eip-107.md b/EIPS/eip-107.md index 494fdca1279ac..48b13a0390b60 100644 --- a/EIPS/eip-107.md +++ b/EIPS/eip-107.md @@ -29,19 +29,19 @@ Account unlocked : ----------------- When the account is already unlocked, the user is presented with the following popup for every transaction that the dapp attempts to make: -![](eip-107/authorization.png) +![](../assets/eip-107/authorization.png) Account locked and no "personal" api exposed via rpc: ----------------- When the account is locked, and the node does not provide access to account unlocking via its rpc interface, the following popup will be presented. This is not ideal since this requires the user to know how to unlock an account: -![](eip-107/authorization-locked.png) +![](../assets/eip-107/authorization-locked.png) Account locked but node exposing the "personal" api via rpc : ----------------- A better option is to ask the user for their password, but this is only possible if the node allows access to the "personal" api via rpc. In such case, the following dialog will be presented to the user so he/she can accept the transaction by providing the password required to unlock the account: -![](eip-107/authorization-password.png) +![](../assets/eip-107/authorization-password.png) Specification diff --git a/EIPS/eip-191.md b/EIPS/eip-191.md new file mode 100644 index 0000000000000..4462d32a69322 --- /dev/null +++ b/EIPS/eip-191.md @@ -0,0 +1,63 @@ +--- +eip: 191 +title: Signed Data Standard +author: Martin Holst Swende (@holiman), Nick Johnson +status: Draft +type: Standards Track +category: ERC +created: 2016-01-20 +--- + +# Abstract + +This ERC proposes a specification about how to handle signed data in Etherum contracts. + +# Motivation + +Several multisignature wallet implementations have been created which accepts `presigned` transactions. A `presigned` transaction is a chunk of binary `signed_data`, along with signature (`r`, `s` and `v`). The interpretation of the `signed_data` has not been specified, leading to several problems: + +* Standard Ethereum transactions can be submitted as `signed_data`. An Ethereum transaction can be unpacked, into the following components: `RLP` (hereby called `RLPdata`), `r`, `s` and `v`. If there are no syntactical constraints on `signed_data`, this means that `RLPdata` can be used as a syntactically valid `presigned` transaction. +* Multisignature wallets have also had the problem that a `presigned` transaction has not been tied to a particular `validator`, i.e a specific wallet. Example: + 1. Users `A`, `B` and `C` have the `2/3`-wallet `X` + 2. Users `A`, `B` and `D` have the `2/3`-wallet `Y` + 3. User `A` and `B` submites `presigned` transaction to `X`. + 4. Attacker can now reuse their presigned transactions to `X`, and submit to `Y`. + +## Specification + +We propose the following format for `signed_data` + +``` +0x19 <1 byte version> . +``` +Version `0` has `<20 byte address>` for the version specific data, and the `address` is the intended validator. In the case of a Multisig wallet, that is the wallet's own address . + +The initial `0x19` byte is intended to ensure that the `signed_data` is not valid [RLP](https://github.com/ethereum/wiki/wiki/RLP) + +> For a single byte whose value is in the [0x00, 0x7f] range, that byte is its own RLP encoding. + +That means that any `signed_data` cannot be one RLP-structure, but a 1-byte `RLP` payload followed by something else. Thus, any ERC-191 `signed_data` can never be an Ethereum transaction. + +Additionally, `0x19` has been chosen because since ethereum/go-ethereum#2940 , the following is prepended before hashing in personal_sign: + +``` +"\x19Ethereum Signed Message:\n" + len(message). +``` + +Using `0x19` thus makes it possible to extend the scheme by defining a version `0x45` (`E`) to handle these kinds of signatures. + +### Example + + function submitTransactionPreSigned(address destination, uint value, bytes data, uint nonce, uint8 v, bytes32 r, bytes32 s) + public + returns (bytes32 transactionHash) + { + // Arguments when calculating hash to validate + // 1: byte(0x19) - the initial 0x19 byte + // 2: byte(0) - the version byte + // 3: this - the validator address + // 4-7 : Application specific data + transactionHash = keccak256(byte(0x19),byte(0),this,destination, value, data, nonce); + sender = ecrecover(transactionHash, v, r, s); + // ... + } diff --git a/EIPS/eip-3.md b/EIPS/eip-3.md index 2cf96c9707e42..6337851663540 100644 --- a/EIPS/eip-3.md +++ b/EIPS/eip-3.md @@ -2,7 +2,7 @@ eip: 3 title: Addition of CALLDEPTH opcode author: Martin Holst Swende -status: Draft +status: Deferred type: Standards Track category: Core created: 2015-11-19 diff --git a/EIPS/eip-609.md b/EIPS/eip-609.md index fce499ad34e79..b81474388105b 100644 --- a/EIPS/eip-609.md +++ b/EIPS/eip-609.md @@ -2,8 +2,7 @@ eip: 609 title: "Hardfork Meta: Byzantium" author: Alex Beregszaszi -type: Standards Track -category: Core +type: Meta status: Final created: 2017-04-23 requires: 100, 140, 196, 197, 198, 211, 214, 649, 658 diff --git a/EIPS/eip-615.md b/EIPS/eip-615.md index ad9d94fcf93da..45216921a0080 100644 --- a/EIPS/eip-615.md +++ b/EIPS/eip-615.md @@ -211,9 +211,8 @@ Validating that jumps are to valid addresses takes two sequential passes over th bool validate_jumps(PC) { - current_sub = PC - // build sets of BEGINSUBs and JUMPDESTs + current_sub = 0 for (PC = 0; instruction = bytecode[PC]; PC = advance_pc(PC)) { if instruction is invalid @@ -230,6 +229,7 @@ Validating that jumps are to valid addresses takes two sequential passes over th } // check that targets are in subroutine + current_sub = 0 for (PC = 0; instruction = bytecode[PC]; PC = advance_pc(PC)) { if instruction is BEGINDATA diff --git a/EIPS/eip-616.md b/EIPS/eip-616.md index 6de3977e4b8de..762b68943eb49 100644 --- a/EIPS/eip-616.md +++ b/EIPS/eip-616.md @@ -1,7 +1,7 @@ --- eip: 616 title: SIMD Operations for the EVM -author: Greg Colvin, greg@colvin.org +author: Greg Colvin type: Standards Track category: Core status: Draft diff --git a/EIPS/eip-627.md b/EIPS/eip-627.md new file mode 100644 index 0000000000000..0da8a6b534446 --- /dev/null +++ b/EIPS/eip-627.md @@ -0,0 +1,183 @@ +--- +eip: 627 +title: Whisper Specification +author: Vlad Gluhovsky +type: Informational +status: Draft +created: 2017-05-05 +--- + +## Abstract + +This draft EIP describes the format of Whisper messages within the ÐΞVp2p Wire Protocol. +This EIP should substitute the [existing specification](https://github.com/ethereum/wiki/wiki/Whisper-Wire-Protocol). +More detailed documentation on Whisper could be found [here](https://github.com/ethereum/go-ethereum/wiki/Whisper). + +## Motivation + +It is necessary to specify the standard for Whisper messages in order to ensure forward compatibility of different Whisper clients. + +## Specification + +All Whisper messages sent as ÐΞVp2p Wire Protocol packets should be RLP-encoded arrays of data containing two objects: integer packet code followed by another object (whose type depends on the packet code). + +If Whisper node does not support a particular packet code, it should just ignore the packet without generating any error. + +### Packet Codes + +The message codes reserved for Whisper protocol: 0 - 127. +Messages with unknown codes must be ignored, for forward compatibility of future versions. + +The Whisper sub-protocol should support the following packet codes: + +| EIP | Name | Int Value | +|-------|----------------------------|-----------| +| | Status | 0 | +| | Messages | 1 | +| | PoW Requirement | 2 | +| | Bloom Filter | 3 | +|-------|----------------------------|-----------| + + +The following message codes are optional, but they are reserved for specific purpose. + +| EIP | Name | Int Value | +|-------|----------------------------|-----------| +| | P2P Request | 126 | +| | P2P Message | 127 | +|-------|----------------------------|-----------| + +### Packet Format and Usage + +**Status** [`0`] + +This packet contains two objects: integer message code (0x00) followed by a list of values: integer version, float PoW requirement, and bloom filter, in this order. The bloom filter paramenter is optional; if it is missing or nil, the node is considered to be full node (i.e. accepts all messages). The format of PoW and bloom filter please see below (message codes 2 and 3). + +Status message should be sent after the initial handshake and prior to any other messages. + +**Messages** [`1`, `whisper_envelopes`] + +This packet contains two objects: integer message code (0x01) followed by a list (possibly empty) of Whisper Envelopes. + +This packet is used for sending the standard Whisper envelopes. + +**PoW Requirement** [`2`, `PoW`] + +This packet contains two objects: integer message code (0x02) followed by a single floating point value of PoW. This value is the IEEE 754 binary representation of 64-bit floating point number. Values of qNAN, sNAN, INF and -INF are not allowed. Negative values are also not allowed. + +This packet is used by Whisper nodes for dynamic adjustment of their individual PoW requirements. Receipient of this message should no longer deliver the sender messages with PoW lower than specified in this message. + +PoW is defined as average number of iterations, required to find the current BestBit (the number of leading zero bits in the hash), divided by message size and TTL: + + PoW = (2**BestBit) / (size * TTL) + +PoW calculation: + + fn short_rlp(envelope) = rlp of envelope, excluding env_nonce field. + fn pow_hash(envelope, env_nonce) = sha3(short_rlp(envelope) ++ env_nonce) + fn pow(pow_hash, size, ttl) = 2**leading_zeros(pow_hash) / (size * ttl) + +where size is the size of the full RLP-encoded envelope. + +**Bloom Filter** [`3`, `bytes`] + +This packet contains two objects: integer message code (0x03) followed by a byte array of arbitrary size. + +This packet is used by Whisper nodes for sharing their interest in messages with specific topics. + +The Bloom filter is used to identify a number of topics to a peer without compromising (too much) privacy over precisely what topics are of interest. Precise control over the information content (and thus efficiency of the filter) may be maintained through the addition of bits. + +Blooms are formed by the bitwise OR operation on a number of bloomed topics. The bloom function takes the topic and projects them onto a 512-bit slice. At most, three bits are marked for each bloomed topic. + +The projection function is defined as a mapping from a 4-byte slice S to a 512-bit slice D; for ease of explanation, S will dereference to bytes, whereas D will dereference to bits. + + LET D[*] = 0 + FOREACH i IN { 0, 1, 2 } DO + LET n = S[i] + IF S[3] & (2 ** i) THEN n += 256 + D[n] = 1 + END FOR + + +OPTIONAL + +**P2P Request** [`126`, `whisper_envelope`] + +This packet contains two objects: integer message code (0x7E) followed by a single Whisper Envelope. + +This packet is used for sending Dapp-level peer-to-peer requests, e.g. Whisper Mail Client requesting old messages from the Whisper Mail Server. + +**P2P Message** [`127`, `whisper_envelope`] + +This packet contains two objects: integer message code (0x7F) followed by a single Whisper Envelope. + +This packet is used for sending the peer-to-peer messages, which are not supposed to be forwarded any further. E.g. it might be used by the Whisper Mail Server for delivery of old (expired) messages, which is otherwise not allowed. + + +### Whisper Envelope + +Envelopes are RLP-encoded structures of the following format: + + [ Expiry, TTL, Topic, Data, Nonce ] + +`Expiry`: 4 bytes (UNIX time in seconds). + +`TTL`: 4 bytes (time-to-live in seconds). + +`Topic`: 4 bytes of arbitrary data. + +`Data`: byte array of arbitrary size (contains encrypted message). + +`Nonce`: 8 bytes of arbitrary data (used for PoW calculation). + +### Contents of Data Field of the Message (Optional) + +This section outlines the optional description of Data Field to set up an example. Later it may be moved to a separate EIP. + +It is only relevant if you want to decrypt the incoming message, but if you only want to send a message, any other format would be perfectly valid and must be forwarded to the peers. + +Data field contains encrypted message of the Envelope. In case of symmetric encryption, it also contains appended Salt (a.k.a. AES Nonce, 12 bytes). Plaintext (unencrypted) payload consists of the following concatenated fields: flags, auxiliary field, payload, padding and signature (in this sequence). + + flags: 1 byte; first two bits contain the size of auxiliary field, third bit indicates whether the signature is present. + + auxiliary field: up to 4 bytes; contains the size of payload. + + payload: byte array of arbitrary size (may be zero). + + padding: byte array of arbitrary size (may be zero). + + signature: 65 bytes, if present. + + salt: 12 bytes, if present (in case of symmetric encryption). + +Those unable to decrypt the message data are also unable to access the signature. The signature, if provided, is the ECDSA signature of the Keccak-256 hash of the unencrypted data using the secret key of the originator identity. The signature is serialised as the concatenation of the `R`, `S` and `V` parameters of the SECP-256k1 ECDSA signature, in that order. `R` and `S` are both big-endian encoded, fixed-width 256-bit unsigned. `V` is an 8-bit big-endian encoded, non-normalised and should be either 27 or 28. + +The padding field was introduced in order to align the message size, since message size alone might reveal important metainformation. Padding can be arbitrary size. However, it is recommended that the size of Data Field (excuding the Salt) before encryption (i.e. plain text) should be factor of 256 bytes. + +### Payload Encryption + +Asymmetric encryption uses the standard Elliptic Curve Integrated Encryption Scheme with SECP-256k1 public key. + +Symmetric encryption uses AES GCM algorithm with random 96-bit nonce. + +## Rationale + +Packet codes 0x00 and 0x01 are already used in all Whisper versions. + +Packet code 0x02 will be necessary for the future developement of Whisper. It will provide possiblitity to adjust the PoW requirement in real time. It is better to allow the network to govern itself, rather than hardcode any specific value for minimal PoW requirement. + +Packet code 0x03 will be necessary for scalability of the network. In case of too much traffic, the nodes will be able to request and receive only the messages they are interested in. + +Packet codes 0x7E and 0x7F may be used to implement Whisper Mail Server and Client. Without P2P messages it would be impossible to deliver the old messages, since they will be recognized as expired, and the peer will be disconnected for violating the Whisper protocol. They might be useful for other purposes when it is not possible to spend time on PoW, e.g. if a stock exchange will want to provide live feed about the latest trades. + +## Backwards Compatibility + +This EIP is compatible with Whisper version 6. Any client which does not implement certain packet codes should gracefully ignore the packets with those codes. This will ensure the forward compatibility. + +## Implementation + +The golang implementation of Whisper (v.6) already uses packet codes 0x00 - 0x03. Parity's implementation of v.6 will also use codes 0x00 - 0x03. Codes 0x7E and 0x7F are reserved, but still unused and left for custom implementation of Whisper Mail Server. + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-681.md b/EIPS/eip-681.md index 4133fdfeec806..a3165e6a58b1c 100644 --- a/EIPS/eip-681.md +++ b/EIPS/eip-681.md @@ -37,7 +37,7 @@ Payment request URLs contain "ethereum" in their schema (protocol) part and are number = [ "-" / "+" ] *DIGIT [ "." 1*DIGIT ] [ ( "e" / "E" ) [ 1*DIGIT ] [ "+" UNIT ] -Where `TYPE` is a standard ABI type name, as defined in [Ethereum Contract ABI specification](https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI). `STRING` is a URL-encoded unicode string of arbitrary length, where delimiters and the +Where `TYPE` is a standard ABI type name, as defined in [Ethereum Contract ABI specification](https://solidity.readthedocs.io/en/develop/abi-spec.html). `STRING` is a URL-encoded unicode string of arbitrary length, where delimiters and the percentage symbol (`%`) are mandatorily hex-encoded with a `%` prefix. `UNIT` is a URL-encoded unicode string. If `UNIT` is ETH, it always means a multiplier of 1018. If it is something diff --git a/EIPS/eip-689.md b/EIPS/eip-689.md new file mode 100644 index 0000000000000..fe19393973363 --- /dev/null +++ b/EIPS/eip-689.md @@ -0,0 +1,48 @@ +--- +eip: 689 +title: Address Collision of Contract Address Causes Exceptional Halt +author: Yoichi Hirai +type: Standard Track +category: Core +status: Draft +created: 2017-08-15 +--- + +## Simple Summary + +This EIP proposes to make contract creation fail on an account with nonempty code or non-zero nonce. + +## Abstract + +Some test cases in the consensus test suite try to deploy a contract at an address already with nonempty code. Although such cases can virtually never happen on the main network before the Constantinople fork block, the test cases detected discrepancies in clients' behavior. Currently, the Yellow Paper says that the contract creation starts with the empty code and the initial nonce even in the case of address collisions. To simplify the semantics, this EIP proposes that address collisions cause failures of contract creation. + +## Motivation + +This EIP has no practical relevance to the main net history, but simplifies testing and reasoning. + +This EIP has no effects after Constantinople fork because [EIP-86](https://github.com/ethereum/EIPs/pull/208) contains the changes proposed in this EIP. Even before the Constantinople fork, this EIP has no practical relevance because the change is visible only in case of a hash collision of keccak256. + +Regarding testing, this EIP relieves clients from supporting reversion of code overwriting. + +Regarding reasoning, this EIP establishes an invariant that non-empty code is never modified. + +## Specification + +If `block.number >= 0`, when a contract creation is on an account with non-zero nonce or non-empty code, the creation fails as if init code execution resulted in an exceptional halt. This applies to contract creation triggered by a contract creation transaction and by CREATE instruction. + +## Rationale + +It seems impractical to implement never-used features just for passing tests. Client implementations will be simpler with this EIP. + +## Backwards Compatibility + +This EIP is backwards compatible on the main network. + +## Test Cases + +At least the BlockchainTest called `createJS\_ExampleContract\_d0g0v0\_EIP158` will distinguish clients that implement this EIP. + +## Implementation + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-695.md b/EIPS/eip-695.md index 58bb9e70fb50f..848d5335bf33b 100644 --- a/EIPS/eip-695.md +++ b/EIPS/eip-695.md @@ -1,7 +1,7 @@ --- eip: 695 title: Create `eth_chainId` method for JSON-RPC -author: Isaac Ardis Wei Tang , @tcz001 +author: Isaac Ardis , Wei Tang , Fan Torchz (@tcz001) type: Standards Track category: Interface status: Draft diff --git a/EIPS/eip-721.md b/EIPS/eip-721.md index 33579a8237596..0495fe67bf639 100644 --- a/EIPS/eip-721.md +++ b/EIPS/eip-721.md @@ -262,13 +262,13 @@ There are many proposed uses of Ethereum smart contracts that depend on tracking **"NFT" Word Choice** -"NFT" was satisfactory to nearly everyone surveyed and is widely applicable to a broad universe of distinguishable digital assets. We recongize that "deed" is very descriptive for certain applications of this standard (notably, physical property). +"NFT" was satisfactory to nearly everyone surveyed and is widely applicable to a broad universe of distinguishable digital assets. We recognize that "deed" is very descriptive for certain applications of this standard (notably, physical property). *Alternatives considered: distinguishable asset, title, token, asset, equity, ticket* **NFT Identifiers** -Every NFT is identified by a unique `uint265` ID inside the ERC-721 smart contract. This identifing number SHALL NOT change for the life of the contract. The pair `(contract address, uint265 tokenId)` will then be a globally unique and fully-qualified identifier for a specific asset on an Ethereum chain. While some ERC-721 smart contracts may find it convenient to start with ID 0 and simply increment by one for each new NFT, callers SHALL NOT assume that ID numbers have any specific pattern to them, and MUST treat the ID as a "black box". Also note that a NFTs MAY become invalid (be destroyed). Please see the enumerations functions for a supported enumeration interface. +Every NFT is identified by a unique `uint256` ID inside the ERC-721 smart contract. This identifying number SHALL NOT change for the life of the contract. The pair `(contract address, uint256 tokenId)` will then be a globally unique and fully-qualified identifier for a specific asset on an Ethereum chain. While some ERC-721 smart contracts may find it convenient to start with ID 0 and simply increment by one for each new NFT, callers SHALL NOT assume that ID numbers have any specific pattern to them, and MUST treat the ID as a "black box". Also note that a NFTs MAY become invalid (be destroyed). Please see the enumerations functions for a supported enumeration interface. The choice of `uint256` allows a wide variety of applications because UUIDs and sha3 hashes are directly convertible to `uint256`. @@ -310,7 +310,7 @@ We have deployed a contract, XXXXERC721, to Testnet which instantiates and track This illustration makes clear: the ERC-721 standard scales. -*Alternatives considered: remove the asset enumeration function if it requries a for-loop, return a Soldity array type from enumeration functions.* +*Alternatives considered: remove the asset enumeration function if it requires a for-loop, return a Solidity array type from enumeration functions.* **Privacy** diff --git a/EIPS/eip-758.md b/EIPS/eip-758.md index 61195fb3c431e..b828425f8509b 100644 --- a/EIPS/eip-758.md +++ b/EIPS/eip-758.md @@ -55,10 +55,10 @@ The caller receives notifications about their transactions' return data in two c ``` ### Polling -Push notifications require full duplex connections (i.e., websocket or IPC). Instead of subscribing, callers using HTTP send an `eth_newFilter` request: +Push notifications require full duplex connections (i.e., websocket or IPC). Instead of subscribing, callers using HTTP send an `eth_newReturnDataFilter` request: ```json -{"jsonrpc": "2.0", "id": 1, "method": "eth_newFilter", "params": ["returnData"]} +{"jsonrpc": "2.0", "id": 1, "method": "eth_newReturnDataFilter"} ``` The Ethereum node responds with a filter ID: @@ -86,7 +86,7 @@ The node responds with an array of transaction hashes and their corresponding re } ``` -All transactions submitted by the client that were sealed _after_ the initial `eth_newFilter` request are included in this array. +All transactions submitted by the client that were sealed _after_ the initial `eth_newReturnDataFilter` request are included in this array. ## Rationale diff --git a/EIPS/eip-777.md b/EIPS/eip-777.md new file mode 100644 index 0000000000000..b813e63359e02 --- /dev/null +++ b/EIPS/eip-777.md @@ -0,0 +1,544 @@ +--- +eip: 777 +title: A New Advanced Token Standard +author: Jordi Baylina , Jacques Dafflon , Thomas Shababi +discussions-to: https://github.com/ethereum/EIPs/issues/777 +status: Draft +type: Standards Track +category: ERC +created: 2017-11-20 +requires: 820 +--- + +## Simple Summary + +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`.* + +## 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. + +## 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: + +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. +3. Both contracts and regular addresses can control and reject which token they receive by registering a `tokensReceived` function – rejection is done by throwing in the function. +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. + +## Specification + +### ERC777Token (Token Contract) + +``` solidity +interface ERC777Token { + function name() public constant returns (string); + function symbol() public constant returns (string); + function totalSupply() public constant returns (uint256); + 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; + function revokeOperator(address operator) public; + function isOperatorFor(address operator, address tokenHolder) public constant returns (bool); + function operatorSend(address from, address to, uint256 amount, bytes userData, bytes operatorData) public; + + event Sent( + address indexed operator, + address indexed from, + address indexed to, + uint256 amount, + bytes userData, + bytes operatorData + ); + event Minted(address indexed operator, address indexed to, uint256 amount, bytes operatorData); + event Burned(address indexed operator, address indexed from, uint256 amount, bytes userData, bytes operatorData); + event AuthorizedOperator(address indexed operator, address indexed tokenHolder); + event RevokedOperator(address indexed operator, address indexed tokenHolder); +} +``` + +The token-contract MUST register the `ERC777Token` interface via ERC820. + +The basic unit token MUST be 1018. + +#### Methods +##### name + +``` solidity + function name() public constant returns (string) +``` + +Returns the name of the token – e.g. `"MyToken"`. + +> **returns:** Name of the token + +
+ +##### symbol + +``` solidity +function symbol() public constant returns (string) +``` + +Returns the symbol of the token – e.g. `"MYT"`. + +> **returns:** Symbol of the token + +
+ +##### granularity + +``` solidity +function granularity() public constant returns (uint256) +``` + +Returns the smallest part of the token that's not divisible. + +Any minting, transfer or burning of tokens MUST be a multiple of this value. Any operation that would result in a balance that's not a multiple of this value, MUST be considered invalid and the transaction MUST throw. + +Most of the tokens SHOULD be fully partitionable, i.e. this function SHOULD return `1` unless there is a good reason for not allowing any partition of the token. + +*NOTE*: `granularity` MUST be greater or equal to `1`. + +> **returns:** The smallest non divisible part of the token. + +
+ +##### totalSupply + +``` solidity +function totalSupply() public constant returns (uint256) +``` + +Get the total number of minted tokens. + +> **returns:** Total supply of tokens currently in circulation. + +
+ +##### balanceOf + +``` solidity +function balanceOf(address tokenHolder) public constant returns (uint256) +``` + +Get the balance of the account with address `tokenHolder`. +> **parameters** +> - `tokenHolder`: Address for which the balance is returned +> +> **returns:** Amount of token held by `tokenHolder` in the token contract. + +
+ +##### 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. + - 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. + +The function MUST `throw` if: + - `msg.sender` account balance does not have enough tokens to spend + - `to` is a contract which is not prepared to receive tokens. + +*NOTE*: Sending an amount of `0` is valid and MUST be treated as a regular send. +> **parameters** +> - `to`: tokens recipient +> - `amount`: number of tokens transferred +> - `userData`: information attached to the transaction by the user (sender) + +
+ +##### authorizeOperator + +``` solidity +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. + +*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. + +> **parameters** +> - `operator`: Address which will be granted rights to manage the tokens. + +
+ +##### revokeOperator + +``` solidity +function revokeOperator(address operator) public +``` + +Revoke a third party `operator`'s rights to send tokens on behalf of `msg.sender`. + +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. + +> **parameters** +> - `operator`: Address which whose rights to manage the tokens will be revoked. + +
+ +##### isOperatorFor + +``` solidity +function isOperatorFor(address operator, address tokenHolder) public constant returns (bool) +``` + +Check whether the `operator` address is allowed to send the tokens held by the `tokenHolder` address. + +> **parameters** +> - `operator`: address to check if it has the right to manage the tokens. +> - `tokenHolder`: address which holds the tokens to be managed. + +
+ +##### operatorSend + +``` solidity +function operatorSend(address from, address to, uint256 amount, bytes userData, bytes operatorData) public +``` + +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 + - 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. + +The method MUST throw if: + - `from` account balance does not have enough tokens to spend. + - `to` is a contract which does not register an address (its own or another) via ERC820 which implement the `ERC777TokensRecipient` interface. + - `to` is a contract which is not prepared to receive tokens. + - `msg.sender` is not an authorized operator for `from`. + +> **parameters** +> - `from`: token holder (sender) +> - `to`: tokens recipient +> - `amount`: number of tokens transferred +> - `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. + +
+ +#### Events + +##### Sent + +``` solidity +event Sent(address indexed operator, address indexed from, address indexed to, uint256 amount, bytes userData, bytes operatorData) +``` + +Indicate a transaction of `amount` of tokens from the `from` address to the `to` address. + +This event MUST be fired on a successful call to `send` and `operatorSend`. + +> **parameters** +> - `operator`: address which triggered the transfer, either the token holder for a direct send or an authorized operator for `operatorSend` +> - `from`: token holder +> - `to`: tokens recipient +> - `amount`: number of tokens sent +> - `userData`: information attached to the transaction by the token holder +> - `operatorData`: information attached to the transaction by the operator + +
+ +##### Minted + +``` solidity +event Minted(address indexed operator, address indexed to, uint256 amount, bytes operatorData) +``` + +Indicate the minting of `amount` of tokens to the `to` address. + +This standard does not enforce a specific way to mint tokens as this can be done in various ways depending on the use case of the tokens. + +However, this event MUST be fired every time tokens are minted and credited to a `to` recipient address. A `Sent` event (even with the `0x0` as `from` address) MUST NOT be fired to indicate minting. + +> **parameters** +> - `operator`: address which triggered the minting +> - `to`: tokens recipient +> - `amount`: number of tokens minted +> - `operatorData`: information attached to the minting by the operator + +###### `tokensReceived` for minting + +Every mint MUST call `tokensReceived` on the address implementing `ERC777TokensRecipient` for the `to` address as returned by a 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. + +The `from` parameter of `tokensReceived` MUST be `0x0`. The operator MUST be `msg.sender`. The `userData` MUST be empty. `operatorData` MAY contain data related to the minting. + +
+ +##### Burned + +``` solidity +event Burned(address indexed operator, address indexed from, uint256 amount, bytes userData, bytes operatorData) +``` + +Indicate the burning of `amount` of tokens from the `from` address. + +This standard does not enforce a specific way to burn tokens as this can be done in various ways depending on the use case of the tokens. + +However, this event MUST be fired every time tokens are burned and taken from a `from` recipient address. A `Sent` event (even with the `0x0` as `to` address) MUST NOT be fired. + +> **parameters** +> - `operator`: address which triggered the minting +> - `from`: token holder +> - `amount`: number of tokens burned +> - `userData`: information attached to the burn by the token holder +> - `operatorData`: information attached to the burn by the operator + +###### `tokensToSend` for burning + +Every burn MUST call `tokensToSend` on the address implementing `ERC777TokensSender` for the `from` address as returned by a 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. + +The `to` parameter of `tokensToSend` MUST be `0x0`. The operator MUST be `msg.sender`. The `userData` MUST be empty. `operatorData` MAY contain data related to the minting. + +
+ +##### AuthorizedOperator + +``` solidity +event AuthorizedOperator(address indexed operator, address indexed tokenHolder) +``` + +Indicate that the `operator` address is allowed to send the token of (i.e. is an operator for) the address `tokenHolder`. + +This event MUST be fired on a successful call to `authorizeOperator`. + +> **parameters** +> - `operator`: Address which is granted rights to manage the tokens. +> - `tokenHolder`: address which holds the tokens to be managed. + +
+ +##### RevokedOperator + +``` solidity +event RevokedOperator(address indexed operator, address indexed tokenHolder) +``` + +Indicate that the `operator` address is denied the rights to send the token of (i.e. is not operator for) the address `tokenHolder`. + +This event MUST be fired on a successful call to `revokeOperator`. + +> **parameters** +> - `operator`: Address which is denied the rights to manage the tokens. +> - `tokenHolder`: address which holds the tokens to be managed. + +
+ +### ERC777TokensSender + +Any address (contract or regular account) CAN register a contract (itself or an other) implementing the `ERC777TokensSender` interface via the ERC820 registry. + +``` solidity +interface ERC777TokensSender { + function tokensToSend( + address operator, + address from, + address to, + uint value, + bytes userData, + bytes operatorData + ) public; +} +``` + +#### Methods + +##### tokensToSend + +``` solidity +function tokensToSend(address operator, address from, address to, uint value, bytes userData, bytes operatorData) public +``` + +Notify the transmission of `amount` of tokens from the `from` address. + +> **parameters** +> - `operator`: address which triggered the transfer, either sender for a direct send or an authorized operator for `operatorSend` +> - `from`: token holder (sender) +> - `to`: tokens recipient (or `0x` for burning) +> - `amount`: number of tokens sent or burned +> - `userData`: information attached to the transaction by the sender +> - `operatorData`: information attached to the transaction by the operator + +###### Burning Versus Sending + +When tokens are sent as a result of burning: + - `to` MUST be `0x0` + - `userData` MUST be empty + - `operator` MUST be the address which initiated the burning + - `operatorData` MAY contain data + +When tokens are sent as a result of sending (`send` or `operatorSend`): + - `to` MUST be the address to which the tokens will be sent + - `to` MUST NOT be `0x0` + + If it is a direct `send` (i.e. not an `operatorSend`) the `operator` MUST be the address from which the tokens originate. That is the `from` and `operator` addresses MUST be equals. + + +### ERC777TokensRecipient + +Any address (contract or regular account) CAN register a contract (itself or an other) implementing the `ERC777TokensRecipient` interface via the ERC820 registry. + +``` solidity +interface ERC777TokensRecipient { + function tokensReceived(address operator, address from, address to, uint amount, bytes userData, bytes operatorData) public; +} +``` + +#### Methods + +##### tokensReceived + +``` solidity +function tokensReceived(address operator, address from, address to, uint amount, bytes userData, bytes operatorData) public +``` + +Notify the transmission of `amount` of tokens to the `to` address. + +> **parameters** +> - `operator`: address which triggered the transfer, either sender for a direct send or an authorized operator for `operatorSend` +> - `from`: token holder (sender or `0x` for minting) +> - `to`: tokens recipient (or `0x` for burning) +> - `amount`: number of tokens sent, minted or burned +> - `userData`: information attached to the transaction by the sender +> - `operatorData`: information attached to the transaction by the operator + +###### Minting Versus Sending + +When tokens are received as a result of minting: + - `from` MUST be `0x0` + - `userData` MUST be empty + - `operator` MUST be the address which initiated the minting + - `operatorData` MAY contain data. + +When tokens are received as a result of sending (`send` or `operatorSend`): + - `from` MUST be the one from which the tokens originate and + - `from` MUST NOT be `0x0`. + +If it is a direct `send` (i.e. not an `operatorSend`) the `operator` MUST be the address from which the tokens originate. That is the `from` and `operator` addresses MUST be equals. + +### Logo + +| **Image** |  ![beige logo](../assets/eip-777/logo/png/ERC-777-logo-beige-48px.png) |  ![white logo](../assets/eip-777/logo/png/ERC-777-logo-white-48px.png) |  ![light grey logo](../assets/eip-777/logo/png/ERC-777-logo-light_grey-48px.png) |  ![dark grey logo](../assets/eip-777/logo/png/ERC-777-logo-dark_grey-48px.png) |  ![black logo](../assets/eip-777/logo/png/ERC-777-logo-black-48px.png?raw=true) +|----------:|:---------:|:---------:|:------------:|:-----------:|:---------:| +| **Color** | beige | white | light grey | dark grey | black | +| **Hex** | `#C99D66` | `#FFFFFF` | `#EBEFF0` | `#3C3C3D` | `#000000` | + +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`. + +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. + +Also the usage of ERC820 allows backwards compatibility with wallets and proxy contracts without having to be redeployed. + +## Backwards 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 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`. + +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). + +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. + +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 table below summarize the different actions the token contract must take when sending, minting and transferring token via ERC777 and ERC20: + + + + + + + + + + + + + + + + + + + + + + + + + + +
ERC820to addressERC777 send/operatorSend and MintingERC20 transfer
+ ERC777TokensRecipient
registered +
regular address + MUST call tokensReceived +
contract
+ ERC777TokensRecipient
not registered +
regular addressSHOULD acceptSHOULD accept
contractMUST throw
+ +There is no particular action to take if `tokensToSend` is not implemented. The transfer MUST proceed and be canceled only if another condition is not respected such as lack of funds, a throw in `tokensReceived` (if present) or in some specific cases if `tokensReceived` is not implemented. + +## 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). + +## 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). + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-820.md b/EIPS/eip-820.md new file mode 100644 index 0000000000000..c3987645e5066 --- /dev/null +++ b/EIPS/eip-820.md @@ -0,0 +1,274 @@ +--- +eip: 820 +title: Pseudo-introspection registry contract +author: Jordi Baylina +discussions-to: https://github.com/ethereum/EIPs/issues/820 +status: Draft +type: Standards Track +category: ERC +created: 2018-01-05 +--- + +## Simple Summary + +This standard defines a universal registry smart contract where any address (contract or regular account) can register which interface it implements and which smart contract is responsible for its implementation. + +This standard keeps backwards compatibility with [EIP-165](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md) + +## Abstract + +This standard attempts to define a registry where smart contracts and regular accounts can publish which functionalities they implement. + +The rest of the world can query this registry to ask if a specific address implements a given interface and which smart contract handles its implementation. + +This registry can be deployed on any chain and will share the exact same address. + +Interfaces where the last 28 bytes are `0` are considered [EIP-165](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md) interfaces, and this registry +will forward the call to the contract to see if they implement that interface. + +This contract will act also as an [EIP-165](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md) cache in order to safe gas. + +## Motivation + +There has been different approaches to define pseudo-introspection in the Ethereum. The first is [EIP-165](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md) which has the problem that it is not available for regular accounts to use. The second approach is EIP-672 which uses reverseENS. Using reverseENS, has two issues. First, it is unnecessarily complex, and second, ENS is still a centralized contract controlled by a multisig. This multisig, theoretically would be able to modify the system. + +This standard is much simpler than [EIP-672](https://github.com/ethereum/EIPs/issues/672) and it is absolutely decentralized. + +This standard also solves the problem of having different addresses for different chains. + +## Specification + +### The smart contract + +```solidity +pragma solidity 0.4.20; + +interface ERC820ImplementerInterface { + /// @notice Contracts that implement an interferce in behalf of another contract must return true + /// @param addr Address that the contract woll implement the interface in behalf of + /// @param interfaceHash keccak256 of the name of the interface + /// @return ERC820_ACCEPT_MAGIC if the contract can implement the interface represented by + /// `ìnterfaceHash` in behalf of `addr` + function canImplementInterfaceForAddress(address addr, bytes32 interfaceHash) view public returns(bytes32); +} + +contract ERC820Registry { + bytes4 constant InvalidID = 0xffffffff; + bytes4 constant ERC165ID = 0x01ffc9a7; + bytes32 constant ERC820_ACCEPT_MAGIC = keccak256("ERC820_ACCEPT_MAGIC"); + + + mapping (address => mapping(bytes32 => address)) interfaces; + mapping (address => address) managers; + mapping (address => mapping(bytes4 => bool)) erc165Cache; + + modifier canManage(address addr) { + require(getManager(addr) == msg.sender); + _; + } + + + event InterfaceImplementerSet(address indexed addr, bytes32 indexed interfaceHash, address indexed implementer); + event ManagerChanged(address indexed addr, address indexed newManager); + + /// @notice Query the hash of an interface given a name + /// @param interfaceName Name of the interfce + function interfaceHash(string interfaceName) public pure returns(bytes32) { + return keccak256(interfaceName); + } + + /// @notice GetManager + function getManager(address addr) public view returns(address) { + // By default the manager of an address is the same address + if (managers[addr] == 0) { + return addr; + } else { + return managers[addr]; + } + } + + /// @notice Sets an external `manager` that will be able to call `setInterfaceImplementer()` + /// on behalf of the address. + /// @param addr Address that you are defining the manager for. + /// @param newManager The address of the manager for the `addr` that will replace + /// the old one. Set to 0x0 if you want to remove the manager. + function setManager(address addr, address newManager) public canManage(addr) { + managers[addr] = newManager == addr ? 0 : newManager; + ManagerChanged(addr, newManager); + } + + /// @notice Query if an address implements an interface and thru which contract + /// @param addr Address that is being queried for the implementation of an interface + /// @param iHash SHA3 of the name of the interface as a string + /// Example `web3.utils.sha3('ERC777Token`')` + /// @return The address of the contract that implements a specific interface + /// or 0x0 if `addr` does not implement this interface + function getInterfaceImplementer(address addr, bytes32 iHash) constant public returns (address) { + if (isERC165Interface(iHash)) { + bytes4 i165Hash = bytes4(iHash); + return erc165InterfaceSupported(addr, i165Hash) ? addr : 0; + } + return interfaces[addr][iHash]; + } + + /// @notice Sets the contract that will handle a specific interface; only + /// the address itself or a `manager` defined for that address can set it + /// @param addr Address that you want to define the interface for + /// @param iHash SHA3 of the name of the interface as a string + /// For example `web3.utils.sha3('Ierc777')` for the Ierc777 + function setInterfaceImplementer(address addr, bytes32 iHash, address implementer) public canManage(addr) { + require(!isERC165Interface(iHash)); + if ((implementer != 0) && (implementer!=msg.sender)) { + require(ERC820ImplementerInterface(implementer).canImplementInterfaceForAddress(addr, iHash) + == ERC820_ACCEPT_MAGIC); + } + interfaces[addr][iHash] = implementer; + InterfaceImplementerSet(addr, iHash, implementer); + } + + +/// ERC165 Specific + + function isERC165Interface(bytes32 iHash) internal pure returns (bool) { + return iHash & 0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0; + } + + function erc165InterfaceSupported(address _contract, bytes4 _interfaceId) constant public returns (bool) { + if (!erc165Cache[_contract][_interfaceId]) { + erc165UpdateCache(_contract, _interfaceId); + } + return interfaces[_contract][_interfaceId] != 0; + } + + function erc165UpdateCache(address _contract, bytes4 _interfaceId) public { + interfaces[_contract][_interfaceId] = + erc165InterfaceSupported_NoCache(_contract, _interfaceId) ? _contract : 0; + erc165Cache[_contract][_interfaceId] = true; + } + + function erc165InterfaceSupported_NoCache(address _contract, bytes4 _interfaceId) public constant returns (bool) { + uint256 success; + uint256 result; + + (success, result) = noThrowCall(_contract, ERC165ID); + if ((success==0)||(result==0)) { + return false; + } + + (success, result) = noThrowCall(_contract, InvalidID); + if ((success==0)||(result!=0)) { + return false; + } + + (success, result) = noThrowCall(_contract, _interfaceId); + if ((success==1)&&(result==1)) { + return true; + } + return false; + } + + function noThrowCall(address _contract, bytes4 _interfaceId) constant internal returns (uint256 success, uint256 result) { + bytes4 erc165ID = ERC165ID; + + assembly { + let x := mload(0x40) // Find empty storage location using "free memory pointer" + mstore(x, erc165ID) // Place signature at begining of empty storage + mstore(add(x, 0x04), _interfaceId) // Place first argument directly next to signature + + success := staticcall( + 30000, // 30k gas + _contract, // To addr + x, // Inputs are stored at location x + 0x08, // Inputs are 8 bytes long + x, // Store output over input (saves space) + 0x20) // Outputs are 32 bytes long + + result := mload(x) // Load the result + } + } +} +``` + +### Raw transaction for deploying the smart contract on any chain + +``` +0xf908778085174876e800830c35008080b908246060604052341561000f57600080fd5b6108068061001e6000396000f30060606040526004361061008d5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166329965a1d81146100925780633d584063146100bd578063571a1f66146100f85780635df8122f1461012457806365ba36c11461014957806390e47957146101ac578063aabbb8ca146101ec578063ddc23ddd1461020e575b600080fd5b341561009d57600080fd5b6100bb600160a060020a03600435811690602435906044351661023a565b005b34156100c857600080fd5b6100dc600160a060020a03600435166103ec565b604051600160a060020a03909116815260200160405180910390f35b341561010357600080fd5b6100bb600160a060020a0360043516600160e060020a031960243516610438565b341561012f57600080fd5b6100bb600160a060020a03600435811690602435166104c2565b341561015457600080fd5b61019a60046024813581810190830135806020601f8201819004810201604051908101604052818152929190602084018383808284375094965061057d95505050505050565b60405190815260200160405180910390f35b34156101b757600080fd5b6101d8600160a060020a0360043516600160e060020a0319602435166105e2565b604051901515815260200160405180910390f35b34156101f757600080fd5b6100dc600160a060020a0360043516602435610658565b341561021957600080fd5b6101d8600160a060020a0360043516600160e060020a0319602435166106b7565b8233600160a060020a031661024e826103ec565b600160a060020a03161461026157600080fd5b61026a8361076e565b1561027457600080fd5b600160a060020a0382161580159061029e575033600160a060020a031682600160a060020a031614155b15610373576040517f4552433832305f4143434550545f4d41474943000000000000000000000000008152601301604051908190039020600160a060020a03831663f008325086866000604051602001526040517c010000000000000000000000000000000000000000000000000000000063ffffffff8516028152600160a060020a0390921660048301526024820152604401602060405180830381600087803b151561034b57600080fd5b6102c65a03f1151561035c57600080fd5b505050604051805191909114905061037357600080fd5b600160a060020a0384811660008181526020818152604080832088845290915290819020805473ffffffffffffffffffffffffffffffffffffffff191693861693841790558591907f93baa6efbd2244243bfee6ce4cfdd1d04fc4c0e9a786abd3a41313bd352db153905160405180910390a450505050565b600160a060020a038082166000908152600160205260408120549091161515610416575080610433565b50600160a060020a03808216600090815260016020526040902054165b919050565b61044282826106b7565b61044d57600061044f565b815b600160a060020a03928316600081815260208181526040808320600160e060020a031996909616808452958252808320805473ffffffffffffffffffffffffffffffffffffffff19169590971694909417909555908152600284528181209281529190925220805460ff19166001179055565b8133600160a060020a03166104d6826103ec565b600160a060020a0316146104e957600080fd5b82600160a060020a031682600160a060020a031614610508578161050b565b60005b600160a060020a0384811660008181526001602052604090819020805473ffffffffffffffffffffffffffffffffffffffff191694841694909417909355908416917f605c2dbf762e5f7d60a546d42e7205dcb1b011ebc62a61736a57c9089d3a4350905160405180910390a3505050565b6000816040518082805190602001908083835b602083106105af5780518252601f199092019160209182019101610590565b6001836020036101000a038019825116818451161790925250505091909101925060409150505180910390209050919050565b600160a060020a0382166000908152600260209081526040808320600160e060020a03198516845290915281205460ff161515610623576106238383610438565b50600160a060020a03918216600090815260208181526040808320600160e060020a0319949094168352929052205416151590565b6000806106648361076e565b1561068957508161067584826105e2565b610680576000610682565b835b91506106b0565b600160a060020a038085166000908152602081815260408083208784529091529020541691505b5092915050565b600080806106e5857f01ffc9a700000000000000000000000000000000000000000000000000000000610790565b90925090508115806106f5575080155b156107035760009250610766565b61071585600160e060020a0319610790565b909250905081158061072657508015155b156107345760009250610766565b61073e8585610790565b90925090506001821480156107535750806001145b156107615760019250610766565b600092505b505092915050565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff161590565b6000807f01ffc9a70000000000000000000000000000000000000000000000000000000060405181815284600482015260208160088389617530fa935080519250505092509290505600a165627a7a72305820b424185958879a1eef1cb7235bfd8ed607a7402b46853860e5343340925f028e00291ba079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798a00aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +``` + +You can see the string of `a`s at the end of the transaction. This is the `s` of the signature, meaning that its a deterministic by hand forced signature. + +### Deployment method + +This contract is going to be deployed using the Nick's Method. + +This method works as follows: + +1. Generate a transaction that deploys the contract from a new random account. This transaction must not use [EIP-155](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md) so it can work on any chain. This transaction needs to also have a relatively high gas price in order to be deployed in any chain. In this case, it's going to be 100Gwei. +2. Set the `v`, `r`, `s` of the transaction signature to the following values: +` + v: 27` +` + r: 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798` +` + s: 0x0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa` +This nice `s` value is a random number generated deterministically by a human. +3. We recover the sender of this transaction. We will have an account that can broadcast that transaction, but we also have the waranty that nobody knows the private key of that account. +4. Send Ether to this deployment account. +5. Broadcast the transaction. + +This operation can be done in any chain, guaranteed that the contract address is going to always be the same and nobody will be able to mess up that address with a different contract. + + +### Special registry deployment account + +``` +0x91c2b265ece9442ed28e3c4283652b1894dcdabb +``` + +This account is generated by reverse engineering it from it's signature for the transaction, in this way no one knows the private key, but it is known that it's the valid signer of the deployment transaction. + +### Deployed contract + +``` +0x991a1bcb077599290d7305493c9a630c20f8b798 +``` + +The contract will have this address for every chain it is deployed to. + +### Interface name + +Your interface name is hashed and sent to `getInterfaceImplementer()`. If you are writing a standard, it is best practice to explicitly state the interface name and link to this published EIP-820 so that other people don't have to come here to look up these rules. + +#### If it's an approved EIP + +The interface is named like `ERC###XXXXX`. The meaning of this interface is defined in the EIP specified. And XXX should be the name of the interface camelCase. + +Examples: + +`sha3("ERC20Token")` +`sha3("ERC777Token")` +`sha3("ERC777TokensReceiver")` +`sha3("ERC777TokensSender")` + +#### [EIP-165](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md) compatible interfaces + +Interfaces where the last 28bytes are 0, then this will be considered an [EIP-165](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md) interface. + +#### Private user defined interface + +This scheme is extensible. If you want to make up your own interface name and raise awareness to get other people to implement it and then check for those implementations, great! Have fun, but please do not conflict with the reserved designations above. + +## Backwards Compatibility + +This standard is backwards compatible with [EIP-165](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md), as both methods can be implemented without conflicting one each other. + +## Test Cases + +Please, check the repository https://github.com/jbaylina/eip820 for the full test suit. + +## Implementation + +The implementation can be found in this repo: https://github.com/jbaylina/eip820 + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-858.md b/EIPS/eip-858.md index b40ed5a4aa175..71ca2b96567f5 100644 --- a/EIPS/eip-858.md +++ b/EIPS/eip-858.md @@ -15,7 +15,7 @@ Reduce the block reward to 1 ETH. The current public Ethereum network has a hashrate that corresponds to a tremendous level of energy consumption. As this energy consumption has a correlated environmental cost the network participants have an ethical obligation to ensure this cost is not higher than necessary. At this time, the most direct way to reduce this cost is to lower the block reward in order to limit the appeal of ETH mining. Unchecked growth in hashrate is also counterproductive from a security standpoint. ## Motivation -The current public Ethereum network has a hashrate of 232 TH/s). This hashrate corresponds to a **lower bound** for power usage of roughly [821 MW](eip-858/calculations.md) and yearly energy consumption of 7.2 TWh (roughly 0.033% of [total](https://en.wikipedia.org/wiki/List_of_countries_by_electricity_consumption) global electricity consumption). A future switch to full Proof of Stake will solve this issue entirely. Yet that switch remains enough in the future that action should be taken in the interim to limit excess harmful side affects of the present network. +The current public Ethereum network has a hashrate of 232 TH/s). This hashrate corresponds to a **lower bound** for power usage of roughly [821 MW](../assets/eip-858/calculations.md) and yearly energy consumption of 7.2 TWh (roughly 0.033% of [total](https://en.wikipedia.org/wiki/List_of_countries_by_electricity_consumption) global electricity consumption). A future switch to full Proof of Stake will solve this issue entirely. Yet that switch remains enough in the future that action should be taken in the interim to limit excess harmful side affects of the present network. ## Specification Block reward to be changed to 1 ETH / block. diff --git a/EIPS/eip-908.md b/EIPS/eip-908.md new file mode 100644 index 0000000000000..77c46aacfa6a6 --- /dev/null +++ b/EIPS/eip-908.md @@ -0,0 +1,73 @@ +--- +eip: 908 +title: Reward full nodes and clients +author: James Ray (@jamesray1), Micah Zoltu (@MicahZoltu) +discussions-to: https://gitter.im/ethereum/topics/topic/5ac8574227c509a774e7901a/eip-reward-full-nodes-and-clients +status: Draft +type: Standards Track +category: Core +created: 2018-03-01 +--- + + +## Simple Summary +Provide a reward to full nodes for validating transactions and give a reward to clients for developing the client. + +## Abstract +This EIP proposes to make a change to the protocol to provide a reward to full nodes for validating transactions and thus providing extra security for the Ethereum network, and a reward to clients for providing the software that enables Ethereum to function. Reward mechanisms that are external to being built in to the protocol are beyond the scope of this EIP. Such extra-protocol reward methods include state channel payments for extra services such as light client servers providing faster information such as receipts; state channel payments for buying state reads from full nodes; archival services (which is only applicable to future proposed versions of Ethereum with stateless clients); and tokens for the client and running full nodes. With a supply cap the issuance can be prevented from increasing indefinitely. + +## Motivation +Currently there is a lack of incentives for anyone to run a full node, while joining a mining pool is not really economical if one has to purchase a mining rig (several GPUs) now, since there is unlikely to be a return on investment by the time that Ethereum transitions to hybrid Proof-of-Work/Proof-of-Stake, then full PoS. Additionally, providing a reward for clients gives a revenue stream that is independent of state channels, which are less secure, although this insecurity can be offset by mechanisms such as insurance, bonded payments and time locks. Rationalising that investors may invest in a client because it is an enabler for the Ethereum ecosystem (and thus opening up investment opportunities) may not scale very well, and it seems that it is more sustainable to monetize the client as part of the service(s) it provides. + +## Specification +Micah: "when a client signs a transaction, it attaches a user agent to the signature. This could then be used to send some amount of ETH to the author of that user agent." In other words, some amount of ETH could be sent to the organization that develops the client (e.g. Parity, the Ethereum Foundation, etc.), when the transaction is processed (similar to mining rewards). The user agent would contain the information needed to send an amount of ETH to the full node operator and the client developer orgnanisation, which are addresses held by these parties and the amounts to add. Full nodes would need to add to their set up to add the address to receive ETH after validating transactions. These fields could be read-only, or immutable, so that someone can't overwrite them with another address, thus preventing one possible attack. + +Alternatively, the full node validator could insert their address (or it could be automatically extracted from the execution environment) after executing the transaction. To prevent the miner getting a double-dose of transaction fees, assert that the full node validator address is not the same as the miner's address. It may also make sense to allocate the rewards for validation not in the same block as the transactions, but multiple blocks later. The details of how these two rewards could be made may be subject to change. The actual amounts are subject to data analysis as discussed below. + +The issuance can be prevented from increasing indefinitely with a supply cap as in [this EIP-issue](https://github.com/ethereum/EIPs/issues/960), which includes reducing the rewards for miners (or other participants as in [sharding](https://ethresear.ch/t/sharding-phase-1-spec/1407) and [Casper](https://github.com/ethereum/research/tree/master/papers)), and in the long-run having no block rewards and just transaction fees, with Ether burnt e.g. from slashing participants in sharding and Casper and [lost or stuck](https://github.com/ethereum/wiki/wiki/Major-issues-resulting-in-lost-or-stuck-funds) [funds](https://github.com/ethereum/EIPs/pull/867). + +Regarding rewards for full nodes, in the [draft phase 1 sharding spec](https://ethresear.ch/t/sharding-phase-1-spec/1407) proposers acting as full nodes have rewards for proposing blobs (without execution) or later in phase 3 transactions (with execution) to be included into collations/blocks. So that would help. However, full nodes that do not act as proposers and just verify transactions, or [full state nodes](https://ethresear.ch/t/incentivizing-full-state-nodes/1640), are still not incentivized. + +## Rationale + +Discussion began at https://ethresear.ch/t/incentives-for-running-full-ethereum-nodes/1239. [Micah stated](https://ethresear.ch/t/incentives-for-running-full-ethereum-nodes/1239/4): +> The first most obvious caveat is that end-users would be incentivized to put an address of their own down as the user agent. Initial thinking on this is that there are few enough users advanced enough to run a custom client so the losses there would be minimal, and client developers are incentivized to not make the user agent string configurable because it is how they get paid. Also, presumably the per-transaction user-agent fee would be small enough such that the average user probably won’t care enough to hack their client to change it (or even switch clients to one that lets the user customize the user agent), usability and simplicity matter more to most. There is a concern that most transactions are coming in through third party Ethereum nodes like Infura or QuikNode and they have incentive and capability to change the user agent. + +Obviously, creating such an incentive to centralize full nodes is not desirable. zk-STARKs may help with this, where miners or Casper block proposers could submit a zk-STARK to prove that they executed the transaction, and reduce the cost of validation. However, zk-STARKs aren't performant enough yet to use in the blockchain. zk-SNARKs aren't transparent, so aren't suitable for including in-protocol on a public blockchain. Further research is needed to find a solution for this problem. Micah continued: + +> I’m tempted to suggest “lets wait and see if user-agent spoofing becomes a meaningful problem before trying to fix it”, since the worst it can do is put is right back where we are now with no incentives for client development. +Something to consider is that the user agent fee could be used to bribe miners by putting the miner address in instead. Once again, I’m tempted to try it out first (unless someone has better ideas) and see how things go because it is a very high coordination cost to actually bribe miners via user agent (since you don’t know who will mine the block your transaction ends up in), and there is no common infrastructure/protocol for broadcasting different transactions to different miners. + +One simple way to prevent bribing miners or miners attempting to validate the transaction in the blocks that they mine is to block miners receiving validation rewards for the blocks that they mine. One problem with this is that a miner could run a full node validator using a different address with the same computer, and just cache the result of their execution and use it for the full node validator. I'm not sure how you would prevent this, but perhaps you could using IP address tracking (similarly asserting that the IP address of a full node validator isn't the same as the miner) which would add additional complexity to the protocol, but this could also be hacked with dynamic IPs and VPNs. + +The amount of computation to validate a transaction will be the same as a miner, since the transaction will need to be executed. Thus, if there would be transaction fees for validating full nodes and clients, and transactions need to be executed by validators just like miners have to, it makes sense to have them calculated in the same way as gas fees for miners. This would controversially increase the amount of transaction fees a lot, since there can be many validators for a transaction. In other words, it is controversial whether to provide the same amount of transaction fee for a full node validator as for a miner (which in one respect is fair, since the validator has to do the same amount of computation), or prevent transaction fees from rising much higher, and have a transaction fee for a full node as, say, the transaction fee for a miner, divided by the average number of full nodes validating a transaction. The latter option seems even more controversial (but is still better than the status quo), since while there would be more of an incentive to run a full node than there is now with no incentive, validators would be paid less for performing the same amount of computation. + +And as for the absolute amounts, this will require data analysis, but clearly a full node should receive much less than a miner for processing a transaction in a block, since there are many transactions in a block, and there are many confirmations of a block. Data analysis could involve calculating the average number of full nodes verifying transactions in a block. Macroeconomic analysis could entail the economic security benefit that full nodes provide to the network. + +Now, as to the ratio of rewards to the client vs the full node, as an initial guess I would suggest something like 99:1. Why such a big difference? Well, I would guess that clients spend roughly 99 times more time on developing and maintaining the client than a full node user spends running and maintaining a full node. During a week there might be several full-time people working on the client, but a full node might only spend half an hour (or less) initially setting it up, plus running it, plus electricity and internet costs. Full node operators probably don't need to upgrade their computer (and buying a mining rig isn't worth it with Casper PoS planning on being implemented soon). + +However, on further analysis, clients would also get the benefit of a large volume of rewards from every full node running the client, so to incentivise full node operation further, the ratio could change to say, 4:1, and of course could be adjusted with even further actual data analysis, rather than speculation. + +Providing rewards to full node validators and to clients would increase the issuance. In order to maintain the issuance at current levels, this EIP could also reduce the mining reward (despite being reduced previously with the Byzantium release in October 2017 from 5 ETH to 3 ETH), but that would generate more controversy and discusssion. + +Another potential point of controversy with rewarding clients and full nodes is that the work previously done by them has not been paid for until now (except of course by the Ethereum Foundation or Parity VCs funding the work), so existing clients may say that this EIP gives an advantage to new entrants. However, this doesn't hold up well, because existing clients have the first mover advantage, with much development to create useful and well-used products. + +There is a tradeoff. Higher fees means you may cut out poor people and people who just don't want to pay fees. But if a laptop can run a full node and get paid for it then that would offset the fees through usage. Full nodes do provide a security benefit, so the total fees given could at least be some fraction of this benefit. Fees that go towards client development incentivise a higher quality client. To me, I think it makes more sense to internalize costs as much as possible: for computation, storage, bandwidth, I/O, client development, running full nodes, mining/validating, etc. You avoid a tragedy of the commons through externalizing costs. The more you internalize costs, the more sustainable it is, and the less you rely on rich people being generous, etc. (Although, getting philosophical, ultimately you can't force rich people to be generous, they have to do so out of the kindness of their hearts.) + + + +## Backwards Compatibility + + +Introducing in-protocol fees is a backwards-incompatible change, so would be introduced in a hard-fork. + +## Test Cases + +TODO + +## Implementation + +TODO + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/share-your-work/public-domain/cc0/). diff --git a/EIPS/eip-969.md b/EIPS/eip-969.md new file mode 100644 index 0000000000000..7c1e0a47f84f9 --- /dev/null +++ b/EIPS/eip-969.md @@ -0,0 +1,202 @@ +--- +eip: 969 +title: Modifications to ethash to invalidate existing dedicated hardware implementations +author: David Stanfill +discussions-to: https://gitter.im/ethereum/topics/topic/5ac4d974109bb043328911ce/eip-969-discussion +status: Draft +type: Standards Track +category: Core +created: 2018-04-03 +--- + + +## Simple Summary + +This EIP modifies ethash in order to break ASIC miners specialized for the current ethash +mining algorithm. + + +## Abstract + +There are companies who currently have dedicated hardware based ethereum miners in +production, and may be actively mining. This EIP aims to "poison +the well" by modifying the block mining algorithm in a low risk manner that +may *"break"* these miners if they are in-fact built as traditional ASICs. + + +## Motivation + +ASIC based miners will have lower operational costs than GPU based miners which +will result in GPU based mining quickly becoming unprofitable. Given that +production of ASIC based miners has a high barrier to entry and few market players, +this will cause a trend towards centralization of mining power. + +Risks include market dominance by a single manufacturer that may utilize production +stock to mine themselves, introduce backdoors in their hardware, or otherwise +facilitate a 51% attack that would be infeasible. + +This trend towards centralization has a negative effect on network security, +putting significant control of the network in the hands of only a few entities. + +Ethash remains ASIC resistant, however ASIC manufacturer technology is advancing +and ethash may require further changes in order to remain resistant to unforeseen +design techniques. This EIP seeks explicitly to buy time during which newly developed +ASIC technology will face a barrier while more long term mechanisms to ensure +continued ASIC resistance can be explored. + +## Specification + +If `block.number >= ASIC_MITIGATION_FORK_BLKNUM`, require that the ethash solution +sealing the block has been mined using `ethashV2`. + +## EthashV2 + +`ethashV2` will be identical in specification to the current `ethash`(v1) algorithm, with +the exception of the implementation of `fnv`. + +The new algorithm replaces the 5 current uses of `fnv` inside `hashimoto` with 5 +separate instances defined as `fnvA`, `fnvB`, `fnvC`, `fnvD`, and `fnvE`, utilizing + +`FNV_PRIME_A=0x10001a7` +`FNV_PRIME_B=0x10001ab` +`FNV_PRIME_C=0x10001cf` +`FNV_PRIME_D=0x10001e3` +`FNV_PRIME_E=0x10001f9` + + +`fnvA` replaces `fnv` in the DAG item selection step +`fnvB` replaces `fnv` in the DAG item mix step +`fnvC(fnvD(fnvE` replaces `fnv(fnv(fnv(` in the compress mix step + +`fnv` as utilized in DAG-item creation should remain unchanged. + +## Agent Changes (Optional Variant) + +The JSON-RPC `eth_GetWork` call may optionally return the proposed blocks algorithm. +While a miner or pool may infer the requirement for ethashV2 based on the computed +epoch of the provided seedHash, it is beneficial to explicitly provide this +field so a miner does not require special configuration when mining on a chain +that chooses not to implement the ASIC_Mitigation hardfork. + +Due to compatibility concerns with implementations that already add additional +parameters to GetWork, it is desired to add BlockNumber as an explicit 4th parameter +as suggested in https://github.com/ethereum/go-ethereum/issues/2333. Algorithm +should then be returned as either `"ethash"` or `"ethashV2"` according to the +`block.number >= ASIC_MITIGATION_FORK_BLKNUM` criteria. + +## Rationale + +This EIP is aimed at breaking existing ASIC based miners via small changes to the +existing ethash algorithm. We hope to accomplish the following: + +1. Break existing ASIC based miners. +2. Demonstrate a willingness to fork in the event of future ASIC miner production. + +Goal #1 is something that we can only do probabilistically without detailed +knowledge of existing ASIC miner design. The known released miner is available for +purchase [here](https://shop.bitmain.com/product/detail?pid=00020180403174908564M8dMJKtz06B7) with delivery slated for mid-summer. + +Our approach should balance the inherent security risks involved with changing +the mining algorithm with the risk that the change we make does not break existing + ASIC miners. This EIP leans towards minimizing the security risks by making minimal + changes to the algorithm accepting the risk that the change may not break dedicated + hardware miners that utilize partially or fully configurable logic. + +Furthermore, we do not wish to introduce significant algorithm changes that +may alter the power utilization or performance profile of existing GPU hardware. + +The change of FNV constant is a minimal change that can be quickly +implemented across the various network node and miner implementations. + +It is proposed that `ASIC_MITIGATION_FORK_BLKNUM` be no more than 5550000 (epoch 185), giving +around 30 days of notice to node and miner developers and a sufficient window +for formal analysis of the changes by experts. We must weigh this window against +the risk introduced by allowing ASICs that may exist to continue to propagate +on the network, as well as the risk of providing too much advanced warning to +ASIC developers. + +It is further understood that this change will not prevent redesign of existing +dedicated hardware with new ASIC chips. The intention of this change is only +to disable currently active or mid-production hardware and provide time for +POS development as well as larger algorithim changes to be well analyzed by +experts. + +The choice of FNV constants is made based on the formal specification at +https://tools.ietf.org/html/draft-eastlake-fnv-14#section-2.1 + +@goobur provided the following python code to output primes matching this criteria + +`candidates = [2**24 + 2**8 + _ for _ in xrange(256)]`
+`candidates = [_ for _ in candidates if is_prime(_)]`
+`["0x%x" % _ for _ in candidates if _ % (2**40 - 2**24 - 1) > (2**24 + 2**8 + 2**7)]`
+ +The minimal prime constraint was relaxed, as has already been the case in ethashV1. + +Typical ASIC synthesis tools would optimize multiplication of a constant +in the FNV algorithm, while reducing the area needed for the multiplier according +to the hamming weight of the constant. To reduce the chance of ASIC adaptation +through minor mask changes, we propose choosing new constants with a larger +hamming weight, however care should be taken not to choose constants with too +large of a weight. + +The current FNV prime, 0x1000193 has a hamming weight of 6. +`HammingWeight(0x10001a7) = 7;` +`HammingWeight(0x10001ab) = 7;` +`HammingWeight(0x10001cf) = 8;` +`HammingWeight(0x10001e3) = 7;` +`HammingWeight(0x10001ef) = 9; // Not chosen` +`HammingWeight(0x10001f9) = 8;` +`HammingWeight(0x10001fb) = 9; // Not chosen` + +An exhaustive analysis was done regarding the dispersion of these constants as compared to 0x01000193 +using the following process. + +``` +uint32_t candidate = 0; +uint32_t dups = 0; +uint32_t fnv_candidate = 0x10001a7; +uint8_t *counts = malloc(0xFFFFFFFF); +memset(counts, '\0', 0xFFFFFFFF); +for ( candidate = 0; candidate <= 0xFFFFFFFF; candidate++) { + uint32_t result = (uint_32)(candidate * fnv_candidate); + uint8_t oldCount = counts[result]; + counts[result] = counts[result]+1; + if (oldCount != 0) { + dups++; + } +} +printf("Candidate 0x%08x : %i dups", dups); +``` + +It can be empirically confirmed that no more than 1 duplicates occur in the 32 bit word space with these constants. + +It is worth noting that FNV is not a cryptographic hash, and it is not used as such in ethash. With +that said, a more invasive hash algorithm change could consider other options. One suggestion has been +[MurmorHash3](https://github.com/aappleby/smhasher/blob/master/src/MurmurHash3.cpp). + +[Other suggestions have been made](https://twitter.com/el33th4xor/status/981292363627810818). [Argon2](https://github.com/P-H-C/phc-winner-argon2), [Equihash](https://blog.z.cash/why-equihash/) of Zcash fame, and [Balloon Hashing](https://crypto.stanford.edu/balloon/). + +Another possible candidate is [Cuckoo Cycle](https://github.com/tromp/cuckoo), although there are some concerns regarding unaddressed optimization vulnerabilities. One review is found [here](https://da-data.blogspot.com/2014/03/a-public-review-of-cuckoo-cycle.html) + +This may be considered once the exact mechanism of the released ASICs is known and +their effectiveness against its optimisations can be fully evaluated. + +## Backwards Compatibility + +This change implements a backwards incompatible change to proof of work based +block mining. All existing miners will be required to update to clients which +implement this new algorithm, and all nodes will require updates to accept +solutions from the new proof of work algorithm. + +## Test Cases + +TODO: will need to generate test cases for `ethereum/tests` repository corresponding to the consensus +changes. + +## Implementation + +TODO + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/README.md b/README.md index 0469ec30d151e..2c9856a797208 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,8 @@ A browsable version of all current and draft EIPs can be found on [the official Your first PR should be a first draft of the final EIP. It must meet the formatting criteria enforced by the build (largely, correct metadata in the header). An editor will manually review the first PR for a new EIP and assign it a number before merging it. Make sure you include a `discussions-to` header with the URL to a discussion forum or open GitHub issue where people can discuss the EIP as a whole. +If your EIP requires images, the image files should be included in a subdirectory of the `assets` folder for that EIP as follow: `assets/eip-X` (for eip **X**). When linking to an image in the EIP, use relative links such as `../assets/eip-X/image.png`. + Once your first PR is merged, we have a bot that helps out by automatically merging PRs to draft EIPs. For this to work, it has to be able to tell that you own the draft being edited. Make sure that the 'author' line of your EIP contains either your Github username or your email address inside . If you use your email address, that address must be the one publicly shown on [your GitHub profile](https://github.com/settings/profile). When you believe your EIP is mature and ready to progress past the draft phase, you should do one of two things: diff --git a/_includes/authorlist.html b/_includes/authorlist.html index e32a48c49ccd2..ff78bba726246 100644 --- a/_includes/authorlist.html +++ b/_includes/authorlist.html @@ -3,6 +3,9 @@ {%- if author contains "<" -%} {%- assign authorparts=author|split:"<" -%} "}}">{{authorparts[0]|strip}} + {%- elsif author contains "(@" -%} + {%- assign authorparts=author|split:"(@" -%} + {{authorparts[0]|strip}} {%- else -%} {{author}} {%- endif -%} diff --git a/EIPS/eip-1/process.png b/assets/eip-1/process.png similarity index 100% rename from EIPS/eip-1/process.png rename to assets/eip-1/process.png diff --git a/EIPS/eip-107/authorization-locked.png b/assets/eip-107/authorization-locked.png similarity index 100% rename from EIPS/eip-107/authorization-locked.png rename to assets/eip-107/authorization-locked.png diff --git a/EIPS/eip-107/authorization-password.png b/assets/eip-107/authorization-password.png similarity index 100% rename from EIPS/eip-107/authorization-password.png rename to assets/eip-107/authorization-password.png diff --git a/EIPS/eip-107/authorization.png b/assets/eip-107/authorization.png similarity index 100% rename from EIPS/eip-107/authorization.png rename to assets/eip-107/authorization.png diff --git a/assets/eip-777/logo/png/ERC-777-logo-beige-1024px.png b/assets/eip-777/logo/png/ERC-777-logo-beige-1024px.png new file mode 100644 index 0000000000000..7faf0eee96562 Binary files /dev/null and b/assets/eip-777/logo/png/ERC-777-logo-beige-1024px.png differ diff --git a/assets/eip-777/logo/png/ERC-777-logo-beige-192px.png b/assets/eip-777/logo/png/ERC-777-logo-beige-192px.png new file mode 100644 index 0000000000000..dc9f9cebf7d2c Binary files /dev/null and b/assets/eip-777/logo/png/ERC-777-logo-beige-192px.png differ diff --git a/assets/eip-777/logo/png/ERC-777-logo-beige-2048px.png b/assets/eip-777/logo/png/ERC-777-logo-beige-2048px.png new file mode 100644 index 0000000000000..86c32b3f8b19e Binary files /dev/null and b/assets/eip-777/logo/png/ERC-777-logo-beige-2048px.png differ diff --git a/assets/eip-777/logo/png/ERC-777-logo-beige-48px.png b/assets/eip-777/logo/png/ERC-777-logo-beige-48px.png new file mode 100644 index 0000000000000..e2743edaeacd5 Binary files /dev/null and b/assets/eip-777/logo/png/ERC-777-logo-beige-48px.png differ diff --git a/assets/eip-777/logo/png/ERC-777-logo-beige-600px.png b/assets/eip-777/logo/png/ERC-777-logo-beige-600px.png new file mode 100644 index 0000000000000..26514a7ebb3d7 Binary files /dev/null and b/assets/eip-777/logo/png/ERC-777-logo-beige-600px.png differ diff --git a/assets/eip-777/logo/png/ERC-777-logo-black-1024px.png b/assets/eip-777/logo/png/ERC-777-logo-black-1024px.png new file mode 100644 index 0000000000000..7d1f221f174a9 Binary files /dev/null and b/assets/eip-777/logo/png/ERC-777-logo-black-1024px.png differ diff --git a/assets/eip-777/logo/png/ERC-777-logo-black-192px.png b/assets/eip-777/logo/png/ERC-777-logo-black-192px.png new file mode 100644 index 0000000000000..0b64da591f8aa Binary files /dev/null and b/assets/eip-777/logo/png/ERC-777-logo-black-192px.png differ diff --git a/assets/eip-777/logo/png/ERC-777-logo-black-2048px.png b/assets/eip-777/logo/png/ERC-777-logo-black-2048px.png new file mode 100644 index 0000000000000..1542250470803 Binary files /dev/null and b/assets/eip-777/logo/png/ERC-777-logo-black-2048px.png differ diff --git a/assets/eip-777/logo/png/ERC-777-logo-black-48px.png b/assets/eip-777/logo/png/ERC-777-logo-black-48px.png new file mode 100644 index 0000000000000..5e5723f5fb2ac Binary files /dev/null and b/assets/eip-777/logo/png/ERC-777-logo-black-48px.png differ diff --git a/assets/eip-777/logo/png/ERC-777-logo-black-600px.png b/assets/eip-777/logo/png/ERC-777-logo-black-600px.png new file mode 100644 index 0000000000000..f273bb12ba653 Binary files /dev/null and b/assets/eip-777/logo/png/ERC-777-logo-black-600px.png differ diff --git a/assets/eip-777/logo/png/ERC-777-logo-dark_grey-1024px.png b/assets/eip-777/logo/png/ERC-777-logo-dark_grey-1024px.png new file mode 100644 index 0000000000000..01b491a6cef6d Binary files /dev/null and b/assets/eip-777/logo/png/ERC-777-logo-dark_grey-1024px.png differ diff --git a/assets/eip-777/logo/png/ERC-777-logo-dark_grey-192px.png b/assets/eip-777/logo/png/ERC-777-logo-dark_grey-192px.png new file mode 100644 index 0000000000000..ccf550a35f6ee Binary files /dev/null and b/assets/eip-777/logo/png/ERC-777-logo-dark_grey-192px.png differ diff --git a/assets/eip-777/logo/png/ERC-777-logo-dark_grey-2048px.png b/assets/eip-777/logo/png/ERC-777-logo-dark_grey-2048px.png new file mode 100644 index 0000000000000..1ccb7a12a90c1 Binary files /dev/null and b/assets/eip-777/logo/png/ERC-777-logo-dark_grey-2048px.png differ diff --git a/assets/eip-777/logo/png/ERC-777-logo-dark_grey-48px.png b/assets/eip-777/logo/png/ERC-777-logo-dark_grey-48px.png new file mode 100644 index 0000000000000..925508c512367 Binary files /dev/null and b/assets/eip-777/logo/png/ERC-777-logo-dark_grey-48px.png differ diff --git a/assets/eip-777/logo/png/ERC-777-logo-dark_grey-600px.png b/assets/eip-777/logo/png/ERC-777-logo-dark_grey-600px.png new file mode 100644 index 0000000000000..8518053b5ccce Binary files /dev/null and b/assets/eip-777/logo/png/ERC-777-logo-dark_grey-600px.png differ diff --git a/assets/eip-777/logo/png/ERC-777-logo-light_grey-1024px.png b/assets/eip-777/logo/png/ERC-777-logo-light_grey-1024px.png new file mode 100644 index 0000000000000..6eee84d2a80a7 Binary files /dev/null and b/assets/eip-777/logo/png/ERC-777-logo-light_grey-1024px.png differ diff --git a/assets/eip-777/logo/png/ERC-777-logo-light_grey-192px.png b/assets/eip-777/logo/png/ERC-777-logo-light_grey-192px.png new file mode 100644 index 0000000000000..2be4d1c4c043e Binary files /dev/null and b/assets/eip-777/logo/png/ERC-777-logo-light_grey-192px.png differ diff --git a/assets/eip-777/logo/png/ERC-777-logo-light_grey-2048px.png b/assets/eip-777/logo/png/ERC-777-logo-light_grey-2048px.png new file mode 100644 index 0000000000000..b77b6c7c92807 Binary files /dev/null and b/assets/eip-777/logo/png/ERC-777-logo-light_grey-2048px.png differ diff --git a/assets/eip-777/logo/png/ERC-777-logo-light_grey-48px.png b/assets/eip-777/logo/png/ERC-777-logo-light_grey-48px.png new file mode 100644 index 0000000000000..98182a9475128 Binary files /dev/null and b/assets/eip-777/logo/png/ERC-777-logo-light_grey-48px.png differ diff --git a/assets/eip-777/logo/png/ERC-777-logo-light_grey-600px.png b/assets/eip-777/logo/png/ERC-777-logo-light_grey-600px.png new file mode 100644 index 0000000000000..bfe98d8f2aa4c Binary files /dev/null and b/assets/eip-777/logo/png/ERC-777-logo-light_grey-600px.png differ diff --git a/assets/eip-777/logo/png/ERC-777-logo-white-1024px.png b/assets/eip-777/logo/png/ERC-777-logo-white-1024px.png new file mode 100644 index 0000000000000..b51524bce1a69 Binary files /dev/null and b/assets/eip-777/logo/png/ERC-777-logo-white-1024px.png differ diff --git a/assets/eip-777/logo/png/ERC-777-logo-white-192px.png b/assets/eip-777/logo/png/ERC-777-logo-white-192px.png new file mode 100644 index 0000000000000..c4cb4aaeca180 Binary files /dev/null and b/assets/eip-777/logo/png/ERC-777-logo-white-192px.png differ diff --git a/assets/eip-777/logo/png/ERC-777-logo-white-2048px.png b/assets/eip-777/logo/png/ERC-777-logo-white-2048px.png new file mode 100644 index 0000000000000..58e945711f23f Binary files /dev/null and b/assets/eip-777/logo/png/ERC-777-logo-white-2048px.png differ diff --git a/assets/eip-777/logo/png/ERC-777-logo-white-48px.png b/assets/eip-777/logo/png/ERC-777-logo-white-48px.png new file mode 100644 index 0000000000000..182ea5db3c41e Binary files /dev/null and b/assets/eip-777/logo/png/ERC-777-logo-white-48px.png differ diff --git a/assets/eip-777/logo/png/ERC-777-logo-white-600px.png b/assets/eip-777/logo/png/ERC-777-logo-white-600px.png new file mode 100644 index 0000000000000..9f07c80b6d41d Binary files /dev/null and b/assets/eip-777/logo/png/ERC-777-logo-white-600px.png differ diff --git a/assets/eip-777/logo/svg/ERC-777-logo-beige.svg b/assets/eip-777/logo/svg/ERC-777-logo-beige.svg new file mode 100644 index 0000000000000..6af82af0d40dc --- /dev/null +++ b/assets/eip-777/logo/svg/ERC-777-logo-beige.svg @@ -0,0 +1,21 @@ + + + + + + + diff --git a/assets/eip-777/logo/svg/ERC-777-logo-black.svg b/assets/eip-777/logo/svg/ERC-777-logo-black.svg new file mode 100644 index 0000000000000..53869e23eef1f --- /dev/null +++ b/assets/eip-777/logo/svg/ERC-777-logo-black.svg @@ -0,0 +1,21 @@ + + + + + + + diff --git a/assets/eip-777/logo/svg/ERC-777-logo-dark_grey.svg b/assets/eip-777/logo/svg/ERC-777-logo-dark_grey.svg new file mode 100644 index 0000000000000..9821736b52596 --- /dev/null +++ b/assets/eip-777/logo/svg/ERC-777-logo-dark_grey.svg @@ -0,0 +1,21 @@ + + + + + + + diff --git a/assets/eip-777/logo/svg/ERC-777-logo-light_grey.svg b/assets/eip-777/logo/svg/ERC-777-logo-light_grey.svg new file mode 100644 index 0000000000000..1e29b8631a3ec --- /dev/null +++ b/assets/eip-777/logo/svg/ERC-777-logo-light_grey.svg @@ -0,0 +1,21 @@ + + + + + + + diff --git a/assets/eip-777/logo/svg/ERC-777-logo-white.svg b/assets/eip-777/logo/svg/ERC-777-logo-white.svg new file mode 100644 index 0000000000000..fae203bddd8b5 --- /dev/null +++ b/assets/eip-777/logo/svg/ERC-777-logo-white.svg @@ -0,0 +1,21 @@ + + + + + + + diff --git a/EIPS/eip-858/calculations.md b/assets/eip-858/calculations.md similarity index 100% rename from EIPS/eip-858/calculations.md rename to assets/eip-858/calculations.md diff --git a/eip-X.md b/eip-X.md index e9460c690b0ac..470cae1836e31 100644 --- a/eip-X.md +++ b/eip-X.md @@ -1,7 +1,7 @@ --- eip: title: -author: +author: > discussions-to: status: Draft type: