diff --git a/EIPS/eip-1.md b/EIPS/eip-1.md index 01717cc6..6de41908 100644 --- a/EIPS/eip-1.md +++ b/EIPS/eip-1.md @@ -65,10 +65,10 @@ Each status change is requested by the EIP author and reviewed by the EIP editor Other exceptional statuses include: -* Deferred -- This is for core EIPs that have been put off for a future hard fork. -* Rejected -- An EIP that is fundamentally broken or a Core EIP that was rejected by the Core Devs and will not be implemented. -* Active -- This is similar to Final, but denotes an EIP which which may be updated without changing its EIP number. -* Superseded -- An EIP which was previously final but is no longer considered state-of-the-art. Another EIP will be in Final status and reference the Superseded EIP. +* **Deferred** -- This is for core EIPs that have been put off for a future hard fork. +* **Rejected** -- An EIP that is fundamentally broken or a Core EIP that was rejected by the Core Devs and will not be implemented. +* **Active** -- This is similar to Final, but denotes an EIP which which may be updated without changing its EIP number. +* **Superseded** -- An EIP which was previously final but is no longer considered state-of-the-art. Another EIP will be in Final status and reference the Superseded EIP. ## What belongs in a successful EIP? @@ -106,9 +106,9 @@ Each EIP must begin with an RFC 822 style header preamble, preceded and followed ` status:` -`* review-period-end: YYYY-MM-DD +`* review-period-end:` YYYY-MM-DD -` type: ` +` type:` ` * category:` diff --git a/EIPS/eip-1013.md b/EIPS/eip-1013.md index 63de5905..a6d3fe62 100644 --- a/EIPS/eip-1013.md +++ b/EIPS/eip-1013.md @@ -5,7 +5,7 @@ author: Nick Savers (@nicksavers) type: Meta status: Draft created: 2018-04-20 -requires: 145, 210, 1014, 1052, 1087 +requires: 145, 1014, 1052, 1234, 1283 --- ## Abstract @@ -21,15 +21,14 @@ This meta-EIP specifies the changes included in the Ethereum hardfork named Cons - `Block >= TBD` on the Ropsten testnet - Included EIPs: - [EIP 145](./eip-145.md): Bitwise shifting instructions in EVM - - [EIP 210](./eip-210.md): Blockhash refactoring - [EIP 1014](./eip-1014.md): Skinny CREATE2 - [EIP 1052](./eip-1052.md): EXTCODEHASH Opcode - - [EIP 1087](./eip-1087.md): Net gas metering for SSTORE operations - - TBD: Ice-age delay + - [EIP 1234](./eip-1234.md): Delay difficulty bomb, adjust block reward + - [EIP 1283](./eip-1283.md): Net gas metering for SSTORE without dirty maps ## References -The list above includes the EIPs discussed as candidates for Constantinople at the [All Core Dev Meeting #42](https://github.com/ethereum/pm/blob/c78d7ff147daaafa4dce60ba56cdedbe268a0488/All%20Core%20Devs%20Meetings/Meeting%2042.md#constantinople-hard-fork-and-timing). Final decision is planned for the subsequent meeting #43. +The list above includes the EIPs discussed as candidates for Constantinople at the All Core Dev [Constantinople Session #1](https://github.com/ethereum/pm/issues/55). See also [Constantinople Progress Tracker](https://github.com/ethereum/pm/issues/53). ## Copyright diff --git a/EIPS/eip-1102.md b/EIPS/eip-1102.md index 16d5a02a..38612d40 100644 --- a/EIPS/eip-1102.md +++ b/EIPS/eip-1102.md @@ -71,11 +71,11 @@ IF provider is undefined ##### `[1] ENABLE` -Dapps MUST request a full provider by calling the `enable` method on the default read-only provider. This method MUST trigger a user interface that allows the user to approve or deny full provider access for a given dapp. This method MUST return a Promise that is resolved if the user approves full provider access or rejected if the user denies full provider access. +Dapps MUST request a full provider by calling the `enable` method on the default read-only provider. This method MUST trigger a user interface that allows the user to approve or deny full provider access for a given dapp. This method MUST return a Promise that is resolved with an array of the user's public addresses if the user approves full provider access or rejected if the user denies full provider access. ##### `[2] RESOLVE` -If a user approves full provider access, DOM environments MUST expose a fully-enabled provider at `window.ethereum` that is populated with accounts. The Promise returned when calling the `enable` method MUST be resolved. +If a user approves full provider access, DOM environments MUST expose a fully-enabled provider at `window.ethereum` that is populated with accounts. The Promise returned when calling the `enable` method MUST be resolved with an array of the user's public addresses. ##### `[3] REJECT` diff --git a/EIPS/eip-1154.md b/EIPS/eip-1154.md index 51651576..a9fedf4d 100644 --- a/EIPS/eip-1154.md +++ b/EIPS/eip-1154.md @@ -34,7 +34,7 @@ Both the ID and the results are intentionally unstructured so that things like t
Oracle
An entity which reports data to the blockchain.
-
Oracle handler
+
Oracle consumer
A smart contract which receives data from an oracle.
ID
@@ -44,12 +44,12 @@ Both the ID and the results are intentionally unstructured so that things like t
Data associated with an id which is reported by an oracle. This data oftentimes will be the answer to a question tied to the id. Other equivalent terms that have been used include: answer, data, outcome.
Report
-
A pair (ID, result) which an oracle sends to an oracle handler.
+
A pair (ID, result) which an oracle sends to an oracle consumer.
```solidity -interface OracleHandler { - function receiveResult(bytes32 id, bytes32 result) external; +interface OracleConsumer { + function receiveResult(bytes32 id, bytes result) external; } ``` @@ -57,21 +57,23 @@ interface OracleHandler { `receiveResult` MUST revert if `receiveResult` has been called with the same `id` before. -`receiveResult` MAY revert if the `id` or `result` cannot be handled by the handler. +`receiveResult` MAY revert if the `id` or `result` cannot be handled by the consumer. + +Consumers MUST coordinate with oracles to determine how to encode/decode results to and from `bytes`. For example, `abi.encode` and `abi.decode` may be used to implement a codec for results in Solidity. `receiveResult` SHOULD revert if the consumer receives a unexpected result format from the oracle. The oracle can be any Ethereum account. ## Rationale The specs are currently very similar to what is implemented by ChainLink (which can use any arbitrarily-named callback) and Oraclize (which uses `__callback`). -With this spec, the oracle _pushes_ state to the handler, which must react accordingly to the updated state. An alternate _pull_-based interface can be prescribed, as follows: +With this spec, the oracle _pushes_ state to the consumer, which must react accordingly to the updated state. An alternate _pull_-based interface can be prescribed, as follows: ### Alternate Pull-based Interface Here are alternate specs loosely based on Gnosis prediction market contracts v1. Reality Check also exposes a similar endpoint (`getFinalAnswer`). ```solidity interface Oracle { - function resultFor(bytes32 id) external view returns (bytes32 result); + function resultFor(bytes32 id) external view returns (bytes result); } ``` @@ -80,25 +82,29 @@ interface Oracle { `resultFor` MUST return the same result for an `id` after that result is available. ### Push vs Pull -Note that push-based interfaces may be adapted into pull-based interfaces. Simply deploy an oracle handler which stores the result received and implements `resultFor` accordingly. +Note that push-based interfaces may be adapted into pull-based interfaces. Simply deploy an oracle consumer which stores the result received and implements `resultFor` accordingly. -Similarly, every pull-based system can be adapted into a push-based system: just add a method on the oracle smart contract which takes an oracle handler address and calls `receiveResult` on that address. +Similarly, every pull-based system can be adapted into a push-based system: just add a method on the oracle smart contract which takes an oracle consumer address and calls `receiveResult` on that address. In both cases, an additional transaction would have to be performed, so the choice to go with push or pull should be based on the dominant use case for these oracles. In the simple case where a single account has the authority to decide the outcome of an oracle question, there is no need to deploy an oracle contract and store the outcome on that oracle contract. Similarly, in the case where the outcome comes down to a vote, existing multisignature wallets can be used as the authorized oracle. -#### Multiple Oracle Handlers -In the case that many oracle handlers depend on a single oracle result and all these handlers expect the result to be pushed to them, the push and pull adaptations mentioned before may be combined if the pushing oracle cannot be trusted to send the same result to every handler (in a sense, this forwards the trust to the oracle adaptor implementation). +#### Multiple Oracle Consumers +In the case that many oracle consumers depend on a single oracle result and all these consumers expect the result to be pushed to them, the push and pull adaptations mentioned before may be combined if the pushing oracle cannot be trusted to send the same result to every consumer (in a sense, this forwards the trust to the oracle adaptor implementation). -In a pull-based system, each of the handlers would have to be called to pull the result from the oracle contract, but in the proposed push-based system, the adapted oracle would have to be called to push the results to each of the handlers. +In a pull-based system, each of the consumers would have to be called to pull the result from the oracle contract, but in the proposed push-based system, the adapted oracle would have to be called to push the results to each of the consumers. -Transaction-wise, both systems are roughly equivalent in efficiency in this scenario, but in the push-based system, there's a need for the oracle handlers to store the results again, whereas in the pull-based system, the handlers may continue to refer to the oracle for the results. Although this may be somewhat less efficient, requiring the handlers to store the results can also provide security guarantees, especially with regards to result immutability. +Transaction-wise, both systems are roughly equivalent in efficiency in this scenario, but in the push-based system, there's a need for the oracle consumers to store the results again, whereas in the pull-based system, the consumers may continue to refer to the oracle for the results. Although this may be somewhat less efficient, requiring the consumers to store the results can also provide security guarantees, especially with regards to result immutability. #### Result Immutability -In both the proposed specification and the alternate specification, results are immutable once they are determined. This is due to the expectation that typical handlers will require results to be immutable in order to determine a resulting state consistently. With the proposed push-based system, the handler enforces the result immutability requirement, whereas in the alternate pull-based system, either the oracle would have to be trusted to implement the spec correctly and enforce the immutability requirement, or the handler would also have to handle result immutability. +In both the proposed specification and the alternate specification, results are immutable once they are determined. This is due to the expectation that typical consumers will require results to be immutable in order to determine a resulting state consistently. With the proposed push-based system, the consumer enforces the result immutability requirement, whereas in the alternate pull-based system, either the oracle would have to be trusted to implement the spec correctly and enforce the immutability requirement, or the consumer would also have to handle result immutability. For data which mutates over time, the `id` field may be structured to specify "what" and "when" for the data (using 128 bits to specify "when" is still safe for many millenia). +## Implementation + +* [Tidbit](https://github.com/levelkdev/tidbit) tracks this EIP. + ## Copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-1193.md b/EIPS/eip-1193.md index afbe3930..bfe09bb4 100644 --- a/EIPS/eip-1193.md +++ b/EIPS/eip-1193.md @@ -14,12 +14,28 @@ requires: 1102 This EIP formalizes an Ethereum Provider JavaScript API for consistency across clients and applications. -The provider is designed to be minimal, containing 3 methods: `send`, `subscribe`, and `unsubscribe`. It emits 4 types of events: `connect`, `close`, `networkChanged`, and `accountsChanged`. +The provider is designed to be minimal, containing 4 methods: `enable`, `send`, `subscribe`, and `unsubscribe`. It emits 4 types of events: `connect`, `close`, `networkChanged`, and `accountsChanged`. + +It is intended to be available on `window.ethereum`. ## API +### Enable + +By default a "read-only" provider is supplied to allow access to the blockchain while preserving user privacy. + +A full provider can be requested to allow account-level methods: + +```js +ethereum.enable(): Promise<[String]>; +``` + +Promise resolves with an array of the accounts' public keys, or rejects with `Error`. + ### Send +Ethereum API methods can be sent and received: + ```js ethereum.send(method: String, params?: Array): Promise; ``` @@ -33,7 +49,7 @@ See the [available methods](https://github.com/ethereum/wiki/wiki/JSON-RPC#json- #### Subscribe ```js -ethereum.subscribe(subscriptionType: String, params?: Array): Promise; +ethereum.subscribe(subscriptionType: String, params?: Array): Promise; ``` Promise resolves with `subscriptionId: String` or rejects with `Error`. @@ -51,7 +67,7 @@ The event emits with `result`, the subscription `result` or an `Error` object. #### Unsubscribe ```js -ethereum.unsubscribe(subscriptionId: String): Promise; +ethereum.unsubscribe(subscriptionId: String): Promise; ``` Promise resolves with `success: Boolean` or rejects with `Error`. @@ -117,113 +133,131 @@ ethereum.constructor.name; ## Examples ```js -// Request Ethereum Provider (EIP 1102) -window.addEventListener('message', event => { - if (event.data && event.data.type === 'ETHEREUM_PROVIDER_SUCCESS') { - start(window.ethereum); - } -}); -window.postMessage({ type: 'ETHEREUM_PROVIDER_REQUEST' }, this.origin); +const ethereum = window.ethereum; -function start(ethereum) { - // A) Primary use case - set provider in web3.js - web3.setProvider(ethereum); +// A) Primary use case - set provider in web3.js +web3.setProvider(ethereum); - // B) Secondary use case - use provider object directly - // Example: Log accounts - ethereum - .send('eth_accounts') - .then(accounts => { - console.log(`Accounts:\n${accounts.join('\n')}`); - }) - .catch(error => { - console.error( - `Error fetching accounts: ${error.message}. - Code: ${error.code}. Data: ${error.data}` - ); - }); +// B) Secondary use case - use provider object directly +// Example 1: Log last block +ethereum + .send('eth_getBlockByNumber', ['latest', 'true']) + .then(block => { + console.log(`Block ${block.number}:\n${block}`); + }) + .catch(error => { + console.error( + `Error fetching last block: ${error.message}. + Code: ${error.code}. Data: ${error.data}` + ); + }); - // Example: Log last block - ethereum - .send('eth_getBlockByNumber', ['latest', 'true']) - .then(block => { - console.log(`Block ${block.number}:\n${block}`); - }) - .catch(error => { - console.error( - `Error fetching last block: ${error.message}. - Code: ${error.code}. Data: ${error.data}` - ); - }); +// Example 2: Enable full provider +ethereum + .enable() + .then(accounts => { + console.log(`Enabled accounts:\n${accounts.join('\n')}`); + }) + .catch(error => { + console.error( + `Error enabling provider: ${error.message}. + Code: ${error.code}. Data: ${error.data}` + ); + }); - // Example: Log new blocks - let subId; - ethereum - .subscribe('newHeads') - .then(subscriptionId => { - subId = subscriptionId; - ethereum.on(subscriptionId, block => { - if (result instanceOf Error) { - const error = result; - console.error( - `Error from newHeads subscription: ${error.message}. - Code: ${error.code}. Data: ${error.data}` - ); - } else { - console.log(`New block ${block.number}:\n${block}`); - } - }); - }) - .catch(error => { - console.error( - `Error making newHeads subscription: ${error.message}. - Code: ${error.code}. Data: ${error.data}` - ); - }); - // to unsubscribe - ethereum - .unsubscribe(subId) - .then(result => { - console.log(`Unsubscribed newHeads subscription ${subscriptionId}`); - }) - .catch(error => { - console.error( - `Error unsubscribing newHeads subscription: ${error.message}. - Code: ${error.code}. Data: ${error.data}` - ); - }); - - // Example: Log when accounts change - const logAccounts = accounts => { +// Example 3: Log available accounts +ethereum + .send('eth_accounts') + .then(accounts => { console.log(`Accounts:\n${accounts.join('\n')}`); - }; - ethereum.on('accountsChanged', logAccounts); - // to unsubscribe - ethereum.removeListener('accountsChanged', logAccounts); - - // Example: Log if connection ends - ethereum.on('close', (code, reason) => { - console.log( - `Ethereum provider connection closed: ${reason}. Code: ${code}` + }) + .catch(error => { + console.error( + `Error fetching accounts: ${error.message}. + Code: ${error.code}. Data: ${error.data}` ); }); } + +// Example 4: Log new blocks +let subId; +ethereum + .subscribe('newHeads') + .then(subscriptionId => { + subId = subscriptionId; + ethereum.on(subscriptionId, block => { + if (result instanceOf Error) { + const error = result; + console.error( + `Error from newHeads subscription: ${error.message}. + Code: ${error.code}. Data: ${error.data}` + ); + } else { + console.log(`New block ${block.number}:\n${block}`); + } + }); + }) + .catch(error => { + console.error( + `Error making newHeads subscription: ${error.message}. + Code: ${error.code}. Data: ${error.data}` + ); + }); +// to unsubscribe +ethereum + .unsubscribe(subId) + .then(result => { + console.log(`Unsubscribed newHeads subscription ${subscriptionId}`); + }) + .catch(error => { + console.error( + `Error unsubscribing newHeads subscription: ${error.message}. + Code: ${error.code}. Data: ${error.data}` + ); + }); + +// Example 5: Log when accounts change +const logAccounts = accounts => { + console.log(`Accounts:\n${accounts.join('\n')}`); +}; +ethereum.on('accountsChanged', logAccounts); +// to unsubscribe +ethereum.removeListener('accountsChanged', logAccounts); + +// Example 6: Log if connection ends +ethereum.on('close', (code, reason) => { + console.log( + `Ethereum provider connection closed: ${reason}. Code: ${code}` + ); +}); ``` ## Specification +### Enable + +The provider supplied to a new dapp **MUST** be a "read-only" provider: authenticating no accounts by default, returning a blank array for `eth_accounts`, and rejecting any methods that require an account. + +If the dapp has been previously authenticated and remembered by the user, then the provider supplied on load **MAY** automatically be enabled with the previously authenticated accounts. + +If no accounts are authenticated, the `enable` method **MUST** ask the user which account(s) they would like to authenticate to the dapp. If the request has been previously granted and remembered, the `enable` method **MAY** immediately return with the prior remembered accounts and permissions. + +The `enable` method **MUST** return a Promise, resolving with an array of the accounts' public keys, or rejecting with an `Error`. If the accounts enabled by provider change, the `accountsChanged` event **MUST** also emit. + ### Send The `send` method **MUST** send a properly formatted [JSON-RPC request](https://www.jsonrpc.org/specification#request_object). If the Ethereum JSON-RPC API returns a response object with no error, then the Promise **MUST** resolve with the `response.result` object untouched by the implementing Ethereum Provider. -If the Ethereum JSON-RPC API returns response object that contains an error property then the Promise **MUST** be rejected with an Error object containing the `response.error.message` as the Error message, `response.error.code` as a code property on the error and `response.error.data` as a data property on the error. +If the Ethereum JSON-RPC API returns response object that contains an error property then the Promise **MUST** reject with an Error object containing the `response.error.message` as the Error message, `response.error.code` as a code property on the error and `response.error.data` as a data property on the error. -If an error occurs during processing, such as an HTTP error or internal parsing error, then the Promise **MUST** be rejected with an Error object. +If an error occurs during processing, such as an HTTP error or internal parsing error, then the Promise **MUST** reject with an `Error` object. If the implementing Ethereum Provider is not talking to an external Ethereum JSON-RPC API provider then it **MUST** resolve with an object that matches the JSON-RPC API object as specified in the [Ethereum JSON-RPC documentation](https://github.com/ethereum/wiki/wiki/JSON-RPC). +If the JSON-RPC request requires an account that is not yet authenticated, the Promise **MUST** reject with an `Error`. + ### Subscriptions The `subscribe` method **MUST** send a properly formatted [JSON-RPC request](https://www.jsonrpc.org/specification#request_object) with method `eth_subscribe` and params `[subscriptionType: String, {...params: Array}]` and **MUST** return a Promise that resolves with `subscriptionId: String` or rejected with an Error object. @@ -262,7 +296,13 @@ The implementing Ethereum Provider **MUST** be compatible as a `web3.js` provide If an Error object is returned, it **MUST** contain a human readable string message describing the error and **SHOULD** populate the `code` and `data` properties on the error object with additional error details. -Appropriate error codes **SHOULD** follow the table of [`CloseEvent` status codes](https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent#Status_codes). +Appropriate error codes **SHOULD** follow the table of [`CloseEvent` status codes](https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent#Status_codes), along with the following table: + +| Status code | Name | Description | +| ----------- | ------------------------- | -------------------------------------------------------------------------------------------------------------- | +| 4001 | User Denied Full Provider | User denied the enabling of the full Ethereum Provider by choosing not to authorize any accounts for the dapp. | +| | | | +| | | | ## Sample Class Implementation @@ -287,6 +327,15 @@ class EthereumProvider extends EventEmitter { /* Methods */ + enable() { + return new Promise((resolve, reject) => { + window.mist + .requestAccounts() + .then(resolve) + .catch(reject); + }); + } + send(method, params = []) { if (!method || typeof method !== 'string') { return new Error('Method is not a valid string.'); diff --git a/EIPS/eip-1271.md b/EIPS/eip-1271.md index 95546d33..2e9b159b 100644 --- a/EIPS/eip-1271.md +++ b/EIPS/eip-1271.md @@ -43,11 +43,12 @@ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "S * * MUST return a bool upon valid or invalid signature with corresponding _data * MUST take (bytes, bytes) as arguments +* MUST allow external calls */ function isValidSignature( - bytes _data, + bytes _data, bytes _signature) - public + public view returns (bool isValid); ``` diff --git a/EIPS/eip-1283.md b/EIPS/eip-1283.md index 14c42626..7ee488fa 100644 --- a/EIPS/eip-1283.md +++ b/EIPS/eip-1283.md @@ -13,15 +13,15 @@ created: 2018-08-01 This EIP proposes net gas metering changes for SSTORE opcode, as an alternative for EIP-1087. It tries to be friendlier to implementations -that uses different opetimiazation strategies for storage change +that use different optimization strategies for storage change caches. ## Motivation EIP-1087 proposes a way to adjust gas metering for SSTORE opcode, -enabling new usages on this opcodes where it is previously too +enabling new usages on these opcodes where it is previously too expensive. However, EIP-1087 requires keeping a dirty map for storage -changes, and implictly makes the assumption that a transaction's +changes, and implicitly makes the assumption that a transaction's storage changes are committed to the storage trie at the end of a transaction. This works well for some implementations, but not for others. After EIP-658, an efficient storage cache implementation would @@ -29,11 +29,11 @@ probably use an in-memory trie (without RLP encoding/decoding) or other immutable data structures to keep track of storage changes, and only commit changes at the end of a block. For them, it is possible to know a storage's original value and current value, but it is not -possible to iterate over all storage changes without incur additional +possible to iterate over all storage changes without incurring additional memory or processing costs. This EIP proposes an alternative way for gas metering on SSTORE, using -information that is more universially available to most +information that is more universally available to most implementations: * *Storage slot's original value*. @@ -43,7 +43,7 @@ implementations: For the specification provided here: * We don't suffer from the optimization limitation of EIP-1087, and it - never costs more gas compared with current scheme. + never costs more gas compared with the current scheme. * It covers all usages for a transient storage. Clients that are easy to implement EIP-1087 will also be easy to implement this specification. Some other clients might require a little bit extra @@ -100,7 +100,7 @@ consumed. ## Explanation -The new gas cost scheme for SSTORE is divided to three different +The new gas cost scheme for SSTORE is divided into three different types: * **No-op**: the virtual machine does not need to do anything. This is @@ -143,7 +143,7 @@ state because that is trivial: ![State Transition](../assets/eip-1283/state.png) -Below are table version of the above diagram. Vertical shows the *new +Below is table version of the above diagram. Vertical shows the *new value* being set, and horizontal shows the state of *original value* and *current value*. @@ -187,7 +187,7 @@ Examine examples provided in EIP-1087's Motivation: ## Backwards Compatibility This EIP requires a hard fork to implement. No gas cost increase is -anticipated, and many contract will see gas reduction. +anticipated, and many contracts will see gas reduction. ## Test Cases diff --git a/EIPS/eip-1328.md b/EIPS/eip-1328.md index 90fb6d21..4142fa96 100644 --- a/EIPS/eip-1328.md +++ b/EIPS/eip-1328.md @@ -1,7 +1,7 @@ --- eip: 1328 title: WalletConnect Standard URI Format -authors: ligi , Pedro Gomes +author: ligi , Pedro Gomes type: Standards Track category: ERC status: Draft @@ -24,8 +24,8 @@ This standard defines how the data to connect some application and a wallet can Function call URIs follow the ERC-831 URI format, with the following parameters: - request = "ethereum" ":" [ "wc-" ]sessionID [ "@" version ][ "?" parameters ] - sessionID = STRING + request = "ethereum" ":" [ "wc-" ]sessionId [ "@" version ][ "?" parameters ] + sessionId = STRING version = 1*DIGIT parameters = parameter *( "&" parameter ) parameter = key "=" value @@ -36,6 +36,12 @@ Function call URIs follow the ERC-831 URI format, with the following parameters: Required parameters are dependent on the WalletConnect standard version which currently is specified to only include mobile-to-desktop connection sessions which only require `name` which describes the dapp name, `bridge` which includes the bridge URL, `symKey` which includes the symmetric key in base64. +### Example + +``` +ethereum:wc-8a5e5bdc-a0e4-4702-ba63-8f1a5655744f@1?name=DappExample&bridge=https://bridge.example.com&symKey=KzpSTk1pezg5eTJRNmhWJmoxdFo6UDk2WlhaOyQ5N0U= +``` + ## Rationale The need for this ERC stems from the discussion to move away from JSON format used in current beta version of the WalletConnect standard which makes for very inneficient parsing of the intent of the QR code, making it easier to create better QR code parsers APIs for Wallets to implement for other compatible EIPs using the ERC-831 URI format for Ethereum. Also by using a URI instead of a JSON inside the QR-Code the Android Intent system can be leveraged. diff --git a/EIPS/eip-1352.md b/EIPS/eip-1352.md new file mode 100644 index 00000000..11416bba --- /dev/null +++ b/EIPS/eip-1352.md @@ -0,0 +1,40 @@ +--- +eip: 1352 +title: Specify restricted address range for precompiles/system contracts +author: Alex Beregszaszi (@axic) +discussions-to: https://ethereum-magicians.org/t/eip-1352-specify-restricted-address-range-for-precompiles-system-contracts/1151 +status: Draft +type: Standards Track +category: Core +created: 2018-07-27 +--- + +## Simple Summary +Specify an Ethereum address range occupied by precompiles and future system contracts. Regular accounts and contracts cannot obtain such an address. + +## Abstract +The address range between 0x0000000000000000000000000000000000000000 and 0x000000000000000000000000000000000000ffff is reserved for precompiles and system contracts. + +## Motivation +This will simplify certain future features where unless this is implemented, several exceptions must be specified. + +## Specification +The address range between 0x0000000000000000000000000000000000000000 and 0x000000000000000000000000000000000000ffff is reserved for precompiles and system contracts. + +Due to the extremely low probability (and lack of adequate testing possibilities) no explicit checks should be added to ensure that external transaction signing or +the invoking of the `CREATE` instruction can result in a precompile address. + +## Rationale +N/A + +## Backwards Compatibility +No contracts on the main network have been created at the specified addresses. As a result it should pose no backwards compatibility problems. + +## Test Cases +N/A + +## Implementation +N/A + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-1355.md b/EIPS/eip-1355.md index cf567db5..94197b68 100644 --- a/EIPS/eip-1355.md +++ b/EIPS/eip-1355.md @@ -1,7 +1,7 @@ --- eip: 1355 title: Ethash 1a -author: Paweł Bylica +author: Paweł Bylica , Jean M. Cyr [@jean-m-cyr](https://github.com/jean-m-cyr) discussions-to: https://ethereum-magicians.org/t/eip-1355-ethash-1a/1167 status: Draft type: Standards Track @@ -21,7 +21,7 @@ Provide minimal set of changes to Ethash algorithm to hinder and delay the adopt return ((v1 ^ v2) * FNV1A_PRIME) % 2**32 ``` where `FNV1A_PRIME` is 16777499 or 16777639. -2. Change the hash function that determines the DAG item index in Ethash algorithm from `fnv() to new `fnv1a()`. +2. Change the hash function that determines the DAG item index in Ethash algorithm from `fnv()` to new `fnv1a()`. In [Main Loop](https://github.com/ethereum/wiki/wiki/Ethash#main-loop) change ```python p = fnv(i ^ s[0], mix[i % w]) % (n // mixhashes) * mixhashes diff --git a/EIPS/eip-1380.md b/EIPS/eip-1380.md new file mode 100644 index 00000000..87a29aad --- /dev/null +++ b/EIPS/eip-1380.md @@ -0,0 +1,57 @@ +--- +eip: 1380 +title: Reduced gas cost for call to self +author: Alex Beregszaszi (@axic), Jacques Wagener (@jacqueswww) +discussions-to: https://ethereum-magicians.org/t/eip-1380-reduced-gas-cost-for-call-to-self/1242 +status: Draft +type: Standards Track +category: Core +created: 2018-08-31 +requires: 150 +--- + +## Abstract +Reduce the gas cost for call instructions, when the goal is to run a new instance of the currently loaded contract. + +## Motivation +The current gas cost of 700 for all call types (`CALL`, `DELEGATECALL`, `CALLCODE` and `STATICCALL`) does not take into account that a call to a contract itself +does not need to perform additional I/O operations, because the current contract code has already been loaded into memory. + +Reducing the call-to-self gas cost would greatly benefit smart contract languages, such as Solidity and Vyper, who would then be able to utilise `CALL` instead +of `JUMP` opcodes for internal function calls. While languages can already utilise `CALL` for internal function calls, they are discouraged to do so due to the +gas costs associated with it. + +Using `JUMP` comes at a considerable cost in complexity to the implementation of a smart contract language and/or compiler. The context (including stack and memory) +must be swapped in and out of the calling functions context. A desired feature is having *pure* functions, which do not modify the state of memory, and realising +them through `JUMP` requires a bigger effort from the compiler as opposed to being able to use `CALL`s. + +Using call-to-self provides the guarentee that when making an internal call the function can rely on a clear reset state of memory or context, benefiting both +contract writers and contract consumers against potentially undetetected edge cases were memory could poison the context of the internal function. + +Because of the `JUMP` usage for internal functions a smart contract languages are also at risk of reaching the stack depth limit considerbly faster, if nested +function calls with many in and/or outputs are required. + +Reducing the gas cost, and thereby incentivising of using call-to-self instead of `JUMP`s for the internal function implementation will also benefit static +analyzers and tracers. + +## Specification +If `block.number >= FORK_BLKNUM`, then decrease the cost of `CALL`, `DELEGATECALL`, `CALLCODE` and `STATICCALL` from 700 to 40, +if and only if, the destination address of the call equals to the address of the caller. + +## Rationale +EIP150 has increased the cost of these instructions from 40 to 700 to more fairly charge for loading new contracts from disk, e.g. to reflect the I/O charge more closely. +By assuming that 660 is the cost of loading a contract from disk, one can assume that the original 40 gas is a fair cost of creating a new VM instance of an already loaded contract code. + +## Backwards Compatibility +This should pose no risk to backwards compatibility. Currently existing contracts should not notice the difference, just see cheaper execution. +With EIP150 contract (and language) developers had a lesson that relying on strict gas costs is not feasible as costs may change. +The impact of this EIP is even less that of EIP150 because the costs are changing downwards and not upwards. + +## Test Cases +TBA + +## Implementation +TBA + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-140.md b/EIPS/eip-140.md index 744db814..8469cb07 100644 --- a/EIPS/eip-140.md +++ b/EIPS/eip-140.md @@ -1,7 +1,7 @@ --- eip: 140 title: REVERT instruction -author: Alex Beregszaszi, Nikolai Mushegian +author: Alex Beregszaszi (@axic), Nikolai Mushegian type: Standards Track category: Core status: Final diff --git a/EIPS/eip-141.md b/EIPS/eip-141.md index 64b6734f..2cc65835 100644 --- a/EIPS/eip-141.md +++ b/EIPS/eip-141.md @@ -1,7 +1,7 @@ --- eip: 141 title: Designated invalid EVM instruction -author: Alex Beregszaszi +author: Alex Beregszaszi (@axic) type: Standards Track category: Core status: Final diff --git a/EIPS/eip-145.md b/EIPS/eip-145.md index d911f0f7..67eacc2e 100644 --- a/EIPS/eip-145.md +++ b/EIPS/eip-145.md @@ -1,7 +1,7 @@ --- eip: 145 title: Bitwise shifting instructions in EVM -author: Alex Beregszaszi, Paweł Bylica +author: Alex Beregszaszi (@axic), Paweł Bylica type: Standards Track category: Core status: Accepted diff --git a/EIPS/eip-155.md b/EIPS/eip-155.md index 7716b6ab..a6739381 100644 --- a/EIPS/eip-155.md +++ b/EIPS/eip-155.md @@ -62,4 +62,5 @@ This would provide a way to send transactions that work on Ethereum without work | 42 | Kovan | | 61 | Ethereum Classic mainnet | | 62 | Ethereum Classic testnet | +| 66 | ewasm testnet | | 1337 | Geth private chains (default) | diff --git a/EIPS/eip-205.md b/EIPS/eip-205.md new file mode 100644 index 00000000..09c5e366 --- /dev/null +++ b/EIPS/eip-205.md @@ -0,0 +1,69 @@ +--- +eip: 205 +title: ENS support for contract ABIs +author: Nick Johnson +type: Standards Track +category: ERC +status: Draft +created: 2017-02-06 +requires: 137, 181 +--- + +## Simple Summary +This EIP proposes a mechanism for storing ABI definitions in ENS, for easy lookup of contract interfaces by callers. + +## Abstract +ABIs are important metadata required for interacting with most contracts. At present, they are typically supplied out-of-band, which adds an additional burden to interacting with contracts, particularly on a one-off basis or where the ABI may be updated over time. The small size of ABIs permits an alternative solution, storing them in ENS, permitting name lookup and ABI discovery via the same process. + +ABIs are typically quite compact; the largest in-use ABI we could find, that for the DAO, is 9450 bytes uncompressed JSON, 6920 bytes uncompressed CBOR, and 1128 bytes when the JSON form is compressed with zlib. Further gains on CBOR encoding are possible using a CBOR extension that permits eliminating repeated strings, which feature extensively in ABIs. Most ABIs, however, are far shorter than this, consisting of only a few hundred bytes of uncompressed JSON. + +This EIP defines a resolver profile for retrieving contract ABIs, as well as encoding standards for storing ABIs for different applications, allowing the user to select between different representations based on their need for compactness and other considerations such as onchain access. + +## Specification +### ABI encodings +In order to allow for different tradeoffs between onchain size and accessibility, several ABI encodings are defined. Each ABI encoding is defined by a unique constant with only a single bit set, allowing for the specification of 256 unique encodings in a single uint. + +The currently recognised encodings are: + +| ID | Description | +|----|----------------------| +| 1 | JSON | +| 2 | zlib-compressed JSON | +| 4 | CBOR | +| 8 | URI | + +This table may be extended in future through the EIP process. + +Encoding type 1 specifies plaintext JSON, uncompressed; this is the standard format in which ABIs are typically encoded, but also the bulkiest, and is not easily parseable onchain. + +Encoding type 2 specifies zlib-compressed JSON. This is significantly smaller than uncompressed JSON, and is straightforward to decode offchain. However, it is impracticalfor onchain consumers to use. + +Encoding type 4 is [CBOR](http://cbor.io/). CBOR is a binary encoding format that is a superset of JSON, and is both more compact and easier to parse in limited environments such as the EVM. Consumers that support CBOR are strongly encouraged to also support the [stringref extension](http://cbor.schmorp.de/stringref) to CBOR, which provides significant additional reduction in encoded size. + +Encoding type 8 indicates that the ABI can be found elsewhere, at the specified URI. This is typically the most compact of the supported forms, but also adds external dependencies for implementers. The specified URI may use any schema, but HTTP, IPFS, and Swarm are expected to be the most common. + +### Resolver profile +A new resolver interface is defined, consisting of the following method: + + function ABI(bytes32 node, uint256 contentType) constant returns (uint256, bytes); + +The interface ID of this interface is 0x2203ab56. + +contentType is a bitfield, and is the bitwise OR of all the encoding types the caller will accept. Resolvers that implement this interface must return an ABI encoded using one of the requested formats, or `(0, "")` if they do not have an ABI for this function, or do not support any of the requested formats. + +The `abi` resolver profile is valid on both forward and reverse records. + +### ABI lookup process + +When attempting to fetch an ABI based on an ENS name, implementers should first attempt an ABI lookup on the name itself. If that lookup returns no results, they should attempt a reverse lookup on the Ethereum address the name resolves to. + +Implementers should support as many of the ABI encoding formats as practical. + +## Rationale + +Storing ABIs onchain avoids the need to introduce additional dependencies for applications wishing to fetch them, such as swarm or HTTP access. Given the typical compactness of ABIs, we believe this is a worthwhile tradeoff in many cases. + +The two-step resolution process permits different names to provide different ABIs for the same contract, such as in the case where it's useful to provide a minimal ABI to some callers, as well as specifying ABIs for contracts that did not specify one of their own. The fallback to looking up an ABI on the reverse record permits contracts to specify their own canonical ABI, and prevents the need for duplication when multiple names reference the same contract without the need for different ABIs. + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-233.md b/EIPS/eip-233.md new file mode 100644 index 00000000..dd6877f2 --- /dev/null +++ b/EIPS/eip-233.md @@ -0,0 +1,35 @@ +--- +eip: 233 +title: Formal process of hard forks +author: Alex Beregszaszi (@axic) +discussions-to: https://ethereum-magicians.org/t/eip-233-formal-process-of-hard-forks/1387 +type: Meta +status: Draft +created: 2017-03-23 +--- + +## Abstract + +To describe the formal process of preparing and activating hard forks. + +## Motivation + +Today discussions about hard forks happen at various forums and sometimes in ad-hoc ways. + +## Specification + +A Meta EIP should be created and merged as a *Draft* as soon as a new hard fork is planned. This EIP should contain: +- the desired codename of the hard fork, +- list of all the EIPs included in the hard fork and +- activation block number once decided and +- the **Requires** header should point to the previous hard fork meta EIP. + +The draft shall be updated with summaries of the decisions around the hard fork. It should move in to the `Accepted` state once the changes are frozen (i.e. all referenced EIPs are in the `Accepted` state) and in to the `Final` state once the hard fork has been activated. + +## Rationale + +A meta EIP for coordinating the hard fork should help in visibility and traceability of the scope of changes as well as provide a simple name and/or number for referring to the proposed fork. + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-5.md b/EIPS/eip-5.md index ae6ad165..dfde87b3 100644 --- a/EIPS/eip-5.md +++ b/EIPS/eip-5.md @@ -2,10 +2,11 @@ eip: 5 title: Gas Usage for `RETURN` and `CALL*` author: Christian Reitwiessner -status: Draft +status: Superseded type: Standards Track category: Core created: 2015-11-22 +superseded-by: 211 --- ### Abstract diff --git a/EIPS/eip-606.md b/EIPS/eip-606.md index d7935a8b..9273e9eb 100644 --- a/EIPS/eip-606.md +++ b/EIPS/eip-606.md @@ -1,7 +1,7 @@ --- eip: 606 title: "Hardfork Meta: Homestead" -author: Alex Beregszaszi +author: Alex Beregszaszi (@axic) type: Meta status: Final created: 2017-04-23 diff --git a/EIPS/eip-607.md b/EIPS/eip-607.md index 6d24572d..5c524c37 100644 --- a/EIPS/eip-607.md +++ b/EIPS/eip-607.md @@ -1,7 +1,7 @@ --- eip: 607 title: "Hardfork Meta: Spurious Dragon" -author: Alex Beregszaszi +author: Alex Beregszaszi (@axic) type: Meta status: Final created: 2017-04-23 diff --git a/EIPS/eip-608.md b/EIPS/eip-608.md index 9d056b0e..5c5060d8 100644 --- a/EIPS/eip-608.md +++ b/EIPS/eip-608.md @@ -1,7 +1,7 @@ --- eip: 608 title: "Hardfork Meta: Tangerine Whistle" -author: Alex Beregszaszi +author: Alex Beregszaszi (@axic) type: Meta status: Final created: 2017-04-23 diff --git a/EIPS/eip-609.md b/EIPS/eip-609.md index bfdd5069..94a708c4 100644 --- a/EIPS/eip-609.md +++ b/EIPS/eip-609.md @@ -1,7 +1,7 @@ --- eip: 609 title: "Hardfork Meta: Byzantium" -author: Alex Beregszaszi +author: Alex Beregszaszi (@axic) type: Meta status: Final created: 2017-04-23 diff --git a/EIPS/eip-820.md b/EIPS/eip-820.md index 6b219b54..8dcb92c9 100644 --- a/EIPS/eip-820.md +++ b/EIPS/eip-820.md @@ -3,7 +3,7 @@ eip: 820 title: Pseudo-introspection Registry Contract author: Jordi Baylina , Jacques Dafflon discussions-to: https://github.com/ethereum/EIPs/issues/820 -status: Draft +status: Last Call type: Standards Track category: ERC created: 2018-01-05 @@ -13,15 +13,15 @@ created: 2018-01-05 This standard defines a universal registry smart contract where any address (contract or regular account) can register which interface it supports and which smart contract is responsible for its implementation. -This standard keeps backwards compatibility with [ERC165]. +This standard keeps backward compatibility with [ERC165]. ## Abstract -This standard attempts to define a registry where smart contracts and regular accounts can publish which functionalities they implement—either directly or through a proxy contract . +This standard defines a registry where smart contracts and regular accounts can publish which functionalities they implement---either directly or through a proxy contract. -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. +Anyone can query this registry to ask if a specific address implements a given interface and which smart contract handles its implementation. -This registry MAY be deployed on any chain and will share the exact same address. +This registry MAY be deployed on any chain and shares the same address on all chains. Interfaces with zeroes (`0`) as the last 28 bytes are considered [ERC165] interfaces, and this registry SHALL forward the call to the contract to see if it implements the interface. @@ -29,11 +29,11 @@ This contract also acts as an [ERC165] cache to reduce gas consumption. ## Motivation -There has been different approaches to define pseudo-introspection in Ethereum. The first is [ERC165] which has the limitation that it cannot be used by regular accounts. The second attempt is [ERC672] 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. +There have been different approaches to define pseudo-introspection in Ethereum. The first is [ERC165] which has the limitation that it cannot be used by regular accounts. The second attempt is [ERC672] which uses reverse [ENS]. Using reverse [ENS] has two issues. First, it is unnecessarily complicated, 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 [ERC672] and it is fully decentralized. +This standard is much simpler than [ERC672], and it is *fully* decentralized. -This standard also provides a unique address for all chains. Thus solving the problem of resolving the correct registry address for different chains. +This standard also provides a *unique* address for all chains. Thus solving the problem of resolving the correct registry address for different chains. ## Specification @@ -70,7 +70,7 @@ This standard also provides a unique address for all chains. Thus solving the pr */ pragma solidity 0.4.24; // IV is value needed to have a vanity address starting with `0x820`. -// IV: 1200 +// IV: 2241 /// @dev The interface a contract MUST implement if it is the implementer of /// some (other) interface for any address other than itself. @@ -260,14 +260,14 @@ contract ERC820Registry { Below is the raw transaction which MUST be used to deploy the smart contract on any chain. ``` -0xf90ab18085174876e800830c35008080b90a5e608060405234801561001057600080fd5b50610a3e806100206000396000f30060806040526004361061008d5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166329965a1d81146100925780633d584063146100bf5780635df8122f146100fc57806365ba36c114610123578063a41e7d511461018e578063aabbb8ca146101bc578063b7056765146101e0578063f712f3e814610222575b600080fd5b34801561009e57600080fd5b506100bd600160a060020a036004358116906024359060443516610250565b005b3480156100cb57600080fd5b506100e0600160a060020a036004351661054b565b60408051600160a060020a039092168252519081900360200190f35b34801561010857600080fd5b506100bd600160a060020a0360043581169060243516610597565b34801561012f57600080fd5b506040805160206004803580820135601f810184900484028501840190955284845261017c9436949293602493928401919081908401838280828437509497506106aa9650505050505050565b60408051918252519081900360200190f35b34801561019a57600080fd5b506100bd600160a060020a0360043516600160e060020a031960243516610774565b3480156101c857600080fd5b506100e0600160a060020a03600435166024356107fe565b3480156101ec57600080fd5b5061020e600160a060020a0360043516600160e060020a031960243516610878565b604080519115158252519081900360200190f35b34801561022e57600080fd5b5061020e600160a060020a0360043516600160e060020a03196024351661092d565b6000600160a060020a038416156102675783610269565b335b9050336102758261054b565b600160a060020a0316146102d3576040805160e560020a62461bcd02815260206004820152600f60248201527f4e6f7420746865206d616e616765720000000000000000000000000000000000604482015290519081900360640190fd5b6102dc836109a3565b15610331576040805160e560020a62461bcd02815260206004820152601960248201527f4d757374206e6f74206265206120455243313635206861736800000000000000604482015290519081900360640190fd5b600160a060020a038216158015906103525750600160a060020a0382163314155b156104da5760405160200180807f4552433832305f4143434550545f4d414749430000000000000000000000000081525060130190506040516020818303038152906040526040518082805190602001908083835b602083106103c65780518252601f1990920191602091820191016103a7565b51815160209384036101000a6000190180199092169116179052604080519290940182900382207ff0083250000000000000000000000000000000000000000000000000000000008352600160a060020a038881166004850152602484018b90529451909650938816945063f0083250936044808401945091929091908290030181600087803b15801561045957600080fd5b505af115801561046d573d6000803e3d6000fd5b505050506040513d602081101561048357600080fd5b5051146104da576040805160e560020a62461bcd02815260206004820181905260248201527f446f6573206e6f7420696d706c656d656e742074686520696e74657266616365604482015290519081900360640190fd5b600160a060020a03818116600081815260208181526040808320888452909152808220805473ffffffffffffffffffffffffffffffffffffffff19169487169485179055518692917f93baa6efbd2244243bfee6ce4cfdd1d04fc4c0e9a786abd3a41313bd352db15391a450505050565b600160a060020a038082166000908152600160205260408120549091161515610575575080610592565b50600160a060020a03808216600090815260016020526040902054165b919050565b6000600160a060020a038316156105ae57826105b0565b335b9050336105bc8261054b565b600160a060020a03161461061a576040805160e560020a62461bcd02815260206004820152600f60248201527f4e6f7420746865206d616e616765720000000000000000000000000000000000604482015290519081900360640190fd5b80600160a060020a031682600160a060020a031614610639578161063c565b60005b600160a060020a03828116600081815260016020526040808220805473ffffffffffffffffffffffffffffffffffffffff19169585169590951790945592519185169290917f605c2dbf762e5f7d60a546d42e7205dcb1b011ebc62a61736a57c9089d3a43509190a3505050565b6000816040516020018082805190602001908083835b602083106106df5780518252601f1990920191602091820191016106c0565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040526040518082805190602001908083835b602083106107425780518252601f199092019160209182019101610723565b5181516020939093036101000a6000190180199091169216919091179052604051920182900390912095945050505050565b61077e8282610878565b61078957600061078b565b815b600160a060020a03928316600081815260208181526040808320600160e060020a031996909616808452958252808320805473ffffffffffffffffffffffffffffffffffffffff19169590971694909417909555908152600284528181209281529190925220805460ff19166001179055565b60008080600160a060020a038516156108175784610819565b335b9150610824846109a3565b15610849575082610835828261092d565b610840576000610842565b815b9250610870565b600160a060020a038083166000908152602081815260408083208884529091529020541692505b505092915050565b600080806108a6857f01ffc9a7000000000000000000000000000000000000000000000000000000006109c5565b90925090508115806108b6575080155b156108c45760009250610870565b6108d685600160e060020a03196109c5565b90925090508115806108e757508015155b156108f55760009250610870565b6108ff85856109c5565b90925090506001821480156109145750806001145b156109225760019250610870565b506000949350505050565b600160a060020a0382166000908152600260209081526040808320600160e060020a03198516845290915281205460ff16151561096e5761096e8383610774565b50600160a060020a03918216600090815260208181526040808320600160e060020a0319949094168352929052205416151590565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff161590565b6040517f01ffc9a7000000000000000000000000000000000000000000000000000000008082526004820183905260009182919060208160088189617530fa9051909690955093505050505600a165627a7a72305820aebcc5581490dc97cade67a16777bfda36414f87fac1422cc9f37c2d60691cea00291ba079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798a00820820820820820820820820820820820820820820820820820820820820820 +0xf90ab18085174876e800830c35008080b90a5e608060405234801561001057600080fd5b50610a3e806100206000396000f30060806040526004361061008d5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166329965a1d81146100925780633d584063146100bf5780635df8122f146100fc57806365ba36c114610123578063a41e7d511461018e578063aabbb8ca146101bc578063b7056765146101e0578063f712f3e814610222575b600080fd5b34801561009e57600080fd5b506100bd600160a060020a036004358116906024359060443516610250565b005b3480156100cb57600080fd5b506100e0600160a060020a036004351661054b565b60408051600160a060020a039092168252519081900360200190f35b34801561010857600080fd5b506100bd600160a060020a0360043581169060243516610597565b34801561012f57600080fd5b506040805160206004803580820135601f810184900484028501840190955284845261017c9436949293602493928401919081908401838280828437509497506106aa9650505050505050565b60408051918252519081900360200190f35b34801561019a57600080fd5b506100bd600160a060020a0360043516600160e060020a031960243516610774565b3480156101c857600080fd5b506100e0600160a060020a03600435166024356107fe565b3480156101ec57600080fd5b5061020e600160a060020a0360043516600160e060020a031960243516610878565b604080519115158252519081900360200190f35b34801561022e57600080fd5b5061020e600160a060020a0360043516600160e060020a03196024351661092d565b6000600160a060020a038416156102675783610269565b335b9050336102758261054b565b600160a060020a0316146102d3576040805160e560020a62461bcd02815260206004820152600f60248201527f4e6f7420746865206d616e616765720000000000000000000000000000000000604482015290519081900360640190fd5b6102dc836109a3565b15610331576040805160e560020a62461bcd02815260206004820152601960248201527f4d757374206e6f74206265206120455243313635206861736800000000000000604482015290519081900360640190fd5b600160a060020a038216158015906103525750600160a060020a0382163314155b156104da5760405160200180807f4552433832305f4143434550545f4d414749430000000000000000000000000081525060130190506040516020818303038152906040526040518082805190602001908083835b602083106103c65780518252601f1990920191602091820191016103a7565b51815160209384036101000a6000190180199092169116179052604080519290940182900382207ff0083250000000000000000000000000000000000000000000000000000000008352600160a060020a038881166004850152602484018b90529451909650938816945063f0083250936044808401945091929091908290030181600087803b15801561045957600080fd5b505af115801561046d573d6000803e3d6000fd5b505050506040513d602081101561048357600080fd5b5051146104da576040805160e560020a62461bcd02815260206004820181905260248201527f446f6573206e6f7420696d706c656d656e742074686520696e74657266616365604482015290519081900360640190fd5b600160a060020a03818116600081815260208181526040808320888452909152808220805473ffffffffffffffffffffffffffffffffffffffff19169487169485179055518692917f93baa6efbd2244243bfee6ce4cfdd1d04fc4c0e9a786abd3a41313bd352db15391a450505050565b600160a060020a038082166000908152600160205260408120549091161515610575575080610592565b50600160a060020a03808216600090815260016020526040902054165b919050565b6000600160a060020a038316156105ae57826105b0565b335b9050336105bc8261054b565b600160a060020a03161461061a576040805160e560020a62461bcd02815260206004820152600f60248201527f4e6f7420746865206d616e616765720000000000000000000000000000000000604482015290519081900360640190fd5b80600160a060020a031682600160a060020a031614610639578161063c565b60005b600160a060020a03828116600081815260016020526040808220805473ffffffffffffffffffffffffffffffffffffffff19169585169590951790945592519185169290917f605c2dbf762e5f7d60a546d42e7205dcb1b011ebc62a61736a57c9089d3a43509190a3505050565b6000816040516020018082805190602001908083835b602083106106df5780518252601f1990920191602091820191016106c0565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040526040518082805190602001908083835b602083106107425780518252601f199092019160209182019101610723565b5181516020939093036101000a6000190180199091169216919091179052604051920182900390912095945050505050565b61077e8282610878565b61078957600061078b565b815b600160a060020a03928316600081815260208181526040808320600160e060020a031996909616808452958252808320805473ffffffffffffffffffffffffffffffffffffffff19169590971694909417909555908152600284528181209281529190925220805460ff19166001179055565b60008080600160a060020a038516156108175784610819565b335b9150610824846109a3565b15610849575082610835828261092d565b610840576000610842565b815b9250610870565b600160a060020a038083166000908152602081815260408083208884529091529020541692505b505092915050565b600080806108a6857f01ffc9a7000000000000000000000000000000000000000000000000000000006109c5565b90925090508115806108b6575080155b156108c45760009250610870565b6108d685600160e060020a03196109c5565b90925090508115806108e757508015155b156108f55760009250610870565b6108ff85856109c5565b90925090506001821480156109145750806001145b156109225760019250610870565b506000949350505050565b600160a060020a0382166000908152600260209081526040808320600160e060020a03198516845290915281205460ff16151561096e5761096e8383610774565b50600160a060020a03918216600090815260208181526040808320600160e060020a0319949094168352929052205416151590565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff161590565b6040517f01ffc9a7000000000000000000000000000000000000000000000000000000008082526004820183905260009182919060208160088189617530fa9051909690955093505050505600a165627a7a72305820e3db118fca3ca7b01f94f0360177adb045fd6d1e613065f54a0a71f84318cdc300291ba08208208208208208208208208208208208208208208208208208208208208200a00820820820820820820820820820820820820820820820820820820820820820 ``` -The string of `820`'s at the end of the transaction is the `s` of the signature. From this pattern, one can clearly deduce that it is a deterministic signature generated by a human. +The strings of `820`'s at the end of the transaction are the `r` and `s` of the signature. From this pattern, one can clearly deduce that it is a deterministic signature generated by a human. ### Deployment Method -This contract is going to be deployed using the keyless deployment method—also known as [Nick]'s method—which relies on a single-use address. (See [Nick's article] for more details). This method works as follows: +This contract is going to be deployed using the keyless deployment method---also known as [Nick]'s method---which relies on a single-use address. (See [Nick's article] for more details). This method works as follows: 1. Generate a transaction which deploys the contract from a new random account. - This transaction MUST NOT use [EIP155] in order to work on any chain. @@ -277,38 +277,45 @@ This contract is going to be deployed using the keyless deployment method— ``` v: 27 - r: 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798 + r: 0x8208208208208208208208208208208208208208208208208208208208208200 s: 0x0820820820820820820820820820820820820820820820820820820820820820 ``` -This nice `s` value---made of a repetion of `820`---is a predicatable "random number" generated deterministically by a human. + Those `r` and `s` values---made of a repeating pattern of `820`'s---are predictable "random numbers" generated deterministically by a human. -3. We recover the sender of this transaction, i.e. the deployment account. + > The values of `r` and `s` must be 32 bytes long each---or 64 characters in hexadecimal. Since `820` is 3 characters long and 3 is not a divisor of 64, but it is a divisor of 63, the `r` and `s` values are padded with one extra character. + > The `s` value is prefixed with a single zero (`0`). The `0` prefix also guarantees that `s < secp256k1n ÷ 2 + 1`. + > The `r` value, cannot be prefixed with a zero, as the transaction becomes invalid. Instead it is suffixed with a zero (`0`) which still respects the condition `s < secp256k1n`. + +3. We recover the sender of this transaction, i.e., the single-use deployment account. > Thus we obtain an account that can broadcast that transaction, but we also have the warranty that nobody knows the private key of that account. -4. Send Ether to this deployment account. +4. Send exactly 0.08 ethers to this single-use deployment account. -5. Broadcast the transaction. +5. Broadcast the deployment transaction. -This operation can be done on any chain, guaranteeing 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. +This operation can be done on any chain, guaranteeing that the contract address is always the same and nobody can use that address with a different contract. -### Special Registry Deployment Account +### Single-use Registry Deployment Account ``` -0xC3AdeE9B2E23837DF6259A984Af7a437dE4E2ab6 +0x2681AFA843b492f3d7851afCeca7385a3D13fCE0 ``` This account is generated by reverse engineering it from its signature for the transaction. This way no one knows the private key, but it is known that it is the valid signer of the deployment transaction. -### Deployed contract +> To deploy the registry, 0.08 ethers MUST be sent to this account *first*. + +### Registry Contract Address ``` -0x820d0Bc4d0AD9E0E7dc19BD8cF9C566FC86054ce +0x820c4597Fc3E4193282576750Ea4fcfe34DdF0a7 ``` -The contract has the address above for every chain it is deployed to. +The contract has the address above for every chain on which it is deployed. +
Raw metadata of ./contracts/ERC820Registry.sol
@@ -625,8 +632,8 @@ The contract has the address above for every chain it is deployed to.
   },
   "sources": {
     "./contracts/ERC820Registry.sol": {
-      "content": "/* ERC820: Pseudo-introspection Registry Contract\n * by Jordi Baylina and Jacques Dafflon\n *\n * To the extent possible under law, Jordi Baylina and Jacques Dafflon who\n * associated CC0 with the ERC820: Pseudo-introspection Registry Contract have\n * waived all copyright and related or neighboring rights to the\n * ERC820: Pseudo-introspection Registry Contract.\n *\n * You should have received a copy of the CC0 legalcode along with this work.\n * If not, see .\n *\n *    ███████╗██████╗  ██████╗ █████╗ ██████╗  ██████╗\n *    ██╔════╝██╔══██╗██╔════╝██╔══██╗╚════██╗██╔═████╗\n *    █████╗  ██████╔╝██║     ╚█████╔╝ █████╔╝██║██╔██║\n *    ██╔══╝  ██╔══██╗██║     ██╔══██╗██╔═══╝ ████╔╝██║\n *    ███████╗██║  ██║╚██████╗╚█████╔╝███████╗╚██████╔╝\n *    ╚══════╝╚═╝  ╚═╝ ╚═════╝ ╚════╝ ╚══════╝ ╚═════╝\n *\n *    ██████╗ ███████╗ ██████╗ ██╗███████╗████████╗██████╗ ██╗   ██╗\n *    ██╔══██╗██╔════╝██╔════╝ ██║██╔════╝╚══██╔══╝██╔══██╗╚██╗ ██╔╝\n *    ██████╔╝█████╗  ██║  ███╗██║███████╗   ██║   ██████╔╝ ╚████╔╝\n *    ██╔══██╗██╔══╝  ██║   ██║██║╚════██║   ██║   ██╔══██╗  ╚██╔╝\n *    ██║  ██║███████╗╚██████╔╝██║███████║   ██║   ██║  ██║   ██║\n *    ╚═╝  ╚═╝╚══════╝ ╚═════╝ ╚═╝╚══════╝   ╚═╝   ╚═╝  ╚═╝   ╚═╝\n *\n */\npragma solidity 0.4.24;\n// IV is value needed to have a vanity address starting with `0x820`.\n// IV: 1200\n\n/// @dev The interface a contract MUST implement if it is the implementer of\n/// some (other) interface for any address other than itself.\ninterface ERC820ImplementerInterface {\n    /// @notice Indicates whether the contract implements the interface `interfaceHash` for the address `addr` or not.\n    /// @param addr Address for which the contract will implement the interface\n    /// @param interfaceHash keccak256 hash of the name of the interface\n    /// @return ERC820_ACCEPT_MAGIC only if the contract implements `interfaceHash` for the address `addr`.\n    function canImplementInterfaceForAddress(address addr, bytes32 interfaceHash) public view returns(bytes32);\n}\n\n\n/// @title ERC820 Pseudo-introspection Registry Contract\n/// @author Jordi Baylina and Jacques Dafflon\n/// @notice This contract is the official implementation of the ERC820 Registry.\n/// @notice For more details, see https://eips.ethereum.org/EIPS/eip-820\ncontract ERC820Registry {\n    /// @notice ERC165 Invalid ID.\n    bytes4 constant INVALID_ID = 0xffffffff;\n    /// @notice Method ID for the ERC165 supportsInterface method (= `bytes4(keccak256('supportsInterface(bytes4)'))`).\n    bytes4 constant ERC165ID = 0x01ffc9a7;\n    /// @notice Magic value which is returned if a contract implements an interface on behalf of some other address.\n    bytes32 constant ERC820_ACCEPT_MAGIC = keccak256(abi.encodePacked(\"ERC820_ACCEPT_MAGIC\"));\n\n    mapping (address => mapping(bytes32 => address)) interfaces;\n    mapping (address => address) managers;\n    mapping (address => mapping(bytes4 => bool)) erc165Cached;\n\n    /// @notice Indicates a contract is the `implementer` of `interfaceHash` for `addr`.\n    event InterfaceImplementerSet(address indexed addr, bytes32 indexed interfaceHash, address indexed implementer);\n    /// @notice Indicates `newManager` is the address of the new manager for `addr`.\n    event ManagerChanged(address indexed addr, address indexed newManager);\n\n    /// @notice Query if an address implements an interface and through which contract.\n    /// @param _addr Address being queried for the implementer of an interface.\n    /// (If `_addr == 0` then `msg.sender` is assumed.)\n    /// @param _interfaceHash keccak256 hash of the name of the interface as a string.\n    /// E.g., `web3.utils.keccak256('ERC777Token')`.\n    /// @return The address of the contract which implements the interface `_interfaceHash` for `_addr`\n    /// or `0x0` if `_addr` did not register an implementer for this interface.\n    function getInterfaceImplementer(address _addr, bytes32 _interfaceHash) external view returns (address) {\n        address addr = _addr == 0 ? msg.sender : _addr;\n        if (isERC165Interface(_interfaceHash)) {\n            bytes4 erc165InterfaceHash = bytes4(_interfaceHash);\n            return implementsERC165Interface(addr, erc165InterfaceHash) ? addr : 0;\n        }\n        return interfaces[addr][_interfaceHash];\n    }\n\n    /// @notice Sets the contract which implements a specific interface for an address.\n    /// Only the manager defined for that address can set it.\n    /// (Each address is the manager for itself until it sets a new manager.)\n    /// @param _addr Address to define the interface for. (If `_addr == 0` then `msg.sender` is assumed.)\n    /// @param _interfaceHash keccak256 hash of the name of the interface as a string.\n    /// For example, `web3.utils.keccak256('ERC777TokensRecipient')` for the `ERC777TokensRecipient` interface.\n    function setInterfaceImplementer(address _addr, bytes32 _interfaceHash, address _implementer) external {\n        address addr = _addr == 0 ? msg.sender : _addr;\n        require(getManager(addr) == msg.sender, \"Not the manager\");\n\n        require(!isERC165Interface(_interfaceHash), \"Must not be a ERC165 hash\");\n        if (_implementer != 0 && _implementer != msg.sender) {\n            require(\n                ERC820ImplementerInterface(_implementer)\n                    .canImplementInterfaceForAddress(addr, _interfaceHash) == ERC820_ACCEPT_MAGIC,\n                \"Does not implement the interface\"\n            );\n        }\n        interfaces[addr][_interfaceHash] = _implementer;\n        emit InterfaceImplementerSet(addr, _interfaceHash, _implementer);\n    }\n\n    /// @notice Sets the `_newManager` as manager for the `_addr` address.\n    /// The new manager will be able to call `setInterfaceImplementer` for `_addr`.\n    /// @param _addr Address for which to set the new manager. (If `_addr == 0` then `msg.sender` is assumed.)\n    /// @param _newManager Address of the new manager for `addr`. (Pass `0x0` to reset the manager to `_addr` itself.)\n    function setManager(address _addr, address _newManager) external {\n        address addr = _addr == 0 ? msg.sender : _addr;\n        require(getManager(addr) == msg.sender, \"Not the manager\");\n        managers[addr] = _newManager == addr ? 0 : _newManager;\n        emit ManagerChanged(addr, _newManager);\n    }\n\n    /// @notice Get the manager of an address.\n    /// @param _addr Address for which to return the manager.\n    /// @return Address of the manager for a given address.\n    function getManager(address _addr) public view returns(address) {\n        // By default the manager of an address is the same address\n        if (managers[_addr] == 0) {\n            return _addr;\n        } else {\n            return managers[_addr];\n        }\n    }\n\n    /// @notice Compute the keccak256 hash of an interface given its name.\n    /// @param _interfaceName Name of the interface.\n    /// @return The keccak256 hash of an interface name.\n    function interfaceHash(string _interfaceName) public pure returns(bytes32) {\n        return keccak256(abi.encodePacked(_interfaceName));\n    }\n\n    /* --- ERC165 Related Functions --- */\n\n    /// @notice Checks whether a contract implements an ERC165 interface or not.\n    /// The result is cached. If the cache is out of date, it must be updated by calling `updateERC165Cache`.\n    /// @param _contract Address of the contract to check.\n    /// @param _interfaceId ERC165 interface to check.\n    /// @return `true` if `_contract` implements `_interfaceId`, false otherwise.\n    /// @dev This function may modify the state when updating the cache. However, this function must have the `view`\n    /// modifier since `getInterfaceImplementer` also calls it. If called from within a transaction, the ERC165 cache\n    /// is updated.\n    function implementsERC165Interface(address _contract, bytes4 _interfaceId) public view returns (bool) {\n        if (!erc165Cached[_contract][_interfaceId]) {\n            updateERC165Cache(_contract, _interfaceId);\n        }\n        return interfaces[_contract][_interfaceId] != 0;\n    }\n\n    /// @notice Updates the cache with whether the contract implements an ERC165 interface or not.\n    /// @param _contract Address of the contract for which to update the cache.\n    /// @param _interfaceId ERC165 interface for which to update the cache.\n    function updateERC165Cache(address _contract, bytes4 _interfaceId) public {\n        interfaces[_contract][_interfaceId] = implementsERC165InterfaceNoCache(_contract, _interfaceId) ? _contract : 0;\n        erc165Cached[_contract][_interfaceId] = true;\n    }\n\n    /// @notice Checks whether a contract implements an ERC165 interface or not without using nor updating the cache.\n    /// @param _contract Address of the contract to check.\n    /// @param _interfaceId ERC165 interface to check.\n    /// @return `true` if `_contract` implements `_interfaceId`, false otherwise.\n    function implementsERC165InterfaceNoCache(address _contract, bytes4 _interfaceId) public view returns (bool) {\n        uint256 success;\n        uint256 result;\n\n        (success, result) = noThrowCall(_contract, ERC165ID);\n        if (success == 0 || result == 0) {\n            return false;\n        }\n\n        (success, result) = noThrowCall(_contract, INVALID_ID);\n        if (success == 0 || result != 0) {\n            return false;\n        }\n\n        (success, result) = noThrowCall(_contract, _interfaceId);\n        if (success == 1 && result == 1) {\n            return true;\n        }\n        return false;\n    }\n\n    /// @notice Checks whether the hash is a ERC165 interface (ending with 28 zeroes) or not.\n    /// @param _interfaceHash The hash to check.\n    /// @return `true` if the hash is a ERC165 interface (ending with 28 zeroes), `false` otherwise.\n    function isERC165Interface(bytes32 _interfaceHash) internal pure returns (bool) {\n        return _interfaceHash & 0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0;\n    }\n\n    function noThrowCall(address _contract, bytes4 _interfaceId)\n        internal view returns (uint256 success, uint256 result)\n    {\n        bytes4 erc165ID = ERC165ID;\n\n        assembly {\n                let x := mload(0x40)               // Find empty storage location using \"free memory pointer\"\n                mstore(x, erc165ID)                // Place signature at begining of empty storage\n                mstore(add(x, 0x04), _interfaceId) // Place first argument directly next to signature\n\n                success := staticcall(\n                    30000,                         // 30k gas\n                    _contract,                     // To addr\n                    x,                             // Inputs are stored at location x\n                    0x08,                          // Inputs are 8 bytes long\n                    x,                             // Store output over input (saves space)\n                    0x20                           // Outputs are 32 bytes long\n                )\n\n                result := mload(x)                 // Load the result\n        }\n    }\n}\n",
-      "keccak256": "0xbc18b6a4ad0aeb405e2ebae976b0ab653c17b3ba60eeaf0f1cf740a26bdcb7f1"
+      "content": "/* ERC820: Pseudo-introspection Registry Contract\n * by Jordi Baylina and Jacques Dafflon\n *\n * To the extent possible under law, Jordi Baylina and Jacques Dafflon who\n * associated CC0 with the ERC820: Pseudo-introspection Registry Contract have\n * waived all copyright and related or neighboring rights to the\n * ERC820: Pseudo-introspection Registry Contract.\n *\n * You should have received a copy of the CC0 legalcode along with this work.\n * If not, see .\n *\n *    ███████╗██████╗  ██████╗ █████╗ ██████╗  ██████╗\n *    ██╔════╝██╔══██╗██╔════╝██╔══██╗╚════██╗██╔═████╗\n *    █████╗  ██████╔╝██║     ╚█████╔╝ █████╔╝██║██╔██║\n *    ██╔══╝  ██╔══██╗██║     ██╔══██╗██╔═══╝ ████╔╝██║\n *    ███████╗██║  ██║╚██████╗╚█████╔╝███████╗╚██████╔╝\n *    ╚══════╝╚═╝  ╚═╝ ╚═════╝ ╚════╝ ╚══════╝ ╚═════╝\n *\n *    ██████╗ ███████╗ ██████╗ ██╗███████╗████████╗██████╗ ██╗   ██╗\n *    ██╔══██╗██╔════╝██╔════╝ ██║██╔════╝╚══██╔══╝██╔══██╗╚██╗ ██╔╝\n *    ██████╔╝█████╗  ██║  ███╗██║███████╗   ██║   ██████╔╝ ╚████╔╝\n *    ██╔══██╗██╔══╝  ██║   ██║██║╚════██║   ██║   ██╔══██╗  ╚██╔╝\n *    ██║  ██║███████╗╚██████╔╝██║███████║   ██║   ██║  ██║   ██║\n *    ╚═╝  ╚═╝╚══════╝ ╚═════╝ ╚═╝╚══════╝   ╚═╝   ╚═╝  ╚═╝   ╚═╝\n *\n */\npragma solidity 0.4.24;\n// IV is value needed to have a vanity address starting with `0x820`.\n// IV: 2241\n\n/// @dev The interface a contract MUST implement if it is the implementer of\n/// some (other) interface for any address other than itself.\ninterface ERC820ImplementerInterface {\n    /// @notice Indicates whether the contract implements the interface `interfaceHash` for the address `addr` or not.\n    /// @param addr Address for which the contract will implement the interface\n    /// @param interfaceHash keccak256 hash of the name of the interface\n    /// @return ERC820_ACCEPT_MAGIC only if the contract implements `interfaceHash` for the address `addr`.\n    function canImplementInterfaceForAddress(address addr, bytes32 interfaceHash) public view returns(bytes32);\n}\n\n\n/// @title ERC820 Pseudo-introspection Registry Contract\n/// @author Jordi Baylina and Jacques Dafflon\n/// @notice This contract is the official implementation of the ERC820 Registry.\n/// @notice For more details, see https://eips.ethereum.org/EIPS/eip-820\ncontract ERC820Registry {\n    /// @notice ERC165 Invalid ID.\n    bytes4 constant INVALID_ID = 0xffffffff;\n    /// @notice Method ID for the ERC165 supportsInterface method (= `bytes4(keccak256('supportsInterface(bytes4)'))`).\n    bytes4 constant ERC165ID = 0x01ffc9a7;\n    /// @notice Magic value which is returned if a contract implements an interface on behalf of some other address.\n    bytes32 constant ERC820_ACCEPT_MAGIC = keccak256(abi.encodePacked(\"ERC820_ACCEPT_MAGIC\"));\n\n    mapping (address => mapping(bytes32 => address)) interfaces;\n    mapping (address => address) managers;\n    mapping (address => mapping(bytes4 => bool)) erc165Cached;\n\n    /// @notice Indicates a contract is the `implementer` of `interfaceHash` for `addr`.\n    event InterfaceImplementerSet(address indexed addr, bytes32 indexed interfaceHash, address indexed implementer);\n    /// @notice Indicates `newManager` is the address of the new manager for `addr`.\n    event ManagerChanged(address indexed addr, address indexed newManager);\n\n    /// @notice Query if an address implements an interface and through which contract.\n    /// @param _addr Address being queried for the implementer of an interface.\n    /// (If `_addr == 0` then `msg.sender` is assumed.)\n    /// @param _interfaceHash keccak256 hash of the name of the interface as a string.\n    /// E.g., `web3.utils.keccak256('ERC777Token')`.\n    /// @return The address of the contract which implements the interface `_interfaceHash` for `_addr`\n    /// or `0x0` if `_addr` did not register an implementer for this interface.\n    function getInterfaceImplementer(address _addr, bytes32 _interfaceHash) external view returns (address) {\n        address addr = _addr == 0 ? msg.sender : _addr;\n        if (isERC165Interface(_interfaceHash)) {\n            bytes4 erc165InterfaceHash = bytes4(_interfaceHash);\n            return implementsERC165Interface(addr, erc165InterfaceHash) ? addr : 0;\n        }\n        return interfaces[addr][_interfaceHash];\n    }\n\n    /// @notice Sets the contract which implements a specific interface for an address.\n    /// Only the manager defined for that address can set it.\n    /// (Each address is the manager for itself until it sets a new manager.)\n    /// @param _addr Address to define the interface for. (If `_addr == 0` then `msg.sender` is assumed.)\n    /// @param _interfaceHash keccak256 hash of the name of the interface as a string.\n    /// For example, `web3.utils.keccak256('ERC777TokensRecipient')` for the `ERC777TokensRecipient` interface.\n    function setInterfaceImplementer(address _addr, bytes32 _interfaceHash, address _implementer) external {\n        address addr = _addr == 0 ? msg.sender : _addr;\n        require(getManager(addr) == msg.sender, \"Not the manager\");\n\n        require(!isERC165Interface(_interfaceHash), \"Must not be a ERC165 hash\");\n        if (_implementer != 0 && _implementer != msg.sender) {\n            require(\n                ERC820ImplementerInterface(_implementer)\n                    .canImplementInterfaceForAddress(addr, _interfaceHash) == ERC820_ACCEPT_MAGIC,\n                \"Does not implement the interface\"\n            );\n        }\n        interfaces[addr][_interfaceHash] = _implementer;\n        emit InterfaceImplementerSet(addr, _interfaceHash, _implementer);\n    }\n\n    /// @notice Sets the `_newManager` as manager for the `_addr` address.\n    /// The new manager will be able to call `setInterfaceImplementer` for `_addr`.\n    /// @param _addr Address for which to set the new manager. (If `_addr == 0` then `msg.sender` is assumed.)\n    /// @param _newManager Address of the new manager for `addr`. (Pass `0x0` to reset the manager to `_addr` itself.)\n    function setManager(address _addr, address _newManager) external {\n        address addr = _addr == 0 ? msg.sender : _addr;\n        require(getManager(addr) == msg.sender, \"Not the manager\");\n        managers[addr] = _newManager == addr ? 0 : _newManager;\n        emit ManagerChanged(addr, _newManager);\n    }\n\n    /// @notice Get the manager of an address.\n    /// @param _addr Address for which to return the manager.\n    /// @return Address of the manager for a given address.\n    function getManager(address _addr) public view returns(address) {\n        // By default the manager of an address is the same address\n        if (managers[_addr] == 0) {\n            return _addr;\n        } else {\n            return managers[_addr];\n        }\n    }\n\n    /// @notice Compute the keccak256 hash of an interface given its name.\n    /// @param _interfaceName Name of the interface.\n    /// @return The keccak256 hash of an interface name.\n    function interfaceHash(string _interfaceName) public pure returns(bytes32) {\n        return keccak256(abi.encodePacked(_interfaceName));\n    }\n\n    /* --- ERC165 Related Functions --- */\n\n    /// @notice Checks whether a contract implements an ERC165 interface or not.\n    /// The result is cached. If the cache is out of date, it must be updated by calling `updateERC165Cache`.\n    /// @param _contract Address of the contract to check.\n    /// @param _interfaceId ERC165 interface to check.\n    /// @return `true` if `_contract` implements `_interfaceId`, false otherwise.\n    /// @dev This function may modify the state when updating the cache. However, this function must have the `view`\n    /// modifier since `getInterfaceImplementer` also calls it. If called from within a transaction, the ERC165 cache\n    /// is updated.\n    function implementsERC165Interface(address _contract, bytes4 _interfaceId) public view returns (bool) {\n        if (!erc165Cached[_contract][_interfaceId]) {\n            updateERC165Cache(_contract, _interfaceId);\n        }\n        return interfaces[_contract][_interfaceId] != 0;\n    }\n\n    /// @notice Updates the cache with whether the contract implements an ERC165 interface or not.\n    /// @param _contract Address of the contract for which to update the cache.\n    /// @param _interfaceId ERC165 interface for which to update the cache.\n    function updateERC165Cache(address _contract, bytes4 _interfaceId) public {\n        interfaces[_contract][_interfaceId] = implementsERC165InterfaceNoCache(_contract, _interfaceId) ? _contract : 0;\n        erc165Cached[_contract][_interfaceId] = true;\n    }\n\n    /// @notice Checks whether a contract implements an ERC165 interface or not without using nor updating the cache.\n    /// @param _contract Address of the contract to check.\n    /// @param _interfaceId ERC165 interface to check.\n    /// @return `true` if `_contract` implements `_interfaceId`, false otherwise.\n    function implementsERC165InterfaceNoCache(address _contract, bytes4 _interfaceId) public view returns (bool) {\n        uint256 success;\n        uint256 result;\n\n        (success, result) = noThrowCall(_contract, ERC165ID);\n        if (success == 0 || result == 0) {\n            return false;\n        }\n\n        (success, result) = noThrowCall(_contract, INVALID_ID);\n        if (success == 0 || result != 0) {\n            return false;\n        }\n\n        (success, result) = noThrowCall(_contract, _interfaceId);\n        if (success == 1 && result == 1) {\n            return true;\n        }\n        return false;\n    }\n\n    /// @notice Checks whether the hash is a ERC165 interface (ending with 28 zeroes) or not.\n    /// @param _interfaceHash The hash to check.\n    /// @return `true` if the hash is a ERC165 interface (ending with 28 zeroes), `false` otherwise.\n    function isERC165Interface(bytes32 _interfaceHash) internal pure returns (bool) {\n        return _interfaceHash & 0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0;\n    }\n\n    function noThrowCall(address _contract, bytes4 _interfaceId)\n        internal view returns (uint256 success, uint256 result)\n    {\n        bytes4 erc165ID = ERC165ID;\n\n        assembly {\n                let x := mload(0x40)               // Find empty storage location using \"free memory pointer\"\n                mstore(x, erc165ID)                // Place signature at begining of empty storage\n                mstore(add(x, 0x04), _interfaceId) // Place first argument directly next to signature\n\n                success := staticcall(\n                    30000,                         // 30k gas\n                    _contract,                     // To addr\n                    x,                             // Inputs are stored at location x\n                    0x08,                          // Inputs are 8 bytes long\n                    x,                             // Store output over input (saves space)\n                    0x20                           // Outputs are 32 bytes long\n                )\n\n                result := mload(x)                 // Load the result\n        }\n    }\n}\n",
+      "keccak256": "0x62a6edf7c4b0584f5fdffb4978cb084768572be3bdf9386577da889f001fb689"
     }
   },
   "version": 1
