diff --git a/EIPS/eip-1057.md b/EIPS/eip-1057.md index 9e27b341909b6..913af46d79213 100644 --- a/EIPS/eip-1057.md +++ b/EIPS/eip-1057.md @@ -1,9 +1,9 @@ --- eip: 1057 title: ProgPoW, a Programmatic Proof-of-Work -author: IfDefElse +author: Greg Colvin , Andrea Lanfranchi (@AndreaLanfranchi), Michael Carter (@bitsbetrippin), IfDefElse discussions-to: https://ethereum-magicians.org/t/eip-progpow-a-programmatic-proof-of-work/272 -status: Draft +status: Accepted type: Standards Track category: Core created: 2018-05-02 @@ -13,15 +13,45 @@ created: 2018-05-02 A new Proof-of-Work algorithm to replace Ethash that utilizes almost all parts of commodity GPUs. +We **Do Not** recommend that this Proposal be deployed at this time. Rather it is being offered in the spirit of [Ben DiFrancesco's compromise](https://ethereum-magicians.org/t/a-progpow-compromise-pre-proposal/4057) which for our purposes we state simply as, +* This Proposal **is not** being proposed for deployment in any planned hardfork. +* This Proposal should be fully implemented and tested across major clients. +* Clients implementing this Proposal should be deployed and maintained on a testnet. + +This leaves open the possibility and threat of future deployment. + ## Abstract -ProgPoW is a proof-of-work algorithm designed to close the efficiency gap available to specialized ASICs. It utilizes almost all parts of commodity hardware (GPUs), and comes pre-tuned for the most common hardware utilized in the Ethereum network. +ProgPoW is a proof-of-work algorithm designed to close the efficiency gap available to specialized ASICs. It utilizes almost all parts of commodity hardware (GPUs), and comes pre-tuned for the most common hardware utilized in the Ethereum network. + +This document presents an overview of the algorithm and examines what it means to be “ASIC-resistant.” Next, we compare existing PoW designs by analyzing how each algorithm executes in hardware. Finally, we present the detailed implementation by walking through the code. ## Motivation -Ever since the first bitcoin mining ASIC was released, many new Proof of Work algorithms have been created with the intention of being “ASIC-resistant”. The goal of “ASIC-resistance” is to resist the centralization of PoW mining power such that these coins couldn’t be so easily manipulated by a few players. +Ever since the first bitcoin mining ASIC was released, many new Proof of Work algorithms have been created with the intention of being “ASIC-resistant”. The goal of “ASIC-resistance” is to resist the centralization of PoW mining power such that these coins couldn’t be so easily manipulated by a few players. -This document presents an overview of the algorithm and examines what it means to be “ASIC-resistant.” Next, we compare existing PoW designs by analyzing how each algorithm executes in hardware. Finally, we present the detailed implementation by walking through the code. +Ethereum's approach is to incentivize a geographically-distributed community of miners with a low barrier to entry on commodity hardware. As stated in the Yellow Paper: + +> 11.5. Mining Proof-of-Work. The mining proof-ofwork (PoW) exists as a cryptographically secure nonce that proves beyond reasonable doubt that a particular amount of computation has been expended in the determination of some token value n. It is utilised to enforce the blockchain security by giving meaning and credence to the notion of difficulty (and, by extension, total difficulty). However, since mining new blocks comes with an attached reward, the proof-of-work not only functions as a method of securing confidence that the blockchain will remain canonical into the future, but also as a wealth distribution mechanism. + +> For both reasons, there are two important goals of the proof-of-work function; firstly, it should be as accessible as possible to as many people as possible. The requirement of, or reward from, specialised and uncommon hardware should be minimised. This makes the distribution model as open as possible, and, ideally, makes the act of mining a simple swap from electricity to Ether at roughly the same rate for anyone around the world. + +> Secondly, it should not be possible to make super-linear profits, and especially not so with a high initial barrier. Such a mechanism allows a well-funded adversary to gain a troublesome amount of the network’s total mining power and as such gives them a super-linear reward (thus skewing distribution in their favour) as well as reducing the network security... + +> ... While ASICs exist for a proof-of-work function, both goals are +placed in jeopardy. + +It is from these premises that Ethash was designed. + +> Two directions exist for ASIC resistance; firstly make it sequential memory-hard, i.e. engineer the function such that the determination of the nonce requires a lot of memory and bandwidth such that the memory cannot be used in parallel to discover multiple nonces simultaneously. The second is to make the type of computation it would need to do general-purpose; the meaning of “specialised hardware” for a general-purpose task set is, naturally, general purpose hardware and as such commodity desktop computers are likely to be pretty close to “specialised hardware” for the task. For Ethereum 1.0 we have chosen the first path. + +5 years of experience with the Ethereum blockchain have demonstrated the success of our approach. This success cannot be taken for granted. +* 11 years of experience with PoW Blockchains have shown a centralization in hardware development, resulting in a [few companies](https://www.asicminervalue.com/) controlling the lifecycle of new hardware, limited distribution and multiple incidents of leverage & contention ((citations)) +* new ASICs for Ethash are providing higher efficiency than GPUs ((cite device specs)) +* the existing Ethereum network is now circa 40% [secured by E3 devices](https://www.overleaf.com/project/5e222c2cac8911000178b239). +* new devices are coming online with ((cite even better specs)) + +ProgPow restores Ethash' ASIC-resistance by extending Etash with a GPU-specific approach to the second path. ### ProgPoW Overview The design goal of ProgPoW is to have the algorithm’s requirements match what is available on commodity GPUs: If the algorithm were to be implemented on a custom ASIC there should be little opportunity for efficiency gains compared to a commodity GPU. @@ -32,6 +62,7 @@ The main elements of the algorithm are: * Adds a random sequence of math in the main loop. * Adds reads from a small, low-latency cache that supports random addresses. * Increases the DRAM read from 128 bytes to 256 bytes. +* ((cite adjustments from 0.9.1 -> 0.9.2 -> 0.9.3 -> 0.9.4)) The random sequence changes every `PROGPOW_PERIOD` (about 2 to 12 minutes depending on the configured value). When mining source code is generated for the random sequence and compiled on the host CPU. The GPU will execute the compiled code where what math to perform and what mix state to use are already resolved. @@ -45,9 +76,9 @@ These would result in minimal, roughly 1.1-1.2x, efficiency gains. This is much ### Rationale for PoW on Commodity Hardware With the growth of large mining pools, the control of hashing power has been delegated to the top few pools to provide a steadier economic return for small miners. While some have made the argument that large centralized pools defeats the purpose of “ASIC resistance,” it’s important to note that ASIC based coins are even more centralized for several reasons. -1. No natural distribution: There isn’t an economic purpose for ultra-specialized hardware outside of mining and thus no reason for most people to have it. -2. No reserve group: Thus, there’s no reserve pool of hardware or reserve pool of interested parties to jump in when coin price is volatile and attractive for manipulation. -3. High barrier to entry: Initial miners are those rich enough to invest capital and ecological resources on the unknown experiment a new coin may be. Thus, initial coin distribution through mining will be very limited causing centralized economic bias. +1. No natural distribution: There isn’t an economic purpose for ultra-specialized hardware outside of mining and thus no reason for most people to have it. +2. No reserve group: Thus, there’s no reserve pool of hardware or reserve pool of interested parties to jump in when coin price is volatile and attractive for manipulation. +3. High barrier to entry: Initial miners are those rich enough to invest capital and ecological resources on the unknown experiment a new coin may be. Thus, initial coin distribution through mining will be very limited causing centralized economic bias. 4. Delegated centralization vs implementation centralization: While pool centralization is delegated, hardware monoculture is not: only the limiter buyers of this hardware can participate so there isn’t even the possibility of divesting control on short notice. 5. No obvious decentralization of control even with decentralized mining: Once large custom ASIC makers get into the game, designing back-doored hardware is trivial. ASIC makers have no incentive to be transparent or fair in market participation. @@ -381,7 +412,7 @@ void progPowLoop( if (i < PROGPOW_CNT_MATH) { // Random Math - // Generate 2 unique sources + // Generate 2 unique sources int src_rnd = kiss99(prog_rnd) % (PROGPOW_REGS * (PROGPOW_REGS-1)); int src1 = src_rnd % PROGPOW_REGS; // 0 <= src1 < PROGPOW_REGS int src2 = src_rnd / PROGPOW_REGS; // 0 <= src2 < PROGPOW_REGS - 1 @@ -463,6 +494,8 @@ hash32_t progPowHash( ## Rationale +((T.B.D. Review audits)) + ProgPoW utilizes almost all parts of a commodity GPU, excluding: * The graphics pipeline (displays, geometry engines, texturing, etc); @@ -492,9 +525,78 @@ Additional test vectors can be found [in the test vectors file](../assets/eip-10 ### progpow 0.9.3 [Machine-readable test vectors](https://github.com/ethereum/EIPs/blob/ad4e73f239d53d72a21cfd8fdc89dc81eb9d2688/assets/eip-1057/test-vectors-0.9.3.json) +Additional test vectors can be found [in the test vectors file](../assets/eip-1057/test-vectors.md#progpowhash). +### progpow 0.9.4 +[Machine-readable test vectors](https://github.com/ethereum/EIPs/blob/ad4e73f239d53d72a21cfd8fdc89dc81eb9d2688/assets/eip-1057/test-vectors-0.9.4.json) ((T.B.D.)) + ## Implementation -The reference ProgPoW mining implementation located at [ProgPOW](https://github.com/ifdefelse/ProgPOW) is a derivative of ethminer so retains the GPL license. +We **Do Not** recommend that this Proposal be deployed at this time. Rather it is being offered in the spirit of [Ben DiFrancesco's compromise](https://ethereum-magicians.org/t/a-progpow-compromise-pre-proposal/4057) which for our purposes we state simply as, +* This Proposal **is not** being proposed for deployment in any planned hardfork. +* This Proposal should be fully implemented and tested across major clients. +* Clients implementing this Proposal should be deployed and maintained on a testnet. + +This leaves open the possibility and threat of future deployment. Some of the authors are engaged in work to [track what devices are mining our network](https://www.overleaf.com/project/5e222c2cac8911000178b239). These and other efforts can provide information relevant to possible deployment. + +### Clients + +| | Languages | 0.9.3 | 0.9.4 +--- | --- | --- | --- +Aleth | C++ | | +Besu | Java | Ready | +EthereumJ | Java | Ready | Developing +EthereumJS | Javascript | Ready | Developing +Etherwall | C++ | | +Geth | Go | Ready | Developing +_IfThenElse_ | C++ | Ready | Ready +Mana | Elixer | | +Nethermind | C# | Ready | +OpenEtheum | Rust | Ready | +Trinity | Python | Ready | Developing + +### Exchanges + +| | Support | 0.9.4 | 0.9.4 +--- | --- | --- | --- +Biki | Yes | Ready | +Bilaxi | Yes | Ready | +Binance | Yes | Ready | +BitMart | Yes | Ready | +BitZ | Yes | Ready | +Coinbase | Yes | Ready | +DCcoin | Yes | Ready | +Digfinex | Yes | Ready | +Etherflyer | Yes | Ready | +Flatbtc | Yes | Ready | +Folgory | Yes | Ready | +HitBTC | Yes | Ready | +Hotbit | Yes | Ready | +Lbank | Yes | Ready | +MXC | Yes | Ready | +Nobi | Yes | Ready | + +### Pools + +| | Support | 0.9.4 | 0.9.4 +--- | --- | --- | --- +2Miners | Yes | Ready | +antpool | Yes | Ready | +beepool | Yes | Ready | +Ethermine | Yes | Ready | +F2Pool | Yes | Ready | +firepool | Yes | Ready | +gpumine | Yes | Ready | +hiveon | Yes | Ready | +huobipool | Yes | Ready | +matppool | Yes | Ready | +miningpoolhub | Yes | Ready | +Noanopool | Yes | Ready | +pool.btc.com | Yes | Ready | +poolin | Yes | Ready | +Sparkpool | Yes | Ready | +Spiderpool | Yes | Ready | +xnpopol | Yes | Ready | + ## License and Copyright The ProgPoW algorithm and this specification are a new work. Copyright and related rights are waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-1077.md b/EIPS/eip-1077.md index 17eaaf144b784..a420703a57759 100644 --- a/EIPS/eip-1077.md +++ b/EIPS/eip-1077.md @@ -191,7 +191,7 @@ TBD One initial implementation of such a contract can be found at [Status.im account-contracts repository](https://github.com/status-im/account-contracts/blob/develop/contracts/account/AccountGasAbstract.sol) -Other version is implemented as Gnosis Safe variant in: http://github.com/status-im/safe-contracts +Other version is implemented as Gnosis Safe variant in: https://github.com/status-im/safe-contracts ### Similar implementations diff --git a/EIPS/eip-1102.md b/EIPS/eip-1102.md index abaace29209d3..07a8e08abc8e0 100644 --- a/EIPS/eip-1102.md +++ b/EIPS/eip-1102.md @@ -1,7 +1,7 @@ --- eip: 1102 title: Opt-in account exposure -author: Paul Bouchon +author: Paul Bouchon , Erik Marks discussions-to: https://ethereum-magicians.org/t/eip-1102-opt-in-provider-access/414 status: Draft type: Standards Track diff --git a/EIPS/eip-1123.md b/EIPS/eip-1123.md index 57d5106d21ff4..2c0eaa6be370a 100644 --- a/EIPS/eip-1123.md +++ b/EIPS/eip-1123.md @@ -1840,7 +1840,7 @@ widespread implementation in commonly-used development tools. The following tools are known to have begun or are nearing completion of a supporting implementation. -- [Truffle](http://trufflesuite.com/) +- [Truffle](https://trufflesuite.com/) - [Populus](https://populus.readthedocs.io/en/latest/) diff --git a/EIPS/eip-1193.md b/EIPS/eip-1193.md index 6930c93102bad..628e2c9e94523 100644 --- a/EIPS/eip-1193.md +++ b/EIPS/eip-1193.md @@ -1,376 +1,499 @@ --- eip: 1193 title: Ethereum Provider JavaScript API -author: Fabian Vogelsteller (@frozeman), Ryan Ghods (@ryanio), Victor Maia (@MaiaVictor), Marc Garreau (@marcgarreau) +author: Fabian Vogelsteller (@frozeman), Ryan Ghods (@ryanio), Victor Maia (@MaiaVictor), Marc Garreau (@marcgarreau), Erik Marks (@rekmarks) discussions-to: https://github.com/ethereum/EIPs/issues/2319 -status: Draft +status: Last Call +review-period-end: 2020-06-04 type: Standards Track category: Interface created: 2018-06-30 -requires: 155, 695, 1102, 1474 +requires: 155, 695 --- ## Summary -This EIP formalizes an Ethereum Provider JavaScript API for consistency across clients and applications. The provider is designed to be minimal and intended to be available on `window.ethereum` for cross environment compatibility. The events are provided as a convenience to enable reactive dapp UIs. +This EIP formalizes a JavaScript Ethereum Provider API for consistency across clients and applications. + +The Provider's interface is designed to be minimal, preferring that features are introduced in the API layer (see e.g. [`eth_requestAccounts`](https://eips.ethereum.org/EIPS/eip-1102)), and agnostic of transport and RPC protocols. + +Historically, Providers have been made available as `window.ethereum` in web browsers, but this convention is not part of the specification. + +The events `connect`, `disconnect`, `chainChanged`, and `accountsChanged` are provided as a convenience to help enable reactive dapp UIs. ## API -### Send +### request + +Makes an Ethereum RPC method call. -Ethereum JSON-RPC API methods can be sent and received: +```typescript +interface RequestArguments { + method: string; + params?: unknown; + [key: string]: unknown; +} -```js -ethereum.send(method: String, params?: Array): Promise; +Provider.request(args: RequestArguments): Promise; ``` -Promise resolves with `result` or rejects with `Error`. +The returned Promise resolves with the method's result or rejects with a [`ProviderRpcError`](#errors). For example: + +```javascript +Provider.request({ method: 'eth_accounts' }) + .then((accounts) => console.log(accounts)) + .catch((error) => console.error(error)); +``` -See [available JSON-RPC methods](https://github.com/ethereumproject/go-ethereum/wiki/JSON-RPC#json-rpc-methods). +Consult each Ethereum RPC method's documentation for its `params` and return type. +You can find a list of common methods [here](https://eips.ethereum.org/EIPS/eip-1474). -### Events +#### RPC Protocols -Events are emitted using [EventEmitter](https://nodejs.org/api/events.html). +Multiple RPC protocols may be available. For examples, see: -#### notification +- [EIP 1474](https://eips.ethereum.org/EIPS/eip-1474), the Ethereum JSON-RPC API +- [EIP 1767](https://eips.ethereum.org/EIPS/eip-1767), the Ethereum GraphQL schema -All subscriptions from the node emit on notification. Attach listeners with: +### sendAsync (DEPRECATED) -```js -ethereum.on('notification', listener: (result: any) => void): this; +This method is deprecated in favor of [`request`](#request). + +`sendAsync` is like `request`, but with JSON-RPC objects and a callback. + +```typescript +Provider.sendAsync(request: Object, callback: Function): void; ``` -To create a subscription, call `ethereum.send('eth_subscribe', [])` or `ethereum.send('shh_subscribe', [])`. +The interfaces of request and response objects are not specified here. +Historically, they have followed the [Ethereum JSON-RPC specification](https://eips.ethereum.org/EIPS/eip-1474). + +### send (DEPRECATED) + +This method is deprecated in favor of [`request`](#request). -See the [eth subscription methods](https://github.com/ethereum/go-ethereum/wiki/RPC-PUB-SUB#supported-subscriptions) and [shh subscription methods](https://github.com/ethereum/go-ethereum/wiki/Whisper-v6-RPC-API#shh_subscribe). +```typescript +Provider.send(...args: Array): unknown; +``` + +### Events + +Events follow the [Node.js `EventEmitter`](https://nodejs.org/api/events.html) API. #### connect -The provider emits `connect` on connect to a network. +The Provider emits `connect` when it: -```js -ethereum.on('connect', listener: () => void): this; -``` +- first connects to a chain after being initialized. +- first connects to a chain, after the `disconnect` event was emitted. -You can detect which chain by sending `eth_chainId`: +```typescript +interface ProviderConnectInfo { + chainId: string; + [key: string]: unknown; +} -```js -const chainId = await ethereum.send('eth_chainId'); -> 1 +Provider.on('connect', listener: (connectInfo: ProviderConnectInfo) => void): Provider; ``` -#### close +The event emits an object with a hexadecimal string `chainId` per the `eth_chainId` Ethereum RPC method, and other properties as determined by the Provider. + +#### disconnect -The provider emits `close` on disconnect from a network. +The Provider emits `disconnect` when it becomes disconnected from all chains. -```js -ethereum.on('close', listener: (code: Number, reason: String) => void): this; +```typescript +Provider.on('disconnect', listener: (error: ProviderRpcError) => void): Provider; ``` -The event emits with `code` and `reason`. The code follows the table of [`CloseEvent` status codes](https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent#Status_codes). +This event emits a [`ProviderRpcError`](#errors). The error `code` follows the table of [`CloseEvent` status codes](https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent#Status_codes). + +#### close (DEPRECATED) + +This event is deprecated in favor of [`disconnect`](#disconnect). #### chainChanged -The provider emits `chainChanged` on connect to a new chain. +The Provider emits `chainChanged` when connecting to a new chain. -```js -ethereum.on('chainChanged', listener: (chainId: Integer) => void): this; +```typescript +Provider.on('chainChanged', listener: (chainId: string) => void): Provider; ``` -The event emits with integer `chainId`, the new chain returned from `eth_chainId`. +The event emits a hexadecimal string `chainId` per the `eth_chainId` Ethereum RPC method. + +#### networkChanged (DEPRECATED) -The event `networkChanged` is deprecated in favor of `chainChanged`. For more info, see [EIP 155: Simple replay attack protection](https://eips.ethereum.org/EIPS/eip-155) and [EIP 695: Create eth_chainId method for JSON-RPC](https://eips.ethereum.org/EIPS/eip-695). +The event `networkChanged` is deprecated in favor of [`chainChanged`](#chainchanged). + +For details, see [EIP 155: Simple replay attack protection](https://eips.ethereum.org/EIPS/eip-155) and [EIP 695: Create eth_chainId method for JSON-RPC](https://eips.ethereum.org/EIPS/eip-695). #### accountsChanged -The provider emits `accountsChanged` if the accounts returned from the provider (`eth_accounts`) changes. +The Provider emits `accountsChanged` if the accounts returned from the Provider (`eth_accounts`) change. + +```typescript +Provider.on('accountsChanged', listener: (accounts: Array) => void): Provider; +``` + +The event emits with `accounts`, an array of account addresses, per the `eth_accounts` Ethereum RPC method. + +#### message + +The Provider emits `message` to communicate arbitrary messages to the consumer. +Messages may include JSON-RPC notifications, GraphQL subscriptions, and/or any other event as defined by the Provider. + +```typescript +interface ProviderMessage { + type: string; + data: unknown; +} -```js -ethereum.on('accountsChanged', listener: (accounts: Array) => void): this; +Provider.on('message', listener: (message: ProviderMessage) => void): Provider; ``` -The event emits with `accounts`, an array of the accounts' addresses. +##### Subscriptions + +Some clients like [Geth](https://geth.ethereum.org/docs/rpc/pubsub) and [Parity](https://wiki.parity.io/JSONRPC-eth_pubsub-module) support Publish-Subscribe (_Pub-Sub_) using JSON-RPC notifications. This lets you subscribe and wait for events instead of polling for them. +See the [`eth_` subscription methods](https://geth.ethereum.org/docs/rpc/pubsub) and [`shh_` subscription methods](https://github.com/ethereum/go-ethereum/wiki/Whisper-v6-RPC-API#shh_subscribe) for details. + +For e.g. `eth_subscribe` subscription updates, `ProviderMessage.type` will equal the string `'eth_subscription'`. + +#### notification (DEPRECATED) + +This event is deprecated in favor of [`message`](#message). + +Historically, this event has returned e.g. `eth_subscribe` subscription updates of the form `{ subscription: string, result: unknown }`. + +### Errors + +```typescript +interface ProviderRpcError extends Error { + message: string; + code: number; + data?: unknown; +} +``` ## Examples -```js -const ethereum = window.ethereum; +> These examples assume a web browser environment. -// A) Set provider in web3.js -var web3 = new Web3(ethereum); -// web3.eth.getBlock('latest', true).then(...) +```javascript +// The Provider will usually be available as window.ethereum on page load. +// This is only a convention, not a standard, and may not be the case in practice. +// Please consult the Provider implementation's documentation. +const ethereum = window.ethereum; +// Example 1: Log chainId +ethereum + .request({ method: 'eth_chainId' }) + .then((chainId) => { + console.log(`hexadecimal string: ${chainId}`); + console.log(`decimal number: ${parseInt(chainId, 16)}`); + }) + .catch((error) => { + console.error(`Error fetching chainId: ${error.code}: ${error.message}`); + }); -// B) Use provider object directly -// Example 1: Log last block +// Example 2: Log last block ethereum - .send('eth_getBlockByNumber', ['latest', 'true']) - .then(block => { + .request({ + method: 'eth_getBlockByNumber', + params: ['latest', 'true'], + }) + .then((block) => { console.log(`Block ${block.number}:`, block); }) - .catch(error => { + .catch((error) => { console.error( `Error fetching last block: ${error.message}. Code: ${error.code}. Data: ${error.data}` ); }); -// Example 2: Log available accounts +// Example 3: Log available accounts ethereum - .send('eth_accounts') - .then(accounts => { + .request({ method: 'eth_accounts' }) + .then((accounts) => { console.log(`Accounts:\n${accounts.join('\n')}`); }) - .catch(error => { + .catch((error) => { console.error( `Error fetching accounts: ${error.message}. - Code: ${error.code}. Data: ${error.data}` + Code: ${error.code}. Data: ${error.data}` ); }); - -// Example 3: Log new blocks -let subId; +// Example 4: Log new blocks ethereum - .send('eth_subscribe', ['newHeads']) - .then(subscriptionId => { - subId = subscriptionId; - ethereum.on('notification', result => { - if (result.subscription === subscriptionId) { - if (result.result instanceof Error) { - const error = result.result; - console.error( - `Error from newHeads subscription: ${error.message}. - Code: ${error.code}. Data: ${error.data}` - ); - } else { - const block = result.result; - console.log(`New block ${block.number}:`, block); + .request({ + method: 'eth_subscribe', + params: ['newHeads'], + }) + .then((subscriptionId) => { + ethereum.on('message', (message) => { + if (message.type === 'eth_subscription') { + const { data } = message; + if (data.subscription === subscriptionId) { + if (typeof data.result === 'string' && data.result) { + const block = data.result; + console.log(`New block ${block.number}:`, block); + } else { + console.error(`Something went wrong: ${data.result}`); + } } } }); }) - .catch(error => { + .catch((error) => { console.error( `Error making newHeads subscription: ${error.message}. Code: ${error.code}. Data: ${error.data}` ); }); - -// Example 4: Log when accounts change -const logAccounts = accounts => { +// 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 5: Log if connection ends -ethereum.on('close', (code, reason) => { - console.log(`Ethereum provider connection closed: ${reason}. Code: ${code}`); +// Example 6: Log if connection ends +ethereum.on('disconnect', (code, reason) => { + console.log(`Ethereum Provider connection closed: ${reason}. Code: ${code}`); }); ``` ## Specification -### Errors +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC-2119](https://www.ietf.org/rfc/rfc2119.txt). -If the Ethereum Provider request returns an error property then the Promise **MUST** reject with an Error object containing the `error.message` as the Error message, `error.code` as a code property on the error and `error.data` as a data property on the error. +> Comments like this are non-normative. -If an error occurs during processing, such as an HTTP error or internal parsing error, then the Promise **MUST** reject with an `Error` object. +### Definitions -If the request requires an account that is not yet authenticated, the Promise **MUST** reject with Error code 4100. +_This section is non-normative._ -### Events +- Provider + - A JavaScript object made available to a dapp, that provides access to Ethereum by means of a Client. +- Client + - An endpoint accessed by a Provider, that receives Remote Procedure Call (RPC) requests and returns their results. +- Remote Procedure Call (RPC) + - A Remote Procedure Call (RPC), is any request submitted to a Provider for some procedure that is to be processed by a Provider or its Client. -The provider **SHOULD** extend from `EventEmitter` to provide dapps flexibility in listening to events. In place of full `EventEmitter` functionality, the provider **MAY** provide as many methods as it can reasonably provide, but **MUST** provide at least `on`, `emit`, and `removeListener`. +### Availability -#### notification +_This section is non-normative._ -All subscriptions received from the node **MUST** emit the `subscription` property with the subscription ID and a `results` property. +How the Provider is made available to consumers is beyond the scope of this specification. +At the time of writing, there exists no specification for Provider availability, merely a convention. +This convention is described here for the benefit of dapp developers and Provider implementers. -#### connect +Historically, Providers have been injected into web pages as `window.ethereum` (more generally, `globalThis.ethereum`), such that they are available on page load. -If the network connects, the Ethereum Provider **MUST** emit an event named `connect`. +In practice, this convention does not handle some situations, including: -#### close +- Multiple Providers being injected into the same page, e.g. when the user has multiple wallets installed +- Asynchronously injected Providers, whether by choice or due to platform limitations -If the network connection closes, the Ethereum Provider **MUST** emit an event named `close` with args `code: Number, reason: String` following the [status codes for `CloseEvent`](https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent#Status_codes). +Provider implementers are encouraged to work with each other and with dapp developers to solve these problems until standards emerge. -#### chainChanged +### Connectivity -If the chain the provider is connected to changes, the provider **MUST** emit an event named `chainChanged` with args `chainId: Integer` containing the ID of the new chain (using the Ethereum JSON-RPC call `eth_chainId`). +The Provider is said to be "connected" when it can service RPC requests to at least one chain. -#### accountsChanged +The Provider is said to be "disconnected" when it cannot service RPC requests to any chain at all. -If the accounts connected to the Ethereum Provider change at any time, the Ethereum Provider **MUST** send an event with the name `accountsChanged` with args `accounts: Array` containing the accounts' addresses. +> To service an RPC request, the Provider must successfully submit the request to the remote location, and receive a response. +> In other words, if the Provider is unable to communicate with its Client, for example due to network issues, the Provider is disconnected. -### Error object and codes +### API -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. +The Provider **MUST** expose the API defined in this section. All API entities **MUST** adhere to the types and interfaces defined in this section. -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: +The Provider **MAY** expose methods and properties not specified in this document. -| Status code | Name | Description | -| ----------- | ---------------------------- | ------------------------------------------------------------------------ | -| 4001 | User Rejected Request | The user rejected the request. | -| 4100 | Unauthorized | The requested method and/or account has not been authorized by the user. | -| 4200 | Unsupported Method | The requested method is not supported by the given Ethereum Provider. | +#### request -## Sample Class Implementation +> The `request` method is intended as a transport- and protocol-agnostic wrapper function for Remote Procedure Calls (RPCs). -```js -class EthereumProvider extends EventEmitter { - constructor() { - // Call super for `this` to be defined - super(); +```typescript +interface RequestArguments { + method: string; + params?: unknown; + [key: string]: unknown; +} - // Init storage - this._nextJsonRpcId = 0; - this._promises = {}; +Provider.request(args: RequestArguments): Promise; +``` - // Fire the connect - this._connect(); +The `request` method **MUST** send a properly formatted request to the Provider's Ethereum client. +Requests **MUST** be handled such that, for a given set of arguments, the returned Promise either resolves with a value per the RPC method's specification, or rejects with an error. - // Listen for jsonrpc responses - window.addEventListener('message', this._handleJsonRpcMessage.bind(this)); - } +The `args` object **MAY** include properties not mentioned in this specification. - /* Methods */ +If resolved, the Promise **MUST NOT** resolve with any RPC protocol-specific response objects, unless the RPC method's return type is so defined by its specification. - send(method, params = []) { - if (!method || typeof method !== 'string') { - return new Error('Method is not a valid string.'); - } +If resolved, the Promise **MUST** resolve with a result per the RPC method's specification. - if (!(params instanceof Array)) { - return new Error('Params is not a valid array.'); - } +If the returned Promise rejects, it **MUST** reject with a `ProviderRpcError` as specified in the [RPC Errors](#rpc-errors) section below. - const id = this._nextJsonRpcId++; - const jsonrpc = '2.0'; - const payload = { jsonrpc, id, method, params }; +The returned Promise **MUST** reject if any of the following conditions are met: - const promise = new Promise((resolve, reject) => { - this._promises[payload.id] = { resolve, reject }; - }); +- The client returns an error for the RPC request. + - If the error returned from the client is compatible with the `ProviderRpcError` interface, the Promise **MAY** reject with that error directly. +- The Provider encounters an error or fails to process the request for any reason. - // Send jsonrpc request to Mist - window.postMessage( - { type: 'mistAPI_ethereum_provider_write', message: payload }, - targetOrigin - ); +> If the Provider implements any kind of authorization logic, the authors recommend rejecting with a `4100` error in case of authorization failures. - return promise; - } - - /* Internal methods */ - - _handleJsonRpcMessage(event) { - // Return if no data to parse - if (!event || !event.data) { - return; - } - - let data; - try { - data = JSON.parse(event.data); - } catch (error) { - // Return if we can't parse a valid object - return; - } - - // Return if not a jsonrpc response - if (!data || !data.message || !data.message.jsonrpc) { - return; - } - - const message = data.message; - const { id, method, error, result } = message; - - if (typeof id !== 'undefined') { - const promise = this._promises[id]; - if (promise) { - // Handle pending promise - if (data.type === 'error') { - promise.reject(message); - } else if (message.error) { - promise.reject(error); - } else { - promise.resolve(result); - } - delete this._promises[id]; - } - } else { - if (method && method.indexOf('_subscription') > -1) { - // Emit subscription notification - this._emitNotification(message.params); - } - } - } +The returned Promise **SHOULD** reject if any of the following conditions are met: - /* Connection handling */ +- The Provider is disconnected. + - If rejecting for this reason, the Promise rejection error `code` **MUST** be `4900`. +- The RPC request is directed at a specific chain, and the Provider is not connected to that chain, but is connected to at least one other chain. + - If rejecting for this reason, the Promise rejection error `code` **MUST** be `4901`. - _connect() { - // Send to Mist - window.postMessage( - { type: 'mistAPI_ethereum_provider_connect' }, - targetOrigin - ); +See the section [Connectivity](#connectivity) for the definitions of "connected" and "disconnected". + +### Supported RPC Methods + +A "supported RPC method" is any RPC method that may be called via the Provider. + +All supported RPC methods **MUST** be identified by unique strings. + +Providers **MAY** support whatever RPC methods required to fulfill their purpose, standardized or otherwise. + +If a Provider supports a method defined in a finalized EIP, the Provider's implementation of this method **MUST** adhere to the method's specification. + +If an RPC method defined in a finalized EIP is not supported, it **SHOULD** be rejected with a `4200` error per the [Provider Errors](#provider-errors) section below, or an appropriate error per the RPC method's specification. + +#### RPC Errors + +```typescript +interface ProviderRpcError extends Error { + message: string; + code: number; + data?: unknown; +} +``` + +- `message` + - **MUST** be a human-readable string + - **SHOULD** adhere to the specifications in the [Error Standards](#error-standards) section below +- `code` + - **MUST** be an integer number + - **SHOULD** adhere to the specifications in the [Error Standards](#error-standards) section below +- `data` + - **SHOULD** contain any other useful information about the error + +##### Error Standards + +`ProviderRpcError` codes and messages **SHOULD** follow these conventions, in order of priority: + +1. The errors in the [Provider Errors](#provider-errors) section below + +2. Any errors mandated by the erroring RPC method's specification + +3. The [`CloseEvent` status codes](https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent#Status_codes) + +#### Provider Errors + +| Status code | Name | Description | +| ----------- | --------------------- | ------------------------------------------------------------------------ | +| 4001 | User Rejected Request | The user rejected the request. | +| 4100 | Unauthorized | The requested method and/or account has not been authorized by the user. | +| 4200 | Unsupported Method | The Provider does not support the requested method. | +| 4900 | Disconnected | The Provider is disconnected from all chains. | +| 4901 | Chain Disconnected | The Provider is not connected to the requested chain. | + +> `4900` is intended to indicate that the Provider is disconnected from all chains, while `4901` is intended to indicate that the Provider is disconnected from a specific chain only. +> In other words, `4901` implies that the Provider is connected to other chains, just not the requested one. + +### Events + +The Provider **SHOULD** extend the [Node.js `EventEmitter`](https://nodejs.org/api/events.html) to provide dapps flexibility in listening to events. In place of full `EventEmitter` functionality, the Provider **MAY** provide as many methods as it can reasonably provide, but **MUST** provide at least `on`, `emit`, and `removeListener`. + +#### message + +The Provider **MAY** emit the event named `message`, for any reason. - // Reconnect on close - this.once('close', this._connect.bind(this)); - } - - /* Events */ - - _emitNotification(result) { - this.emit('notification', result); - } - - _emitConnect() { - this.emit('connect'); - } - - _emitClose(code, reason) { - this.emit('close', code, reason); - } - - _emitChainChanged(chainId) { - this.emit('chainChanged', chainId); - } - - _emitAccountsChanged(accounts) { - this.emit('accountsChanged', accounts); - } - - /* - Provide `sendAsync` to be compatible as an older web3.js provider. - */ - - sendAsync(payload, callback) { - return this.send(payload.method, payload.params) - .then(result => { - const response = payload; - response.result = result; - callback(null, response); - }) - .catch(error => { - callback(error, null); - // eslint-disable-next-line no-console - console.error( - `Error from EthereumProvider sendAsync ${payload}: ${error}` - ); - }); - } +If the Provider supports Ethereum RPC subscriptions, e.g. [`eth_subscribe`](https://geth.ethereum.org/docs/rpc/pubsub), the Provider **MUST** emit the `message` event when it receives a subscription notification. + +When emitted, the `message` event **MUST** be emitted with an object argument of the following form: + +```typescript +interface ProviderMessage { + type: string; + data: unknown; +} +``` + +##### Converting a Subscription Message to a ProviderMessage + +If the Provider receives a subscription message from e.g. an `eth_subscribe` subscription, the Provider **MUST** emit a `message` event with a `ProviderMessage` object of the following form: + +```typescript +interface EthSubscription extends ProviderMessage { + type: 'eth_subscription'; + data: { + subscription: string; + result: unknown; + }; } ``` +#### connect + +See the section [Connectivity](#connectivity) for the definition of "connected". + +If the Provider becomes connected, the Provider **MUST** emit the event named `connect`. + +This includes when: + +- The Provider first connects to a chain after initialization. +- The Provider connects to a chain after the `disconnect` event was emitted. + +This event **MUST** be emitted with an object of the following form: + +```typescript +interface ProviderConnectInfo { + chainId: string; + [key: string]: unknown; +} +``` + +`chainId` **MUST** specify the integer ID of the connected chain as a hexadecimal string, per the [`eth_chainId`](https://eips.ethereum.org/EIPS/eip-695) Ethereum RPC method. + +The `ProviderConnectInfo` object **MAY** contain any other `string` properties with values of any type. + +#### disconnect + +See the section [Connectivity](#connectivity) for the definition of "disconnected". + +If the Provider becomes disconnected from all chains, the Provider **MUST** emit the event named `disconnect` with value `error: ProviderRpcError`, per the interfaced defined in the [RPC Errors](#rpc-errors) section. The value of the error's `code` property **MUST** follow the [status codes for `CloseEvent`](https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent#Status_codes). + +#### chainChanged + +If the chain the Provider is connected to changes, the Provider **MUST** emit the event named `chainChanged` with value `chainId: string`, specifying the integer ID of the new chain as a hexadecimal string, per the [`eth_chainId`](https://eips.ethereum.org/EIPS/eip-695) Ethereum RPC method. + +#### accountsChanged + +If the accounts available to the Provider change, the Provider **MUST** emit the event named `accountsChanged` with value `accounts: Array`, containing the account addresses per the `eth_accounts` Ethereum RPC method. + +The "accounts available to the Provider" change when the return value of `eth_accounts` changes. + ## References -* [Initial discussion in `ethereum/interfaces`](https://github.com/ethereum/interfaces/issues/16) -* [Ethereum Magicians thread](https://ethereum-magicians.org/t/eip-1193-ethereum-provider-javascript-api/640) +- [Initial discussion in `ethereum/interfaces`](https://github.com/ethereum/interfaces/issues/16) +- [Ethereum Magicians thread](https://ethereum-magicians.org/t/eip-1193-ethereum-provider-javascript-api/640) +- [Continuing EIP-1193 discussion](https://github.com/ethereum/EIPs/issues/2319) +- Related EIPs + - [EIP 1102](https://eips.ethereum.org/EIPS/eip-1102) + - [EIP 1474](https://eips.ethereum.org/EIPS/eip-1474) + - [EIP 1767](https://eips.ethereum.org/EIPS/eip-1767) ## Copyright diff --git a/EIPS/eip-1363.md b/EIPS/eip-1363.md new file mode 100644 index 0000000000000..d75ab6d3f0e6e --- /dev/null +++ b/EIPS/eip-1363.md @@ -0,0 +1,209 @@ +--- +eip: 1363 +title: ERC-1363 Payable Token +author: Vittorio Minacori (@vittominacori) +discussions-to: https://github.com/ethereum/eips/issues/1363 +status: Draft +type: Standards Track +category: ERC +created: 2020-01-31 +requires: 20, 165 +--- + +## Simple Summary +Description of a **Payable Token** compatible with the ERC-20 definition. +Also description of a Token **Receiver** and/or **Spender** that accepts Payable Token payments. + +## Abstract +The following describes standard functions a token contract and contracts working with specified token can implement to make a Token Payable. + +## Motivation +This proposal allows to implement an ERC-20 compatible token that can be used for payments. + +It defines `transferAndCall` and `transferFromAndCall` functions that will call an `onTransferReceived` on a `ERC1363Receiver` contract. +It defines `approveAndCall` functions that will call an `onApprovalReceived` on a `ERC1363Spender` contract. + +This proposal is inspired by the ERC-721 `onERC721Received` and `ERC721TokenReceiver` behaviours. + +## Specification +Every Payable Token compliant contract MUST implement the ERC-1363 interface other than ERC-20 and ERC-165 interfaces. + +```solidity +pragma solidity ^0.6.0; + + +interface ERC1363 /* is ERC20, ERC165 */ { + /* + * Note: the ERC-165 identifier for this interface is 0x4bbee2df. + * 0x4bbee2df === + * bytes4(keccak256('transferAndCall(address,uint256)')) ^ + * bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^ + * bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^ + * bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) + */ + + /* + * Note: the ERC-165 identifier for this interface is 0xfb9ec8ce. + * 0xfb9ec8ce === + * bytes4(keccak256('approveAndCall(address,uint256)')) ^ + * bytes4(keccak256('approveAndCall(address,uint256,bytes)')) + */ + + /** + * @notice Transfer tokens from `msg.sender` to another address and then call `onTransferReceived` on receiver + * @param to address The address which you want to transfer to + * @param value uint256 The amount of tokens to be transferred + * @return true unless throwing + */ + function transferAndCall(address to, uint256 value) external returns (bool); + + /** + * @notice Transfer tokens from `msg.sender` to another address and then call `onTransferReceived` on receiver + * @param to address The address which you want to transfer to + * @param value uint256 The amount of tokens to be transferred + * @param data bytes Additional data with no specified format, sent in call to `to` + * @return true unless throwing + */ + function transferAndCall(address to, uint256 value, bytes memory data) external returns (bool); + + /** + * @notice Transfer tokens from one address to another and then call `onTransferReceived` on receiver + * @param from address The address which you want to send tokens from + * @param to address The address which you want to transfer to + * @param value uint256 The amount of tokens to be transferred + * @return true unless throwing + */ + function transferFromAndCall(address from, address to, uint256 value) external returns (bool); + + + /** + * @notice Transfer tokens from one address to another and then call `onTransferReceived` on receiver + * @param from address The address which you want to send tokens from + * @param to address The address which you want to transfer to + * @param value uint256 The amount of tokens to be transferred + * @param data bytes Additional data with no specified format, sent in call to `to` + * @return true unless throwing + */ + function transferFromAndCall(address from, address to, uint256 value, bytes memory data) external returns (bool); + + /** + * @notice Approve the passed address to spend the specified amount of tokens on behalf of msg.sender + * and then call `onApprovalReceived` on spender. + * Beware that changing an allowance with this method brings the risk that someone may use both the old + * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this + * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: + * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 + * @param spender address The address which will spend the funds + * @param value uint256 The amount of tokens to be spent + */ + function approveAndCall(address spender, uint256 value) external returns (bool); + + /** + * @notice Approve the passed address to spend the specified amount of tokens on behalf of msg.sender + * and then call `onApprovalReceived` on spender. + * Beware that changing an allowance with this method brings the risk that someone may use both the old + * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this + * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: + * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 + * @param spender address The address which will spend the funds + * @param value uint256 The amount of tokens to be spent + * @param data bytes Additional data with no specified format, sent in call to `spender` + */ + function approveAndCall(address spender, uint256 value, bytes memory data) external returns (bool); +} + +interface ERC20 { + function totalSupply() external view returns (uint256); + function balanceOf(address account) external view returns (uint256); + function transfer(address recipient, uint256 amount) external returns (bool); + function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); + function allowance(address owner, address spender) external view returns (uint256); + function approve(address spender, uint256 amount) external returns (bool); + event Transfer(address indexed from, address indexed to, uint256 value); + event Approval(address indexed owner, address indexed spender, uint256 value); +} + +interface ERC165 { + function supportsInterface(bytes4 interfaceId) external view returns (bool); +} +``` + +A contract that wants to accept token payments via `transferAndCall` or `transferFromAndCall` MUST implement the following interface: + +```solidity +/** + * @title ERC1363Receiver interface + * @dev Interface for any contract that wants to support transferAndCall or transferFromAndCall + * from ERC1363 token contracts. + */ +interface ERC1363Receiver { + /* + * Note: the ERC-165 identifier for this interface is 0x88a7ca5c. + * 0x88a7ca5c === bytes4(keccak256("onTransferReceived(address,address,uint256,bytes)")) + */ + + /** + * @notice Handle the receipt of ERC1363 tokens + * @dev Any ERC1363 smart contract calls this function on the recipient + * after a `transfer` or a `transferFrom`. This function MAY throw to revert and reject the + * transfer. Return of other than the magic value MUST result in the + * transaction being reverted. + * Note: the token contract address is always the message sender. + * @param operator address The address which called `transferAndCall` or `transferFromAndCall` function + * @param from address The address which are token transferred from + * @param value uint256 The amount of tokens transferred + * @param data bytes Additional data with no specified format + * @return `bytes4(keccak256("onTransferReceived(address,address,uint256,bytes)"))` + * unless throwing + */ + function onTransferReceived(address operator, address from, uint256 value, bytes memory data) external returns (bytes4); +} +``` + +A contract that wants to accept token payments via `approveAndCall` MUST implement the following interface: + +```solidity +/** + * @title ERC1363Spender interface + * @dev Interface for any contract that wants to support approveAndCall + * from ERC1363 token contracts. + */ +interface ERC1363Spender { + /* + * Note: the ERC-165 identifier for this interface is 0x7b04a2d0. + * 0x7b04a2d0 === bytes4(keccak256("onApprovalReceived(address,uint256,bytes)")) + */ + + /** + * @notice Handle the approval of ERC1363 tokens + * @dev Any ERC1363 smart contract calls this function on the recipient + * after an `approve`. This function MAY throw to revert and reject the + * approval. Return of other than the magic value MUST result in the + * transaction being reverted. + * Note: the token contract address is always the message sender. + * @param owner address The address which called `approveAndCall` function + * @param value uint256 The amount of tokens to be spent + * @param data bytes Additional data with no specified format + * @return `bytes4(keccak256("onApprovalReceived(address,uint256,bytes)"))` + * unless throwing + */ + function onApprovalReceived(address owner, uint256 value, bytes memory data) external returns (bytes4); +} +``` + +## Rationale +There are many proposed uses of Ethereum smart contracts that can accept ERC-20 payments (i.e. to create a token payable crowdsale, selling services for tokens, paying invoices, making subscriptions, use them for a specific utility and many other purposes). + +This proposal wants to make token payments easier and working without the use of any other listener. It also allows to make a callback after a transfer in a single transaction. + +## Backwards Compatibility +This proposal is inspired also by ERC-223 and ERC-677 but it uses the ERC-721 approach so it doesn't override the ERC-20 `transfer` and `transferFrom` methods and defines the interfaces IDs to be implemented maintaining the ERC-20 backwards compatibility. + +## Test Cases +[https://github.com/vittominacori/erc1363-payable-token/tree/master/test](https://github.com/vittominacori/erc1363-payable-token/tree/master/test) + +## Implementation +[https://github.com/vittominacori/erc1363-payable-token/tree/master/contracts/token/ERC1363](https://github.com/vittominacori/erc1363-payable-token/tree/master/contracts/token/ERC1363) + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-1474.md b/EIPS/eip-1474.md index 4d38dc9622835..7857747062edb 100644 --- a/EIPS/eip-1474.md +++ b/EIPS/eip-1474.md @@ -1,7 +1,7 @@ --- eip: 1474 title: Remote procedure call specification -author: Paul Bouchon +author: Paul Bouchon , Erik Marks discussions-to: https://ethereum-magicians.org/t/eip-remote-procedure-call-specification/1537 status: Draft type: Standards Track diff --git a/EIPS/eip-1559.md b/EIPS/eip-1559.md index 4dec83e889355..62c9548604b4a 100644 --- a/EIPS/eip-1559.md +++ b/EIPS/eip-1559.md @@ -1,7 +1,7 @@ --- eip: 1559 title: Fee market change for ETH 1.0 chain -author: Vitalik Buterin (@vbuterin), Eric Conner (@econoar) +author: Vitalik Buterin (@vbuterin), Eric Conner (@econoar), Rick Dudley (@AFDudley), Matthew Slipper (@mslipper), Ian Norden (@i-norden) discussions-to: https://ethereum-magicians.org/t/eip-1559-fee-market-change-for-eth-1-0-chain/2783 status: Draft type: Standards Track @@ -17,11 +17,13 @@ The current "first price auction" fee model in Ethereum is inefficient and needl ## Abstract -There is a BASEFEE value in protocol, which can move up or down by a maximum of 1/8 in each block; initially, miners adjust this value to target an average gas usage of 8 million, increasing BASEFEE if usage is higher and decreasing it if usage is lower. Transaction senders specify their fees by providing two values: +There is a base fee value in protocol, which can move up or down by a maximum of 1/8 in each block. The base fee value is adjusted by the protocol to target an average gas usage of 10 million, increasing base fee if usage is higher and decreasing it if usage is lower. Transaction senders specify their fees by providing two values: -* A "premium" gasprice which gets added onto the BASEFEE gasprice, which can either be set to a fairly low value (eg. 1 gwei) to compensate miners for uncle rate risk or to a high value to compete during sudden bursts of activity. The BASEFEE gets burned, the premium is given to the miner. +* A gas premium which gets added onto the base fee to calculate the gas price. The gas premium can either be set to a fairly low value (eg. 1 gwei) to compensate miners for uncle rate risk or to a high value to compete during sudden bursts of activity. The base fee gets burned, the gas premium is given to the miner. -* A "cap" which represents the maximum total that the transaction sender would be willing to pay to get included. +* A fee cap which represents the maximum total (base fee + gas premium) that the transaction sender would be willing to pay to get their transaction included. + +The current miner-voting based gas limit is changed to a hard-coded gas limit of 16 million. Instead of miners directly adjusting the gas limit in response to changes in network demand, the protocol adjusts the base fee to apply economic pressure towards a target gas usage of 10 million. ## Motivation @@ -32,34 +34,63 @@ Ethereum currently prices transaction fees using a simple auction mechanism, whe * **Inefficiencies of first price auctions**: see https://ethresear.ch/t/first-and-second-price-auctions-and-improved-transaction-fee-markets/2410 for a detailed writeup. In short, the current approach, where transaction senders publish a transaction with a fee, miners choose the highest-paying transactions, and everyone pays what they bid, is well-known in mechanism design literature to be highly inefficient, and so complex fee estimation algorithms are required, and even these algorithms often end up not working very well, leading to frequent fee overpayment. See also https://blog.bitgo.com/the-challenges-of-bitcoin-transaction-fee-estimation-e47a64a61c72 for a Bitcoin core developer's description of the challenges involved in fee estimation in the status quo. * **Instability of blockchains with no block reward**: in the long run, blockchains where there is no issuance (including Bitcoin and Zcash) at present intend to switch to rewarding miners entirely through transaction fees. However, there are [known results](http://randomwalker.info/publications/mining_CCS.pdf) showing that this likely leads to a lot of instability, incentivizing mining "sister blocks" that steal transaction fees, opening up much stronger selfish mining attack vectors, and more. There is at present no good mitigation for this. -The proposal in this EIP is to start with a BASEFEE amount which is adjusted up and down by the protocol based on how congested the network is. To accommodate this system, the network capacity would be increased to 16 million gas, so that 50% utilization matches up with our current 8 million gas limit. Then, when the network is at >50% capacity, the BASEFEE increments up slightly and when capacity is at <50%, it decrements down slightly. Because these increments are constrained, the maximum difference in BASEFEE from block to block is predictable. This then allows wallets to auto-set the gas fees for users in a highly reliable fashion. It is expected that most users will not have to manually adjust gas fees, even in periods of high network activity. For most users, the BASEFEE will be automatically set by their wallet, along with the addition of a small fixed amount, called a ‘tip’, to compensate miners (e.g. 0.5 gwei). +The proposal in this EIP is to start with a base fee amount which is adjusted up and down by the protocol based on how congested the network is. To accommodate this system, the total network capacity would be increased to 16 million gas. When the network exceeds the target 10 million gas usage, the base fee increments up slightly and when capacity is below the target, it decrements down slightly. Because these increments are constrained, the maximum difference in base fee from block to block is predictable. This then allows wallets to auto-set the gas fees for users in a highly reliable fashion. It is expected that most users will not have to manually adjust gas fees, even in periods of high network activity. For most users post 1559 implementation the base fee will be estimated by their wallet and a small gas premium- which acts as a 'tip' to compensate miners (e.g. 0.5 gwei)- will be automatically set. Users can also manually set the transaction fee cap to bound their total costs. + +An important aspect of this upgraded fee system is that miners only get to keep the tips. The base fee is always burned (i.e. it is destroyed by the protocol). Burning this is important because it prevents miners from manipulating the fee in order to extract more fees from users. It also ensures that only ETH can ever be used to pay for transactions on Ethereum, cementing the economic value of ETH within the Ethereum platform. Additionally, this burn counterbalances Ethereum inflation without greatly diminishing miner rewards. -An important aspect of this upgraded fee system is that miners only get to keep the tips. The BASEFEE is always burned (i.e. it is destroyed by the protocol). Burning this is important because it prevents miners from manipulating the fee in order to extract more fees from users. It also ensures that only ETH can ever be used to pay for transactions on Ethereum, cementing the economic value of ETH within the Ethereum platform. +The transition to this gas price system will occur in two phases, in the first phase both legacy and EIP1559 transactions will be accepted by the protocol. Over the course of this first phase the amount of gas available for processing legacy transactions will decrease while the amount of gas available for processing EIP1559 transactions will increase, moving gas from the legacy pool into the EIP1559 pool until the legacy pool is depleted and the EIP1559 pool contains the entire gas maximum. After all of the gas has transitioned to the EIP1559 pool, the second- finalized- phase is entered and legacy transactions will no longer be accepted on the network. ## Specification **Parameters** -* `FORK_BLKNUM`: TBD +* `INITIAL_FORK_BLKNUM`: TBD * `BASEFEE_MAX_CHANGE_DENOMINATOR`: 8 -* `SLACK_COEFFICIENT`: 3 -* `TARGET_GASUSED`: 8,000,000 +* `TARGET_GAS_USED`: 10,000,000 +* `MAX_GAS_EIP1559`: 16,000,000 +* `EIP1559_DECAY_RANGE`: `MAX_GAS_EIP1559 / 20` == `800,000` +* `FINAL_FORK_BLKNUM`: `INITIAL_FORK_BLKNUM + EIP1559_DECAY_RANGE` +* `EIP1559_GAS_INCREMENT_AMOUNT`: `(MAX_GAS_EIP1559 / 2) / EIP1559_DECAY_RANGE` == `10` +* `INITIAL_BASEFEE` : 1,000,000,000 wei (1 gwei) +* `PER_TX_GASLIMIT`: 8,000,000 **Proposal** -For all blocks where `block.number >= FORK_BLKNUM`: - -* Impose a hard in-protocol gas limit of `SLACK_COEFFICIENT * TARGET_GASUSED`, used instead of the gas limit calculated using the previously existing formulas -* Replace the `GASLIMIT` field in the block header with a BASEFEE field (the same field can be used) -* Let `PARENT_BASEFEE` be the parent block's `BASEFEE` (or 1 billion wei if `block.number == FORK_BLKNUM`). A valid `BASEFEE` is one such that `abs(BASEFEE - PARENT_BASEFEE) <= max(1, PARENT_BASEFEE // BASEFEE_MAX_CHANGE_DENOMINATOR)` -* Redefine the way the `tx.gasprice` field is used: define `tx.fee_premium = tx.gasprice // 2**128` and `tx.fee_cap = tx.gasprice % 2**128` -* During transaction execution, we calculate the cost to the `tx.origin` and the gain to the `block.coinbase` as follows: - * Let `gasprice = min(BASEFEE + tx.fee_premium, tx.fee_cap)`. The `tx.origin` initially pays `gasprice * tx.gas`, and gets refunded `gasprice * (tx.gas - gasused)`. - * The `block.coinbase` gains `(gasprice - BASEFEE) * gasused`. If `gasprice < BASEFEE` (due to the `fee_cap`), this means that the `block.coinbase` _loses_ funds from this operation; in this case, check that the post-balance is non-negative and throw an exception if it is negative. -As a default strategy, miners set `BASEFEE` as follows. Let `delta = block.gas_used - TARGET_GASUSED` (possibly negative). Set `BASEFEE = PARENT_BASEFEE + PARENT_BASEFEE * delta // TARGET_GASUSED // BASEFEE_MAX_CHANGE_DENOMINATOR`, clamping this result inside of the allowable bounds if needed (with the parameter setting above clamping will not be required). +For all blocks where `block.number >= INITIAL_FORK_BLKNUM`: + +For the gas limit: + +* `MAX_GAS_EIP1559` acts as the hard in-protocol gas limit, instead of the gas limit calculated using the previously existing formulas +* The `GASLIMIT` field in the block header is the gas limit for the EIP1559 gas pool, and over the transition period this value increases until it reaches `MAX_GAS_EIP1559` at `FINAL_FORK_BLKNUM` +* The gas limit for the legacy gas pool is `MAX_GAS_EIP1559 - GASLIMIT`, as `GASLIMIT` increases towards `MAX_GAS_EIP1559` gas is moved from the legacy pool into the EIP1559 pool until all of the gas is in the EIP1559 pool +* At `block.number == INITIAL_FORK_BLKNUM`, let `GASLIMIT = (MAX_GAS_EIP1559 / 2)` so that the gas maximum is split evenly between the legacy and EIP1559 gas pools +* As `block.number` increases towards `FINAL_FORK_BLKNUM`, at every block we shift `EIP1559_GAS_INCREMENT_AMOUNT` from the legacy pool into the EIP1559 gas pool +* At `block.number >= FINAL_FORK_BLKNUM` the entire `MAX_GAS_EIP1559` is assigned to the EIP1559 gas pool and the legacy pool is empty +* We enforce a maximum gas usage on individual transactions: `PER_TX_GASLIMIT` + +For the gas price: + +* We add a new field to the block header, `BASEFEE` + * `BASEFEE` is maintained under consensus by the ethash engine +* At `block.number == INITIAL_FORK_BLKNUM` we set `BASEFEE = INITIAL_BASEFEE` +* `BASEFEE` is set as follows + * Let `delta = block.gas_used - TARGET_GASUSED` (possibly negative). + * Set `BASEFEE = PARENT_BASEFEE + PARENT_BASEFEE * delta // TARGET_GASUSED // BASEFEE_MAX_CHANGE_DENOMINATOR` + * Clamp the resulting `BASEFEE` inside of the allowable bounds if needed, where a valid `BASEFEE` is one such that `abs(BASEFEE - PARENT_BASEFEE) <= max(1, PARENT_BASEFEE // BASEFEE_MAX_CHANGE_DENOMINATOR)` +* We add two new fields to transactions: `GAS_PREMIUM` and `FEECAP` +* During the transition phase, these fields can be left `nil` and a `tx.gas_price` can be set as usual to generate a backwards compatible legacy transaction +* To produce an EIP1559 transactions, `tx.gas_price` is set to `nil` while the new `GAS_PREMIUM` and `FEECAP` fields are set whereby: + * `GAS_PREMIUM` serves as a "tip" to the miner + * `FEECAP` serves as the absolute maximum that the transaction sender is willing to pay +* During transaction execution, for EIP1559 transactions we calculate the cost to the `tx.origin` and the gain to the `block.coinbase` as follows: + * Set `GASPRICE = min(BASEFEE + tx.GasPremium, tx.fee_cap)` + * Let `GASUSED` be the gas used during the transaction execution/state transition + * The `tx.origin` initially pays `GASPRICE * tx.gas`, and gets refunded `GASPRICE * (tx.gas - GASUSED)` + * The `block.coinbase` gains `(GASPRICE - BASEFEE) * GASUSED`. + * If `GASPRICE < BASEFEE` (due to the `FEECAP`), this means that the `block.coinbase` _loses_ funds from this operation; in this case, we check that the post-balance is non-negative and throw an exception if it is negative. ## Backwards Compatibility -Transactions published before this EIP or by wallets that do not support this EIP will be interpreted by the above formulas as having a `fee_premium` of zero and a `fee_cap` of the fee that they submit. Provided that at least some miners are temporarily willing to be altruistic and accept zero-fee-premium transactions for a short period of time after the fork, this should not greatly affect usability. There is an invariant that a `gasprice` constructed "the old way" still constitutes an upper bound on the amount that a user will pay. +We split the EIP1559 upgrade into two phases with a transition period during which both legacy and EIP1559 transaction can be accepted so that compatibility with wallets and other ETH-adjacent software is maintained while their maintainers have time to upgrade to using the new transaction type. During this transition period legacy transactions are accepted and processed identically to the current implementation, with the only difference being that the amount of gas (gas limit) dedicated to processing legacy transactions is calculated as above and incrementally decreases over this period. ## Test Cases @@ -68,7 +99,32 @@ Transactions published before this EIP or by wallets that do not support this EI ## Implementation - +Go-ethereum implementation by Vulcanize Inc: https://github.com/vulcanize/go-ethereum-EIP1559 + +## Security Considerations + +The security considerations for this EIP are: +1. The consequences of raising the gas limit + * This concern was brought up [here](https://ethereum-magicians.org/t/eip-1559-fee-market-change-for-eth-1-0-chain/2783/45) + * This EIP currently proposes to raise the total gas limit from 8,000,000 to 16,000,000 +2. The consequences of the new gas pricing on total transaction order + * This concern was brought up [here](https://ethereum-magicians.org/t/eip-1559-fee-market-change-for-eth-1-0-chain/2783/45) + * This issue is avoided by maintaining a single total ordering of transactions by price and nonce, where the derived EIP1559 gas price is used like the legacy gas price +3. The effects on miner incentives + * This concern was brought up [here](https://ethereum-magicians.org/t/eip-1559-fee-market-change-for-eth-1-0-chain/2783/15) + * This concern is addressed [here](https://ethereum-magicians.org/t/eip-1559-fee-market-change-for-eth-1-0-chain/2783/16) +4. Concerns of BASEFEE manipulation + * This concern was brought up [here](https://ethereum-magicians.org/t/eip-1559-fee-market-change-for-eth-1-0-chain/2783/50) + * To avoid this, the BASEFEE is included as part of the header structure and is maintained under consensus by the ethash engine +5. Implications of BASEFEE burning on proposals to cap the total ether supply (e.g. EIP-960). + * This concern was brought up [here](https://ethereum-magicians.org/t/eip-1559-fee-market-change-for-eth-1-0-chain/2783/13) + +## Resources +* [Call notes](https://github.com/ethereum/pm/blob/master/All%20Core%20Devs%20Meetings/Meeting%2077.md) +* [Original Magicians thread](https://ethereum-magicians.org/t/eip-1559-fee-market-change-for-eth-1-0-chain/2783) +* [Ethresear.ch Post w/ Vitalik’s Paper](https://ethresear.ch/t/draft-position-paper-on-resource-pricing/2838) +* [Go-ethereum implementation](https://github.com/vulcanize/go-ethereum-EIP1559) +* [Implementation-specific Magicians thread](https://ethereum-magicians.org/t/eip-1559-go-etheruem-implementation/3918) ## Copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-1613.md b/EIPS/eip-1613.md index fdd4379b698cc..a5a45fe576a63 100644 --- a/EIPS/eip-1613.md +++ b/EIPS/eip-1613.md @@ -89,7 +89,7 @@ Glossary of terms used in the processes below: * `Sender` - an external address with a valid keypair but no ETH to pay for gas. * `Relay` - a node holding ETH in an external address, listed in RelayHub and relaying transactions from Senders to RelayHub for a fee. -![Sequence Diagram](http://bit.ly/2WZqM23) +![Sequence Diagram](https://bit.ly/2WZqM23) The process of registering/refreshing a `Relay`: diff --git a/EIPS/eip-1706.md b/EIPS/eip-1706.md index 7d8ec43c9ae32..0db0e754d587a 100644 --- a/EIPS/eip-1706.md +++ b/EIPS/eip-1706.md @@ -3,12 +3,14 @@ eip: 1706 title: Disable SSTORE with gasleft lower than call stipend author: Alex Forshtat , Yoav Weiss discussions-to: https://github.com/alex-forshtat-tbk/EIPs/issues/1 -status: Draft +status: Abandoned type: Standards Track category: Core created: 2019-01-15 requires: 1283 +superseded-by: 2200 --- +> :information_source: **[EIP2200] has superseded [EIP1706].** :information_source: diff --git a/EIPS/eip-1753.md b/EIPS/eip-1753.md index a4ea4cf71d051..ef92881b3aed6 100644 --- a/EIPS/eip-1753.md +++ b/EIPS/eip-1753.md @@ -43,7 +43,7 @@ This EIP seeks to define a standard that will allow for the granting and/or mana Returns the name of the permit - e.g. `"MyPermit"`. ``` js -function name() public view returns (string) +function name() public view returns (string); ``` #### totalSupply @@ -51,7 +51,7 @@ function name() public view returns (string) Returns the total permit supply. ``` js -function totalSupply() public view returns (uint256) +function totalSupply() public view returns (uint256); ``` #### grantAuthority @@ -59,7 +59,7 @@ function totalSupply() public view returns (uint256) Adds an ethereum address to a white list of addresses that have authority to modify a permit. ``` js -function grantAuthority(address who) +function grantAuthority(address who) public; ``` #### revokeAuthority @@ -67,7 +67,7 @@ function grantAuthority(address who) Removes an ethereum address from a white list of addresses that have authority to modify a permit. ``` js -function revokeAuthority(address who) +function revokeAuthority(address who) public; ``` #### hasAuthority @@ -75,7 +75,7 @@ function revokeAuthority(address who) Checks to see if the address has authority to grant or revoke permits. ``` js -function hasAuthority(address who) +function hasAuthority(address who) public view; ``` #### issue @@ -83,7 +83,7 @@ function hasAuthority(address who) Issues an ethereum address a permit between the specified date range. ``` js -function issue(address who, uint256 from, uint256 to) public; +function issue(address who, uint256 validFrom, uint256 validTo) public; ``` #### revoke @@ -99,7 +99,7 @@ function revoke(address who) public; Checks to see if an ethereum address has a valid permit. ``` js -function hasValid(address who) public view returns (boolean); +function hasValid(address who) external view returns (bool); ``` #### purchase @@ -107,7 +107,7 @@ function hasValid(address who) public view returns (boolean); Allows a user to self procure a licence. ``` js -function purchase(uint256 from, uint256 to) public payable; +function purchase(uint256 validFrom, uint256 validTo) external payable; ``` ## Rationale @@ -124,7 +124,7 @@ The EIP has been developed following the review of a number of licensing regulat A real world example of a Licence is a permit required to camp in a national park in Australia (e.g. Kakadu national park in the Northern Territory of Australia) under the Environment Protection and Biodiversity Conservation Regulations 2000 (Cth) (EPBC Act) and the Environment Protection and Biodiversity Conservation Regulations 2000 (the Regulations). Pursuant to the EPBC Act and the Regulations, the Director of National Parks oversees a camping permit system, which is intended to help regulate certain activities in National Parks. Permits allowing access to National Parks can be issued to legal or natural persons if the applicant has met certain conditions. -The current digital portal and application form to camp at Kakadu National Park (the Application) can be accessed at: http://www.environment.gov.au/system/files/resources/b3481ed3-164b-4e72-a9f8-91fc987d90e7/files/kakadu-camping-permit-form-19jan2015-pdf.pdf +The current digital portal and application form to camp at Kakadu National Park (the Application) can be accessed at: https://www.environment.gov.au/system/files/resources/b3481ed3-164b-4e72-a9f8-91fc987d90e7/files/kakadu-camping-permit-form-19jan2015-pdf.pdf The user must provide the following details when making an Application: @@ -170,15 +170,15 @@ interface EIP1753 { string public name; uint256 public totalSupply; - function grantAuthority(address who); - function revokeAuthority(address who); - function hasAuthority(address who) pure public returns (bool); + function grantAuthority(address who) public; + function revokeAuthority(address who) public; + function hasAuthority(address who) external view returns (bool); - function issue(address who, uint256 from, uint256 to) public; + function issue(address who, uint256 from, uint256 to) external; function revoke(address who) public; - function hasValid(address who) public view returns (boolean); - function purchase(uint256 from, uint256 to) public payable; + function hasValid(address who) external view returns (bool); + function purchase(uint256 validFrom, uint256 validTo) public payable; } pragma solidity ^0.5.3; @@ -194,8 +194,8 @@ contract EIP is EIP1753 { struct Permit { address issuer; - uint256 start; - uint256 end; + uint256 validFrom; + uint256 validTo; } constructor() public { @@ -210,7 +210,7 @@ contract EIP is EIP1753 { delete _authorities[who]; } - function hasAuthority(address who) public view returns (bool) { + function hasAuthority(address who) external view returns (bool) { return _authorities[who] == true; } @@ -223,11 +223,11 @@ contract EIP is EIP1753 { delete _holders[who]; } - function hasValid(address who) public view returns (bool) { + function hasValid(address who) external view returns (bool) { return _holders[who].start > now && _holders[who].end < now; } - function purchase(uint256 from, uint256 to) public payable { + function purchase(uint256 validFrom, uint256 validTo) external payable { require(msg.value == 1 ether, "Incorrect fee"); issue(msg.sender, from, to); } @@ -238,7 +238,7 @@ contract EIP is EIP1753 { } modifier onlyAuthority() { - require(hasAuthority(msg.sender) == true, "Only an authority can perform this function"); + require(hasAuthority(msg.sender), "Only an authority can perform this function"); _; } } diff --git a/EIPS/eip-1761.md b/EIPS/eip-1761.md index d5bec18d12053..d7145da0efe4a 100644 --- a/EIPS/eip-1761.md +++ b/EIPS/eip-1761.md @@ -162,7 +162,7 @@ The Scope Metadata JSON Schema was added in order to support human-readable scop **Standards** - [ERC-1155 Multi Token Standard](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1155.md) - [ERC-165 Standard Interface Detection](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md) -- [JSON Schema](http://json-schema.org/) +- [JSON Schema](https://json-schema.org/) **Implementations** - [Enjin Coin](https://enjincoin.io) ([github](https://github.com/enjin)) diff --git a/EIPS/eip-1829.md b/EIPS/eip-1829.md index 20d6a5c8e0b5d..58bf0b763553c 100644 --- a/EIPS/eip-1829.md +++ b/EIPS/eip-1829.md @@ -104,7 +104,7 @@ Conversion from affine coordinates to compressed coordinates is trivial: `y' = 0 * Special point addition/doubling [formulas][formulas] for `α = -3`, `α = -1`, `α = 0`, `β = 0`. -[formulas]: http://www.hyperelliptic.org/EFD/g1p/auto-shortw.html +[formulas]: https://www.hyperelliptic.org/EFD/g1p/auto-shortw.html TODO: The special cases for `α` and `β` might be worth implementing and offered a gas discount. diff --git a/EIPS/eip-1930.md b/EIPS/eip-1930.md index 267b7296f8ed7..3e611128572a0 100644 --- a/EIPS/eip-1930.md +++ b/EIPS/eip-1930.md @@ -19,7 +19,7 @@ The current CALL, DELEGATE_CALL, STATIC_CALL opcode do not enforce the gas being This is for example the case for meta-transaction where the contract needs to ensure the call is executed exactly as the signing user intended. -But this is also the case for common use cases, like checking "on-chain" if a smart contract support a specific interface (via [EIP-165](http://eips.ethereum.org/EIPS/eip-165) for example). +But this is also the case for common use cases, like checking "on-chain" if a smart contract support a specific interface (via [EIP-165](https://eips.ethereum.org/EIPS/eip-165) for example). The solution presented here is to add new call semantic that enforce the amount of gas specified : the call either proceed with the exact amount of gas or do not get executed and the current call revert. @@ -58,7 +58,7 @@ Its main benefit though is that it does not require extra opcodes. #### strict gas semantic -To be precise, regarding the strict gas semantic, based on [EIP-150](http://eips.ethereum.org/EIPS/eip-150), the current call must revert unless G >= I x 64/63 where G is gas left at the point of call (after deducing the cost of the call itself) and I is the gas specified. +To be precise, regarding the strict gas semantic, based on [EIP-150](https://eips.ethereum.org/EIPS/eip-150), the current call must revert unless G >= I x 64/63 where G is gas left at the point of call (after deducing the cost of the call itself) and I is the gas specified. So instead of ``` @@ -82,7 +82,7 @@ if !callCost.IsUint64() || gas < callCost.Uint64() { ### Rationale -Currently the gas specified as part of these opcodes is simply a maximum value. And due to the behavior of [EIP-150](http://eips.ethereum.org/EIPS/eip-150) it is possible for an external call to be given less gas than intended (less than the gas specified as part of the CALL) while the rest of the current call is given enough to continue and succeed. Indeed since with EIP-150, the external call is given at max ```G - Math.floor(G/64)``` where G is the gasleft() at the point of the CALL, the rest of the current call is given ```Math.floor(G/64)``` which can be plenty enough for the transaction to succeed. For example, when G = 6,400,000 the rest of the transaction will be given 100,000 gas plenty enough in many case to succeed. +Currently the gas specified as part of these opcodes is simply a maximum value. And due to the behavior of [EIP-150](https://eips.ethereum.org/EIPS/eip-150) it is possible for an external call to be given less gas than intended (less than the gas specified as part of the CALL) while the rest of the current call is given enough to continue and succeed. Indeed since with EIP-150, the external call is given at max ```G - Math.floor(G/64)``` where G is the gasleft() at the point of the CALL, the rest of the current call is given ```Math.floor(G/64)``` which can be plenty enough for the transaction to succeed. For example, when G = 6,400,000 the rest of the transaction will be given 100,000 gas plenty enough in many case to succeed. This is an issue for contracts that require external call to only fails if they would fails with enough gas. This requirement is present in smart contract wallet and meta transaction in general, where the one executing the transaction is not the signer of the execution data. Because in such case, the contract needs to ensure the call is executed exactly as the signing user intended. @@ -90,9 +90,9 @@ But this is also true for simple use case, like checking if a contract implement Indeed, if the caller do not ensure that 30,000 gas or more is provided to the callee, the callee might throw because of a lack of gas (and not because it does not support the interface), and the parent call will be given up to 476 gas to continue. This would result in the caller interepreting wrongly that the callee is not implementing the interface in question. -While such requirement can be enforced by checking the gas left according to EIP-150 and the precise gas required before the call (see solution presented in that [bug report](https://web.solidified.io/contract/5b4769b1e6c0d80014f3ea4e/bug/5c83d86ac2dd6600116381f9) or after the call (see the native meta transaction implementation [here](https://github.com/pixowl/thesandbox-contracts/blob/623f4d4ca10644dcee145bcbd9296579a1543d3d/src/Sand/erc20/ERC20MetaTxExtension.sol#L176), it would be much better if the EVM allowed us to strictly specify how much gas is to be given to the CALL so contract implementations do not need to follow [EIP-150](http://eips.ethereum.org/EIPS/eip-150) behavior and the current gas pricing so closely. +While such requirement can be enforced by checking the gas left according to EIP-150 and the precise gas required before the call (see solution presented in that [bug report](https://web.solidified.io/contract/5b4769b1e6c0d80014f3ea4e/bug/5c83d86ac2dd6600116381f9) or after the call (see the native meta transaction implementation [here](https://github.com/pixowl/thesandbox-contracts/blob/623f4d4ca10644dcee145bcbd9296579a1543d3d/src/Sand/erc20/ERC20MetaTxExtension.sol#L176), it would be much better if the EVM allowed us to strictly specify how much gas is to be given to the CALL so contract implementations do not need to follow [EIP-150](https://eips.ethereum.org/EIPS/eip-150) behavior and the current gas pricing so closely. -This would also allow the behaviour of [EIP-150](http://eips.ethereum.org/EIPS/eip-150) to be changed without having to affect contract that require this strict gas behaviour. +This would also allow the behaviour of [EIP-150](https://eips.ethereum.org/EIPS/eip-150) to be changed without having to affect contract that require this strict gas behaviour. As mentioned, such strict gas behaviour is important for smart contract wallet and meta transaction in general. The issue is actually already a problem in the wild as can be seen in the case of Gnosis safe which did not consider the behavior of EIP-150 and thus fails to check the gas properly, requiring the safe owners to add otherwise unnecessary extra gas to their signed message to avoid the possibility of losing funds. See https://github.com/gnosis/safe-contracts/issues/100 @@ -143,7 +143,7 @@ None fully implemented yet. But see Specifications for an example in geth. ## References -1. EIP-150, http://eips.ethereum.org/EIPS/eip-150 +1. EIP-150, https://eips.ethereum.org/EIPS/eip-150 ## Copyright diff --git a/EIPS/eip-1965.md b/EIPS/eip-1965.md index aad5ea94dd499..387d3bdb01510 100644 --- a/EIPS/eip-1965.md +++ b/EIPS/eip-1965.md @@ -16,7 +16,7 @@ This EIP adds a precompile that returns whether a specific chainID (EIP-155 uniq ## Motivation [EIP-155](https://eips.ethereum.org/EIPS/eip-155) proposes to use the chain ID to prevent the replay of transactions between different chains. It would be a great benefit to have the same possibility inside smart contracts when handling off-chain message signatures, especially for Layer 2 signature schemes using [EIP-712](https://eips.ethereum.org/EIPS/eip-712). -[EIP-1344](http://eips.ethereum.org/EIPS/eip-1344) is attempting to solve this by giving smart contract access to the tip of the chainID history. This is insuficient as such value is changing. Hence why EIP-1344 describes a contract based solution to work around the problem. It would be better to solve it in a simpler, cheaper and safer manner, removing the potential risk of misuse present in EIP-1344. Furthermore EIP-1344 can't protect replay properly for minority-led hardfork as the caching system cannot guarantee accuracy of the blockNumber at which the new chainID has been introduced. +[EIP-1344](https://eips.ethereum.org/EIPS/eip-1344) is attempting to solve this by giving smart contract access to the tip of the chainID history. This is insuficient as such value is changing. Hence why EIP-1344 describes a contract based solution to work around the problem. It would be better to solve it in a simpler, cheaper and safer manner, removing the potential risk of misuse present in EIP-1344. Furthermore EIP-1344 can't protect replay properly for minority-led hardfork as the caching system cannot guarantee accuracy of the blockNumber at which the new chainID has been introduced. [EIP-1959](https://github.com/ethereum/EIPs/pull/1959) solves the issue of EIP-1344 but do not attempt to protect from minority-led hardfork as mentioned in the rationale. We consider this a mistake, since it remove some freedom to fork. We consider that all fork should be given equal oportunities. And while there will always be issues we can't solve for the majority that ignore a particular fork, **users that decide to use both the minority-fork and the majority-chain should be protected from replay without having to wait for the majority chain to update its chainID.** @@ -60,4 +60,4 @@ While the pair could be optional for contract that do not care about replays or This was previously suggested as part of [EIP1959 discussion](https://ethereum-magicians.org/t/eip-1959-valid-chainid-opcode/3170). ## Copyright -Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). \ No newline at end of file +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-1985.md b/EIPS/eip-1985.md index dd6417eb3f4e2..95b940c2bda70 100644 --- a/EIPS/eip-1985.md +++ b/EIPS/eip-1985.md @@ -97,7 +97,7 @@ However, setting the limit `2^32 - 1` is beneficial from a VM design perspective ### Code size -[EIP-170](http://eips.ethereum.org/EIPS/eip-170) has implemented a code size limit of 0x6000, however even before that, it was practically impossible to deploy a code blob exceeding `2**32 - 1` bytes in size. +[EIP-170](https://eips.ethereum.org/EIPS/eip-170) has implemented a code size limit of 0x6000, however even before that, it was practically impossible to deploy a code blob exceeding `2**32 - 1` bytes in size. ### Comparing current implementations diff --git a/EIPS/eip-2009.md b/EIPS/eip-2009.md index ffbd33bbfae9b..74ecc22430db4 100644 --- a/EIPS/eip-2009.md +++ b/EIPS/eip-2009.md @@ -294,7 +294,7 @@ Copyright and related rights waived via [CC0](https://creativecommons.org/public [KYC-Wikipedia]: https://en.wikipedia.org/wiki/Know_your_customer [AML-Wikipedia]: https://en.wikipedia.org/wiki/Money_laundering#Anti-money_laundering -[ERC-777]: http://eips.ethereum.org/EIPS/eip-777 -[ERC-1066]: http://eips.ethereum.org/EIPS/eip-1066 -[ERC-1444]: http://eips.ethereum.org/EIPS/eip-1444 -[ERC-1462]: http://eips.ethereum.org/EIPS/eip-1462 +[ERC-777]: https://eips.ethereum.org/EIPS/eip-777 +[ERC-1066]: https://eips.ethereum.org/EIPS/eip-1066 +[ERC-1444]: https://eips.ethereum.org/EIPS/eip-1444 +[ERC-1462]: https://eips.ethereum.org/EIPS/eip-1462 diff --git a/EIPS/eip-2020.md b/EIPS/eip-2020.md index aa089a3fc6bf2..94224224f2e44 100644 --- a/EIPS/eip-2020.md +++ b/EIPS/eip-2020.md @@ -224,10 +224,10 @@ This proposal has been collaboratively implemented by [adhara.io](https://adhara ## Copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). -[ERC-20]: http://eips.ethereum.org/EIPS/eip-20 -[ERC-1066]: http://eips.ethereum.org/EIPS/eip-1066 -[ERC-1462]: http://eips.ethereum.org/EIPS/eip-1462 -[ERC-1996]: http://eips.ethereum.org/EIPS/eip-1996 -[ERC-2018]: http://eips.ethereum.org/EIPS/eip-2018 -[ERC-2019]: http://eips.ethereum.org/EIPS/eip-2019 -[ERC-2021]: http://eips.ethereum.org/EIPS/eip-2021 +[ERC-20]: https://eips.ethereum.org/EIPS/eip-20 +[ERC-1066]: https://eips.ethereum.org/EIPS/eip-1066 +[ERC-1462]: https://eips.ethereum.org/EIPS/eip-1462 +[ERC-1996]: https://eips.ethereum.org/EIPS/eip-1996 +[ERC-2018]: https://eips.ethereum.org/EIPS/eip-2018 +[ERC-2019]: https://eips.ethereum.org/EIPS/eip-2019 +[ERC-2021]: https://eips.ethereum.org/EIPS/eip-2021 diff --git a/EIPS/eip-2025.md b/EIPS/eip-2025.md index fbb6e188b35f7..f96a7b3895a45 100644 --- a/EIPS/eip-2025.md +++ b/EIPS/eip-2025.md @@ -14,7 +14,7 @@ requires: 1890 Add `0.0055 ETH` per block for 18 months (A total of 17050 ETH) as a developer block reward reserved for funding specific Ethereum1.X working groups. The working groups are State rent (750k), Better sync (360k), Finality gadget (360k), Fee market (360k), Testing infrastructure (360k). Governance of the funds will be through a multisig of trusted individuals from the ecosystem including client teams, the foundation, and the community. -[EIP-1890](http://eips.ethereum.org/EIPS/eip-1890) proposes a mechanism to capture a portion of block rewards for sustainably funding ongoing network development. That EIP sets values and addresses to zero and so does not actually collect any rewards. This proposal is to explicitly set those values and begin collecting a portion of block rewards for 18 months in order to fund Ethereum 1.X working groups and organization efforts. This funding will be used to repay an initial loan provided by investors in the community funding this work with a small amount of interest. After 18 months the block reward would again reduce to zero. +[EIP-1890](https://eips.ethereum.org/EIPS/eip-1890) proposes a mechanism to capture a portion of block rewards for sustainably funding ongoing network development. That EIP sets values and addresses to zero and so does not actually collect any rewards. This proposal is to explicitly set those values and begin collecting a portion of block rewards for 18 months in order to fund Ethereum 1.X working groups and organization efforts. This funding will be used to repay an initial loan provided by investors in the community funding this work with a small amount of interest. After 18 months the block reward would again reduce to zero. diff --git a/EIPS/eip-2028.md b/EIPS/eip-2028.md index ba594d2f90f88..6a7d1bd8d2a61 100644 --- a/EIPS/eip-2028.md +++ b/EIPS/eip-2028.md @@ -71,7 +71,7 @@ To suggest the gas cost of calldata we shall conduct two types of tests: [2] Rafael Pass, Lior Seeman, Abhi Shelat: [Analysis of the Blockchain Protocol in Asynchronous Networks](https://eprint.iacr.org/2016/454.pdf), ePrint report 2016/454 -[3] Christian Decker, Roger Wattenhofer: [Information propagation in the Bitcoin network](http://www.gsd.inesc-id.pt/~ler/docencia/rcs1314/papers/P2P2013_041.pdf). P2P 2013: 1-10 +[3] Christian Decker, Roger Wattenhofer: [Information propagation in the Bitcoin network](https://www.gsd.inesc-id.pt/~ler/docencia/rcs1314/papers/P2P2013_041.pdf). P2P 2013: 1-10 [4] Vitalik Buterin: [Uncle Rate and Transaction Fee Analysis](https://blog.ethereum.org/2016/10/31/uncle-rate-transaction-fee-analysis/) diff --git a/EIPS/eip-205.md b/EIPS/eip-205.md index 09c5e3666bb6d..e4753a3ef6504 100644 --- a/EIPS/eip-205.md +++ b/EIPS/eip-205.md @@ -38,7 +38,7 @@ Encoding type 1 specifies plaintext JSON, uncompressed; this is the standard for 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 4 is [CBOR](https://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. diff --git a/EIPS/eip-2070.md b/EIPS/eip-2070.md index 82f533da2261e..a4ca34aafb472 100644 --- a/EIPS/eip-2070.md +++ b/EIPS/eip-2070.md @@ -24,36 +24,24 @@ This meta-EIP specifies the changes included in the Ethereum hardfork named Berl ### Accepted EIPs -- TBD - -### Tentatively Accepted EIPs - -- [EIP-663](https://eips.ethereum.org/EIPS/eip-663): Unlimited SWAP and DUP instructions -- [EIP-1057](https://eips.ethereum.org/EIPS/eip-1057): ProgPoW, a Programmatic - Proof-of-Work - - There is a - [pending audit](https://medium.com/ethereum-cat-herders/progpow-audit-goals-expectations-75bb902a1f01), - above and beyond standard security considerations, that should be evaluated - prior to inclusion. -- [EIP-1380](https://eips.ethereum.org/EIPS/eip-1380): Reduced gas cost for call to self -- [EIP-1702](https://eips.ethereum.org/EIPS/eip-1702): Generalized account versioning scheme -- [EIP-1962](https://eips.ethereum.org/EIPS/eip-1962): EC arithmetic and pairings with runtime definitions - - replaces EIP-1829 -- [EIP-1985](https://eips.ethereum.org/EIPS/eip-1985): Sane limits for certain EVM parameters -- [EIP-2045](https://eips.ethereum.org/EIPS/eip-2045): Particle gas costs for EVM opcodes -- [EIP-2046](https://eips.ethereum.org/EIPS/eip-2046): Reduced gas cost for static calls made to precompiles +- [EIP-2315](https://eips.ethereum.org/EIPS/eip-2315): Simple Subroutines for the EVM +- [EIP-2537](https://github.com/ethereum/EIPs/pull/2537): BLS12-381 curve operations ### Proposed EIPs -- TBD +- [EIP-2046](https://eips.ethereum.org/EIPS/eip-2046): Reduced gas cost for static calls made to precompiles +- [EIP-2565](https://eips.ethereum.org/EIPS/eip-2565): Repricing of the EIP-198 ModExp precompile ## Timeline -- TBD +(Proposed) +- Early June: Testnets +- Mid July: Mainnet ## References -- TBD +- Tracking [EFI](https://github.com/orgs/ethereum/projects/5) +- ACD meeting [notes 85](https://github.com/ethereum/pm/blob/ee277386af75621c48923f9740e4913ee241cd05/All%20Core%20Devs%20Meetings/Meeting%2085.md) ## Copyright diff --git a/EIPS/eip-2098.md b/EIPS/eip-2098.md index 72913d011f4fc..38d2802d7e276 100644 --- a/EIPS/eip-2098.md +++ b/EIPS/eip-2098.md @@ -50,7 +50,7 @@ used in Bitcoin.) Second, the top bit of the `s` parameters is **always** 0, due to the use of canonical signatures which flip the solution parity to prevent negative values, -which was introduced as [a constraint in Homestead](http://eips.ethereum.org/EIPS/eip-2). +which was introduced as [a constraint in Homestead](https://eips.ethereum.org/EIPS/eip-2). So, we can hijack the top bit in the `s` parameter to store the value of `v`, resulting in: diff --git a/EIPS/eip-2193.md b/EIPS/eip-2193.md index fdab1455a42a1..093ee3b4d0370 100644 --- a/EIPS/eip-2193.md +++ b/EIPS/eip-2193.md @@ -16,13 +16,13 @@ We are proposing Alias - a semantic standard for identifying on-chain resour ## Abstract -The dType Alias is a system for providing human-readable resource identifiers to on-chain content. A resource identifier is based on the type of data (identifier provided by dType, [EIP-1900](http://eips.ethereum.org/EIPS/eip-1900)) and the data content (identifier provided by a dType Storage Contract, [EIP-2157](http://eips.ethereum.org/EIPS/eip-2157)). It is a universal way of addressing content, supporting any type of data. +The dType Alias is a system for providing human-readable resource identifiers to on-chain content. A resource identifier is based on the type of data (identifier provided by dType, [EIP-1900](https://eips.ethereum.org/EIPS/eip-1900)) and the data content (identifier provided by a dType Storage Contract, [EIP-2157](https://eips.ethereum.org/EIPS/eip-2157)). It is a universal way of addressing content, supporting any type of data. ## Motivation -There are standards that currently address the need for attaching human-readable identifiers to Ethereum accounts, such as [EIP-137](http://eips.ethereum.org/EIPS/eip-137). These standards are an attempt to bring domain names to Ethereum, following the same format as DNS: `subdomain.domain.tld`. This leaf -> root format is unintuitive and contradicts the semantic meaning that `.` has in programming languages, which is a root -> leaf connection (e.g. in OOP, when accessing an object's property). A more intuitive and widely used approach is a root->leaf format, used in file browsers, hierarchical menus, and even in other decentralized systems, which give unique identifiers to resources (e.g. `0x56.Currency.TCoin` in [Libra](https://medium.com/r/?url=https%3A%2F%2Fdevelopers.libra.org). +There are standards that currently address the need for attaching human-readable identifiers to Ethereum accounts, such as [EIP-137](https://eips.ethereum.org/EIPS/eip-137). These standards are an attempt to bring domain names to Ethereum, following the same format as DNS: `subdomain.domain.tld`. This leaf -> root format is unintuitive and contradicts the semantic meaning that `.` has in programming languages, which is a root -> leaf connection (e.g. in OOP, when accessing an object's property). A more intuitive and widely used approach is a root->leaf format, used in file browsers, hierarchical menus, and even in other decentralized systems, which give unique identifiers to resources (e.g. `0x56.Currency.TCoin` in [Libra](https://medium.com/r/?url=https%3A%2F%2Fdevelopers.libra.org). -Moreover, [EIP-137](http://eips.ethereum.org/EIPS/eip-137) is not flexible enough to address smart contract content, which can contain heterogeneous data that belongs to various accounts. For example, a `PaymentChannel` smart contract can have an domain name. However, the `Alice-Bob` channel data from inside the smart contract, cannot have a subdomain name. Having uniquely identified, granular resources opens the way to creating both human and machine-readable protocols on top of Ethereum. It also provides a basis for protocols based on functional programming. +Moreover, [EIP-137](https://eips.ethereum.org/EIPS/eip-137) is not flexible enough to address smart contract content, which can contain heterogeneous data that belongs to various accounts. For example, a `PaymentChannel` smart contract can have an domain name. However, the `Alice-Bob` channel data from inside the smart contract, cannot have a subdomain name. Having uniquely identified, granular resources opens the way to creating both human and machine-readable protocols on top of Ethereum. It also provides a basis for protocols based on functional programming. This ERC proposes a set of separators which maintain their semantic meaning and provides a way to address any type of resource - from Ethereum addresses, to individual `struct` instances inside smart contracts. @@ -34,7 +34,7 @@ This alias system can be used off-chain, to replace the old DNS system with a de The dType registry will provide domain and subdomain names for the resource type. Subdomains can be attributed recursively, to dType types which contain other complex types in their composition. We define an `Alias` registry contract, that keeps track of the human-readable identifiers for data resources, which exist in dType storage contracts. -Anyone can set an alias in the `Alias` registry, as long as the Ethereum address that signs the alias data has ownership on the resource, in the dType storage contract. Storage contract data ownership will be detailed in [EIP-2157](http://eips.ethereum.org/EIPS/eip-2157). An owner can update or delete an alias at any time. +Anyone can set an alias in the `Alias` registry, as long as the Ethereum address that signs the alias data has ownership on the resource, in the dType storage contract. Storage contract data ownership will be detailed in [EIP-2157](https://eips.ethereum.org/EIPS/eip-2157). An owner can update or delete an alias at any time. ```solidity interface Alias { @@ -58,7 +58,7 @@ interface Alias { - `signature`: Alias owner signature on `dtypeIdentifier`, `identifier`, `name`, `separator`, `nonce`, `aliasAddress`, `chainId`. - `nonce`: monotonically increasing counter, used to prevent replay attacks - `aliasAddress`: Ethereum address of `Alias` contract - - `chainId`: chain on which the `Alias` contract is deployed, as detailed in [EIP-155](http://eips.ethereum.org/EIPS/eip-155), used to prevent replay attacks when updating the `identifier` for an alias. + - `chainId`: chain on which the `Alias` contract is deployed, as detailed in [EIP-155](https://eips.ethereum.org/EIPS/eip-155), used to prevent replay attacks when updating the `identifier` for an alias. Content addressability can be done: - using the `bytes32` identifiers directly, e.g. `0x0b5e76559822448f6243a6f76ac7864eba89c810084471bdee2a63429c92d2e7@0x9dbb9abe0c47484c5707699b3ceea23b1c2cca2ac72681256ab42ae01bd347da` @@ -69,9 +69,9 @@ Both of the above examples will resolve to the same content. ## Rationale -Current attempts to solve content addressability, such as [EIP-137](http://eips.ethereum.org/EIPS/eip-137), only target Ethereum accounts. These are based on inherited concepts from HTTP and DNS, which are not machine friendly. +Current attempts to solve content addressability, such as [EIP-137](https://eips.ethereum.org/EIPS/eip-137), only target Ethereum accounts. These are based on inherited concepts from HTTP and DNS, which are not machine friendly. -With [EIP-1900](http://eips.ethereum.org/EIPS/eip-1900) and [EIP-2157](http://eips.ethereum.org/EIPS/eip-2157), general content addressability can be achieved. dType provides type information and a reference to the smart contract where the type instances are stored. Additionally, Alias uses the semantic meaning of subdomain separators to have a [intuitive order rule](https://github.com/loredanacirstea/articles/blob/master/articles/Flexible_Alias_or_Why_ENS_is_Obsolete.md). +With [EIP-1900](https://eips.ethereum.org/EIPS/eip-1900) and [EIP-2157](https://eips.ethereum.org/EIPS/eip-2157), general content addressability can be achieved. dType provides type information and a reference to the smart contract where the type instances are stored. Additionally, Alias uses the semantic meaning of subdomain separators to have a [intuitive order rule](https://github.com/loredanacirstea/articles/blob/master/articles/Flexible_Alias_or_Why_ENS_is_Obsolete.md). Multiple aliases can be assigned to a single resource. Either by using a different `name` or by using a different `separator`. Each `separator` can have a specific standard for displaying and processing data, based on its semantic meaning. diff --git a/EIPS/eip-2315.md b/EIPS/eip-2315.md index dffa2356f8e1d..6ab9a5360dc58 100644 --- a/EIPS/eip-2315.md +++ b/EIPS/eip-2315.md @@ -4,111 +4,165 @@ title: Simple Subroutines for the EVM status: Draft type: Standards Track category: Core -author: Greg Colvin (greg@colvin.org) +author: Greg Colvin (greg@colvin.org), Martin Holst Swende (@holiman) discussions-to: https://ethereum-magicians.org/t/eip-2315-simple-subroutines-for-the-evm/3941 created: 2019-10-17 --- ## Abstract -This proposal introduces three opcodes to support subroutines: `BEGINSUB`, `JUMPSUB` and `RETURNSUB`. +This proposal introduces three opcodes to support subroutines: `BEGINSUB`, `JUMPSUB` and `RETURNSUB`. ## Motivation -The EVM does not provide subroutines as a primitive. Instead, calls can be synthesized by fetching and pushing the current program counter on the data stack and jumping to the subroutine address; returns can be synthesized by contriving to get the return address back to the top of stack and jumping back to it. Complex calling conventions are then needed to use the same stack for computation and control flow. Code becomes harder to read and write, and tools may need to pattern-match the conventions to identify the use of subroutines. Complex calling conventions like these can be avoided using memory, but regardless, it costs a lot of gas. +The EVM does not provide subroutines as a primitive. Instead, calls can be synthesized by fetching and pushing the current program counter on the data stack and jumping to the subroutine address; returns can be synthesized by contriving to get the return address back to the top of stack and jumping back to it. Complex calling conventions are then needed to use the same stack for computation and control flow. Memory allows for simpler conventions but still costs gas. Eschewing subroutines in user code is the least costly -- but also the most failure-prone. -Having opcodes to directly support subroutines can eliminate this complexity and cost, just as for other physical and virtual machines going back at least 50 years. +Over the course of 30 years the computer industry struggled with this complexity and cost +and settled in on opcodes to directly support subroutines. These are provided in some form by most all physical and virtual machines going back at least 50 years. -In the Appendix we show example solc output for a simple program that uses over three times as much gas just calling and returning from subroutines as comparable code using these opcodes. +Our design is modeled on the original Forth two-stack machine of 1970. The data stack is supplemented with a return stack to provide simple support for subroutines, as specified below. + +In the Appendix we show example solc output for a simple program that uses over three times as much gas just calling and returning from subroutines as comparable code using these opcodes. Actual differences in run-time efficiency will of course vary widely. ## Specification -##### `BEGINSUB` -Marks the entry point to a subroutine. +We introduce one more stack into the EVM in addition to the existing `data stack` which we call the `return stack`. The `return stack` is limited to `1023` items. + +#### `BEGINSUB` + +Marks the entry point to a subroutine. Attempted execution of a `BEGINSUB` causes an _`abort`_: terminate execution with an `OOG` (Out Of Gas) exception. + +#### `JUMPSUB` + +Transfers control to a subroutine. + +1. Pop the `location` off the `data stack`. +2. If the opcode at `location` is not a `BEGINSUB` _`abort`_. +3. If the `return stack` already has `1023` items _`abort`_. +4. Push the current `pc + 1` to the `return stack`. +5. Set `pc` to `location + 1`. + +* _pops one item off the `data stack`_ +* _pushes one item on the `return stack`_ + +#### `RETURNSUB` + +Returns control to the caller of a subroutine. + +1. If the `return stack` is empty _`abort`_. +2. Pop `pc` off the `return stack`. + +* _pops one item off the `return stack`_ -##### `JUMPSUB` -Jumps to the destination address on top of the stack, which must be the offset of a `BEGINSUB`. +_Note 1: If a resulting `pc` to be executed is beyond the last instruction then the opcode is implicitly a `STOP`, which is not an error._ -##### `RETURNSUB` -Returns to the most recently executed `JUMPSUB` and advances to the following instruction. +_Note 2: Values popped off the `return stack` do not need to be validated, since they are alterable only by `JUMPSUB` and `RETURNSUB`._ -A program may `JUMPSUB` at most 1023 times without an intervening `RETURNSUB`. A program which executes `RETURNSUB` without no prior `BEGINSUB` will `STOP`. +_Note 3: The description above lays out the semantics of this feature in terms of a `return stack`. But the actual state of the `return stack` is not observable by EVM code or consensus-critical to the protocol. (For example, a node implementor may code `JUMPSUB` to unobservably push `pc` on the `return stack` rather than `pc + 1`, which is allowed so long as `RETURNSUB` observably returns control to the `pc + 1` location.)_ ## Rationale -This is the smallest possible change that provides native subroutines without breaking backwards compatibility. +This is the is a small change that provides native subroutines without breaking backwards compatibility. ## Backwards Compatibility These changes do not affect the semantics of existing EVM code. -## Test Cases -``` - data return -offset step opcode stack stack -0 0 PUSH1 3 [] [] -1 1 JUMPSUB [3] [1] -2 4 STOP [] [1] -3 2 BEGINSUB [] [1] -4 3 RETURNSUB [] [] -``` -The above code should terminate after 4 steps with an empty stack. +# Test Cases + +### Simple routine + +This should jump into a subroutine, back out and stop. + +Bytecode: `0x6004b300b2b7` + + +| Pc | Op | Cost | Stack | RStack | +|-------|-------------|------|-----------|-----------| +| 0 | PUSH1 | 3 | [] | [] | +| 2 | JUMPSUB | 5 | [4] | [] | +| 5 | RETURNSUB | 2 | [] | [ 2] | +| 3 | STOP | 0 | [] | [] | + +### Two levels of subroutines + +This should execute fine, going into one two depths of subroutines +Bytecode: `0x6800000000000000000cb300b26011b3b7b2b7` + +| Pc | Op | Cost | Stack | RStack | +|-------|-------------|------|-----------|-----------| +| 0 | PUSH9 | 3 | [] | [] | +| 10 | JUMPSUB | 5 | [12] | [] | +| 13 | PUSH1 | 3 | [] | [10] | +| 15 | JUMPSUB | 5 | [17] | [10] | +| 18 | RETURNSUB | 2 | [] | [10,15] | +| 16 | RETURNSUB | 2 | [] | [10] | +| 11 | STOP | 0 | [] | [] | + + +### Failure 1: invalid jump + +This should fail, since the given `location` is outside of the code-range. The code is the same as previous example, +except that the pushed `location` is `0x01000000000000000c` instead of `0x0c`. + +Bytecode: `0x6801000000000000000cb300b26011b3b7b2b7 ` + +| Pc | Op | Cost | Stack | RStack | +|-------|-------------|------|-----------|-----------| +| 0 | PUSH9 | 3 | [] | [] | +| 10 | JUMPSUB | 5 |[18446744073709551628] | [] | + ``` - data return -offset step opcode stack stack -0 0 PUSH1 2 [] [] -1 1 JUMPSUB [2] [1] -2 2 BEGINSUB [] [1] -3 3 RETURNSUB [] [] +Error: at pc=10, op=JUMPSUB: evm: invalid jump destination ``` -The above code should terminate after 4 steps with an empty stack. + +### Failure 2: shallow `return stack` + +This should fail at first opcode, due to shallow `return stack` + +Bytecode: `0xb75858` (`RETURNSUB`, `PC`, `PC`) + + +| Pc | Op | Cost | Stack | RStack | +|-------|-------------|------|-----------|-----------| +| 0 | RETURNSUB | 2 | [] | [] | + ``` - data return -offset step opcode stack stack -0 0 PUSH1 3 [] [] -1 1 JUMPSUB [3] [1] -2 8 STOP [] [] -3 2 BEGINSUB [] [1] -4 3 PUSH1 7 [] [1] -5 4 JUMPSUB [7] [1,5] -6 7 RETURNSUB [] [1] -7 5 BEGINSUB [] [1] -8 6 RETURNSUB [] [1] +Error: at pc=0, op=RETURNSUB: evm: invalid retsub ``` -The above code should terminate after 8 steps with an empty stack. The above code should terminate after 8 steps with an empty stack. + +### Subroutine at end of code + +In this example. the JUMPSUB is on the last byte of code. When the subroutine returns, it should hit the 'virtual stop' _after_ the bytecode, and not exit with error + +Bytecode: `0x600556b2b75b6003b3` + +| Pc | Op | Cost | Stack | RStack | +|-------|-------------|------|-----------|-----------| +| 0 | PUSH1 | 3 | [] | [] | +| 2 | JUMP | 8 | [5] | [] | +| 5 | JUMPDEST | 1 | [] | [] | +| 6 | PUSH1 | 3 | [] | [] | +| 8 | JUMPSUB | 5 | [3] | [] | +| 3 | BEGINSUB | 1 | [] | [ 8] | +| 4 | RETURNSUB | 2 | [] | [ 8] | +| 9 | STOP | 0 | [] | [] | + +Consumed gas: `26` ## Implementations -No clients have implemented this proposal as of yet, but there are Draft PRs on the [evmone](https://github.com/ethereum/evmone/pull/229) and [geth](https://github.com/ethereum/go-ethereum/pull/20619) interpreters. +Three clients have implemented the previous version of proposal: -The new operators proposed here are demonstrated by the following pseudocode, which adds a return stack and cases for `BEGINSUB`, `JUMPSUB` and `RETURNSUB` to a simple loop-and-switch interpreter. -``` -bytecode[code_size] -data_stack[1024] = { } -return_stack[1024] = { code_size } -PC = 0 -while PC < code_size { - opcode = bytecode[PC] - switch opcode { - ... - case BEGINSUB: - - case JUMPSUB: - push(return_stack, PC) - PC = pop(data_stack) - continue - - case RETURNSUB: - PC = pop(return_stack) - } - ++PC -} -``` -Execution of EVM bytecode begins with one value on the return stack—the size of the bytecode. The implicit 0 bytes at and after this offset are EVM `STOP` opcods. So executing a `RETURNSUB` with no prior `JUMPSUB` jumps to the _code_size_ offset on the stack, then executes a `STOP` on the next cycle. A `STOP` or `RETURN` ends the execution of the program. +- [geth](https://github.com/ethereum/go-ethereum/pull/20619) . +- [besu](https://github.com/hyperledger/besu/pull/717), and +- [openethereum](https://github.com/openethereum/openethereum/pull/11629). + +The changes for the current version are trivial. ### Costs and Codes -We suggest that the cost of `BEGINSUB` be _base_, `JUMPSUB` be _low_, and `RETURNSUB` be _verylow_. +We suggest that the cost of `JUMPSUB` be _low_, and `RETURNSUB` be _verylow_. Measurement will tell. We suggest the following opcodes: ``` @@ -116,9 +170,12 @@ We suggest that the cost of `BEGINSUB` be _base_, `JUMPSUB` be _low_, and `RETUR 0xb3 JUMPSUB 0xb7 RETURNSUB ``` + ## Security Considerations -Program flow analysis frameworks will need to be updated to allow for a new type of branch - `JUMPSUB` - which will cause a jump to a destination which is a `BEGINSUB`, not a `JUMPDEST`. +These changes do introduce new flow control instructions, so any software which does static/dynamic analysis of evm-code +needs to be modified accordingly. The `JUMPSUB` semantics are similar to `JUMP` (but jumping to a `BEGINSUB`), whereas the `RETURNSUB` instruction is different, since it can 'land' on any opcode (but the possible destinations can be statically inferred). + ## Appendix: Comparative costs. @@ -170,7 +227,7 @@ MULTIPLY: ``` solc does a good job with the multiply() function, which is a leaf. Non-leaf functions are more awkward to get out of. Calling `fun.test()` will cost _118 gas_, plus 5 for the `mul`. - This is the same code written using `jumpsub` and `returnsub`. Calling `fun.test()` will cost _34 gas_ (plus 5). + This is the same code written using `jumpsub` and `returnsub`. Calling `fun.test()` will cost _32 gas_ plus 5 for the `mul`. ``` TEST: beginsub @@ -190,4 +247,4 @@ MULTIPLY: returnsub ``` -**Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).** \ No newline at end of file +**Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).** diff --git a/EIPS/eip-2333.md b/EIPS/eip-2333.md index a27d4e532f29b..261a0653a8598 100644 --- a/EIPS/eip-2333.md +++ b/EIPS/eip-2333.md @@ -27,7 +27,7 @@ This specification is designed not only to be an Ethereum 2.0 standard, but one ### Deficiencies of the existing mechanism -The new curve (BLS12-381) used for signatures within Ethereum 2.0 (alongside many other projects) mandates a new key derivation scheme. The most commonly used scheme for key derivation at the within Ethereum 1.x is [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) (also known as HD derivation) which deems keys greater than the curve order invalid. Based on the order of the private key subgroup of BLS12-381 and the size of the entropy utilised, more than 54% of keys generated by BIP32 would be invalid. (secp256k1 keys derived by BIP32 are invalid with probability less than 1 in 2-127.) +The new curve (BLS12-381) used for signatures within Ethereum 2.0 (alongside many other projects) mandates a new key derivation scheme. The most commonly used scheme for key derivation within Ethereum 1.x is [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) (also known as HD derivation) which deems keys greater than the curve order invalid. Based on the order of the private key subgroup of BLS12-381 and the size of the entropy utilised, more than 54% of keys generated by BIP32 would be invalid. (secp256k1 keys derived by BIP32 are invalid with probability less than 1 in 2-127.) ### Establishing a multi-chain standard early on @@ -35,7 +35,7 @@ By establishing a standard before the first users begin to generate their keys, ### A post-quantum backup -This key derivation scheme has a Lamport key pair which is generated as a intermediate step in the key generation process. This key pair can be used to provide a Lamport signature which is a useful backup in the event of BLS12-381 no longer being considered secure (in the event of quantum computing making a sudden advancement, for example.). The idea is the Lamport signature will act as a bridge to a new signature scheme which is deemed to be secure. +This key derivation scheme has a Lamport key pair which is generated as a intermediate step in the key generation process. This key pair can be used to provide a Lamport signature which is a useful backup in the event of BLS12-381 no longer being considered secure (in the event of quantum computing making a sudden advancement, for example). The idea is the Lamport signature will act as a bridge to a new signature scheme which is deemed to be secure. ## Specification @@ -198,7 +198,7 @@ The child key derivation function takes in the parent's private key and the inde Lamport signatures are used as the backup mechanism because of their relative simplicity for a post-quantum signature scheme. Lamport signatures are very easy both to explain and implement as the sole cryptographic dependency is a secure hash function. This is important as it minimises the complexity of implementing this standard as well as the compute time for deriving a key. Lamport signatures have very large key sizes which make them impractical for many use cases, but this is not deemed to be an issue in this case as this scheme is only meant to be a once-off event to migrate to a new scheme. -Revealing a the associated Lamport public key for a corresponding BLS key is done by verifying that the Lamport public key is the pre-image of the corresponding BLS private key (which in tern is verified against the BLS public key). This means that using a key's Lamport signature reveals the BLS private key rendering the BLS key pair unsafe. This has the upside of not requiring additional storage space for backup keys alongside BLS keys but does require that the Lamport signatures be used once and that the BLS key is no longer trusted after that point. +Revealing the associated Lamport public key for a corresponding BLS key is done by verifying that the Lamport public key is the pre-image of the corresponding BLS private key (which in turn is verified against the BLS public key). This means that using a key's Lamport signature reveals the BLS private key rendering the BLS key pair unsafe. This has the upside of not requiring additional storage space for backup keys alongside BLS keys but does require that the Lamport signatures be used once and that the BLS key is no longer trusted after that point. The Lamport signatures used within this scheme have 255 bits worth of security, not 256. This is done because HKDF-SHA256, the mechanism used to stretch a key's entropy, has a length-limit of `255 * hash_function_digest_size`. The 1-bit reduction in security is deemed preferable over increasing the complexity of the entropy stretching mechanism. diff --git a/EIPS/eip-2335.md b/EIPS/eip-2335.md index 372c21965a4f0..c40263486efad 100644 --- a/EIPS/eip-2335.md +++ b/EIPS/eip-2335.md @@ -40,7 +40,7 @@ The process of decrypting the secret held within a keystore can be broken down i This standard makes use of the notion of a _module_ which serves to represent, in an abstract sense, the different cryptographic constructions and corresponding parameters for each component of the keystore. The idea being that components can be swapped out without affecting the rest of the specification should the need arise. -A module consists is comprised of a `function`, which defines which cryptographic construct is being used, `params`, the parameters required by the function, and `message` the primary input to the function. +A module is comprised of a `function`, which defines which cryptographic construct is being used, `params`, the parameters required by the function, and `message` the primary input to the function. ### Decryption key @@ -188,7 +188,7 @@ The `version` is set to 4 to prevent collisions with the existing Ethereum keyst ## Backwards Compatibility -This specification is not backwards compatible with the [existing keystore standard](https://github.com/ethereum/wiki/wiki/Web3-Secret-Storage-Definition) due to the lack of Keccak256 checksums as explained above. While this format is capable of supporting Keccak checksums via the Checksum module, it would defeat the purpose of this standard to include it as this standard could nop longer be considered neutral with respect to other projects in the industry. +This specification is not backwards compatible with the [existing keystore standard](https://github.com/ethereum/wiki/wiki/Web3-Secret-Storage-Definition) due to the lack of Keccak256 checksums as explained above. While this format is capable of supporting Keccak checksums via the Checksum module, it would defeat the purpose of this standard to include it as this standard could no longer be considered neutral with respect to other projects in the industry. ## Test Cases diff --git a/EIPS/eip-2378.md b/EIPS/eip-2378.md index ac34c07b91d6d..371bb3a977b58 100644 --- a/EIPS/eip-2378.md +++ b/EIPS/eip-2378.md @@ -50,6 +50,8 @@ Development of clear specifications and pull requests to existing Ethereum Clien | EIP-1962 | EC arithmetic and pairings with runtime definitions | ELIGIBLE | 2019-11-01 | [🔗](https://github.com/ethereum/pm/blob/master/All%20Core%20Devs%20Meetings/Meeting%2074.md) | | EIP-1985 | Sane limits for certain EVM parameters | ELIGIBLE | 2019-11-01 | [🔗](https://github.com/ethereum/pm/blob/master/All%20Core%20Devs%20Meetings/Meeting%2074.md) | | EIP-2046 | Reduced gas cost for static calls made to precompiles | ELIGIBLE | 2019-11-01 | [🔗](https://github.com/ethereum/pm/blob/master/All%20Core%20Devs%20Meetings/Meeting%2074.md) | +| EIP-2315 | Simple Subroutines for the EVM | ELIGIBLE | 2020-02-21 | [🔗](https://github.com/ethereum/pm/blob/master/All%20Core%20Devs%20Meetings/Meeting%2081.md#decisions) | +| EIP-2537 | Precompile for BLS12-381 curve operations | ELIGIBLE | 2020-03-06 | [🔗](https://github.com/ethereum/pm/blob/master/All%20Core%20Devs%20Meetings/Meeting%2082.md) | ## Rationale diff --git a/EIPS/eip-2384.md b/EIPS/eip-2384.md index fa710412d6a0b..f00101490ac1b 100644 --- a/EIPS/eip-2384.md +++ b/EIPS/eip-2384.md @@ -6,7 +6,6 @@ discussions-to: https://ethereum-magicians.org/t/eip-2384-difficulty-bomb-delay type: Standards Track category: Core status: Final -review-period-end: 2019-12-12 created: 2019-11-20 --- diff --git a/EIPS/eip-2387.md b/EIPS/eip-2387.md index 65b329e1a0248..095c30b4ef621 100644 --- a/EIPS/eip-2387.md +++ b/EIPS/eip-2387.md @@ -5,7 +5,6 @@ author: James Hancock (@madeoftin) discussions-to: https://ethereum-magicians.org/t/hard-fork-to-address-the-ice-age-eip-2387 type: Meta status: Final -review-period-end: 2019-12-12 created: 2019-11-22 requires: 1679, 2384 --- diff --git a/EIPS/eip-2458.md b/EIPS/eip-2458.md new file mode 100644 index 0000000000000..d4c99dcb61ff3 --- /dev/null +++ b/EIPS/eip-2458.md @@ -0,0 +1,83 @@ +--- +eip: 2458 +title: Updates and Updated-by Header +author: Edson Ayllon (@edsonayllon) +discussions-to: https://github.com/ethereum/EIPs/issues/2453 +status: Draft +type: Informational +created: 2020-01-06 +--- + +## Simple Summary + + +Adds EIP header options `updates` and `updated-by` to frontmatter of `active` EIPs for use as needed. + +## Abstract + + +EIP headers `updates` and `updated-by` are used for updating `active` EIPs. This is to make the improvement process of EIPs more modular, and have updates to existing `active` EIPs receive similar exposures to EIPs which replace existing `final` EIPs. + +## Motivation + + +Currently, EIP1 specifies EIP headers: `updated`, `replaces`, and `superseded-by`. Headers `replaces` and `superseded-by` indicates when an entire EIP is being replaced by another EIP, indicating when an EIP is now historical, and is updated by a new standard. + +The header `updated` indicates the date an EIP has received an update by EIP authors and editors, an example EIP being EIP1. `updated` is reserved for EIPs in `draft` or `active` status. + +In the case of `active` status, an EIP may receive an update, but these updates don't operate as with EIPs in `final` status, where a historical EIP is created, and the new EIP is referenced by the historical one. While these updates are not kept immutably, updates to active EIPs can be done modularly by creating a new EIP that goes through the standard discussion and auditing process EIPs undergo. The EIP headers `updates` and `updated-by` are to facilitate this modularity. Creating a new EIP also provides sufficient notification to affected stakeholders of an active EIP before that EIP is `updated`. + +## Specification + + +### `updated-by` + +`updated-by` is reserved for EIPs in `active` status. For an EIP in status `active`, updates to that EIP, which update the header `updated`, should be started by opening a new EIP to start vetting for that update. When an `active` EIP receives a new entry to header `updated`, an associated `updated-by` EIP listing should be included, where that newly listed EIP has reached `final` status. + +`updates` should be included as an EIP header, as all EIP headers, and include a reference to an EIP designation. When multiple EIP designations are referenced, each should be separated by a comma. Example: + +``` +--- +updated-by: EIP9999, EIP9998 +--- +``` + +### `updates` + +`updates` is reserved for EIPs updating EIPs in `active` status. An EIP listed as `updates` is implied to also be `requires`; only `updates` is needed for those EIP listings. Having an EIP listing `updates` does not necessarily mean that referenced EIP must reference back with an `updated-by` listing. + +`updates` should be included as an EIP header, as all EIP headers, and include a reference to an EIP designation. When multiple EIP designations are referenced, each should be separated by a comma. Example: + +``` +--- +updates: EIP1 +--- +``` + +## Rationale + + +`updates` and `updated-by` apply only to EIPs in `active` status as updates to EIPs in `final` status are already handled by EIP headers `superseded-by` and `replaces`. + +The syntax should align with previous EIP header syntax, as this EIP is not updating syntax, simply adding header options. + +## Backwards Compatibility + + +These EIP headers are optional and do not introduce compatibility issues. + + +## Implementation + + +An implementation is adding a header option. + +## Security Considerations + + +This standard is informational and does not introduce technical security issues. + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). + + diff --git a/EIPS/eip-2470.md b/EIPS/eip-2470.md new file mode 100644 index 0000000000000..50476d4cd9c1d --- /dev/null +++ b/EIPS/eip-2470.md @@ -0,0 +1,197 @@ +--- +eip: 2470 +title: Singleton Factory +author: Ricardo Guilherme Schmidt (@3esmit) +discussions-to: https://ethereum-magicians.org/t/erc-2470-singleton-factory/3933 +status: Draft +type: Standards Track +category: ERC +created: 15-01-2020 +requires: 1014 +--- + +## Simple Summary + +Some DApps needs one, and only one, instance of an contract, which have the same address on any chain. + +A permissionless factory for deploy of keyless deterministic contracts addresses based on its bytecode. + +## Abstract + +Some contracts are designed to be Singletons which have the same address no matter what chain they are, which means that should exist one instance for all, such as [EIP-1820] and [EIP-2429]. These contracts are usually deployed using a method known as [Nick]'s method, so anyone can deploy those contracts on any chain and they have a deterministic address. +This standard proposes the creation of a CREATE2 factory using this method, so other projects requiring this feature can use this factory in any chain with the same setup, even in development chains. + +## Motivation + +Code reuse, using the factory becomes easier to deploy singletons. + +## Specification + +### [ERC2470] Singleton Factory + +> This is an exact copy of the code of the [ERC2470 factory smart contract]. + +```solidity +pragma solidity 0.6.2; + + +/** + * @title Singleton Factory (EIP-2470) + * @notice Exposes CREATE2 (EIP-1014) to deploy bytecode on deterministic addresses based on initialization code and salt. + * @author Ricardo Guilherme Schmidt (Status Research & Development GmbH) + */ +contract SingletonFactory { + /** + * @notice Deploys `_initCode` using `_salt` for defining the deterministic address. + * @param _initCode Initialization code. + * @param _salt Arbitrary value to modify resulting address. + * @return createdContract Created contract address. + */ + function deploy(bytes memory _initCode, bytes32 _salt) + public + returns (address payable createdContract) + { + assembly { + createdContract := create2(0, add(_initCode, 0x20), mload(_initCode), _salt) + } + } +} +// IV is a value changed to generate the vanity address. +// IV: 6583047 +``` + +### Deployment Transaction + +Below is the raw transaction which MUST be used to deploy the smart contract on any chain. + +``` +0xf9016c8085174876e8008303c4d88080b90154608060405234801561001057600080fd5b50610134806100206000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c80634af63f0214602d575b600080fd5b60cf60048036036040811015604157600080fd5b810190602081018135640100000000811115605b57600080fd5b820183602082011115606c57600080fd5b80359060200191846001830284011164010000000083111715608d57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550509135925060eb915050565b604080516001600160a01b039092168252519081900360200190f35b6000818351602085016000f5939250505056fea26469706673582212206b44f8a82cb6b156bfcc3dc6aadd6df4eefd204bc928a4397fd15dacf6d5320564736f6c634300060200331b83247000822470 +``` + +The strings of `2470`'s at the end of the transaction are the `r` and `s` of the signature. +From this deterministic pattern (generated by a human), anyone can deduce that no one knows the private key for the deployment account. + +### 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: + +1. Generate a transaction which deploys the contract from a new random account. + - This transaction MUST NOT use [EIP-155] in order to work on any chain. + - This transaction MUST have a relatively high gas price to be deployed on any chain. In this case, it is going to be 100 Gwei. + +2. Forge a transaction with the following parameters: + ```js + { + nonce: 0, + gasPrice: 100000000000, + value: 0, + data: '0x608060405234801561001057600080fd5b50610134806100206000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c80634af63f0214602d575b600080fd5b60cf60048036036040811015604157600080fd5b810190602081018135640100000000811115605b57600080fd5b820183602082011115606c57600080fd5b80359060200191846001830284011164010000000083111715608d57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550509135925060eb915050565b604080516001600160a01b039092168252519081900360200190f35b6000818351602085016000f5939250505056fea26469706673582212206b44f8a82cb6b156bfcc3dc6aadd6df4eefd204bc928a4397fd15dacf6d5320564736f6c63430006020033', + gasLimit: 247000, + v: 27, + r: '0x247000', + s: '0x2470' + } + ``` + > The `r` and `s` values, made of starting `2470`, are obviously a human determined value, instead of a real signature. + +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 exactly 0.0247 ether to this single-use deployment account. + +5. Broadcast the deployment transaction. + + > Note: 247000 is the double of gas needed to deploy the smart contract, this ensures that future changes in OPCODE pricing are unlikely to cause this deploy transction to fail out of gas. A left over will sit in the address of about 0.01 ETH will be forever locked in the single use address. + +The resulting transaction hash is `0x803351deb6d745e91545a6a3e1c0ea3e9a6a02a1a4193b70edfcd2f40f71a01c`. + +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. + + +### Single-use Factory Deployment Account + +![](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAAB0UlEQVR4nO3asW1CQRBAQdpyCa6CIpxTjgujDGTJNEC2QqvjTbDx33c3P7vL79f1fzLf98dobn8/o5nuP53p/tPzm+5/AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4CMBnH6B0/23L2AbEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ8JYPsCtw+w3g9AvB+AeD8A8X4A4v0AxPsBiPcDEO8HIN4PQLwfgHg/APF+AOL9AMT7AYj3AxDvP/5ByOkApt/PvwgCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgJYDtA9w+gO0fYHsAAGB/CQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAdALYfNExnun+9H4B4PwDxfgDi/QDE+wGI9wMQ7wcg3g9AvB+AeD8A8X4A4v0AxPsBiPcDEO8HIN4/fhCy/aDidADb5wcAAGcHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAO8CsH2ApwPY/j4Ah+8PAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPB6nlegoDNgrfyiAAAAAElFTkSuQmCC) + +`0xBb6e024b9cFFACB947A71991E386681B1Cd1477D` + +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. + +> To deploy the registry, 0.0247 ether MUST be sent to this account *first*. + +### Factory Contract Address +![](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAABn0lEQVR4nO3coRECMRRF0S2GutCUQzd4WqAMLB4qQGWYP+EecXXeZo/OcTrf35Ndbq+l7F/rmB6w+wXuvh+A+H4A4vsBiO8HIL4fgPh+AOL7AYjvByC+H4D4fgDi+wGI7wcgvh+A+H4A4vuXAUxfwPX5GG33+wMAgL0/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPgGYHrA9A+cbhoQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wlgesD0+bvvXz0fgM33AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB8ATB9gZoNgHgAxAMgHgDxAIgHQDwA4gEQD4B4AMQDIB4A8QCIB0A8AOId0w8caK3V/wfA5gEQD4B4AMQDIB4A8QCIB0A8AOIBEA+AeADEAyAeAPEAiAdAPADiARAPgHgAxAMgHgDxAIgHQDwA4gEQD4B4AMQDIB4A8QCItwxg+oECDT8QMT1AAAgAASAABIAAEAACQAAIAAEgAASAANAv+gDxVDRR1CVqRAAAAABJRU5ErkJggg==) + +`0xce0042B868300000d44A59004Da54A005ffdcf9f` + +The contract has the address above for every chain on which it is deployed. +### ABI for SingletonFactory: +```json +[ + { + "constant": false, + "inputs": [ + { + "internalType": "bytes", + "name": "_initCode", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "_salt", + "type": "bytes32" + } + ], + "name": "deploy", + "outputs": [ + { + "internalType": "address payable", + "name": "createdContract", + "type": "address" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + } +] +``` + +## Rationale + +SingletonFactory does not allow sending value on create2, this was done to prevent different results on the created object. +SingletonFactory allows user defined salt to facilitate the creation of vanity addresses for other projects. If vanity address is not necessary, salt `bytes(0)` should be used. +Contracts that are constructed by the SingletonFactory MUST not use `msg.sender` in their constructor, all variables must came through initialization data. This is intentional, as if allowing a callback after creation to aid initialization state would lead to contracts with same address (but different chains) to have the same address but different initial state. +The resulting address can be calculated in chain by any contract using this formula: `address(keccak256(bytes1(0xff), 0xce0042B868300000d44A59004Da54A005ffdcf9f, _salt, keccak256(_code)) << 96)` or in javascript using https://github.com/ethereumjs/ethereumjs-util/blob/master/docs/README.md#const-generateaddress2. + +## Backwards Compatibility + +Does not apply as there are no past versions of Singleton Factory being used. + +## Test Cases + +TBD + +## Implementation + +https://github.com/3esmit/ERC2470 + +## Security Considerations + +Some contracts can possibly not support being deployed on any chain, or require a different address per chain, that can be safely done by using comparison in [EIP-1344] in constructor. +Account contracts are singletons in the point of view of each user, when wallets want to signal what chain id is intended, [EIP-1191] should be used. +Contracts deployed on factory must not use `msg.sender` in constructor, instead use constructor parameters, otherwise the factory would end up being the controller/only owner of those. + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). + +[EIP-155]: https://eips.ethereum.org/EIPS/eip-155 +[EIP-1191]: https://eips.ethereum.org/EIPS/eip-1191 +[EIP-1344]: https://eips.ethereum.org/EIPS/eip-1344 +[EIP-1820]: https://eips.ethereum.org/EIPS/eip-1820 +[EIP-2429]: https://gitlab.com/status-im/docs/EIPs/blob/secret-multisig-recovery/EIPS/eip-2429.md +[Nick's article]: https://medium.com/@weka/how-to-send-ether-to-11-440-people-187e332566b7 +[Nick]: https://github.com/Arachnid/ + diff --git a/EIPS/eip-2477.md b/EIPS/eip-2477.md index d95265867af15..fc843a66ddad6 100644 --- a/EIPS/eip-2477.md +++ b/EIPS/eip-2477.md @@ -32,10 +32,74 @@ Several token standards allow attaching metadata to specific tokens using a URI Although all these standards allow storing the metadata entirely on-chain (using the "data" URI, RFC 2397), or using a content-addressable system (e.g. IPFS's Content IDentifiers [sic]), nearly every implementation we have found is using Uniform Resource Locators (the exception is The Sandbox which uses IPFS URIs). These URLs provide no guarantees of content correctness or immutability. This standard adds such guarantees. +## Design + +**Approach A:** A token contract may reference metadata by using its URL. This provides no integrity protection because the referenced metadata and/or schema could change at any time if the hosted content is mutable. This is the world before EIP-2477: + +``` +┌───────────────────────┐ ┌────────┐ ┌────────┐ +│ TokenID │──────▶│Metadata│─────▶│ Schema │ +└───────────────────────┘ └────────┘ └────────┘ +``` + +Note: according to the JSON Schema project, a metadata document referencing a schema using a URI in the `$schema` key is a known approach, but it is not standardized. + +**Approach B:** EIP-2477 provides mechanisms to establish integrity for these references. In one approach, there is integrity for the metadata document. Here, the on-chain data includes a hash of the metadata document. The metadata may or may not reference a schema. In this approach, changing the metadata document will require updating on-chain `tokenURIIntegrity`: + +``` +┌───────────────────────┐ ┌────────┐ ┌ ─ ─ ─ ─ +│ TokenID │──────▶│Metadata│─ ─ ─▶ Schema │ +└───────────────────────┘ └────────┘ └ ─ ─ ─ ─ +┌───────────────────────┐ ▲ +│ tokenURIIntegrity │════════════╝ +└───────────────────────┘ +``` + +**Approach C:** In a stronger approach, the schema is referenced by the metadata using an extension to JSON Schema, providing integrity. In this approach, changing the metadata document or the schema will require updating on-chain `tokenURIIntegrity` and the metadata document, additionally changing the schema requires updating the on-chain `tokenURISchemaIntegrity`: + +``` +┌───────────────────────┐ ┌────────┐ ┌────────┐ +│ TokenID │──────▶│Metadata│═════▶│ Schema │ +└───────────────────────┘ └────────┘ └────────┘ +┌───────────────────────┐ ▲ +│ tokenURIIntegrity │════════════╝ +└───────────────────────┘ +``` + +**Approach D:** Equally strong, the metadata can make a normal reference (no integrity protection) to the schema and on-chain data also includes a hash of the schema document. In this approach, changing the metadata document will require updating on-chain `tokenURIIntegrity` and updating the schema document will require updating the `tokenURISchemaIntegrity`: + +``` +┌───────────────────────┐ ┌────────┐ ┌────────┐ +│ TokenID │──────▶│Metadata│─────▶│ Schema │ +└───────────────────────┘ └────────┘ └────────┘ +┌───────────────────────┐ ▲ ▲ +│ tokenURIIntegrity │════════════╝ ║ +└───────────────────────┘ ║ +┌───────────────────────┐ ║ +│tokenURISchemaIntegrity│════════════════════════════╝ +└───────────────────────┘ +``` + +**Approach E:** Lastly, the schema can be referenced with integrity from the metadata and also using on-chain data. In this approach, changing the metadata document or the schema will require updating on-chain `tokenURIIntegrity` and the metadata document, additionally changing the schema requires updating the on-chain `tokenURISchemaIntegrity`: + +``` +┌───────────────────────┐ ┌────────┐ ┌────────┐ +│ TokenID │──────▶│Metadata│═════▶│ Schema │ +└───────────────────────┘ └────────┘ └────────┘ +┌───────────────────────┐ ▲ ▲ +│ tokenURIIntegrity │════════════╝ ║ +└───────────────────────┘ ║ +┌───────────────────────┐ ║ +│tokenURISchemaIntegrity│════════════════════════════╝ +└───────────────────────┘ +``` + ## Specification The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119. +### Smart contracts + **Smart contracts implementing the ERC-2477 standard MUST implement the `ERC2477` interface.** ```solidity @@ -48,16 +112,16 @@ interface ERC2477 /* is ERC165 */ { /** * @notice Get the cryptographic hash of the specified tokenID's metadata * @param tokenId Identifier for a specific token - * @return digest Bytes returned from the hash algorithm - * @return hashAlgorithm The name of the cryptographic hash algorithm + * @return digest Bytes returned from the hash algorithm, or "" if not available + * @return hashAlgorithm The name of the cryptographic hash algorithm, or "" if not available */ function tokenURIIntegrity(uint256 tokenId) external view returns(bytes memory digest, string memory hashAlgorithm); /** * @notice Get the cryptographic hash for the specified tokenID's metadata schema * @param tokenId Id of the Xcert. - * @return digest Bytes returned from the hash algorithm or "" if there is no schema - * @return hashAlgorithm The name of the cryptographic hash algorithm or "" if there is no schema + * @return digest Bytes returned from the hash algorithm, or "" if not available + * @return hashAlgorithm The name of the cryptographic hash algorithm, or "" if not available */ function tokenURISchemaIntegrity(uint256 tokenId) external view returns(bytes memory digest, string memory hashAlgorithm); } @@ -67,7 +131,7 @@ The returned cryptographic hashes correspond to the token's metadata document an For example, with ERC-721 `tokenURIIntegrity(21)` would correspond to `tokenURI(21)`. With ERC-1155, `tokenURIIntegrity(16)` would correspond to `uri(16)`. In both cases, `tokenURISchemaIntegrity(32)` would correspond to the schema of the document matched by `tokenURIIntegrity(32)`. -**Smart contracts implementing the ERC-2477 standard MUST implement the ERC-165 standard, including the interface identifier above.** +**Smart contracts implementing the ERC-2477 standard MUST implement the ERC-165 standard, including the interface identifiers above.** Smart contracts implementing the ERC-2477 standard MAY use any hashing or content integrity scheme. @@ -75,7 +139,45 @@ Smart contracts implementing the ERC-2477 standard MAY use or omit a mechanism t Smart contracts implementing the ERC-2477 standard MAY use any mechanism to provide schemas for metadata documents and SHOULD use JSON-LD on the metadata document for this purpose (i.e. `"@schema":...`). -A client implementing the ERC-2477 standard MUST support at least the `sha256` hash algorithm and MAY support other algorithm. +### Metadata + +A metadata document MAY use this schema to provide referential integrity to its schema document. + +```json +{ + "title": "EIP-2477 JSON Object With Refererential Integrity to Schema", + "type": "object", + "properties": { + "$schema": { + "type": "string", + "format": "uri" + }, + "$schemaIntegrity": { + "type": "object", + "properties": { + "digest": { + "type": "string" + }, + "hashAlgorithm": { + "type": "string" + } + }, + "required": [ + "digest", + "hashAlgorithm" + ] + } + }, + "required": [ + "$schema", + "$schemaIntegrity" + ] +} +``` + +### Clients + +A client implementing the ERC-2477 standard MUST support at least the `sha256` hash algorithm and MAY support other algorithms. ### Caveats @@ -210,9 +312,14 @@ Other standards 6. Uniform Resource Identifier (URI): Generic Syntax. https://tools.ietf.org/html/rfc3986 7. CID [Specification] (DRAFT). https://github.com/multiformats/cid +Discussion + +1. JSON-LD discussion of referential integrity. https://lists.w3.org/Archives/Public/public-json-ld-wg/2020Feb/0003.html +2. JSON Schema use of `$schema` key for documents. https://github.com/json-schema-org/json-schema-spec/issues/647#issuecomment-417362877 + Other -1. [Shattered] The first collision for full SHA-1. http://shattered.io/static/shattered.pdf +1. [Shattered] The first collision for full SHA-1. https://shattered.io/static/shattered.pdf 2. [320 byte file] The second SHA Collision. https://privacylog.blogspot.com/2019/12/the-second-sha-collision.html 3. [Chosen prefix] https://sha-mbles.github.io 4. Transitions: Recommendation for Transitioning the Use of Cryptographic Algorithms and Key Lengths. (Rev. 1. Superseded.) https://csrc.nist.gov/publications/detail/sp/800-131a/rev-1/archive/2015-11-06 diff --git a/EIPS/eip-2481.md b/EIPS/eip-2481.md new file mode 100644 index 0000000000000..bc989b0f81649 --- /dev/null +++ b/EIPS/eip-2481.md @@ -0,0 +1,166 @@ +--- +eip: 2481 +title: "eth/66: request identifier" +author: Christoph Burgdorf +discussions-to: https://github.com/ethereum/EIPs/issues/2482 +status: Draft +type: Standards Track +category: Networking +created: 2020-01-17 +requires: 2464 +--- + + + +## Simple Summary + +This document proposes a way to increase the efficiency of the `eth` networking protocol while at the same time reducing complexity in Ethereum node implementations. It does so by introducing a request id to all requests which their corresponding responses must include. + +## Abstract + +The `eth` protocol defines various request and response commands that are used to exchange data between Ethereum nodes. For example, to ask a peer node for a specific set of headers, a node sends it the [`GetBlockHeaders`](https://github.com/ethereum/devp2p/blob/master/caps/eth.md#getblockheaders-0x03) command. + +*Citing from the [`GetBlockHeaders` spec definition](https://github.com/ethereum/devp2p/blob/master/caps/eth.md#getblockheaders-0x03):* + +>`[block: {P, B_32}, maxHeaders: P, skip: P, reverse: P in {0, 1}]` + +>Require peer to return a `BlockHeaders` message. Reply must contain a number of block +headers, of rising number when `reverse` is `0`, falling when `1`, `skip` blocks apart, +beginning at block `block` (denoted by either number or hash) in the canonical chain, and +with at most `maxHeaders` items. + +The node that receives the `GetBlockHeaders` command should answer it with the [`BlockHeaders`](https://github.com/ethereum/devp2p/blob/master/caps/eth.md#blockheaders-0x04) response command accordingly. + +*Citing from the [`BlockHeaders` spec definition](https://github.com/ethereum/devp2p/blob/master/caps/eth.md#blockheaders-0x04):* + +>`[blockHeader_0, blockHeader_1, ...]` + +>Reply to `GetBlockHeaders`. The items in the list (following the message ID) are block +headers in the format described in the main Ethereum specification, previously asked for +in a GetBlockHeaders message. This may validly contain no block headers if none of the +requested block headers were found. The number of headers that can be requested in a +single message may be subject to implementation-defined limits. + +Let's consider a client making many simultaneous requests for `GetBlockHeaders` to one of its peers. By nature it can not be guaranteed that the expected responses arrive in the same order as they were sent. For the client to associate the incoming responses to the correct requests it has to loop through all pending requests trying to match it with the incoming response based on its contents. + +This can be particular tricky for responses that are ambiguous such as empty responses. + +This EIP proposes to change the `GetBlockHeaders` and the `BlockHeaders` command to include a `request_id` as shown below. + +* `GetBlockHeaders (0x03)` + * **Current (eth/65):** `[block: {P, B_32}, maxHeaders: P, skip: P, reverse: P in {0, 1}]` + * **Then (eth/66)**: `[request_id: P, [block: {P, B_32}, maxHeaders: P, skip: P, reverse: P in {0, 1}]]` +* `BlockHeaders (0x04)` + * **Current (eth/65):** `[blockHeader_0, blockHeader_1, ...]` + * **Then (eth/66)**: `[request_id: P, [blockHeader_0, blockHeader_1, ...]]` + +The `request_id` is a 64-bit integer set by the client when it makes the request. On the responding side, the exact same `request_id` from the incoming request is put back into the response object. + +This change allows the requesting client to match incoming responses **directly** back to their pending requests without going through all of the pending requests to check if they might match based on the response data. + +The selected request/response pair serves as an example for many similar request/response pairs in the `eth` networking protocol. + +## Motivation + +The lack of request identifiers in the request / response paris of the `eth` protocol puts unnecessary burden of code complexity into every Ethereum client. It also makes the communication slightly less efficient. Another argument can be made that the addition of request identifiers makes the protocol more aligned with the `les` protocol which **does** already defines request identifiers for each request / response pair. + +## Specification + + +Change the following message types in the `eth` protocol: + +* `GetBlockHeaders (0x03)` + * **Current (eth/65):** `[block: {P, B_32}, maxHeaders: P, skip: P, reverse: P in {0, 1}]` + * **Then (eth/66)**: `[request_id: P, [block: {P, B_32}, maxHeaders: P, skip: P, reverse: P in {0, 1}]]` +* `BlockHeaders (0x04)` + * **Current (eth/65):** `[blockHeader_0, blockHeader_1, ...]` + * **Then (eth/66)**: `[request_id: P, [blockHeader_0, blockHeader_1, ...]]` +* `GetBlockBodies (0x05)` + * **Current (eth/65):** `[hash_0: B_32, hash_1: B_32, ...]` + * **Then (eth/66)**: `[request_id: P, [hash_0: B_32, hash_1: B_32, ...]]` +* `GetPooledTransactions (0x09)`: + * **Current (eth/65)**`[hash_0: B_32, hash_1: B_32, ...]` + * **Then (eth/66)**`[request_id: P, [hash_0: B_32, hash_1: B_32, ...]]` +* `PooledTransactions (0x0a)`: + * **Current (eth/65)**`[[nonce: P, receivingAddress: B_20, value: P, ...], ...]` + * **Then (eth/66)**`[request_id: P, [[nonce: P, receivingAddress: B_20, value: P, ...], ...]]` +* `BlockBodies (0x06)` + * **Current (eth/65):** `[hash_0: B_32, hash_1: B_32, ...]` + * **Then (eth/66)**: `[request_id: P, [hash_0: B_32, hash_1: B_32, ...]]` +* `GetNodeData (0x0d)` + * **Current (eth/65):** `[hash_0: B_32, hash_1: B_32, ...]` + * **Then (eth/66)**: `[request_id: P, [hash_0: B_32, hash_1: B_32, ...]]` +* `NodeData (0x0e)` + * **Current (eth/65):** `[value_0: B, value_1: B, ...]` + * **Then (eth/66)**: `[request_id: P, [value_0: B, value_1: B, ...]]` +* `GetReceipts (0x0f)` + * **Current (eth/65):** `[blockHash_0: B_32, blockHash_1: B_32, ...]` + * **Then (eth/66)**: `[request_id: P, [blockHash_0: B_32, blockHash_1: B_32, ...]]` +* `Receipts (0x10)` + * **Current (eth/65):** `[[receipt_0, receipt_1], ...]` + * **Then (eth/66)**: `[request_id: P, [[receipt_0, receipt_1], ...]]` + + +To elaborate, each command is altered in the following way: + +1. Create a list with the `request_id` being the first element. +2. Make the second element the list that defines the whole command in the current scheme. + +This is consistent with the request / response pairs in the `les` protocol. + +The ``request_id`` has the following characteristics: + +* 64 bit integer +* Doesn't need to be sequential (can be random) +* Does allow duplicates + +## Rationale + + +**Q: The efficiency gains might encourage clients to flood their peers with too many simultaneous requests** + +Peers can always throttle or disconnect if they don't feel treated well. This is the same as today. + +**Q: If `les` already defines the commands like this, why not just use the `les` protocol?** + +In practice, peers that serve the `les` protocol are much harder to find in the network. The reasons for this are varied but might boil down to client defaults, immature implementations or missing incentives. + +**Q: Networking works today, isn't this just adding bloat?** + +This is adding a single integer per command while at the same time reducing code complexity and improving networking efficiency. The addition seems justified. + +**Q: Why not demand request ids to be sequential?** + +Assuming request ids start always to count from `0` upon connection, things will become messy when +connections are lost and clients reconnect and start over with the same request ids that they had used +in the previous session. + +**Q: Why allow duplicate request ids?** + +The main benefit is flexibility and simplicity on the implementation side. Clients could decide to share +the same ids across multiple different request types since they are naturally separated anyway. Clients +could even decide to not rely on request ids at all, therefore using the same constant request id across +all requests. + +**Q: Why choose a 64-bit integer for the request ids** + +64-bit integer were chosen to keep compatibility with the `les` protocol. + +## Backwards Compatibility + +This EIP extends the `eth` protocol in a backwards incompatible way and requires rolling out a new version, `eth/66`. However, `devp2p` supports running multiple versions of the same wire protocol side-by-side, so rolling out `eth/66` does not require client coordination, since non-updated clients can keep using `eth/65`. + +This EIP does not change the consensus engine, thus does *not* require a hard fork. + +## Implementation + + +Trinity has a [draft PR](https://github.com/ethereum/trinity/pull/1672) with an implementation. + +## Security Considerations + + +None + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-2515.md b/EIPS/eip-2515.md new file mode 100644 index 0000000000000..ef482e672a1b4 --- /dev/null +++ b/EIPS/eip-2515.md @@ -0,0 +1,99 @@ +--- +eip: 2512 +title: Implement Difficulty Freeze +author: James Hancock (@madeoftin) +discussions-to: https://ethereum-magicians.org/t/eip-2515-replace-the-difficulty-bomb-with-a-difficulty-freeze/3995 +status: Draft +type: Standards Track +category: Core +created: 2020/02/10 +requires (*optional): +replaces (*optional): +--- + + +## Simple Summary + +The difficulty Freeze is an alternative to the Difficulty Bomb that is implemented within the protocols difficulty adjustment algorithm. The Difficulty Freeze begins at a certain block height, determined in advance, freezes the difficulty and increases by 1% after that block forever. This does not stop the chain, but it incentivizes devs to upgrade at a regular cadence and requires any chain split to address the difficulty freeze. + +## Abstract + +The difficulty Freeze is a mechanism that is easy to predict and model, and the pressures of missing it are more readily felt by the core developers and client maintainers. The client maintainers are also positioned as the group that is most able to respond to an incoming Difficulty Freeze. This combined with the predictability is more likely to lead to the timely diffusual of the bomb. + + +## Motivation + +The current difficulty bombs' effect on the Block Time Targeting mechanism is rather complex to model, and it has both appeared when it was not expected (Muir Glacier) and negatively affected miners when they are not the target (in the case of delaying forks due to technical difficulties). Miners are affected by a reduction in block rewards due to the increase in block time. Users are affected as a function of the usability of the chain is affected by increased block times. Both of these groups are unable on their own to address the difficulty bomb. In the case of the Difficulty Freeze, the consequences of missing it are more directly felt by the client maintainers and it is more predictiable and so knowing when to make the change is readily apparent. + +## Specification + +Add variable `DIFFICULTY_FREEZE_HEIGHT` + + +The logic of the Difficulty Freeze is defined as follows: + +``` +if (BLOCK_HEIGHT <= DIFFICULTY_FREEZE_HEIGHT): + block_diff = parent_diff + parent_diff // 2048 * max( + 1 - (block_timestamp - parent_timestamp) // 10, -99) + +else: + block_diff = parent_diff + parent_diff * 0.01 +``` + +**Optional Implementation** + +Add the variable `DIFFICULTY_FREEZE_DIFFERENCE` and use the `LAST_FORK_HEIGHT` to calculate when the Difficulty Freeze would occur. + +For example we can set the `DFD = 1,800,000 blocks` or approximately 9 months. The Difficulty Calculation would then be. + +``` +if (BLOCK_HEIGHT <= LAST_FORK_HEIGHT + DIFFICUTLY_FREEZE_DIFFERENCE) : + block_diff = parent_diff + parent_diff // 2048 * max( + 1 - (block_timestamp - parent_timestamp) // 10, -99) + +else: + block_diff = parent_diff + parent_diff * 0.01 +``` + +This approach would have the added benefit that updating the Difficulty Freeze is easier as it happens automatically at the time of every upgrade. The trade-off is that the logic for checking is more complex and would require further analysis and test cases to ensure no consensus bugs arise. + +## Rationale + +Block height is very easy to predict and evaluate within the system. This removes the effect of the Difficulty Bomb on block time, simplifying the block time targeting mechanism. The addition of an increase in the difficulty was added after feedback that the game theory of the mechanism did not reliably result in . + +https://twitter.com/quentinc137/status/1227110578235330562 + +## Backwards Compatibility + +No backward incompatibilities + +## Test Cases + +TBD + +## Implementation + +TBD + +## Security Considerations + +The effect of missing the Difficulty Freeze has a different impact than missing the Difficulty Bomb. At the point of a Difficulty freeze, the protocol is no longer able to adapt to changes in hash power on the network. This can lead to one of three scenarios. + + - The Hash rate Increases: + Block Times would increase on the network for short time until the increase in difficulty is too high for the network to add any more miners. + - The Hash rate decreases: + Block times would increase. + - The Hash rate stays the same: + A consistent increase in blocktimes. + +Clients are motivated to have their client sync fully to the network and so are very motivated to keep this situation from occurring. Simultaneously delaying the Difficulty Freeze is most easily implemented by client teams. Therefore the group that is most negatively affected is also the group that can most efficiently address it. + +## Economic Considerations + +Under the current Difficult, Bomb issuance of ETH is reduced as the Ice Age takes affect. Under the Difficulty Freeze, it is more likely that issuance would increase for a short time; however, clients are motivated to prevent this and keep clients syncing effectively. This means it is much less likely to occur. The increase to the difficulty over time will eventually reduce blocktimes and also issuance. + +It is also easy to predict when this change would happen, and stakeholders who are affected (Eth Holders) can keep client developers accountable by observing when the Difficulty Freeze is approaching and yell at them on twitter. + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-2525.md b/EIPS/eip-2525.md new file mode 100644 index 0000000000000..1e323b837e4d6 --- /dev/null +++ b/EIPS/eip-2525.md @@ -0,0 +1,171 @@ +--- +eip: 2525 +title: ENSLogin +author: Hadrien Croubois (@amxx) +discussions-to: https://ethereum-magicians.org/t/discussion-ens-login/3569 +status: Draft +type: Standards Track +category: ERC +created: 19/02/2020 +requires: 137, 634, 1193, 2304 +--- + +## 1. Abstract + +This presents a method to improve a universal method of login to the ethereum blockchain, leveraging the metadata storage provided by the ENS. We consider a user to be logged in when we have an [EIP 1193](https://eips.ethereum.org/EIPS/eip-1193) provider that can sign transaction and messages on his behalf. This method is inspired by [Alex Van de Sande's work](https://www.youtube.com/watch?v=1LVwWknE-NQ) and [Web3Connect](https://web3connect.com). In the future, the approach described here-after should be extended to work with any blockchain. + +## 2. Motivation + +Multiple wallet solutions can be used to interact with the Ethereum blockchain. Some (metamask, gnosis, ...) are compatible as they inject a standardized wallet object in the browser without requiring any effort from the Dapp developers, but they require an effort on the user side (user has to install the plugin). Other solutions (Portis, Authereum, Torus, Universal Login, ...) propose a more seamless flow to non-crypto-aware users but require an integration effort from the Dapp developers. Hardware wallet (ledger, trezor, keepkey, ...) also require integration effort from the Dapp developers. + +When Dapps integrate login with multiple solutions, they rely on the user choosing the correct wallet-provider. This could prove increasingly difficult as the number of wallet-provider increases, particularly for novice users. Additionally, if decentralized applications pick and choose only a handful of wallets to support, the current incumbent wallets will have a distinct advantage and new wallets will struggle to find adoption. This will create a less competitive environment and stifle innovation. Rather than relying on the user choosing which wallet-provider to connect with (as does Web3Connect), ENSLogin proposes to use user-owned ENS domain as entry points. Metadata attached to these ENS domains is used to detect which wallet-provider if used by the corresponding account. + +That way, ENSLogin would allow any user to connect to any Dapp with any wallet, using a simple domain as a login. + +## 3. Description + +### 3.1. Overview + +The ENSLogin works as follow: + +* Request an ENS domain from the user +* Resolve the ENS domain to retrieve (see [EIP 137](https://eips.ethereum.org/EIPS/eip-20)) + * An address (see [EIP 137](https://eips.ethereum.org/EIPS/eip-20)) + * A text entry (see [EIP 634](https://eips.ethereum.org/EIPS/eip-634)) +* Interpret the text entry and download the file it points to +* Evaluate the content of the downloaded file +* Return the corresponding object to the Dapp + +At this point, the app should process like with any web3 provider. Calling the `enable()` functions should ask the users for wallet specific credentials is needed. + +This workflow is to be implemented by an SDK that Dapp could easily import. The SDK would contain the resolution mechanism and support for both centralized and decentralized storage solution. Wallet-provider specific code should NOT be part of SDK. Wallet-provider specific code should only be present in the external file used to generate the web3 provider. + +### 3.2. Details + +* **Text entry resolution:** A pointer to the code needed to instantiate the wallet-provider is recorded using the ENS support for text entries (see [EIP 634](https://eips.ethereum.org/EIPS/eip-634)). The corresponding key is `enslogin` (**subject to change**). If no value is associated with the key `enslogin` at the targeted domain, we fallback to metadata store on the parent's node with the key `enslogin-default` (**subject to change**). +**Example:** for the ens domain `username.domain.eth`, the resolution would look for (in order): + * `resolver.at(ens.owner(nodehash("username.domain.eth"))).text(nodehash("username.domain.eth"), 'enslogin')` + * `resolver.at(ens.owner(nodehash("domain.eth"))).text(nodehash("domain.eth"), 'enslogin-default')` + +* **Provider link:** Code for instantiating the wallet-provider must be pointed to in a standardized manner. **This is yet not specified.** The current approach uses a human-readable format `scheme://path` such as: + + * `ipfs://Qm12345678901234567890123456789012345678901234` + * `https://server.com/enslogin-module-someprovider` + + And adds a suffix depending on the targeted blockchain type (see [SLIP 44](https://github.com/satoshilabs/slips/blob/master/slip-0044.md)) and language. Canonical case is a webapp using ethereum so the target would be: + + * `ipfs://Qm12345678901234567890123456789012345678901234/60/js` + * `https://server.com/enslogin-module-someprovider/60/js` + + Note that this suffix mechanism is compatible with http/https as well as IPFS. It is a constraint on the storage layer as some may not be able to do this kind of resolution. + +* **Provider instantiation:** + * [JAVASCRIPT/ETHEREUM] The file containing the wallet-provider's code should inject a function `global.provider: (config) => Promise` that returns a promise to a standardized provider object. For EVM blockchains, the object should follow [EIP 1193](https://eips.ethereum.org/EIPS/eip-1193). + * Other blockchain types/langages should be detailed in the future. + + +* **Configuration object:** In addition to the username (ENS domain), the Dapp should have the ability to pass a configuration object that could be used by the wallet-provider instantiating function. This configuration should include: + * A body (common to all provider) that specify details about the targeted chain (network name / node, address of the ens entrypoint ...). If any of these are missing, a fallback can be used (mainnet as a default network, bootstrapping an in-browser IPFS node, ...). + * Wallet provider-specific fields (**optional**, starting with one underscore `_`) can be added to pass additional, wallet-provider specific, parameters / debugging flags. + * SDK specific fields (**optional**, starting with two underscores `__`) can be used to pass additional arguments. + + Minimal configuration: + ``` + { + provider: { + network: 'goerli' + } + } + ``` + Example of advanced configuration object: + ``` + { + provider: { + network: 'goerli', + ens: '0x112234455c3a32fd11230c42e7bccd4a84e02010' + }, + ipfs: { + host: 'ipfs.infura.io', + port: 5001, + protocol: 'https' + }, + _authereum: {...}, + _portis: {...}, + _unilogin: {...}, + _torus: {...}, + __callbacks: { + resolved: (username, addr, descr) => { + console.log(`[CALLBACKS] resolved: ${username} ${addr} ${descr}`); + }, + loading: (protocol, path) => { + console.log(`[CALLBACKS] loading: ${protocol} ${path}`); + }, + loaded: (protocol, path) => { + console.log(`[CALLBACKS] loaded: ${protocol} ${path}`); + } + } + } + ``` + +**TODO** *(maybe move that part to section 6.1)*: +Add [SLIP 44](https://github.com/satoshilabs/slips/blob/master/slip-0044.md) compliant blockchain description to the config for better multichain support. This will require a additional field `ENS network` to know which ethereum network to use for resolution when the targeted blockchain/network is not ethereum (could also be used for cross chain resolution on ethereum, for example xDAI login with metadata stored on mainnet) + +### 3.3. Decentralization + +Unlike solution like Web3Connect, ENSLogin proposes a modular approach that is decentralized by nature. +The code needed for a Dapp to use ENSLogin (hereafter referred to as the SDK) only contains lookup mechanism for the ethereum blockchain and the data storages solutions. The solution is limited by the protocols (https / ipfs / ...) that the SDK can interact with. Beyond that, any wallet-provider that follows the expected structure and that is available through one of the supported protocol is automatically compatible with all the Dapps proposing ENSLogin support. There is no need to go through a centralized approval process. Furthermore, deployed SDK do not need to be upgraded to benefit from the latest wallet updates. The only permissioned part of the protocol is in the ENS control of the users over the metadata that describes their wallet-provider implementation. Users could also rely on the fallback mechanism to have the wallet-provider update it for them. + +### 3.4. Incentives + +We believe ENSLogin's biggest strength is the fact that it aligns the incentives of Dapp developers and wallet-providers to follow this standard. + +* A wallet-provider that implements the required file and make them available will ensure the compatibility of its wallet with all Dapps using ENSLogin. This will remove the burden of asking all Dapps to integrate their solutions, which Dapps are unlikely to do until the wallet as strong userbase. Consequently, ENSLogin will improve the competition between wallet-providers and encourage innovation in that space +* A Dapp that uses ENSLogin protocol, either by including the ENSLogin's SDK or by implementing compatible behaviour, will make itself available to all the users of all the compatible wallet. At some point, being compatible with ENSLogin will be the easiest to reach a large user-base. +* ENSLogin should be mostly transparent for the users. Most wallet provider will set up the necessary entries without requiring any effort from the user. Advanced users can take control over the wallet resolution process, which will be simple once the right tooling is available. + +### 3.5. Drawbacks + +While ENSLogin allows dapps to support any wallet for logging in, dapps still must choose which wallets they suggest to users for registration. This can be done through a component like Web3Connect or BlockNative's + +## 4. Prototype + +**TODO** + +## 5. Support by the community + +### 5.1. Adoption + +| Name | Live | Module | Assigns ENS names | support by default | +| -------------- | ---- | ------ | ----------------- | ------------------ | +| Argent | yes | no | yes | no | +| Authereum | yes | yes | yes | no | +| Fortmatic | yes | no | no | no | +| Gnosis Safe | yes | yes\* | no | no | +| Ledger | yes | beta | no | no | +| KeepKey | yes | no | no | no | +| Metamask | yes | yes | no | no | +| Opera | yes | yes\* | no | no | +| Portis | yes | yes | no | no | +| SquareLink | yes | no | no | no | +| Shipl | no | no | no | no | +| Torus | yes | yes | no | no | +| Trezor | yes | no | no | no | +| UniLogin | beta | beta | yes | no | + +\*use the metamask module + +## 6. Possible evolutions + +### 6.1. Multichain support + +**TODO** + +## 7. FAQ + +### 7.1. Can anyone connect with my login? Where are my private keys stored? + +ENSLogin only has access to what is recorded on the ENS, namely your address and the provider you use. Private key management is a is handled by the provider and is outside ENSLogin's scope. Some might store the key on disk. Other might rely on custodial keys stored on a remote (hopefully secure) server. Others might use a dedicated hardware component to handle signature and never directly have access to the private key. + +### 7.2. How do I get an ENS Login? + +**TODO** (this might need a separate ERC) diff --git a/EIPS/eip-2542.md b/EIPS/eip-2542.md new file mode 100644 index 0000000000000..dba63d4197b88 --- /dev/null +++ b/EIPS/eip-2542.md @@ -0,0 +1,93 @@ +--- +eip: 2542 +title: New opcodes TXGASLIMIT and CALLGASLIMIT +author: Alex Forshtat +discussions-to: https://ethereum-magicians.org/t/eip-2542-add-txgaslimit-callgaslimit-txgasrefund-opcodes +status: Draft +type: Standards Track +category: Core +created: 2020-02-29 +--- + + + +## Simple Summary + +A mechanism to allow smart contracts to access information on gas limits for the current transaction and execution frame. + +## Abstract +Currently, there is an existing opcode `0x45 GASLIMIT` that provides access to the block gas limit. While this information may be useful in some cases, it is probably not a value that smart contract developers may be concerned about. The opcode `0x5a GAS` provides the remaining gas, not the initial one. Also, it is worth noting how existing `0x32 ORIGIN`, `0x33 CALLER`, `0x34 CALLVALUE` and `0x3a GASPRICE` opcodes set a pattern of having access to both the transaction and current execution frame state. +TBD: as 0x30 opcode range is exhausted, the proposed opcodes can be added to 0x50 range, or a new range can be added. + +## Motivation + +As concepts of relaying, meta-transactions, gas fees, and account abstraction gain popularity, it becomes critical for some contracts to be able to track gas expenditure with absolute precision. Without access to this data on an EVM level, such contracts resort to approximation, mimicking EVM logic on-chain, and some use-cases even become infeasible. + +## Specification +If block.number >= TBD, add three new opcodes: + +TXGASLIMIT: 0x5c + +Pushes the gas limit of the entire transaction onto the stack. This is a value of the 'startgas' parameter signed by the externally owned account. +Gas costs: 2 (same as `GASLIMIT`) + +CALLGASLIMIT: 0x5d + +Pushes the gas limit of the current execution frame onto the stack. This is the 'callGas' value that was obtained after the application of the EIP-150 “all but one 64th” rule. +Gas costs: 2 (same as `GASLIMIT`) + +Also, consider renaming `0x45 GASLIMIT` to `BLOCKGASLIMIT` to avoid confusion. + +## Rationale + +Consider a solidity smart contract that wants to know how much gas the entire transaction or a part of it had consumed. It is not entirely possible with the current EVM. With proposed changes, using a pseudo-Solidity syntax, this information would be easily available: +``` +function keepTrackOfGas(string memory message, uint256 number) public { + ... + uint gasUsed = msg.gasLimit - gasleft(); +} +``` +This is an extremely common use case, and multiple implementations suffer from not taking the non-accessible expenses into consideration. The state-of-the-art solution for the `gasUsed` problem is to access 'gasleft()' as the first line of your smart contract. +Note how variable transaction input size means the gas used by the transaction depends on the number of zero and non-zero bytes of input, as well `GTXDATANONZERO`. Another issue is that Solidity handles `public` methods by loading the entire input from `calldata` to `memory`, spending an unpredictable amount of gas. + +Another application is for a method to have a requirement for a gas limit given to it. This situation arises quite commonly in the context of meta-transactions, where the msg.sender's account holder may not be too interested in the inner transaction's success. Exaggerated pseudocode: + +``` +function verifyGasLimit(uint256 desiredGasLimit, bytes memory signature, address signer, bytes memory someOtherData) public { + require(ecrecover(abi.encodePacked(desiredGasLimit, someOtherData), signature) == signer, "Signature does not match"); + require(tx.gasLimit == desiredGasLimit, "Transaction limit does not match the signed value. The signer did not authorize that."); + ... +} +``` +In this situation it is not possible to rely on 'gasleft()' value, because it is dynamic, depends on opcode and calldata pricing, and cannot be signed. + + +## Backwards Compatibility +This proposal introduces two new opcodes and renames an existing one, but stays fully backwards compatible apart from that. + +## Forwards Compatibility +A major consideration for this proposal is its alignment with one or many possible future modifications to the EVM: + +1. EIP-2489 Deprecate the GAS opcode (a.k.a. 39-UNGAS proposal) + There is a sentiment that the ability of smart contracts to perform "gas introspection" leads to the contracts being dependent on current opcode pricing. + While criticizing said misconception is beyond the scope of this EIP, in case there is a need to make a breaking change to the behavior of the existing `0x5a GAS` opcode, the same considerations will apply to the proposed opcodes. This means this EIP does not add any new restraints on EMV evolution. + +2. Stateless Ethereum + The UNGAS proposal is said to be related to the ongoing project of Stateless Ethereum. It’s not strictly necessary for stateless Ethereum, but it is an idea for how to make future breaking changes to gas schedules easier. + As long as the concept of 'gas limit' is part of the EVM, the author sees no reason proposed opcodes would conflict with Stateless Ethereum. Gas schedules are not exposed by this proposal. + +3. Comparison with other controversial opcodes + There are opcodes that are not proposed for deprecation but face criticism. Examples include `0x32 ORIGIN` being misused by smart contract developers, or `0x46 CHAINID` making some smart-contracts 'unforkable'. + This EIP neither encourages nor enables any bad security practices, and does not introduce any concepts that are new for EVM either. + +## Security considerations + +Existing smart contracts are not affected by this change. +Smart contracts that will use proposed opcodes must not use them for the core of any security features, but only as a source of information about their execution environment. + +## Implementation + +The implementations must be completed before any EIP is given status "Final", but it need not be completed before the EIP is accepted. While there is merit to the approach of reaching consensus on the specification and rationale before writing code, the principle of "rough consensus and running code" is still useful when it comes to resolving many discussions of API details. + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-2544.md b/EIPS/eip-2544.md new file mode 100644 index 0000000000000..46d971fc6f3c0 --- /dev/null +++ b/EIPS/eip-2544.md @@ -0,0 +1,110 @@ +--- +eip: 2544 +title: ENS Wildcard Resolution +author: Nick Johnson (@arachnid), 0age (@0age) +discussions-to: https://ethereum-magicians.org/t/eip-2544-ens-wildcard-resolution +status: Draft +type: Standards Track +category: ERC +created: 2020-02-28 +requires: 137 +--- + +## Simple Summary + +EIP-2544 extends ENS client behavior to support "wildcard" resolution of subdomains. This is accomplished by using a parent domain's resolver if none is set on a given subdomain. + +## Abstract + +The Ethereum Name Service Specification (EIP-137) establishes a two-step name resolution process. First, an ENS client takes a provided name, performs the namehash algorithm to determine the associated "node", and supplies that node to the ENS Registry contract to determine the resolver. Then, if a resolver has been set on the Registry, the client supplies that same node to the resolver contract, which will return the associated address or other record. + +As currently specified, this process terminates if a resolver is not set on the ENS Registry for a given node. This EIP extends the existing name resolution process by adding an additional step if a resolver is not set for subdomain. This step strips out the leftmost label from the name, derives the node of the new fragment, and supplies that node to the ENS Registry. If a resolver is located for that node, the client supplies the original, complete node to that resolver contract to derive the relevant records. + +## Motivation + +Many applications such as wallet providers, exchanges, and dapps have expressed a desire to issue ENS names for their users via custom subdomains on a shared parent domain. However, the cost of doing so is currently prohibitive for large user bases, as a distinct record must be set on the ENS Registry for each subdomain. + +Furthermore, users cannot immediately utilize these subdomains upon account creation, as the transaction to assign a resolver for the node of the subdomain must first be submitted and mined on-chain. This adds unnecessary friction when onboarding new users, who coincidentally would often benefit greatly from the usability improvements afforded by an ENS name. + +Enabling wildcard support allows for the design of more advanced resolvers that deterministically generate addresses and other records for unassigned subdomains. The generated addresses could map to counterfactual contract deployment addresses (i.e. `CREATE2` addresses), to designated "fallback" addresses, or other schemes. Additionally, individual resolvers would still be assignable to any given subdomain, which would supersede the wildcard resolution using the parent resolver. + +Another critical motivation with EIP-2544 is to enable wildcard resolution in a backwards-compatible fashion. It does not require modifying the current ENS Registry contract or any assigned resolvers, and continues to support existing ENS records — legacy ENS clients would simply fail to resolve wildcard records. + +## Specification + +The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119. + +EIP-2544-compliant ENS clients MUST perform the following sequence when determining the resolver for a given name: + +1. Apply the namehash algorithm to the supplied name as specified in EIP-137 to derive the `node`. +2. Call the ENS Registry contract, supplying the node as the argument to `function resolver(bytes32 node) constant returns (address)`. +3. If an address other than the null address is returned, the client MUST use the returned address as the resolver. +4. If the null address is returned, the client MUST strip the leftmost label from the name to derive a new name. +5. If the only remaining label is a top-level domain, or if no labels remain, the client MUST refuse to interact with the resolver. +6. Apply the namehash algorithm to the new name as specified in EIP-137 to derive the `parentNode`. +7. Call the ENS Registry contract, supplying the parent node as the argument to `function resolver(bytes32 node) constant returns (address)` to determine the resolver. +8. If the null address is returned from this second request, the client MUST refuse to interact with the resolver. + +In the event that a non-null resolver is located via this process, the client MUST supply the full, original `node` to the resolver to derive the address or other records. As with EIP-137, clients attempting to resolve an address via `function addr(bytes32 node) constant returns (address)` MUST refuse to interact with the returned address when the null address is returned. + +### Pseudocode +``` +function getNodeAndResolver(name) { + // 1. Apply the namehash algorithm to supplied name to determine the node. + const node = namehash(name); + + // 2. Attempt to retrieve a resolver from the ENS Registry using the node. + let resolver = ENS_REGISTRY.methods.resolver(node).call(); + + // 3. Use the resolver if a non-null result is returned from the registry. + if (resolver != "0x0000000000000000000000000000000000000000") { + return (node, resolver); + } + + // 4. Remove the leftmost label from the name. + const labelsWithoutLeftmost = name.split(".").slice(1); + + // 5. Do not continue if only the top-level domain (or no domain) remains. + if (labelsWithoutLeftmost.length < 2) { + throw new Error("ENS resolver not found."); + } + + // 6. Apply the namehash algorithm to new name to determine the parent node. + const parentNode = namehash(labelsWithoutLeftmost.join(".")); + + // 7. Attempt to retrieve a resolver from registry using the parent node. + resolver = ENS_REGISTRY.methods.resolver(parentNode).call(); + + // 8. Do not continue if a null result is returned from the registry. + if (resolver == "0x0000000000000000000000000000000000000000") { + throw new Error("ENS resolver not found."); + } + + // Return the located resolver along with the original node. + return (node, resolver); +}; +``` + +## Rationale + +The proposed implementation supports wildcard resolution in a manner that minimizes the impact to existing systems. It also reuses existing algorithms and procedures to the greatest possible extent, thereby easing the burden placed on authors and maintainers of various ENS clients. + +It also recognizes an existing consensus concerning the desirability of wildcard resolution for ENS, enabling more widespread adoption of the original specification by solving for a key scalability obstacle. + +By not recursively applying the namehash operation after removing successive leftmost subdomains, round-trip requests are reduced and edge cases around overriding ownership of nested subdomains are adequately handled. ENS clients may optimize further for reduced latency by utilizing a helper contract that performs the logic necessary to support wildcard resolution. + +## Backwards Compatibility + +There are no backwards compatibility concerns — existing ENS clients that are compliant with EIP-137 will fail to resolve wildcard records and refuse to interact with them, while those compliant with EIP-2544 will continue to correctly resolve, or reject, existing ENS records. + +## Security Considerations + +While compliant ENS clients will continue to refuse to resolve records without a resolver, there is still the risk that an improperly-configured client will refer to an incorrect resolver, or will not reject interactions with the null address when a resolver cannot be located. + +Additionally, resolvers supporting completely arbitrary wildcard subdomain resolution will increase the likelihood of funds being sent to unintended recipients as a result of typos. Applications that implement such resolvers should consider making additional name validation available to clients depending on the context, or implementing features that support recoverability of funds. + +There is also the possibility that some applications might require that no resolver be set for certain subdomains. For this to be problematic, the parent domain would need to successfully resolve the given subdomain node — to the knowledge of the authors, no application currently supports this feature or expects that subdomains should not resolve to a record. + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). \ No newline at end of file diff --git a/EIPS/eip-2565.md b/EIPS/eip-2565.md new file mode 100644 index 0000000000000..5ec5a4c1e7818 --- /dev/null +++ b/EIPS/eip-2565.md @@ -0,0 +1,93 @@ +--- +eip: 2565 +title: Repricing of the EIP-198 ModExp precompile +author: Kelly Olson (@ineffectualproperty), Sean Gulley (@sean-sn), Simon Peffers (@simonatsn), Justin Drake (@justindrake), Dankrad Feist (@dankrad) +discussions-to: https://ethereum-magicians.org/t/big-integer-modular-exponentiation-eip-198-gas-cost/4150 +status: Draft +type: Standards Track +category: Core +created: 2020-03-20 +Requires: 198 +--- + +## Simple Summary +The [EIP-198](https://eips.ethereum.org/EIPS/eip-198) ‘big integer modular exponentiation’, or `ModExp`, precompile is currently overpriced. Re-pricing this precompile will enable more cost efficient verification of RSA signatures, verifiable delay functions (VDFs), primality checks, and more. + +## Abstract +After benchmarking the ModExp precompile, we discovered that it is ‘overpriced’ relative to other precompiles. We also discovered that the current gas pricing formula could be improved to better estimate the computational complexity of various ModExp input variables. To improve the gas cost pricing for this precompile the following options are available: + +1. Changing the value of the `GQUADDIVISOR` parameter in the ModExp pricing formula to bring its costs more in-line with other precompiles +2. Modifying the gas pricing formula to better reflect the computational complexity of ModExp operations +3. Improving the underlying libraries beneath the ModExp Precompile +4. Any combination of (1), (2), and (3) + +We recommend **Option (1)** which provides a large practical improvement to gas estimation while keeping implementation complexity low. Options (2) and (3) could also be implemented and would further improve the gas pricing for a broader range of use cases. Additional data can be provided for options (2) and (3) as desired. + +## Motivation +Modular exponentiation is a foundational arithmetic operation for many cryptographic functions including signatures, VDFs, SNARKs, accumulators, and more. Unfortunately, the ModExp precompile is currently over-priced, making these operations inefficient and expensive. By reducing the cost of this precompile, these cryptographic functions become more practical, enabling improved security, stronger randomness (VDFs), and more. + +## Specification +The current gas pricing formula is defined in EIP-198. This formula divides a ‘computational complexity’ function by a ‘gas conversion’ parameter called `GQUADDIVISOR` to arrive at a gas cost. + +### **Recommended** Option (1): Change value of GQUADDIVISOR +`GQUADDIVISOR` is set to ‘20’ per EIP-198. We recommend changing the value of this parameter to ‘200’. + +### Option (2): Modify ‘computational complexity’ function +The current complexity function, as defined in EIP-198 is as follow: + +``` +def mult_complexity(x): + if x <= 64: return x ** 2 + elif x <= 1024: return x ** 2 // 4 + 96 * x - 3072 + else: return x ** 2 // 16 + 480 * x - 199680 +``` +where is `x` is `max(length_of_MODULUS, length_of_BASE)` + +This complexity formula was meant to approximate the difficulty of Karatsuba multiplication. However, we found a better approximation for modelling modular exponentiation. We recommend the following formula to better estimate the computational complexity for varying input values: + +``` +def mult_complexity(x): + ceiling(x/64)^2 +``` +where is `x` is `max(length_of_MODULUS, length_of_BASE)`. `x` is divided by 64 to account for the number of limbs in multiprecision arithmetic. + +You can find comparison of these two complexity fomulas for the current test vector as the following [spreadsheet](https://docs.google.com/spreadsheets/d/1Fq3d3wUjGN0R_FX-VPj7TKhCK33ac--P4QXB9MPQ8iw/edit?usp=sharing). + +### Option (3): Replace libraries used by ModExp precompiles +ModExp benchmarks for different libraries can be found at the following [spreadsheet](https://docs.google.com/spreadsheets/d/1Fq3d3wUjGN0R_FX-VPj7TKhCK33ac--P4QXB9MPQ8iw/edit?usp=sharing). + +While alternative libraries can provide improved performance, this option is not recommended at this time. + +## Rationale + +### **Recommended** Option (1): Change value of GQUADDIVISOR: +Changing the value of this parameter from 20 to 200 will reduce the gas cost of this precompile by a factor of 10 with minimal implementation changes. With this change, the cost of the ModExp precompile will have a higher cost (gas/second) than other precompiles such as ECRecover. + +![Option 1 Graph](../assets/eip-2565/GQuad_Change.png) + +### Option (2): Modify ‘computational complexity’ formula +An alternative ‘complexity’ function can be found at the following [spreadsheet](https://docs.google.com/spreadsheets/d/1Fq3d3wUjGN0R_FX-VPj7TKhCK33ac--P4QXB9MPQ8iw/edit?usp=sharing). + +![Option 2 Graph](../assets/eip-2565/Complexity_Regression.png) + +The new complexity function has a better fit vs. the execution time when compared to the current complexity function. This better fit is because the new complexity formula accounts for the use of binary exponentiation algorithms that are used by ‘bigint’ libraries for large exponents. You may also notice the regression line of the proposed complexity function bisects the test vector data points. This is because the run time varies depending on if the modulus is even or odd. + +While modifying the computational complexity formula can improve gas estimation at a medium implementation cost, we do not recommend it at this time. + +### Option (3): Improving the ModExp precompile implementations + +![Option 3 Graph](../assets/eip-2565/Library_Benchmarks.png) + +Replacing the underlying library can improve the performance of the ModExp precompile by 2x-4x for large exponents, but comes at a high implementation cost. We do not recommend this option at this time. + +## Test Cases +There are no changes to the underlying interface or arithmetic algorithms, so the existing test vectors can be reused. Gas values will need to be updated in the existing unit tests based on the final pricing decided in this EIP. This will ensure that the updated gas calculations are done correctly. + +## Security Considerations +The biggest security consideration for this EIP is creating a potential DOS vector by making ModExp operations too inexpensive relative to their computation time. Once a gas pricing formula is finalized in this EIP, we will run an analysis to ensure that a DOS vector is not created. This can be done by assuming all the gas in the block is used for this pre-compile for the worst-case input values. + +## References +[EIP-198](https://eips.ethereum.org/EIPS/eip-198) + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-3.md b/EIPS/eip-3.md index d3616cad69891..842e3e3d6c0f4 100644 --- a/EIPS/eip-3.md +++ b/EIPS/eip-3.md @@ -2,7 +2,7 @@ eip: 3 title: Addition of CALLDEPTH opcode author: Martin Holst Swende -status: Draft +status: Abandoned type: Standards Track category: Core created: 2015-11-19 diff --git a/EIPS/eip-615.md b/EIPS/eip-615.md index 38a058741d5f5..545ad929c7381 100644 --- a/EIPS/eip-615.md +++ b/EIPS/eip-615.md @@ -44,7 +44,7 @@ The result is that all of the following validations and optimizations can be don ### Dependencies -> **[EIP-1702](http://eips.ethereum.org/EIPS/eip-1702). Generalized Account Versioning Scheme.** This proposal needs a versioning scheme to allow for its bytecode (and eventually eWasm bytecode) to be deployed with existing bytecode on the same blockchain. +> **[EIP-1702](https://eips.ethereum.org/EIPS/eip-1702). Generalized Account Versioning Scheme.** This proposal needs a versioning scheme to allow for its bytecode (and eventually eWasm bytecode) to be deployed with existing bytecode on the same blockchain. ### Proposal @@ -520,4 +520,4 @@ There is a large and growing ecosystem of researchers, authors, teachers, audito ## Copyright -Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). \ No newline at end of file +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-695.md b/EIPS/eip-695.md index 0c58a05c19038..db00a279ed14f 100644 --- a/EIPS/eip-695.md +++ b/EIPS/eip-695.md @@ -1,7 +1,7 @@ --- eip: 695 title: Create `eth_chainId` method for JSON-RPC -author: Isaac Ardis , Wei Tang (@sorpaas), Fan Torchz (@tcz001) +author: Isaac Ardis , Wei Tang (@sorpaas), Fan Torchz (@tcz001), Erik Marks (@rekmarks) discussions-to: https://ethereum-magicians.org/t/eip-695-create-eth-chainid-method-for-json-rpc/1845 type: Standards Track category: Interface @@ -20,7 +20,7 @@ Include `eth_chainId` method in `eth_`-namespaced JSON-RPC methods. The `eth_chainId` method should return a single STRING result for an integer value in hexadecimal format, describing the currently configured `CHAIN_ID` value used for signing replay-protected transactions, -introduced via [EIP-155](./eip-155.md). +introduced by [EIP-155](https://eips.ethereum.org/EIPS/eip-155). ## Motivation @@ -34,7 +34,15 @@ the RPC. ### `eth_chainId` Returns the currently configured chain ID, a value used in replay-protected transaction -signing as introduced by [EIP-155](./eip-155.md). +signing as introduced by [EIP-155](https://eips.ethereum.org/EIPS/eip-155). + +The chain ID returned should always correspond to the information in the current known +head block. This ensures that caller of this RPC method can always use the retrieved +information to sign transactions built on top of the head. + +If the current known head block does not specify a chain ID, the client should treat any +calls to `eth_chainId` as though the method were not supported, and return a suitable +error. #### Parameters @@ -69,6 +77,12 @@ MetaMask, to add multi-chain support. Not relevant. +## Security Considerations + +Consumers should prefer `eth_chainId` over `net_version`, so that they can reliably identify chain they are communicating with. + +Implementers should take care to implement `eth_chainId` correctly and promote its use, since the chain ID is critical in replay attack prevention as described in [EIP-155](https://eips.ethereum.org/EIPS/eip-155), and consumers will rely on it to identify the chain they are communicating with. + ## Implementation - [Parity PR](https://github.com/paritytech/parity/pull/6329) @@ -77,7 +91,7 @@ Not relevant. ## Reference -Return value `QUANTITY` adheres to standard JSON RPC hex value encoding, as documented here: https://github.com/ethereum/wiki/wiki/JSON-RPC#hex-value-encoding. +Return value `QUANTITY` adheres to standard JSON RPC hex value encoding, as documented in the [Ethereum Wiki](https://github.com/ethereum/wiki/wiki/JSON-RPC#hex-value-encoding). ## Copyright diff --git a/EIPS/eip-721.md b/EIPS/eip-721.md index f106f9187bff5..ae2ef6633d79d 100644 --- a/EIPS/eip-721.md +++ b/EIPS/eip-721.md @@ -394,8 +394,8 @@ XXXXERC721, by William Entriken -- a scalable example implementation 1. ERC-20 Token Standard. https://eips.ethereum.org/EIPS/eip-20 1. ERC-165 Standard Interface Detection. https://eips.ethereum.org/EIPS/eip-165 1. ERC-173 Owned Standard. https://eips.ethereum.org/EIPS/eip-173 -1. ERC-223 Token Standard. https://eips.ethereum.org/EIPS/eip-223 -1. ERC-677 `transferAndCall` Token Standard. https://eips.ethereum.org/EIPS/eip-677 +1. ERC-223 Token Standard. https://github.com/ethereum/EIPs/issues/223 +1. ERC-677 `transferAndCall` Token Standard. https://github.com/ethereum/EIPs/issues/677 1. ERC-827 Token Standard. https://eips.ethereum.org/EIPS/eip-827 1. Ethereum Name Service (ENS). https://ens.domains 1. Instagram -- What's the Image Resolution? https://help.instagram.com/1631821640426723 diff --git a/EIPS/eip-777.md b/EIPS/eip-777.md index e57a19e655fc7..daf15ba2248e5 100644 --- a/EIPS/eip-777.md +++ b/EIPS/eip-777.md @@ -884,7 +884,7 @@ When called from a `transferFrom`, `operator` MUST be the address which issued t The `tokensReceived` hook notifies of any increment of the balance (send and mint) for a given *recipient*. Any address (regular or contract) wishing to be notified of token credits to their address -MAY register the address of a contract implementing the `ERC777TokensSender` interface described below via [ERC1820]. +MAY register the address of a contract implementing the `ERC777TokensRecipient` interface described below via [ERC1820]. > This is done by calling the `setInterfaceImplementer` function on the [ERC1820] registry > with the *recipient* address as the address, diff --git a/assets/eip-2565/Complexity_Regression.png b/assets/eip-2565/Complexity_Regression.png new file mode 100644 index 0000000000000..236f9dc35d31f Binary files /dev/null and b/assets/eip-2565/Complexity_Regression.png differ diff --git a/assets/eip-2565/GQuad_Change.png b/assets/eip-2565/GQuad_Change.png new file mode 100644 index 0000000000000..8553cda4be1f3 Binary files /dev/null and b/assets/eip-2565/GQuad_Change.png differ diff --git a/assets/eip-2565/Library_Benchmarks.png b/assets/eip-2565/Library_Benchmarks.png new file mode 100644 index 0000000000000..fa9c9235546c6 Binary files /dev/null and b/assets/eip-2565/Library_Benchmarks.png differ