@@ -640,6 +647,19 @@ Any interface name is hashed using `keccak256` and sent to `getInterfaceImplemen
 
 If the interface is part of a standard, it is best practice to explicitly state the interface name and link to this published [ERC820] such that other people don't have to come here to look up these rules.
 
+For convenience the registry provides a function to compute the hash on-chain:
+
+``` solidity
+function interfaceHash(string _interfaceName) public pure returns(bytes32)
+```
+
+Compute the keccak256 hash of an interface given its name.
+
+> **identifier:** `65ba36c1`  
+> **parameters**  
+> `_interfaceName`: Name of the interface.  
+> **returns:** The `keccak256` hash of an interface name.
+
 #### **Approved ERCs**
 
 If the interface is part of an approved ERC, it MUST be named `ERC###XXXXX` where `###` is the number of the ERC and XXXXX should be the name of the interface in CamelCase. The meaning of this interface SHOULD be defined in the specified ERC.
@@ -655,6 +675,38 @@ Examples:
 
 Any interface where the last 28 bytes are zeroes (`0`) SHALL be considered an [ERC165] interface.
 
+**[ERC165] Lookup**
+
+Anyone can explicitly check if a contract implements an [ERC165] interface using the registry by calling one of the two functions below:
+
+``` solidity
+function implementsERC165Interface(address _contract, bytes4 _interfaceId) public view returns (bool)
+```
+
+Checks whether a contract implements an [ERC165] interface or not.
+
+The result is cached. If the cache is out of date, it must be updated by calling `updateERC165Cache`.
+
+*NOTE*: This function may modify the state when updating the cache. However, this function must have the `view` modifier since `getInterfaceImplementer` also calls it. If called from within a transaction, the [ERC165] cache is updated.
+
+> **identifier:** `f712f3e8`  
+> **parameters**  
+> `_contract`: Address of the contract to check.  
+> `_interfaceId`: [ERC165] interface to check.  
+> **returns:** `true` if `_contract` implements `_interfaceId`, false otherwise.
+
+``` solidity
+function implementsERC165InterfaceNoCache(address _contract, bytes4 _interfaceId) public view returns (bool)
+```
+
+Checks whether a contract implements an [ERC165] interface or not without using nor updating the cache.
+
+> **identifier:** `b7056765`  
+> **parameters**  
+> `_contract`: Address of the contract to check.  
+> `_interfaceId`: [ERC165] interface to check.  
+> **returns:** `true` if `_contract` implements `_interfaceId`, false otherwise.
+
 **[ERC165] Cache**
 
 Whether a contract implements an [ERC165] interface or not is automatically cached during [lookup] if the lookup is part of a transaction.
@@ -665,9 +717,10 @@ If a contract dynamically changes its interface, that contract SHOULD update the
 function updateERC165Cache(address _contract, bytes4 _interfaceId) public
 ```
 
+> **identifier:** `a41e7d51`  
 > **parameters**  
 > `_contract`: Address of the contract for which to update the cache.  
-> `_interfaceHash`: ERC165 interface for which to update the cache.
+> `_interfaceHash`: [ERC165] interface for which to update the cache.
 
 #### **Private User-defined Interfaces**
 
@@ -681,7 +734,7 @@ For any address to set a contract as the interface implementation, it must call
 function setInterfaceImplementer(address _addr, bytes32 _interfaceHash, address _implementer) public
 ```
 
-Sets the contract that will handle a specific interface.
+Sets the contract which implements a specific interface for an address.
 
 Only the `manager` defined for that address can set it. (Each address is the manager for itself, see the [manager] section for more details.)
 
@@ -690,8 +743,9 @@ Only the `manager` defined for that address can set it. (Each address is the man
 - The `_implementer` MUST implement the `ERC820ImplementerInterface` (detailed below).
 - Calling `canImplementInterfaceForAddress` on `_implementer` with the given `_addr` and  `_interfaceHash` MUST return the `ERC820_ACCEPT_MAGIC` value.
 
-*NOTE*: The `_interfaceHash` MUST NOT be an [ERC165] interface—it MUST NOT end with 28 zeroes (`0`).
+*NOTE*: The `_interfaceHash` MUST NOT be an [ERC165] interface---it MUST NOT end with 28 zeroes (`0`).
 
+> **identifier:** `29965a1d`  
 > **parameters**  
 > `_addr`: Address to define the interface for (if `_addr == 0` them `msg.sender`: is assumed)  
 > `_interfaceHash`: `keccak256` hash of the name of the interface as a string, for example `web3.utils.keccak256('ERC777TokensRecipient')` for the ERC777TokensRecipient interface.
@@ -708,6 +762,7 @@ Query if an address implements an interface and through which contract.
 
 *NOTE*: If the last 28 bytes of the `_interfaceHash` are zeroes (`0`), then the first 4 bytes are considered an [ERC165] interface and the registry SHALL forward the call to the contract at `_addr` to see if it implements the [ERC165] interface (the first 4 bytes of `_interfaceHash`). The registry SHALL also cache [ERC165] queries to reduce gas consumption. Anyone MAY call the `erc165UpdateCache` function to update whether a contract implements an interface or not.
 
+> **identifier:** `aabbb8ca`  
 > **parameters**  
 > `_addr`: Address being queried for the implementer of an interface. (If `_addr == 0` them `msg.sender` is assumed.)  
 > `_interfaceHash`: keccak256 hash of the name of the interface as a string. E.g. `web3.utils.keccak256('ERC777Token')`  
@@ -736,9 +791,11 @@ Indicates whether a contract implements an interface (`interfaceHash`) for a giv
 
 If a contract implements the interface (`interfaceHash`) for a given address (`addr`), it MUST return `ERC820_ACCEPT_MAGIC` when called with the `addr` and the `interfaceHash`. If it does not implement the `interfaceHash` for a given address (`addr`), it MUST NOT return `ERC820_ACCEPT_MAGIC`.
 
+> **identifier:** `f0083250`  
 > **parameters**  
 > `addr`: Address for which the interface is implemented  
-> `interfaceHash`: Hash of the interface which is implemented
+> `interfaceHash`: Hash of the interface which is implemented  
+> **returns:** `ERC820_ACCEPT_MAGIC` only if the contract implements `ìnterfaceHash` for the address `addr`.
 
 The special value `ERC820_ACCEPT_MAGIC` is defined as the `keccka256` hash of the string `"ERC820_ACCEPT_MAGIC"`.
 
@@ -752,7 +809,7 @@ bytes32 constant ERC820_ACCEPT_MAGIC = keccak256("ERC820_ACCEPT_MAGIC");
 
 The manager of an address (regular account or a contract) is the only entity allowed to register implementations of interfaces for the address. By default, any address is its own manager.
 
-The manager can transfer its role to another address by calling `setManager` with the address for which to transfer the manager and the address of the new manager.
+The manager can transfer its role to another address by calling `setManager` on the registry contract with the address for which to transfer the manager and the address of the new manager.
 
 **`setManager` function**
 
@@ -767,6 +824,7 @@ The new manager will be able to call `setInterfaceImplementer` for `_addr`.
 If `_addr` is `0x0`, `msg.sender` is assumed for `_addr`.  
 If `_newManager` is `0x0`, the manager is reset to `_addr` itself as the manager.
 
+> **identifier:** `5df8122f`  
 > **parameters**  
 > `_addr`: Address for which to set the new manager. (Pass `0x0` to use `msg.sender` as the address.)  
 > `_newManager`: The address of the new manager for `_addr`. (Pass `0x0` to reset the manager to `_addr`.)
@@ -779,6 +837,7 @@ function getManager(address _addr) public view returns(address)
 
 Get the manager of an address.
 
+> **identifier:** `3d584063`  
 > **parameters**  
 > `_addr`: Address for which to return the manager.  
 > **returns:** Address of the manager for a given address.
@@ -809,3 +868,4 @@ Copyright and related rights waived via [CC0].
 [jbaylina/eip820]: https://github.com/jbaylina/eip820
 [CC0]: https://creativecommons.org/publicdomain/zero/1.0/
 [Nick]: https://github.com/Arachnid/
+[ENS]: https://ens.domains/
diff --git a/EIPS/eip-998.md b/EIPS/eip-998.md
index 1f8bab05..88f0b920 100644
--- a/EIPS/eip-998.md
+++ b/EIPS/eip-998.md
@@ -1312,6 +1312,10 @@ Here is an example of what could occur if **from** was not explicitly provided i
 
 
 ### Additional Reading Material
+[Introducing Crypto Composables](https://medium.com/coinmonks/introducing-crypto-composables-ee5701fde217)
+
+[Crypto Composables — Building Blocks and Applications](https://medium.com/coinmonks/introducing-crypto-composables-ee5701fde217)
+
 [Top-Down and Bottom-Up Composables, What's the Difference and Which One Should You Use?](https://hackernoon.com/top-down-and-bottom-up-composables-whats-the-difference-and-which-one-should-you-use-db939f6acf1d)
 
 Join the discussion about composables in the [NFTy Magician's Discord](https://discord.gg/8cuuj2Y).