diff --git a/.travis.yml b/.travis.yml index 184de5e866e963..78772718a5e3e1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,7 +30,7 @@ matrix: - language: rust cache: cargo before_script: - - cargo install eipv --version=0.0.5 + - cargo install eipv --version=0.1.1 env: TASK='eip-validator' - python: 3.3 env: TASK='codespell' diff --git a/EIPS/eip-1.md b/EIPS/eip-1.md index a57413acfc177c..f0ae480de86254 100644 --- a/EIPS/eip-1.md +++ b/EIPS/eip-1.md @@ -1,11 +1,10 @@ --- eip: 1 title: EIP Purpose and Guidelines -status: Active +status: Living type: Meta author: Martin Becze , Hudson Jameson , et al. created: 2015-10-27 -updated: 2015-12-07, 2016-02-01, 2018-03-21, 2018-05-29, 2018-10-17, 2019-05-19, 2019-12-04, 2020-06-17 --- ## What is an EIP? @@ -22,12 +21,14 @@ For Ethereum implementers, EIPs are a convenient way to track the progress of th There are three types of EIP: -- A **Standards Track EIP** describes any change that affects most or all Ethereum implementations, such as a change to the network protocol, a change in block or transaction validity rules, proposed application standards/conventions, or any change or addition that affects the interoperability of applications using Ethereum. Furthermore Standard EIPs can be broken down into the following categories. Standards Track EIPs consist of three parts, a design document, implementation, and finally if warranted an update to the [formal specification]. - - **Core** - improvements requiring a consensus fork (e.g. [EIP-5], [EIP-101]), as well as changes that are not necessarily consensus critical but may be relevant to [“core dev” discussions](https://github.com/ethereum/pm) (for example, [EIP-90], and the miner/node strategy changes 2, 3, and 4 of [EIP-86]). - - **Networking** - includes improvements around [devp2p] ([EIP-8]) and [Light Ethereum Subprotocol], as well as proposed improvements to network protocol specifications of [whisper] and [swarm]. - - **Interface** - includes improvements around client [API/RPC] specifications and standards, and also certain language-level standards like method names ([EIP-6]) and [contract ABIs]. The label “interface” aligns with the [interfaces repo] and discussion should primarily occur in that repository before an EIP is submitted to the EIPs repository. - - **ERC** - application-level standards and conventions, including contract standards such as token standards ([ERC20]), name registries ([ERC26], [ERC137]), URI schemes ([ERC67]), library/package formats ([EIP-82]), and wallet formats ([EIP-75], [EIP-85]). +- A **Standards Track EIP** describes any change that affects most or all Ethereum implementations, such as—a change to the network protocol, a change in block or transaction validity rules, proposed application standards/conventions, or any change or addition that affects the interoperability of applications using Ethereum. Standards Track EIPs consist of three parts—a design document, an implementation, and (if warranted) an update to the [formal specification]. Furthermore, Standards Track EIPs can be broken down into the following categories: + - **Core**: improvements requiring a consensus fork (e.g. [EIP-5](./eip-5.md), [EIP-101](./eip-101.md)), as well as changes that are not necessarily consensus critical but may be relevant to [“core dev” discussions](https://github.com/ethereum/pm) (for example, [EIP-90], and the miner/node strategy changes 2, 3, and 4 of [EIP-86](./eip-86.md)). + - **Networking**: includes improvements around [devp2p] ([EIP-8](./eip-8.md)) and [Light Ethereum Subprotocol], as well as proposed improvements to network protocol specifications of [whisper] and [swarm]. + - **Interface**: includes improvements around client [API/RPC] specifications and standards, and also certain language-level standards like method names ([EIP-6](./eip-6.md)) and [contract ABIs]. The label “interface” aligns with the [interfaces repo] and discussion should primarily occur in that repository before an EIP is submitted to the EIPs repository. + - **ERC**: application-level standards and conventions, including contract standards such as token standards ([ERC-20](./eip-20.md)), name registries ([ERC-137](./eip-137.md)), URI schemes, library/package formats, and wallet formats. + - A **Meta EIP** describes a process surrounding Ethereum or proposes a change to (or an event in) a process. Process EIPs are like Standards Track EIPs but apply to areas other than the Ethereum protocol itself. They may propose an implementation, but not to Ethereum's codebase; they often require community consensus; unlike Informational EIPs, they are more than recommendations, and users are typically not free to ignore them. Examples include procedures, guidelines, changes to the decision-making process, and changes to the tools or environment used in Ethereum development. Any meta-EIP is also considered a Process EIP. + - An **Informational EIP** describes an Ethereum design issue, or provides general guidelines or information to the Ethereum community, but does not propose a new feature. Informational EIPs do not necessarily represent Ethereum community consensus or a recommendation, so users and implementers are free to ignore Informational EIPs or follow their advice. It is highly recommended that a single EIP contain a single key proposal or new idea. The more focused the EIP, the more successful it tends to be. A change to one client doesn't require an EIP; a change that affects multiple clients, or defines a standard for multiple apps to use, does. @@ -47,9 +48,9 @@ REVERT (0xfe) Parties involved in the process are you, the champion or *EIP author*, the [*EIP editors*](#eip-editors), and the [*Ethereum Core Developers*](https://github.com/ethereum/pm). -Before you begin writing a formal EIP, you should vet your idea. Ask the Ethereum community first if an idea is original to avoid wasting time on something that will be be rejected based on prior research. It is thus recommended to open a discussion thread on [the Ethereum Magicians forum] to do this, but you can also use [one of the Ethereum Gitter chat rooms], [the Ethereum subreddit] or [the Issues section of this repository]. +Before you begin writing a formal EIP, you should vet your idea. Ask the Ethereum community first if an idea is original to avoid wasting time on something that will be rejected based on prior research. It is thus recommended to open a discussion thread on [the Ethereum Magicians forum] to do this, but you can also use [one of the Ethereum Gitter chat rooms], [the Ethereum subreddit] or [the Issues section of this repository]. -In addition to making sure your idea is original, it will be your role as the author to make your idea clear to reviewers and interested parties, as well as inviting editors, developers and community to give feedback on the aforementioned channels. You should try and gauge whether the interest in your EIP is commensurate with both the work involved in implementing it and how many parties will have to conform to it. For example, the work required for implementing a Core EIP will be much greater than for an ERC and the EIP will need sufficient interest from the Ethereum client teams. Negative community feedback will be taken into consideration and may prevent your EIP from moving past the Draft stage. +Once the idea has been vetted, your next responsibility will be to present (by means of an EIP) the idea to the reviewers and all interested parties, invite editors, developers, and the community to give feedback on the aforementioned channels. You should try and gauge whether the interest in your EIP is commensurate with both the work involved in implementing it and how many parties will have to conform to it. For example, the work required for implementing a Core EIP will be much greater than for an ERC and the EIP will need sufficient interest from the Ethereum client teams. Negative community feedback will be taken into consideration and may prevent your EIP from moving past the Draft stage. ### Core EIPs @@ -67,57 +68,43 @@ These calls generally result in a "rough consensus" around what EIPs should be i ### EIP Process -Following is the process that a successful non-Core EIP will move along: +The following is the standardization process for all EIPs in all tracks: -``` -[ WIP ] -> [ DRAFT ] -> [ LAST CALL ] -> [ FINAL ] -``` +![EIP Status Diagram](../assets/eip-1/EIP-process.png) -Following is the process that a successful Core EIP will move along: +**Idea** - An idea that is pre-draft. This is not tracked within the EIP Repository. -``` -[ IDEA ] -> [ DRAFT ] -> [ LAST CALL ] -> [ ACCEPTED ] -> [ FINAL ] -``` +**Draft** - The first formally tracked stage of an EIP in development. An EIP is merged by an EIP Editor into the EIP repository when properly formatted. + +**Review** - An EIP Author marks an EIP as ready for and requesting Peer Review. + +**Last Call** - This is the final review window for an EIP before moving to `FINAL`. An EIP editor will assign `Last Call` status and set a review end date (review-period-end), typically 14 days later. + +If this period results in necessary normative changes it will revert the EIP to `REVIEW`. -Each status change is requested by the EIP author and reviewed by the EIP editors. Use a pull request to update the status. Please include a link to where people should continue discussing your EIP. The EIP editors will process these requests as per the conditions below. - -* **Idea** -- Once the champion has asked the Ethereum community whether an idea has any chance of support, they will write a draft EIP as a [pull request]. Consider including an implementation if this will aid people in studying the EIP. - * :arrow_right: Draft -- If agreeable, EIP editor will assign the EIP a number (generally the issue or PR number related to the EIP) and merge your pull request. The EIP editor will not unreasonably deny an EIP. - * :x: Draft -- Reasons for denying draft status include being too unfocused, too broad, duplication of effort, being technically unsound, not providing proper motivation or addressing backwards compatibility, or not in keeping with the [Ethereum philosophy](https://github.com/ethereum/wiki/wiki/White-Paper#philosophy). -* **Draft** -- Once the first draft has been merged, you may submit follow-up pull requests with further changes to your draft until such point as you believe the EIP to be mature and ready to proceed to the next status. An EIP in draft status must be implemented to be considered for promotion to the next status (ignore this requirement for core EIPs). - * :arrow_right: Last Call -- If agreeable, the EIP editor will assign Last Call status and set a review end date (`review-period-end`), normally 14 days later. - * :x: Last Call -- A request for Last Call status will be denied if material changes are still expected to be made to the draft. We hope that EIPs only enter Last Call once, so as to avoid unnecessary noise on the RSS feed. -* **Last Call** -- This EIP will listed prominently on the https://eips.ethereum.org/ website (subscribe via RSS at [last-call.xml](/last-call.xml)). - * :x: -- A Last Call which results in material changes or substantial unaddressed technical complaints will cause the EIP to revert to Draft. - * :arrow_right: Accepted (Core EIPs only) -- A successful Last Call without material changes or unaddressed technical complaints will become Accepted. - * :arrow_right: Final (Non-Core EIPs) -- A successful Last Call without material changes or unaddressed technical complaints will become Final. -* **Accepted (Core EIPs only)** -- This status signals that material changes are unlikely and Ethereum client developers should consider this EIP for inclusion. Their process for deciding whether to encode it into their clients as part of a hard fork is not part of the EIP process. - * :arrow_right: Draft -- The Core Devs can decide to move this EIP back to the Draft status at their discretion. E.g. a major, but correctable, flaw was found in the EIP. - * :arrow_right: Rejected -- The Core Devs can decide to mark this EIP as Rejected at their discretion. E.g. a major, but uncorrectable, flaw was found in the EIP. - * :arrow_right: Final -- Standards Track Core EIPs must be implemented in at least three viable Ethereum clients before it can be considered Final. When the implementation is complete and adopted by the community, the status will be changed to “Final”. -* **Final** -- This EIP represents the current state-of-the-art. A Final EIP should only be updated to correct errata. - -Other exceptional statuses include: - -* **Active** -- Some Informational and Process EIPs may also have a status of “Active” if they are never meant to be completed. E.g. EIP 1 (this EIP). -* **Abandoned** -- This EIP is no longer pursued by the original authors or it may not be a (technically) preferred option anymore. - * :arrow_right: Draft -- Authors or new champions wishing to pursue this EIP can ask for changing it to Draft status. -* **Rejected** -- An EIP that is fundamentally broken or a Core EIP that was rejected by the Core Devs and will not be implemented. An EIP cannot move on from this state. -* **Superseded** -- An EIP which was previously Final but is no longer considered state-of-the-art. Another EIP will be in Final status and reference the Superseded EIP. An EIP cannot move on from this state. +**Final** - This EIP represents the final standard. A Final EIP exists in a state of finality and should only be updated to correct errata and add non-normative clarifications. + +**Stagnant** - Any EIP in `DRAFT` or `REVIEW` if inactive for a period of 6 months or greater is moved to `STAGNANT`. An EIP may be resurrected from this state by Authors or EIP Editors through moving it back to `DRAFT`. + +>*EIP Authors are notified of any algorithmic change to the status of their EIP* + +**Withdrawn** - The EIP Author(s) have withdrawn the proposed EIP. This state has finality and can no longer be resurrected using this EIP number. If the idea is pursued at later date it is considered a new proposal. + +**Living** - A special status for EIPs that are designed to be continually updated and not reach a state of finality. This includes most notably EIP-1. Any changes to these EIPs will move between `REVIEW` and `LIVING` states. ## What belongs in a successful EIP? Each EIP should have the following parts: -- Preamble - RFC 822 style headers containing metadata about the EIP, including the EIP number, a short descriptive title (limited to a maximum of 44 characters), and the author details. See [below](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1.md#eip-header-preamble) for details. +- Preamble - RFC 822 style headers containing metadata about the EIP, including the EIP number, a short descriptive title (limited to a maximum of 44 characters), and the author details. See [below](./eip-1.md#eip-header-preamble) for details. - Abstract - A short (~200 word) description of the technical issue being addressed. -- Motivation (*optional) - The motivation is critical for EIPs that want to change the Ethereum protocol. It should clearly explain why the existing protocol specification is inadequate to address the problem that the EIP solves. EIP submissions without sufficient motivation may be rejected outright. +- Motivation (*optional) - A motivation section is critical for EIPs that want to change the Ethereum protocol. It should clearly explain why the existing protocol specification is inadequate to address the problem that the EIP solves. EIP submissions without sufficient motivation may be rejected outright. - Specification - The technical specification should describe the syntax and semantics of any new feature. The specification should be detailed enough to allow competing, interoperable implementations for any of the current Ethereum platforms (cpp-ethereum, go-ethereum, parity, ethereumJ, ethereumjs-lib, [and others](https://github.com/ethereum/wiki/wiki/Clients). - Rationale - The rationale fleshes out the specification by describing what motivated the design and why particular design decisions were made. It should describe alternate designs that were considered and related work, e.g. how the feature is supported in other languages. The rationale may also provide evidence of consensus within the community, and should discuss important objections or concerns raised during discussion. - Backwards Compatibility - All EIPs that introduce backwards incompatibilities must include a section describing these incompatibilities and their severity. The EIP must explain how the author proposes to deal with these incompatibilities. EIP submissions without a sufficient backwards compatibility treatise may be rejected outright. -- Test Cases - Test cases for an implementation are mandatory for EIPs that are affecting consensus changes. Other EIPs can choose to include links to test cases if applicable. -- Implementations - The implementations must be completed before any EIP is given status “Final”, but it need not be completed before the EIP is merged as draft. 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. -- Security Considerations - All EIPs must contain a section that discusses the security implications/considerations relevant to the proposed change. Include information that might be important for security discussions, surfaces risks and can be used throughout the life cycle of the proposal. E.g. include security-relevant design decisions, concerns, important discussions, implementation-specific guidance and pitfalls, an outline of threats and risks and how they are being addressed. EIP submissions missing the "Security Considerations" section will be rejected. An EIP cannot proceed to status "Final" without a Security Considerations discussion deemed sufficient by the reviewers. +- Test Cases - Test cases for an implementation are mandatory for EIPs that are affecting consensus changes. Tests should either be inlined in the EIP as data (such as input/expected output pairs, or included in `../assets/eip-###/`. +- Reference Implementation - An optional section that contains a reference/example implementation that people can use to assist in understanding or implementing this specification. +- Security Considerations - All EIPs must contain a section that discusses the security implications/considerations relevant to the proposed change. Include information that might be important for security discussions, surfaces risks and can be used throughout the life-cycle of the proposal. E.g. include security-relevant design decisions, concerns, important discussions, implementation-specific guidance and pitfalls, an outline of threats and risks and how they are being addressed. EIP submissions missing the "Security Considerations" section will be rejected. An EIP cannot proceed to status "Final" without a Security Considerations discussion deemed sufficient by the reviewers. - Copyright Waiver - All EIPs must be in the public domain. See the bottom of this EIP for an example copyright waiver. ## EIP Formats and Templates @@ -136,7 +123,7 @@ Each EIP must begin with an [RFC 822](https://www.ietf.org/rfc/rfc822.txt) style ` * discussions-to:` *a url pointing to the official discussion thread* -` status:` *Draft, Last Call, Accepted, Final, Active, Abandoned, Rejected, or Superseded* +` status:` *Draft, Review, Last Call, Final, Stagnant, Withdrawn, Living* `* review-period-end:` *date review period ends* @@ -162,7 +149,7 @@ Headers requiring dates will always do so in the format of ISO 8601 (yyyy-mm-dd) #### `author` header -The `author` header optionally lists the names, email addresses or usernames of the authors/owners of the EIP. Those who prefer anonymity may use a username only, or a first name and a username. The format of the author header value must be: +The `author` header lists the names, email addresses or usernames of the authors/owners of the EIP. Those who prefer anonymity may use a username only, or a first name and a username. The format of the `author` header value must be: > Random J. User <address@dom.ain> @@ -176,6 +163,10 @@ if the email address or GitHub username is included, and if the email address is not given. +It is not possible to use both an email and a GitHub username at the same time. If important to include both, one could include their name twice, once with the GitHub username, and once with the email. + +At least one author must use a GitHub username, in order to get notified on change requests and have the capability to approve or reject them. + #### `resolution` header The `resolution` header is required for Standards Track EIPs only. It contains a URL that should point to an email message or other web resource where the pronouncement about the EIP is made. @@ -212,6 +203,10 @@ EIPs may have a `requires` header, indicating the EIP numbers that this EIP depe EIPs may also have a `superseded-by` header indicating that an EIP has been rendered obsolete by a later document; the value is the number of the EIP that replaces the current document. The newer EIP must have a `replaces` header containing the number of the EIP that it rendered obsolete. +## Linking to other EIPs + +References to other EIPs should follow the format `EIP-N` where `N` is the EIP number you are referring to. Each EIP that is referenced in an EIP **MUST** be accompanied by a relative markdown link the first time it is referenced, and **MAY** be accompanied by a link on subsequent references. The link **MUST** always be done via relative paths so that the links work in this GitHub repository, forks of this repository, the main EIPs site, mirrors of the main EIP site, etc. For example, you would link to this EIP with `[EIP-1](./eip-1.md)`. + ## Auxiliary Files Images, diagrams and auxiliary files should be included in a subdirectory of the `assets` folder for that EIP as follows: `assets/eip-N` (where **N** is to be replaced with the EIP number). When linking to an image in the EIP, use relative links such as `../assets/eip-1/image.png`. @@ -220,29 +215,21 @@ Images, diagrams and auxiliary files should be included in a subdirectory of the It occasionally becomes necessary to transfer ownership of EIPs to a new champion. In general, we'd like to retain the original author as a co-author of the transferred EIP, but that's really up to the original author. A good reason to transfer ownership is because the original author no longer has the time or interest in updating it or following through with the EIP process, or has fallen off the face of the 'net (i.e. is unreachable or isn't responding to email). A bad reason to transfer ownership is because you don't agree with the direction of the EIP. We try to build consensus around an EIP, but if that's not possible, you can always submit a competing EIP. -If you are interested in assuming ownership of an EIP, send a message asking to take over, addressed to both the original author and the EIP editor. If the original author doesn't respond to email in a timely manner, the EIP editor will make a unilateral decision (it's not like such decisions can't be reversed :)). +If you are interested in assuming ownership of an EIP, send a message asking to take over, addressed to both the original author and the EIP editor. If the original author doesn't respond to the email in a timely manner, the EIP editor will make a unilateral decision (it's not like such decisions can't be reversed :)). ## EIP Editors The current EIP editors are -` * Nick Johnson (@arachnid)` - -` * Casey Detrio (@cdetrio)` - -` * Hudson Jameson (@Souptacular)` - -` * Vitalik Buterin (@vbuterin)` - -` * Nick Savers (@nicksavers)` - -` * Martin Becze (@wanderer)` - -` * Greg Colvin (@gcolvin)` - -` * Alex Beregszaszi (@axic)` - -` * Micah Zoltu (@MicahZoltu)` +- Nick Johnson (@arachnid) +- Casey Detrio (@cdetrio) +- Hudson Jameson (@Souptacular) +- Vitalik Buterin (@vbuterin) +- Nick Savers (@nicksavers) +- Martin Becze (@wanderer) +- Greg Colvin (@gcolvin) +- Alex Beregszaszi (@axic) +- Micah Zoltu (@MicahZoltu) ## EIP Editor Responsibilities @@ -274,46 +261,15 @@ When referring to an EIP by number, it should be written in the hyphenated form This document was derived heavily from [Bitcoin's BIP-0001] written by Amir Taaki which in turn was derived from [Python's PEP-0001]. In many places text was simply copied and modified. Although the PEP-0001 text was written by Barry Warsaw, Jeremy Hylton, and David Goodger, they are not responsible for its use in the Ethereum Improvement Process, and should not be bothered with technical questions specific to Ethereum or the EIP. Please direct all comments to the EIP editors. -December 7, 2015: EIP-1 has been improved and will be placed as a PR. - -February 1, 2016: EIP-1 has added editors, made draft improvements to process, and has merged with Master stream. - -March 21, 2018: Minor edits to accommodate the new automatically-generated EIP directory on [eips.ethereum.org](https://eips.ethereum.org/). - -May 29, 2018: A last call process was added. - -Oct 17, 2018: The `updated` header was introduced. - -May 19, 2019: The **Abandoned** status was introduced. - -Dec 4, 2019: The "Security Considerations" section was introduced. - -June 17, 2020: Canonicalizes the format for referencing EIPs by number in the "Style Guide". - -See [the revision history for further details](https://github.com/ethereum/EIPs/commits/master/EIPS/eip-1.md), which is also available by clicking on the History button in the top right of the EIP. - ### Bibliography -[EIP-5]: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-5.md -[EIP-101]: https://github.com/ethereum/EIPs/issues/28 -[EIP-90]: https://github.com/ethereum/EIPs/issues/90 -[EIP-86]: https://github.com/ethereum/EIPs/issues/86#issue-145324865 [devp2p]: https://github.com/ethereum/wiki/wiki/%C3%90%CE%9EVp2p-Wire-Protocol -[EIP-8]: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-8.md [Light Ethereum Subprotocol]: https://github.com/ethereum/wiki/wiki/Light-client-protocol [whisper]: https://github.com/ethereum/go-ethereum/wiki/Whisper-Overview [swarm]: https://github.com/ethereum/go-ethereum/pull/2959 [API/RPC]: https://github.com/ethereum/wiki/wiki/JSON-RPC -[EIP-6]: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-6.md [contract ABIs]: https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI [interfaces repo]: https://github.com/ethereum/interfaces -[ERC-20]: https://github.com/ethereum/EIPs/issues/20 -[ERC-26]: https://github.com/ethereum/EIPs/issues/26 -[ERC-137]: https://github.com/ethereum/EIPs/issues/137 -[ERC-67]: https://github.com/ethereum/EIPs/issues/67 -[EIP-82]: https://github.com/ethereum/EIPs/issues/82 -[EIP-75]: https://github.com/ethereum/EIPs/issues/75 -[EIP-85]: https://github.com/ethereum/EIPs/issues/85 [the Ethereum subreddit]: https://www.reddit.com/r/ethereum/ [one of the Ethereum Gitter chat rooms]: https://gitter.im/ethereum/ [pull request]: https://github.com/ethereum/EIPs/pulls diff --git a/EIPS/eip-1011.md b/EIPS/eip-1011.md index a35c0a7b6de81b..3e3087b1f5e7b3 100644 --- a/EIPS/eip-1011.md +++ b/EIPS/eip-1011.md @@ -400,7 +400,7 @@ Normal block transactions cannot affect casper `vote` validation results, but ca The call to `initialize_epoch` at the beginning of each epoch requires 0 gas so that this protocol state transition does not take any gas allowance away from normal transactions. #### NULL_SENDER and Account Abstraction -This EIP implements a limited version of account abstraction for validators' `vote` transactions. The general design was borrowed from [EIP 86](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-86.md). Rather than relying upon native transaction signatures, each validator specifies a signature contract when sending their `deposit` to `CASPER_ADDR`. When casting a `vote`, the validator bundles and signs the parameters of their `vote` according to the requirements of their signature contract. The `vote` method of the casper contract checks the signature of the parameters against the validator's signature contract, exiting the transaction as unsuccessful if the signature is not successfully verified. +This EIP implements a limited version of account abstraction for validators' `vote` transactions. The general design was borrowed from [EIP-86](./eip-86.md). Rather than relying upon native transaction signatures, each validator specifies a signature contract when sending their `deposit` to `CASPER_ADDR`. When casting a `vote`, the validator bundles and signs the parameters of their `vote` according to the requirements of their signature contract. The `vote` method of the casper contract checks the signature of the parameters against the validator's signature contract, exiting the transaction as unsuccessful if the signature is not successfully verified. This allows validators to customize their own signing scheme for votes. Use cases include: * quantum-secure signature schemes diff --git a/EIPS/eip-1013.md b/EIPS/eip-1013.md index e4cf68a98a7530..ea3f55cb486425 100644 --- a/EIPS/eip-1013.md +++ b/EIPS/eip-1013.md @@ -22,11 +22,11 @@ This meta-EIP specifies the changes included in the Ethereum hardfork named Cons - `Block >= 9_200_000` on the Kovan testnet - `Block >= 3_660_663` on the Rinkeby testnet - Included EIPs: - - [EIP 145](https://eips.ethereum.org/EIPS/eip-145): Bitwise shifting instructions in EVM - - [EIP 1014](https://eips.ethereum.org/EIPS/eip-1014): Skinny CREATE2 - - [EIP 1052](https://eips.ethereum.org/EIPS/eip-1052): EXTCODEHASH Opcode - - [EIP 1234](https://eips.ethereum.org/EIPS/eip-1234): Delay difficulty bomb, adjust block reward - - [EIP 1283](https://eips.ethereum.org/EIPS/eip-1283): Net gas metering for SSTORE without dirty maps + - [EIP-145](./eip-145.md): Bitwise shifting instructions in EVM + - [EIP-1014](./eip-1014.md): Skinny CREATE2 + - [EIP-1052](./eip-1052.md): EXTCODEHASH Opcode + - [EIP-1234](./eip-1234.md): Delay difficulty bomb, adjust block reward + - [EIP-1283](./eip-1283.md): Net gas metering for SSTORE without dirty maps ## References diff --git a/EIPS/eip-1014.md b/EIPS/eip-1014.md index 37e2501e8c08bc..31d4d62ec1dfc9 100644 --- a/EIPS/eip-1014.md +++ b/EIPS/eip-1014.md @@ -42,13 +42,13 @@ Since address calculation depends on hashing the `init_code`, it would leave cli The `init_code` is the code that, when executed, produces the runtime bytecode that will be placed into the state, and which typically is used by high level languages to implement a 'constructor'. -This EIP makes collisions possible. The behaviour at collisions is specified by [EIP 684](https://github.com/ethereum/EIPs/issues/684): +This EIP makes collisions possible. The behaviour at collisions is specified by [EIP-684](https://github.com/ethereum/EIPs/issues/684): > If a contract creation is attempted, due to either a creation transaction or the `CREATE` (or future `CREATE2`) opcode, and the destination address already has either nonzero nonce, or nonempty code, then the creation throws immediately, with exactly the same behavior as would arise if the first byte in the init code were an invalid opcode. This applies retroactively starting from genesis. Specifically, if `nonce` or `code` is nonzero, then the create-operation fails. -With [EIP 161](https://eips.ethereum.org/EIPS/eip-161) +With [EIP-161](./eip-161.md) > Account creation transactions and the `CREATE` operation SHALL, prior to the execution of the initialisation code, increment the nonce over and above its normal starting value by one diff --git a/EIPS/eip-1015.md b/EIPS/eip-1015.md index b884e84a962ea8..e21c7f17201663 100644 --- a/EIPS/eip-1015.md +++ b/EIPS/eip-1015.md @@ -24,20 +24,20 @@ Moving to PoS has been on the roadmap since day 0 for ethereum, along with a red #### Issuance Cap at 120 Million -[EIP 960](https://github.com/ethereum/EIPs/issues/960), Vitalik's not so jokey april's fool has been taken seriously. It proposes the issuance to be slowly reduced until it reaches 120 million ether. One of the main counterpoints by Vlad can be simplified by [we don't know enough to know what that ether can be used for](https://medium.com/@Vlad_Zamfir/against-vitaliks-fixed-supply-eip-eip-960-18e182a7e5bd) and Vitalik's counterpoint is that [reducing emissions can be a way to reduce future abuse of these funds by finding a schelling point at 0](https://medium.com/@VitalikButerin/to-be-clear-im-not-necessarily-wedded-to-a-finite-supply-cap-a7aa48ab880c). Issuance has already been reduced once, from 5 ether to the current 3 ether per block. The main point of a hard cap is that a lot of people consider *not issuing* as having a positive contribution, that can outweigh other actions. Burning ether is also a valid issuance decision. +[EIP-960](https://github.com/ethereum/EIPs/issues/960), Vitalik's not so jokey april's fool has been taken seriously. It proposes the issuance to be slowly reduced until it reaches 120 million ether. One of the main counterpoints by Vlad can be simplified by [we don't know enough to know what that ether can be used for](https://medium.com/@Vlad_Zamfir/against-vitaliks-fixed-supply-eip-eip-960-18e182a7e5bd) and Vitalik's counterpoint is that [reducing emissions can be a way to reduce future abuse of these funds by finding a schelling point at 0](https://medium.com/@VitalikButerin/to-be-clear-im-not-necessarily-wedded-to-a-finite-supply-cap-a7aa48ab880c). Issuance has already been reduced once, from 5 ether to the current 3 ether per block. The main point of a hard cap is that a lot of people consider *not issuing* as having a positive contribution, that can outweigh other actions. Burning ether is also a valid issuance decision. #### Asics and advantadges of PoW -[EIP 960](https://eips.ethereum.org/EIPS/eip-969) proposes a change in algorithm to avoid mining being dominated by ASICS. Counter arguments by Phil Daian argue among others than [resisting economies of scale is futile and there might be specific security advantadges to specialized hardware](https://pdaian.com/blog/anti-asic-forks-considered-harmful/). One of the main arguments for PoW mining, even when it doesn't provide security, it is useful as a fair distribution mechanism, that **PoW allows any person with a computer, internet access and electricity to obtain currency without having to deal with government imposed currency controls**. +[EIP-960](https://eips.ethereum.org/EIPS/eip-969) proposes a change in algorithm to avoid mining being dominated by ASICS. Counter arguments by Phil Daian argue among others than [resisting economies of scale is futile and there might be specific security advantadges to specialized hardware](https://pdaian.com/blog/anti-asic-forks-considered-harmful/). One of the main arguments for PoW mining, even when it doesn't provide security, it is useful as a fair distribution mechanism, that **PoW allows any person with a computer, internet access and electricity to obtain currency without having to deal with government imposed currency controls**. #### Recovery Forks -After the Parity Multisig library self destruction, three different strategies have been attempted to recover the funds: [a general protocol improvement to allow reviving self destructed contracts](https://gist.github.com/5chdn/a9bb8617cc8523a030126a3d1c60baf3) (which was considered dangerous), a [general process to recover funds](https://github.com/ethereum/EIPs/pull/867) and a [specific recovery of the multisig library](https://eips.ethereum.org/EIPS/eip-999). The latter two are finding a lot of resistance from the community, but it's unlikely that these issues are going away soon. The affected parties have a large incentive (fluctuating at almost half a billion dollars) to keep trying, and it's an issue that is likely to occur again in the future. If they get reimbursed, [there are many other special cases of ether provably burnt or stuck](https://github.com/ethereum/EIPs/issues/156) that might deserve the same treatment. If they get shut down, they have an incentive to move forward a fork implementation: even if they are a minority chain, it's likely they'll recover an amount larger than 0, which is what they would otherwise, and it means the main ethereum community might lose a valuable team of developers. +After the Parity Multisig library self destruction, three different strategies have been attempted to recover the funds: [a general protocol improvement to allow reviving self destructed contracts](https://gist.github.com/5chdn/a9bb8617cc8523a030126a3d1c60baf3) (which was considered dangerous), a [general process to recover funds](https://github.com/ethereum/EIPs/pull/867) and a [specific recovery of the multisig library](./eip-999.md). The latter two are finding a lot of resistance from the community, but it's unlikely that these issues are going away soon. The affected parties have a large incentive (fluctuating at almost half a billion dollars) to keep trying, and it's an issue that is likely to occur again in the future. If they get reimbursed, [there are many other special cases of ether provably burnt or stuck](https://github.com/ethereum/EIPs/issues/156) that might deserve the same treatment. If they get shut down, they have an incentive to move forward a fork implementation: even if they are a minority chain, it's likely they'll recover an amount larger than 0, which is what they would otherwise, and it means the main ethereum community might lose a valuable team of developers. #### Other Public Goods -There are many other types of public goods that could be funded by issuance. By *Public Good*, I'm using a strict definition of something that brings value to everyone, both those who funded it and free-loaders, making it hard to fund it exclusively by traditional private incentives. They can be research, whole network security, [incentivize full clients and networking](https://eips.ethereum.org/EIPS/eip-908), fair distribution of tokens etc. +There are many other types of public goods that could be funded by issuance. By *Public Good*, I'm using a strict definition of something that brings value to everyone, both those who funded it and free-loaders, making it hard to fund it exclusively by traditional private incentives. They can be research, whole network security, [incentivize full clients and networking](./eip-908.md), fair distribution of tokens etc. ## Proposed Solution ### Issuance Contract diff --git a/EIPS/eip-1052.md b/EIPS/eip-1052.md index 77692c77bced5f..6dc6015e16a40e 100644 --- a/EIPS/eip-1052.md +++ b/EIPS/eip-1052.md @@ -25,7 +25,7 @@ takes one argument from the stack, zeros the first 96 bits and pushes to the stack the keccak256 hash of the code of the account at the address being the remaining 160 bits. -In case the account does not exist or is empty (as defined by [EIP-161](https://eips.ethereum.org/EIPS/eip-161)) `0` is pushed to the stack. +In case the account does not exist or is empty (as defined by [EIP-161](./eip-161.md)) `0` is pushed to the stack. In case the account does not have code the keccak256 hash of empty data (i.e. `c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470`) diff --git a/EIPS/eip-1056.md b/EIPS/eip-1056.md index 2ed52193e506b2..a600cb92fdc87a 100644 --- a/EIPS/eip-1056.md +++ b/EIPS/eip-1056.md @@ -19,7 +19,7 @@ This ERC describes a standard for creating and updating identities with a limite ## Motivation -As we have been developing identity systems for the last couple of years at uPort it has become apparent that the cost of identity creation is a large issue. The previous Identity proposal [ERC725](https://eips.ethereum.org/EIPS/eip-725) faces this exact issue. Our requirements when creating this ERC is that identity creation should be free, and should be possible to do in an offline environment (e.g. refugee scenario). However it must also be possible to rotate keys without changing the primary identifier of the identity. The identity system should be fit to use off-chain as well as on-chain. +As we have been developing identity systems for the last couple of years at uPort it has become apparent that the cost of identity creation is a large issue. The previous Identity proposal [ERC-725](./eip-725.md) faces this exact issue. Our requirements when creating this ERC is that identity creation should be free, and should be possible to do in an offline environment (e.g. refugee scenario). However it must also be possible to rotate keys without changing the primary identifier of the identity. The identity system should be fit to use off-chain as well as on-chain. ## Definitions diff --git a/EIPS/eip-1057.md b/EIPS/eip-1057.md index 7d0271649f0b01..fa7a61f6602829 100644 --- a/EIPS/eip-1057.md +++ b/EIPS/eip-1057.md @@ -3,7 +3,7 @@ eip: 1057 title: ProgPoW, a Programmatic Proof-of-Work 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: Accepted +status: Review type: Standards Track category: Core created: 2018-05-02 diff --git a/EIPS/eip-1066.md b/EIPS/eip-1066.md index 6560b608a9c1e9..9f057326ec6833 100644 --- a/EIPS/eip-1066.md +++ b/EIPS/eip-1066.md @@ -33,7 +33,7 @@ Status codes convey a much richer set of information [than Booleans](https://exi _End users get little to no feedback, and there is no translation layer._ -Since ERC1066 status codes are finite and known in advance, we can leverage [ERC1444](https://eips.ethereum.org/EIPS/eip-1444) to provide global, human-readable sets of status messages. These may also be translated into any language, differing levels of technical detail, added as `revert` messages, natspecs, and so on. +Since ERC1066 status codes are finite and known in advance, we can leverage [ERC-1444](./eip-1444.md) to provide global, human-readable sets of status messages. These may also be translated into any language, differing levels of technical detail, added as `revert` messages, natspecs, and so on. Status codes convey a much richer set of information than Booleans, and are able to be reacted to autonomously unlike arbitrary strings. @@ -45,7 +45,7 @@ At time of writing, other than stepping through EVM execution and inspecting mem Having a fixed set of codes also makes it possible to write common helper functions to react in common ways to certain signals. This can live off- or on-chain library, lowering the overhead in building smart contracts, and helping raise code quality with trusted shared components. -We also see a desire for this [in transactions](https://eips.ethereum.org/EIPS/eip-658), and there's no reason that these status codes couldn't be used by the EVM itself. +We also see a desire for this [in transactions](./eip-658.md), and there's no reason that these status codes couldn't be used by the EVM itself. ### Smart Contract Autonomy @@ -506,7 +506,7 @@ While this repository includes helper enums, we have found working directly in t #### Localizations -One commonly requested application of this spec is human-readable translations of codes. This has been moved to its own proposal: [ERC-1444](https://github.com/ethereum/EIPs/pull/1444/), primarily due to a desire to keep both specs focused. +One commonly requested application of this spec is human-readable translations of codes. This has been moved to its own proposal: [ERC-1444](./eip-1444.md), primarily due to a desire to keep both specs focused. ### Extensibility diff --git a/EIPS/eip-1077.md b/EIPS/eip-1077.md index a420703a577591..3d37476ce9b424 100644 --- a/EIPS/eip-1077.md +++ b/EIPS/eip-1077.md @@ -197,7 +197,7 @@ Other version is implemented as Gnosis Safe variant in: https://github.com/statu The idea of using signed messages as executable intent has been around for a while and many other projects are taking similar approaches, which makes it a great candidate for a standard that guarantees interoperability: -* [EIP 877](https://github.com/ethereum/EIPs/pull/877) An attempt of doing the same but with a change in the protocol +* [EIP-877](https://github.com/ethereum/EIPs/pull/877) An attempt of doing the same but with a change in the protocol * [Status](https://github.com/status-im/ideas/issues/73) * [Aragon](https://github.com/aragonlabs/pay-protocol) (this might not be the best link to show their work in this area) * [Token Standard Functions for Preauthorized Actions](https://github.com/ethereum/EIPs/issues/662) @@ -223,7 +223,7 @@ Copyright and related rights waived via [CC0](https://creativecommons.org/public * [Universal Logins talk at UX Unconf, Toronto](https://www.youtube.com/watch?v=qF2lhJzngto) -[EIP-20]: https://eips.ethereum.org/EIPS/eip-20 -[EIP-191]: https://eips.ethereum.org/EIPS/eip-191 -[EIP-1271]: https://eips.ethereum.org/EIPS/eip-1271 -[EIP-1344]: https://eips.ethereum.org/EIPS/eip-1344 +[EIP-20]: ./eip-20.md +[EIP-191]: ./eip-191.md +[EIP-1271]: ./eip-1271.md +[EIP-1344]: ./eip-1344.md diff --git a/EIPS/eip-1078.md b/EIPS/eip-1078.md index 320c8376c6d080..9c40dd81321361 100644 --- a/EIPS/eip-1078.md +++ b/EIPS/eip-1078.md @@ -64,7 +64,7 @@ Once the desired level is known, the app must take these steps: 3. **Generate the bytecode** for a transaction calling the function `addKey(PUBLICKEY,LEVEL)`. 4. **Broadcast a transaction request on a whisper channel** or some other decentralized network of peers. Details on this step require further discussions 1. **If web3 is available** then attempt calling web3.eth.sendTransaction. This can be automatic or prompted by user action. -1. **Attempt calling a URI** if the app supports [URL format for transaction requests EIP](https://eips.ethereum.org/EIPS/eip-681) then attempt calling this. This can be automatic or prompted by user action. +1. **Attempt calling a URI** if the app supports [URL format for transaction requests EIP](./eip-681.md) then attempt calling this. This can be automatic or prompted by user action. 1. **Show a QR code**: with an EIP681 formatted URL. That QR code can be clickable to attempt to retry the other options, but it should be done last: if step 1 works, the user should receive a notification on their compatible device and won't need to use the QR code. Here's an example of a EIP681 compatible address to add a public key generated locally in the app: diff --git a/EIPS/eip-1102.md b/EIPS/eip-1102.md index 07a8e08abc8e03..cf26f0006dfa3a 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 , Erik Marks +author: Paul Bouchon , Erik Marks (@rekmarks) discussions-to: https://ethereum-magicians.org/t/eip-1102-opt-in-provider-access/414 status: Draft type: Standards Track diff --git a/EIPS/eip-1108.md b/EIPS/eip-1108.md index 661097a7244559..a1feaa7d00db0d 100644 --- a/EIPS/eip-1108.md +++ b/EIPS/eip-1108.md @@ -73,9 +73,9 @@ components because of the structure of the algorithm. Thus using a 'fair' price of 25.86 gas per microsecond, we get a gas formula of ~`35,000 * k + 45,000` gas, where `k` is the number of pairings being computed. [4] -[1]- Per [EIP-196](https://github.com/ethereum/EIPs/blob/984cf5de90bbf5fbe7e49be227b0c2f9567e661e/EIPS/eip-196.md#gas-costs). +[1]- Per [EIP-196](./eip-196.md). -[2]- Per [EIP-197](https://github.com/ethereum/EIPs/blob/df132cd37efb3986f9cd3ef4922b15a767d2c54a/EIPS/eip-197.md#specification). +[2]- Per [EIP-197](./eip-197.md). [3]- [Parity benchmarks.](https://gist.github.com/zac-williamson/838410a3da179d47d31b25b586c15e53) @@ -87,7 +87,7 @@ Thus using a 'fair' price of 25.86 gas per microsecond, we get a gas formula of Fast elliptic curve cryptography is a keystone of a growing number of protocols built on top of Ethereum. To list a few: -* [The AZTEC protocol](https://github.com/AztecProtocol/AZTEC) utilizes the elliptic curve precompiles to construct private tokens, with zero-knowledge transaction logic, via the [ERC1723](https://github.com/ethereum/EIPs/issues/1723) and [ERC1724](https://github.com/ethereum/EIPs/issues/1724) standard. +* [The AZTEC protocol](https://github.com/AztecProtocol/AZTEC) utilizes the elliptic curve precompiles to construct private tokens, with zero-knowledge transaction logic, via the [ERC-1723](https://github.com/ethereum/EIPs/issues/1723) and [ERC-1724](https://github.com/ethereum/EIPs/issues/1724) standard. * [Matter Labs](https://github.com/matter-labs/matter-network) utilizes the precompiles to implement Ignis, a scaling solution with a throughput of 500txns per second * [Rollup](https://github.com/rollup/rollup) utilizes the precompiles to create L2 scaling solutions, where the correctness of transactions is guaranteed by main-net, without an additional consensus layer * [ZEther](https://crypto.stanford.edu/~buenz/papers/zether.pdf) uses precompiles `ECADD` and `ECMUL` to construct confidential transactions @@ -115,7 +115,7 @@ If zk-SNARK verification costs are decreased, these solutions can be deployed fo ### Parity and Geth already have fast algorithms that justify reduced gas costs -This EIP does not require Parity or Geth to deploy new cryptographic libraries, as fast bn128 algorithms have already been integrated into these clients. This goal of proposing this EIP for Istanbul, is to supplement [EIP-1829](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1829.md) (arithmetic over generic elliptic curves), providing an immediate solution to the pressing problem of expensive cryptography, while more advanced solutions are developed, defined and deployed. +This EIP does not require Parity or Geth to deploy new cryptographic libraries, as fast bn128 algorithms have already been integrated into these clients. This goal of proposing this EIP for Istanbul, is to supplement [EIP-1829](./eip-1829.md) (arithmetic over generic elliptic curves), providing an immediate solution to the pressing problem of expensive cryptography, while more advanced solutions are developed, defined and deployed. ## Test Cases diff --git a/EIPS/eip-1109.md b/EIPS/eip-1109.md index 8a98507f3a490e..d666a5f2090641 100644 --- a/EIPS/eip-1109.md +++ b/EIPS/eip-1109.md @@ -21,7 +21,7 @@ This EIP tries to resolve the problem of high gas consumption when calling preco Each precompiled contract has an already defined cost for calling it. It does not make sense to add the implicit extra gas cost of the CALL opcode. -As an example, SHA256 precompiled contract costs 60 and ECADD costs 500 (proposed to costs only 50 in [EIP1108](https://github.com/ethereum/EIPs/pull/1108) . When a precompiled contract is called, 700 gas is consumed just for the CALL opcode besides the costs of the precompiled contract. +As an example, SHA256 precompiled contract costs 60 and ECADD costs 500 (proposed to costs only 50 in [EIP-1108](./eip-1108.md) . When a precompiled contract is called, 700 gas is consumed just for the CALL opcode besides the costs of the precompiled contract. This makes no sense, and right now it's impossible to define a precompiled contract whose effective cost for using it, is less than 700. diff --git a/EIPS/eip-1123.md b/EIPS/eip-1123.md index 06a2b620bcf605..b0ea91705bde6a 100644 --- a/EIPS/eip-1123.md +++ b/EIPS/eip-1123.md @@ -3,14 +3,14 @@ eip: 1123 title: Revised Ethereum Smart Contract Packaging Standard author: g. nicholas d’andrea (@gnidan), Piper Merriam (@pipermerriam), Nick Gheorghita (@njgheorghita), Danny Ryan (@djrtwo) discussions-to: https://github.com/ethereum/EIPs/issues/1123 -status: Abandoned +status: Withdrawn type: Standards Track category: ERC created: 2018-06-01 replaces: 190 --- -This ERC has been abandoned in favor of the EthPM V3 smart contract packaging standard defined in [ERC-2678](https://eips.ethereum.org/EIPS/eip-2678) +This ERC has been abandoned in favor of the EthPM V3 smart contract packaging standard defined in [ERC-2678](./eip-2678.md) Simple Summary ============== @@ -44,7 +44,7 @@ practices in mind. As version 2 of this specification, this standard seeks to address a number of areas of improvement found for the previous version (defined in -[EIP-190](https://eips.ethereum.org/EIPS/eip-190)). +[EIP-190](./eip-190.md)). This version: - Generalizes storage URIs to represent any content addressable URI @@ -1869,7 +1869,7 @@ Acknowledgements ================ The authors of this document would like to thank the original authors of -[EIP-190](https://eips.ethereum.org/EIPS/eip-190), +[EIP-190](./eip-190.md), [ETHPrize](http://ethprize.io/) for their funding support, all community [contributors](https://github.com/ethpm/ethpm-spec/graphs/contributors), diff --git a/EIPS/eip-1154.md b/EIPS/eip-1154.md index cdcfa5a8e3b06e..159bab8f2cc1f8 100644 --- a/EIPS/eip-1154.md +++ b/EIPS/eip-1154.md @@ -3,7 +3,7 @@ eip: 1154 title: Oracle Interface author: Alan Lu (@cag) discussions-to: https://github.com/ethereum/EIPs/issues/1161 -status: Abandoned +status: Withdrawn type: Standards Track category: ERC created: 2018-06-13 diff --git a/EIPS/eip-1155.md b/EIPS/eip-1155.md index e3f411314ee14c..5a509bfc7f1505 100644 --- a/EIPS/eip-1155.md +++ b/EIPS/eip-1155.md @@ -399,7 +399,7 @@ Example of such a URI: `https://token-cdn-domain/{id}.json` would be replaced wi #### Metadata Extensions -The optional `ERC1155Metadata_URI` extension can be identified with the (ERC-165 Standard Interface Detection)[https://eips.ethereum.org/EIPS/eip-165]. +The optional `ERC1155Metadata_URI` extension can be identified with the (ERC-165 Standard Interface Detection)[./eip-165.md]. If the optional `ERC1155Metadata_URI` extension is included: * The ERC-165 `supportsInterface` function MUST return the constant value `true` if `0x0e89341c` is passed through the `interfaceID` argument. @@ -440,24 +440,24 @@ This JSON schema is loosely based on the "ERC721 Metadata JSON Schema", but incl "properties": { "name": { "type": "string", - "description": "Identifies the asset to which this token represents", + "description": "Identifies the asset to which this token represents" }, "decimals": { "type": "integer", - "description": "The number of decimal places that the token amount should display - e.g. 18, means to divide the token amount by 1000000000000000000 to get its user representation.", + "description": "The number of decimal places that the token amount should display - e.g. 18, means to divide the token amount by 1000000000000000000 to get its user representation." }, "description": { "type": "string", - "description": "Describes the asset to which this token represents", + "description": "Describes the asset to which this token represents" }, "image": { "type": "string", - "description": "A URI pointing to a resource with mime type image/* representing the asset to which this token represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive.", + "description": "A URI pointing to a resource with mime type image/* representing the asset to which this token represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive." }, "properties": { "type": "object", - "description": "Arbitrary properties. Values may be strings, numbers, object or arrays.", - }, + "description": "Arbitrary properties. Values may be strings, numbers, object or arrays." + } } } ``` @@ -508,15 +508,15 @@ Metadata localization should be standardized to increase presentation uniformity }, "decimals": { "type": "integer", - "description": "The number of decimal places that the token amount should display - e.g. 18, means to divide the token amount by 1000000000000000000 to get its user representation.", + "description": "The number of decimal places that the token amount should display - e.g. 18, means to divide the token amount by 1000000000000000000 to get its user representation." }, "description": { "type": "string", - "description": "Describes the asset to which this token represents", + "description": "Describes the asset to which this token represents" }, "image": { "type": "string", - "description": "A URI pointing to a resource with mime type image/* representing the asset to which this token represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive.", + "description": "A URI pointing to a resource with mime type image/* representing the asset to which this token represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive." }, "properties": { "type": "object", @@ -539,7 +539,7 @@ Metadata localization should be standardized to increase presentation uniformity "description": "The list of locales for which data is available. These locales should conform to those defined in the Unicode Common Locale Data Repository (http://cldr.unicode.org/)." } } - }, + } } } ``` @@ -577,7 +577,7 @@ fr.json: ### Approval -The function `setApprovalForAll` allows an operator to manage one's entire set of tokens on behalf of the approver. To permit approval of a subset of token IDs, an interface such as [ERC-1761 Scoped Approval Interface](https://eips.ethereum.org/EIPS/eip-1761) is suggested. +The function `setApprovalForAll` allows an operator to manage one's entire set of tokens on behalf of the approver. To permit approval of a subset of token IDs, an interface such as [ERC-1761 Scoped Approval Interface](./eip-1761.md) is suggested. The counterpart `isApprovedForAll` provides introspection into any status set by `setApprovalForAll`. An owner SHOULD be assumed to always be able to operate on their own tokens regardless of approval status, so should SHOULD NOT have to call `setApprovalForAll` to approve themselves as an operator before they can operate on them. @@ -592,7 +592,7 @@ The `name` function (for human-readable asset names, on-chain) was removed from ### Upgrades -The requirement to emit `TransferSingle` or `TransferBatch` on balance change implies that a valid implementation of ERC-1155 redeploying to a new contract address MUST emit events from the new contract address to replicate the deprecated contract final state. It is valid to only emit a minimal number of events to reflect only the final balance and omit all the transactions that led to that state. The event emit requirement is to ensure that the current state of the contract can always be traced only through events. To alleviate the need to emit events when changing contract address, consider using the proxy pattern, such as described in [EIP-2535](https://eips.ethereum.org/EIPS/eip-2535). This will also have the added benefit of providing a stable contract address for users. +The requirement to emit `TransferSingle` or `TransferBatch` on balance change implies that a valid implementation of ERC-1155 redeploying to a new contract address MUST emit events from the new contract address to replicate the deprecated contract final state. It is valid to only emit a minimal number of events to reflect only the final balance and omit all the transactions that led to that state. The event emit requirement is to ensure that the current state of the contract can always be traced only through events. To alleviate the need to emit events when changing contract address, consider using the proxy pattern, such as described in [EIP-2535](./eip-2535.md). This will also have the added benefit of providing a stable contract address for users. ### Design decision: Supporting non-batch @@ -610,7 +610,7 @@ As the Ethereum ecosystem continues to grow, many dapps are relying on tradition The function `setApprovalForAll` allows an operator to manage one's entire set of tokens on behalf of the approver. It enables frictionless interaction with exchange and trade contracts. -Restricting approval to a certain set of token IDs, quantities or other rules MAY be done with an additional interface or an external contract. The rationale is to keep the ERC-1155 standard as generic as possible for all use-cases without imposing a specific approval scheme on implementations that may not need it. Standard token approval interfaces can be used, such as the suggested [ERC-1761 Scoped Approval Interface](https://eips.ethereum.org/EIPS/eip-1761) which is compatible with ERC-1155. +Restricting approval to a certain set of token IDs, quantities or other rules MAY be done with an additional interface or an external contract. The rationale is to keep the ERC-1155 standard as generic as possible for all use-cases without imposing a specific approval scheme on implementations that may not need it. Standard token approval interfaces can be used, such as the suggested [ERC-1761 Scoped Approval Interface](./eip-1761.md) which is compatible with ERC-1155. ## Backwards Compatibility @@ -686,9 +686,9 @@ Another simple way to represent non-fungibles is to allow a maximum value of 1 f ## References **Standards** -- [ERC-721 Non-Fungible Token Standard](https://eips.ethereum.org/EIPS/eip-721) -- [ERC-165 Standard Interface Detection](https://eips.ethereum.org/EIPS/eip-165) -- [ERC-1538 Transparent Contract Standard](https://eips.ethereum.org/EIPS/eip-1538) +- [ERC-721 Non-Fungible Token Standard](./eip-721.md) +- [ERC-165 Standard Interface Detection](./eip-165.md) +- [ERC-1538 Transparent Contract Standard](./eip-1538.md) - [JSON Schema](https://json-schema.org/) - [RFC 2119 Key words for use in RFCs to Indicate Requirement Levels](https://www.ietf.org/rfc/rfc2119.txt) diff --git a/EIPS/eip-1185.md b/EIPS/eip-1185.md index 9d8bf26b954f6f..88b9672799e43e 100644 --- a/EIPS/eip-1185.md +++ b/EIPS/eip-1185.md @@ -1,7 +1,7 @@ --- eip: 1185 title: Storage of DNS Records in ENS -author: Jim McDonald +author: Jim McDonald (@mcdee) status: Draft type: Standards Track category: ERC diff --git a/EIPS/eip-1186.md b/EIPS/eip-1186.md index f7e50df3b28aa8..7443ea22ff54ef 100644 --- a/EIPS/eip-1186.md +++ b/EIPS/eip-1186.md @@ -134,12 +134,5 @@ Since this only adds a new Method there are no issues with Backwards Compatibili TODO: Tests still need to be implemented, but the core function creating the proof already exists inside the clients and are well tested. -## Implementation - -We implemented this function for: - -- [x] [parity](https://github.com/paritytech/parity/pull/9001) (Status: pending pull request) - [Docker](https://hub.docker.com/r/slockit/parity-in3/tags/) -- [x] [geth](https://github.com/ethereum/go-ethereum/pull/17737) (Status: pending pull request) - [Docker](https://hub.docker.com/r/slockit/geth-in3/tags/) - ## Copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-1193.md b/EIPS/eip-1193.md index d6be5f2c31ff26..890310376eb783 100644 --- a/EIPS/eip-1193.md +++ b/EIPS/eip-1193.md @@ -214,7 +214,7 @@ interface ProviderConnectInfo { } ``` -`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. +`chainId` **MUST** specify the integer ID of the connected chain as a hexadecimal string, per the [`eth_chainId`](./eip-695.md) Ethereum RPC method. #### disconnect @@ -224,7 +224,7 @@ If the Provider becomes disconnected from all chains, the Provider **MUST** emit #### 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. +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`](./eip-695.md) Ethereum RPC method. #### accountsChanged @@ -295,7 +295,7 @@ It is paramount that the Provider implementer protects the user, Wallet, and Cli ### Chain Changes -Since all Ethereum operations are directed at a particular chain, it's important that the Provider accurately reflects the Client's configured chain, per the `eth_chainId` Ethereum RPC method (see [EIP-695](https://eips.ethereum.org/EIPS/eip-155)). +Since all Ethereum operations are directed at a particular chain, it's important that the Provider accurately reflects the Client's configured chain, per the `eth_chainId` Ethereum RPC method (see [EIP-695](./eip-695.md)). This includes ensuring that `eth_chainId` has the correct return value, and that the `chainChanged` event is emitted whenever that value changes. @@ -308,7 +308,7 @@ As with `eth_chainId`, it is critical that `eth_accounts` has the correct return The return value of `eth_accounts` is ultimately controlled by the Wallet or Client. In order to protect user privacy, the authors recommend not exposing any accounts by default. -Instead, Providers should support RPC methods for explicitly requesting account access, such as `eth_requestAccounts` (see [EIP-1102](https://eips.ethereum.org/EIPS/eip-1102)) or `wallet_requestPermissions` (see [EIP-2255](https://eips.ethereum.org/EIPS/eip-2255)). +Instead, Providers should support RPC methods for explicitly requesting account access, such as `eth_requestAccounts` (see [EIP-1102](./eip-1102.md)) or `wallet_requestPermissions` (see [EIP-2255](./eip-2255.md)). ## References @@ -316,10 +316,10 @@ Instead, Providers should support RPC methods for explicitly requesting account - [Deprecated Ethereum Magicians thread](https://ethereum-magicians.org/t/eip-1193-ethereum-provider-javascript-api/640) - [Continuing discussion](https://github.com/ethereum/EIPs/issues/2319) - Related EIPs - - [EIP-1102: Opt-in Account Exposure](https://eips.ethereum.org/EIPS/eip-1102) - - [EIP-1474: Remote Procedure Call Specification](https://eips.ethereum.org/EIPS/eip-1474) - - [EIP-1767: GraphQL Interface to Ethereum Node Data](https://eips.ethereum.org/EIPS/eip-1767) - - [EIP-2255: Wallet Permissions](https://eips.ethereum.org/EIPS/eip-2255) + - [EIP-1102: Opt-in Account Exposure](./eip-1102.md) + - [EIP-1474: Remote Procedure Call Specification](./eip-1474.md) + - [EIP-1767: GraphQL Interface to Ethereum Node Data](./eip-1767.md) + - [EIP-2255: Wallet Permissions](./eip-2255.md) ## Copyright @@ -349,14 +349,14 @@ Provider.request({ method: 'eth_accounts' }) ``` 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). +You can find a list of common methods [here](./eip-1474.md). #### RPC Protocols Multiple RPC protocols may be available. For examples, see: -- [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 +- [EIP-1474](./eip-1474.md), the Ethereum JSON-RPC API +- [EIP-1767](./eip-1767.md), the Ethereum GraphQL schema ### Events @@ -464,7 +464,7 @@ ethereum ethereum .request({ method: 'eth_getBlockByNumber', - params: ['latest', 'true'], + params: ['latest', true], }) .then((block) => { console.log(`Block ${block.number}:`, block); @@ -500,7 +500,7 @@ ethereum if (message.type === 'eth_subscription') { const { data } = message; if (data.subscription === subscriptionId) { - if (typeof data.result === 'string' && data.result) { + if ('result' in data && typeof data.result === 'object') { const block = data.result; console.log(`New block ${block.number}:`, block); } else { @@ -547,7 +547,7 @@ This method is superseded by [`request`](#request). Provider.sendAsync(request: Object, callback: Function): void; ``` -Historically, the request and response object interfaces have followed the [Ethereum JSON-RPC specification](https://eips.ethereum.org/EIPS/eip-1474). +Historically, the request and response object interfaces have followed the [Ethereum JSON-RPC specification](./eip-1474.md). ### send (DEPRECATED) @@ -567,7 +567,7 @@ This event is superseded by [`disconnect`](#disconnect). The event `networkChanged` is superseded by [`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). +For details, see [EIP-155: Simple replay attack protection](./eip-155.md) and [EIP-695: Create eth_chainId method for JSON-RPC](./eip-695.md). #### notification (DEPRECATED) diff --git a/EIPS/eip-1202.md b/EIPS/eip-1202.md index aa5cd118d70843..f979466c18a804 100644 --- a/EIPS/eip-1202.md +++ b/EIPS/eip-1202.md @@ -22,9 +22,9 @@ Voting is one of the earliest example of EVM programming, and also a key to DAO/ 1. Allow general UI and applications to be built on top of a standardized voting to allow more general user to participate, and encourage more DApp and DAO to think about their governance 2. Allow delegate voting / smart contract voting, automatic voting 3. Allow voting results to be recorded on-chain, in a standard way, and allow DAOs and DApps to honor the voting result programmatically. -4. Allow the compatibility with token standard such as [ERC-20](https://eips.ethereum.org/EIPS/eip-20) or other new standards([EIP-777](https://eips.ethereum.org/EIPS/eip-777)) and item standard such as [EIP-721](https://eips.ethereum.org/EIPS/eip-721) +4. Allow the compatibility with token standard such as [ERC-20](./eip-20.md) or other new standards([EIP-777](./eip-777.md)) and item standard such as [EIP-721](./eip-721.md) 5. Create massive potential for interoperability within Ethereum echo systems and other system. -6. Allow setting voting deadline, allow determine on single or multiple options. Allow requiring voting orders. (trade-off is interface complexity, we might need [ERC-20](https://eips.ethereum.org/EIPS/eip-20) approach and later a [EIP-777](https://eips.ethereum.org/EIPS/eip-777) for advanced voting) +6. Allow setting voting deadline, allow determine on single or multiple options. Allow requiring voting orders. (trade-off is interface complexity, we might need [ERC-20](./eip-20.md) approach and later a [EIP-777](./eip-777.md) for advanced voting) 7. Recording the voting with weights with token amount. 8. Possibly allow trust-worthy privacy-safe voting and anonymous voting (with either voter address being un-associated with the vote they cast, given a list of randomized/obfuscated voting options). 8 @@ -32,7 +32,7 @@ Voting is one of the earliest example of EVM programming, and also a key to DAO/ ### Use-cases: 1. Determine on issuing new token, issuing more token or issuing sub-token -2. Determine on creating new item under [EIP-721](https://eips.ethereum.org/EIPS/eip-721) +2. Determine on creating new item under [EIP-721](./eip-721.md) 3. Determine on election on certain person or smart contract to be delegated leader for project or subproject 4. Determine on auditing result ownership allowing migration of smart contract proxy address @@ -116,17 +116,17 @@ The fourth consideration is potential abuse. When voting is standardized and put ## Bibliography ### Related EIPs - - [EIP-20: ERC-20 Token Standard (a.k.a. ERC-20)](https://eips.ethereum.org/EIPS/eip-20) - - [EIP-165: Standard Interface Detection](https://eips.ethereum.org/EIPS/eip-165) - - [EIP-721: Non-Fungible Token Standard(a.k.a. ERC-721)](https://eips.ethereum.org/EIPS/eip-721) + - [EIP-20: ERC-20 Token Standard (a.k.a. ERC-20)](./eip-20.md) + - [EIP-165: Standard Interface Detection](./eip-165.md) + - [EIP-721: Non-Fungible Token Standard(a.k.a. ERC-721)](./eip-721.md) - [EIP-735: ERC: Claim Holder](https://github.com/ethereum/EIPs/issues/735) - [EIP-780: ERC: Ethereum Claims Registry](https://github.com/ethereum/EIPs/issues/780) - - [EIP-777: A New Advanced Token Standard](https://eips.ethereum.org/EIPS/eip-777) - - [EIP-897: ERC DelegateProxy](https://eips.ethereum.org/EIPS/eip-897) - - [EIP-1155: Crypto Item Standard](https://eips.ethereum.org/EIPS/eip-1155) - - [EIP-1178: Multi-class Token Standard](https://eips.ethereum.org/EIPS/eip-1178) - - [EIP-1167: Minimal Proxy Contract](https://eips.ethereum.org/EIPS/eip-1167) - - [EIP-1203: Multi-class Token Standard(ERC-20 Extension)](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1203.md) + - [EIP-777: A New Advanced Token Standard](./eip-777.md) + - [EIP-897: ERC DelegateProxy](./eip-897.md) + - [EIP-1155: Crypto Item Standard](./eip-1155.md) + - [EIP-1178: Multi-class Token Standard](./eip-1178.md) + - [EIP-1167: Minimal Proxy Contract](./eip-1167.md) + - [EIP-1203: Multi-class Token Standard(ERC-20 Extension)](./eip-1203.md) ### Worthnoting Projects - [Ethereum DAO: How to build a DEMOCRACY on the blockchain](https://www.ethereum.org/dao) diff --git a/EIPS/eip-1203.md b/EIPS/eip-1203.md index d4e30c9e877415..12ccfba22872df 100644 --- a/EIPS/eip-1203.md +++ b/EIPS/eip-1203.md @@ -67,7 +67,7 @@ contract ERC1203 is ERC20 { ### ERC-20 Methods and Events (fully compatible) -Please see [ERC-20 Token Standard](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md) for detailed specifications. Do note that these methods and events only work on the "default" class of an MCT. +Please see [ERC-20 Token Standard](./eip-20.md) for detailed specifications. Do note that these methods and events only work on the "default" class of an MCT. ```solidity function totalSupply() public view returns (uint256); @@ -222,9 +222,9 @@ The repository at [jeffishjeff/ERC-1203](https://github.com/jeffishjeff/ERC-1203 The repository at [jeffishjeff/ERC-1203](https://github.com/jeffishjeff/ERC-1203) contains the [sample implementation](https://github.com/jeffishjeff/ERC-1203/blob/master/token.sol). ## References -- ERC-20 Token Standard. https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md -- ERC-721 Non-Fungible Token Standard. https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md -- ERC-1178 Multi-class Token Standard. https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1178.md +- ERC-20 Token Standard. ./eip-20.md +- ERC-721 Non-Fungible Token Standard. ./eip-721.md +- ERC-1178 Multi-class Token Standard. ./eip-1178.md ## Copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-1227.md b/EIPS/eip-1227.md index 6bc6da904bb204..be566ead875d12 100644 --- a/EIPS/eip-1227.md +++ b/EIPS/eip-1227.md @@ -17,13 +17,13 @@ This EIP proposes to permanently disable the "difficulty bomb" and reset the blo Starting with `FORK_BLKNUM` the client will calculate the difficulty without the additional exponential component. Furthermore, block rewards will be adjusted to a base of 5 ETH, uncle and nephew rewards will be adjusted accordingly. ## Motivation -Due to the "difficulty bomb" (also known as the "ice age"), introduced in EIP [#2](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2.md), an artificial exponential increase in difficulty until chain freeze, users may find it much more challenging to remain on the unforked chain after a hard-fork. This is a desirable effect of the ice age (in fact, its only stated purpose) in the case of a scheduled network upgrade, but is especially problematic when a hard-fork includes a controversial change. +Due to the "difficulty bomb" (also known as the "ice age"), introduced in EIP [#2](./eip-2.md), an artificial exponential increase in difficulty until chain freeze, users may find it much more challenging to remain on the unforked chain after a hard-fork. This is a desirable effect of the ice age (in fact, its only stated purpose) in the case of a scheduled network upgrade, but is especially problematic when a hard-fork includes a controversial change. -This situation has already been observed: during the Byzantium hard-fork users were given the "choice" of following the upgraded side of the chain or remaining on the original chain, the latter already experiencing block times greater than 30 seconds. In reality one will find that organizing a disperse and decentralized set of individuals to keep the original, soon-to-be-dead chain alive under such conditions impossible. This is exacerbated when a controversial change, such as EIP [#649](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-649.md), is merged in so close to the hard-fork date, as users cannot be organized to take an educated stance for or against the change on such short notice. +This situation has already been observed: during the Byzantium hard-fork users were given the "choice" of following the upgraded side of the chain or remaining on the original chain, the latter already experiencing block times greater than 30 seconds. In reality one will find that organizing a disperse and decentralized set of individuals to keep the original, soon-to-be-dead chain alive under such conditions impossible. This is exacerbated when a controversial change, such as EIP [#649](./eip-649.md), is merged in so close to the hard-fork date, as users cannot be organized to take an educated stance for or against the change on such short notice. Ultimately, the difficulty bomb serves but a single purpose: make it more difficult to keep the original chain alive after a hard-fork. This is unacceptable if the only way the community can make their voice heard is running/not running client software, and not through the EIP process, since they effectively have no choice and therefore no power. This EIP proposes to completely eliminate the difficulty bomb, returning some measure of power over Ethereum's governance process to the users, to the community. -Given the controversy surrounding the directly relevant EIP [#649](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-649.md), the issuance should also be reset to pre-Byzantium levels. It may be reduced again at a later time via a new hard-fork, only this time users would actually have a meaningful choice in accepting the change or not. Note: the issuance reduction is not the focus of this proposal, and is optional; the defusing of the difficulty bomb is of primary concern. +Given the controversy surrounding the directly relevant EIP [#649](./eip-649.md), the issuance should also be reset to pre-Byzantium levels. It may be reduced again at a later time via a new hard-fork, only this time users would actually have a meaningful choice in accepting the change or not. Note: the issuance reduction is not the focus of this proposal, and is optional; the defusing of the difficulty bomb is of primary concern. ## Specification #### Remove Exponential Component of Difficulty Adjustment @@ -49,7 +49,7 @@ The nephew reward for `block.number >= FORK_BLKNUM` is This is the existing pre-Byzantium formula for nephew rewards, simply adjusted with `new_block_reward`. ## Rationale -This will permanently, without further changes, disable the "ice age." It will also reset the block reward to pre-Byzantium levels. Both of these changes are specified similarly to EIP [#649](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-649.md), so they should require only minimal changes from client developers. +This will permanently, without further changes, disable the "ice age." It will also reset the block reward to pre-Byzantium levels. Both of these changes are specified similarly to EIP [#649](./eip-649.md), so they should require only minimal changes from client developers. ## Backwards Compatibility This EIP is not forward compatible and introduces backwards incompatibilities in the difficulty calculation, as well as the block, uncle and nephew reward structure. However, it may be controversial in nature among different sections of the userbase—the very problem this EIP is made to address. Therefore, it should not be included in a scheduled hardfork at a certain block number. It is suggested to implement this EIP in an isolated hard-fork before the second of the two Metropolis hard-forks. diff --git a/EIPS/eip-1234.md b/EIPS/eip-1234.md index 5cf44307ef3793..c4363d36dbb59e 100644 --- a/EIPS/eip-1234.md +++ b/EIPS/eip-1234.md @@ -55,7 +55,7 @@ This EIP is not forward compatible and introduces backwards incompatibilities in Test cases shall be created once the specification is to be accepted by the developers or implemented by the clients. ## Implementation -The implementation in it's logic does not differ from [EIP-649](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-649.md); an implementation for Parity-Ethereum is available in [parity-ethereum#9187](https://github.com/paritytech/parity-ethereum/pull/9187). +The implementation in it's logic does not differ from [EIP-649](./eip-649.md); an implementation for Parity-Ethereum is available in [parity-ethereum#9187](https://github.com/paritytech/parity-ethereum/pull/9187). ## Copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-1240.md b/EIPS/eip-1240.md index 6f847409654dff..f20570a91fb2b1 100644 --- a/EIPS/eip-1240.md +++ b/EIPS/eip-1240.md @@ -5,7 +5,7 @@ author: Micah Zoltu (@MicahZoltu) discussions-to: https://ethereum-magicians.org/t/difficulty-bomb-removal/832 type: Standards Track category: Core -status: Abandoned +status: Withdrawn created: 2018-07-21 --- diff --git a/EIPS/eip-1261.md b/EIPS/eip-1261.md index 022a3ed8ee114a..d8224f77635652 100644 --- a/EIPS/eip-1261.md +++ b/EIPS/eip-1261.md @@ -361,10 +361,10 @@ Membership Verification Token ERC1261 -- a reference implementation **Standards** -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-725/735 Claim Registry https://eips.ethereum.org/EIPS/eip-725 -1. ERC-173 Owned Standard. https://eips.ethereum.org/EIPS/eip-173 +1. ERC-20 Token Standard. ./eip-20.md +1. ERC-165 Standard Interface Detection. ./eip-165.md +1. ERC-725/735 Claim Registry ./eip-725.md +1. ERC-173 Owned Standard. ./eip-173.md 1. JSON Schema. https://json-schema.org/ 1. Multiaddr. https://github.com/multiformats/multiaddr 1. RFC 2119 Key words for use in RFCs to Indicate Requirement Levels. https://www.ietf.org/rfc/rfc2119.txt diff --git a/EIPS/eip-1271.md b/EIPS/eip-1271.md index 7a76a2f53fbc9e..8241665759def7 100644 --- a/EIPS/eip-1271.md +++ b/EIPS/eip-1271.md @@ -19,7 +19,7 @@ Externally Owned Accounts (EOA) can sign messages with their associated private In the future, it is likely that many users will hold their assets in a smart contract instead of holding them in their externally owned account directly since contracts can improve user experience significantly while providing extra security. This means that contracts using signature based functions should not assume that a given address can provide ECDSA signatures. Otherwise, identity based contracts and contracts holding assets may not be able to interact with functions requiring ECDSA signatures directly. -Here, we use the term *smart account* to refer to any contract that acts as an account, which can include identity based methods (e.g. [ERC-725](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md) & [ERC-1078](https://github.com/alexvandesande/EIPs/blob/ee2347027e94b93708939f2e448447d030ca2d76/EIPS/eip-1078.md)), asset ownership (e.g. Multisigs, proxy contracts) and/or executable signed messages methods (e.g. [ERC-1077)](https://github.com/alexvandesande/EIPs/blob/ee2347027e94b93708939f2e448447d030ca2d76/EIPS/eip-1077.md). This terminology is important for the reader to better distinguish a contract that acts as an account (e.g. a multisig, wallet or [Gnosis Safe](https://github.com/gnosis/safe-contracts) contract) and a contract that does not act as an account but requires signatures. +Here, we use the term *smart account* to refer to any contract that acts as an account, which can include identity based methods (e.g. [ERC-725](./eip-725.md) & [ERC-1078](./eip-1078.md)), asset ownership (e.g. Multisigs, proxy contracts) and/or executable signed messages methods (e.g. [ERC-1077)](https://github.com/alexvandesande/EIPs/blob/ee2347027e94b93708939f2e448447d030ca2d76/EIPS/eip-1077.md). This terminology is important for the reader to better distinguish a contract that acts as an account (e.g. a multisig, wallet or [Gnosis Safe](https://github.com/gnosis/safe-contracts) contract) and a contract that does not act as an account but requires signatures. One example of an application that requires addresses to provide signatures would be decentralized exchanges with off-chain orderbook, where buy/sell orders are signed messages (see [0x](https://0xproject.com/) and [etherdelta](https://etherdelta.com/) for examples). In these applications, EOAs sign orders, signaling their desire to buy/sell a given asset and giving explicit permissions to the exchange smart contracts to conclude a trade via an ECDSA signature. When it comes to contracts however, ECDSA signature is not possible since contracts do not possess a private key. In the first version of the 0x protocol, smart contracts could not generate buy/sell orders for this very reason, as the `maker` needed to both own the assets *and* sign the order via ECDSA method. This was revised in their protocol version 2 (see below). @@ -37,7 +37,7 @@ contract ERC1271 { /** * @dev Should return whether the signature provided is valid for the provided data - * @param _data Arbitrary length data signed on the behalf of address(this) + * @param _hash Hash of the data to be signed * @param _signature Signature byte array associated with _data * * MUST return the bytes4 magic value 0x1626ba7e when function passes. diff --git a/EIPS/eip-1276.md b/EIPS/eip-1276.md index 5ba312529ec09a..d5bcc711b3a4c0 100644 --- a/EIPS/eip-1276.md +++ b/EIPS/eip-1276.md @@ -48,7 +48,7 @@ This is the existing pre-Constantinople formula for nephew rewards, simply adjus ## Rationale This will completely remove the difficulty bomb on difficulty adjustment algorithm without delaying the difficulty bomb again, therefore it is possible to prevent network delay on the beginning of 2019. -This EIP-1276 opposes directly the intent of [EIP-1234](https://eips.ethereum.org/EIPS/eip-1234) which should be also considered in discussions. +This EIP-1276 opposes directly the intent of [EIP-1234](./eip-1234.md) which should be also considered in discussions. ## Backwards Compatibility This EIP is not forward compatible and introduces backwards incompatibilities in the difficulty calculation, as well as the block, uncle and nephew reward structure. Therefore, it should be included in a scheduled hardfork at a certain block number. It's suggested to include this EIP in the second Metropolis hard-fork, _Constantinople_. diff --git a/EIPS/eip-1319.md b/EIPS/eip-1319.md index f494166d5783e2..94991c0a9c877c 100644 --- a/EIPS/eip-1319.md +++ b/EIPS/eip-1319.md @@ -13,7 +13,7 @@ discussions-to: https://github.com/ethereum/EIPs/issues/1319 A standard interface for smart contract package registries. ## Abstract -This EIP specifies an interface for publishing to and retrieving assets from smart contract package registries. It is a companion EIP to [1123](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1123.md) which defines a standard for smart contract package manifests. +This EIP specifies an interface for publishing to and retrieving assets from smart contract package registries. It is a companion EIP to [1123](./eip-1123.md) which defines a standard for smart contract package manifests. ## Motivation The goal is to establish a framework that allows smart contract publishers to design and deploy code registries with arbitrary business logic while exposing a set of common endpoints that tooling can use to retrieve assets for contract consumers. @@ -39,8 +39,8 @@ The specification describes a small read/write API whose components are mandator + a **package** is a collection of **releases** + a **package** is identified by a unique string name and unique bytes32 **packageId** within a given **registry** + a **release** is identified by a `bytes32` **releaseId** which must be unique for a given package name and release version string pair. -+ a **releaseId** maps to a set of data that includes a **manifestURI** string which describes the location of an [EIP 1123 package manifest](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1123.md). This manifest contains data about the release including the location of its component code assets. -+ a **manifestURI** is a URI as defined by [RFC3986](https://tools.ietf.org/html/rfc3986) which can be used to retrieve the contents of the package manifest. In addition to validation against RFC3986, each **manifestURI** must also contain a hash of the content as specified in the [EIP 1123](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1123.md). ++ a **releaseId** maps to a set of data that includes a **manifestURI** string which describes the location of an [EIP 1123 package manifest](./eip-1123.md). This manifest contains data about the release including the location of its component code assets. ++ a **manifestURI** is a URI as defined by [RFC3986](https://tools.ietf.org/html/rfc3986) which can be used to retrieve the contents of the package manifest. In addition to validation against RFC3986, each **manifestURI** must also contain a hash of the content as specified in the [EIP-1123](./eip-1123.md). ### Examples @@ -164,7 +164,7 @@ release versions while allowing them to use any versioning schema they choose. + Provide the minimum set of getter methods needed to retrieve package data from a registry so that registry aggregators can read all of their data. + Define a standard query that synthesizes a release identifier from a package name and version pair so that tooling can resolve specific package version requests without needing to query a registry about all of a package's releases. -Registries may offer more complex `read` APIs that manage requests for packages within a semver range or at `latest` etc. This EIP is agnostic about how tooling or registries might implement these. It recommends that registries implement [EIP 165](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md) and avail themselves of resources to publish more complex interfaces such as [EIP 926](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-926.md). +Registries may offer more complex `read` APIs that manage requests for packages within a semver range or at `latest` etc. This EIP is agnostic about how tooling or registries might implement these. It recommends that registries implement [EIP-165](./eip-165.md) and avail themselves of resources to publish more complex interfaces such as [EIP-926](./eip-926.md). ## Backwards Compatibility No existing standard exists for package registries. The package registry currently deployed by EthPM would not comply with the standard since it implements only one of the method signatures described in the specification. diff --git a/EIPS/eip-1344.md b/EIPS/eip-1344.md index 10684a31b9239f..f10106a0016d3d 100644 --- a/EIPS/eip-1344.md +++ b/EIPS/eip-1344.md @@ -14,7 +14,7 @@ requires: 155 This EIP adds an opcode that returns the current chain's EIP-155 unique identifier. ## Motivation -[EIP-155](https://eips.ethereum.org/EIPS/eip-155) proposes to use the chain ID to prevent replay attacks between different chains. It would be a great benefit to have the same possibility inside smart contracts when handling signatures, especially for Layer 2 signature schemes using [EIP-712](https://eips.ethereum.org/EIPS/eip-712). +[EIP-155](./eip-155.md) proposes to use the chain ID to prevent replay attacks between different chains. It would be a great benefit to have the same possibility inside smart contracts when handling signatures, especially for Layer 2 signature schemes using [EIP-712](./eip-712.md). ## Specification Adds a new opcode `CHAINID` at 0x46, which uses 0 stack arguments. It pushes the current chain ID onto the stack. Chain ID is a 256-bit value. The operation costs `G_base` to execute. @@ -37,7 +37,7 @@ This proposed opcode would be the simplest possible way to implement this functi This EIP is fully backwards compatible with all chains which implement EIP-155 chain ID domain separator for transaction signing. ## References -This was previously suggested as part of [EIP901](https://github.com/ethereum/EIPs/issues/901). +This was previously suggested as part of [EIP-901](https://github.com/ethereum/EIPs/issues/901). ## Test Cases Test Cases added to [ethereum/tests](https://github.com/ethereum/tests/pull/627) diff --git a/EIPS/eip-1355.md b/EIPS/eip-1355.md index 18fecc6d3ee599..dba48d45c8e780 100644 --- a/EIPS/eip-1355.md +++ b/EIPS/eip-1355.md @@ -3,7 +3,7 @@ eip: 1355 title: Ethash 1a author: Paweł Bylica (@chfast), Jean M. Cyr (@jean-m-cyr) discussions-to: https://ethereum-magicians.org/t/eip-1355-ethash-1a/1167 -status: Abandoned +status: Withdrawn type: Standards Track category: Core created: 2018-08-26 diff --git a/EIPS/eip-1363.md b/EIPS/eip-1363.md index b459d5b86f948b..007b7db1df6dba 100644 --- a/EIPS/eip-1363.md +++ b/EIPS/eip-1363.md @@ -3,8 +3,7 @@ eip: 1363 title: ERC-1363 Payable Token author: Vittorio Minacori (@vittominacori) discussions-to: https://github.com/ethereum/eips/issues/1363 -status: Last Call -review-period-end: 2020-09-30 +status: Final type: Standards Track category: ERC created: 2020-01-31 @@ -12,21 +11,36 @@ requires: 20, 165 --- ## Simple Summary -Defines a token interface for ERC-20 tokens that supports executing recipient code on `transfer` or spender code on `approve`. +Defines a token interface for [ERC-20](./eip-20.md) tokens that supports executing recipient code after `transfer` or `transferFrom`, or spender code after `approve`. ## Abstract -The following describes standard functions a token contract and contracts working with specified token can implement to make a Token Payable. +Standard functions a token contract and contracts working with tokens can implement to make a token Payable. + +`transferAndCall` and `transferFromAndCall` will call an `onTransferReceived` on a `ERC1363Receiver` contract. + +`approveAndCall` will call an `onApprovalReceived` on a `ERC1363Spender` contract. ## Motivation -This proposal allows to implement an ERC-20 compatible token that can be used for payments. +There is no way to execute code after a [ERC-20](./eip-20.md) transfer or approval (i.e. making a payment), so to make an action it is required to send another transaction and pay GAS twice. + +This proposal wants to make token payments easier and working without the use of any other listener. It allows to make a callback after a transfer or approval in a single transaction. + +There are many proposed uses of Ethereum smart contracts that can accept [ERC-20](./eip-20.md) payments. + +Examples could be +* to create a token payable crowdsale +* selling services for tokens +* paying invoices +* making subscriptions -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. +For these reasons it was named as **"Payable Token"**. -This proposal is inspired by the ERC-721 `onERC721Received` and `ERC721TokenReceiver` behaviours. +Anyway you can use it for specific utilities or for any other purposes who require the execution of a callback after a transfer or approval received. + +This proposal has been inspired by the [ERC-721](./eip-721.md) `onERC721Received` and `ERC721TokenReceiver` behaviours. ## Specification -Every Payable Token compliant contract **MUST** implement the ERC-1363 interface as well as the ERC-20 and ERC-165 interfaces. +Implementing contracts **MUST** implement the [ERC-1363](./eip-1363.md) interface as well as the [ERC-20](./eip-20.md) and [ERC-165](./eip-165.md) interfaces. ```solidity pragma solidity ^0.7.0; @@ -184,23 +198,15 @@ interface ERC1363Spender { ``` ## 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. +The choice to use `transferAndCall`, `transferFromAndCall` and `approveAndCall` derives from the [ERC-20](./eip-20.md) naming. They want to highlight that they have the same behaviours of `transfer`, `transferFrom` and `approve` with the addition of a callback on receiver or spender. ## 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) +This proposal has been inspired also by [ERC-223](https://github.com/ethereum/EIPs/issues/223) and [ERC-677](https://github.com/ethereum/EIPs/issues/677) but it uses the [ERC-721](./eip-721.md) approach, so it doesn't override the [ERC-20](./eip-20.md) `transfer` and `transferFrom` methods and defines the interfaces IDs to be implemented maintaining the [ERC-20](./eip-20.md) backwards compatibility. ## Security Considerations -The `appeoveAndCall` and `transferFromAndCall` methods can be affected by the same issue of the standard ERC-20 `approve` and `transferFrom` method. +The `approveAndCall` and `transferFromAndCall` methods can be affected by the same issue of the standard [ERC-20](./eip-20.md) `approve` and `transferFrom` method. -Changing an allowance with the `appeoveAndCall` methods brings the risk that someone may use both the old and the new allowance by unfortunate transaction ordering. +Changing an allowance with the `approveAndCall` methods 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 ([EIP-20#issuecomment-263524729](https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729)). diff --git a/EIPS/eip-137.md b/EIPS/eip-137.md index d32297b2322402..b35e9ef62c2649 100644 --- a/EIPS/eip-137.md +++ b/EIPS/eip-137.md @@ -163,7 +163,7 @@ Resolvers have one mandatory function: function supportsInterface(bytes4 interfaceID) constant returns (bool) ``` -The `supportsInterface` function is documented in [EIP-165](https://eips.ethereum.org/EIPS/eip-165), and returns true if the resolver implements the interface specified by the provided 4 byte identifier. An interface identifier consists of the XOR of the function signature hashes of the functions provided by that interface; in the degenerate case of single-function interfaces, it is simply equal to the signature hash of that function. If a resolver returns `true` for `supportsInterface()`, it must implement the functions specified in that interface. +The `supportsInterface` function is documented in [EIP-165](./eip-165.md), and returns true if the resolver implements the interface specified by the provided 4 byte identifier. An interface identifier consists of the XOR of the function signature hashes of the functions provided by that interface; in the degenerate case of single-function interfaces, it is simply equal to the signature hash of that function. If a resolver returns `true` for `supportsInterface()`, it must implement the functions specified in that interface. `supportsInterface` must always return true for `0x01ffc9a7`, which is the interface ID of `supportsInterface` itself. diff --git a/EIPS/eip-1417.md b/EIPS/eip-1417.md index f30735effc242a..aa9f51c36821d1 100644 --- a/EIPS/eip-1417.md +++ b/EIPS/eip-1417.md @@ -21,7 +21,7 @@ A standard interface for Polls to be used with EIP-1261 (MVT). ## Abstract -The following standard allows for the implementation of a standard API for polls to be used with MVTs (refer [EIP-1261](https://eips.ethereum.org/EIPS/eip-1261)). The standard provides basic functionality to vote, unvote, tally votes, get voter turnout, and a lot more. The poll standard attempts to modularize blockchain voting by breaking down a poll into 4 crucial building blocks: voterbase qualification, vote weight calculation, vote consequences, and vote tallying. By creating a common interface for polls that have different kinds of building blocks, the poll standard makes it possible to make interactive front end applications which can seamlessly get data from a poll contract in order to bring transparency into consensus and decision making on the blockchain. +The following standard allows for the implementation of a standard API for polls to be used with MVTs (refer [EIP-1261](./eip-1261.md)). The standard provides basic functionality to vote, unvote, tally votes, get voter turnout, and a lot more. The poll standard attempts to modularize blockchain voting by breaking down a poll into 4 crucial building blocks: voterbase qualification, vote weight calculation, vote consequences, and vote tallying. By creating a common interface for polls that have different kinds of building blocks, the poll standard makes it possible to make interactive front end applications which can seamlessly get data from a poll contract in order to bring transparency into consensus and decision making on the blockchain. We considered the usage of polls with MVTs because MVTs serve as a permissioning mechanism. The manual permissioning of polls allows for vote weightage functions to take up several shapes and forms. Hence the voterbase function applies several logical checks on the vote sender to confirm that they are member(see EIP 1261) of a certain entity or combination of entities. For the specification of the nature of voting, we define the vote weight function. The vote weight function decides how much of vote share each voter will receive and this can be based on several criteria, some of which are listed below in this article. There are certain kinds of polls that enforce certain consequences on the voter, for example a poll may require a voter to lock in a certain amount of tokens, or require the voter to pay a small fee. These on-chain consequences can be coded into the consequence module of the poll standard. Finally, the last module is where the votes are added. A ballot for each candidate is updated whenever relevant, depending on the vote value, and the corresponding NoV count(number of voters). This module is common for most polls, and is the most straightforward. Polls may be time bound, ie. having a finish time, after which no votes are recorded, or be unbound, such that there is no finish time. The following are some examples of specific polls which leverage the flexibility of the poll standard, and it is possible to come up with several others: @@ -60,7 +60,7 @@ All that being said, we are very excited to share our proposal with the communit 1. Building applications (pollscan.io) on top of a standardized voting interface enables transparency and encourage more DAO/DAICO's to act responsibly in terms of governance 2. Create Action contracts which take actions programmatically based on the result of a poll -3. Allow the compatibility with token standard such as [ERC-20](https://eips.ethereum.org/EIPS/eip-20) or (https://eips.ethereum.org/EIPS/eip-777)) and membership standard such as [EIP-1261](https://eips.ethereum.org/EIPS/eip-1261) +3. Allow the compatibility with token standard such as [ERC-20](./eip-20.md) or (./eip-777.md)) and membership standard such as [EIP-1261](./eip-1261.md) 4. Flexibility allows for various voting schemes including but not limited to modern schemes such as PLCR Voting ### Use-cases: @@ -257,10 +257,10 @@ Voting Standard -- a reference implementation **Standards** -- [EIP-20: ERC-20 Token Standard (a.k.a. ERC-20)](https://eips.ethereum.org/EIPS/eip-20) -- [EIP-165: Standard Interface Detection](https://eips.ethereum.org/EIPS/eip-165) -- [EIP-721: Non-Fungible Token Standard(a.k.a. ERC-721)](https://eips.ethereum.org/EIPS/eip-721) -- [ERC-1261 MV Token Standard](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1261.md) +- [EIP-20: ERC-20 Token Standard (a.k.a. ERC-20)](./eip-20.md) +- [EIP-165: Standard Interface Detection](./eip-165.md) +- [EIP-721: Non-Fungible Token Standard(a.k.a. ERC-721)](./eip-721.md) +- [ERC-1261 MV Token Standard](./eip-1261.md) - [RFC 2119 Key words for use in RFCs to Indicate Requirement Levels](https://www.ietf.org/rfc/rfc2119.txt) **Issues** diff --git a/EIPS/eip-1444.md b/EIPS/eip-1444.md index b46d4f58e7dcae..4977ed7de67e0a 100644 --- a/EIPS/eip-1444.md +++ b/EIPS/eip-1444.md @@ -23,7 +23,7 @@ There are many cases where an end user needs feedback or instruction from a smar Returning a hard-coded string (typically in English) only serves a small segment of the global population. This standard proposes a method to allow users to create, register, share, and use a decentralized collection of translations, enabling richer messaging that is more culturally and linguistically diverse. -There are several machine efficient ways of representing intent, status, state transition, and other semantic signals including booleans, enums and [ERC-1066 codes](https://eips.ethereum.org/EIPS/eip-1066). By providing human-readable messages for these signals, the developer experience is enhanced by returning easier to consume information with more context (ex. `revert`). End user experience is enhanced by providing text that can be propagated up to the UI. +There are several machine efficient ways of representing intent, status, state transition, and other semantic signals including booleans, enums and [ERC-1066 codes](./eip-1066.md). By providing human-readable messages for these signals, the developer experience is enhanced by returning easier to consume information with more context (ex. `revert`). End user experience is enhanced by providing text that can be propagated up to the UI. ## Specification @@ -135,7 +135,7 @@ Text with 2 or more arguments SHOULD use the POSIX parameter field extension. `bytes32` is very efficient since it is the EVM's base word size. Given the enormous number of elements (card(A) > 1.1579 × 1077), it can embed nearly any practical signal, enum, or state. In cases where an application's key is longer than `bytes32`, hashing that long key can map that value into the correct width. -Designs that use datatypes with small widths than `bytes32` (such as `bytes1` in [ERC-1066](https://eips.ethereum.org/EIPS/eip-1066)) can be directly embedded into the larger width. This is a trivial one-to-one mapping of the smaller set into the the larger one. +Designs that use datatypes with small widths than `bytes32` (such as `bytes1` in [ERC-1066](./eip-1066.md)) can be directly embedded into the larger width. This is a trivial one-to-one mapping of the smaller set into the the larger one. ### Local vs Globals and Singletons diff --git a/EIPS/eip-1450.md b/EIPS/eip-1450.md index c7f17a73872b09..c905b7a2d4f783 100644 --- a/EIPS/eip-1450.md +++ b/EIPS/eip-1450.md @@ -301,7 +301,7 @@ Investors may “lose” their credentials for a number of reasons: they simply If an Investor (or, say, the Investor’s heir) loses their credentials, the Investor must go through a notarized process to notify the RTA of the situation and supply a new Investor address. From there, the RTA can `mint` the “lost” securities to the new Investor address and `burnFrom` the old Investor address (because the RTA knows all Investors’ addresses). ## Rationale -The are currently no token standards that facilitate compliance with SEC regulations. The closest token is [ERC-884 (Delaware General Corporations Law (DGCL) compatible share token)](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-884.md) which states that SEC requirements are out of scope. [EIP-1404 (Simple Restricted Token Standard)](https://github.com/ethereum/EIPs/issues/1404) does not go far enough to address SEC requirements around re-issuing securities to Investors. +The are currently no token standards that facilitate compliance with SEC regulations. The closest token is [ERC-884 (Delaware General Corporations Law (DGCL) compatible share token)](./eip-884.md) which states that SEC requirements are out of scope. [EIP-1404 (Simple Restricted Token Standard)](https://github.com/ethereum/EIPs/issues/1404) does not go far enough to address SEC requirements around re-issuing securities to Investors. ## Backwards Compatibility `ERC-1450` maintains compatibility with ERC-20 tokens with the following stipulations: diff --git a/EIPS/eip-1459.md b/EIPS/eip-1459.md index 9c269fe8a65583..e559fc2bd8110a 100644 --- a/EIPS/eip-1459.md +++ b/EIPS/eip-1459.md @@ -32,7 +32,7 @@ configure the client to use the provider's list. # Specification -A 'node list' is a list of 'node records' [as defined by EIP-778](https://eips.ethereum.org/EIPS/eip-778) +A 'node list' is a list of 'node records' [as defined by EIP-778](./eip-778.md) of arbitrary length. Lists may refer to other lists using links. The entire list is signed using a secp256k1 private key. The corresponding public key must be known to the client diff --git a/EIPS/eip-1462.md b/EIPS/eip-1462.md index 72196c51956d3e..6893c3878b889f 100644 --- a/EIPS/eip-1462.md +++ b/EIPS/eip-1462.md @@ -16,7 +16,7 @@ An extension to ERC-20 standard token that provides compliance with securities r ## Abstract -This EIP defines a minimal set of additions to the default token standard such as [ERC-20](https://eips.ethereum.org/EIPS/eip-20), that allows for compliance with domestic and international legal requirements. Such requirements include KYC (Know Your Customer) and AML (Anti Money Laundering) regulations, and the ability to lock tokens for an account, and restrict them from transfer due to a legal dispute. Also the ability to attach additional legal documentation, in order to set up a dual-binding relationship between the token and off-chain legal entities. +This EIP defines a minimal set of additions to the default token standard such as [ERC-20](./eip-20.md), that allows for compliance with domestic and international legal requirements. Such requirements include KYC (Know Your Customer) and AML (Anti Money Laundering) regulations, and the ability to lock tokens for an account, and restrict them from transfer due to a legal dispute. Also the ability to attach additional legal documentation, in order to set up a dual-binding relationship between the token and off-chain legal entities. The scope of this standard is being kept as narrow as possible to avoid restricting potential use-cases of this base security token. Any additional functionality and limitations not defined in this standard may be enforced on per-project basis. @@ -24,7 +24,7 @@ The scope of this standard is being kept as narrow as possible to avoid restrict There are several security token standards that have been proposed recently. Examples include [ERC-1400](https://github.com/ethereum/EIPs/issues/1411), also [ERC-1450](https://eips.ethereum.org/EIPS/eip-1450). We have concerns about each of them, mostly because the scope of each of these EIPs contains many project-specific or market-specific details. Since many EIPs are coming from the respective backing companies, they capture many niche requirements that are excessive for a general case. -For instance, ERC-1411 uses dependency on [ERC-1410](https://github.com/ethereum/eips/issues/1410) but it falls out of the "security tokens" scope. Also its dependency on [ERC-777](https://eips.ethereum.org/EIPS/eip-777) will block the adoption for a quite period of time before ERC-777 is finalized, but the integration guidelines for existing ERC-20 workflows are not described in that EIP, yet. Another attempt to make a much simpler base standard [ERC-1404](https://github.com/ethereum/EIPs/issues/1404) is missing a few important points, specifically it doesn't provide enough granularity to distinguish between different ERC-20 transfer functions such as `transfer` and `transferFrom`. It also doesn't provide a way to bind legal documentation to the issued tokens. +For instance, ERC-1411 uses dependency on [ERC-1410](https://github.com/ethereum/eips/issues/1410) but it falls out of the "security tokens" scope. Also its dependency on [ERC-777](./eip-777.md) will block the adoption for a quite period of time before ERC-777 is finalized, but the integration guidelines for existing ERC-20 workflows are not described in that EIP, yet. Another attempt to make a much simpler base standard [ERC-1404](https://github.com/ethereum/EIPs/issues/1404) is missing a few important points, specifically it doesn't provide enough granularity to distinguish between different ERC-20 transfer functions such as `transfer` and `transferFrom`. It also doesn't provide a way to bind legal documentation to the issued tokens. What we propose in this EIP is a simple and very modular solution for creating a base security token for the widest possible scope of applications, so it can be used by other issuers to build upon. The issuers should be able to add more restrictions and policies to the token, using the functions and implementation proposed below, but they must not be limited in any way while using this ERC. @@ -65,15 +65,15 @@ interface BaseSecurityToken /* is ERC-20 */ { We introduce four new functions that should be used to check that the actions are allowed for the provided inputs. The implementation details of each function are left for the token issuer, it is the issuer's responsibility to add all necessary checks that will validate an operation in accordance with KYC/AML policies and legal requirements set for a specific token asset. -Each function must return a status code from the common set of Ethereum status codes (ESC), according to [ERC-1066](https://eips.ethereum.org/EIPS/eip-1066). Localization of these codes is out of the scope of this proposal and may be optionally solved by adopting [ERC-1444](https://github.com/ethereum/EIPs/pull/1444) on the application level. If the operation is allowed by a checking function, the return status code must be `0x11` (Allowed) or an issuer-specific code with equivalent but more precise meaning. If the operation is not allowed by a checking function, the status must be `0x10` (Disallowed) or an issuer-specific code with equivalent but more precise meaning. Upon an internal error, the function must return the most relevant code from the general code table or an issuer-specific equivalent, example: `0xF0` (Off-Chain Failure). +Each function must return a status code from the common set of Ethereum status codes (ESC), according to [ERC-1066](./eip-1066.md). Localization of these codes is out of the scope of this proposal and may be optionally solved by adopting [ERC-1444](./eip-1444.md) on the application level. If the operation is allowed by a checking function, the return status code must be `0x11` (Allowed) or an issuer-specific code with equivalent but more precise meaning. If the operation is not allowed by a checking function, the status must be `0x10` (Disallowed) or an issuer-specific code with equivalent but more precise meaning. Upon an internal error, the function must return the most relevant code from the general code table or an issuer-specific equivalent, example: `0xF0` (Off-Chain Failure). -**For [ERC-20](https://eips.ethereum.org/EIPS/eip-20) based tokens,** +**For [ERC-20](./eip-20.md) based tokens,** * It is required that transfer function must be overridden with logic that checks the corresponding checkTransferAllowed return status code. * It is required that `transferFrom` function must be overridden with logic that checks the corresponding `checkTransferFromAllowed` return status code. * It is required that `approve` function must be overridden with logic that checks the corresponding `checkTransferFromAllowed` return status code. * Other functions such as `mint` and `burn` must be overridden, if they exist in the token implementation, they should check `checkMintAllowed` and `checkBurnAllowed` status codes accordingly. -**For [ERC-777](https://eips.ethereum.org/EIPS/eip-777) based tokens,** +**For [ERC-777](./eip-777.md) based tokens,** * It is required that `send` function must be overridden with logic that checks the corresponding return status codes: - `checkTransferAllowed` return status code, if transfer happens on behalf of the tokens owner; - `checkTransferFromAllowed` return status code, if transfer happens on behalf of an operator (i.e. delegated transfer). @@ -98,9 +98,9 @@ We also introduce two new functions that should be used for document management This EIP targets both ERC-20 and ERC-777 based tokens, although the most emphasis is given to ERC-20 due to its widespread adoption. However, this extension is designed to be compatible with the forthcoming ERC-777 standard, as well. -All checking functions are named with prefixes `check` since they return check status code, not booleans, because that is important to facilitate the debugging and tracing process. It is responsibility of the issuer to implement the logic that will handle the return codes appropriately. Some handlers will simply throw errors, other handlers would log information for future process mining. More rationale for status codes can be seen in [ERC-1066](https://eips.ethereum.org/EIPS/eip-1066). +All checking functions are named with prefixes `check` since they return check status code, not booleans, because that is important to facilitate the debugging and tracing process. It is responsibility of the issuer to implement the logic that will handle the return codes appropriately. Some handlers will simply throw errors, other handlers would log information for future process mining. More rationale for status codes can be seen in [ERC-1066](./eip-1066.md). -We require two different transfer validation functions: `checkTransferAllowed` and `checkTransferFromAllowed` since the corresponding `transfer` and `transferFrom` are usually called in different contexts. Some token standards such as [ERC-1450](https://eips.ethereum.org/EIPS/eip-1450) explicitly disallow use of `transfer`, while allowing only `transferFrom`. There might be also different complex scenarios, where `transfer` and `transferFrom` should be treated differently. ERC-777 is relying on its own `send` for transferring tokens, so it is reasonable to switch between checker functions based on its call context. We decided to omit the `checkApprove` function since it would be used in exactly the same context as `checkTransferFromAllowed`. In many cases it is required not only regulate securities transfers, but also restrict burn and `mint` operations, and additional checker functions have been added for that. +We require two different transfer validation functions: `checkTransferAllowed` and `checkTransferFromAllowed` since the corresponding `transfer` and `transferFrom` are usually called in different contexts. Some token standards such as [ERC-1450](./eip-1450.md) explicitly disallow use of `transfer`, while allowing only `transferFrom`. There might be also different complex scenarios, where `transfer` and `transferFrom` should be treated differently. ERC-777 is relying on its own `send` for transferring tokens, so it is reasonable to switch between checker functions based on its call context. We decided to omit the `checkApprove` function since it would be used in exactly the same context as `checkTransferFromAllowed`. In many cases it is required not only regulate securities transfers, but also restrict burn and `mint` operations, and additional checker functions have been added for that. The documentation functions that we propose here are a must-have tool to create dual-bindings with off-chain legal documents, a great example of this can be seen in [Neufund's Employee Incentive Options Plan](https://medium.com/@ZoeAdamovicz/37376fd0384a) legal framework that implements full legal enforceability: the smart contract refers to printed ESOP Terms & Conditions Document, which itself refers back to smart contract. This is becoming a widely adopted practice even in cases where there are no legal requirements to reference the documents within the security token. However they're almost always required, and it's a good way to attach useful documentation of various types. diff --git a/EIPS/eip-1474.md b/EIPS/eip-1474.md index 05900ffe9842b0..82bbce978b7ef5 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 , Erik Marks +author: Paul Bouchon , Erik Marks (@rekmarks) discussions-to: https://ethereum-magicians.org/t/eip-remote-procedure-call-specification/1537 status: Draft type: Standards Track @@ -94,7 +94,7 @@ The RPC methods below take a default block identifier as a parameter. - `eth_call` - `eth_getProof` -Since there is no way to clearly distinguish between a `Data` parameter and a `Quantity` parameter, [EIP-1898](eip-1898.md) provides a format to specify a block either using the block hash or block number. The block identifier is a JSON `object` with the following fields: +Since there is no way to clearly distinguish between a `Data` parameter and a `Quantity` parameter, [EIP-1898](./eip-1898.md) provides a format to specify a block either using the block hash or block number. The block identifier is a JSON `object` with the following fields: |Property|Type|Description| |-|-|-| @@ -286,7 +286,7 @@ Common chain IDs: - `"4"` - Rinkeby testnet - `"42"` - Kovan testnet -**Note:** See EIP-155 for a [complete list](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md#list-of-chain-ids) of possible chain IDs. +**Note:** See EIP-155 for a [complete list](./eip-155.md#list-of-chain-ids) of possible chain IDs. ##### Example @@ -639,7 +639,7 @@ curl -X POST --data '{ "stateRoot": "0xd5855eb08b3387c0af375e9cdb6acfc05eb8f519e419b874b6ff2ffda7ed1dff", "timestamp": "0x54e34e8e" "totalDifficulty": "0x027f07", - "transactions": [] + "transactions": [] "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "uncles": ["0x1606e5...", "0xd5145a9..."] } @@ -715,7 +715,7 @@ curl -X POST --data '{ "stateRoot": "0xd5855eb08b3387c0af375e9cdb6acfc05eb8f519e419b874b6ff2ffda7ed1dff", "timestamp": "0x54e34e8e" "totalDifficulty": "0x027f07", - "transactions": [] + "transactions": [] "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "uncles": ["0x1606e5...", "0xd5145a9..."] } @@ -1394,16 +1394,23 @@ curl -X POST --data '{ "id": 1337, "jsonrpc": "2.0", "result": { - "blockHash": '0xc6ef2fc5426d6ad6fd9e2a26abeab0aa2411b7ab17f30a99d3cb96aed1d1055b', - "blockNumber": '0xb', - "contractAddress": '0xb60e8dd61c5d32be8058bb8eb970870f07233155', - "cumulativeGasUsed": '0x33bc', - "gasUsed": '0x4dc', - "logs": [], - "logsBloom": "0x00...0", - "status": "0x1", - "transactionHash": '0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238', - "transactionIndex": '0x1' + "difficulty": "0x027f07", + "extraData": "0x0000000000000000000000000000000000000000000000000000000000000000", + "gasLimit": "0x9f759", + "gasUsed": "0x9f759", + "hash": "0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331", + "logsBloom": "0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331", + "miner": "0x4e65fda2159562a496f9f3522f89122a3088497a", + "nonce": "0xe04d296d2460cfb8472af2c5fd05b5a214109c25688d3704aed5484f9a7792f2", + "number": "0x1b4", + "parentHash": "0x9646252be9520f6e71339a8df9c55e4d7619deeb018d2a3f2d21fc165dde5eb5", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "size": "0x027f07", + "stateRoot": "0xd5855eb08b3387c0af375e9cdb6acfc05eb8f519e419b874b6ff2ffda7ed1dff", + "timestamp": "0x54e34e8e" + "totalDifficulty": "0x027f07", + "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncles": [] } } ``` @@ -1461,16 +1468,23 @@ curl -X POST --data '{ "id": 1337, "jsonrpc": "2.0", "result": { - "blockHash": '0xc6ef2fc5426d6ad6fd9e2a26abeab0aa2411b7ab17f30a99d3cb96aed1d1055b', - "blockNumber": '0xb', - "contractAddress": '0xb60e8dd61c5d32be8058bb8eb970870f07233155', - "cumulativeGasUsed": '0x33bc', - "gasUsed": '0x4dc', - "logs": [], - "logsBloom": "0x00...0", - "status": "0x1", - "transactionHash": '0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238', - "transactionIndex": '0x1' + "difficulty": "0x027f07", + "extraData": "0x0000000000000000000000000000000000000000000000000000000000000000", + "gasLimit": "0x9f759", + "gasUsed": "0x9f759", + "hash": "0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331", + "logsBloom": "0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331", + "miner": "0x4e65fda2159562a496f9f3522f89122a3088497a", + "nonce": "0xe04d296d2460cfb8472af2c5fd05b5a214109c25688d3704aed5484f9a7792f2", + "number": "0x1b4", + "parentHash": "0x9646252be9520f6e71339a8df9c55e4d7619deeb018d2a3f2d21fc165dde5eb5", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "size": "0x027f07", + "stateRoot": "0xd5855eb08b3387c0af375e9cdb6acfc05eb8f519e419b874b6ff2ffda7ed1dff", + "timestamp": "0x54e34e8e" + "totalDifficulty": "0x027f07", + "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncles": [] } } ``` @@ -1976,7 +1990,7 @@ Calculates an Ethereum-specific signature in the form of `keccak256("\x19Ethereu |1|{[`Data`](#data)}|address to use for signing| |2|{[`Data`](#data)}|message to sign containing type information, a domain separator, and data| -**Note:** Client developers should refer to EIP-712 for complete semantics around [encoding and signing data](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md#specification). Dapp developers should refer to EIP-712 for the expected structure of [RPC method input parameters](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md#parameters). +**Note:** Client developers should refer to EIP-712 for complete semantics around [encoding and signing data](./eip-712.md#specification). Dapp developers should refer to EIP-712 for the expected structure of [RPC method input parameters](./eip-712.md#parameters). ##### Returns diff --git a/EIPS/eip-1484.md b/EIPS/eip-1484.md index fd0c7799ae8d88..d5777e8ca8dec4 100644 --- a/EIPS/eip-1484.md +++ b/EIPS/eip-1484.md @@ -14,10 +14,10 @@ requires: 191 A protocol for aggregating digital identity information that's broadly interoperable with existing, proposed, and hypothetical future digital identity standards. ## Abstract -This EIP proposes an identity management and aggregation framework on the Ethereum blockchain. It allows entities to claim an `Identity` via a singular `Identity Registry` smart contract, associate it with Ethereum addresses in a variety of meaningful ways, and use it to interact with smart contracts. This enables arbitrarily complex identity-related functionality. Notably (among other features) ERC-1484 `Identities`: are self-sovereign, can natively support [ERC-725](https://github.com/NoahZinsmeister/ERC-1484/tree/master/contracts/examples/Resolvers/ERC725) and [ERC-1056](https://github.com/NoahZinsmeister/ERC-1484/tree/master/contracts/examples/Resolvers/ERC1056) identities, are [DID compliant](https://github.com/NoahZinsmeister/ERC-1484/blob/master/best-practices/DID-Method.md), and can be fully powered by [meta-transactions](https://github.com/NoahZinsmeister/ERC-1484/tree/master/contracts/examples/Providers/MetaTransactions). +This EIP proposes an identity management and aggregation framework on the Ethereum blockchain. It allows entities to claim an `Identity` via a singular `Identity Registry` smart contract, associate it with Ethereum addresses in a variety of meaningful ways, and use it to interact with smart contracts. This enables arbitrarily complex identity-related functionality. Notably (among other features) ERC-1484 `Identities`: are self-sovereign, can natively support [ERC-725](./eip-725.md) and [ERC-1056](./eip-1056.md) identities, are [DID compliant](https://github.com/NoahZinsmeister/ERC-1484/blob/master/best-practices/DID-Method.md), and can be fully powered by [meta-transactions](https://github.com/NoahZinsmeister/ERC-1484/tree/master/contracts/examples/Providers/MetaTransactions). ## Motivation -Emerging identity standards and related frameworks proposed by the Ethereum community (including ERCs/EIPs [725](https://eips.ethereum.org/EIPS/eip-725), [735](https://github.com/ethereum/EIPs/issues/735), [780](https://github.com/ethereum/EIPs/issues/780), [1056](https://eips.ethereum.org/EIPS/eip-1056), etc.) define and instrumentalize digital identity in a variety of ways. As existing approaches mature, new standards emerge, and isolated, non-standard approaches to identity develop, coordinating on identity will become increasingly burdensome for blockchain users and developers, and involve the unnecessary duplication of work. +Emerging identity standards and related frameworks proposed by the Ethereum community (including ERCs/EIPs [725](./eip-725.md), [735](https://github.com/ethereum/EIPs/issues/735), [780](https://github.com/ethereum/EIPs/issues/780), [1056](./eip-1056.md), etc.) define and instrumentalize digital identity in a variety of ways. As existing approaches mature, new standards emerge, and isolated, non-standard approaches to identity develop, coordinating on identity will become increasingly burdensome for blockchain users and developers, and involve the unnecessary duplication of work. The proliferation of on-chain identity solutions can be traced back to the fact that each codifies a notion of identity and links it to specific aspects of Ethereum (claims protocols, per-identity smart contracts, signature verification schemes, etc.). This proposal eschews that approach, instead introducing a protocol layer in between the Ethereum network and individual identity applications. This solves identity management and interoperability challenges by enabling any identity-driven application to leverage an un-opinionated identity management protocol. @@ -63,7 +63,7 @@ The address management function consists of trustlessly connecting multiple user Trustlessness in the address management function is achieved through a robust permissioning scheme. To add an `Associated Address` to an `Identity`, implicit permission from a transaction sender or explicit permission from a signature is required from 1) an address already within the registry and 2) an address to be claimed. Importantly, the transaction need not come from any particular address, as long as permission is established, which allows not only users but third parties (companies, governments, etc.) to bear the overhead of managing identities. To prevent a compromised `Associated Address` from unilaterally removing other `Associated Addresses`, it's only possible to remove an `Associated Address` by transacting or producing a signature from it. -All signatures required in ERC-1484 are designed per the [ERC-191](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-191.md) v0 specification. To avoid replay attacks, all signatures must include a timestamp within a rolling lagged window of the current `block.timestamp`. For more information, see this [best practices document](https://github.com/NoahZinsmeister/ERC-1484/blob/master/best-practices/VerifyingSignatures.md) in the reference implementation. +All signatures required in ERC-1484 are designed per the [ERC-191](./eip-191.md) v0 specification. To avoid replay attacks, all signatures must include a timestamp within a rolling lagged window of the current `block.timestamp`. For more information, see this [best practices document](https://github.com/NoahZinsmeister/ERC-1484/blob/master/best-practices/VerifyingSignatures.md) in the reference implementation. ### Provider Management While the protocol allows users to directly call identity management functions, it also aims to be more robust and future-proof by allowing `Providers`, typically smart contracts, to perform identity management functions on a user's behalf. A `Provider` set by an `Identity` can perform address management and resolver management functions by passing a user's `EIN` in function calls. @@ -536,9 +536,9 @@ interface IdentityRegistryInterface { ## Additional References - [ERC-1484 Reference Implementation](https://github.com/NoahZinsmeister/ERC-1484) -- [ERC-191 Signatures](https://eips.ethereum.org/EIPS/eip-191) -- [ERC-725 Identities](https://eips.ethereum.org/EIPS/eip-725) -- [ERC-1056 Identities](https://eips.ethereum.org/EIPS/eip-1056) +- [ERC-191 Signatures](./eip-191.md) +- [ERC-725 Identities](./eip-725.md) +- [ERC-1056 Identities](./eip-1056.md) ## Copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-1485.md b/EIPS/eip-1485.md index 7b2c29f4f9f0cc..bbddd55bb5abfc 100644 --- a/EIPS/eip-1485.md +++ b/EIPS/eip-1485.md @@ -69,7 +69,7 @@ Provide original Ethash proof of work verification with minimal set of changes b #### 3. FNV1A hash algorithm description -Previous proposed algorithm based on FNV1 [EIP-1355](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1355.md) +Previous proposed algorithm based on FNV1 [EIP-1355](./eip-1355.md) There's a implementation that looks like "Missing Offset Bias" at **FNV1A**. diff --git a/EIPS/eip-150.md b/EIPS/eip-150.md index c9bef1ed152106..34acf72522b989 100644 --- a/EIPS/eip-150.md +++ b/EIPS/eip-150.md @@ -10,7 +10,7 @@ created: 2016-09-24 ### Meta reference -[Tangerine Whistle](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-608.md). +[Tangerine Whistle](./eip-608.md). ### Parameters diff --git a/EIPS/eip-1504.md b/EIPS/eip-1504.md index 6746ed4e2763c8..cb7eb3d3a6b11d 100644 --- a/EIPS/eip-1504.md +++ b/EIPS/eip-1504.md @@ -300,7 +300,7 @@ contract Upgrader { ### Caveats -Since the Upgrader contract in [ERC-1504](https://gist.github.com/swordghost/969648793ed54fdf027cb6df1b894b75) has a simple voting mechanism, it is prone to all the limitations that the voting contract is facing: +Since the Upgrader contract in [ERC-1504](./eip-1504.md) has a simple voting mechanism, it is prone to all the limitations that the voting contract is facing: - The administrator can only be the owner of data and Handler contracts. Furthermore, only the administrator has the power to add voters and start a proposal. - It requires voters to be constantly active, informative and attentive to make a upgrader succeed. @@ -343,7 +343,7 @@ We have been very inclusive in this process and invite anyone with questions or ## Implementations 1. [Renaissance](https://www.renaissance.app) - a protocol that connect creators and fans financially -2. [ERC-1504](https://gist.github.com/swordghost/969648793ed54fdf027cb6df1b894b75) - a reference implementation +2. [ERC-1504](./eip-1504.md) - a reference implementation ## Copyright diff --git a/EIPS/eip-1538.md b/EIPS/eip-1538.md index 74b1c835d8b36b..6eeb8735b470bc 100644 --- a/EIPS/eip-1538.md +++ b/EIPS/eip-1538.md @@ -3,7 +3,7 @@ eip: 1538 title: Transparent Contract Standard author: Nick Mudge discussions-to: https://github.com/ethereum/EIPs/issues/1538 -status: Abandoned +status: Withdrawn type: Standards Track category: ERC created: 2018-10-31 @@ -277,7 +277,7 @@ Functions are removed by passing `address(0)` as the first argument to the `upda The transparent contract source code and the source code for the delegate contracts should be verified in a provable way by a third party source such as etherscan.io. ### Function Selector Clash diff --git a/EIPS/eip-155.md b/EIPS/eip-155.md index b8d174463bd4c0..17024fa653e75d 100644 --- a/EIPS/eip-155.md +++ b/EIPS/eip-155.md @@ -9,7 +9,7 @@ created: 2016-10-14 --- ### Hard fork -[Spurious Dragon](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-607.md) +[Spurious Dragon](./eip-607.md) ### Parameters - `FORK_BLKNUM`: 2,675,000 diff --git a/EIPS/eip-1559.md b/EIPS/eip-1559.md index a477089040e6d5..65836b751356ff 100644 --- a/EIPS/eip-1559.md +++ b/EIPS/eip-1559.md @@ -1,54 +1,64 @@ --- eip: 1559 title: Fee market change for ETH 1.0 chain -author: Vitalik Buterin (@vbuterin), Eric Conner (@econoar), Rick Dudley (@AFDudley), Matthew Slipper (@mslipper), Ian Norden (@i-norden) +author: Vitalik Buterin (@vbuterin), Eric Conner (@econoar), Rick Dudley (@AFDudley), Matthew Slipper (@mslipper), Ian Norden (@i-norden), Abdelhamid Bakhta (@abdelhamidbakhta) discussions-to: https://ethereum-magicians.org/t/eip-1559-fee-market-change-for-eth-1-0-chain/2783 -status: Draft +status: Review type: Standards Track category: Core created: 2019-04-13 +requires: 2718 --- ## Simple Summary A transaction pricing mechanism that includes fixed-per-block network fee that is burned and dynamically expands/contracts block sizes to deal with transient congestion. ## Abstract +We introduce a new [EIP-2718](./eip-2718.md) transaction type, with the format `0x02 || rlp([chainId, nonce, maxInclusionFeePerGas, maxFeePerGas, gasLimit, to, value, data, access_list, signatureYParity, signatureR, signatureS])`. + There is a base fee per gas in protocol, which can move up or down each block according to a formula which is a function of gas used in parent block and gas target (formerly known as gas limit) of parent block. The algorithm results in the base fee per gas increasing when blocks are above the gas target, and decreasing when blocks are below the gas target. The base fee per gas is burned. -Transactions specify both the maximum fee per gas they are willing to pay, as well as the maximum fee per gas they are willing to give to miners to incentivize them to include their transaction (aka: gas premium). -The transaction will always pay the base fee per gas of the block it was included in, and they will pay the premium per gas set in the transaction, as long as the combined amount of the two fees doesn't exceed the transaction's maximum fee per gas. - -This specification also includes a mechanism for migrating from the current transaction/block fee system to the new one. -Initially, half of a block can be legacy transactions, and half of a block can be new transactions. -Over time, the percentage of the block that can contain legacy transactions decreases, as more room for new transactions is made. +Transactions specify the maximum fee per gas they are willing to give to miners to incentivize them to include their transaction (aka: inclusion fee). +Transactions also specify the maximum fee per gas they are willing to pay total (aka: max fee), which covers both the inclusion fee and the block's network fee per gas (aka: base fee). +The transaction will always pay the base fee per gas of the block it was included in, and they will pay the inclusion fee per gas set in the transaction, as long as the combined amount of the two fees doesn't exceed the transaction's maximum fee per gas. ## Motivation -Ethereum currently prices transaction fees using a simple auction mechanism, where users send transactions with bids ("gasprices") and miners choose transactions with the highest bids, and transactions that get included pay the bid that they specify. This leads to several large sources of inefficiency: +Ethereum historically priced transaction fees using a simple auction mechanism, where users send transactions with bids ("gasprices") and miners choose transactions with the highest bids, and transactions that get included pay the bid that they specify. This leads to several large sources of inefficiency: -* **Mismatch between volatility of transaction fee levels and social cost of transactions**: bids to include transactions on mature public blockchains, that have enough usage so that blocks are full, tend to be extremely volatile. On Ethereum, minimum bids range between 1 nanoeth (10^9 nanoeth = 1 ETH), but sometimes go over 100 nanoeth and have reached over 200 nanoeth. This clearly creates many inefficiencies, because it's absurd to suggest that the cost incurred by the network from accepting one more transaction into a block actually is 200x more when gas prices are 200 nanoeth than when they are 1 nanoeth; in both cases, it's a difference between 8 million gas and 8.02 million gas. +* **Mismatch between volatility of transaction fee levels and social cost of transactions**: bids to include transactions on mature public blockchains, that have enough usage so that blocks are full, tend to be extremely volatile. It's absurd to suggest that the cost incurred by the network from accepting one more transaction into a block actually is 10x more when the cost per gas is 10 nanoeth compared to when the cost per gas is 1 nanoeth; in both cases, it's a difference between 8 million gas and 8.02 million gas. * **Needless delays for users**: because of the hard per-block gas limit coupled with natural volatility in transaction volume, transactions often wait for several blocks before getting included, but this is socially unproductive; no one significantly gains from the fact that there is no "slack" mechanism that allows one block to be bigger and the next block to be smaller to meet block-by-block differences in demand. * **Inefficiencies of first price auctions**: The current approach, where transaction senders publish a transaction with a bid a maximum fee, miners choose the highest-paying transactions, and everyone pays what they bid. This is well-known in mechanism design literature to be highly inefficient, and so complex fee estimation algorithms are required. But even these algorithms often end up not working very well, leading to frequent fee overpayment. * **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 issues with this that 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 base fee amount which is adjusted up and down by the protocol based on how congested the network is. When the network exceeds the target per-block gas usage, the base fee increases slightly and when capacity is below the target, it decreases slightly. Because these base fee changes 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 the base fee will be estimated by their wallet and a small gas premium, which acts as a 'bribe' to compensate miners taking on orphan risk (e.g. 1 nanoeth), will be automatically set. Users can also manually set the transaction fee cap to bound their total costs. +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. When the network exceeds the target per-block gas usage, the base fee increases slightly and when capacity is below the target, it decreases slightly. Because these base fee changes 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 the base fee will be estimated by their wallet and a small inclusion fee, which compensates miners taking on orphan risk (e.g. 1 nanoeth), will be automatically set. Users can also manually set the transaction max fee to bound their total costs. -An important aspect of this fee system is that miners only get to keep the gas premium. The base fee is always burned (i.e. it is destroyed by the protocol). Burning this is important because it removes miner incentive to manipulate 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. - -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. +An important aspect of this fee system is that miners only get to keep the inclusion fee. The base fee is always burned (i.e. it is destroyed by the protocol). This ensures that only ETH can ever be used to pay for transactions on Ethereum, cementing the economic value of ETH within the Ethereum platform and reducing risks associated with miner extractable value (MEV). Additionally, this burn counterbalances Ethereum inflation while still giving the block reward and inclusion fee to miners. Finally, ensuring the miner of a block does not receive the base fee is important because it removes miner incentive to manipulate the fee in order to extract more fees from users. ## Specification -*Note: `//` in Python is integer division with rounding toward negative infinity.* +Block validity is defined in the reference implementation below. +The `GASPRICE` (`0x3a`) opcode **MUST** return the `effective_gas_price` as defined in the reference implementation below. + +As of `FORK_BLOCK_NUMBER`, a new [EIP-2718](./eip-2718.md) transaction is introduced with `TransactionType` 2. + +The [EIP-2718](./eip-2718.md) `TransactionPayload` for this transaction is `rlp([chainId, nonce, maxInclusionFeePerGas, maxFeePerGas, gasLimit, to, value, data, access_list, signatureYParity, signatureR, signatureS])`. + +The `signatureYParity, signatureR, signatureS` elements of this transaction represent a secp256k1 signature over `keccak256(0x02 || rlp([chainId, nonce, maxInclusionFeePerGas, maxFeePerGas, gasLimit, to, value, data, access_list]))`. + +The [EIP-2718](./eip-2718.md) `ReceiptPayload` for this transaction is `rlp([status, effectiveGasPrice, cumulativeGasUsed, logsBloom, logs])`. + +*Note: `//` is integer division, round down.* ```python -from typing import Union, Sequence +from typing import Union, Dict, Sequence, List, Tuple, Literal from dataclasses import dataclass, field from abc import ABC, abstractmethod @dataclass class TransactionLegacy: - account_nonce: int = 0 + signer_nonce: int = 0 gas_price: int = 0 gas_limit: int = 0 + destination: int = 0 amount: int = 0 payload: bytes = bytes() v: int = 0 @@ -56,18 +66,59 @@ class TransactionLegacy: s: int = 0 @dataclass -class Transaction1559: - account_nonce: int = 0 +class Transaction2930Payload: + chain_id: int = 0 + signer_nonce: int = 0 + gas_price: int = 0 gas_limit: int = 0 + destination: int = 0 amount: int = 0 payload: bytes = bytes() - gas_premium: int = 0 - fee_cap: int = 0 - v: int = 0 - r: int = 0 - s: int = 0 + access_list: List[Tuple[int, List[int]]] = field(default_factory=list) + signature_y_parity: bool = False + signature_r: int = 0 + signature_s: int = 0 + +@dataclass +class Transaction2930Envelope: + type: Literal[1] = 1 + payload: Transaction2930Payload = Transaction2930Payload() + +@dataclass +class Transaction1559Payload: + chain_id: int = 0 + signer_nonce: int = 0 + max_inclusion_fee_per_gas: int = 0 + max_fee_per_gas: int = 0 + gas_limit: int = 0 + destination: int = 0 + amount: int = 0 + payload: bytes = bytes() + access_list: List[Tuple[int, List[int]]] = field(default_factory=list) + signature_y_parity: bool = False + signature_r: int = 0 + signature_s: int = 0 + +@dataclass +class Transaction1559Envelope: + type: Literal[2] = 2 + payload: Transaction1559Payload = Transaction1559Payload() + +Transaction2718 = Union[Transaction1559Envelope, Transaction2930Envelope] -Transaction = Union[TransactionLegacy, Transaction1559] +Transaction = Union[TransactionLegacy, Transaction2718] + +@dataclass +class NormalizedTransaction: + signer_address: int = 0 + signer_nonce: int = 0 + max_inclusion_fee_per_gas: int = 0 + max_fee_per_gas: int = 0 + gas_limit: int = 0 + destination: int = 0 + amount: int = 0 + payload: bytes = bytes() + access_list: List[Tuple[int, List[int]]] = field(default_factory=list) @dataclass class Block: @@ -86,107 +137,123 @@ class Block: extra_data: bytes = bytes() proof_of_work: int = 0 nonce: int = 0 - base_fee: int = 0 # default to 0 for blocks before INITIAL_FORK_BLOCK_NUMBER + base_fee_per_gas: int = 0 # default to 1,000,000,000 for blocks before INITIAL_FORK_BLOCK_NUMBER @dataclass class Account: + address: int = 0 nonce: int = 0 balance: int = 0 storage_root: int = 0 code_hash: int = 0 INITIAL_FORK_BLOCK_NUMBER = 10 # TBD -MIGRATION_DURATION_IN_BLOCKS = 800000 -FINAL_FORK_BLOCK_NUMBER = INITIAL_FORK_BLOCK_NUMBER + MIGRATION_DURATION_IN_BLOCKS BASE_FEE_MAX_CHANGE_DENOMINATOR = 8 +ELASTICITY_MULTIPLIER = 2 class World(ABC): def validate_block(self, block: Block) -> None: - parent_base_fee = self.parent(block).base_fee + parent_base_fee_per_gas = self.parent(block).base_fee_per_gas parent_gas_used = self.parent(block).gas_used parent_gas_target = self.parent(block).gas_target - transactions_all = self.transactions(block) + transactions = self.transactions(block) + + # check if the block used too much gas + assert block.gas_used <= block.gas_target * ELASTICITY_MULTIPLIER, 'invalid block: too much gas used' # check if the block changed the gas target too much assert block.gas_target <= parent_gas_target + parent_gas_target // 1024, 'invalid block: gas target increased too much' assert block.gas_target >= parent_gas_target - parent_gas_target // 1024, 'invalid block: gas target decreased too much' # check if the base fee is correct - if parent_gas_used >= parent_gas_target: - gas_delta = parent_gas_used - parent_gas_target - fee_delta = max(parent_base_fee * gas_delta // parent_gas_target // BASE_FEE_MAX_CHANGE_DENOMINATOR, 1) - expected_base_fee = parent_base_fee + fee_delta + if parent_gas_used == parent_gas_target: + expected_base_fee_per_gas = parent_base_fee_per_gas + elif parent_gas_used > parent_gas_target: + gas_used_delta = parent_gas_used - parent_gas_target + base_fee_per_gas_delta = max(parent_base_fee_per_gas * gas_used_delta // parent_gas_target // BASE_FEE_MAX_CHANGE_DENOMINATOR, 1) + expected_base_fee_per_gas = parent_base_fee_per_gas + base_fee_per_gas_delta else: - gas_delta = parent_gas_target - parent_gas_used - fee_delta = (parent_base_fee * gas_delta - 1) // parent_gas_used // BASE_FEE_MAX_CHANGE_DENOMINATOR + 1 - expected_base_fee = parent_base_fee - fee_delta - assert expected_base_fee == block.base_fee, 'invalid block: base fee not correct' + gas_used_delta = parent_gas_target - parent_gas_used + base_fee_per_gas_delta = parent_base_fee_per_gas * gas_used_delta // parent_gas_target // BASE_FEE_MAX_CHANGE_DENOMINATOR + expected_base_fee_per_gas = max(parent_base_fee_per_gas - base_fee_per_gas_delta, 0) + assert expected_base_fee_per_gas == block.base_fee_per_gas, 'invalid block: base fee not correct' # execute transactions and do gas accounting - cumulative_legacy_transaction_gas_used = 0 - cumulative_1559_transaction_gas_used = 0 - for transaction in transactions_all: - signer = self.transaction_signer_account(transaction) + cumulative_transaction_gas_used = 0 + for unnormalized_transaction in transactions: + # Note: this validates transaction signature and chain ID which must happen before we normalize below since normalized transactions don't include signature or chain ID + signer_address = self.validate_and_recover_signer_address(unnormalized_transaction) + transaction = self.normalize_transaction(unnormalized_transaction, signer_address) + + signer = self.account(signer_address) + signer.balance -= transaction.amount assert signer.balance >= 0, 'invalid transaction: signer does not have enough ETH to cover attached value' - # handle legacy transactions, can differentiate by number of items if desired (Legacy == 8 items) - if isinstance(transaction, TransactionLegacy): - signer.balance -= transaction.gas_limit * transaction.gas_price - assert signer.balance >= 0, 'invalid transaction: signer does not have enough ETH to cover gas' - gas_used = self.execute_transaction(transaction) - cumulative_legacy_transaction_gas_used += gas_used - signer.balance += (transaction.gas_limit - gas_used) * transaction.gas_price - self.account(block.author).balance += gas_used * transaction.gas_price - - # handle 1559 transactions, can differentiate by number of items if desired (1559 == 9 items) - elif isinstance(transaction, Transaction1559): - # premium is capped such that base fee is filled first - premium_per_gas = min(transaction.gas_premium, transaction.fee_cap - block.base_fee) - # ensure that the final fee isn't negative - assert premium_per_gas >= 0, 'invalid transaction: miner premium is negative' - # signer pays both the premium and the base fee - signer.balance -= transaction.gas_limit * premium_per_gas - signer.balance -= transaction.gas_limit * block.base_fee - assert signer.balance >= 0, 'invalid transaction: signer does not have enough ETH to cover gas' - gas_used = self.execute_transaction(transaction) - gas_refund = transaction.gas_limit - gas_used - cumulative_1559_transaction_gas_used += gas_used - # signer gets refunded for unused gas - signer.balance += gas_refund * block.base_fee - signer.balance += gas_refund * premium_per_gas - # miner only receives the premium; note that the base fee is not given to anyone (it is burned) - self.account(block.author).balance += gas_used * premium_per_gas - - # any other length transaction is an error - else: - raise Exception('invalid transaction: unexpected number of items') - - # check if the block spent too much gas on legacy transactions - assert cumulative_legacy_transaction_gas_used <= self.gas_target_legacy(block), 'invalid block: too much gas spent on legacy transactions' - - # check if the block spent too much gas on 1559 transactions - assert cumulative_1559_transaction_gas_used <= self.gas_target_1559(block), 'invalid block: too much gas spent on EIP-1559 transactions' + # ensure that the user was willing to at least pay the base fee + assert transaction.max_fee_per_gas >= block.base_fee_per_gas + # inclusion fee is capped because the base fee is filled first + inclusion_fee_per_gas = min(transaction.max_inclusion_fee_per_gas, transaction.max_fee_per_gas - block.base_fee_per_gas) + # signer pays both the inclusion fee and the base fee + effective_gas_price = inclusion_fee_per_gas + block.base_fee_per_gas + signer.balance -= transaction.gas_limit * effective_gas_price + assert signer.balance >= 0, 'invalid transaction: signer does not have enough ETH to cover gas' + gas_used = self.execute_transaction(transaction, effective_gas_price) + gas_refund = transaction.gas_limit - gas_used + cumulative_transaction_gas_used += gas_used + # signer gets refunded for unused gas + signer.balance += gas_refund * effective_gas_price + # miner only receives the inclusion fee; note that the base fee is not given to anyone (it is burned) + self.account(block.author).balance += gas_used * inclusion_fee_per_gas + + # check if the block spent too much gas transactions + assert cumulative_transaction_gas_used == block.gas_used, 'invalid block: gas_used does not equal total gas used in all transactions' # TODO: verify account balances match block's account balances (via state root comparison) # TODO: validate the rest of the block - def gas_target_1559(self, block: Block) -> int: - # before the fork block, there is no space for 1559 transactions in a block - if block.number < INITIAL_FORK_BLOCK_NUMBER: - return 0 - # at the start of the migration period, half of the block's gas target is for 1559 transactions - if block.number == INITIAL_FORK_BLOCK_NUMBER: - return block.gas_target // 2 - # after the migration is over, the block's gas target is fully devoted to 1559 transactions - if block.number >= FINAL_FORK_BLOCK_NUMBER: - return block.gas_target - # during the migration, we slowly increase the space devoted to 1559 transactions - return (block.gas_target + block.gas_target * (block.number - INITIAL_FORK_BLOCK_NUMBER) // MIGRATION_DURATION_IN_BLOCKS) // 2 - - def gas_target_legacy(self, block: Block) -> int: - # legacy transactions get all of the block gas target that isn't used by 1559, which means they'll eventually have 0 space - return block.gas_target - self.gas_target_1559(block) + def normalize_transaction(self, transaction: Transaction, signer_address: int) -> NormalizedTransaction: + # legacy transactions + if isinstance(transaction, TransactionLegacy): + return NormalizedTransaction( + signer_address = signer_address, + signer_nonce = transaction.signer_nonce, + gas_limit = transaction.gas_limit, + max_inclusion_fee_per_gas = transaction.gas_price, + max_fee_per_gas = transaction.gas_price, + destination = transaction.destination, + amount = transaction.amount, + payload = transaction.payload, + access_list = [], + ) + # 2930 transactions + elif isinstance(transaction, Transaction2930Envelope): + return NormalizedTransaction( + signer_address = signer_address, + signer_nonce = transaction.payload.signer_nonce, + gas_limit = transaction.payload.gas_limit, + max_inclusion_fee_per_gas = transaction.payload.gas_price, + max_fee_per_gas = transaction.payload.gas_price, + destination = transaction.payload.destination, + amount = transaction.payload.amount, + payload = transaction.payload.payload, + access_list = transaction.payload.access_list, + ) + # 1559 transactions + elif isinstance(transaction, Transaction1559Envelope): + return NormalizedTransaction( + signer_address = signer_address, + signer_nonce = transaction.payload.signer_nonce, + gas_limit = transaction.payload.gas_limit, + max_inclusion_fee_per_gas = transaction.payload.max_inclusion_fee_per_gas, + max_fee_per_gas = transaction.payload.max_fee_per_gas, + destination = transaction.payload.destination, + amount = transaction.payload.amount, + payload = transaction.payload.payload, + access_list = transaction.payload.access_list, + ) + else: + raise Exception('invalid transaction: unexpected number of items') @abstractmethod def parent(self, block: Block) -> Block: pass @@ -197,19 +264,25 @@ class World(ABC): @abstractmethod def transactions(self, block: Block) -> Sequence[Transaction]: pass + # effective_gas_price is the value returned by the GASPRICE (0x3a) opcode @abstractmethod - def execute_transaction(self, transaction: Transaction) -> int: pass + def execute_transaction(self, transaction: NormalizedTransaction, effective_gas_price: int) -> int: pass @abstractmethod - def transaction_signer_account(self, transaction: Transaction) -> Account: pass + def validate_and_recover_signer_address(self, transaction: Transaction) -> int: pass @abstractmethod def account(self, address: int) -> Account: pass ``` ## Backwards Compatibility -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 decreases over this period. +Legacy Ethereum transactions will still work and be included in blocks, but they will not benefit directly from the new pricing system. This is due to the fact that upgrading from legacy transactions to new transactions results in the legacy transaction's `gas_price ` entirely being consumed either by the `base_fee_per_gas` and the `inclusion_fee_per_gas`. + +### Block Hash Changing +The datastructure that is passed into keccak256 to calculate the block hash is changing, and all applications that are validating blocks are valid or using the block hash to verify block contents will need to be adapted to support the new datastructe (one additional item). If you only take the block header bytes and hash them you should still correctly get a hash, but if you construct a block header from its constituent elements you will need to add in the new one at the end. +### GASPRICE +Previous to this change, `GASPRICE` represented both the ETH paid by the signer per gas for a transaction as well as the ETH received by the miner per gas. As of this change, `GASPRICE` now only represents the amount of ETH paid by the signer per gas, and the amount a miner was paid for the transaction is no longer accessible directly in the EVM. ## Test Cases @@ -221,25 +294,15 @@ Go-ethereum implementation by Vulcanize Inc: https://github.com/vulcanize/go-eth This EIP will increase the maximum block size, which could cause problems if miners are unable to process a block fast enough as it will force them to mine an empty block. Over time, the average block size should remain about the same as without this EIP, so this is only an issue for short term size bursts. It is possible that one or more clients may handle short term size bursts poorly and error (such as out of memory or similar) and client implementations should make sure their clients can appropriately handle individual blocks up to max size. ### Transaction Ordering -With most people not competing on miner fees and instead using a baseline fee to get included, transaction ordering now depends on individual client internal implementation details such as how they store the transactions in memory. It is recommended that transactions with the same miner fee be sorted by time the transaction was received to protect the network from spamming attacks where the attacker throws a bunch of transactions into the pending pool in order to ensure that at least one lands in a favorable position. Miners should still prefer higher tip transactions over lower tip, purely from a selfish mining perspective. +With most people not competing on miner fees and instead using a baseline fee to get included, transaction ordering now depends on individual client internal implementation details such as how they store the transactions in memory. It is recommended that transactions with the same miner fee be sorted by time the transaction was received to protect the network from spamming attacks where the attacker throws a bunch of transactions into the pending pool in order to ensure that at least one lands in a favorable position. Miners should still prefer higher tip transactions over those with a lower tip, purely from a selfish mining perspective. ### Miners Mining Empty Blocks -It is possible that miners will mine empty blocks until such time as the base fee is very low and then proceed to mine half full blocks and revert to sorting transactions by the gas premium. While this attack is possible, it is not a particularly stable equilibrium as long as mining is decentralized. Any defector from this strategy will be more profitable than a miner participating in the attack for as long as the attack continues (even after the base fee reached 0). Since any miner can anonymously defect from a cartel, and there is no way to prove that a particular miner defected, the only feasible way to execute this attack would be to control 50% or more of hashing power. If an attacker had exectly 50% of hashing power, they would make no money from gas premium while defectors would make double the money from premiums. For an attacker to turn a profit, they need to have some amount over 50% hashing power, which means they can alternatively execute double spend attacks or simply ignore any other miners which is a far more profitable strategy. +It is possible that miners will mine empty blocks until such time as the base fee is very low and then proceed to mine half full blocks and revert to sorting transactions by the inclusion fee. While this attack is possible, it is not a particularly stable equilibrium as long as mining is decentralized. Any defector from this strategy will be more profitable than a miner participating in the attack for as long as the attack continues (even after the base fee reached 0). Since any miner can anonymously defect from a cartel, and there is no way to prove that a particular miner defected, the only feasible way to execute this attack would be to control 50% or more of hashing power. If an attacker had exactly 50% of hashing power, they would make no money from inclusion fee while defectors would make double the money from inclusion fees. For an attacker to turn a profit, they need to have some amount over 50% hashing power, which means they can instead execute double spend attacks or simply ignore any other miners which is a far more profitable strategy. Should a miner attempt to execute this attack, we can simply increase the elasticity multiplier (currently 2x) which requires they have even more hashing power available before the attack can even be theoretically profitable against defectors. ### ETH Burn Precludes Fixed Supply -By burning the base fee, we can no longer guarantee a fixed token supply. This could result in economic instabality as the long term supply of ETH will no longer be constant over time. While a valid concern, it is difficult to quantify how much of an impact this will have. If more is burned on base fee than is generated in mining rewards then ETH will be deflationary and if more is generated in mining rewards than is burned then ETH will be inflationary. Since we cannot control user demand for block space, we cannot assert at the moment whether ETH will end up inflationary or deflationary, so this change causes the core developers to lose some control over Ethereum's long term monetary policy. - -## 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) -* [First and second-price auctions and improved transaction-fee markets](https://ethresear.ch/t/first-and-second-price-auctions-and-improved-transaction-fee-markets/2410) -* [The Challenges of Bitcoin Transaction Fee Estimation](https://blog.bitgo.com/the-challenges-of-bitcoin-transaction-fee-estimation-e47a64a61c72) -* [On the Instability of Bitcoin Without the Block Reward](http://randomwalker.info/publications/mining_CCS.pdf) +By burning the base fee, we can no longer guarantee a fixed token supply. This could result in economic instability as the long term supply of ETH will no longer be constant over time. While a valid concern, it is difficult to quantify how much of an impact this will have. If more is burned on base fee than is generated in mining rewards then ETH will be deflationary and if more is generated in mining rewards than is burned then ETH will be inflationary. Since we cannot control user demand for block space, we cannot assert at the moment whether ETH will end up inflationary or deflationary, so this change causes the core developers to lose some control over Ethereum's long term monetary policy. ## Copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-158.md b/EIPS/eip-158.md index c5dbef191eaf88..6dde3019a62ef7 100644 --- a/EIPS/eip-158.md +++ b/EIPS/eip-158.md @@ -4,7 +4,7 @@ title: State clearing author: Vitalik Buterin type: Standards Track category: Core -status: Superseded +status: Final created: 2016-10-16 superseded-by: 161 --- diff --git a/EIPS/eip-1588.md b/EIPS/eip-1588.md index 4e6d279aa00c89..f25760a697adb4 100644 --- a/EIPS/eip-1588.md +++ b/EIPS/eip-1588.md @@ -19,7 +19,7 @@ This meta-EIP specifies the changes included in the alternative Ethereum hardfor - Activation: - `Block >= 7280000` on the Ethereum mainnet - Included EIPs: - - [EIP 1057](./eip-1057.md): ProgPoW, a Programmatic Proof-of-Work + - [EIP-1057](./eip-1057.md): ProgPoW, a Programmatic Proof-of-Work ## Copyright diff --git a/EIPS/eip-1592.md b/EIPS/eip-1592.md index da3764bb7d83c1..9345541329cf99 100644 --- a/EIPS/eip-1592.md +++ b/EIPS/eip-1592.md @@ -28,9 +28,9 @@ This standard proposal should answer the following challenges: If these challenges are answered, this proposal will provide a unified basis for transfer rules and hopefully address the transfer restriction needs of other EIPs as well, e.g. -[EIP-902](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-902.md), -[EIP-1066](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1066.md) -and [EIP-1175](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1175.md). +[EIP-902](./eip-902.md), +[EIP-1066](./eip-1066.md) +and [EIP-1175](./eip-1175.md). This document proposes specifications for a standard of **transfer rules** and interfaces to both the rules and the rule engine, which was made to be inherited by a token, but may have a much broader scope in the authors' opinion. diff --git a/EIPS/eip-160.md b/EIPS/eip-160.md index 21a12dfef18bb7..0caf02b6b66778 100644 --- a/EIPS/eip-160.md +++ b/EIPS/eip-160.md @@ -9,7 +9,7 @@ created: 2016-10-20 --- ### Hard fork -[Spurious Dragon](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-607.md) +[Spurious Dragon](./eip-607.md) ### Parameters - `FORK_BLKNUM`: 2,675,000 diff --git a/EIPS/eip-161.md b/EIPS/eip-161.md index fa61e602ca84d1..f148c76c75daaa 100644 --- a/EIPS/eip-161.md +++ b/EIPS/eip-161.md @@ -9,7 +9,7 @@ created: 2016-10-24 --- ### Hard fork -[Spurious Dragon](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-607.md) +[Spurious Dragon](./eip-607.md) ### Parameters - `FORK_BLKNUM`: 2,675,000 diff --git a/EIPS/eip-1613.md b/EIPS/eip-1613.md index c284bb88a4a3f4..2de2b2a663656d 100644 --- a/EIPS/eip-1613.md +++ b/EIPS/eip-1613.md @@ -20,9 +20,9 @@ Require no network changes, and minimal contract changes. Communicating with dapps currently requires paying ETH for gas, which limits dapp adoption to ether users. Therefore, contract owners may wish to pay for the gas to increase user acquisition, or let their users pay for gas with fiat money. Alternatively, a 3rd party may wish to subsidize the gas costs of certain contracts. -Solutions such as described in [EIP-1077](https://eips.ethereum.org/EIPS/eip-1077) could allow transactions from addresses that hold no ETH. +Solutions such as described in [EIP-1077](./eip-1077.md) could allow transactions from addresses that hold no ETH. -The gas stations network is an [EIP-1077](https://eips.ethereum.org/EIPS/eip-1077) compliant effort to solve the problem by creating an incentive for nodes to run gas stations, where gasless transactions can be "fueled up". +The gas stations network is an [EIP-1077](./eip-1077.md) compliant effort to solve the problem by creating an incentive for nodes to run gas stations, where gasless transactions can be "fueled up". It abstracts the implementation details from both the dapp maintainer and the user, making it easy to convert existing dapps to accept "collect-calls". The network consists of a single public contract trusted by all participating dapp contracts, and a decentralized network of relay nodes (gas stations) incentivized to listen on non-ether interfaces such as web or whisper, diff --git a/EIPS/eip-162.md b/EIPS/eip-162.md index 8648c599d103ef..e3a86f87e46e0e 100644 --- a/EIPS/eip-162.md +++ b/EIPS/eip-162.md @@ -31,7 +31,7 @@ created: 2016-10-25 This ERC describes the implementation, as deployed to the main ethereum network on 2017-05-04, of a registrar contract to govern the allocation of names in the Ethereum Name Service (ENS). The corresponding source code is [here](https://github.com/ethereum/ens/blob/mainnet/contracts/HashRegistrarSimplified.sol). -For more background, refer to [EIP 137](https://eips.ethereum.org/EIPS/eip-137). +For more background, refer to [EIP-137](./eip-137.md). > Registrars are responsible for allocating domain names to users of the system, and are the only entities capable of updating the ENS; the owner of a node in the ENS registry is its registrar. Registrars may be contracts or externally owned accounts, though it is expected that the root and top-level registrars, at a minimum, will be implemented as contracts. > @@ -235,8 +235,8 @@ This approach is simpler than the familiar model of requiring owners to make rec ## Prior work This document borrows heavily from several sources: -- [EIP 137](https://eips.ethereum.org/EIPS/eip-137) outlines the initial implementation of the Registry Contract (ENS.sol) and associated Resolver contracts. -- [ERC 26](https://github.com/ethereum/EIPs/issues/26) was the first ERC to propose a name service at the contract layer +- [EIP-137](./eip-137.md) outlines the initial implementation of the Registry Contract (ENS.sol) and associated Resolver contracts. +- [ERC-26](https://github.com/ethereum/EIPs/issues/26) was the first ERC to propose a name service at the contract layer - @alexvandesande's current implementation of the [HashRegistrar](https://github.com/ethereum/ens/blob/mainnet/contracts/HashRegistrarSimplified.sol) ### Edits: diff --git a/EIPS/eip-165.md b/EIPS/eip-165.md index 91ab10c0bafbf3..1998ffa47f8bfb 100644 --- a/EIPS/eip-165.md +++ b/EIPS/eip-165.md @@ -24,7 +24,7 @@ Herein, we standardize the following: ## Motivation -For some "standard interfaces" like [the ERC-20 token interface](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md), it is sometimes useful to query whether a contract supports the interface and if yes, which version of the interface, in order to adapt the way in which the contract is to be interacted with. Specifically for ERC-20, a version identifier has already been proposed. This proposal standardizes the concept of interfaces and standardizes the identification (naming) of interfaces. +For some "standard interfaces" like [the ERC-20 token interface](./eip-20.md), it is sometimes useful to query whether a contract supports the interface and if yes, which version of the interface, in order to adapt the way in which the contract is to be interacted with. Specifically for ERC-20, a version identifier has already been proposed. This proposal standardizes the concept of interfaces and standardizes the identification (naming) of interfaces. ## Specification @@ -70,7 +70,7 @@ interface ERC165 { } ``` -The interface identifier for this interface is `0x01ffc9a7`. You can calculate this by running ` bytes4(keccak256('supportsInterface(bytes4)'));` or using the `Selector` contract above. +The interface identifier for this interface is `0x01ffc9a7`. You can calculate this by running `bytes4(keccak256('supportsInterface(bytes4)'));` or using the `Selector` contract above. Therefore the implementing contract will have a `supportsInterface` function that returns: @@ -105,7 +105,7 @@ We tried to keep this specification as simple as possible. This implementation i The mechanism described above (with `0xffffffff`) should work with most of the contracts previous to this standard to determine that they do not implement ERC-165. -Also [the ENS](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-137.md) already implements this EIP. +Also [the ENS](./eip-137.md) already implements this EIP. ## Test Cases diff --git a/EIPS/eip-1679.md b/EIPS/eip-1679.md index fafda89f9aec20..0c968c1e181b69 100644 --- a/EIPS/eip-1679.md +++ b/EIPS/eip-1679.md @@ -25,12 +25,12 @@ This meta-EIP specifies the changes included in the Ethereum hardfork named Ista - `Block >= 1,561,651` on the Görli testnet ### Included EIPs - - [EIP-152](https://eips.ethereum.org/EIPS/eip-152): Add Blake2 compression function `F` precompile - - [EIP-1108](https://eips.ethereum.org/EIPS/eip-1108): Reduce alt_bn128 precompile gas costs - - [EIP-1344](https://eips.ethereum.org/EIPS/eip-1344): Add ChainID opcode - - [EIP-1884](https://eips.ethereum.org/EIPS/eip-1884): Repricing for trie-size-dependent opcodes - - [EIP-2028](https://eips.ethereum.org/EIPS/eip-2028): Calldata gas cost reduction - - [EIP-2200](https://eips.ethereum.org/EIPS/eip-2200): Rebalance net-metered SSTORE gas cost with consideration of SLOAD gas cost change + - [EIP-152](./eip-152.md): Add Blake2 compression function `F` precompile + - [EIP-1108](./eip-1108.md): Reduce alt_bn128 precompile gas costs + - [EIP-1344](./eip-1344.md): Add ChainID opcode + - [EIP-1884](./eip-1884.md): Repricing for trie-size-dependent opcodes + - [EIP-2028](./eip-2028.md): Calldata gas cost reduction + - [EIP-2200](./eip-2200.md): Rebalance net-metered SSTORE gas cost with consideration of SLOAD gas cost change ## References diff --git a/EIPS/eip-1682.md b/EIPS/eip-1682.md index 6c81518296f144..48213b3499321d 100644 --- a/EIPS/eip-1682.md +++ b/EIPS/eip-1682.md @@ -3,7 +3,7 @@ eip: 1682 title: Storage Rent author: Felix J Lange (@fjl), Martin Holst Swende (@holiman) discussions-to: https://ethereum-magicians.org/t/storage-rent-eip/2357 -status: Abandoned +status: Withdrawn type: Standards Track category: Core created: 2018-11-10 diff --git a/EIPS/eip-170.md b/EIPS/eip-170.md index 4f965519841223..d2448f2f0e9bf4 100644 --- a/EIPS/eip-170.md +++ b/EIPS/eip-170.md @@ -9,7 +9,7 @@ created: 2016-11-04 --- ### Hard fork -[Spurious Dragon](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-607.md) +[Spurious Dragon](./eip-607.md) ### Parameters - `FORK_BLKNUM`: 2,675,000 diff --git a/EIPS/eip-1706.md b/EIPS/eip-1706.md index 02174324a30f12..f7ac77a38fec87 100644 --- a/EIPS/eip-1706.md +++ b/EIPS/eip-1706.md @@ -3,20 +3,20 @@ 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: Abandoned +status: Withdrawn type: Standards Track category: Core created: 2019-01-15 requires: 1283 superseded-by: 2200 --- -> :information_source: **[EIP2200] has superseded [EIP1706].** :information_source: +> :information_source: **[EIP-2200] has superseded [EIP-1706].** :information_source: ## Simple Summary The proposal that had been accepted changes security properties of a large portion of an existing contract code base that may be infeasible to update and validate. This proposal will make the old assumptions hold even after a network upgrade. ## Abstract -[EIP-1283](https://eips.ethereum.org/EIPS/eip-1283) significantly lowers the gas costs of writing to contract's storage. This created a danger of a new kind of reentrancy attacks on existing contracts as Solidity by default grants a 'stipend' of 2300 gas to simple transfer calls. +[EIP-1283](./eip-1283.md) significantly lowers the gas costs of writing to contract's storage. This created a danger of a new kind of reentrancy attacks on existing contracts as Solidity by default grants a 'stipend' of 2300 gas to simple transfer calls. This danger is easily mitigated if SSTORE is not allowed in low gasleft state, without breaking the backward compatibility and the original intention of this EIP. ## Motivation diff --git a/EIPS/eip-1710.md b/EIPS/eip-1710.md index 3b41b90d1ce331..f18e9f5f6db774 100644 --- a/EIPS/eip-1710.md +++ b/EIPS/eip-1710.md @@ -24,7 +24,7 @@ Lots of dApps that are trying to improve their mobile experience are currently ( In order to make the experience more seamless, dApps should still be able to recommend a specific mobile web3 browser via [deferred deeplinking](https://en.wikipedia.org/wiki/Deferred_deep_linking) but by having a standard url format, if the user already has a web3 browser installed that implements this standard, it will be automatically linked to it. -There is also a compatibility problem with the current `ethereum:` url scheme described in [EIP-831](https://eips.ethereum.org/EIPS/eip-831) where any ethereum related app (wallets, identity management, etc) already registered it and because of iOS unpredictable behavior for multiple apps handling a single url scheme, users can end up opening an `ethereum:` link in an app that doesn not include a web3 browser and will not be able to handle the deeplink correctly. +There is also a compatibility problem with the current `ethereum:` url scheme described in [EIP-831](./eip-831.md) where any ethereum related app (wallets, identity management, etc) already registered it and because of iOS unpredictable behavior for multiple apps handling a single url scheme, users can end up opening an `ethereum:` link in an app that doesn not include a web3 browser and will not be able to handle the deeplink correctly. ## Specification @@ -38,7 +38,7 @@ Web3 browser URLs contain "dapp" in their schema (protocol) part and are constru ### Semantics -`chain_id` is optional and it is a parameter for the browser to automatically select the corresponding chain ID as specified in [EIP-155](https://eips.ethereum.org/EIPS/eip-155) before opening the dApp. +`chain_id` is optional and it is a parameter for the browser to automatically select the corresponding chain ID as specified in [EIP-155](./eip-155.md) before opening the dApp. `dapp_url` is a valid [RFC3986](https://www.ietf.org/rfc/rfc3986.txt) URI diff --git a/EIPS/eip-1716.md b/EIPS/eip-1716.md index eca11e0c84b78c..00b98d0f832ff6 100644 --- a/EIPS/eip-1716.md +++ b/EIPS/eip-1716.md @@ -23,7 +23,7 @@ This meta-EIP specifies the changes included in the Ethereum hardfork that remov - `Block >= 4_321_234` on the Rinkeby testnet - `Block >= 0` on the Görli testnet - Removed EIPs: - - [EIP 1283](./eip-1283.md): Net gas metering for SSTORE without dirty maps + - [EIP-1283](./eip-1283.md): Net gas metering for SSTORE without dirty maps If `Petersburg` and `Constantinople` are applied at the same block, `Petersburg` takes precedence: with the net effect of EIP-1283 being _disabled_. diff --git a/EIPS/eip-173.md b/EIPS/eip-173.md index 0853913f85a0c4..bc77693e94c801 100644 --- a/EIPS/eip-173.md +++ b/EIPS/eip-173.md @@ -87,7 +87,7 @@ Here are other schemes that were considered: This standard does not exclude the above ownership schemes or other schemes from also being implemented in the same contract. For example a contract could implement this standard and also implement the other schemes so that ownership could be managed and transferred in multiple ways. This standard does provide a simple ownership scheme that is backwards compatible, is light-weight and simple to implement, and can be widely adopted and depended on. -This standard can be extended by other standards to add additional ownership functionality. For example [EIP-2767](https://eips.ethereum.org/EIPS/eip-2767) uses and extends this standard by adding decentralized contract ownership governance. +This standard can be extended by other standards to add additional ownership functionality. For example [EIP-2767](./eip-2767.md) uses and extends this standard by adding decentralized contract ownership governance. ## Security Considerations diff --git a/EIPS/eip-1761.md b/EIPS/eip-1761.md index d7145da0efe4ac..bd62772bc14a4b 100644 --- a/EIPS/eip-1761.md +++ b/EIPS/eip-1761.md @@ -21,7 +21,7 @@ This interface is designed for use with token contracts that have an "ID" domain Sample use cases for scopes: * A company may represent its fleet of vehicles on the blockchain and it could create a scope for each regional office. -* Game developers could share an [ERC-1155](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1155.md) contract where each developer manages tokens under a specified scope. +* Game developers could share an [ERC-1155](./eip-1155.md) contract where each developer manages tokens under a specified scope. * Tokens of different value could be split into separate scopes. High-value tokens could be kept in smaller separate scopes while low-value tokens might be kept in a shared scope. Users would approve the entire low-value token scope to a third-party smart contract, exchange, or other application without concern about losing their high-value tokens in the event of a problem. ## Motivation @@ -160,8 +160,8 @@ The Scope Metadata JSON Schema was added in order to support human-readable scop ## References **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) +- [ERC-1155 Multi Token Standard](./eip-1155.md) +- [ERC-165 Standard Interface Detection](./eip-165.md) - [JSON Schema](https://json-schema.org/) **Implementations** diff --git a/EIPS/eip-1775.md b/EIPS/eip-1775.md index bc93338ba5e5d4..9eb79ee299c163 100644 --- a/EIPS/eip-1775.md +++ b/EIPS/eip-1775.md @@ -23,10 +23,10 @@ In a wallet, an user often holds most of her funds in her main accounts. These a We introduce here a new account type, app keys, which permits signing delegation and accounts isolation across applications for privacy and security. In this EIP, we provide a proposal on how to uniquely identify and authenticate each application, how to derive a master account (or app key) unique for the domain from an user private key (her root private key or any other private key of an account derived or not from her root one). This EIP aims at becoming a standard on how to derive keys specific to each application that can be regenerated from scratch without further input from the user if she restores her wallet and uses again the application for which this key was derived. -These app keys can then be endowed a different set of permissions (through the requestPermission model introduced in [EIP2255](https://eips.ethereum.org/EIPS/eip-2255)). This will potentially allow an user to partly trust some apps to perform some crypto operations on their behalf without compromising any security with respect to her main accounts. +These app keys can then be endowed a different set of permissions (through the requestPermission model introduced in [EIP-2255](./eip-2255.md)). This will potentially allow an user to partly trust some apps to perform some crypto operations on their behalf without compromising any security with respect to her main accounts. ## Motivation -Wallets developers have agreed on an HD derivation path for ethereum accounts using BIP32, BIP44, SLIP44, [(see the discussion here)](https://github.com/ethereum/EIPs/issues/84). Web3 wallets have implemented in a roughly similar way the rpc eth api. [EIP1102](https://eips.ethereum.org/EIPS/eip-1102) introduced privacy through non automatic opt-in of a wallet account into an app increasing privacy. +Wallets developers have agreed on an HD derivation path for ethereum accounts using BIP32, BIP44, SLIP44, [(see the discussion here)](https://github.com/ethereum/EIPs/issues/84). Web3 wallets have implemented in a roughly similar way the rpc eth api. [EIP-1102](./eip-1102.md) introduced privacy through non automatic opt-in of a wallet account into an app increasing privacy. However several limitations remain in order to allow for proper design and UX for crypto permissioned apps. @@ -146,7 +146,7 @@ https://github.com/ethereum/EIPs/issues/85 https://ethereum-magicians.org/t/default-accounts-for-dapps/904 * non wallet/crypto accounts -[EIP1581: Non-wallet usage of keys derived from BIP32 trees](https://eips.ethereum.org/EIPS/eip-1581) +[EIP1581: Non-wallet usage of keys derived from BIP32 trees](./eip-1581.md) * state channel application @@ -174,18 +174,18 @@ MetaMask team, Christian Lundkvist, Counterfactual team, Liam Horne, Erik Bryn, * [Issue 85](https://github.com/ethereum/EIPs/issues/85) -* [EIP600 Ethereum purpose allocation for Deterministic Wallets](https://eips.ethereum.org/EIPS/eip-600) +* [EIP600 Ethereum purpose allocation for Deterministic Wallets](./eip-600.md) -* [EIP601 Ethereum hierarchy for deterministic wallets](https://eips.ethereum.org/EIPS/eip-601) +* [EIP601 Ethereum hierarchy for deterministic wallets](./eip-601.md) ### Previous proposals and discussions related to app keys * [Meta: we should value privacy more](https://ethereum-magicians.org/t/meta-we-should-value-privacy-more/2475) -* [EIP1102: Opt-in account exposure](https://eips.ethereum.org/EIPS/eip-1102) +* [EIP1102: Opt-in account exposure](./eip-1102.md) -* [EIP1581: Non-wallet usage of keys derived from BIP-32 trees](https://eips.ethereum.org/EIPS/eip-1581) +* [EIP1581: Non-wallet usage of keys derived from BIP-32 trees](./eip-1581.md) * [EIP1581: discussion](https://ethereum-magicians.org/t/non-wallet-usage-of-keys-derived-from-bip-32-trees/1817/4) diff --git a/EIPS/eip-1803.md b/EIPS/eip-1803.md index 448ccbcc62d872..855b51242ec329 100644 --- a/EIPS/eip-1803.md +++ b/EIPS/eip-1803.md @@ -34,7 +34,7 @@ Not applicable. ## References -[EIP-6](https://eips.ethereum.org/EIPS/eip-6) previously renamed `SUICIDE` (`0xff`) to `SELFDESTRUCT`. +[EIP-6](./eip-6.md) previously renamed `SUICIDE` (`0xff`) to `SELFDESTRUCT`. Renaming `SHA3` was previously proposed by [EIP-59](https://github.com/ethereum/EIPs/issues/59). ## Copyright diff --git a/EIPS/eip-1812.md b/EIPS/eip-1812.md index 29ddeff3feaff5..7b496dadd2f493 100644 --- a/EIPS/eip-1812.md +++ b/EIPS/eip-1812.md @@ -14,15 +14,15 @@ requires: 712 ## Simple Summary -Reusable Verifiable Claims using [EIP 712 Signed Typed Data](https://eips.ethereum.org/EIPS/eip-712). +Reusable Verifiable Claims using [EIP 712 Signed Typed Data](./eip-712.md). ## Abstract -A new method for Off-Chain Verifiable Claims built on [EIP 712](https://eips.ethereum.org/EIPS/eip-712). These Claims can be issued by any user with a EIP 712 compatible web3 provider. Claims can be stored off chain and verified on-chain by Solidity Smart Contracts, State Channel Implementations or off-chain libraries. +A new method for Off-Chain Verifiable Claims built on [EIP-712](./eip-712.md). These Claims can be issued by any user with a EIP 712 compatible web3 provider. Claims can be stored off chain and verified on-chain by Solidity Smart Contracts, State Channel Implementations or off-chain libraries. ## Motivation Reusable Off-Chain Verifiable Claims provide an important piece of integrating smart contracts with real world organizational requirements such as meeting regulatory requirements such as KYC, GDPR, Accredited Investor rules etc. -[ERC 735](https://github.com/ethereum/EIPs/issues/735) and [ERC 780](https://github.com/ethereum/EIPs/issues/780) provide methods of making claims that live on chain. This is useful for some particular use cases, where some claim about an address must be verified on chain. +[ERC-735](https://github.com/ethereum/EIPs/issues/735) and [ERC-780](https://github.com/ethereum/EIPs/issues/780) provide methods of making claims that live on chain. This is useful for some particular use cases, where some claim about an address must be verified on chain. In most cases though it is both dangerous and in some cases illegal (according to EU GDPR rules for example) to record Identity Claims containing Personal Identifying Information (PII) on an immutable public database such as the Ethereum blockchain. @@ -30,14 +30,14 @@ The W3C [Verifiable Claims Data Model and Representations](https://www.w3.org/TR While built on industry standards such as [JSON-LD](https://json-ld.org) and [JWT](https://jwt.io) neither of them are easy to integrate with the Ethereum ecosystem. -[EIP 712](https://eips.ethereum.org/EIPS/eip-712) introduces a new method of signing off chain Identity data. This provides both a data format based on Solidity ABI encoding that can easily be parsed on-chain an a new JSON-RPC call that is easily supported by existing Ethereum wallets and Web3 clients. +[EIP-712](./eip-712.md) introduces a new method of signing off chain Identity data. This provides both a data format based on Solidity ABI encoding that can easily be parsed on-chain an a new JSON-RPC call that is easily supported by existing Ethereum wallets and Web3 clients. This format allows reusable off-chain Verifiable Claims to be cheaply issued to users, who can present them when needed. ## Prior Art Verified Identity Claims such as those proposed by [uPort](https://developer.uport.me/messages/verification) and [W3C Verifiable Claims Working Group](https://www.w3.org/2017/vc/WG/) form an important part of building up reusable identity claims. -[ERC 735](https://github.com/ethereum/EIPs/issues/735) and [ERC 780](https://github.com/ethereum/EIPs/issues/780) provide on-chain storage and lookups of Verifiable Claims. +[ERC-735](https://github.com/ethereum/EIPs/issues/735) and [ERC-780](https://github.com/ethereum/EIPs/issues/780) provide on-chain storage and lookups of Verifiable Claims. ## Specification ### Claims @@ -149,7 +149,7 @@ KeyDelegation can be used to implement off chain signing for smart contract base #### ERC1056 Signing Delegation -[ERC-1056](https://github.com/ethereum/EIPs/issues/1056) provides a method for addresses to assign delegate signers. One of the primary use cases for this is that a smart contract can allow a key pair to sign on its behalf for a certain period. It also allows server based issuance tools to institute key rotation. +[ERC-1056](./eip-1056.md) provides a method for addresses to assign delegate signers. One of the primary use cases for this is that a smart contract can allow a key pair to sign on its behalf for a certain period. It also allows server based issuance tools to institute key rotation. To support this an additional `issuer` attribute can be added to the Claim Type struct. In this case the verification code should lookup the EthereumDIDRegistry to see if the signer of the data is an allowed signing delegate for the `issuer` diff --git a/EIPS/eip-1820.md b/EIPS/eip-1820.md index c4f5c2e7a44ead..641555ff3064ef 100644 --- a/EIPS/eip-1820.md +++ b/EIPS/eip-1820.md @@ -11,18 +11,18 @@ created: 2019-03-04 replaces: 820 --- -> :information_source: **[ERC1820] has superseded [ERC820].** :information_source: -> [ERC1820] fixes the incompatibility in the [ERC165] logic which was introduced by the Solidity 0.5 update. +> :information_source: **[ERC-1820] has superseded [ERC-820].** :information_source: +> [ERC-1820] fixes the incompatibility in the [ERC-165] logic which was introduced by the Solidity 0.5 update. > Have a look at the [official announcement][erc1820-annoucement], and the comments about the [bug][erc820-bug] and the [fix][erc820-fix]. -> Apart from this fix, [ERC1820] is functionally equivalent to [ERC820]. +> Apart from this fix, [ERC-1820] is functionally equivalent to [ERC-820]. > -> :warning: [ERC1820] MUST be used in lieu of [ERC820]. :warning: +> :warning: [ERC-1820] MUST be used in lieu of [ERC-820]. :warning: ## Simple Summary This standard defines a universal registry smart contract where any address (contract or regular account) can register which interface it supports and which smart contract is responsible for its implementation. -This standard keeps backward compatibility with [ERC165]. +This standard keeps backward compatibility with [ERC-165]. ## Abstract @@ -32,27 +32,27 @@ Anyone can query this registry to ask if a specific address implements a given i This registry MAY be deployed on any chain and shares the same address on all chains. -Interfaces with zeroes (`0`) as the last 28 bytes are considered [ERC165] interfaces, +Interfaces with zeroes (`0`) as the last 28 bytes are considered [ERC-165] interfaces, and this registry SHALL forward the call to the contract to see if it implements the interface. -This contract also acts as an [ERC165] cache to reduce gas consumption. +This contract also acts as an [ERC-165] cache to reduce gas consumption. ## Motivation There have been different approaches to define pseudo-introspection in Ethereum. -The first is [ERC165] which has the limitation that it cannot be used by regular accounts. -The second attempt is [ERC672] which uses reverse [ENS]. Using reverse [ENS] has two issues. +The first is [ERC-165] which has the limitation that it cannot be used by regular accounts. +The second attempt is [ERC-672] which uses reverse [ENS]. Using reverse [ENS] has two issues. First, it is unnecessarily complicated, and second, [ENS] is still a centralized contract controlled by a multisig. This multisig theoretically would be able to modify the system. -This standard is much simpler than [ERC672], and it is *fully* decentralized. +This standard is much simpler than [ERC-672], and it is *fully* decentralized. This standard also provides a *unique* address for all chains. Thus solving the problem of resolving the correct registry address for different chains. ## Specification -### [ERC1820] Registry Smart Contract +### [ERC-1820] Registry Smart Contract > This is an exact copy of the code of the [ERC1820 registry smart contract]. @@ -294,7 +294,7 @@ This contract is going to be deployed using the keyless deployment method---also (See [Nick's article] for more details). This method works as follows: 1. Generate a transaction which deploys the contract from a new random account. - - This transaction MUST NOT use [EIP155] in order to work on any chain. + - 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. Set the `v`, `r`, `s` of the transaction signature to the following values: @@ -664,7 +664,7 @@ The contract has the address above for every chain on which it is deployed. Any interface name is hashed using `keccak256` and sent to `getInterfaceImplementer()`. -If the interface is part of a standard, it is best practice to explicitly state the interface name and link to this published [ERC1820] such that other people don't have to come here to look up these rules. +If the interface is part of a standard, it is best practice to explicitly state the interface name and link to this published [ERC-1820] such that other people don't have to come here to look up these rules. For convenience, the registry provides a function to compute the hash on-chain: @@ -691,21 +691,21 @@ Examples: - `keccak256("ERC777TokensSender")` - `keccak256("ERC777TokensRecipient")` -#### **[ERC165] Compatible Interfaces** +#### **[ERC-165] Compatible Interfaces** -> The compatibility with [ERC165], including the [ERC165 Cache], has been designed and developed with [William Entriken]. +> The compatibility with [ERC-165], including the [ERC165 Cache], has been designed and developed with [William Entriken]. -Any interface where the last 28 bytes are zeroes (`0`) SHALL be considered an [ERC165] interface. +Any interface where the last 28 bytes are zeroes (`0`) SHALL be considered an [ERC-165] interface. -**[ERC165] Lookup** +**[ERC-165] Lookup** -Anyone can explicitly check if a contract implements an [ERC165] interface using the registry by calling one of the two functions below: +Anyone can explicitly check if a contract implements an [ERC-165] interface using the registry by calling one of the two functions below: ``` solidity function implementsERC165Interface(address _contract, bytes4 _interfaceId) public view returns (bool) ``` -Checks whether a contract implements an [ERC165] interface or not. +Checks whether a contract implements an [ERC-165] interface or not. If the result is not cached a direct lookup on the contract address is performed. @@ -715,26 +715,26 @@ If the result is not cached a direct lookup on the contract address is performed > **identifier:** `f712f3e8` > **parameters** > `_contract`: Address of the contract to check. -> `_interfaceId`: [ERC165] interface to check. +> `_interfaceId`: [ERC-165] interface to check. > **returns:** `true` if `_contract` implements `_interfaceId`, `false` otherwise. ``` solidity function implementsERC165InterfaceNoCache(address _contract, bytes4 _interfaceId) public view returns (bool) ``` -Checks whether a contract implements an [ERC165] interface or not without using nor updating the cache. +Checks whether a contract implements an [ERC-165] interface or not without using nor updating the cache. > **identifier:** `b7056765` > **parameters** > `_contract`: Address of the contract to check. -> `_interfaceId`: [ERC165] interface to check. +> `_interfaceId`: [ERC-165] interface to check. > **returns:** `true` if `_contract` implements `_interfaceId`, false otherwise. -**[ERC165] Cache** +**[ERC-165] Cache** -Whether a contract implements an [ERC165] interface or not can be cached manually to save gas. +Whether a contract implements an [ERC-165] interface or not can be cached manually to save gas. -If a contract dynamically changes its interface and relies on the [ERC165] cache of the [ERC1820] registry, the cache MUST be updated manually---there is no automatic cache invalidation or cache update. +If a contract dynamically changes its interface and relies on the [ERC-165] cache of the [ERC-1820] registry, the cache MUST be updated manually---there is no automatic cache invalidation or cache update. Ideally the contract SHOULD automatically update the cache when changing its interface. However anyone MAY update the cache on the contract's behalf. @@ -747,7 +747,7 @@ function updateERC165Cache(address _contract, bytes4 _interfaceId) external > **identifier:** `a41e7d51` > **parameters** > `_contract`: Address of the contract for which to update the cache. -> `_interfaceId`: [ERC165] interface for which to update the cache. +> `_interfaceId`: [ERC-165] interface for which to update the cache. #### **Private User-defined Interfaces** @@ -757,7 +757,7 @@ Have fun but please, you MUST not conflict with the reserved designations above. ### Set An Interface For An Address -For any address to set a contract as the interface implementation, it must call the following function of the [ERC1820] registry: +For any address to set a contract as the interface implementation, it must call the following function of the [ERC-1820] registry: ``` solidity function setInterfaceImplementer(address _addr, bytes32 _interfaceHash, address _implementer) external @@ -773,7 +773,7 @@ Only the `manager` defined for that address can set it. - The `_implementer` MUST implement the `ERC1820ImplementerInterface` (detailed below). - Calling `canImplementInterfaceForAddress` on `_implementer` with the given `_addr` and `_interfaceHash` MUST return the `ERC1820_ACCEPT_MAGIC` value. -*NOTE*: The `_interfaceHash` MUST NOT be an [ERC165] interface---it MUST NOT end with 28 zeroes (`0`). +*NOTE*: The `_interfaceHash` MUST NOT be an [ERC-165] interface---it MUST NOT end with 28 zeroes (`0`). *NOTE*: The `_addr` MAY be `0`, then `msg.sender` is assumed. This default value simplifies interactions via multisigs where the data of the transaction to sign is constant regardless of the address of the multisig instance. @@ -786,7 +786,7 @@ This default value simplifies interactions via multisigs where the data of the t ### Get An Implementation Of An Interface For An Address -Anyone MAY query the [ERC1820] Registry to obtain the address of a contract implementing an interface on behalf of some address using the `getInterfaceImplementer` function. +Anyone MAY query the [ERC-1820] Registry to obtain the address of a contract implementing an interface on behalf of some address using the `getInterfaceImplementer` function. ``` solidity function getInterfaceImplementer(address _addr, bytes32 _interfaceHash) external view returns (address) @@ -794,8 +794,8 @@ function getInterfaceImplementer(address _addr, bytes32 _interfaceHash) external Query if an address implements an interface and through which contract. -*NOTE*: If the last 28 bytes of the `_interfaceHash` are zeroes (`0`), then the first 4 bytes are considered an [ERC165] interface and the registry SHALL forward the call to the contract at `_addr` to see if it implements the [ERC165] interface (the first 4 bytes of `_interfaceHash`). -The registry SHALL also cache [ERC165] queries to reduce gas consumption. Anyone MAY call the `erc165UpdateCache` function to update whether a contract implements an interface or not. +*NOTE*: If the last 28 bytes of the `_interfaceHash` are zeroes (`0`), then the first 4 bytes are considered an [ERC-165] interface and the registry SHALL forward the call to the contract at `_addr` to see if it implements the [ERC-165] interface (the first 4 bytes of `_interfaceHash`). +The registry SHALL also cache [ERC-165] queries to reduce gas consumption. Anyone MAY call the `erc165UpdateCache` function to update whether a contract implements an interface or not. *NOTE*: The `_addr` MAY be `0`, then `msg.sender` is assumed. This default value is consistent with the behavior of the `setInterfaceImplementer` function and simplifies interactions via multisigs where the data of the transaction to sign is constant regardless of the address of the multisig instance. @@ -887,7 +887,7 @@ Get the manager of an address. This standards offers a way for any type of address (externally owned and contracts) to implement an interface and potentially delegate the implementation of the interface to a proxy contract. This delegation to a proxy contract is necessary for externally owned accounts and useful to avoid redeploying existing contracts such as multisigs and DAOs. -The registry can also act as a [ERC165] cache in order to save gas when looking up if a contract implements a specific [ERC165] interface. +The registry can also act as a [ERC-165] cache in order to save gas when looking up if a contract implements a specific [ERC-165] interface. This cache is intentionally kept simple, without automatic cache update or invalidation. Anyone can easily and safely update the cache for any interface and any contract by calling the `updateERC165Cache` function. @@ -895,7 +895,7 @@ The registry is deployed using a keyless deployment method relying on a single-u ## Backward Compatibility -This standard is backward compatible with [ERC165], as both methods MAY be implemented without conflicting with each other. +This standard is backward compatible with [ERC-165], as both methods MAY be implemented without conflicting with each other. ## Test Cases @@ -908,11 +908,11 @@ The implementation is available in the repo: [0xjac/ERC1820]. ## Copyright Copyright and related rights waived via [CC0]. -[EIP155]: https://eips.ethereum.org/EIPS/eip-155 -[ERC165]: https://eips.ethereum.org/EIPS/eip-165 -[ERC672]: https://github.com/ethereum/EIPs/issues/672 -[ERC820]: https://eips.ethereum.org/EIPS/eip-820 -[ERC1820]: https://eips.ethereum.org/EIPS/eip-1820 +[EIP-155]: ./eip-155.md +[ERC-165]: ./eip-165.md +[ERC-672]: https://github.com/ethereum/EIPs/issues/672 +[ERC-820]: ./eip-820.md +[ERC-1820]: ./eip-1820.md [ERC1820 registry smart contract]: https://github.com/0xjac/ERC1820/blob/master/contracts/ERC1820Registry.sol [erc1820-annoucement]: https://github.com/ethereum/EIPs/issues/820#issuecomment-464109166 [erc820-bug]: https://github.com/ethereum/EIPs/issues/820#issuecomment-452465748 diff --git a/EIPS/eip-1829.md b/EIPS/eip-1829.md index 07a0e3b7cb6b57..49e82e894b5064 100644 --- a/EIPS/eip-1829.md +++ b/EIPS/eip-1829.md @@ -107,9 +107,9 @@ TODO: The special cases for `α` and `β` might be worth implementing and offere **Linear Combination.** We could instead have a simple multiply `C = r ⋅ A`. In this case we would need a separate pre-compile for addition. In addition, a linear combination allows for optimizations that like Shamir's trick that are not available in a single scalar multiplication. ECDSA requires `s₀ ⋅ A₀ + s₁ ⋅ A₁` and would benefit from this. -The BN254 (aka alt_bn8) multiplication operation introduced by the [EIP-196][eip196] precompile only handles a single scalar multiplication. The missed performance is such that for two or more points it is cheaper to use EVM, as practically demonstrated by [Weierstrudel][ws]. +The BN254 (aka alt_bn8) multiplication operation introduced by the [EIP-196][EIP-196] precompile only handles a single scalar multiplication. The missed performance is such that for two or more points it is cheaper to use EVM, as practically demonstrated by [Weierstrudel][ws]. -[eip196]: https://eips.ethereum.org/EIPS/eip-196 +[EIP-196]: ./eip-196.md [ws]: https://medium.com/aztec-protocol/huffing-for-crypto-with-weierstrudel-9c9568c06901 **Variable Time Math.** When called during a transaction, there is no assumption of privacy and no mitigations for side-channel attacks are necessary. @@ -140,10 +140,10 @@ The reference implementation will be production grade and compile to a native li This EIP overlaps in scope with -* [EIP-196](https://eips.ethereum.org/EIPS/eip-196): ecadd, ecmul for altbn128 +* [EIP-196](./eip-196.md): ecadd, ecmul for altbn128 * [EIP issue 603](https://github.com/ethereum/EIPs/issues/603): ecadd, ecmul for SECP256k1. -* [EIP 665](https://eips.ethereum.org/EIPS/eip-665): ECDSA verify for ED25519. -* [EIP 1108](https://eips.ethereum.org/EIPS/eip-1108): Optimize ecadd and ecmul for altbn128. +* [EIP-665](./eip-665.md): ECDSA verify for ED25519. +* [EIP-1108](./eip-1108.md): Optimize ecadd and ecmul for altbn128. ## Copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-1884.md b/EIPS/eip-1884.md index f2baec0f91d537..a16dc9cdba0669 100644 --- a/EIPS/eip-1884.md +++ b/EIPS/eip-1884.md @@ -94,7 +94,7 @@ opcodes: `EXTBALANCE(address)` and `SELFBALANCE`, and have two different prices. ### `EXTCODEHASH` -`EXTCODEHASH` was introduced in Constantinople, with [EIP-1052](https://eips.ethereum.org/EIPS/eip-1052). It was priced at `400` with the reasoning: +`EXTCODEHASH` was introduced in Constantinople, with [EIP-1052](./eip-1052.md). It was priced at `400` with the reasoning: > The gas cost is the same as the gas cost for the `BALANCE` opcode because the execution of the `EXTCODEHASH` requires the same account lookup as in `BALANCE`. @@ -108,7 +108,7 @@ The changes require a hardfork. The changes have the following consequences: - Certain calls will become more expensive. - Default-functions which access the storage and may in some cases require more than`2300` gas (the minimum gas that is always available in calls). - Contracts that assume a certain fixed gas cost for calls (or internal sections) may cease to function. - - A fixed gas cost is specified in [ERC-165](https://eips.ethereum.org/EIPS/eip-165) and implementations of this interface do use the affected opcodes. + - A fixed gas cost is specified in [ERC-165](./eip-165.md) and implementations of this interface do use the affected opcodes. - The ERC-165 method `supportsInterface` must return a `bool` and use at most `30,000` gas. - The two example implementations from the EIP were, at the time of writing 1. `586` gas for any input, and @@ -157,4 +157,4 @@ func opSelfBalance(pc *uint64, interpreter *EVMInterpreter, contract *Contract, ## Copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). -[eip-150]: https://eips.ethereum.org/EIPS/eip-150 +[eip-150]: ./eip-150.md diff --git a/EIPS/eip-1890.md b/EIPS/eip-1890.md index d4a6eb8827c96c..c927937226bf34 100644 --- a/EIPS/eip-1890.md +++ b/EIPS/eip-1890.md @@ -3,7 +3,7 @@ eip: 1890 title: Commitment to Sustainable Ecosystem Funding author: Gregory Markou , Kevin Owocki , Lane Rettig discussions-to: https://t.me/joinchat/DwEd_xahL5hHvzNYH2RnQA -status: Draft +status: Withdrawn type: Standards Track category: Core created: 2019-03-31 diff --git a/EIPS/eip-1898.md b/EIPS/eip-1898.md index 0d6ade6c5c64fc..8a387deddcaae2 100644 --- a/EIPS/eip-1898.md +++ b/EIPS/eip-1898.md @@ -15,7 +15,7 @@ For JSON-RPC methods which currently accept a default block parameter, additiona ## Abstract -This EIP can be considered a generalization of [EIP-234](https://github.com/ethereum/EIPs/blob/d053eb66921c5915f3e16d72c7566289e2d7c151/EIPS/eip-234.md). It would enable clients to unambiguously specify the block they want to query for certain JSON-RPC methods, even if the block is not in the canonical chain. This allows clients to maintain a coherent picture of blockchain state that they are interested in, even in the presence of reorgs, without requiring that the node maintain a persistent connection with the client or store any client-specific state. +This EIP can be considered a generalization of [EIP-234](./eip-234.md). It would enable clients to unambiguously specify the block they want to query for certain JSON-RPC methods, even if the block is not in the canonical chain. This allows clients to maintain a coherent picture of blockchain state that they are interested in, even in the presence of reorgs, without requiring that the node maintain a persistent connection with the client or store any client-specific state. ## Specification diff --git a/EIPS/eip-190.md b/EIPS/eip-190.md index 4b7edca48cfcdd..bf909700db3f26 100644 --- a/EIPS/eip-190.md +++ b/EIPS/eip-190.md @@ -31,7 +31,7 @@ A packaging standard should have the following positive effects on the ecosystem * Greater overall productivity caused by the ability to reuse existing code. * Increased security caused by the ability to reuse existing well audited implementations of common patterns (ERC20, crowdfunding, etc). -Smart contract packaging should also have a direct positive effect on the end user. Wallet software will be able to consume a released package and generate an interface for interacting with any deployed contracts included within that package. With the advent of [ENS](https://eips.ethereum.org/EIPS/eip-137) all of the pieces will be in place for a wallet to take a human readable name and present the user with an interface for interacting with the underlying application. +Smart contract packaging should also have a direct positive effect on the end user. Wallet software will be able to consume a released package and generate an interface for interacting with any deployed contracts included within that package. With the advent of [ENS](./eip-137.md) all of the pieces will be in place for a wallet to take a human readable name and present the user with an interface for interacting with the underlying application. # Specification diff --git a/EIPS/eip-1901.md b/EIPS/eip-1901.md index 7affe394e3f900..cb0397f9448424 100644 --- a/EIPS/eip-1901.md +++ b/EIPS/eip-1901.md @@ -20,7 +20,7 @@ This was first proposed [here as an ECIP](https://github.com/etclabscore/ECIPs/b ## Motivation -Although [EIP-1474](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1474.md) outlines a JSON-RPC specification. Ethereum still lacks a machine-readable JSON-RPC Specification that can be used as the industry standard for tooling. This proposal attempts to standardize such a specification in a way that is versionable, and both human and machine readable. +Although [EIP-1474](./eip-1474.md) outlines a JSON-RPC specification. Ethereum still lacks a machine-readable JSON-RPC Specification that can be used as the industry standard for tooling. This proposal attempts to standardize such a specification in a way that is versionable, and both human and machine readable. Ethereum clients can expose RPC endpoints with different method signatures and cause compatibility issues between clients. @@ -62,7 +62,7 @@ Use cases for machine-readable [JSON-RPC 2.0](https://www.jsonrpc.org/specificat ### Alternative -[OpenRPC](https://github.com/open-rpc/spec) documents just describe [JSON-RPC](https://www.jsonrpc.org/specification) APIs services, and are represented in JSON format. These documents may be produced and served statically OR generated dynamically from an application and returned via the [`rpc.discover`](https://github.com/open-rpc/spec#service-discovery-method) method. This gives projects and communities the opportunity to adopt tools, documentation, and clients outlined in the [etclabscore/ethereum-json-rpc-specification](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1474.md) before the [`rpc.discover`](https://github.com/open-rpc/spec#service-discovery-method) method is implemented for a particular client. +[OpenRPC](https://github.com/open-rpc/spec) documents just describe [JSON-RPC](https://www.jsonrpc.org/specification) APIs services, and are represented in JSON format. These documents may be produced and served statically OR generated dynamically from an application and returned via the [`rpc.discover`](https://github.com/open-rpc/spec#service-discovery-method) method. This gives projects and communities the opportunity to adopt tools, documentation, and clients outlined in the [etclabscore/ethereum-json-rpc-specification](./eip-1474.md) before the [`rpc.discover`](https://github.com/open-rpc/spec#service-discovery-method) method is implemented for a particular client. ## Implementation diff --git a/EIPS/eip-191.md b/EIPS/eip-191.md index f3b79ae5ba8bb3..a652ab057c429a 100644 --- a/EIPS/eip-191.md +++ b/EIPS/eip-191.md @@ -54,8 +54,8 @@ Using `0x19` thus makes it possible to extend the scheme by defining a version ` | `0x01` | [712][eip-712] | Structured data | `0x45` | [191][eip-191] | `personal_sign` messages -[eip-191]: https://eips.ethereum.org/EIPS/eip-191 -[eip-712]: https://eips.ethereum.org/EIPS/eip-712 +[EIP-191]: ./eip-191.md +[EIP-712]: ./eip-712.md ### Example diff --git a/EIPS/eip-1921.md b/EIPS/eip-1921.md index 29ad1312cd2ac6..8c530a056e3d10 100644 --- a/EIPS/eip-1921.md +++ b/EIPS/eip-1921.md @@ -11,11 +11,11 @@ requires: 1900 --- ## Simple Summary -In the context of dType, the Decentralized Type System described in [EIP-1900](https://eips.ethereum.org/EIPS/eip-1900), we are proposing to add support for registering functions (with a preference for `pure` and `view`) in the dType Registry. +In the context of dType, the Decentralized Type System described in [EIP-1900](./eip-1900.md), we are proposing to add support for registering functions (with a preference for `pure` and `view`) in the dType Registry. ## Abstract -This proposal is part of a series of EIPs focused on expanding the concept of a Decentralized Type System, as explained in [EIP-1900](https://eips.ethereum.org/EIPS/eip-1900). +This proposal is part of a series of EIPs focused on expanding the concept of a Decentralized Type System, as explained in [EIP-1900](./eip-1900.md). The current EIP specifies the data definitions and interfaces needed to support registering individual smart contract functions, as entries in the dType Registry. ## Motivation @@ -25,7 +25,7 @@ This implies having access to all the data needed to run the function inside the Aside from the above motivation, there are also near future benefits for this proposal. Having a globally available, non-custodial functions registry, will democratize the development of tools, such as those targeting: blockchain data analysis (e.g. block explorers), smart contract IDEs, security analysis of smart contracts. -Registering new smart contract functions can be done through the same consensus mechanism as [EIP-1900](https://eips.ethereum.org/EIPS/eip-1900) mentions, in order to avoid burdening the chain state with redundant or improper records. +Registering new smart contract functions can be done through the same consensus mechanism as [EIP-1900](./eip-1900.md) mentions, in order to avoid burdening the chain state with redundant or improper records. ## Specification diff --git a/EIPS/eip-1922.md b/EIPS/eip-1922.md index 37b01be376d055..aa6d0810699b24 100644 --- a/EIPS/eip-1922.md +++ b/EIPS/eip-1922.md @@ -167,12 +167,12 @@ Detailed example implementations and Truffle tests of these example implementati **Standards** -1. ERC-20 Token Standard. https://eips.ethereum.org/EIPS/eip-20 +1. ERC-20 Token Standard. ./eip-20.md -1. ERC-165 Standard Interface Detection. https://eips.ethereum.org/EIPS/eip-165 -1. ERC-173 Contract Ownership Standard (DRAFT). https://eips.ethereum.org/EIPS/eip-173 -1. ERC-196 Precompiled contracts for addition and scalar multiplication on the elliptic curve alt_bn128. https://eips.ethereum.org/EIPS/eip-196 -1. ERC-197 Precompiled contracts for optimal ate pairing check on the elliptic curve alt_bn128. https://eips.ethereum.org/EIPS/eip-197 +1. ERC-165 Standard Interface Detection. ./eip-165.md +1. ERC-173 Contract Ownership Standard (DRAFT). ./eip-173.md +1. ERC-196 Precompiled contracts for addition and scalar multiplication on the elliptic curve alt_bn128. ./eip-196.md +1. ERC-197 Precompiled contracts for optimal ate pairing check on the elliptic curve alt_bn128. ./eip-197.md 1. Ethereum Name Service (ENS). https://ens.domains 1. RFC 2119 Key words for use in RFCs to Indicate Requirement Levels. https://www.ietf.org/rfc/rfc2119.txt diff --git a/EIPS/eip-1923.md b/EIPS/eip-1923.md index bf858c76936d6a..2e2fc46591ca68 100644 --- a/EIPS/eip-1923.md +++ b/EIPS/eip-1923.md @@ -120,12 +120,12 @@ Detailed example implementations and Truffle tests of these example implementati **Standards** -1. ERC-20 Token Standard. https://eips.ethereum.org/EIPS/eip-20 +1. ERC-20 Token Standard. ./eip-20.md -1. ERC-165 Standard Interface Detection. https://eips.ethereum.org/EIPS/eip-165 -2. ERC-173 Contract Ownership Standard (DRAFT). https://eips.ethereum.org/EIPS/eip-173 -3. ERC-196 Precompiled contracts for addition and scalar multiplication on the elliptic curve alt_bn128. https://eips.ethereum.org/EIPS/eip-196 -4. ERC-197 Precompiled contracts for optimal ate pairing check on the elliptic curve alt_bn128. https://eips.ethereum.org/EIPS/eip-197 +1. ERC-165 Standard Interface Detection. ./eip-165.md +2. ERC-173 Contract Ownership Standard (DRAFT). ./eip-173.md +3. ERC-196 Precompiled contracts for addition and scalar multiplication on the elliptic curve alt_bn128. ./eip-196.md +4. ERC-197 Precompiled contracts for optimal ate pairing check on the elliptic curve alt_bn128. ./eip-197.md 5. Ethereum Name Service (ENS). https://ens.domains 6. RFC 2119 Key words for use in RFCs to Indicate Requirement Levels. https://www.ietf.org/rfc/rfc2119.txt diff --git a/EIPS/eip-1930.md b/EIPS/eip-1930.md index 9c20100888fe61..162704ffbd914c 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](https://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](./eip-165.md) 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](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. +To be precise, regarding the strict gas semantic, based on [EIP-150](./eip-150.md), 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](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. +Currently the gas specified as part of these opcodes is simply a maximum value. And due to the behavior of [EIP-150](./eip-150.md) 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 interpreting 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](https://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](./eip-150.md) behavior and the current gas pricing so closely. -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. +This would also allow the behaviour of [EIP-150](./eip-150.md) 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, https://eips.ethereum.org/EIPS/eip-150 +1. EIP-150, ./eip-150.md ## Copyright diff --git a/EIPS/eip-1948.md b/EIPS/eip-1948.md index a944d69e164c32..d6be67ee4cabcc 100644 --- a/EIPS/eip-1948.md +++ b/EIPS/eip-1948.md @@ -29,7 +29,7 @@ The proposal is made to standardize on tokens with dynamic data. Interactions wi ## Specification -An extension of [ERC721](https://eips.ethereum.org/EIPS/eip-721) interface with the following functions and events is suggested: +An extension of [ERC-721](./eip-721.md) interface with the following functions and events is suggested: ``` solidity pragma solidity ^0.5.2; diff --git a/EIPS/eip-1959.md b/EIPS/eip-1959.md index 40af70b401ca76..36c9624734e1ae 100644 --- a/EIPS/eip-1959.md +++ b/EIPS/eip-1959.md @@ -18,9 +18,9 @@ To protect off-chain messages from being reused across different chain, a mechan This EIP adds an opcode that returns whether the specific number passed in has been a valid chainID (EIP-155 unique identifier) in the history of the chain (including the current chainID). ## Motivation -[EIP-155](https://eips.ethereum.org/EIPS/eip-155) proposes to use the chain ID to prevent replay attacks between different chains. It would be a great benefit to have the same possibility inside smart contracts when handling signatures, especially for Layer 2 signature schemes using [EIP-712](https://eips.ethereum.org/EIPS/eip-712). +[EIP-155](./eip-155.md) proposes to use the chain ID to prevent replay attacks between different chains. It would be a great benefit to have the same possibility inside smart contracts when handling signatures, especially for Layer 2 signature schemes using [EIP-712](./eip-712.md). -[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 insufficient 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. +[EIP-1344](./eip-1344.md) is attempting to solve this by giving smart contract access to the tip of the chainID history. This is insufficient 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. ## Specification Adds a new opcode ```VALID_CHAINID``` at 0x46, which uses 1 stack argument : a 32 bytes value that represent the chainID to test. It will push ```0x1``` onto the stack if the uint256 value is part of the history (since genesis) of chainIDs of that chain, ```0x0``` otherwise. @@ -34,7 +34,7 @@ Note though that the alternative to keep track of old chainID is to implement a ## Rationale The only approach available today is to specify the chain ID at compile time. Using this approach will result in problems after a contentious hardfork as the contract can't accept message signed with a new chainID. -The approach proposed by EIP-1344 is to give access to the latest chainID. This is in itself not sufficient and pose the opposite of the problem mentioned above since as soon as a hardfork that change the chainID happens, every L2 messages signed as per [EIP-712](https://eips.ethereum.org/EIPS/eip-712) (with the previous chainID) will fails to be accepted by the contracts after the fork. +The approach proposed by EIP-1344 is to give access to the latest chainID. This is in itself not sufficient and pose the opposite of the problem mentioned above since as soon as a hardfork that change the chainID happens, every L2 messages signed as per [EIP-712](./eip-712.md) (with the previous chainID) will fails to be accepted by the contracts after the fork. That's why in the rationale of EIP-1344 it is mentioned that users need to implement/use a mechanism to verify the validity of past chainID via a trustless cache implemented via smart contract. diff --git a/EIPS/eip-196.md b/EIPS/eip-196.md index c514122d4a1073..f3be641133d900 100644 --- a/EIPS/eip-196.md +++ b/EIPS/eip-196.md @@ -1,7 +1,7 @@ --- eip: 196 title: Precompiled contracts for addition and scalar multiplication on the elliptic curve alt_bn128 -author: Christian Reitwiessner +author: Christian Reitwiessner type: Standards Track category: Core status: Final diff --git a/EIPS/eip-1962.md b/EIPS/eip-1962.md index 3ef97b10f9c8c2..d880f2be506094 100644 --- a/EIPS/eip-1962.md +++ b/EIPS/eip-1962.md @@ -12,7 +12,7 @@ requires: 1109 # Simple summary -This proposal is an extension and formalization of [EIP1829](https://eips.ethereum.org/EIPS/eip-1829) with an inclusion of pairings. [EIP1109](https://eips.ethereum.org/EIPS/eip-1109) is required due to low cost of some operations compared to the `STATICCALL` opcode (more information in the corresponding section below). +This proposal is an extension and formalization of [EIP-1829](./eip-1829.md) with an inclusion of pairings. [EIP-1109](./eip-1109.md) is required due to low cost of some operations compared to the `STATICCALL` opcode (more information in the corresponding section below). ## Abstract @@ -31,14 +31,14 @@ Full functionality of the precompile is described below in `Specification` secti ## Motivation -- There is a pending proposal to implement base elliptic curve arithmetic is covered by [EIP1829](https://eips.ethereum.org/EIPS/eip-1829) and will allow to implement various privacy-preserving protocols with a reasonable gas costs per operation. +- There is a pending proposal to implement base elliptic curve arithmetic is covered by [EIP-1829](./eip-1829.md) and will allow to implement various privacy-preserving protocols with a reasonable gas costs per operation. - Pairings are an important extension for basic arithmetic and so this new precompile is proposed with the following benefits: - Extended set of curves will be available to allow Ethereum users to choose their security parameters and required functionality. - Generic approach of this precompile will allow Ethereum users to experiment with newly found curves of their choice and new constructions constructions without waiting for new forks. - EC arithmetic is indeed re-implemented in this precompile, but it's strictly required. Most of the pairing-based protocols still need to perform standard EC multiplications or additions and thus such operations must be available on generic set of curves. - Gas costs - this EIP is designed to estimate gas-cost of performed operation as early as possible during the call and base if solely on specified parameters and operation type. This is a strict requirement for any precompile to allow Ethereum nodes to efficiently reject transactions and operations as early as possible. -Functionality of this newly proposed precompile is different from [EIP1829](https://eips.ethereum.org/EIPS/eip-1829) in the following aspects: +Functionality of this newly proposed precompile is different from [EIP-1829](./eip-1829.md) in the following aspects: - Operation on arbitrary-length modulus (up to some upper-limit) for a base field and scalar field of the curve - Pairing operations are introduced - Different ABI due to variable parameter length diff --git a/EIPS/eip-1965.md b/EIPS/eip-1965.md index 387d3bdb01510a..89357acbd80f07 100644 --- a/EIPS/eip-1965.md +++ b/EIPS/eip-1965.md @@ -14,11 +14,11 @@ requires: 155 This EIP adds a precompile that returns whether a specific chainID (EIP-155 unique identifier) is valid at a specific blockNumber. ChainID are assumed to be valid up to the blockNumber at which they get replaced by a new chainID. ## 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-155](./eip-155.md) 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](./eip-712.md). -[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-1344](./eip-1344.md) 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.** +[EIP-1959](./eip-1959.md) 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.** ## Specification Adds a new precompile which uses 2 argument : a 32 bytes value that represent the chainID to test and a 32 bytes value representing the blockNumber at which the chainID is tested. It return 0x1 if the chainID is valid at the specific blockNumber, 0x0 otherwise. Note that chainID are considered valid up to the blockNumber at which they are replaced. So they are valid for every blockNumber past their replacement. diff --git a/EIPS/eip-1967.md b/EIPS/eip-1967.md index e8bf6e113c3640..185350b946a835 100644 --- a/EIPS/eip-1967.md +++ b/EIPS/eip-1967.md @@ -13,7 +13,7 @@ created: 2019-04-24 Standardise how proxies store the address of the logic contract they delegate to, and other proxy specific information. ## Abstract -Delegating **proxy contracts** are widely used for both upgradeability and gas savings. These proxies rely on a **logic contract** (also known as implementation contract or master copy) that is called using `delegatecall`. This allows proxies to keep a persistent state (storage and balance) while the code is delegated to the logic contract. +Delegating **proxy contracts** are widely used for both upgradeability and gas savings. These proxies rely on a **logic contract** (also known as implementation contract or master copy) that is called using `delegatecall`. This allows proxies to keep a persistent state (storage and balance) while the code is delegated to the logic contract. To avoid clashes in storage usage between the proxy and logic contract, the address of the logic contract is typically saved in a [specific storage slot](https://blog.zeppelinos.org/upgradeability-using-unstructured-storage/) guaranteed to be never allocated by a compiler. This EIP proposes a set of standard slots to store proxy information. This allows clients like block explorers to properly extract and show this information to end users, and logic contracts to optionally act upon it. @@ -24,7 +24,7 @@ However, the lack of a common interface for obtaining the logic address for a pr A classic example of this is a block explorer. Here, the end user wants to interact with the underlying logic contract and not the proxy itself. Having a common way to retrieve the logic contract address from a proxy would allow a block explorer, among other things, to show the ABI of the logic contract and not that of the proxy (see [this proxy](https://etherscan.io/token/0x00fdae9174357424a78afaad98da36fd66dd9e03#readContract) for an example). The explorer should check the storage of the contract at the distinguished slots to determine if it is indeed a proxy, in which case it should show information on both the proxy and the logic contract. -Another example are logic contracts that explicitly act upon the fact that they are being proxied. This allows them to potentially trigger a code update as part of their logic, as is the case of [Universal Upgradeable Proxy Standard (EIP1822)](https://eips.ethereum.org/EIPS/eip-1822). A common storage slot allows these use cases independently of the specific proxy implementation being used. +Another example are logic contracts that explicitly act upon the fact that they are being proxied. This allows them to potentially trigger a code update as part of their logic, as is the case of [Universal Upgradeable Proxy Standard (EIP1822)](./eip-1822.md). A common storage slot allows these use cases independently of the specific proxy implementation being used. ## Specification The main requirement for the storage slots chosen is that they must never be picked by the compiler to store any contract state variable. Otherwise, a logic contract could inadvertently overwrite this information on the proxy when writing to a variable of its own. @@ -40,7 +40,13 @@ More slots for additional information can be added in subsequent ERCs as needed. Storage slot `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc` (obtained as `bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)`). -Holds the address of the logic contract that this proxy delegates to. +Holds the address of the logic contract that this proxy delegates to. SHOULD be empty if a beacon is used instead. + +### Beacon contract address + +Storage slot `0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50` (obtained as `bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)`). + +Holds the address of the beacon contract this proxy relies on (fallback). SHOULD be empty if a logic address is used directly instead, and should only be considered if the logic contract slot is empty. See the Beacons section below. ### Admin address @@ -51,17 +57,36 @@ Holds the address that is allowed to upgrade the logic contract address for this ## Rationale -This EIP standardises the **storage slot** for the logic contract address, instead of a public method on the proxy contract as [DelegateProxy (EIP897)](https://eips.ethereum.org/EIPS/eip-897) does. The rationale for this is that proxies should never expose functions to end users that could potentially clash with those of the logic contract. +This EIP standardises the **storage slot** for the logic contract address, instead of a public method on the proxy contract as [DelegateProxy (EIP897)](./eip-897.md) does. The rationale for this is that proxies should never expose functions to end users that could potentially clash with those of the logic contract. -Note that a clash may occur even among functions with different names, since the ABI relies on just four bytes for the function selector. This can lead to unexpected errors, or even exploits, where a call to a proxied contract returns a different value than expected, since the proxy intercepts the call and answers with a value of its own. +Note that a clash may occur even among functions with different names, since the ABI relies on just four bytes for the function selector. This can lead to unexpected errors, or even exploits, where a call to a proxied contract returns a different value than expected, since the proxy intercepts the call and answers with a value of its own. From [_Malicious backdoors in Ethereum proxies_](https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357) by Nomic Labs: > Any function in the Proxy contract whose selector matches with one in the implementation contract will be called directly, completely skipping the implementation code. -> +> > Because the function selectors use a fixed amount of bytes, there will always be the possibility of a clash. This isn’t an issue for day to day development, given that the Solidity compiler will detect a selector clash within a contract, but this becomes exploitable when selectors are used for cross-contract interaction. Clashes can be abused to create a seemingly well-behaved contract that’s actually concealing a backdoor. -The fact that proxy public functions are potentially exploitable makes it necessary to standardise the logic contract address in a different way. This approach is also used as part of [Universal Upgradeable Proxy Standard (EIP1822)](https://eips.ethereum.org/EIPS/eip-1822), which could become a specialization of this EIP. +The fact that proxy public functions are potentially exploitable makes it necessary to standardise the logic contract address in a different way. This approach is also used as part of [Universal Upgradeable Proxy Standard (EIP1822)](./eip-1822.md), which could become a specialization of this EIP. + +## Beacons + +Some use-cases rely on multiple proxy contracts delegating their calls to the same logic contract. If each contract was to store the address of the logic contract using the logic contract storage slot, upgrading them would require writing to the corresponding storage slot of every instance, which could be very expensive in terms of gas. + +Another approach is to have each proxy retrieve the logic contract's address from a dedicated "beacon". Using this pattern, the address of the logic contract can be modified in the beacon and take immediate effect for all the corresponding proxy contracts. + +A beacon MUST implement the function: + +``` +function implementation() returns (address) +``` + +Beacon based proxy contracts do not use the logic contract slot. Instead, they use the beacon contract slot to store the address of the beacon they are attached to. In order to know the logic contract used by a beacon proxy, one should: + +- Read the address of the beacon for the beacon logic storage slot; +- Call the `implementation()` function on the beacon contract. + +The result of the `implementation()` function on the beacon contract SHOULD NOT depend on the caller (`msg.sender`). ## Implementation Sample proxy implementations that follow this standard can be found in the [ZeppelinOS repository](https://github.com/zeppelinos/zos/blob/dc9e4ed/packages/lib/contracts/upgradeability/BaseUpgradeabilityProxy.sol), albeit with a different set of slots. diff --git a/EIPS/eip-1985.md b/EIPS/eip-1985.md index 95b940c2bda708..f3f713ff81c7c5 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](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. +[EIP-170](./eip-170.md) 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-1996.md b/EIPS/eip-1996.md index 53cee83fae0a1b..8043fa5c816e3d 100644 --- a/EIPS/eip-1996.md +++ b/EIPS/eip-1996.md @@ -275,7 +275,7 @@ This standards provides a functionality, to guarantee future payments, which is It goes a step further than the ERC-20 `approve` function by ensuring that the held balance will be available when the transfer is done. Something that can not be done with `approve`, as the approved amount is only a maximum spending amount, but never guaranteed to be available. -While not requiring it, the naming of the functions `authorizeHoldOperator`, `revokeHoldOperator` and `isHoldOperatorFor` follows the naming convention of [ERC-777](https://eips.ethereum.org/EIPS/eip-777). +While not requiring it, the naming of the functions `authorizeHoldOperator`, `revokeHoldOperator` and `isHoldOperatorFor` follows the naming convention of [ERC-777](./eip-777.md). The `operationId` is a string and not something more gas efficient to allow easy traceability of the hold and allow human readable ids. It is up to the implementer if the string should be stored on-chain or only its hash, as it is enough to identify a hold. diff --git a/EIPS/eip-2.md b/EIPS/eip-2.md index 81d4fb986d5c69..14bc9e606f93ae 100644 --- a/EIPS/eip-2.md +++ b/EIPS/eip-2.md @@ -10,7 +10,7 @@ created: 2015-11-15 ### Meta reference -[Homestead](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-606.md). +[Homestead](./eip-606.md). ### Parameters diff --git a/EIPS/eip-20-token-standard.md b/EIPS/eip-20-token-standard.md index b77c0de5b610d8..0a18b5683ad3b8 100644 --- a/EIPS/eip-20-token-standard.md +++ b/EIPS/eip-20-token-standard.md @@ -1 +1 @@ -Moved to [EIP 20](https://eips.ethereum.org/EIPS/eip-20). +Moved to [EIP-20](./eip-20.md). diff --git a/EIPS/eip-2003.md b/EIPS/eip-2003.md index c5ab43fa184351..d8b81488ee0ac5 100644 --- a/EIPS/eip-2003.md +++ b/EIPS/eip-2003.md @@ -107,7 +107,7 @@ EVMC provides the [evmc-vmtester] tool for checking compatibility with the EVMC Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). -[EIP-1352]: https://eips.ethereum.org/EIPS/eip-1352 +[EIP-1352]: ./eip-1352.md [EVMC]: https://github.com/ethereum/evmc [EVMC documentation]: https://ethereum.github.io/evmc/ [EVMC VM API]: https://ethereum.github.io/evmc/vmguide.html diff --git a/EIPS/eip-2009.md b/EIPS/eip-2009.md index 6374b55311d86e..31ddc0a2fdd021 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]: 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 +[ERC-777]: ./eip-777.md +[ERC-1066]: ./eip-1066.md +[ERC-1444]: ./eip-1444.md +[ERC-1462]: ./eip-1462.md diff --git a/EIPS/eip-2014.md b/EIPS/eip-2014.md index 918dcce09130e5..ee8df44a72a141 100644 --- a/EIPS/eip-2014.md +++ b/EIPS/eip-2014.md @@ -90,8 +90,8 @@ TBA Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). [Contract ABI Encoding]: https://solidity.readthedocs.io/en/latest/abi-spec.html -[EIP-140]: https://eips.ethereum.org/EIPS/eip-140 -[EIP-210]: https://eips.ethereum.org/EIPS/eip-210 -[EIP-1344]: https://eips.ethereum.org/EIPS/eip-1344 +[EIP-140]: ./eip-140.md +[EIP-210]: ./eip-210.md +[EIP-1344]: ./eip-1344.md [EIP-1959]: https://github.com/ethereum/EIPs/pull/1959 [EIP-1965]: https://github.com/ethereum/EIPs/pull/1965 diff --git a/EIPS/eip-2015.md b/EIPS/eip-2015.md index 7875f49016f2c7..e57fc49ffbf749 100644 --- a/EIPS/eip-2015.md +++ b/EIPS/eip-2015.md @@ -1,7 +1,7 @@ --- eip: 2015 -title: Wallet Update Chain JSON-RPC Method (`wallet_updateChain`) -author: Pedro Gomes (@pedrouid) +title: Wallet Update Ethereum Chain RPC Method (`wallet_updateEthereumChain`) +author: Pedro Gomes (@pedrouid), Erik Marks (@rekmarks) discussions-to: https://ethereum-magicians.org/t/eip-2015-wallet-update-chain-json-rpc-method-wallet-updatechain/3274 status: Draft type: Standards Track @@ -11,26 +11,26 @@ requires: 155, 1474 --- ## Simple Summary -Wallets can update the active chain when connected to a Dapp but not vice-versa, with `wallet_updateChain` the Dapp will be able to request this change from the Wallet. +Wallets can update the active chain when connected to a Dapp but not vice-versa, with `wallet_updateEthereumChain` the Dapp will be able to request this change from the Wallet. ## Abstract -Dapp can request the Wallet to switch chains by providing the minimal parameters of `chainId`, `networkId`, `rpcUrl` and `nativeCurrency`. The Wallet will display a UI element to inform the user of this change. +Dapp can request the Wallet to switch chains by providing the minimal parameters of `chainId`, `chainName`, `rpcUrl`, `nativeCurrency` and `blockExplorerUrl`. The Wallet will display a UI element to inform the user of this change. ## Motivation -Wallet and Dapp communication rely on the present provider that acts as middleware between the two. Using JSON-RPC methods, the Dapp is able to access not only the active accounts but also the active chain. With [EIP-1102](https://eips.ethereum.org/EIPS/eip-1102) we introduced the ability for Dapps to request access to the active accounts and the Wallet is able to provide a simple UI to inform the user of this action however the same is not currently possible for switching chains. The current pattern is to display some UI to request the user to switch chains within the Dapp, however this could be easily improved by triggering a UI from the Wallet side that can be approved or rejected by the user instead. +Wallet and Dapp communication rely on the present provider that acts as middleware between the two. Using JSON-RPC methods, the Dapp is able to access not only the active accounts but also the active chain. With [EIP-1102](./eip-1102.md) we introduced the ability for Dapps to request access to the active accounts and the Wallet is able to provide a simple UI to inform the user of this action however the same is not currently possible for switching chains. The current pattern is to display some UI to request the user to switch chains within the Dapp, however this could be easily improved by triggering a UI from the Wallet side that can be approved or rejected by the user instead. ## Specification The JSON RPC method will be part of `wallet_` namespaced methods which aim to improve the UX and interoperability between Dapps and Wallets. ### Required Parameters -- chainId (number): the id of the chain complaint with EIP-155 -- networkId (number): the id of the chain's network +- chainId (string): the id of the chain compliant with EIP-155 +- chainName (string): the name of the chain to update - rpcUrl (string): the url endpoint for RPC requests for this chain -- nativeCurrency (Object): includes two fields for `name` (string) and `symbol` (string) - +- nativeCurrency (Object): includes three fields for `name` (string), `symbol` (string) and `decimals` (number) +- blockExplorerUrl (string): the url endpoint for a block explorer web site for the chain. ### Best Practices -- The Wallet should display a UI view similar to a [EIP-1102](https://eips.ethereum.org/EIPS/eip-1102) informing the user that the currently connected Dapp wants to switch to the specified chain. +- The Wallet should display a UI view similar to a [EIP-1102](./eip-1102.md) informing the user that the currently connected Dapp wants to switch to the specified chain. - the Wallet should default the rpcUrl to any existing endpoints matching a chainId known previously to the wallet, otherwise it will use the provided rpcUrl as a fallback. - the Wallet should call the rpcUrl with `net_version` and `eth_chainId` to verify the provided chainId and networkId match the responses from the rpcUrl - the Wallet should change all nativeCurrency symbols to the provided parameter @@ -44,13 +44,14 @@ A JSON-RPC request from a Dapp to switch the Ethereum Goerli chain would be as f "method": "wallet_updateChain", "params": [ { - "chainId": 5, - "networkId": 5, + "chainId": 0x5, + "chainName": "Goerli", "rpcUrl": "https://goerli.infura.io/v3/406405f9c65348f99d0d5c27104b2213", "nativeCurrency": { "name": "Goerli ETH", "symbol": "gorETH" - } + }, + "blockExplorerUrl": "https://goerli.etherscan.io" } ] } @@ -65,17 +66,43 @@ A JSON-RPC request from a Dapp to switch the POA Network's xDAI chain would be a "method": "wallet_updateChain", "params": [ { - "chainId": 100, - "networkId": 100, - "rpcUrl": "https://dai.poa.network", + "chainId": "0x5", + "chainName": "Goerli", + "rpcUrl": "https://goerli.infura.io/v3/406405f9c65348f99d0d5c27104b2213", "nativeCurrency": { - "name": "xDAI", - "symbol": "xDAI" - } + "name": "Goerli ETH", + "symbol": "gorETH" + }, + "blockExplorerUrl": "https://goerli.etherscan.io" } ] } ``` +### Responses + +A success response: + +```json +{ + "id": 1, + "jsonrpc": "2.0", + "result": true +} +``` + +A failure response: + +```json +{ + "id": 1, + "jsonrpc": "2.0", + "error": { + "code": 4001, + "message": "The user rejected the request." + } +} +``` + ## Copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-2018.md b/EIPS/eip-2018.md index 75d72ee2b37389..ec98a676098488 100644 --- a/EIPS/eip-2018.md +++ b/EIPS/eip-2018.md @@ -237,7 +237,7 @@ The `operationId` is a string and not something more gas efficient to allow easy The `operationId` is a competitive resource. It is recommended, but not required, that the hold issuers used a unique prefix to avoid collisions. -While not requiring it, the naming of the functions `authorizeClearableTransferOperator`, `revokeClearableTransferOperator` and `isClearableTransferOperatorFor` follows the naming convention of [ERC-777](https://eips.ethereum.org/EIPS/eip-777). +While not requiring it, the naming of the functions `authorizeClearableTransferOperator`, `revokeClearableTransferOperator` and `isClearableTransferOperatorFor` follows the naming convention of [ERC-777](./eip-777.md). ## Backwards Compatibility @@ -258,4 +258,4 @@ Copyright and related rights waived via [CC0](https://creativecommons.org/public [Clearing-Wikipedia]: https://en.wikipedia.org/wiki/Clearing_(finance) [KYC-Wikipedia]: https://en.wikipedia.org/wiki/Know_your_customer [AML-Wikipedia]: https://en.wikipedia.org/wiki/Money_laundering#Anti-money_laundering -[EIP-1996]: https://eips.ethereum.org/EIPS/eip-1996 +[EIP-1996]: ./eip-1996.md diff --git a/EIPS/eip-2019.md b/EIPS/eip-2019.md index d4f05a2cff7957..152bec120528e7 100644 --- a/EIPS/eip-2019.md +++ b/EIPS/eip-2019.md @@ -252,4 +252,4 @@ 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]: https://eips.ethereum.org/EIPS/eip-20 +[ERC-20]: ./eip-20.md diff --git a/EIPS/eip-2020.md b/EIPS/eip-2020.md index 94224224f2e44f..24dbf6bcf5961d 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]: 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 +[ERC-20]: ./eip-20.md +[ERC-1066]: ./eip-1066.md +[ERC-1462]: ./eip-1462.md +[ERC-1996]: ./eip-1996.md +[ERC-2018]: ./eip-2018.md +[ERC-2019]: ./eip-2019.md +[ERC-2021]: ./eip-2021.md diff --git a/EIPS/eip-2021.md b/EIPS/eip-2021.md index 416f7b5ae605fc..f8e43fcc424f41 100644 --- a/EIPS/eip-2021.md +++ b/EIPS/eip-2021.md @@ -285,6 +285,6 @@ 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]: https://eips.ethereum.org/EIPS/eip-20 -[EIP-1066]: https://eips.ethereum.org/EIPS/eip-1066 -[EIP-1996]: https://eips.ethereum.org/EIPS/eip-1996 +[ERC-20]: ./eip-20.md +[EIP-1066]: ./eip-1066.md +[EIP-1996]: ./eip-1996.md diff --git a/EIPS/eip-2025.md b/EIPS/eip-2025.md index bc215c00a9e62d..44115af814e00b 100644 --- a/EIPS/eip-2025.md +++ b/EIPS/eip-2025.md @@ -3,7 +3,7 @@ eip: 2025 title: Block Rewards Proposal for funding Eth1.x author: James Hancock (@madeoftin) discussions-to: https://github.com/MadeofTin/EIPs/issues -status: Draft +status: Withdrawn type: Standards Track category: Core created: 2019-04-20 @@ -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](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. +[EIP-1890](./eip-1890.md) 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. ## Abstract diff --git a/EIPS/eip-2029.md b/EIPS/eip-2029.md index 3c8844c9e71c0e..b6da59d61756d5 100644 --- a/EIPS/eip-2029.md +++ b/EIPS/eip-2029.md @@ -35,7 +35,7 @@ Two alternative solutions were considered so far: 1. Extending the structure of the Ethereum state to introduce more fields, and hence change the way the state root is constructed. The main downside of this approach is the impact on the software what is currently coupled with the particular way the state root is constructed. Particularly it affects the software that deals with merkle proofs derived from the state root. -2. Extended State Oracle ([EIP-2014](https://eips.ethereum.org/EIPS/eip-2014)). Under such proposal, there will be a precompile contract with standardised interface, capable of returning +2. Extended State Oracle ([EIP-2014](./eip-2014.md)). Under such proposal, there will be a precompile contract with standardised interface, capable of returning current values of the counters. However, the actual data being returned by such oracle is not explicitly in the state, and is not Merkelised. It means that all the counters need to be added to the snapshots when the snapshot sync is perform, so they still present in the state, but implicitly. ## Backwards Compatibility diff --git a/EIPS/eip-2031.md b/EIPS/eip-2031.md index 9baee3c7c7af7f..40de135a8f550d 100644 --- a/EIPS/eip-2031.md +++ b/EIPS/eip-2031.md @@ -13,7 +13,7 @@ requires: 2029 ## Simple Summary Ethereum starts to track the number of transactions inside its state (for now, only number of transactions after this change is introduced, therefore it is called *Net* transaction count). -It is done by incrementing a storage slot in the special contract, called *State counter contract* ([EIP-2029](https://eips.ethereum.org/EIPS/eip-2029)). +It is done by incrementing a storage slot in the special contract, called *State counter contract* ([EIP-2029](./eip-2029.md)). ## Abstract It is part of the State Rent roadmap. This particular change makes any Ethereum transaction increment the transaction counter, which is a special storage slot diff --git a/EIPS/eip-2035.md b/EIPS/eip-2035.md index b4d0d900c1e00e..81e469ad61f69c 100644 --- a/EIPS/eip-2035.md +++ b/EIPS/eip-2035.md @@ -30,7 +30,7 @@ analysis, `SSTORE` is not considered, because its effect on the database accesse the block. Stateless clients approach to the contract storage will largely negate that latency because no database accesses will be required. Instead, bandwidth consumption goes up. There is emprical analysis (unpublished, but will be) suggesting that 1 uncached `SSTORE` or `SLOAD` adds at most 1 kB to the block proofs. At the current cost of data transmission (68 gas per byte), this translates to the increase of gas cost of both -operations by 69k gas. However, in light of proposal in [EIP-2028](https://eips.ethereum.org/EIPS/eip-2028), the increase can be made much smaller. +operations by 69k gas. However, in light of proposal in [EIP-2028](./eip-2028.md), the increase can be made much smaller. ## Specification Not very formal at the moment, but will be formalised with more research and prototyping. Gas of operations `SLOAD` and `SSTORE` increases by `X` gas when the storage slots accessed (read by `SLOAD` or written by `SSTORE`) were not previously accessed (by another `SLOAD` or `SSTORE`) during the same transaction. @@ -39,11 +39,11 @@ Future variant (will be possible after the implementation of the *Gross contract depending on the size of the contract storage, i.e. `SLOAD` and `SSTORE` for smaller contracts will be cheaper. ## Rationale -[EIP-1884](https://eips.ethereum.org/EIPS/eip-1884) seeks to increase the gas cost of `SLOAD` but using a different justification +[EIP-1884](./eip-1884.md) seeks to increase the gas cost of `SLOAD` but using a different justification (latency of the execution as described in the Motivation). This EIP is likely to increase the cost of `SLOAD` by a larger amount, therefore partially (because EIP-1884 also proposed other increases) supersedes EIP-1884. -[EIP-2028](https://eips.ethereum.org/EIPS/eip-2028) describes the model that can be used for deciding the gas cost of data transmission. It is relevant +[EIP-2028](./eip-2028.md) describes the model that can be used for deciding the gas cost of data transmission. It is relevant because in the stateless client regime `SSTORE` and `SLOAD` operations add more data to be transmitted (as well as computation to verify the proofs). The main alternate design is the rent proportional to the size of the contract storage, which unfortunately introduces a serious griefing @@ -53,7 +53,7 @@ However, this approach is likely to be very expensive on the non-technical (ecos ## Backwards Compatibility This change is not backwards compatible and requires hard fork to be activated. There might also be an adverse effect of this change on the already deployed contract. It is expected that after this EIP and -[EIP-2026](https://eips.ethereum.org/EIPS/eip-2026) (rent prepayment for accounts), the recommendation will be made to raise the gas limit. This can somewhat dampen the +[EIP-2026](./eip-2026.md) (rent prepayment for accounts), the recommendation will be made to raise the gas limit. This can somewhat dampen the adverse effect of EIP. The most problematic cases would be with the contracts that assume certain gas costs of `SLOAD` and `SSTORE` and hard-code them in their internal gas computations. For others, the cost of interacting with the contract storage will rise and may make some dApps based on such interactions, non-viable. This is a trade off to avoid even bigger diff --git a/EIPS/eip-2045.md b/EIPS/eip-2045.md index ee3f998e59f1a9..1b907af472bf63 100644 --- a/EIPS/eip-2045.md +++ b/EIPS/eip-2045.md @@ -13,7 +13,7 @@ created: 2019-05-17 According to recent benchmarks, EVM opcodes for computation (`ADD`, `SUB`, `MUL`, etc.) are generally overpriced relative to opcodes for storage I/O (`SLOAD`, `SSTORE`, etc.). Currently the minimum gas cost is 1 (i.e. one unit of gas), and most computational opcodes have a cost near to 1 (e.g. 3, 5, or 8), so the range in possible cost reduction is limited. A new minimum unit of gas, called a "particle", which is a fraction of 1 gas, would expand the range of gas costs and thus enable reductions below the current minimum. ## Motivation -The transaction capacity of an Ethereum block is determined by the gas cost of transactions relative to the block gas limit. One way to boost the transaction capacity is to raise the block gas limit. Unfortunately, raising the block gas limit would also increase the rate of state growth, unless the costs of state-expanding storage opcodes (`SSTORE`, `CREATE`, etc.) are simultaneously increased to the same proportion. Increasing the cost of storage opcodes may have adverse side effects, such as shifting the economic assumptions around gas fees of deployed contracts, or possibly breaking invariants in current contract executions (as mentioned in [EIP-2035](https://eips.ethereum.org/EIPS/eip-2035)[1](#eip2035), more research is needed on the potential effects of increasing the cost of storage opcodes). +The transaction capacity of an Ethereum block is determined by the gas cost of transactions relative to the block gas limit. One way to boost the transaction capacity is to raise the block gas limit. Unfortunately, raising the block gas limit would also increase the rate of state growth, unless the costs of state-expanding storage opcodes (`SSTORE`, `CREATE`, etc.) are simultaneously increased to the same proportion. Increasing the cost of storage opcodes may have adverse side effects, such as shifting the economic assumptions around gas fees of deployed contracts, or possibly breaking invariants in current contract executions (as mentioned in [EIP-2035](./eip-2035.md)[1](#eip2035), more research is needed on the potential effects of increasing the cost of storage opcodes). Another way to boost the transaction capacity of a block is to reduce the gas cost of transactions. Reducing the gas costs of computational opcodes while keeping the cost of storage opcodes the same, is effectively equivalent to raising the block gas limit and simultaneously increasing the cost of storage opcodes. However, reducing the cost of computational opcodes might avoid the adverse side effects of an increase in cost of storage opcodes (again, more research is needed on this topic). @@ -111,7 +111,7 @@ TODO TODO ## References -1. [EIP-2035](https://eips.ethereum.org/EIPS/eip-2035): Stateless Clients - Repricing SLOAD and SSTORE to pay for block proofs +1. [EIP-2035](./eip-2035.md): Stateless Clients - Repricing SLOAD and SSTORE to pay for block proofs 2. https://github.com/ewasm/benchmarking diff --git a/EIPS/eip-2046.md b/EIPS/eip-2046.md index ca35c7eefe8e8a..00d3644ca58b40 100644 --- a/EIPS/eip-2046.md +++ b/EIPS/eip-2046.md @@ -54,7 +54,7 @@ TBA ## References -This has been previously suggested as part of [EIP-1109](https://github.com/ethereum/EIPs/pull/1109) and [EIP-1231](https://github.com/ethereum/EIPs/pull/1231). +This has been previously suggested as part of [EIP-1109](./eip-1109.md) and [EIP-1231](https://github.com/ethereum/EIPs/pull/1231). However EIP-1109 was later changed to a very different approach. The author [has suggested to change EIP-1109](https://ethereum-magicians.org/t/eip-1109-remove-call-costs-for-precompiled-contracts/447/7). ## Acknowledgements @@ -66,4 +66,4 @@ Jordi Baylina (@jbaylina) and Matthew Di Ferrante (@mattdf) who have proposed th Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). [Yellow Paper]: https://github.com/ethereum/yellowpaper -[EIP-1352]: https://eips.ethereum.org/EIPS/eip-1352 +[EIP-1352]: ./eip-1352.md diff --git a/EIPS/eip-2070.md b/EIPS/eip-2070.md index 876b9eef8d0a90..e568b0a35af0f4 100644 --- a/EIPS/eip-2070.md +++ b/EIPS/eip-2070.md @@ -16,32 +16,9 @@ This meta-EIP specifies the changes included in the Ethereum hardfork named Berl ## Specification - Codename: Berlin -- Activation: TBD -### Included EIPs - -- TBD - -### Accepted EIPs - -- [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 - -- [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 - -(Proposed) -- Testnets - TBD -- Mainnet - TBD - -## References - -- Tracking [EFI](https://github.com/orgs/ethereum/projects/5) -- ACD meeting [notes 90](https://github.com/ethereum/pm/blob/master/All%20Core%20Devs%20Meetings/Meeting%2090.md), [notes 85](https://github.com/ethereum/pm/blob/ee277386af75621c48923f9740e4913ee241cd05/All%20Core%20Devs%20Meetings/Meeting%2085.md) +In the current stage of coordination, the changes are tracked and discussed in the [eth1.0-specs](https://github.com/ethereum/eth1.0-specs) repository. +For an accurate status please refer to the [`berlin.md`](https://github.com/ethereum/eth1.0-specs/blob/master/network-upgrades/berlin.md) file. ## Copyright diff --git a/EIPS/eip-2098.md b/EIPS/eip-2098.md index 38d2802d7e2760..2a98c2a676a3bd 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](https://eips.ethereum.org/EIPS/eip-2). +which was introduced as [a constraint in Homestead](./eip-2.md). So, we can hijack the top bit in the `s` parameter to store the value of `v`, resulting in: diff --git a/EIPS/eip-2124.md b/EIPS/eip-2124.md index ff0d014deb1aba..3f8ee13b91fbee 100644 --- a/EIPS/eip-2124.md +++ b/EIPS/eip-2124.md @@ -16,7 +16,7 @@ Currently nodes in the Ethereum network try to find each other by establishing r To avoid this overhead, Ethereum needs a mechanism that can precisely identify whether a node will be useful, as early as possible. Such a mechanism requires a way to summarize chain configurations, as well as a way to disseminate said summaries in the network. -This proposal focuses only on the definition of said summary - a generally useful *fork identifier* - and it's validation rules, allowing it to be embedded into arbitrary network protocols (e.g. [discovery ENRs](https://eips.ethereum.org/EIPS/eip-778) or `eth/6x` handshakes). +This proposal focuses only on the definition of said summary - a generally useful *fork identifier* - and it's validation rules, allowing it to be embedded into arbitrary network protocols (e.g. [discovery ENRs](./eip-778.md) or `eth/6x` handshakes). ## Abstract diff --git a/EIPS/eip-2135.md b/EIPS/eip-2135.md index 181110035d7eae..970cae1b198aed 100644 --- a/EIPS/eip-2135.md +++ b/EIPS/eip-2135.md @@ -54,7 +54,7 @@ The event notifies subscribers whoever are interested to learn an asset is being To keep it simple, this standard *intentionally* contains no functions or events related to creation of a consumable asset. This is because the creation of a consumable asset will need to make assumption of the nature of an actual use-case. If we see some common use-case of creation, we can have another follow up standard. -We also left out metadata associated to the consumables from the standard. If necessary, related metadata can be created with a separate metadata extension interface like [`ERC721Metadata`](https://eips.ethereum.org/EIPS/eip-721) +We also left out metadata associated to the consumables from the standard. If necessary, related metadata can be created with a separate metadata extension interface like [`ERC-721 Metadata`](./eip-721.md) ## Backwards Compatibility @@ -73,7 +73,7 @@ See [GitHub/xinbenlv/eip-2135/impl/test](https://github.com/xinbenlv/eip-2135/tr ## Reference ### Standards -- [ERC-721](https://eips.ethereum.org/EIPS/eip-721) +- [ERC-721](./eip-721.md) ## Copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-2193.md b/EIPS/eip-2193.md index a3be794f44f677..1d65946b606702 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](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. +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](./eip-1900.md)) and the data content (identifier provided by a dType Storage Contract, [EIP-2157](./eip-2157.md)). 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](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). +There are standards that currently address the need for attaching human-readable identifiers to Ethereum accounts, such as [EIP-137](./eip-137.md). 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](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. +Moreover, [EIP-137](./eip-137.md) 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](https://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](./eip-2157.md). 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](https://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](./eip-155.md), 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](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. +Current attempts to solve content addressability, such as [EIP-137](./eip-137.md), only target Ethereum accounts. These are based on inherited concepts from HTTP and DNS, which are not machine friendly. -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). +With [EIP-1900](./eip-1900.md) and [EIP-2157](./eip-2157.md), 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-2200.md b/EIPS/eip-2200.md index d173862da87085..a5182f9fa829bb 100644 --- a/EIPS/eip-2200.md +++ b/EIPS/eip-2200.md @@ -314,9 +314,9 @@ We always start at state X. The first `SSTORE` can: Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). -[EIP-1283]: https://eips.ethereum.org/EIPS/eip-1283 -[EIP-1706]: https://eips.ethereum.org/EIPS/eip-1706 -[EIP-1884]: https://eips.ethereum.org/EIPS/eip-1884 -[EIP-1087]: https://eips.ethereum.org/EIPS/eip-1087 -[EIP-1153]: https://eips.ethereum.org/EIPS/eip-1153 -[EIP-658]: https://eips.ethereum.org/EIPS/eip-658 +[EIP-1283]: ./eip-1283.md +[EIP-1706]: ./eip-1706.md +[EIP-1884]: ./eip-1884.md +[EIP-1087]: ./eip-1087.md +[EIP-1153]: ./eip-1153.md +[EIP-658]: ./eip-658.md diff --git a/EIPS/eip-2228.md b/EIPS/eip-2228.md new file mode 100644 index 00000000000000..000702a32ce79b --- /dev/null +++ b/EIPS/eip-2228.md @@ -0,0 +1,106 @@ +--- +eip: 2228 +title: Canonicalize the name of network with chain ID 1 +author: William Entriken (@fulldecent) +discussions-to: https://github.com/ethereum/EIPs/issues/2228 +status: Draft +type: Informational +created: 2019-08-04 +--- + +## Simple Summary + +The Ethereum network with chainid 1 is named Ethereum Mainnet. + +## Abstract + +The name for the Ethereum network with network ID 1 and chain ID 1 shall be Ethereum Mainnet or just Mainnet. This is a proper noun. + +This standard specifies the name for this network and provides reference examples in an effort to standardize the word choice and provide a common language for use to use to refer to this network. + +## Motivation + +The Ethereum network with chainid 1 is referenced from authoritative sources using several names that are conflicting: + +* Vitalik has called it "main net" at http://eips.ethereum.org/EIPS/eip-155 http://eips.ethereum.org/EIPS/eip-170 +* Vitalik has called it "mainnet" at http://eips.ethereum.org/EIPS/eip-86 +* Vitalik has called it "Main net" at http://eips.ethereum.org/EIPS/eip-2* http://eips.ethereum.org/EIPS/eip-150 + * \* In EIP-2, it is unclear if the first letter is capital because it is a proper noun or if it is the the first word in a text column presented in sentence case +* Vitalik has called it "Mainnet" at http://eips.ethereum.org/EIPS/eip-7 +* Geth documentation calls its "mainnet" at https://geth.ethereum.org/support/FAQ +* A final EIP here has referred to it as "Mainnet" at http://eips.ethereum.org/EIPS/eip-779 + +## Specification + +The network name shall be Ethereum Mainnet, or just Mainnet if the context is known to be discussing Ethereum networks. This IS a proper noun. Several examples are given below which differentiate between usage of the name of the network versus a descriptive reference to the network. + +Any name or word styling (i.e. capitalization of the letters) of the network which is inconsistent with the test cases cited below shall NOT be used. + +## Rationale + +Choosing common word use promotes interoperability of implementations and increases customer awareness. Also, it adds a sense of professionalism when customers see the same word and word styling (i.e. capitalization of letters) across different implementations. + +Anybody that has travelled to certain countries and seen an "IPhone [sic]" repair store should immediately recognize that this is off-brand and unofficial. Likewise, the astute customer of Ethereum should recognize if they see the name of the network referred to using different names in different software, so let's avoid this. + +## Backwards Compatibility + +- MetaMask currently uses the wording "Main Ethereum Network" in the account network chooser. In this context, it is understood that "main" is used as an adjective, not a proper noun form. Such usage is acceptable per this EIP. Also, MetaMask is using "Main" and "Network" with a capitalized first letter for stylistic purposes, not to designate a proper noun. + +- Certain references to "Mainnet" and alternate spellings are published in EIPs made in the following published EIPs 2, 7, 150, 155, 170 and 779. + +## Test Cases + +### Examples referencing the name of the network + +> The contract was deployed to Ethereum Mainnet. + +> Ethereum runs many applications, this Dapp was deployed to Mainnet. + +No specification is made on whether Dapp, dapp, dApp, etc. is preferred. + +> SWITCH TO MAINNET + +This example shows a user interface which is in uppercase. To be semantically correct, this could be written in HTML as `Switch to Mainnet`. + +> switch to mainnet + +This example shows a user interface which is in lowercase. To be semantically correct, this could be written in HTML as `Switch to Mainnet`. + +### Examples referencing the network in a descriptive way + +> Mainnet has ### times the number of transactions as the test networks. + +### Examples of other correct word usage + +> The main network on Ethereum is Mainnet + +This shows that "main" is used as a descriptive word, but Mainnet is the specific network which is having chain ID 1. + +### Examples of poor word choice (avoid this) + +> Deploy your contract to the Ethereum main network. + +This is referring to a "main" network which is context-dependent. If you were reading this text on a page about Ethereum Classic, they would be referring to network_id: 2 / chain_id: 62. Therefore this word usage is less crisp. Do NOT use wording like this. + +> Connect to mainnet. + +These words literally mean nothing. The lowercase, not-proper-noun word "mainnet" is not a plain English word and it should not be in any dictionary. Do NOT use wording like this. + +## Implementation + +An exhaustive list of examples is provided above in the specification and test cases sections. + +## References + +**Standards** + +1. [EIP-2](./eip-2.md) Homestead Hard-fork Changes. +1. [EIP-7](./eip-7.md) DELEGATECALL. +1. [EIP-150](./eip-150.md) Gas cost changes for IO-heavy operations. +1. [EIP-155](./eip-155.md) Simple replay attack protection. +1. [EIP-170](./eip-170.md) Contract code size limit. +1. [EIP-779](./eip-779.md) Hardfork Meta: DAO Fork. + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-2242.md b/EIPS/eip-2242.md index d4ecf0d290b6cb..4be7be2946e0e1 100644 --- a/EIPS/eip-2242.md +++ b/EIPS/eip-2242.md @@ -16,7 +16,7 @@ An additional, optional transaction field is added for "postdata," data that is A paradigm shift in how blockchains are used has been seen recently in Eth 2.0, with the rise of [_Execution Environments_](https://notes.ethereum.org/w1Pn2iMmSTqCmVUTGV4T5A?view) (EEs), and [_stateless clients_](https://ethresear.ch/t/the-stateless-client-concept/172). This shift involves blockchains serving as a secure data availability and arbitration layer, _i.e._, they provide a globally-accepted source of available data, and process fraud/validity and data availability proofs. This same paradigm can be applied on Eth 1.x, replacing EEs with [trust-minimized side chains](https://ethresear.ch/t/building-scalable-decentralized-payment-systems-request-for-feedback/5312). ## Motivation -While [EIP-2028](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2028.md) provides a reduction in gas cost of calldata, and is a step in the right direction of encouraging use of history rather than state, the EVM does not actually need to see all data that is posted on-chain. Following the principle of "don't pay for what you don't use," a distinct way of posting data on-chain, but without actually being usable within the EVM, is needed. +While [EIP-2028](./eip-2028.md) provides a reduction in gas cost of calldata, and is a step in the right direction of encouraging use of history rather than state, the EVM does not actually need to see all data that is posted on-chain. Following the principle of "don't pay for what you don't use," a distinct way of posting data on-chain, but without actually being usable within the EVM, is needed. For [trust-minimized side chains with fraud proofs](https://ethresear.ch/t/minimal-viable-merged-consensus/5617), we simply need to ensure that the side chain block proposer has attested that _some_ data is available. Authentication can be performed as part of a fraud proof should that data end up invalid. Note that [trust-minimized side chains with validity proofs](https://ethresear.ch/t/on-chain-scaling-to-potentially-500-tx-sec-through-mass-tx-validation/3477) can't make use of the changes proposed in this EIP, as they required immediate authentication of the posted data. This will be [the topic of a future EIP](https://ethresear.ch/t/multi-threaded-data-availability-on-eth-1/5899). diff --git a/EIPS/eip-2255.md b/EIPS/eip-2255.md index 3a50c10da80e2f..883ac33961a587 100644 --- a/EIPS/eip-2255.md +++ b/EIPS/eip-2255.md @@ -72,7 +72,7 @@ const response = await provider.send({ }) ``` -If this request was rejected, it would throw an error with a `code` value equal to `4001`, per [EIP 1193 errors](https://eips.ethereum.org/EIPS/eip-1193), which the MetaMask team has canonized in a module [eth-json-rpc-errors](https://github.com/metamask/eth-json-rpc-errors). +If this request was rejected, it would throw an error with a `code` value equal to `4001`, per [EIP 1193 errors](./eip-1193.md), which the MetaMask team has canonized in a module [eth-json-rpc-errors](https://github.com/metamask/eth-json-rpc-errors). If the request is accepted by the user, then subsequent requests to `eth_accounts` will succeed, and return an accounts array as usual. diff --git a/EIPS/eip-2256.md b/EIPS/eip-2256.md index 9912183e97a740..fcdeb3da52ad7a 100644 --- a/EIPS/eip-2256.md +++ b/EIPS/eip-2256.md @@ -22,7 +22,7 @@ There is no standardized way for a dApp to request a list of owned assets from a There are financial dApps that require a list of owned assets from a user, for various purposes - calculating taxes, selecting customized payment options, etc. Each of these dApps are now forced to keep a list of popular assets (smart contract addresses, ABIs) and retrieve the user's data from the blockchain, for each asset. This leads to effort duplication and nonoptimal UX where the user is presented with either more or less asset options than the user would like - various airdrops, incomplete list of assets kept by the dApp. -This list of owned assets can be retrieved from the wallet used by the user. The wallet can allow the user to manage only the assets that the user is interested in. Therefore, a new JSON-RPC method is proposed: `wallet_getOwnedAssets`. This method is complementary to [EIP-747](https://eips.ethereum.org/EIPS/eip-747), which proposes a way for sites to suggest users new assets to watch on their wallet. +This list of owned assets can be retrieved from the wallet used by the user. The wallet can allow the user to manage only the assets that the user is interested in. Therefore, a new JSON-RPC method is proposed: `wallet_getOwnedAssets`. This method is complementary to [EIP-747](./eip-747.md), which proposes a way for sites to suggest users new assets to watch on their wallet. ## Specification @@ -31,7 +31,7 @@ New JSON-RPC method to be added to web3 browsers: `wallet_getOwnedAssets`. This **Arguments:** - type `address`, Ethereum address that owns the assets - options object, optional: - - `chainId` - type `uint`, chain id respecting [EIP-155](https://eips.ethereum.org/EIPS/eip-155); optional + - `chainId` - type `uint`, chain id respecting [EIP-155](./eip-155.md); optional - `limit` - type `uint`, the maximum number of owned assets expected by the dApp to be returned; optional - `types` - type `string[]`, array of asset interface identifiers such as `['ERC20', 'ERC721']`; optional - `justification` - type `string`, human-readable text provided by the dApp, explaining the intended purpose of this request; optional but recommended @@ -40,7 +40,7 @@ New JSON-RPC method to be added to web3 browsers: `wallet_getOwnedAssets`. This - array with asset records: - `address` - type `address`, Ethereum checksummed address - `chainId` - type `uint`, identifier for the chain on which the assets are deployed - - `type` - type `string`, asset interface ERC identifier; e.g. `ERC20`; optional - [EIP-1820](https://eips.ethereum.org/EIPS/eip-1820) could be used + - `type` - type `string`, asset interface ERC identifier; e.g. `ERC20`; optional - [EIP-1820](./eip-1820.md) could be used - `options` - an object with asset-specific fields; `ERC20` tokens example: - `name` - type `string`, token name; optional if the token does not implement it - `symbol` - type `string`, token symbol; optional if the token does not implement it diff --git a/EIPS/eip-2304.md b/EIPS/eip-2304.md index 73d4289c6db56c..53b98763d4e719 100644 --- a/EIPS/eip-2304.md +++ b/EIPS/eip-2304.md @@ -100,7 +100,7 @@ For example, the Bitcoin SegWit address `BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F To translate a text format checksummed hex address into binary format, simply remove the '0x' prefix and hex decode it. `0x314159265dD8dbb310642f98f50C066173C1259b` is hex-decoded and stored as the 20 bytes `314159265dd8dbb310642f98f50c066173c1259b`. -A checksum format is specified by [EIP 55](https://eips.ethereum.org/EIPS/eip-55), and extended by [RSKIP60](https://github.com/rsksmart/RSKIPs/blob/master/IPs/RSKIP60.md), which specifies a means of including the chain ID in the checksum. The checksum on a text format address must be checked. Addresses with invalid checksums that are not all uppercase or all lowercase MUST be rejected with an error. Implementations may choose whether to accept non-checksummed addresses, but the authors recommend at least providing a warning to users in this situation. +A checksum format is specified by [EIP-55](./eip-55.md), and extended by [RSKIP60](https://github.com/rsksmart/RSKIPs/blob/master/IPs/RSKIP60.md), which specifies a means of including the chain ID in the checksum. The checksum on a text format address must be checked. Addresses with invalid checksums that are not all uppercase or all lowercase MUST be rejected with an error. Implementations may choose whether to accept non-checksummed addresses, but the authors recommend at least providing a warning to users in this situation. When encoding an address from binary to text, an EIP55/RSKIP60 checksum MUST be used - so the correct encoding of the above address for Ethereum is `0x314159265dD8dbb310642f98f50C066173C1259b`. diff --git a/EIPS/eip-2309.md b/EIPS/eip-2309.md index 16d17823313da6..8cccb4af9447a3 100644 --- a/EIPS/eip-2309.md +++ b/EIPS/eip-2309.md @@ -106,7 +106,7 @@ This can lead to bugs and unnecessary complex logic for platforms using these ev As the NFT market continues to grow so does the need for the ability to scale the smart contracts. Users need to be able to do things like mint a massive amount of tokens at one time, transfer a massive amount of tokens, and be able to track ownership of all these assets. We need to do this in a way that is cost effective and doesn’t fail under the confines of the Ethereum blockchain. As millions of tokens are minted we need contracts with the ability to scale. -[ERC-1155](./eip-1155) was created and added as a standard in 2019 to try to solve these problems, but it falls short when it comes to minting massive amounts of unique tokens in a cost-effective way. With ERC-1155 it’s either going to cost hundreds (or thousands) of dollars or it’s going to run out of gas. ERC-1155 works well when minting many semi-fungible tokens but falls short when minting many unique tokens. Using the 2039 standard you could mint millions of blank NFTs upfront and update the metadata for each one in a cost effective way. +[ERC-1155](./eip-1155.md) was created and added as a standard in 2019 to try to solve these problems, but it falls short when it comes to minting massive amounts of unique tokens in a cost-effective way. With ERC-1155 it’s either going to cost hundreds (or thousands) of dollars or it’s going to run out of gas. ERC-1155 works well when minting many semi-fungible tokens but falls short when minting many unique tokens. Using the 2039 standard you could mint millions of blank NFTs upfront and update the metadata for each one in a cost effective way. ## Backwards Compatibility diff --git a/EIPS/eip-2315.md b/EIPS/eip-2315.md index 390306a0847056..d57a56e8f7685f 100644 --- a/EIPS/eip-2315.md +++ b/EIPS/eip-2315.md @@ -1,10 +1,10 @@ --- eip: 2315 title: Simple Subroutines for the EVM -status: Draft +status: Withdrawn type: Standards Track category: Core -author: Greg Colvin (greg@colvin.org), Martin Holst Swende (@holiman) +author: Greg Colvin , Martin Holst Swende (@holiman) discussions-to: https://ethereum-magicians.org/t/eip-2315-simple-subroutines-for-the-evm/3941 created: 2019-10-17 --- @@ -15,15 +15,13 @@ This proposal introduces three opcodes to support subroutines: `BEGINSUB`, `JUMP ## 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. Memory allows for simpler conventions but still costs gas. Eschewing subroutines in user code is the least costly -- but also the most failure-prone. +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. Sometimes 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. 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. 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 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. @@ -62,7 +60,7 @@ _Note 3: The description above lays out the semantics of this feature in terms o ## Rationale -This is the is a small change that provides native subroutines without breaking backwards compatibility. +This is almost the smallest change that provides native subroutines without breaking backwards compatibility. ## Backwards Compatibility @@ -203,75 +201,4 @@ We suggest the following opcodes: 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. - -``` -contract fun { - function test(uint x, uint y) public returns (uint) { - return test_mul(2,3); - } - function test_mul(uint x, uint y) public returns (uint) { - return multiply(x,y); - } - function multiply(uint x, uint y) public returns (uint) { - return x * y; - } -} - -``` -Here is solc 0.6.3 assembly code with labeled destinations. -``` -TEST: - jumpdest - 0x00 - RTN - 0x02 - 0x03 - TEST_MUL - jump -TEST_MUL: - jumpdest - 0x00 - RTN - dup4 - dup4 - MULTIPLY - jump -RTN: - jumpdest - swap4 - swap3 - pop - pop - pop - jump -MULTIPLY: - jumpdest - mul - swap1 - jump -``` -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 _32 gas_ plus 5 for the `mul`. -``` -TEST: - beginsub - 0x02 - 0x03 - TEST_MUL - jumpsub - returnsub -TEST_MUL: - beginsub - MULTIPLY - jumpsub - returnsub -MULTIPLY: - beginsub - mul - returnsub -``` - **Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).** diff --git a/EIPS/eip-2327.md b/EIPS/eip-2327.md index be7ed55b929430..3546458110da69 100644 --- a/EIPS/eip-2327.md +++ b/EIPS/eip-2327.md @@ -10,25 +10,33 @@ created: 2019-10-28 --- ## Simple Summary -Introduces a new opcode `BEGINDATA`, which indicates that the remaining bytes of the contract should be regarded as data rather than contract code. +Introduces a new opcode `BEGINDATA`, which indicates that the remaining bytes of the contract should be regarded as data rather than contract code +and cannot be executed. ## Abstract -It is common for smart contracts to efficiently store data directly in the contract bytecode. Examples include constant variables, compiler metadata and the contract runtime during the init phase. Currently, such data is not distinguished from normal bytecode and is still being analysed for `JUMPDEST`s by EVM interpreters. This EIP introduces a new opcode `BEGINDATA` at byte `0xb6`, which marks the remainding bytecode as data, indicating to EVM interpreters, static analysis tools and chain explorers that the remaining bytes do not represent opcodes. +It is common for smart contracts to efficiently store data directly in the contract bytecode. Examples include constructor arguments, constant variables, compiler metadata and the contract runtime during the init phase. Currently, such data is not distinguished from normal bytecode and is still being analysed for `JUMPDEST`s by EVM interpreters. This EIP introduces a new opcode `BEGINDATA` at byte `0xb6`, which marks the remainding bytecode as data, indicating to EVM interpreters, static analysis tools and chain explorers that the remaining bytes do not represent opcodes. ## Motivation -The `BEGINDATA` opcode has been suggested before as part of the EIP `Subroutines and Static Jumps for the EVM` [EIP-615](https://eips.ethereum.org/EIPS/eip-615) as a way to determine the position of jumptables in contract bytecode. It is here introduced in its own right in order to exclude data from the `JUMPDEST` analysis of contracts, making it impossible to jump to data. This makes it easier for static analysis tools to analyse contracts, allows disassemblers, chain explorers and debuggers to not display data as a mess of INVALID opcodes and may even provide a marginal improvement in performance. Additionally, it paves the way for suggestions such as [EIP 1712](https://github.com/ethereum/EIPs/pull/1712) to disallow unused opcodes, jumptables [EIP-615](https://eips.ethereum.org/EIPS/eip-615) and speculative proposals to disallow for deployment of contracts with stack usage violations. +The `BEGINDATA` opcode has been suggested before as part of the EIP `Subroutines and Static Jumps for the EVM` [EIP-615](./eip-615.md) as a way to determine the position of jumptables in contract bytecode. It is here introduced in its own right in order to exclude data from the `JUMPDEST` analysis of contracts, making it impossible to jump to data. This makes it easier for static analysis tools to analyse contracts, allows disassemblers, chain explorers and debuggers to not display data as a mess of INVALID opcodes and may even provide a marginal improvement in performance. It also helps scalability because it improves on-chain evaluation of transactions from other chains in that the validation that the code conforms to a certain pattern does not need to do a full jumpdest analysis to see that data is not executed and thus does not have to conform to the pattern (used by the optimism project). Additionally, it paves the way for suggestions such as [EIP-1712](https://github.com/ethereum/EIPs/pull/1712) to disallow unused opcodes, jumptables [EIP-615](./eip-615.md) and speculative proposals to disallow for deployment of contracts with stack usage violations. ## Specification -While computing the valid `JUMPDEST`s of a contract, halt analysis if `BEGINDATA` is encountered. A `JUMP` to a value higher than the `PC` value of `BEGINDATA` should throw with a `BAD_JUMP_DESTINATION` error. Bytes past `BEGINDATA` remain accessible via `CODECOPY` and `EXTCODECOPY`. +While computing the valid `JUMPDEST`s of a contract, halt analysis once the first `BEGINDATA` is encountered. In other words: A jump to any codelocation equal to or greater than the location of the first `BEGINDATA` causes a `BAD_JUMP_DESTINATION` error. If `BEGINDATA` is encountered during contract execution, it has the same semantics as `STOP`. It uses 0 gas. +Bytes past `BEGINDATA` remain accessible via `CODECOPY` and `EXTCODECOPY`. `BEGINDATA` does not influence `CODESIZE` or `EXTCODESIZE`. + ## Rationale -The byte `0xb6` was chosen to align with [EIP-615](https://eips.ethereum.org/EIPS/eip-615). +The byte `0xb6` was chosen to align with [EIP-615](./eip-615.md). The choice to `STOP` if `BEGINDATA` is encountered is somewhat arbitrary. An alternative would be to be to abort the execution with an out-of-gas error. ## Backwards Compatibility The proposal will not change any existing contracts unless their current behaviour relies upon the usage of unused opcodes. +Since contracts have been using data from the very start, in a sense all of them use unused opcodes, +but they would have to use data in a way that it is skipped during execution and jumped over. +The Solidity compiler never generated such code. It has to be evaluated whether contracts created by other means +could have such a code structure. + ## Test Cases Test cases should include: 1) A contract which jumps to a destination `X`, where `X` has a pc value higher than the `BEGINDATA` opcode, and the byte at `X` is `0x5b`. This should fail with a `BAD_JUMP_DESTINATION` error. diff --git a/EIPS/eip-233.md b/EIPS/eip-233.md index 7dde4bafe65594..c70c6b49c7ab56 100644 --- a/EIPS/eip-233.md +++ b/EIPS/eip-233.md @@ -52,7 +52,7 @@ The Meta EIP representing the hard fork should move in to the `Accepted` state o ## Template -A template for the [Istanbul Hardfork Meta 1679](https://eips.ethereum.org/EIPS/eip-1679) is included below ([source file on GitHub](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1679.md)): +A template for the [Istanbul Hardfork Meta 1679](./eip-1679.md) is included below ([source file on GitHub](./eip-1679.md)): ``` {% raw %} diff --git a/EIPS/eip-2333.md b/EIPS/eip-2333.md index b929bbf849d8a0..7e601b0c3c7a39 100644 --- a/EIPS/eip-2333.md +++ b/EIPS/eip-2333.md @@ -241,9 +241,9 @@ There are no major backwards compatibility issues brought upon by this EIP as it ```text seed = 0xc55257c360c07c72029aebc1b53c05ed0362ada38ead3e3e9efa3708e53495531f09a6987599d18264c1e1c92f2cf141630c7a3c4ab7c81b2f001698e7463b04 -master_SK = 5399117110774477986698372024995405256382522670366369834617409486544348441851 +master_SK = 6083874454709270928345386274498605044986640685124978867557563392430687146096 child_index = 0 -child_SK = 11812940737387919040225825939013910852517748782307378293770044673328955938106 +child_SK = 20397789859736650942317412262472558107875392172444076792671091975210932703118 ``` This test case can be extended to test the entire mnemonic-to-`child_SK` stack, assuming [BIP39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki) is used as the mnemonic generation mechanism. Using the following parameters, the above seed can be calculated: diff --git a/EIPS/eip-2334.md b/EIPS/eip-2334.md index de803a3b794eae..300a1ac794eeb2 100644 --- a/EIPS/eip-2334.md +++ b/EIPS/eip-2334.md @@ -12,11 +12,11 @@ requires: 2333 ## Simple Summary -This EIP defines the purpose of a given key, or family thereof, within a tree of keys. When combined with [EIP-2333](https://eips.ethereum.org/EIPS/eip-2333), the combination of a seed and knowledge of the desired purpose of a key is sufficient to determine a key pair. +This EIP defines the purpose of a given key, or family thereof, within a tree of keys. When combined with [EIP-2333](./eip-2333.md), the combination of a seed and knowledge of the desired purpose of a key is sufficient to determine a key pair. ## Abstract -A standard for allocating keys generated by [EIP-2333](https://eips.ethereum.org/EIPS/eip-2333) to a specific purpose. It defines a `path` which is a string that parses into the indices to be used when traversing the tree of keys that [EIP-2333](https://eips.ethereum.org/EIPS/eip-2333) generates. +A standard for allocating keys generated by [EIP-2333](./eip-2333.md) to a specific purpose. It defines a `path` which is a string that parses into the indices to be used when traversing the tree of keys that [EIP-2333](./eip-2333.md) generates. ## A note on purpose @@ -24,9 +24,9 @@ This specification is designed not only to be an Ethereum 2.0 standard, but one ## Motivation -Ethereum 2.0 alongside many other projects will use BLS12-381 signatures. This new scheme requires a new key derivation mechanism, which is established within [EIP-2333](https://eips.ethereum.org/EIPS/eip-2333). This new scheme is incompatible with the current form of this specification ([BIP44](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki)) due to the: exclusive use of hardened keys, the increased number of keys per level, not using [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) for key derivation. It is therefore necessary to establish a new *path* for traversing the [EIP-2333](https://eips.ethereum.org/EIPS/eip-2333) key-tree. +Ethereum 2.0 alongside many other projects will use BLS12-381 signatures. This new scheme requires a new key derivation mechanism, which is established within [EIP-2333](./eip-2333.md). This new scheme is incompatible with the current form of this specification ([BIP44](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki)) due to the: exclusive use of hardened keys, the increased number of keys per level, not using [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) for key derivation. It is therefore necessary to establish a new *path* for traversing the [EIP-2333](./eip-2333.md) key-tree. -The path structure specified in this EIP aims to be more general than [BIP44](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki) by not having UTXO-centric features [which gave rise to the 4 different types of wallet paths being used within Ethereum 1.0](https://github.com/ethereum/EIPs/issues/84#issuecomment-292324521) and gave rise to (draft) EIPs [600](https://eips.ethereum.org/EIPS/eip-600) & [601](https://eips.ethereum.org/EIPS/eip-601) +The path structure specified in this EIP aims to be more general than [BIP44](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki) by not having UTXO-centric features [which gave rise to the 4 different types of wallet paths being used within Ethereum 1.0](https://github.com/ethereum/EIPs/issues/84#issuecomment-292324521) and gave rise to (draft) [EIP-600](./eip-600.md) & [EIP-601](./eip-601.md) ## Specification @@ -40,14 +40,14 @@ m / purpose / coin_type / account / use #### Notation -The notation used within the path is specified within the [EIP-2333](https://eips.ethereum.org/EIPS/eip-2333), but is summarized again below for convenience. +The notation used within the path is specified within the [EIP-2333](./eip-2333.md), but is summarized again below for convenience. * `m` Denotes the master node (or root) of the tree * `/` Separates the tree into depths, thus `i / j` signifies that `j` is a child of `i` ### Purpose -The `purpose` is set to `12381` which is the name of the new curve (BLS12-381). In order to be in compliance with this standard, the [EIP-2333](https://eips.ethereum.org/EIPS/eip-2333) MUST be implemented as the KDF and therefore, the purpose `12381` MAY NOT be used unless this is the case. +The `purpose` is set to `12381` which is the name of the new curve (BLS12-381). In order to be in compliance with this standard, the [EIP-2333](./eip-2333.md) MUST be implemented as the KDF and therefore, the purpose `12381` MAY NOT be used unless this is the case. ### Coin Type @@ -89,13 +89,13 @@ The purpose needs to be distinct from these standards as the KDF and path are no ### Eth2 Specific Parameters -A new coin type is chosen for Eth2 keys to help ensure a clean separation between Eth2 and Eth1 keys. Although the distinction between Eth1 ETH and Eth2 ETH is subtle, they are distinct entities and there are services which only distinguish between coins by their coin name (eg. [ENS' multichain address resolution](https://eips.ethereum.org/EIPS/eip-2304)). `3600` is chosen specifically because it is the square of the Eth1's `coin_type` (`3600==60^2`) thereby signaling that it is second instantiation of Ether the currency. +A new coin type is chosen for Eth2 keys to help ensure a clean separation between Eth2 and Eth1 keys. Although the distinction between Eth1 ETH and Eth2 ETH is subtle, they are distinct entities and there are services which only distinguish between coins by their coin name (eg. [ENS' multichain address resolution](./eip-2304.md)). `3600` is chosen specifically because it is the square of the Eth1's `coin_type` (`3600==60^2`) thereby signaling that it is second instantiation of Ether the currency. The primary reason validators have separate signing and withdrawal keys is to allow for the different security concerns of actions within Eth2. The signing key is given to the validator client where it signs messages as per the requirements of being a validator, it is therefore a "hot key". If this key is compromised, the worst that can happen (locally) is that a slashable message is signed, resulting in the validator being slashed and forcibly exited. The withdrawal key is only needed when a validator wishes to perform an action not related to validating and has access to the full funds at stake for that validator. The withdrawal key therefore has higher security concerns and should be handled as a "cold key". By having the signing key be a child of the withdrawal key, secure storage of the withdrawal key is sufficient to recover the signing key should the need arise. ## Backwards Compatibility -[BIP43](https://github.com/bitcoin/bips/blob/master/bip-0043.mediawiki) and [BIP44](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki) are the commonly used standards for this purpose within Ethereum 1.0, however they have not been `Accepted` as standards as yet. Due to the use of a new KDF within [EIP-2333](https://eips.ethereum.org/EIPS/eip-2333), a new path standard is required. This EIP implements this, with minor changes. +[BIP43](https://github.com/bitcoin/bips/blob/master/bip-0043.mediawiki) and [BIP44](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki) are the commonly used standards for this purpose within Ethereum 1.0, however they have not been `Accepted` as standards as yet. Due to the use of a new KDF within [EIP-2333](./eip-2333.md), a new path standard is required. This EIP implements this, with minor changes. `purpose` `12381` paths do not support hardened keys and therefore the `'` character is invalid. diff --git a/EIPS/eip-2335.md b/EIPS/eip-2335.md index 561660f5c7ac99..4bad77e287bf12 100644 --- a/EIPS/eip-2335.md +++ b/EIPS/eip-2335.md @@ -28,7 +28,7 @@ The secure storage and exchange of keys is a vital component of the user experie In Ethereum 1, [the Web3 Secret Storage Definition](https://github.com/ethereum/wiki/wiki/Web3-Secret-Storage-Definition) fulfills these requirements, however it is not perfectly suitable for these purposes moving forward. Specifically the problems with the existing standard are: -* __The use of Keccak256.__ Eth1 keystores use Keccak for their checksum, a sensible choice considering its usage within Ethereum 1. BLS12-381 [signatures](https://tools.ietf.org/html/draft-irtf-cfrg-bls-signature-00), [keys (EIP-2333)](https://eips.ethereum.org/EIPS/eip-2333), and key-storage are inter-chain standards, the establishment and proliferation of which hinges on them being neutral to all chains, something which Keccak is not. +* __The use of Keccak256.__ Eth1 keystores use Keccak for their checksum, a sensible choice considering its usage within Ethereum 1. BLS12-381 [signatures](https://tools.ietf.org/html/draft-irtf-cfrg-bls-signature-00), [keys (EIP-2333)](./eip-2333.md), and key-storage are inter-chain standards, the establishment and proliferation of which hinges on them being neutral to all chains, something which Keccak is not. * __A lack of abstraction.__ Eth1 keystores are a result of an iterative design process whereby functionality was added and modified as needed without considering how abstractions could simplify the notion of different properties. @@ -110,7 +110,7 @@ The `pubkey` is the public key associated with the the private key secured withi ## Path -The `path` indicates where in the key-tree a key originates from. It is a string defined by [EIP-2334](https://eips.ethereum.org/EIPS/eip-2334), if no path is known or the path is not relevant, the empty string, `""` indicates this. The `path` can specify an arbitrary depth within the tree and the deepest node within the tree indicates the depth of the key stored within this file. +The `path` indicates where in the key-tree a key originates from. It is a string defined by [EIP-2334](./eip-2334.md), if no path is known or the path is not relevant, the empty string, `""` indicates this. The `path` can specify an arbitrary depth within the tree and the deepest node within the tree indicates the depth of the key stored within this file. ## UUID diff --git a/EIPS/eip-2364.md b/EIPS/eip-2364.md index 88654d3d9d8ad5..dde5598e4eb9cd 100644 --- a/EIPS/eip-2364.md +++ b/EIPS/eip-2364.md @@ -12,9 +12,9 @@ requires: 2124 ## Abstract -The [`forkid` (EIP-2124)](https://eips.ethereum.org/EIPS/eip-2124) was designed to permit two Ethereum nodes to quickly and cheaply decide if they are compatible or not, not only at a genesis/networking level, but also from the perspective of the currently passed network updates (i.e. forks). +The [`forkid` (EIP-2124)](./eip-2124.md) was designed to permit two Ethereum nodes to quickly and cheaply decide if they are compatible or not, not only at a genesis/networking level, but also from the perspective of the currently passed network updates (i.e. forks). -[EIP-2124](https://eips.ethereum.org/EIPS/eip-2124) only defines how the `forkid` is calculated and validated, but does not specify how the `forkid` should be exchanged between peers. This EIP specifies the inclusion of the `forkid` as a new field in the Ethereum wire protocol (`eth`) handshake (releasing a new version, `eth/64`). +[EIP-2124](./eip-2124.md) only defines how the `forkid` is calculated and validated, but does not specify how the `forkid` should be exchanged between peers. This EIP specifies the inclusion of the `forkid` as a new field in the Ethereum wire protocol (`eth`) handshake (releasing a new version, `eth/64`). By cross-validating `forkid` during the handshake, incompatible nodes can disconnect before expensive block exchanges and validations take place (PoW check, EVM execution, state reconstruction). This further prevents peer slots from being taken up by nodes that are incompatible, but have not yet been detected as such. @@ -28,13 +28,13 @@ From a macro perspective, keeping incompatible nodes partitioned from one anothe The specification is tiny since most parts are already specified in EIP-2124. `eth/63` is not specified as an EIP, but is maintained [here](https://github.com/ethereum/devp2p/blob/master/caps/eth.md). -- Implement `forkid` generation and validation per [EIP-2124](https://eips.ethereum.org/EIPS/eip-2124). +- Implement `forkid` generation and validation per [EIP-2124](./eip-2124.md). - Advertise a new `eth` protocol capability (version) at `eth/64`. - The old `eth/63` protocol should still be kept alive side-by-side, until `eth/64` is sufficiently adopted by implementors. - Redefine `Status (0x00)` for `eth/64` to add a trailing `forkid` field: - Old packet: `[protocolVersion, networkId, td, bestHash, genesisHash]` - New packet: `[protocolVersion, networkId, td, bestHash, genesisHash, forkid]`, - where `forkid` is `[forkHash: [4]byte, forkNext: uint64]` (fields per [EIP-2124](https://eips.ethereum.org/EIPS/eip-2124) ). + where `forkid` is `[forkHash: [4]byte, forkNext: uint64]` (fields per [EIP-2124](./eip-2124.md) ). Whenever two peers connect using the `eth/64` protocol, the updated `Status` message must be sent as the protocol handshake, and each peer must validate the remote `forkid`, disconnecting at a detected incompatibility. @@ -46,7 +46,7 @@ Advertising and validating the `forkid` in the discovery protocol is a more opti Compared to the `eth` protocol however, discovery is a bit fuzzy. The goal there is to suggest potential peers, not to be fool-proof. Information may be outdated, nodes may have changed or disappeared. Discovery can do a rough filtering, but more precision is still needed afterwards. -Additionally, `forkid` validation via the discovery protocol requires ENR implementation ([EIP-778](https://eips.ethereum.org/EIPS/eip-778)) and ENR extension support ([EIP-868](https://eips.ethereum.org/EIPS/eip-868)), which is not mandated by the Ethereum network currently. Lastly, the discovery protocol is just one way to find peers, but systems that cannot use UDP or that rely on other mechanism (e.g. DNS discovery ([EIP-1459](https://eips.ethereum.org/EIPS/eip-1459))) still need a way to filter connections. +Additionally, `forkid` validation via the discovery protocol requires ENR implementation ([EIP-778](./eip-778.md)) and ENR extension support ([EIP-868](./eip-868.md)), which is not mandated by the Ethereum network currently. Lastly, the discovery protocol is just one way to find peers, but systems that cannot use UDP or that rely on other mechanism (e.g. DNS discovery ([EIP-1459](./eip-1459.md))) still need a way to filter connections. ##### The `forkid` implicitly contains the genesis hash checksummed into the `FORK_HASH` field. Why doesn't this proposal remove the `genesisHash` field from the `eth` handshake? @@ -62,7 +62,7 @@ This EIP does not change the consensus engine, thus does _not_ require a hard fo ## Test Cases -For calculating and validating fork IDs, see test cases in [EIP-2124](https://eips.ethereum.org/EIPS/eip-2124). +For calculating and validating fork IDs, see test cases in [EIP-2124](./eip-2124.md). Testing proper advertising and validation at the networking level will require a [hive](https://github.com/ethereum/hive) test. diff --git a/EIPS/eip-2384.md b/EIPS/eip-2384.md index f00101490ac1bc..2c7c39dd8accfe 100644 --- a/EIPS/eip-2384.md +++ b/EIPS/eip-2384.md @@ -34,7 +34,7 @@ This EIP is not forward compatible and introduces backwards incompatibilities in Test cases shall be created once the specification is to be accepted by the developers or implemented by the clients. ## Implementation -The implementation in it's logic does not differ from [EIP-649](https://eips.ethereum.org/EIPS/eip-649) or [EIP-1234](https://eips.ethereum.org/EIPS/eip-1234); an implementation for Parity-Ethereum is available in [parity-ethereum#9187](https://github.com/paritytech/parity-ethereum/pull/9187). +The implementation in it's logic does not differ from [EIP-649](./eip-649.md) or [EIP-1234](./eip-1234.md); an implementation for Parity-Ethereum is available in [parity-ethereum#9187](https://github.com/paritytech/parity-ethereum/pull/9187). ## Copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-2387.md b/EIPS/eip-2387.md index 095c30b4ef621c..94e810c43825ec 100644 --- a/EIPS/eip-2387.md +++ b/EIPS/eip-2387.md @@ -36,7 +36,7 @@ This fork will push back the Iceage as far as far as is reasonable and will give - `Block >= N/A` on the Görli testnet ### Included EIPs - - [EIP-2384](https://eips.ethereum.org/EIPS/eip-2384): Istanbul/Berlin Difficulty Bomb Delay + - [EIP-2384](./eip-2384.md): Istanbul/Berlin Difficulty Bomb Delay ## Rationale @@ -64,7 +64,7 @@ This fork would give us time to address the community to understand their priori ### POA Testnets -Muir Glacier never activates on PoA chains – thus will have zero impact on [forkid](https://eips.ethereum.org/EIPS/eip-2124). +Muir Glacier never activates on PoA chains – thus will have zero impact on [forkid](./eip-2124.md). ### Note on Issuance Reduction diff --git a/EIPS/eip-2400.md b/EIPS/eip-2400.md index b8ea5929a5288d..9cc754e2a48b17 100644 --- a/EIPS/eip-2400.md +++ b/EIPS/eip-2400.md @@ -100,5 +100,5 @@ Future upgrades that are partially or fully incompatible with this proposal must Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). -[ERC-831]: https://eips.ethereum.org/EIPS/eip-831 -[ERC-681]: https://eips.ethereum.org/EIPS/eip-681 +[ERC-831]: ./eip-831.md +[ERC-681]: ./eip-681.md diff --git a/EIPS/eip-2458.md b/EIPS/eip-2458.md index 89da328c89dfb7..21ea4bc1ef8249 100644 --- a/EIPS/eip-2458.md +++ b/EIPS/eip-2458.md @@ -3,7 +3,7 @@ eip: 2458 title: Updates and Updated-by Header author: Edson Ayllon (@edsonayllon) discussions-to: https://github.com/ethereum/EIPs/issues/2453 -status: Draft +status: Withdrawn type: Informational created: 2020-01-06 --- diff --git a/EIPS/eip-2470.md b/EIPS/eip-2470.md index f7a573a9a7952c..811385f030b4c9 100644 --- a/EIPS/eip-2470.md +++ b/EIPS/eip-2470.md @@ -27,7 +27,7 @@ Code reuse, using the factory becomes easier to deploy singletons. ## Specification -### [ERC2470] Singleton Factory +### [ERC-2470] Singleton Factory > This is an exact copy of the code of the [ERC2470 factory smart contract]. @@ -187,10 +187,10 @@ Contracts deployed on factory must not use `msg.sender` in constructor, instead ## 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-155]: ./eip-155.md +[EIP-1191]: ./eip-1191.md +[EIP-1344]: ./eip-1344.md +[EIP-1820]: ./eip-1820.md [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-2474.md b/EIPS/eip-2474.md new file mode 100644 index 00000000000000..df5983cda63859 --- /dev/null +++ b/EIPS/eip-2474.md @@ -0,0 +1,62 @@ +--- +eip: 2474 +title: Coinbase calls +author: Ricardo Guilherme Schmidt (@3esmit) +discussions-to: https://ethresear.ch/t/gas-abstraction-non-signed-block-validator-only-procedures/4388/2 +status: Draft +type: Standards Track +category: Core +created: 2020-01-19 +--- + +## Simple Summary + +Allow contracts to be called directly by `block.coinbase` (block validator), without a transaction. + +## Abstract + +_In proof-of-work blockchains, validators are known as miners._ + +The validator might want to execute functions directly, without having to sign a transaction. Some examples might be presenting a proof in a contract for an change which also benefits the validator. + +A notable example would be when a validator want to act as an [EIP-1077](./eip-1077.md) Gas Relayer, incentivized to pick up fees from meta transactions. +Without this change, they can do so by signing from any address a `gasPrice = 0` transaction with the gas relayed call. +However this brings an overhead of a signed transaction by validator that does nothing, as `msg.sender` is never used, and there is no gas cost to EVM charge. + +This proposal makes possible to remove this unused ecrecover. + +## Motivation + +In order to reduce the overhead of calls that don't use `msg.sender` and are being called by validator with `tx.gasPrice = 0`. + +## Specification + +The calls to be executed by `block.coinbase` would be included first at block, and would consume normally the gas of block, however they won't pay/cost gas, instead the call logic would pay the validator in other form. + +Would be valid to execute any calls without a transaction by the block coinbase, except when the validator call tries to read `msg.sender`, which would throw an invalid jump. + +Calls included by the validator would have `tx.origin = block.coinbase` and `gas.price = 0` for the rest of call stack, the rest follows as normal calls. + +## Rationale + +TBD + +## Backwards Compatibility + +`tx.origin = block.coinbase` could cause some issues on bad designed contracts, such as using `tx.origin` to validate a signature, an analysis on how contracts use tx.origin might be useful to decide if this is a good choice. + +## Test Cases + +TBD + +## Implementation + +TBD + +## Security Considerations + +TBD + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-2477.md b/EIPS/eip-2477.md index 82c9483aca1c2d..7ce473676740dd 100644 --- a/EIPS/eip-2477.md +++ b/EIPS/eip-2477.md @@ -296,17 +296,17 @@ TODO: ADD IMPLEMENTATIONS WITH 0XCERT ENJIN, NIKE, AZURE/MICROSOFT Normative standard references 1. RFC 2119 Key words for use in RFCs to Indicate Requirement Levels. https://www.ietf.org/rfc/rfc2119.txt -2. ERC-165 Standard Interface Detection. https://eips.ethereum.org/EIPS/eip-165 -3. ERC-721 Non-Fungible Token Standard. https://eips.ethereum.org/EIPS/eip-721 -4. ERC-1155 Multi Token Standard. https://eips.ethereum.org/EIPS/eip-1155 +2. ERC-165 Standard Interface Detection. ./eip-165.md +3. ERC-721 Non-Fungible Token Standard. ./eip-721.md +4. ERC-1155 Multi Token Standard. ./eip-1155.md 5. JSON-LD. https://www.w3.org/TR/json-ld/ 6. Secure Hash Standard (SHS). https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf Other standards -1. ERC-1046 ERC-20 Metadata Extension (DRAFT). https://eips.ethereum.org/EIPS/eip-1046 -2. ERC-918 Mineable Token Standard (DRAFT). https://eips.ethereum.org/EIPS/eip-918 -3. ERC-1523 Standard for Insurance Policies as ERC-721 Non Fungible Tokens (DRAFT). https://eips.ethereum.org/EIPS/eip-1523 +1. ERC-1046 ERC-20 Metadata Extension (DRAFT). ./eip-1046.md +2. ERC-918 Mineable Token Standard (DRAFT). ./eip-918.md +3. ERC-1523 Standard for Insurance Policies as ERC-721 Non Fungible Tokens (DRAFT). ./eip-1523.md 4. W3C Subresource Integrity (SRI). https://www.w3.org/TR/SRI/ 5. The "data" URL scheme. https://tools.ietf.org/html/rfc2397 6. Uniform Resource Identifier (URI): Generic Syntax. https://tools.ietf.org/html/rfc3986 diff --git a/EIPS/eip-2481.md b/EIPS/eip-2481.md index 2d5bf5285665a5..584c2e6a3e9dc5 100644 --- a/EIPS/eip-2481.md +++ b/EIPS/eip-2481.md @@ -3,7 +3,7 @@ eip: 2481 title: "eth/66: request identifier" author: Christoph Burgdorf discussions-to: https://github.com/ethereum/EIPs/issues/2482 -status: Draft +status: Review type: Standards Track category: Networking created: 2020-01-17 @@ -43,14 +43,7 @@ Let's consider a client making many simultaneous requests for `GetBlockHeaders` 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, ...]]` +This EIP proposes to change the `GetBlockHeaders` and the `BlockHeaders` command to include a `request_id`. 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. @@ -103,8 +96,6 @@ 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 @@ -151,10 +142,279 @@ This EIP does not change the consensus engine, thus does *not* require a hard fo ## Implementation Trinity has a [draft PR](https://github.com/ethereum/trinity/pull/1672) with an implementation. +Geth [PR](https://github.com/ethereum/go-ethereum/pull/22241). ## Security Considerations None +## Test cases + +These testcases cover RLP-encoding of all the redefined messages types, where the `rlp` portion is the rlp-encoding of the message defined in the `data` portion. + + +```json +{ + "type": "GetBlockHeadersPacket66", + "rlp": "0xe8820457e4a000000000000000000000000000000000000000000000000000000000deadc0de050580", + "data": { + "RequestId": 1111, + "Origin": { + "Hash": "0x00000000000000000000000000000000000000000000000000000000deadc0de", + "Number": 0 + }, + "Amount": 5, + "Skip": 5, + "Reverse": false + } +} +``` +```json +{ + "type": "GetBlockHeadersPacket66", + "rlp": "0xca820457c682270f050580", + "data": { + "RequestId": 1111, + "Origin": { + "Hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "Number": 9999 + }, + "Amount": 5, + "Skip": 5, + "Reverse": false + } +} +``` +```json +{ + "type": "BlockHeadersPacket66", + "rlp": "0xf90202820457f901fcf901f9a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008208ae820d0582115c8215b3821a0a827788a00000000000000000000000000000000000000000000000000000000000000000880000000000000000", + "data": { + "RequestId": 1111, + "BlockHeadersPacket": [ + { + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "sha3Uncles": "0x0000000000000000000000000000000000000000000000000000000000000000", + "miner": "0x0000000000000000000000000000000000000000", + "stateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "transactionsRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "receiptsRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "difficulty": "0x8ae", + "number": "0xd05", + "gasLimit": "0x115c", + "gasUsed": "0x15b3", + "timestamp": "0x1a0a", + "extraData": "0x7788", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "hash": "0x8c2f2af15b7b563b6ab1e09bed0e9caade7ed730aec98b70a993597a797579a9" + } + ] + } +} +``` +```json +{ + "type": "GetBlockBodiesPacket66", + "rlp": "0xf847820457f842a000000000000000000000000000000000000000000000000000000000deadc0dea000000000000000000000000000000000000000000000000000000000feedbeef", + "data": { + "RequestId": 1111, + "GetBlockBodiesPacket": [ + "0x00000000000000000000000000000000000000000000000000000000deadc0de", + "0x00000000000000000000000000000000000000000000000000000000feedbeef" + ] + } +} +``` +```json +{ + "type": "BlockBodiesPacket66", + "rlp": "0xf902dc820457f902d6f902d3f8d2f867088504a817c8088302e2489435353535353535353535353535353535353535358202008025a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c12a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10f867098504a817c809830334509435353535353535353535353535353535353535358202d98025a052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afba052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afbf901fcf901f9a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008208ae820d0582115c8215b3821a0a827788a00000000000000000000000000000000000000000000000000000000000000000880000000000000000", + "data": { + "RequestId": 1111, + "BlockBodiesPacket": [ + { + "Transactions": [ + { + "nonce": "0x8", + "gasPrice": "0x4a817c808", + "gas": "0x2e248", + "to": "0x3535353535353535353535353535353535353535", + "value": "0x200", + "input": "0x", + "v": "0x25", + "r": "0x64b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c12", + "s": "0x64b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10", + "hash": "0x588df025c4c2d757d3e314bd3dfbfe352687324e6b8557ad1731585e96928aed" + }, + { + "nonce": "0x9", + "gasPrice": "0x4a817c809", + "gas": "0x33450", + "to": "0x3535353535353535353535353535353535353535", + "value": "0x2d9", + "input": "0x", + "v": "0x25", + "r": "0x52f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afb", + "s": "0x52f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afb", + "hash": "0xf39c7dac06a9f3abf09faf5e30439a349d3717611b3ed337cd52b0d192bc72da" + } + ], + "Uncles": [ + { + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "sha3Uncles": "0x0000000000000000000000000000000000000000000000000000000000000000", + "miner": "0x0000000000000000000000000000000000000000", + "stateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "transactionsRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "receiptsRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "difficulty": "0x8ae", + "number": "0xd05", + "gasLimit": "0x115c", + "gasUsed": "0x15b3", + "timestamp": "0x1a0a", + "extraData": "0x7788", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "hash": "0x8c2f2af15b7b563b6ab1e09bed0e9caade7ed730aec98b70a993597a797579a9" + } + ] + } + ] + } +} +``` +```json +{ + "type": "GetNodeDataPacket66", + "rlp": "0xf847820457f842a000000000000000000000000000000000000000000000000000000000deadc0dea000000000000000000000000000000000000000000000000000000000feedbeef", + "data": { + "RequestId": 1111, + "GetNodeDataPacket": [ + "0x00000000000000000000000000000000000000000000000000000000deadc0de", + "0x00000000000000000000000000000000000000000000000000000000feedbeef" + ] + } +} +``` +```json +{ + "type": "NodeDataPacket66", + "rlp": "0xce820457ca84deadc0de84feedbeef", + "data": { + "RequestId": 1111, + "NodeDataPacket": [ + "0xdeadcode", + "0xfeedbeef" + ] + } +} +``` +```json +{ + "type": "GetReceiptsPacket66", + "rlp": "0xf847820457f842a000000000000000000000000000000000000000000000000000000000deadc0dea000000000000000000000000000000000000000000000000000000000feedbeef", + "data": { + "RequestId": 1111, + "GetReceiptsPacket": [ + "0x00000000000000000000000000000000000000000000000000000000deadc0de", + "0x00000000000000000000000000000000000000000000000000000000feedbeef" + ] + } +} +``` +```json +{ + "type": "ReceiptsPacket66", + "rlp": "0xf90172820457f9016cf90169f901668001b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f85ff85d940000000000000000000000000000000000000011f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100ff", + "data": { + "RequestId": 1111, + "ReceiptsPacket": [ + [ + { + "root": "0x", + "status": "0x0", + "cumulativeGasUsed": "0x1", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "logs": [ + { + "address": "0x0000000000000000000000000000000000000011", + "topics": [ + "0x000000000000000000000000000000000000000000000000000000000000dead", + "0x000000000000000000000000000000000000000000000000000000000000beef" + ], + "data": "0x0100ff", + "blockNumber": "0x0", + "transactionHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "transactionIndex": "0x0", + "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "logIndex": "0x0", + "removed": false + } + ], + "transactionHash": "0x00000000000000000000000000000000000000000000000000000000deadc0de", + "contractAddress": "0x0000000000000000000000000000000000011111", + "gasUsed": "0x1b207", + "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "transactionIndex": "0x0" + } + ] + ] + } +} +``` + +```json +{ + "type": "GetPooledTransactionsPacket66", + "rlp": "0xf847820457f842a000000000000000000000000000000000000000000000000000000000deadc0dea000000000000000000000000000000000000000000000000000000000feedbeef", + "data": { + "RequestId": 1111, + "GetPooledTransactionsPacket": [ + "0x00000000000000000000000000000000000000000000000000000000deadc0de", + "0x00000000000000000000000000000000000000000000000000000000feedbeef" + ] + } +} +``` +```json +{ + "type": "PooledTransactionsPacket66", + "rlp": "0xf8d7820457f8d2f867088504a817c8088302e2489435353535353535353535353535353535353535358202008025a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c12a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10f867098504a817c809830334509435353535353535353535353535353535353535358202d98025a052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afba052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afb", + "data": { + "RequestId": 1111, + "PooledTransactionsPacket": [ + { + "nonce": "0x8", + "gasPrice": "0x4a817c808", + "gas": "0x2e248", + "to": "0x3535353535353535353535353535353535353535", + "value": "0x200", + "input": "0x", + "v": "0x25", + "r": "0x64b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c12", + "s": "0x64b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10", + "hash": "0x588df025c4c2d757d3e314bd3dfbfe352687324e6b8557ad1731585e96928aed" + }, + { + "nonce": "0x9", + "gasPrice": "0x4a817c809", + "gas": "0x33450", + "to": "0x3535353535353535353535353535353535353535", + "value": "0x2d9", + "input": "0x", + "v": "0x25", + "r": "0x52f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afb", + "s": "0x52f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afb", + "hash": "0xf39c7dac06a9f3abf09faf5e30439a349d3717611b3ed337cd52b0d192bc72da" + } + ] + } +} +``` + + ## Copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-2488.md b/EIPS/eip-2488.md index c258c5050910e6..35e548a31bc149 100644 --- a/EIPS/eip-2488.md +++ b/EIPS/eip-2488.md @@ -18,7 +18,7 @@ Deprecate `CALLCODE` in a *somewhat* backwards compatible way, by making it alwa `CALLCODE` was part of the Frontier release of Ethereum. In the first few weeks/months it became clear that it cannot accomplish its intended design goal. This was rectified with introducing `DELEGATECALL` -([EIP-7](https://eips.ethereum.org/EIPS/eip-7)) in the Homestead update (early 2016). +([EIP-7](./eip-7.md)) in the Homestead update (early 2016). `CALLCODE` became never utilized, but it still puts a burden on EVM implementations. diff --git a/EIPS/eip-2520.md b/EIPS/eip-2520.md new file mode 100644 index 00000000000000..5546ee247ec7d9 --- /dev/null +++ b/EIPS/eip-2520.md @@ -0,0 +1,75 @@ +--- +eip: 2520 +title: Multiple contenthash records for ENS +author: Filip Štamcar (@filips123) +discussions-to: https://github.com/ethereum/EIPs/issues/2393 +status: Draft +type: Standards Track +category: ERC +created: 2020-02-18 +requires: 1577 +--- + +## Simple Summary +ENS support for multiple `contenthash` records on a single ENS name. + +## Motivation +Many applications are resolving ENS names to content hosted on distributed systems. To do this, they use `contenthash` record from ENS domain to know how to resolve names and which distributed system should be used. + +However, the domain can store only one `contenthash` record which means that the site owner needs to decide which hosting system to use. Because there are many ENS-compatible hosting systems available (IPFS, Swarm, recently Onion and ZeroNet), and there will probably be even more in the future, lack of support for multiple records could become problematic. Instead, domains should be able to store multiple `contenthash` records to allow applications to resolve to multiple hosting systems. + +## Specification +Setting and getting functions **MUST** have the same public interface as specified in EIP 1577. Additionally, they **MUST** also have new public interfaces introduced by this EIP: + +* For setting a `contenthash` record, the `setContenthash` **MUST** provide additional `proto` parameter and use it to save the `contenthash`. When `proto` is not provided, it **MUST** save the record as default record. + + ```solidity + function setContenthash(bytes32 node, bytes calldata proto, bytes calldata hash) external authorised(node); + ``` + +* For getting a `contenthash` record, the `contenthash` **MUST** provide additional `proto` parameter and use it to get the `contenthash` for requested type. When `proto` is not provided, it **MUST** return the default record. + + ```solidity + function contenthash(bytes32 node, bytes calldata proto) external view returns (bytes memory); + ``` + +* Resolver that supports multiple `contenthash` records **MUST** return `true` for `supportsInterface` with interface ID `0x6de03e07`. + +Applications that are using ENS `contenthash` records **SHOULD** handle them in the following way: + +* If the application only supports one hosting system (like directly handling ENS from IPFS/Swarm gateways), it **SHOULD** request `contenthash` with a specific type. The contract **MUST** then return it and application **SHOULD** correctly handle it. + +* If the application supports multiple hosting systems (like MetaMask), it **SHOULD** request `contenthash` without a specific type (like in EIP 1577). The contract **MUST** then return the default `contenthash` record. + +## Rationale +The proposed implementation was chosen because it is simple to implement and supports all important requested features. However, it doesn't support multiple records for the same type and priority order, as they don't give much advantage and are harder to implement properly. + +## Backwards Compatibility +The EIP is backwards-compatible with EIP 1577, the only differences are additional overloaded methods. Old applications will still be able to function correctly, as they will receive the default `contenthash` record. + +## Implementation +```solidity +contract ContentHashResolver { + bytes4 constant private MULTI_CONTENT_HASH_INTERFACE_ID = 0x6de03e07; + mapping(bytes32=>mapping(bytes=>bytes)) hashes; + + function setContenthash(bytes32 node, bytes calldata proto, bytes calldata hash) external { + hashes[node][proto] = hash; + emit ContenthashChanged(node, hash); + } + + function contenthash(bytes32 node, bytes calldata proto) external view returns (bytes memory) { + return hashes[node][proto]; + } + + function supportsInterface(bytes4 interfaceID) public pure returns(bool) { + return interfaceID == MULTI_CONTENT_HASH_INTERFACE_ID; + } +} +``` + +## Security Considerations +TBD + +## 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 index 35c330af139e3b..4153668eb3cd37 100644 --- a/EIPS/eip-2525.md +++ b/EIPS/eip-2525.md @@ -12,7 +12,7 @@ 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. +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](./eip-1193.md) 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 @@ -29,9 +29,9 @@ That way, ENSLogin would allow any user to connect to any Dapp with any wallet, 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)) +* Resolve the ENS domain to retrieve (see [EIP-137](./eip-137.md)) + * An address (see [EIP-137](./eip-137.md)) + * A text entry (see [EIP-634](./eip-634.md)) * 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 @@ -42,7 +42,7 @@ This workflow is to be implemented by an SDK that Dapp could easily import. The ### 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**). +* **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](./eip-634.md)). 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')` @@ -60,7 +60,7 @@ This workflow is to be implemented by an SDK that Dapp could easily import. The 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). + * [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](./eip-1193.md). * Other blockchain types/langages should be detailed in the future. diff --git a/EIPS/eip-2535.md b/EIPS/eip-2535.md index f8722e189513d1..a92d0e4749e6db 100644 --- a/EIPS/eip-2535.md +++ b/EIPS/eip-2535.md @@ -1,7 +1,7 @@ --- eip: 2535 title: Diamond Standard -author: Nick Mudge +author: Nick Mudge (@mudgen), Nick Mudge discussions-to: https://github.com/ethereum/EIPs/issues/2535 status: Draft type: Standards Track @@ -13,18 +13,48 @@ created: 2020-02-22 ## Simple Summary -A new smart contract paradigm that works today. +Enables people to write contracts with virtually no size limit in a modular and gas-efficient way. -A diamond is a contract with functionality from multiple contracts that can share internal functions, libraries and state variables. +Diamonds can be upgraded on the fly without having to redeploy existing functionality. -Diamonds are powerful, organized, modular, optionally upgradeable, flexible, unlimited in size, and transparent. - -Diamonds enable you to build efficient, powerful, flexible, modular smart contract systems. +Standardizes contract interfaces and implementation details of diamonds, enabling software integration and interoperability. A diamond is a contract that implements the Specification in this standard. Terminology from the diamond industry. +## Motivation + +There are a number of different reasons to use diamonds. Here are some of them: + +1. **Your contract exceeds the 24KB maximum contract size.** You may have related functionality that it makes sense to keep in a single contract, or at a single contract address. A diamond does not have a max contract size. +2. **A diamond provides a way to organize contract code and data.** You may want to build a contract system with a lot of functionality. A diamond provides a systematic way to isolate different functionality and connect them together and share data between them as needed in a gas-efficient way. +3. **A diamond provides a way to upgrade functionality.** Upgradeable diamonds can be upgraded to add/replace/remove functionality. Because diamonds have no max contract size, there is no limit to the amount of functionality that can be added to diamonds over time. Diamonds can be upgradeable or immutable. It is also possible to make an upgradeable diamond and then at a later time remove its upgrade capability. + +### Diamonds Support Transparency + +To find out what functions a regular smart contract has it is only necessary to look at its verified source code. + +The verified source code of a diamond does not include what functions it has so a different mechanism is needed. + +A diamond has four standard functions called the loupe functions that are used to show what functions a diamond has. + +The loupe functions can be used for many things including: +1. To show all functions used by a diamond. +1. To query services like Etherscan or files to retrieve and show all source code used by a diamond. +1. To query services like Etherscan or files to retrieve ABI information for a diamond. +1. To test or verify that a transaction that adds/replaces/removes functions on a diamond succeeded. +1. To find out what functions a diamond has before calling functions on it. +1. To be used by tools and programming libraries to deploy and upgrade diamonds. +1. To be used by user interfaces to show information about diamonds. +1. To be used by user interfaces to enable users to call functions on diamonds. + +Diamonds support another form of transparency which is a historical record of all upgrades on a diamond. This is done with the DiamondCut event which is used to record all functions that are added, replaced or removed on a diamond. + +This standard is an improvement of [EIP-1538 Transparent Contract Standard](https://eips.ethereum.org/EIPS/eip-1538). The same motivations of that standard apply to this standard. + +See the [Learning & References section](https://eips.ethereum.org/EIPS/eip-2535#learning--references) for additional information and uses of diamonds. + ## What is a Diamond? A diamond is a contract with external functions that are supplied by contracts called **facets**. @@ -35,19 +65,20 @@ Facets are separate, independent contracts that can share internal functions, li A diamond stores within it a mapping of function selector to facet address, for example `selectorToFacet`. -When an external function is called on a diamond its fallback function is executed. The fallback function finds in the `selectorToFacet` mapping which facet has the function that has been called and then executes that function from the facet using `delegatecall`. +When an external function is called on a diamond its fallback function is executed. The fallback function finds in the `selectorToFacet` mapping which facet has the function that has been called and then executes that function from the facet using `delegatecall`. A diamond's fallback function and `delegatecall` enable a diamond to execute a facet's external function as its own external function. The `msg.sender` and `msg.value` values do not change and only the diamond's contract storage is read and written to. Here is a simple example of a diamond's fallback function: + ```Solidity // Find facet for function that is called and execute the // function if a facet is found and return any value. -fallback() external payable { - address facet = selectorTofacet[msg.sig]; +fallback() external payable { + address facet = selectorTofacet[msg.sig]; require(facet != address(0)); // Execute external function from facet using delegatecall and return any value. - assembly { + assembly { calldatacopy(0, 0, calldatasize()) let result := delegatecall(gas(), facet, 0, calldatasize(), 0, 0) returndatacopy(0, 0, returndatasize()) @@ -55,7 +86,7 @@ fallback() external payable { case 0 {revert(0, returndatasize())} default {return (0, returndatasize())} } -} +} ``` A diamond can use a `diamondCut` function to add/replace/remove any number of functions from any number of facets in a single transaction. `diamondCut` updates the mapping of function selector to facet address. Other such functions can be used. @@ -76,17 +107,14 @@ A diamond can be upgraded if it has a diamondCut external function or other func A facet defines external functions and can define or use internal functions, libraries, and state variables. -A facet can declare and use state variables but it does it in a way that is safer, easier and more flexible for diamonds. - -Facet state variables are declared in structs. Each struct is given a specific position in contract storage. This technique is called **Diamond Storage**. +A facet can declare state variables in structs. Each struct is given a specific position in contract storage. This technique is called **Diamond Storage**. Here is a simple example that shows diamond storage and its use in a facet: ```Solidity // A contract that implements diamond storage. -// This contract is inherited and used by facets. -contract DiamondStorageContract { - +library LibA { + // This struct contains state variables we care about. struct DiamondStorage { address owner; @@ -95,25 +123,25 @@ contract DiamondStorageContract { // Returns the struct from a specified position in contract storage // ds is short for DiamondStorage - function diamondStorage() internal pure returns(DiamondStorage storage ds) { - // Specifies a random position from a hash of a string - bytes32 storagePosition = keccak256("diamond.storage") - // Set the position of our struct in contract storage + function diamondStorage() internal pure returns(DiamondStorage storage ds) { + // Specifies a random position from a hash of a string + bytes32 storagePosition = keccak256("diamond.storage.LibA") + // Set the position of our struct in contract storage assembly {ds.slot := storagePosition} } } -// Our facet inherits and uses the diamond storage defined above. -contract FacetA is DiamondStorageContract { +// Our facet uses the diamond storage defined above. +contract FacetA { function setDataA(bytes32 _dataA) external { - DiamondStorage storage ds = diamondStorage(); + LibA.DiamondStorage storage ds = LibA.diamondStorage(); require(ds.owner == msg.sender, "Must be owner."); ds.dataA = _dataA } - + function getDataA() external view returns (bytes32) { - return diamondStorage().dataA + return LibDiamond.diamondStorage().dataA } } ``` @@ -124,7 +152,11 @@ By using diamond storage facets can declare their own state variables that do no By using diamond storage facets can be developed independently, without connection or concern for other facets. -Solidity libraries can also use diamond storage. +## Diamonds Can Use Other Contract Storage Strategies + +Diamonds and facets don't have to use diamond storage. They can use other contract storage strategies such as contract inheritance. + +Diamonds only need to implement the [Specification section](#specification) of this standard. ## Facets Can Share State and Functionality @@ -140,11 +172,11 @@ A deployed facet can be used by any number of diamonds. Different combinations of facets can be used with different diamonds. -It is possible to create and deploy a set of facets that are reused by different diamonds over time. +It is possible to create and deploy a set of facets that are reused by different diamonds over time. The ability to use the same deployed facets for many diamonds reduces deployment costs. -A limitation is that two external functions with the same function signature can't be added to a diamond at the same time because a diamond, or any contract, cannot have two external functions with the same function signature. +A limitation is that two external functions with the same function signature can't be added to a diamond at the same time because a diamond, or any contract, cannot have two external functions with the same function signature. ## Diagrams @@ -161,11 +193,12 @@ The diagram below shows facets with their own data and data shared between them. Notice that all data is stored in the diamond. But different facets have different access to data. In this diagram -* Only FacetA can access DataA -* Only FacetB can access DataB -* Only the diamond's own code can access DataD. -* FacetA and FacetB share access to DataAB. -* The diamond's own code, FacetA and FacetB share access to DataABD. + +- Only FacetA can access DataA +- Only FacetB can access DataB +- Only the diamond's own code can access DataD. +- FacetA and FacetB share access to DataAB. +- The diamond's own code, FacetA and FacetB share access to DataABD. @@ -175,10 +208,10 @@ A deployed facet can be used by any number of diamonds. The diagram below shows two diamonds using the same two facets. -* FacetA is used by Diamond1 -* FacetA is used by Diamond2 -* FacetB is used by Diamond1 -* FacetB is used by Diamond2 +- FacetA is used by Diamond1 +- FacetA is used by Diamond2 +- FacetB is used by Diamond1 +- FacetB is used by Diamond2 @@ -190,7 +223,7 @@ The diagram below shows two diamonds using the same two facets. 1. Fine-grained upgrades, so you can change just the parts of a diamond that need to be changed. 1. Have greater control over when and what functions exist. 1. Decentralized Autonomous Organizations (DAOs) and other governance systems can be used to upgrade diamonds. -1. An event that shows what functions are added, replaced and removed. +1. An event that shows what functions are added, replaced and removed. 1. The ability to show all changes made to a diamond. 1. Increase trust over time by showing all changes made to a diamond. 1. A way to look at a diamond to see its current facets and functions. @@ -201,8 +234,8 @@ The diagram below shows two diamonds using the same two facets. 1. Enables zero, partial or full diamond immutability as desired, and when desired. 1. The ability to develop and improve an application over time with an upgradeable diamond and then make it immutable and trustless if desired. 1. Develop incrementally and let your diamond grow with your application. -1. Upgrade diamonds to fix bugs, add functionality and implement new standards. -1. Organize your code with a diamond and facets. +1. Upgrade diamonds to fix bugs, add functionality and implement new standards. +1. Organize your code with a diamond and facets. 1. Diamonds can be large (have many functions) but still be modular because they are compartmented with facets. 1. Contract architectures that call multiple contracts in a single transaction can save gas by condensing those contracts into a single diamond and accessing state variables directly. 1. Save gas by creating external functions for specific use cases, such as bulk transfers. @@ -217,6 +250,7 @@ Diamond events can be filtered from the Ethereum blockchain to show all changes Existing and new programming libraries and software can be used to deploy, show, upgrade and use diamonds. ### Upgradeable Diamond vs. Centralized Private Database + Why have an upgradeable diamond instead of a centralized, private, mutable database? 1. Decentralized Autonomous Organizations (DAOs) and other governance systems can be used to upgrade diamonds. @@ -227,6 +261,7 @@ Why have an upgradeable diamond instead of a centralized, private, mutable datab 1. It is possible for an upgradeable diamond to become immutable and trustless. ### Different Kinds of Diamonds + Many designs of diamonds are possible. Here are a few kinds of diamonds and their uses. **Upgradeable Diamond** @@ -236,22 +271,24 @@ An upgradeable diamond has the `diamondCut` function and/or possibly other funct A finished diamond was an upgradeable diamond and had a number of upgrades. Then its `diamondCut` function and/or other upgrade functions were removed and upgrades are no longer possible. It is no longer possible to add/replace/remove functions. It has become an immutable diamond. **Single Cut Diamond** -A single cut diamond adds all functions to itself in its constructor function, but it does not add the `diamondCut` function or any other function that can add/replace/remove functions. This means that a single cut diamond is fully created in its constructor and once created can never be upgraded. It has the same immutability and trustless guarantees as a regular vanilla contract. Why would someone do this? There may be a number of reasons. The two use cases below are good reasons. +A single cut diamond adds all functions to itself in its constructor function, but it does not add the `diamondCut` function or any other function that can add/replace/remove functions. This means that a single cut diamond is fully created in its constructor and once created can never be upgraded. It has the same immutability and trustless guarantees as a regular vanilla contract. Why would someone do this? There may be a number of reasons. The two use cases below are good reasons. -1. Your contract hits the max contract size limit. Make it into a single cut diamond. You still break your big contract into smaller facets, modularizing your code. +1. Your contract hits the max contract size limit. Make it into a single cut diamond. You still break your big contract into smaller facets, modularizing your code. 2. You start with an upgradeable diamond in your development and testing and upgrade it to your heart's delight. Reap the advantages of easy upgrading and a stable address as you work out new features, bugs and kinks. Release the upgradeable diamond on a test network with your application for beta testing and upgrade it when needed. This is iterative development. When it is solid then deploy it as a single cut diamond on the main network. ## Specification -> **Note:** -The solidity `delegatecall` opcode enables a contract to execute a function from another contract, but it is executed as if the function was from the calling contract. Essentially `delegatecall` enables a contract to "borrow" another contract's function. Functions executed with `delegatecall` affect the contract storage of the calling contract, not the contract where the functions are defined. + +> **Note:** +> The solidity `delegatecall` opcode enables a contract to execute a function from another contract, but it is executed as if the function was from the calling contract. Essentially `delegatecall` enables a contract to "borrow" another contract's function. Functions executed with `delegatecall` affect the contract storage of the calling contract, not the contract where the functions are defined. > **Note:** This specification specifies what needs to be implemented for a contract to be a diamond. ### Terms + 1. A **diamond** is a contract that uses functions from its facets to execute function calls. A diamond can have one or more facets. 2. The word **facet** comes from the diamond industry. It is a side, or flat surface of a diamond. A diamond can have many facets. In this standard a facet is a contract with one or more functions that executes functionality of a diamond. 3. A **loupe** is a magnifying glass that is used to look at diamonds. In this standard a loupe is a facet that provides functions to look at a diamond and its facets. -3. An **immutable function** is a function that is defined directly in a diamond and so cannot be replaced or removed. Or it is a function that is defined in a facet that cannot be replaced or removed because all upgrade functions have been removed from a diamond. +4. An **immutable function** is a function that is defined directly in a diamond and so cannot be replaced or removed. Or it is a function that is defined in a facet that cannot be replaced or removed because all upgrade functions have been removed from a diamond. ### General Summary @@ -261,13 +298,13 @@ In the diamond industry diamonds are created and shaped by being cut, creating f #### The diamondCut Function -The standard `diamondCut` function specified below can be used to add/replace/remove any number of functions from/to a diamond in a single transaction. It has been designed for maximum flexibility while using the least amount of gas. +The standard `diamondCut` function specified below can be used to add/replace/remove any number of functions from/to a diamond in a single transaction. The standard `diamondCut` function below is specified for the purpose of interoperability. Diamond tools, software and user-interfaces should expect and use the standard `diamondCut` function. Diamonds that might work with diamond specific tooling to add/replace/remove functions should implement the standard `diamondCut` function. The `diamondCut` function is optional. It does not have to be implemented in a diamond. For example an immutable diamond wouldn't have this function. -You can implement your own custom functions that add or replace or remove functions. You can also implement your own non-standard versions of `diamondCut` that have different parameters. +You can implement your own custom functions that add or replace or remove functions. You can also implement your own non-standard versions of `diamondCut` that have different parameters. If you want to create your own custom function(s) for adding/replacing/removing functions you might also want to implement the standard `diamondCut` function for interoperability with tools. @@ -276,10 +313,15 @@ If you want to create your own custom function(s) for adding/replacing/removing The `DiamondCut` event records all changes to a diamond. ### Diamond Interface + ```Solidity interface IDiamondCut { - struct Facet { + enum FacetCutAction {Add, Replace, Remove} + // Add=0, Replace=1, Remove=2 + + struct FacetCut { address facetAddress; + FacetCutAction action; bytes4[] functionSelectors; } @@ -290,12 +332,12 @@ interface IDiamondCut { /// @param _calldata A function call, including function selector and arguments /// _calldata is executed with delegatecall on _init function diamondCut( - Facet[] calldata _diamondCut, + FacetCut[] calldata _diamondCut, address _init, bytes calldata _calldata ) external; - event DiamondCut(Facet[] _diamondCut, address _init, bytes _calldata); + event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata); } ``` @@ -303,23 +345,33 @@ interface IDiamondCut { A diamond contains within it a mapping of function selectors to facet addresses. Functions are added/replaced/removed by modifying this mapping. -The `_diamondCut` argument is an array of Facet structs. +The `_diamondCut` argument is an array of FacetCut structs. + +Each FacetCut struct contains a facet address and array of function selectors that are updated in a diamond. + +To add new functions create a FacetCut struct with `facetAddress` set to the facet that has the new functions and `functionSelectors` set with the function selectors to add. Set the `action` enum to `Add`. + +To replace functions create a FacetCut struct with `facetAddress` set to the facet that has the replacement functions and `functionSelectors` set with the function selectors to replace. Set the `action` enum to `Replace`. -Each Facet struct contains a facet address and an array of one or more function selectors. The mapping in a diamond is updated by each Facets struct. The selectors in a Facet struct are associated with the facet address in the same Facet struct. This is how functions are added or replaced. +To remove functions create a FacetCut struct with `facetAddress` set to `address(0)` and `functionSelectors` set with the function selectors to remove. Set the `action` enum to `Remove`. -However if a facet address in a Facet struct is `address(0)` then the function selectors in the same Facet struct are removed. This is how functions are removed from a diamond. +It is the design of the `diamondCut` function that cuts are explicit and intentional. -The `diamondCut` function does nothing if a supplied function selector is already associated with the supplied facet address. The `diamondCut` function does nothing if a supplied function selector can’t be removed because it already does not exist. +The `diamondCut` function reverts when attempting to add a function that already exists. -#### Executing _calldata +The `diamondCut` function reverts when attempting to replace a function with a facet it is already using. + +The `diamondCut` function reverts when attempting to remove a function that already does not exist. + +#### Executing \_calldata After adding/replacing/removing functions the `_calldata` argument is executed with `delegatecall` on `_init`. This execution is done to initialize data or setup or remove anything needed or no longer needed after adding, replacing and/or removing functions. -If the `_init` value is `address(0)` then `_calldata` must contain 0 bytes or the transaction reverts. +If the `_init` value is `address(0)` then `_calldata` must contain 0 bytes or the transaction reverts. -If the `_init` value is not `address(0)` then `_calldata` must contain more than 0 bytes or the transaction reverts. +If the `_init` value is not `address(0)` then `_calldata` must contain more than 0 bytes or the transaction reverts. -If `_init` is `address(0)` and `_calldata` contains 0 bytes then `_calldata` execution is skipped. `_calldata` is not executed and the `diamondCut` call can complete successfully. +If `_init` is `address(0)` and `_calldata` contains 0 bytes then `_calldata` execution is skipped. `_calldata` is not executed and the `diamondCut` call can complete successfully. #### DiamondCut Event @@ -328,12 +380,14 @@ The `_diamondCut`, `_init`, and `_calldata` arguments are passed directly to the Any time one or more functions are added, replaced or removed the `DiamondCut` event MUST be emitted to record changes. ### Diamond Loupe + > A loupe is a small magnifying glass used to look at diamonds. -These functions look at diamonds. +> These functions look at diamonds. The function selectors used by a diamond are queried to get what functions the diamond has and what facets are used. A diamond loupe is a facet that implements this interface: + ```Solidity // A loupe is a small magnifying glass used to look at diamonds. // These functions look at diamonds @@ -366,21 +420,25 @@ interface IDiamondLoupe { function facetAddress(bytes4 _functionSelector) external view returns (address facetAddress_); } ``` + See the [reference implementation](https://github.com/mudgen/Diamond) to see an example of how this can be implemented. -The loupe functions are designed for user-interface software. A user interface calls these functions to provide information about and visualize diamonds. +The loupe functions can be used in user-interface software. A user interface calls these functions to provide information about and visualize diamonds. + +The loupe functions can be used in deployment functionality, upgrade functionality, testing and other software. -In some implementations the loupe functions may not be gas efficient and so should not be called in on-chain transactions. In some implementations the loupe functions may be gas efficient and can be called in on-chain transactions. +Some loupe implementations are not gas efficient and should not be called in on-chain transactions. Some loupe implementations may be gas efficient and can be called in on-chain transactions. Read the documentation of the loupe implementation you use. ### Implementation Points A diamond implements the following implementation points: -1. A diamond contains a fallback function and zero or more immutable functions that are defined directly within it. +1. A diamond contains a fallback function and zero or more immutable functions that are defined within it. 1. A diamond associates function selectors with facets. -1. When a function is called on a diamond it executes immediately if it is an "immutable function" defined directly in the diamond. Otherwise the diamond's fallback function is executed. The fallback function finds the facet associated with the function and executes the function using `delegatecall`. If there is no facet for the function and no other mechanism to handle it then execution reverts. +1. When a function is called on a diamond it executes immediately if it is an "immutable function" defined in the diamond. Otherwise the diamond's fallback function is executed. The fallback function finds the facet associated with the function and executes the function using `delegatecall`. If there is no facet for the function and no other mechanism to handle it then execution reverts. 1. Each time functions are added, replaced or removed a `DiamondCut` event is emitted to record it. 1. A diamond implements the DiamondLoupe interface. +1. All immutable functions must be emitted in the `DiamondCut` event as new functions added. And the loupe functions must return information about immutable functions if they exist. The facet address for an immutable function is the diamond's address. 1. A diamond implements ERC165. If a diamond has the `diamondCut` function then the interface ID used for it is `IDiamondCut.diamondCut.selector`. The interface ID used for the diamond loupe interface is `IDiamondLoupe.facets.selector ^ IDiamondLoupe.facetFunctionSelectors.selector ^ IDiamondLoupe.facetAddresses.selector ^ IDiamondLoupe.facetAddress.selector`. The diamond address is the address that users interact with. The diamond address does not change. Only facet addresses can change by using the `diamondCut` function, or other function. @@ -395,15 +453,15 @@ A reference implementation is given in the [Diamond repository](https://github.c User interface software can be used to retrieve function selectors and face addresses from a diamond in order show what functions a diamond has. -This standard is designed to make diamonds work well with user-interface software. Function selectors with the ABI of a contract provide enough information about functions to be useful for user-interface software. +This standard is designed to make diamonds work well with user-interface software. Function selectors with the ABI of a contract provide enough information about functions to be useful for user-interface software. ### Gas Considerations -Delegating function calls does have some gas overhead. This is mitigated in several ways: +Delegating function calls does have some gas overhead. This is mitigated in several ways: + 1. Because diamonds do not have a max size limitation it is possible to add gas optimizing functions for use cases. For example someone could use a diamond to implement the ERC721 standard and implement batch transfer functions from the [ERC1412 standard](https://github.com/ethereum/EIPs/issues/1412) to reduce gas (and make batch transfers more convenient). -1. Some contract architectures require calling many contracts in one transaction. Gas savings can be realized by condensing those contracts into a single diamond and accessing contract storage directly. +1. Some contract architectures require calling many contracts in one transaction. Gas savings can be realized by condensing those contracts into a single diamond and accessing contract storage directly. 1. Facets can be small, reducing gas costs. Because it costs more gas to call a function in a contract with many functions than a contract with few functions. - 1. The Solidity optimizer can be set to a high setting causing more bytecode to be generated but the facets will use less gas when executed. ### Diamond Storage @@ -417,12 +475,15 @@ Diamond storage is not the same thing as unstructured storage. Unstructured stor Software or a user can verify what version of a function is called by getting the facet address of the function. This can be done by calling the `facetAddress` function from the DiamondLoupe interface. This function takes a function selector as an argument and returns the facet address where it is implemented. ### Sharing Functions Between Facets + In some cases it might be necessary to call a function defined in a different facet. Here are some solutions to this: + 1. Copy internal function code in one facet to the other facet. 1. Put common internal functions in a contract that is inherited by multiple facets. 1. Put common internal functions in a Solidity library and use the library in facets. -1. Use `delegatecall` to call external functions defined in other facets. Here is an example of doing that: +1. A type safe way to call an external function defined in another facet is to do this: MyOtherFacet(this).myFunction(arg1, arg2) +1. A more gas-efficent way to call an external function defined in another facet is to use `delegatecall`. Here is an example of doing that: ```Solidity DiamondStorage storage ds = diamondStorage(); bytes4 functionSelector = bytes4(keccak256("myFunction(uint256)")); @@ -432,26 +493,27 @@ bytes memory myFunctionCall = abi.encodeWithSelector(functionSelector, 4); (bool success, uint result) = address(facet).delegatecall(myFunctionCall); require(success, "myFunction failed"); ``` -5. Instead of using `delegatecall` to call an external function defined in another facet you can instead create an internal function version of the external function and use that. - +6. Instead of calling an external function defined in another facet you can instead create an internal function version of the external function. Add the internal version of the function to the facet that needs to use it. ## Security Considerations ### Ownership and Authentication ->**Note:** The design and implementation of diamond ownership/authentication is **not** part of this standard. The examples given in this standard and in the reference implementation are just **examples** of how it could be done. +> **Note:** The design and implementation of diamond ownership/authentication is **not** part of this standard. The examples given in this standard and in the reference implementation are just **examples** of how it could be done. -It is possible to create many different authentication or ownership schemes with the diamond standard. Authentication schemes can be very simple or complex, fine grained or coarse. The diamond standard does not limit it in any way. For example ownership/authentication could be as simple as a single account address having the authority to add/replace/remove functions. Or a decentralized autonomous organization could have the authority to only add/replace/remove certain functions. +It is possible to create many different authentication or ownership schemes with the diamond standard. Authentication schemes can be very simple or complex, fine grained or coarse. The diamond standard does not limit it in any way. For example ownership/authentication could be as simple as a single account address having the authority to add/replace/remove functions. Or a decentralized autonomous organization could have the authority to only add/replace/remove certain functions. -Consensus functionality could be implemented such as an approval function that multiple different people call to approve changes before they are executed with the `diamondCut` function. These are just examples. +Consensus functionality could be implemented such as an approval function that multiple different people call to approve changes before they are executed with the `diamondCut` function. These are just examples. The development of standards and implementations of ownership, control and authentication of diamonds is encouraged. ### Security of Diamond Storage + If a person can add/replace functions then that person can alter storage willy-nilly. This is very powerful and very dangerous. However the capability can be used while eliminating or reducing the danger. The danger is eliminated or reduced by limiting **who** can add/replace/remove functions, limiting **when** functions can be added/replaced/removed and by **transparency**. **Who** Here are some ways **who** can be limited: + 1. Only allow a trusted individual or organization to make diamond upgrades. 1. Only allow a distributed autonomous organization to make diamond upgrades. 1. Only allow multi-signature upgrades. @@ -460,22 +522,25 @@ Here are some ways **who** can be limited: **When** Here are some ways **when** can be limited: + 1. Only allow upgrades during development and testing. Make a single cut diamond for main network release. 1. Use an upgradeable diamond until it is certain that no new features are needed and then make it a finished diamond by removing the ability to add/replace/remove functions. 1. Program into the `diamondCut` function certain periods of time that the diamond can be upgraded. For example the `diamondCut` function could be programmed so that a diamond could only be upgraded during a specific five hour period each year. Attention and transparency could be applied to that five hour period to ensure upgrades are done right. **Transparency** Transparency provides certainty and proof that upgrades are done correctly and honestly. + 1. Publish and make available verified source code used by diamonds and facets. 1. Provide documentation for diamonds, facets, upgrade plans, and results of upgrades. 1. Provide tools and/or user interfaces that make your diamonds more visible and understandable. ### Function Selector Clash -A function selector clash occurs when two different function signatures hash to the same four-byte hash. This has the unintended consequence of replacing an existing function in a diamond when the intention was to add a new function. Function selector clashes are very rare but should be prevented by using tools that check for function selector clashes before calling the `diamondCut` function or similar function. + +A function selector clash occurs when two different function signatures hash to the same four-byte hash. This has the unintended consequence of replacing an existing function in a diamond when the intention was to add a new function. This scenario is not possible with the `diamondCut` function because it prevents adding function selectors that already exist. ### Transparency -Diamonds emit an event every time one or more functions are added, replaced or removed. All source code can be verified. This enables people and software to monitor changes to a contract. If any bad acting function is added to a diamond then it can be seen. +Diamonds emit an event every time one or more functions are added, replaced or removed. All source code can be verified. This enables people and software to monitor changes to a contract. If any bad acting function is added to a diamond then it can be seen. Security and domain experts can review the history of change of a diamond to detect any history of foul play. @@ -491,12 +556,28 @@ This standard makes upgradeable diamonds compatible with future standards and fu [Understanding Diamonds](https://dev.to/mudgen/understanding-diamonds-on-ethereum-1fb) -[New Storage Layout For Proxy Contracts and Diamonds](https://medium.com/1milliondevs/new-storage-layout-for-proxy-contracts-and-diamonds-98d01d0eadb) +[Why Ethereum Diamonds Need A Standard](https://dev.to/mudgen/why-diamonds-need-a-standard-1i1h) + +[Diamond Loupe Functions?](https://dev.to/mudgen/why-loupe-functions-for-diamonds-1kc3) [The Diamond Standard: A new paradigm for upgradeability](https://medium.com/derivadex/the-diamond-standard-a-new-paradigm-for-upgradeability-569121a08954) [Upgradeable smart contracts using the Diamond Standard](https://hiddentao.com/archives/2020/05/28/upgradeable-smart-contracts-using-diamond-standard) +[Ethereum Diamonds for On-Chain Decentralized Governance](https://dev.to/mudgen/ethereum-diamonds-for-on-chain-decentralized-governance-39op) + +### Diamond Storage Articles + +[How Diamond Storage Works](https://dev.to/mudgen/how-diamond-storage-works-90e) + +[New Storage Layout For Proxy Contracts and Diamonds](https://medium.com/1milliondevs/new-storage-layout-for-proxy-contracts-and-diamonds-98d01d0eadb) + +[Solidity Libraries Can't Have State Variables -- Oh Yes They Can!](https://dev.to/mudgen/solidity-libraries-can-t-have-state-variables-oh-yes-they-can-3ke9) + +[ Smart Contracts Sharing Common Data](https://medium.com/coinmonks/smart-contracts-sharing-common-data-777310263ac0?source=friends_link&sk=b462ff3559ae9c8da243ba31a557e4f4) + +[Sharing Common Data Using Libraries](https://medium.com/coinmonks/sharing-common-data-using-libraries-6573857d328c?source=friends_link&sk=1da1ef153b8d15f3f7bb9f4ce429890a) + ### Diamond Tools [buidler-deploy](https://github.com/wighawag/buidler-deploy#diamonds-and-facets) @@ -507,6 +588,10 @@ This standard makes upgradeable diamonds compatible with future standards and fu [Diamond Reference Implementation](https://github.com/mudgen/Diamond) +[GHST Staking](https://github.com/aavegotchi/ghst-staking) + +[pie-dao / ExperiPie](https://github.com/pie-dao/ExperiPie) + [Nayms Contracts](https://github.com/nayms/contracts) ### Help @@ -515,14 +600,14 @@ This standard makes upgradeable diamonds compatible with future standards and fu ## Inspiration & Development -The Diamond Standard is an improved design over [EIP-1538](https://eips.ethereum.org/EIPS/eip-1538) using ABIEncoderV2 and function selectors. +The Diamond Standard is an improved design over [EIP-1538](./eip-1538.md) using ABIEncoderV2 and function selectors. The Diamond Standard replaces EIP-1538. -This standard was inspired by [EIP-1538](https://eips.ethereum.org/EIPS/eip-1538) and ZeppelinOS's implementation of [Upgradeability with vtables](https://github.com/zeppelinos/labs/tree/master/upgradeability_with_vtable). +This standard was inspired by [EIP-1538](./eip-1538.md) and ZeppelinOS's implementation of [Upgradeability with vtables](https://github.com/zeppelinos/labs/tree/master/upgradeability_with_vtable). This standard was also inspired by the design and implementation of the [Mokens contract](https://etherscan.io/address/0xc1eab49cf9d2e23e43bcf23b36b2be14fc2f8838#code). - ## Copyright + Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-2537.md b/EIPS/eip-2537.md index bce8c74290ac79..7efb51cf6628f9 100644 --- a/EIPS/eip-2537.md +++ b/EIPS/eip-2537.md @@ -113,7 +113,7 @@ Scalar for multiplication operation is encoded as `32` bytes by performing BigEn ##### Behavior on empty inputs: -Certain operations have variable length input, such as multiexponentiations (takes a list of pairs `(point, scalar)`), or pairing (takes a list of `(G1, G2)` points). While their behavior is well-defined (from arithmetic perspective) on empty inputs, this EIP discourages such use cases and variable input length operations must return an error if input is empty. Also note special case of DDoS protection in *Error handling on the variable-length input* section below. +Certain operations have variable length input, such as multiexponentiations (takes a list of pairs `(point, scalar)`), or pairing (takes a list of `(G1, G2)` points). While their behavior is well-defined (from arithmetic perspective) on empty inputs, this EIP discourages such use cases and variable input length operations must return an error if input is empty. #### ABI for operations @@ -218,7 +218,7 @@ Assuming a constant `30 MGas/second` following prices are suggested. ##### G1 addition -`600` gas +`500` gas ##### G1 multiplication @@ -226,11 +226,11 @@ Assuming a constant `30 MGas/second` following prices are suggested. ##### G2 addition -`4500` gas +`800` gas ##### G2 multiplication -`55000` gas +`45000` gas ##### G1/G2 Multiexponentiation @@ -248,7 +248,7 @@ Discounts table as a vector of pairs `[k, discount]`: ##### Pairing operation -Cost of the pairing operation is `23000*k + 115000` where `k` is a number of pairs. +Cost of the pairing operation is `43000*k + 65000` where `k` is a number of pairs. ##### Fp-to-G1 mappign operation @@ -256,7 +256,7 @@ Fp -> G1 mapping is `5500` gas. ##### Fp2-to-G2 mappign operation -Fp2 -> G2 mapping is `110000` gas +Fp2 -> G2 mapping is `75000` gas #### Gas schedule clarifications for the variable-length input @@ -345,6 +345,27 @@ Required properties for pairing operation: Test vector for all operations are expanded in this `csv` files in [repo](https://github.com/matter-labs/eip1962/tree/master/src/test/test_vectors/eip2537). +### Benchmarking test cases + +Here one can find inputs (encoded with ABI of from this spec) that can be considered "worst cases" for "double-and-add" multiplication algorithm, and some cases for pairing call. Those are purely for convenience of initial benchmarking of the full ABI without manual test generation. + +``` +G1 addition example input = +0000000000000000000000000000000012196c5a43d69224d8713389285f26b98f86ee910ab3dd668e413738282003cc5b7357af9a7af54bb713d62255e80f560000000000000000000000000000000006ba8102bfbeea4416b710c73e8cce3032c31c6269c44906f8ac4f7874ce99fb17559992486528963884ce429a992fee000000000000000000000000000000000001101098f5c39893765766af4512a0c74e1bb89bc7e6fdf14e3e7337d257cc0f94658179d83320b99f31ff94cd2bac0000000000000000000000000000000003e1a9f9f44ca2cdab4f43a1a3ee3470fdf90b2fc228eb3b709fcd72f014838ac82a6d797aeefed9a0804b22ed1ce8f7 +G2 addition example input = +0000000000000000000000000000000018c0ada6351b70661f053365deae56910798bd2ace6e2bf6ba4192d1a229967f6af6ca1c9a8a11ebc0a232344ee0f6d6000000000000000000000000000000000cc70a587f4652039d8117b6103858adcd9728f6aebe230578389a62da0042b7623b1c0436734f463cfdd187d20903240000000000000000000000000000000009f50bd7beedb23328818f9ffdafdb6da6a4dd80c5a9048ab8b154df3cad938ccede829f1156f769d9e149791e8e0cd900000000000000000000000000000000079ba50d2511631b20b6d6f3841e616e9d11b68ec3368cd60129d9d4787ab56c4e9145a38927e51c9cd6271d493d938800000000000000000000000000000000192fa5d8732ff9f38e0b1cf12eadfd2608f0c7a39aced7746837833ae253bb57ef9c0d98a4b69eeb2950901917e99d1e0000000000000000000000000000000009aeb10c372b5ef1010675c6a4762fda33636489c23b581c75220589afbc0cc46249f921eea02dd1b761e036ffdbae220000000000000000000000000000000002d225447600d49f932b9dd3ca1e6959697aa603e74d8666681a2dca8160c3857668ae074440366619eb8920256c4e4a00000000000000000000000000000000174882cdd3551e0ce6178861ff83e195fecbcffd53a67b6f10b4431e423e28a480327febe70276036f60bb9c99cf7633 +G1 mul double and add worst case = +0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +G2 mul double and add worst case = +00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79beffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +Pairing case for 2 pairs = +0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be +Pairing case for 4 pairs = +0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be +Pairing case for 6 pairs = +0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be +``` + ## Implementation There is a various choice of existing implementations of the curve operations. It may require extra work to add an ABI: diff --git a/EIPS/eip-2539.md b/EIPS/eip-2539.md index fdf32c595a74de..8977521b907d8c 100644 --- a/EIPS/eip-2539.md +++ b/EIPS/eip-2539.md @@ -211,7 +211,7 @@ Discounts table as a vector of pairs `[k, discount]`: ##### Pairing operation -Cost of the pairing operation is `23000*k + 115000` where `k` is a number of pairs. +Cost of the pairing operation is `55000*k + 65000` where `k` is a number of pairs. ## Rationale Motivation section covers a total motivation to have operations over BLS12-377 curve available. We also extend a rationale for move specific fine points. diff --git a/EIPS/eip-2565.md b/EIPS/eip-2565.md index 969d9bf782ecdf..2ad443c00798aa 100644 --- a/EIPS/eip-2565.md +++ b/EIPS/eip-2565.md @@ -1,10 +1,10 @@ --- eip: 2565 -title: Repricing of the EIP-198 ModExp precompile +title: ModExp Gas Cost 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: Last Call -review-period-end: 2020-07-31 +review-period-end: 2020-10-09 type: Standards Track category: Core created: 2020-03-20 @@ -12,26 +12,40 @@ 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. +Defines the gas cost of the `ModExp` (`0x00..05`) precompile. ## 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. Modifying the gas pricing formula to better reflect the computational complexity of ModExp operations -2. Changing the value of the `GQUADDIVISOR` parameter in the ModExp pricing formula to bring its costs more in-line with other precompiles -3. Improving the underlying libraries beneath the ModExp Precompile -4. Any combination of (1), (2), and (3) - -We recommend **Option (1) and (2)** which provides a large practical improvement to gas estimation while keeping implementation complexity low. Option (3) can be implemented at a later point to improve the gas pricing even further. +To accurately reflect the real world operational cost of the `ModExp` precompile, this EIP specifies an algorithm for calculating the gas cost. This algorithm approximates the multiplication complexity cost and multiplies that by an approximation of the iterations required to execute the exponentiation. ## 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: `floor(mult_complexity(x)/GQUADDIVISOR)` +As of `FORK_BLOCK_NUMBER`, the gas cost of calling the precompile at address `0x0000000000000000000000000000000000000005` will be calculated as follows: +``` +def calculate_multiplication_complexity(base_length, modulus_length): + max_length = max(base_length, modulus_length) + words = math.ceil(max_length / 8) + return words**2 + +def calculate_iteration_count(exponent_length, exponent): + iteration_count = 0 + if exponent_length <= 32 and exponent == 0: iteration_count = 0 + elif exponent_length <= 32: iteration_count = exponent.bit_length() - 1 + elif exponent_length > 32: iteration_count = (8 * (exponent_length - 32)) + ((exponent & (2**256 - 1)).bit_length() - 1) + return max(iteration_count, 1) + +def calculate_gas_cost(base_length, modulus_length, exponent_length, exponent): + multiplication_complexity = calculate_multiplication_complexity(base_length, modulus_length) + iteration_count = calculate_iteration_count(exponent_length, exponent) + return max(200, math.floor(multiplication_complexity * iteration_count / 3)) +``` + +## Rationale +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. The following changes improve the accuracy of the `ModExp` pricing: -### **Recommended** Option (1): Modify ‘computational complexity’ function and add minimum gas cost -The current complexity function, as defined in EIP-198 is as follow: +### 1. Modify ‘computational complexity’ formula to better reflect the computational complexity +The complexity function defined in [EIP-198](./eip-198.md) is as follow: ``` def mult_complexity(x): @@ -41,54 +55,51 @@ def mult_complexity(x): ``` 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 vectors as the following [spreadsheet](https://docs.google.com/spreadsheets/d/1-xBzA-2-l2ZQDQ1eh3XXGZjcRSBQ_Hnp7NubXpbiSUY/edit?usp=sharing). - -In addition to modifying the `mult_complexity` formula as above, we also recommend wrapping the entire function with a minimum gas price of 100 to ensure that a minimum amount of gas is used when the precompile is called e.g. `max(100,floor(mult_complexity(x)/GQUADDIVISOR))` - -### **Recommended** Option (2): Change value of GQUADDIVISOR -`GQUADDIVISOR` is set to `20` per EIP-198. We recommend changing the value of this parameter to `3` to account for the changes in the recommended 'computational complexity' formula above. - -### 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 a further 2-5x improvement in performance, this option is not recommended at this time. - -## Rationale - -### **Recommended** Option (1): Modify ‘computational complexity’ formula -A comparison of the current ‘complexity’ function and the proposed function described above can be found at the following [spreadsheet](https://docs.google.com/spreadsheets/d/1-xBzA-2-l2ZQDQ1eh3XXGZjcRSBQ_Hnp7NubXpbiSUY/edit?usp=sharing). +The complexity formula in [EIP-198](./eip-198.md) was meant to approximate the difficulty of Karatsuba multiplication. However, we found a better approximation for modelling modular exponentiation. In the complexity formula defined in this EIP, `x` is divided by 8 to account for the number of limbs in multiprecision arithmetic. A comparison of the current ‘complexity’ function and the proposed function against the execution time can be seen below: ![Option 1 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. +The complexity function defined here has a better fit vs. the execution time when compared to the [EIP-198](./eip-198.md) complexity function. This better fit is because this 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. -### **Recommended** Option (2): Change value of GQUADDIVISOR: -After changing the 'computational complexity' formula it is necessary to change `QGUADDIVSOR` to bring the gas costs inline with their runtime. We recommend changing the value from '20' to '3'. With this change, the cost of the ModExp precompile will have a higher cost (gas/second) than other precompiles such as ECRecover. +### 2. Change the value of GQUADDIVISOR +After changing the 'computational complexity' formula in [EIP-198](./eip-198.md) to the one defined here it is necessary to change `QGUADDIVSOR` to bring the gas costs inline with their runtime. By setting the `QGUADDIVISOR` to `3` the cost of the ModExp precompile will have a higher cost (gas/second) than other precompiles such as ECRecover. ![Option 2 Graph](../assets/eip-2565/GQuad_Change.png) -### 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. +### 3. Set a minimum gas cost to prevent abuse +This prevents the precompile from underpricing small input values. ## 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. +There are no changes to the underlying interface or arithmetic algorithms, so the existing test vectors can be reused. Below is a table with the updated test vectors: + +| Test Case | EIP-198 Pricing | EIP-2565 Pricing | +| ------------- | ------------- | ------------- | +| modexp_nagydani_1_square | 204 | 200 | +| modexp_nagydani_1_qube | 204 | 200 | +| modexp_nagydani_1_pow0x10001 | 3276 | 341 | +| modexp_nagydani_2_square | 665 | 200 | +| modexp_nagydani_2_qube | 665 | 200 | +| modexp_nagydani_2_pow0x10001 | 10649 | 1365 | +| modexp_nagydani_3_square | 1894 | 341 | +| modexp_nagydani_3_qube | 1894 | 341 | +| modexp_nagydani_3_pow0x10001 | 30310 | 5461 | +| modexp_nagydani_4_square | 5580 | 1365 | +| modexp_nagydani_4_qube | 5580 | 1365 | +| modexp_nagydani_4_pow0x10001 | 89292 | 21845 | +| modexp_nagydani_5_square | 17868 | 5461 | +| modexp_nagydani_5_qube | 17868 | 5461 | +| modexp_nagydani_5_pow0x10001 | 285900 | 87381 | + +## Implementations +[Geth](https://github.com/ethereum/go-ethereum/pull/21607) + +[Python](https://gist.github.com/ineffectualproperty/60e34f15c31850c5b60c8cf3a28cd423) ## 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. ## References -[EIP-198](https://eips.ethereum.org/EIPS/eip-198) +[EIP-198](./eip-198.md) ## Copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-2566.md b/EIPS/eip-2566.md new file mode 100644 index 00000000000000..00a1cb6fb3dda9 --- /dev/null +++ b/EIPS/eip-2566.md @@ -0,0 +1,106 @@ +--- +eip: 2566 +title: Human Readable Parameters for Contract Function Execution +author: Joseph Stockermans (@jstoxrocky) +discussions-to: https://ethereum-magicians.org/t/human-readable-parameters-for-contract-function-execution/4154 +status: Draft +type: Standards Track +category: Interface +created: 2020-03-23 +--- + +## Simple Summary +New Ethereum RPC method `eth_sendTransactionToContractFunction` that parallels `eth_sendTransaction` but allows for human-readable contract function execution data to be displayed to users. + +## Abstract +When a dapp prompts a user to execute a smart contract function via a ProviderWallet, confirmation screens displayed in the ProviderWallet layer cannot display the human readable details of the function to be called and the arguments to be passed. This is because the Ethereum RPC method used for contract function execution (`eth_sendTransaction`) accepts information about what function to call in a non-human readable (and non-recoverable) format. As such, when a ProviderWallet receives this non-human readable information from a dapp, they are unable to display a human readable version since they never received one and cannot recover one from the data. + +This creates a poor and potentially dangerous user experience. For example, a malicious dapp could swap out the `address` argument in a token contract's `transfer(address,uint256)` function and reroute the tokens intended for someone else to themselves. This sleight-of-hand would be quiet and unlikely to be picked up by a casual user glancing over the non-human readable data. By adding a new Ethereum RPC method (`eth_sendTransactionToContractFunction`) that accepts the function ABI, ProviderWallets can recreate and display the human readable details of contract function execution to users. + +## Motivation +### ProviderWallet Definition +ProviderWallets like Metamask and Geth are hybrid software that combine an Ethereum API provider with an Ethereum wallet. This allows them to sign transactions on behalf of their users and also broadcast those signed transactions to the Ethereum network. ProviderWallets are used for both convenience and for the protection they give users through human readable confirmation prompts. + +### Existing Solutions +Much discussion has been made in the past few years on the topic of human readable Ethereum transaction data. Aragon's [Radspec](https://github.com/aragon/radspec) addresses this issue by requiring contract developers to amend their contract functions with human readable comments. ProviderWallets can then use Aragon's Radspec software to parse these comments from the contract code and display them to the end user - substituting in argument values where necessary. Unfortunately, this approach cannot work with contracts that do not have Radspec comments (and may require integration with IPFS). + +[EIP 1138](https://github.com/ethereum/EIPs/issues/1138) also addresses this issue directly but contains serious security issues - allowing untrusted dapps to generate the human readable message displayed to users. In a similar train of thought, [Geth's #2940 PR](https://github.com/ethereum/go-ethereum/pull/2940) and [EIPs 191](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-191.md), [712](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md) all highlight the Ethereum community's desire for ProviderWallets to better inform users about what data they are actually acting upon. + +Finally, the ProviderWallet Metamask already includes some built-in magic for interactions with ERC20 contracts that allows confirmation prompts to display the intended *token* recipient and *token* value. Although this is accomplished in an ad hoc fashion for ERC20-like contracts only, the motivation is the same: users deserve better information about the execution of contract functions they are relying on ProviderWallets to perform. + +### Background +At one point or another, a dapp will ask a user to interact with a contract. The interaction between dapps and contracts is a large part of the Ethereum ecosystem and is most commonly brokered by a ProviderWallet. When a dapp asks a user to interact with a contract, it will do so by sending the `eth_sendTransaction` method name to the Ethereum API exposed by a ProviderWallet along with the relevant transaction data. The `data` field of the transaction data contains the information necessary for the Ethereum virtual machine to identify and execute the contract's function. This field has a specific formatting that is both non-human readable and non-recoverable to its human readable state. + +The accepted format for `eth_sendTransaction`'s `data` field is the hexadecimal encoding of the first four bytes of the keccak256 digest of the function signature. This abbreviated hash is then concatenated with the ABI encoded arguments to the function. Since the keccak256 digest of the function signature cannot be converted back into the function signature, the `data` field is not only non-human readable, its non-recoverable as well. On top of this, additional insight into the concatenated argument values is further obfuscated as information about their data types are held in the function signature preimage. + +## Specification +This EIP proposes increasing the set of Ethereum RPC methods to include a new method - `eth_sendTransactionToContractFunction`. This method parallels `eth_sendTransaction` with the only difference being the inclusion of the contract function's `abi` field. + +Parameters + +1. `Object` - The transaction object + * `from`: `DATA`, 20 Bytes - The address the transaction is sent from. + * `to`: `DATA`, 20 Bytes - (optional when creating new contract) The address the transaction is directed to. + * `gas`: `QUANTITY` - (optional, default: 90000) Integer of the gas provided for the transaction execution. It will return unused gas. + * `gasPrice`: `QUANTITY` - (optional, default: To-Be-Determined) Integer of the gasPrice used for each paid gas + * `value`: `QUANTITY` - (optional) Integer of the value sent with this transaction + * `data`: `DATA` - The hash of the invoked method signature and encoded parameters + * `abi`: `DATA` - The function ABI + * `nonce`: `QUANTITY` - (optional) Integer of a nonce. This allows to overwrite your own pending transactions that use the same nonce. + +Example Parameters +``` + params: [{ + "from": "0x69e6F1b01f34A702Ce63bA6EF83c64fAEC37a227", + "to": "0xe44127f6fA8A00ee0228730a630fc1F3162C4d52", + "gas": "0x76c0", // 30400 + "gasPrice": "0x9184e72a000", // 10000000000000 + "value": "0x9184e72a", // 2441406250 + "abi": "{ + "inputs": [{ + "name": "_address", + "type": "address" + }, { + "name": "_value", + "type": "uint256" + }], + "name": "transferTokens", + "outputs": [{ + "name": "success", + "type": "bool" + }], + "stateMutability": "nonpayable", + "type": "function" + }", + "data": "0xbec3fa170000000000000000000000006Aa89e52c9a826496A8f311c1a9db62fd477E256000000000000000000000000000000000000000000000000000000174876E800" + }] +``` + +Returns +DATA, 32 Bytes - the transaction hash, or the zero hash if the transaction is not yet available. + +Example +// Request +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_sendTransactionToContractFunction","params":[{see above}],"id":1}' + +// Result +{ + "id":1, + "jsonrpc": "2.0", + "result": "0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331" +} + +## Rationale +This EIP's proposed `eth_sendTransactionToContractFunction` method is intended to parallel `eth_sendTransaction` as much as possible since both methods result in the same behaviour when executing a contract function. The newly introduced `abi` field is an element of the contract's ABI that corresponds to the intended function. The `data` field is the same `data` field from `eth_sendTransaction`. The `abi` field can be combined with values parsed from the `data` field to recreate human readable contract function execution information. + +## Implementation +The `data` field in `eth_sendTransactionToContractFunction` is the same as that required for `eth_sendTransaction` allowing the transaction to be completed via the existing mechanisms used for `eth_sendTransaction`. The input argument values can be parsed from the `data` field and since we know their types from the `abi` field, the provider wallet can use this info to encode and display the values in an appropriate human readable format. Furthermore, the hashed and truncated function signature in the `data` field can be reconstructed using the information provided in the `abi` field providing an additional check to ensure that the supplied ABI matches the `data` field. + +## Backwards Compatibility +With backwards compatibility in mind, this EIP proposes augmenting the set of Ethereum RPC methods with an additional method instead of mutating the existing method. Precedent for adding a new RPC method comes from [EIP 712](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md) in which adding the method `eth_signTypedData` is proposed for confirmation prompt security. As an alternate approach, the `eth_sendTransaction` method could be changed to accept an additional `abi` argument, but this would break all existing code attempting to execute a contract function. + +## Security Considerations +Displaying the contract address, function name, and argument values can provide additional security to users, but it is not a guarantee that a function will execute as the user expects. A poorly implemented contract can still name its function `transfer` and accept `address` and `uint256` arguments - but there is nothing short of contract examination that will let a user know that this contract is indeed a valid ERC20 contract. This EIP does not intend to solve the larger problem around trust in a contract's code, but instead intends to give users better tools to understand exactly what is contained within the data they are broadcasting to the Ethereum network. + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-2583.md b/EIPS/eip-2583.md index f521d0eae6fc50..6514d9c9b92a3e 100644 --- a/EIPS/eip-2583.md +++ b/EIPS/eip-2583.md @@ -28,7 +28,7 @@ From an implementation perspective, a node can (and does) use various caching me This is attackable. By forcing a node to lookup non-existent keys, an attacker can maximize the number of disk lookups. Sidenote: even if the 'non-existence' is cached, it's trivial to use a new non-existent key the next time, and never hit the same non-existent key again. Thus, caching 'non-existence' might be dangerous, since it will evict 'good' entries. -So far, the attempts to handle this problem has been in raising the gas cost, e.g. [EIP-150](https://eips.ethereum.org/EIPS/eip-150), [EIP-1884](https://eips.ethereum.org/EIPS/eip-1884). +So far, the attempts to handle this problem has been in raising the gas cost, e.g. [EIP-150](./eip-150.md), [EIP-1884](./eip-1884.md). However, when determining gas-costs, a secondary problem that arises due to the large discrepancy between 'happy-path' and 'notorious path' -- how do we determine the pricing? diff --git a/EIPS/eip-2612.md b/EIPS/eip-2612.md index 9d559b9d1c5362..d23fa0931778af 100644 --- a/EIPS/eip-2612.md +++ b/EIPS/eip-2612.md @@ -11,7 +11,7 @@ requires: 20, 712 --- ## Simple Summary -A function `permit` extending [ERC-20](https://eips.ethereum.org/EIPS/eip-20) which allows for approvals to be made via `secp256k1` signatures. This kind of "account abstraction for ERC-20" brings about two main benefits: +A function `permit` extending [ERC-20](./eip-20.md) which allows for approvals to be made via `secp256k1` signatures. This kind of "account abstraction for ERC-20" brings about two main benefits: - transactions involving ERC-20 operations can be paid using the token itself rather than ETH, - approve and pull operations can happen in a single transaction instead of two consecutive transactions, @@ -26,13 +26,13 @@ However, a limiting factor in this design stems from the fact that the ERC-20 `a This ERC extends the ERC-20 standard with a new function `permit`, which allows users to modify the `allowance` mapping using a signed message, instead of through `msg.sender`. -For an improved user experience, the signed data is structured following [ERC-712](https://eips.ethereum.org/EIPS/eip-712), which already has wide spread adoption in major RPC providers. +For an improved user experience, the signed data is structured following [ERC-712](./eip-712.md), which already has wide spread adoption in major RPC providers. ## Motivation -While ERC-20 tokens have become ubiquotous in the Ethereum ecosystem, their status remains that of second class tokens from the perspective of the protocol. The ability for users to interact with Ethereum without holding any ETH has been a [long outstanding goal](https://github.com/ethereum/EIPs/blob/ed621645c8f3bc5756492f327cda015f35d9f8da/EIPS/eip-101.md) and the [subject](https://eips.ethereum.org/EIPS/eip-1077) [of](https://eips.ethereum.org/EIPS/eip-777) [many](https://github.com/ethereum/EIPs/issues/1776#) [EIPs](https://eips.ethereum.org/EIPS/eip-1271). +While ERC-20 tokens have become ubiquotous in the Ethereum ecosystem, their status remains that of second class tokens from the perspective of the protocol. The ability for users to interact with Ethereum without holding any ETH has been a [long outstanding goal](https://github.com/ethereum/EIPs/blob/ed621645c8f3bc5756492f327cda015f35d9f8da/EIPS/eip-101.md) and the [subject](./eip-1077.md) [of](./eip-777.md) [many](https://github.com/ethereum/EIPs/issues/1776#) [EIPs](https://eips.ethereum.org/EIPS/eip-1271). -So far, many of these proposals have seen very little adoption, and the ones that have been adopted (such as [ERC-777](https://eips.ethereum.org/EIPS/eip-777)), introduce a lot of additional functionality, causing [unexpected behavior in mainstream contracts](https://medium.com/consensys-diligence/uniswap-audit-b90335ac007). +So far, many of these proposals have seen very little adoption, and the ones that have been adopted (such as [ERC-777](./eip-777.md)), introduce a lot of additional functionality, causing [unexpected behavior in mainstream contracts](https://medium.com/consensys-diligence/uniswap-audit-b90335ac007). This ERC proposes an alternative solution which is designed to be as minimal as possible and to only address _one problem_: the lack of abstraction in the ERC-20 `approve` method. @@ -43,15 +43,13 @@ While it may be tempting to introduce `*_by_signature` counterparts for every ER ## Specification -A new method -```solidity -function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) -``` -and a new storage item -```solidity -mapping(address=>uint256) nonces; +Three new functions are added to the ERC20 ABI: +```sol +function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external +function nonces(address owner) external view returns (uint) +function DOMAIN_SEPARATOR() external view returns (bytes32) ``` -with accompanying getter function are introduced, the semantics of which are as follows: +The semantics of which are as follows: For all addresses `owner`, `spender`, uint256s `value`, `deadline` and `nonce`, uint8 `v`, bytes32 `r` and `s`, a call to `permit(owner, spender, value, deadline, v, r, s)` will set @@ -66,25 +64,32 @@ if and only if the following conditions are met: - `nonces[owner]` (before the state update) is equal to `nonce`. - `r`, `s` and `v` is a valid `secp256k1` signature from `owner` of the message: -in solidity pseudocode: -```solidity -keccak256(hex"1901" - ++ keccak256( - keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)") - ++ keccak256(bytes(erc20name)) - ++ keccak256(bytes(version)) - ++ bytes(chainid) - ++ bytes(tokenAddress)) - ++ keccak256( - keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)") - ++ bytes(owner) - ++ bytes(spender) - ++ bytes(value) - ++ bytes(nonce) - ++ bytes(deadline)) +```sol +keccak256(abi.encodePacked( + hex"1901", + DOMAIN_SEPARATOR, + keccak256(abi.encode( + keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"), + owner, + spender, + value, + nonce, + deadline)) )) ``` -where `++` denotes bytestring concatenation, `tokenAddress` is the address of the token contract, `chainid` is the chain id of the network it is deployed to and `erc20name` is the name of the token as defined by `ERC-20`. `version` is a `string` defined at contract deployment which remains constant throughout the lifetime of the contract, but is otherwise unconstrained. +where `DOMAIN_SEPARATOR` is defined according to EIP-712. The `DOMAIN_SEPARATOR` should be unique to the contract and chain to prevent replay attacks from other domains, +and satisfy the requirements of EIP-712, but is otherwise unconstrained. +A common choice for `DOMAIN_SEPARATOR` is: +```solidity +DOMAIN_SEPARATOR = keccak256( + abi.encode( + keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'), + keccak256(bytes(name)), + keccak256(bytes(version)), + chainid, + address(this) +)); +``` In other words, the message is the ERC-712 typed structure: @@ -191,6 +196,8 @@ Signed `Permit` messages are censorable. The relaying party can always choose to The standard [ERC-20 race condition for approvals](https://swcregistry.io/docs/SWC-114) applies to `permit` as well. +If the `DOMAIN_SEPARATOR` contains the `chainId` and is defined at contract deployment instead of reconstructed for every signature, there is a risk of possible replay attacks between chains in the event of a fututre chain split. + ## Copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-2645.md b/EIPS/eip-2645.md new file mode 100644 index 00000000000000..bdbe0349a6e929 --- /dev/null +++ b/EIPS/eip-2645.md @@ -0,0 +1,71 @@ +--- +eip: 2645 +title: Hierarchical Deterministic Wallet for Layer-2 +author: Tom Brand , Louis Guthmann +discussions-to: https://ethereum-magicians.org/t/hierarchical-deterministic-wallet-for-computation-integrity-proof-cip-layer-2/4286 +status: Draft +type: Standards Track +category: ERC +created: 2020-05-13 +--- + +## Simple Summary +In the context of Computation Integrity Proof (CIP) Layer-2 solutions such as ZK-Rollups, users are required to sign messages on new elliptic curves optimized for those environnements. We leverage existing work on Key Derivation ([BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki), [BIP39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki) and [BIP44](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki)) to define an efficient way to securely produce CIP L2s private keys, as well as creating domain separation between Layer-2 applications. + +## Abstract +We provide a Derivation Path allowing a user to derive hierarchical keys for Layer-2 solutions depending on the zk-technology, the application, the user’s Layer-1 address, as well as an efficient grinding method to enforce the private key distribution within the curve domain. The propose Derivation Path is defined as follow +``` +m / purpose' / layer' / application' / eth_address_1' / eth_address_2' / index +``` + +## Motivation +In the context of Computation Integrity Proof (CIP) Layer-2 solutions such as ZK-Rollups, users are required to sign messages on new elliptic curves optimized for those environnements. Extensive work has been done to make it secure on Bitcoin via [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki), [BIP39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki) and [BIP44](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki). Those protosals have become the standard for wallets in the entire industry, independently on the associated blockchain. As Layer-2 solutions are taking off, it is a necessary requirement to maintain the same standard and security in this new space. + +## Specification +Starkware keys are derived with the following [BIP43](https://github.com/bitcoin/bips/blob/master/bip-0043.mediawiki)-compatible derivation path, with direct inspiration from [BIP44](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki): +``` +m / purpose' / layer' / application' / eth_address_1' / eth_address_2' / index +``` +where: +* `m` - the seed. +* `purpose` - `2645` (the number of this EIP). +* `layer` - the 31 lowest bits of sha256 on the layer name. Serve as a domain separator between different technologies. In the context of `starkex`, the value would be `579218131`. +* `application` - the 31 lowest bits of sha256 of the application name. Serve as a domain separator between different applications. In the context of DeversiFi in June 2020, it is the 31 lowest bits of sha256(starkexdvf) and the value would be `1393043894`. +* `eth_address_1 / eth_address_2` - the first and second 31 lowest bits of the corresponding eth_address. +* `index` - to allow multiple keys per eth_address. + +As example, the expected path for address 0x0000....0000 assuming seed `m` and index 0 in the context of DeversiFi in June 2020: `m/2645'/579218131'/1393043894'/0'/0'/0` + +The key derivation should follow the following algorithm +``` +N = 2**256 +n = Layer2 curve order +path = stark derivation path +BIP32() = Official BIP-0032 derivation function on secp256k1 +hash = SHA256 +i = 0 +root_key = BIP32(path) +while True: + key = hash(root_key|i) + if (key < (N - (N % n))): + return key % n + i++ +``` +This algorithm has been defined to maintain efficiency on existing restricted devices. + +Nota Bene: At each round, the probability for a key to be greater than (N - (N % n)) is < 2^(-5). + +## Rationale +This EIP specifies two aspects of keys derivation in the context of Hierarchical Wallets: +- Derivation Path +- Grinding Algorithm to enforce a uniform distribution over the elliptic curve. +The derivation path is defined to allow efficient keys separation based on technology and application while maintaining a 1-1 relation with the Layer-1 wallet. In such a way, losing EIP-2645 wallets falls back to losing the Layer-1 wallet. + +## Backwards Compatibility +This standard complies with BIP43. + +## Security Considerations +This EIP has been defined to maintain separation of keys while providing foolproof logic on key derivation. + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-2666.md b/EIPS/eip-2666.md new file mode 100644 index 00000000000000..1c2de46647404e --- /dev/null +++ b/EIPS/eip-2666.md @@ -0,0 +1,133 @@ +--- +eip: 2666 +title: Repricing of precompiles and Keccak256 function +author: Alex Vlasov (@shamatar) +discussions-to: https://ethereum-magicians.org/t/eip2666-global-precompiles-repricing-and-many-more-discussion-thread/4332 +status: Draft +type: Standards Track +category: Core +created: 2020-05-22 +requires: 1352, 2046, 2565 +--- + +## Simple Summary + +This EIP tries to set prices of certain precompiles and built-in EVM function to be in line with their performance, consumed resources and newer changes in EVM itself. + +New price formulas are proposed for: +- SHA256 precompile (`0x02`) +- RIPEMD precompile (`0x03`) +- KECCAK256 opcode (`0x20`) + +## Abstract + +Costs of many precompiles and built-in functions are invalid at the current state of the clients. This EIP contains a list of changes to the pricing formulas to better reflect underlying computations' structure. + +## Motivation + +Historical pricing for these functions in EVM does not reflect inner structure of the underlying computations (inner structure of the hash functions). + +- EIP-2046 changes a `STATICCALL (0xfa)` cost to precompile and it may be necessary to adjust costs of some precompiles that *may* have taken old large cost (`700` gas) into account and tried to compensate for it +- Some precompiles are overpriced and their pricing formulas do not reflect the structure of underlying functions +- Keccak256 built-in function (opcode) in EVM has pricing that does not reflect underlying hash function structure + +## Specification + +If `block_number >= X` set the gas cost of the following precompiles and Keccak256 opcode: +- SHA256 (precompile `0x02`): `10 + ((len(input) + 8)/64 + 1) * 9` +- RIPEMD (precompile `0x03`): `6 + ((len(input) + 8)/64 + 1) * 12` +- KECCAK256 (`0x20`): `13 + (len(input)/136 + 1)*15` + +This EIP *ideally* requires that `MODEXP` repricing is [implemented](./eip-2565.md) to also accurately reflect that there is no implicit compensation for an old `STATICCALL (0xfa)` cost (pre-2046). + +## Rationale +Cost of functions being executed must accurately reflect real CPU time spent on computations, so benchmarking was performed for current precompiles and Keccak256 function to measure running time versus input parameters. + +### Detailed summary of repricing approach + +This EIP relies on two facts: +- apriori knowledge of the inner strucute of the hash functions +- benchmarks provided by the client teams for some reasonable range of input lengths for random inputs (random byte strings of a given length) + +### Benchmarks on the most popular clients + +Necessary benchmarks for EIP-2666 were provided by the clients and raw form is assembled in [here](https://docs.google.com/spreadsheets/d/1aCQnk7prrp3Mbcf011BE5zZnkbc3Iw7QAixn6mLbKS0/edit?usp=sharing) + +- SHA256 precompile + +Currently it's `60` gas + `12` gas per `32` byte word (number of words is `ceil(len(input)/word_len)` here and in similar places. If there is no `floor` or `ceil` specifier all divisions below are integer divisions (floor divisions)). Proposed formula is `A * ((len(input) + 8) / 64 + 1) + B`, with coefficients below + +| | | A | B | +|---|---|---|---| +| Geth | | 5 | 3 | +| OE | | 9 | 4 | +| Besu | | 5 | 10 | +| Nethermind | | 10 | 5 | + +EIP-2666 proposes `A = 9`, `B = 10`. There are no large one-off costs in this precompile, so it's EIP-2046 - safe. + +- RIPEMD precompile + +Currently it's `600` gas + `120` gas per `32` byte word. Proposed formula is `A * ((len(input) + 8) / 64 + 1) + B`, with coefficients below + +| | | A | B | +|---|---|---|---| +| Geth | | 12 | 6 | +| OE | | 8 | 2 | +| Besu | | 29 | 16 | +| Nethermind | | 10 | 6 | + +EIP-2666 proposes `A = 12`, `B = 6`. There are no large one-off costs in this precompile, so it's EIP-2046 - safe. Besu expects to have performance improvements by the end of the year. + +- Keccak256 performance + +Currently it's `30` gas + `6` gas per `32` byte word. Proposed formula is `A * (len(input) / 136 + 1) + B`, with coefficients below + +| | | A | B | +|---|---|---|---| +| Geth | | 13 | 13 | +| OE | | 15 | 2 | +| Besu | | 19 | 28 | +| Nethermind | | 16 | 3 | + +EIP-2666 proposes `A = 15`, `B = 13`. There are no large one-off costs in this precompile, so it's EIP-2046 - safe. Besu expects to have performance improvements by the end of the year. + +### Tooling and data + +Reference material (from benchmarks of different clients) with raw data can be found [here](https://docs.google.com/spreadsheets/d/1aCQnk7prrp3Mbcf011BE5zZnkbc3Iw7QAixn6mLbKS0/edit?usp=sharing). + +There is a repository available with inputs for benchmarking and precompiles testing [here](https://github.com/shamatar/bench_precompiles) that can be used by client teams to perform all the necessary measurements. + +Raw Besu [benchmarks](https://gist.github.com/shemnon/0ddba91be501fa23291bdec9107fe99a). + +### Note on formulas structure + +There are terms in formulas that look like `A * 1` and those are explicitly not combined to the `B` coefficient to reflect that hash of an empty byte array requires to perform a round of hashing anyway. + +## Backwards Compatibility +Precompile repricings has happened in a past and can be considered standard procedure. Gas costs of many contracts is expected to reduce that may break re-entrancy protection measures based on fixed gas costs. In any case, such protection should have never been considered good and final. + +## Test Cases + +Let's consider a simple example of Keccak256 hash of `0`, `64` and `160` bytes that can is a simple sanity check for implementation. + +- Hash `0` bytes: + - Old price: `30 + 6 * ceil(0 / 32) = 30` gas + - New price: `15 * (0/136 + 1) + 13 = 28` gas +- Hash `64` bytes + - Old price: `30 + 6 * ceil(64 / 32) = 42` gas + - New price: `15 * (64/136 + 1) + 13 = 28` gas +- Hash `160` bytes + - Old price: `30 + 6 * ceil(160 / 32) = 60` gas + - New price: `15 * (160/136 + 1) + 13 = 43` gas + +## Implementation + +There is no reference implementation at the time of writing as it requires just a simple change of constants in major clients. + +## Security Considerations + +As described in backward compatibility section in some cases reduction of cost may allow e.g. re-entrancy that was not expected before, but we think that re-entrancy protection based on fixed gas costs is anyway flawed design decision. + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-2677.md b/EIPS/eip-2677.md index d7d32e7fb8f5f1..749464a9ec7938 100644 --- a/EIPS/eip-2677.md +++ b/EIPS/eip-2677.md @@ -17,7 +17,7 @@ Enforce a maximum size limit (`max_initcode_size`) of `49152` (`0xc000`) for `in Enforce a maximum size limit (`max_initcode_size`) for `initcode`. If the size of `initcode` exceeds `max_initcode_size`, then contract creation fails with an out of gas error. -Since [EIP-170](https://eips.ethereum.org/EIPS/eip-170) was implemented, there has been a size limit of `24576` (`0x6000`) on contract code. We propose to also limit the size of executable code to `2x` the above limit, i.e. `49152` (`0xc000`). +Since [EIP-170](./eip-170.md) was implemented, there has been a size limit of `24576` (`0x6000`) on contract code. We propose to also limit the size of executable code to `2x` the above limit, i.e. `49152` (`0xc000`). This also leads to two nice properties: diff --git a/EIPS/eip-2678.md b/EIPS/eip-2678.md index f9a43648e74141..6edc8621590e3e 100644 --- a/EIPS/eip-2678.md +++ b/EIPS/eip-2678.md @@ -1,13 +1,12 @@ --- eip: 2678 title: Revised Ethereum Smart Contract Packaging Standard (EthPM v3) -author: g. nicholas d’andrea (@gnidan), Piper Merriam (@pipermerriam), Nick Gheorghita (@njgheorghita), Christian Reitwiessner(@chriseth), Ben Hauser (@iamdefinitelyahuman), Bryant Eisenbach (@fubuloubu) +author: g. nicholas d’andrea (@gnidan), Piper Merriam (@pipermerriam), Nick Gheorghita (@njgheorghita), Christian Reitwiessner (@chriseth), Ben Hauser (@iamdefinitelyahuman), Bryant Eisenbach (@fubuloubu) discussions-to: https://ethereum-magicians.org/t/ethpm-v3-specification-working-group/4086 -status: Draft +status: Review type: Standards Track category: ERC created: 2020-05-26 -replaces: 1123 --- @@ -22,7 +21,9 @@ This EIP defines a data format for *package manifest* documents, representing a package of one or more smart contracts, optionally including source code and any/all deployed instances across multiple networks. Package manifests are minified JSON objects, to be distributed -via content addressable storage networks, such as IPFS. +via content addressable storage networks, such as IPFS. Packages +are then published to on-chain EthPM registries, defined in +[EIP-1319](./eip-1319.md), from where they can be freely accessed. This document presents a natural language description of a formal specification for version **3** of this format. @@ -37,13 +38,6 @@ provide support for package management tools development by offering a general-purpose solution that has been designed with observed common practices in mind. -As version 3 of this specification, this standard seeks to address a -number of areas of improvement found for the previous version (defined -in -[EIP-1123](https://eips.ethereum.org/EIPS/eip-1123)). -This version: - - - Updates the schema for a *package manifest* to be compatible with the [metadata](https://solidity.readthedocs.io/en/latest/metadata.html) output for compilers. - Updates the `"sources"` object definition to support a wider range of source file types and serve as [JSON input](https://solidity.readthedocs.io/en/latest/using-the-compiler.html#compiler-input-and-output-json-description) for a compiler. @@ -54,22 +48,6 @@ This version: - Updates key formatting from `snake_case` to `camelCase` to be more consistent with [JSON convention](https://google.github.io/styleguide/jsoncstyleguide.xml?showone=Property_Name_Format#Property_Name_Format). -
- -## Specification - -This document defines the specification for an EthPM package manifest. A -package manifest provides metadata about a *package*, and -in most cases should provide sufficient information about the packaged -contracts and its dependencies to do bytecode verification of its -contracts. - -A [hosted version](http://ethpm.github.io/ethpm-spec) -of this specification is available via GitHub Pages. This EIP and the -hosted HTML document were both autogenerated from the same documentation -source. - - ### Guiding Principles This specification makes the following assumptions about the document @@ -89,6 +67,22 @@ lifecycle. 4. Package manifests can be used to verify public deployments of source contracts. +### Use Cases + +The following use cases were considered during the creation of this +specification. + +* **owned**: A package which contains contracts which are not meant to be used by themselves but rather as base contracts to provide functionality to other contracts through inheritance. +* **transferable**: A package which has a single dependency. +* **standard-token**: A package which contains a reusable contract. +* **safe-math-lib**: A package which contains deployed instance of one of the package contracts. +* **piper-coin**: A package which contains a deployed instance of a reusable contract from a dependency. +* **escrow**: A package which contains a deployed instance of a local contract which is linked against a deployed instance of a local library. +* **wallet**: A package with a deployed instance of a local contract which is linked against a deployed instance of a library from a dependency. +* **wallet-with-send**: A package with a deployed instance which links against a deep dependency. +* **simple-auction**: Compiler `"metadata"` field output. + +## Package Specification ### Conventions @@ -103,28 +97,13 @@ document are to be interpreted as described in RFC 2119. #### Prefixed vs Unprefixed -A [prefixed](#term-prefixed) hexadecimal value begins with `0x`. -[Unprefixed](#term-unprefixed) values have no prefix. Unless otherwise +A [prefixed](#prefixed) hexadecimal value begins with `0x`. +[Unprefixed](#unprefixed) values have no prefix. Unless otherwise specified, all hexadecimal values **should** be represented with the `0x` prefix. - ---- - - - - - - - - - - -

Prefixed

0xdeadbeef

Unprefixed

deadbeef

- +* **Prefixed**: `0xdeadbeef` +* **Unprefixed**: `deadbeef` ### Document Format @@ -154,62 +133,22 @@ The following fields are defined for the package. Custom fields **may** be included. Custom fields **should** be prefixed with `x-` to prevent name collisions with future versions of the specification. - ---- - - - - - - - - - - -

See Also

Formalized (JSON-Schema) version of this specification: package.spec.json

Jump To

Definitions

- +* **See Also**: Formalized ([JSON-Schema](https://json-schema.org)) version of this specification: [package.spec.json](../assets/eip-2678/package.spec.json) +* **Jump To**: [Definitions](#object-definitions) -
- -### EthPM Manifest Version: `manifest` +### EthPM Manifest Version The `manifest` field defines the specification version that this document conforms to. - Packages **must** include this field. - ---- - - - - - - - - - - - - - - - - - - -

Required

Yes

Key

manifest

Type

String

Allowed Values

ethpm/3

- - -
- -### Package Name: `name` +* **Required**: Yes +* **Key**: `manifest` +* **Type**: String +* **Allowed Values**: `ethpm/3` + +### Package Name The `name` field defines a human readable name for this package. @@ -217,40 +156,17 @@ The `name` field defines a human readable name for this package. registry. - Package names **must** begin with a lowercase letter and be - comprised of only lowercase letters, numeric characters, and the + comprised of only the lowercase letters `a-z`, numeric characters `0-9`, and the dash character `-`. - Package names **must** not exceed 255 characters in length. - ---- - - - - - - - - - - - - - - - - - - -

Required

If version is included.

Key

name

Type

String

Format

must match the regular expression ^[a-z][-a-z0-9]{0,255}$

- - -
- -### Package Version: `version` +* **Required**: If `version` is included. +* **Key**: `name` +* **Type**: String +* **Format**: **must** match the regular expression `^[a-z][-a-z0-9]{0,255}$` + +### Package Version The `version` field declares the version number of this release. @@ -261,30 +177,11 @@ The `version` field declares the version number of this release. [semver](http://semver.org/) version numbering specification. - ---- - - - - - - - - - - - - - - -

If name is included.

Yes

Key

version

Type

String

- -
- -### Package Metadata: `meta` +* **Required**: If `name` is included. +* **Key**: `version` +* **Type**: String + +### Package Metadata The `meta` field defines a location for metadata about the package which is not integral in nature for package installation, but may be important @@ -292,64 +189,24 @@ or convenient to have on-hand for other reasons. - This field **should** be included in all Packages. - ---- - - - - - - - - - - - - - - -

Required

No

Key

meta

Type

Package Meta Object

- - -
- -### Sources: `sources` +* **Required**: No +* **Key**: `meta` +* **Type**: [Package Meta Object](#the-package-meta-object) + +### Sources The `sources` field defines a source tree that **should** comprise the full source tree necessary to recompile the contracts contained in this release. - ---- - - - - - - - - - - - - - - -

Required

No

Key

sources

Type

Object (String: Sources Object)

- - -
- -### Contract Types: `contractTypes` +* **Required**: No +* **Key**: `sources` +* **Type**: Object (String: [Sources Object](#the-source-object)) + +### Contract Types The `contractTypes` field hosts the [Contract -Types](#term-contract-type) which have been included in this release. +Types](#contract-type) which have been included in this release. - Packages **should** only include contract types that can be found in the source files for this package. @@ -359,139 +216,47 @@ Types](#term-contract-type) which have been included in this release. - Packages **should not** include abstract contracts in the contract types section of a release. - ---- - - - - - - - - - - - - - - - - - - -

Required

No

Key

contractTypes

Type

Object (String: Contract Type Object)

Format

Keys must be valid Contract Aliases.

-

Values must conform to the Contract Type Object definition.

- -
- -### Compilers: `compilers` +* **Required**: No +* **Key**: `contractTypes` +* **Type**: Object (String: [Contract Type Object](#the-contract-type-object)) +* **Format**: Keys **must** be valid [Contract Aliases](#contract-alias).
Values **must** conform to the [Contract Type Object](#the-contract-type-object) definition. + +### Compilers The `compilers` field holds the information about the compilers and their settings that have been used to generate the various `contractTypes` included in this release. - ---- - - - - - - - - - - - - - - -

Required

No

Key

compilers

Type

Array (Compiler Information Object)

- - -
- -### Deployments: `deployments` +* **Required**: No +* **Key**: `compilers` +* **Type**: Array ([Compiler Information Object](#the-compiler-information-object)) + +### Deployments The `deployments` field holds the information for the chains on which -this release has [Contract Instances](#term-contract-instance) as well -as the [Contract Types](#term-contract-type) and other deployment +this release has [Contract Instances](#contract-instance) as well +as the [Contract Types](#contract-type) and other deployment details for those deployed contract instances. The set of chains defined -by the [BIP122 URI](#bip122) keys for this object **must** be +by the [BIP122 URI](#bip122-uri) keys for this object **must** be unique. There cannot be two different URI keys in a deployments field representing the same blockchain. - ---- - - - - - - - - - - - - - - - - - - -

Required

No

Key

deployments

Type

Object (String: Object(String: Contract Instance Object))

Format

Keys must be a valid BIP122 URI chain definition.

-

Values must be objects which conform to the following format:

-

- Keys must be valid Contract Instance Names.

-

- Values must be a valid Contract Instance Object.

- - -
- -### Build Dependencies: `buildDependencies` +* **Required**: No +* **Key**: `deployments` +* **Type**: Object (String: Object(String: [Contract Instance Object](#the-contract-instance-object))) +* **Format**: Keys **must** be a valid BIP122 URI chain definition.
Values **must** be objects which conform to the following format:
- Keys **must** be valid [Contract Instance Names](#contract-instance-name)
- Values **must** be a valid [Contract Instance Object](#the-contract-instance-object) + +### Build Dependencies The `buildDependencies` field defines a key/value mapping of EthPM packages that this project depends on. - ---- - - - - - - - - - - - - - - - - - - -

Required

No

Key

buildDependencies

Type

Object (String: String)

Format

Keys must be valid package names.

-

Values must be a Content Addressable URI which resolves to a valid package that conforms the same EthPM manifest version as its parent.

- -
- -### Definitions +* **Required**: No +* **Key**: `buildDependencies` +* **Type**: Object (String: String) +* **Format**: Keys **must** be valid [package names](#package-name).
Values **must** be a [Content Addressable URI](#content-addressable-uri) which resolves to a valid package that conforms the same EthPM manifest version as its parent. + +### Object Definitions Definitions for different objects used within the Package. All objects allow custom fields to be included. Custom fields **should** be prefixed @@ -499,13 +264,11 @@ with `x-` to prevent name collisions with future versions of the specification. - - ### The *Link Reference* Object -A [Link Reference](#term-link-reference) object has the following +A [Link Reference](#link-reference) object has the following key/value pairs. All link references are assumed to be associated with -some corresponding [Bytecode](#term-bytecode). +some corresponding [Bytecode](#bytecode). #### Offsets: `offsets` @@ -515,22 +278,8 @@ Locations are 0-indexed from the beginning of the bytes representation of the corresponding bytecode. This field is invalid if it references a position that is beyond the end of the bytecode. - ---- - - - - - - - - - - -

Required

Yes

Type

Array

+* **Required**: Yes +* **Type**: Array #### Length: `length` @@ -538,55 +287,22 @@ The `length` field is an integer which defines the length in bytes of the link reference. This field is invalid if the end of the defined link reference exceeds the end of the bytecode. - ---- - - - - - - - - - - -

Required

Yes

Type

Integer

+* **Required**: Yes +* **Type**: Integer #### Name: `name` The `name` field is a string which **must** be a valid -[Identifier](#term-identifier). Any link references which **should** be +[Identifier](#identifier). Any link references which **should** be linked with the same link value **should** be given the same name. - ---- - - - - - - - - - - - - - - -

Required

No

Type

String

Format

must conform to the Identifier format.

- - +* **Required**: No +* **Type**: String +* **Format**: **must** conform to the [Identifier](#identifier) format. ### The *Link Value* Object -Describes a single [Link Value](#term-link-value). +Describes a single [Link Value](#link-value). A **Link Value object** is defined to have the following key/value pairs. @@ -599,26 +315,9 @@ bytecode where the `value` for this link value was written. These locations are 0-indexed from the beginning of the bytes representation of the corresponding bytecode. - ---- - - - - - - - - - - - - - - -

Required

Yes

Type

Integer

Format

See Below.

+* **Required**: Yes +* **Type**: Integer +* **Format**: See below. Format @@ -633,67 +332,32 @@ following. #### Type: `type` The `type` field defines the `value` type for determining what is -encoded when [linking](#term-linking) the corresponding bytecode. - - ---- - - - - - - - - - - - - - - -

Required

Yes

Type

String

Allowed Values

"literal" for bytecode literals

-

"reference" for named references to a particular Contract Instance

+encoded when [linking](#linking) the corresponding bytecode. + +* **Required**: Yes +* **Type**: String +* **Allowed Values**: `"literal"` for bytecode literals.
`"reference"` for named references to a particular [Contract Instance](#contract-instance) #### Value: `value` -The `value` field defines the value which should be written when -[linking](#term-linking) the corresponding bytecode. - - ---- - - - - - - - - - - - - - - -

Required

Yes

Type

String

Format

Determined based on type, see below.

+The `value` field defines the value which should be written when [linking](#linking) the corresponding bytecode. + +* **Required**: Yes +* **Type**: String +* **Format**: Determined based on `type`, see below. Format -For static value *literals* (e.g. address), value **must** be a *byte -string* +For static value *literals* (e.g. address), value **must** be a 0x-prefixed +hexadecimal string representing bytes. + To reference the address of a [Contract -Instance](#term-contract-instance) from the current package the value +Instance](#contract-instance) from the current package the value should be the name of that contract instance. - This value **must** be a valid [Contract Instance - Name](#term-contract-instance-name). + Name](#contract-instance-name). - The chain definition under which the contract instance that this link value belongs to must contain this value within its keys. @@ -701,7 +365,7 @@ should be the name of that contract instance. - This value **may not** reference the same contract instance that this link value belongs to. -To reference a contract instance from a [Package](#term-package) from +To reference a contract instance from a [Package](#package) from somewhere within the dependency tree the value is constructed as follows. @@ -718,10 +382,10 @@ follows. - The value is represented by the string `::<...>::` where all of ``, ``, `` are valid package names and `` is - a valid [Contract Name](#term-contract-name). + a valid [Contract Name](#contract-name). - The `` value **must** be a valid [Contract - Instance Name](#term-contract-instance-name). + Instance Name](#contract-instance-name). - Within the package of the dependency defined by ``, all of the following must be satisfiable: @@ -733,8 +397,6 @@ follows. - The `` value **must** be present in the keys of the matching chain. -
- ### The *Bytecode* Object A bytecode object has the following key/value pairs. @@ -744,88 +406,36 @@ A bytecode object has the following key/value pairs. The `bytecode` field is a string containing the `0x` prefixed hexadecimal representation of the bytecode. - ---- - - - - - - - - - - - - - - -

Required

Yes

Type

String

Format

0x prefixed hexadecimal.

- - -#### Link References: `link_references` +* **Required**: Yes +* **Type**: String +* **Format**: `0x` prefixed hexadecimal. + +#### Link References: `linkReferences` The `linkReferences` field defines the locations in the corresponding -bytecode which require [linking](#term-linking). - - ---- - - - - - - - - - - - - - - -

Required

No

Type

Array

Format

All values must be valid Link Reference objects. See also below.

+bytecode which require [linking](#linking). + +* **Required**: No +* **Type**: Array +* **Format**: All values **must** be valid [Link Reference objects](#the-link-reference-object). See also below. Format This field is considered invalid if *any* of the [Link -References](#term-link-reference) are invalid when applied to the +References](#link-reference) are invalid when applied to the corresponding `bytecode` field, *or* if any of the link references intersect. Intersection is defined as two link references which overlap. -#### Link Dependencies: `link_dependencies` +#### Link Dependencies: `linkDependencies` -The `linkDependencies` defines the [Link Values](#term-link-value) that +The `linkDependencies` defines the [Link Values](#link-value) that have been used to link the corresponding bytecode. - ---- - - - - - - - - - - - - - - -

Required

No

Type

Array

Format

All values must be valid Link Value objects. See also below.

+* **Required**: No +* **Type**: Array +* **Format**: All values **must** be valid [Link Value objects](#the-link-value-object). See also below. Format @@ -834,133 +444,60 @@ Validation of this field includes the following: - Two link value objects **must not** contain any of the same values for `offsets`. -- Each [link value object](#link-value-object) **must** have a - corresponding [link reference object](#link-reference-object) under +- Each [link value object](#the-link-value-object) **must** have a + corresponding [link reference object](#the-link-reference-object) under the `linkReferences` field. - The length of the resolved `value` **must** be equal to the `length` - of the corresponding [Link Reference](#term-link-reference). + of the corresponding [Link Reference](#link-reference). -
- ### The *Package Meta* Object The *Package Meta* object is defined to have the following key/value pairs. -#### Authors: `authors` +#### Authors The `authors` field defines a list of human readable names for the authors of this package. Packages **may** include this field. +* **Required**: No +* **Key**: `authors` +* **Type**: Array(String) - ---- - - - - - - - - - - - - - - -

Required

No

Key

authors

Type

Array (String)

- -
- -#### License: `license` +#### License The `license` field declares the license associated with this package. This value **should** conform to the -[SPDX](https://en.wikipedia.org/wiki/Software_Package_Data_Exchange) +[SPDX](https://spdx.org/licenses/) format. Packages **should** include this field. If a file [Source -Object](#source-object) defines its own license, that license takes +Object](#the-source-object) defines its own license, that license takes precedence for that particular file over this package-scoped `meta` license. - ---- - - - - - - - - - - - - - - -

Required

No

Key

license

Type

String

- -#### Description: `description` +* **Required**: No +* **Key**: `license` +* **Type**: String + +#### Description The `description` field provides additional detail that may be relevant for the package. Packages **may** include this field. - ---- - - - - - - - - - - - - - - -

Required

No

Key

description

Type

String

- -#### Keywords: `keywords` +* **Required**: No +* **Key**: `description` +* **Type**: String + +#### Keywords The `keywords` field provides relevant keywords related to this package. - ---- - - - - - - - - - - - - - - -

Required

No

Key

keywords

Type

Array(String)

- -#### Links: `links` +* **Required**: No +* **Key**: `keywords` +* **Type**: Array(String) + +#### Links The `links` field provides URIs to relevant resources associated with this package. When possible, authors **should** use the following keys @@ -972,52 +509,16 @@ for the following common resources. - `repository`: Location of the project source code. - ---- - - - - - - - - - - - - - - -

Required

No

Key

links

Type

Object (String: String)

- -
+* **Required**: No +* **Key**: `links` +* **Type**: Object (String: String) ### The *Sources* Object A *Sources* object is defined to have the following fields. - ---- - - - - - - - - - - -

Key

A unique identifier for the source file. (String)

Value

Source Object

- - -
+* **Key**: A unique identifier for the source file. (String) +* **Value**: [Source Object](#the-source-object) ### The *Source* Object @@ -1025,27 +526,9 @@ A *Sources* object is defined to have the following fields. Hash of the source file. - ---- - - - - - - - - - - - - - - -

Required

If there are no URLs present that contain a content hash.

Key

checksum

Value

Checksum Object

- +* **Required**: Only **if** the `content` field is missing and none of the provided URLs contain a content hash. +* **Key**: `checksum` +* **Value**: [Checksum Object](#the-checksum-object) #### URLS: `urls` @@ -1062,54 +545,18 @@ Array of urls that resolve to the same source file. - If the resulting document is a file the key **should** be interpreted as a file path. - ---- - - - - - - - - - - - - - - -

Required

If content is not included.

Key

urls

Value

Array(String)

- +* **Required**: If `content` is not included. +* **Key**: `urls` +* **Value**: Array(String) #### Content: `content` Inlined contract source. If both `urls` and `content` are provided, the `content` value **must** match the content of the files identified in `urls`. - ---- - - - - - - - - - - - - - - -

Required

If urls is not included.

Key

content

Value

String

- +* **Required**: If `urls` is not included. +* **Key**: `content` +* **Value**: String #### Install Path: `installPath` @@ -1124,27 +571,9 @@ Filesystem path of source file. - **Must not** contain `../` to avoid accessing files outside of the source folder in improper implementations. - ---- - - - - - - - - - - - - - - -

Required

This field must be included for the package to be writable to disk.

Key

installPath

Value

String

- +* **Required**: This field **must** be included for the package to be writable to disk. +* **Key**: `installPath` +* **Value**: String #### Type: `type` @@ -1152,57 +581,19 @@ The `type` field declares the type of the source file. The field **should** be one of the following values: `solidity`, `vyper`, `abi-json`, `solidity-ast-json`. - ---- - - - - - - - - - - - - - - -

Required

No

Key

type

Value

String

- +* **Required**: No +* **Key**: `type` +* **Value**: String #### License: `license` The `license` field declares the type of license associated with this source file. When defined, this license overrides the -package-scoped [meta license](#meta-license). - - ---- - - - - - - - - - - - - - - -

Required

No

Key

license

Value

String

- - -
+package-scoped [meta license](#license). + +* **Required**: No +* **Key**: `license` +* **Value**: String ### The *Checksum* Object @@ -1214,48 +605,16 @@ The `algorithm` used to generate the corresponding hash. Possible algorithms include, but are not limited to `sha3`, `sha256`, `md5`, `keccak256`. - ---- - - - - - - - - - - -

Required

Yes

Type

String

- +* **Required**: Yes +* **Type**: String #### Hash: `hash` The `hash` of a source files contents generated with the corresponding algorithm. - ---- - - - - - - - - - - -

Required

Yes

Type

String

- - -
+* **Required**: Yes +* **Type**: String ### The *Contract Type* Object @@ -1265,224 +624,78 @@ pairs. #### Contract Name: `contractName` The `contractName` field defines the [Contract -Name](#term-contract-name) for this [Contract -Type](#term-contract-type). - - ---- - - - - - - - - - - - - - - -

Required

If the Contract Name and Contract Alias are not the same.

Type

String

Format

Must be a valid Contract Name.

+Name](#contract-name) for this [Contract +Type](#contract-type). +* **Required**: If the [Contract Name](#contract-name) and [Contract Alias](#contract-alias) are not the same. +* **Type**: String +* **Format**: **Must** be a valid [Contract Name](#contract-name) #### Source ID: `sourceId` The global source identifier for the source file from which this contract type was generated. - ---- - - - - - - - - - - - - - - -

Required

No

Type

String

Format

Must match a unique source ID included in the Sources Object for this package.

- +* **Required**: No +* **Type**: String +* **Format**: **Must** match a unique source ID included in the [Sources Object](#the-sources-object) for this package. #### Deployment Bytecode: `deploymentBytecode` The `deploymentBytecode` field defines the bytecode for this [Contract -Type](#term-contract-type). - - ---- - - - - - - - - - - - - - - -

Required

No

Type

Object

Format

Must conform to the Bytecode object format.

+Type](#contract-type). +* **Required**: No +* **Type**: Object +* **Format**: **Must** conform to the [Bytecode object](#the-bytecode-object) format. #### Runtime Bytecode: `runtimeBytecode` The `runtimeBytecode` field defines the unlinked `0x`-prefixed runtime -portion of [Bytecode](#term-bytecode) for this [Contract -Type](#term-contract-type). - - ---- - - - - - - - - - - - - - - -

Required

No

Type

Object

Format

Must conform to the Bytecode object format.

+portion of [Bytecode](#bytecode) for this [Contract +Type](#contract-type). +* **Required**: No +* **Type**: Object +* **Format**: **Must** conform to the [Bytecode object](#the-bytecode-object) format. #### ABI: `abi` - ---- - - - - - - - - - - - - - - -

Required

No

Type

Array

Format

Must conform to Ethereum Contract ABI JSON format.

- +* **Required**: No +* **Type**: Array +* **Format**: **Must** conform to the [Ethereum Contract ABI JSON](https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI#json) format. #### UserDoc: `userdoc` - ---- - - - - - - - - - - - - - - -

Required

No

Type

Object

Format

Must conform to UserDoc format.

- +* **Required**: No +* **Type**: Object +* **Format**: **Must** conform to the [UserDoc](https://github.com/ethereum/wiki/wiki/Ethereum-Natural-Specification-Format#user-documentation) format. #### DevDoc: `devdoc` - ---- - - - - - - - - - - - - - - -

Required

No

Type

Object

Format

Must conform to DevDoc format.

- - -
+* **Required**: No +* **Type**: Object +* **Format**: **Must** conform to the [DevDoc](https://github.com/ethereum/wiki/wiki/Ethereum-Natural-Specification-Format#developer-documentation) format. ### The *Contract Instance* Object A **Contract Instance Object** represents a single deployed [Contract -Instance](#term-contract-instance) and is defined to have the following +Instance](#contract-instance) and is defined to have the following key/value pairs. #### Contract Type: `contractType` The `contractType` field defines the [Contract -Type](#term-contract-type) for this [Contract -Instance](#term-contract-instance). This can reference any of the -contract types included in this [Package](#term-package) *or* any of the +Type](#contract-type) for this [Contract +Instance](#contract-instance). This can reference any of the +contract types included in this [Package](#package) *or* any of the contract types found in any of the package dependencies from the `buildDependencies` section of the [Package -Manifest](#term-package-manifest). - - ---- - - - - - - - - - - - - - - -

Required

Yes

Type

String

Format

See Below.

+Manifest](#package-manifest). +* **Required**: Yes +* **Type**: String +* **Format**: See below. Format @@ -1493,7 +706,7 @@ To reference a contract type from this Package, use the format ``. - The `` value **must** be a valid [Contract - Alias](#term-contract-alias). + Alias](#contract-alias). - The value **must** be present in the keys of the `contractTypes` section of this Package. @@ -1505,133 +718,58 @@ To reference a contract type from a dependency, use the format `buildDependencies` of this Package. - The `` value **must** be be a valid [Contract - Alias](#term-contract-alias). + Alias](#contract-alias). - The resolved package for `` must contain the `` value in the keys of the `contractTypes` section. #### Address: `address` -The `address` field defines the [Address](#term-address) of the -[Contract Instance](#term-contract-instance). - - ---- - - - - - - - - - - - - - - -

Required

Yes

Type

String

Format

Hex encoded 0x prefixed Ethereum address matching the regular expression ^0x[0-9a-fA-F]{40}$.

+The `address` field defines the [Address](#address) of the +[Contract Instance](#contract-instance). +* **Required**: Yes +* **Type**: String +* **Format**: Hex encoded `0x` prefixed Ethereum address matching the regular expression `^0x[0-9a-fA-F]{40}$`. #### Transaction: `transaction` The `transaction` field defines the transaction hash in which this -[Contract Instance](#term-contract-instance) was created. - - ---- - - - - - - - - - - - - - - -

Required

No

Type

String

Format

0x prefixed hex encoded transaction hash.

+[Contract Instance](#contract-instance) was created. +* **Required**: No +* **Type**: String +* **Format**: `0x` prefixed hex encoded transaction hash. #### Block: `block` The `block` field defines the block hash in which this the transaction which created this *contract instance* was mined. - ---- - - - - - - - - - - - - - - -

Required

No

Type

String

Format

0x prefixed hex encoded block hash.

- +* **Required**: No +* **Type**: String +* **Format**: `0x` prefixed hex encoded block hash. #### Runtime Bytecode: `runtimeBytecode` The `runtimeBytecode` field defines the runtime portion of bytecode for -this [Contract Instance](#term-contract-instance). When present, the +this [Contract Instance](#contract-instance). When present, the value from this field supersedes the `runtimeBytecode` from the -[Contract Type](#term-contract-type) for this [Contract -Instance](#term-contract-instance). - - ---- - - - - - - - - - - - - - - -

Required

No

Type

Object

Format

Must conform to the Bytecode Object format.

+[Contract Type](#contract-type) for this [Contract +Instance](#contract-instance). +* **Required**: No +* **Type**: Object +* **Format**: **Must** conform to the [Bytecode Object](#the-bytecode-object) format. Every entry in the `linkReferences` for this bytecode **must** have a corresponding entry in the `linkDependencies` section. - -
- ### The *Compiler Information* Object The `compilers` field defines the various compilers and settings used -during compilation of any [Contract Types](#term-contract-type) or -[Contract Instance](#term-contract-instance) included in this package. +during compilation of any [Contract Types](#contract-type) or +[Contract Instance](#contract-instance) included in this package. A *Compiler Information* object is defined to have the following key/value pairs. @@ -1640,27 +778,9 @@ key/value pairs. The `name` field defines which compiler was used in compilation. - ---- - - - - - - - - - - - - - - -

Required

Yes

Key

name

Type

String

- +* **Required**: Yes +* **Key**: `name` +* **Type**: String #### Version: `version` @@ -1671,27 +791,9 @@ form of either the stable version in nightly should be denoted in the form of `-` ex: `0.4.8-commit.60cc1668`. - ---- - - - - - - - - - - - - - - -

Required

Yes

Key

version

Type

String

- +* **Required**: Yes +* **Key**: `version` +* **Type**: String #### Settings: `settings` @@ -1700,31 +802,13 @@ in compilation. For the `"solc"` compiler, this **should** conform to the [Compiler Input and Output Description](http://solidity.readthedocs.io/en/latest/using-the-compiler.html#compiler-input-and-output-json-description). - ---- - - - - - - - - - - - - - - -

Required

No

Key

settings

Type

Object

- +* **Required**: No +* **Key**: `settings` +* **Type**: Object #### Contract Types: `contractTypes` -A list of the [Contract Alias](#term-contract-alias) or [Contract Types](#term-contract-type) in this package +A list of the [Contract Alias](#contract-alias) or [Contract Types](#contract-type) in this package that used this compiler to generate its outputs. - All `contractTypes` that locally declare `runtimeBytecode` @@ -1733,31 +817,12 @@ that used this compiler to generate its outputs. - A single `contractTypes` **must** not be attributed to more than one compiler. - ---- - - - - - - - - - - - - - - -

Required

No

Key

contractTypes

Type

Array(Contract Alias)

- - -
- -### BIP122 URIs +* **Required**: No +* **Key**: `contractTypes` +* **Type**: Array([Contract Alias](#contract-alias)) + + +### BIP122 URI BIP122 URIs are used to define a blockchain via a subset of the [BIP-122](https://github.com/bitcoin/bips/blob/master/bip-0122.mediawiki) @@ -1775,48 +840,27 @@ free to choose their desired level of confirmations). The terms in this glossary have been updated to reflect the changes made in V3. -
-ABI +#### ABI The JSON representation of the application binary interface. See the official [specification](https://solidity.readthedocs.io/en/develop/abi-spec.html) for more information. -
-Address +#### Address A public identifier for an account on a particular chain -
-Bytecode +#### Bytecode The set of EVM instructions as produced by a compiler. Unless otherwise specified this should be assumed to be hexadecimal encoded, representing -a whole number of bytes, and [prefixed](#term-prefixed) with `0x`. +a whole number of bytes, and [prefixed](#prefixed) with `0x`. Bytecode can either be linked or unlinked. (see -[Linking](#term-linking)) - - ---- - - - - - - - - - - -

Unlinked Bytecode

The hexadecimal representation of a contract’s EVM instructions that contains sections of code that requires linking for the contract to be functional.

-

The sections of code which are unlinked must be filled in with zero bytes.

-

Example: 0x606060405260e06000730000000000000000000000000000000000000000634d536f

Linked Bytecode

The hexadecimal representation of a contract’s EVM instructions which has had all Link References replaced with the desired Link Values.

-

Example: 0x606060405260e06000736fe36000604051602001526040518160e060020a634d536f

- -
-Chain Definition +[Linking](#linking)) + +* **Unlinked Bytecode**: The hexadecimal representation of a contract’s EVM instructions that contains sections of code that requires [linking](#linking) for the contract to be functional.
The sections of code which are unlinked **must** be filled in with zero bytes.
**Example**: `0x606060405260e06000730000000000000000000000000000000000000000634d536f` +* **Linked Bytecode**: The hexadecimal representation of a contract’s EVM instructions which has had all [Link References](#link-reference) replaced with the desired [Link Values](#link-value). **Example**: `0x606060405260e06000736fe36000604051602001526040518160e060020a634d536f` + +#### Chain Definition This definition originates from [BIP122 URI](https://github.com/bitcoin/bips/blob/master/bip-0122.mediawiki). @@ -1833,8 +877,7 @@ block hash matches the `chain_id` and the block defined by `block_hash` can be found on that chain. It is possible for multiple chains to match a single URI, in which case all chains are considered valid matches -
-Content Addressable URI +#### Content Addressable URI Any URI which contains a cryptographic hash which can be used to verify the integrity of the content found at the URI. @@ -1842,11 +885,10 @@ The URI format is defined in RFC3986 It is **recommended** that tools support IPFS and Swarm. -
-Contract Alias +#### Contract Alias This is a name used to reference a specific [Contract -Type](#term-contract-type). Contract aliases **must** be unique within a -single [Package](#term-package). +Type](#contract-type). Contract aliases **must** be unique within a +single [Package](#package). The contract alias **must** use *one of* the following naming schemes: @@ -1855,31 +897,29 @@ The contract alias **must** use *one of* the following naming schemes: - `` The `` portion **must** be the same as the [Contract -Name](#term-contract-name) for this contract type. +Name](#contract-name) for this contract type. The `` portion **must** match the regular expression `^[-a-zA-Z0-9]{1,256}$`. -
-Contract Instance +#### Contract Instance A contract instance a specific deployed version of a [Contract -Type](#term-contract-type). +Type](#contract-type). -All contract instances have an [Address](#term-address) on some specific +All contract instances have an [Address](#address) on some specific chain. -
-Contract Instance Name +#### Contract Instance Name A name which refers to a specific [Contract -Instance](#term-contract-instance) on a specific chain from the -deployments of a single [Package](#term-package). This name **must** be +Instance](#contract-instance) on a specific chain from the +deployments of a single [Package](#package). This name **must** be unique across all other contract instances for the given chain. The name must conform to the regular expression `^[a-zA-Z_$][a-zA-Z0-9_$]{0,255}$` In cases where there is a single deployed instance of a given [Contract -Type](#term-contract-type), package managers **should** use the -[Contract Alias](#term-contract-alias) for that contract type for this +Type](#contract-type), package managers **should** use the +[Contract Alias](#contract-alias) for that contract type for this name. In cases where there are multiple deployed instances of a given contract @@ -1887,17 +927,15 @@ type, package managers **should** use a name which provides some added semantic information as to help differentiate the two deployed instances in a meaningful way. -
-Contract Name +#### Contract Name The name found in the source code that defines a specific [Contract -Type](#term-contract-type). These names **must** conform to the regular +Type](#contract-type). These names **must** conform to the regular expression `^[a-zA-Z_$][a-zA-Z0-9_$]{0,255}$`. There can be multiple contracts with the same contract name in a projects source files. -
-Contract Type +#### Contract Type Refers to a specific contract in the package source. This term can be used to refer to an abstract contract, a normal contract, or a library. Two contracts are of the same contract type if they have the same @@ -1912,212 +950,92 @@ Example: A deployed instance of the `Wallet` contract would be of of type `Wallet`. -
-Identifier -Refers generally to a named entity in the [Package](#term-package). +#### Identifier +Refers generally to a named entity in the [Package](#package). A string matching the regular expression `^[a-zA-Z][-_a-zA-Z0-9]{0,255}$` - -Link Reference +#### Link Reference A location within a contract’s bytecode which needs to be linked. A link reference has the following properties. - ---- - - - - - - - - - - - - - - -

offset

Defines the location within the bytecode where the link reference begins.

length

Defines the length of the reference.

name

(optional) A string to identify the reference

- - - -Link Value +* **`offset`**: Defines the location within the bytecode where the link reference begins. +* **`length`**: Defines the length of the reference. +* **`name`**: (optional) A string to identify the reference. + +#### Link Value A link value is the value which can be inserted in place of a [Link -Reference](#term-link-reference) +Reference](#link-reference) -
-Linking -The act of replacing [Link References](#term-link-reference) with [Link -Values](#term-link-value) within some [Bytecode](#term-bytecode). +#### Linking +The act of replacing [Link References](#link-reference) with [Link +Values](#link-value) within some [Bytecode](#bytecode). -
-Package +#### Package Distribution of an application’s source or compiled bytecode along with metadata related to authorship, license, versioning, et al. For brevity, the term **Package** is often used metonymously to mean -[Package Manifest](#term-package-manifest). +[Package Manifest](#package-manifest). -
-Package Manifest +#### Package Manifest A machine-readable description of a package. -
-Prefixed -[Bytecode](#term-bytecode) string with leading `0x`. - - ---- - - - - - - -

Example

0xdeadbeef

- -
-Unprefixed -Not [Prefixed](#term-prefixed). - - ---- - - - - - - -

Example

deadbeef

- - -## Rationale - -The following use cases were considered during the creation of this -specification. - - ---- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

owned

A package which contains contracts which are not meant to be used by themselves but rather as base contracts to provide functionality to other contracts through inheritance.

transferable

A package which has a single dependency.

standard-token

A package which contains a reusable contract.

safe-math-lib

A package which contains deployed instance of one of the package contracts.

piper-coin

A package which contains a deployed instance of a reusable contract from a dependency.

escrow

A package which contains a deployed instance of a local contract which is linked against a deployed instance of a local library.

wallet

A package with a deployed instance of a local contract which is linked against a deployed instance of a library from a dependency.

wallet-with-send

A package with a deployed instance which links against a deep dependency.

simple-auction

Compiler "metadata" field output.

- -Each use case builds incrementally on the previous one. - -A full listing of [Use -Cases](https://ethpm.github.io/ethpm-spec/use-cases.html) -can be found on the hosted version of this specification. - -## Backwards Compatibility - -To improve understanding and readability of the EthPM spec, the -`manifest_version` field was updated to `manifest` in v3. To ensure -backwards compatibility, v3 packages **must** define a top-level -`"manifest"` with a value of `"ethpm/3"`. Additionally, -`"manifest_version"` is a forbidden top-level key in v3 packages. - - -## Implementations +#### Prefixed +[Bytecode](#bytecode) string with leading `0x`. -This submission aims to coincide with development efforts towards -widespread implementation in commonly-used development tools. +* **Example**: `0xdeadbeef` -The following tools are known to have begun or are nearing completion of -a supporting implementation. +#### Unprefixed +Not [Prefixed](#prefixed). -- [Truffle](https://trufflesuite.com/) +* **Example**: `deadbeef` -- [Brownie](https://eth-brownie.readthedocs.io/en/stable/) - -- [web3.py](https://github.com/ethereum/web3.py/) - -- [ethpm-cli](https://github.com/ethpm/ethpm-cli) +## Rationale -Full support in implementation **may** require [Further -Work](#further-work), specified below. +### Minification +EthPM packages are distributed as alphabetically-ordered & minified JSON to ensure consistency. +Since packages are published on content-addressable filesystems (eg. IPFS), this restriction +guarantees that any given set of contract assets will always resolve to the same content-addressed URI. -## Further Work +### Package Names -This EIP addresses only the data format for package descriptions. -Excluded from the scope of this specification are: +Package names are restricted to lower-case characters, numbers, and `-` to improve the readability +of the package name, in turn improving the security properties for a package. A user is more likely +to accurately identify their target package with this restricted set of characters, and not confuse +a malicious package that disguises itself as a trusted package with similar but different +characters (e.g. `O` and `0`). -- Package registry interface definition [ERC 1319](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1319.md) +### BIP122 -- Tooling integration, or how packages are stored on disk. +The BIP-122 standard has been used since EthPM v1 since it is an industry standard URI scheme for +identifying different blockchains and distinguishing between forks. -These efforts **should** be considered separate, warranting future -dependent EIP submssions. +### Compilers +Compilers are now defined in a top-level array, simplifying the task for tooling to identify the compiler types +needed to interact with or validate the contract assets. This also removes unnecessarily duplicated +information, should multiple `contractTypes` share the same compiler type. -## Acknowledgements +## Backwards Compatibility -The authors of this document would like to thank the original authors of -[EIP-190](https://eips.ethereum.org/EIPS/eip-190), -[EIP-1123](https://eips.ethereum.org/EIPS/eip-1123), all community -[contributors](https://github.com/ethpm/ethpm-spec/graphs/contributors), -and the Ethereum community at large. +To improve understanding and readability of the EthPM spec, the +`manifest_version` field was updated to `manifest` in v3. To ensure +backwards compatibility, v3 packages **must** define a top-level +`"manifest"` with a value of `"ethpm/3"`. Additionally, +`"manifest_version"` is a forbidden top-level key in v3 packages. ## Security Considerations -The same security considerations from v2 are still relevant for EthPM v3. Using EthPM packages implicitly requires -that users import &/or execute code written by others. The EthPM spec guarantees that when using a properly -constructed and released EthPM package, the user will have the exact same code that was included in the package -by the package author. However, it is impossible to guarantee that this code is safe to interact with. Therefore, -it is critical that end users only interact with EthPM packages authored and released by individuals or organizations -that they trust to include non-malicious code. +Using EthPM packages implicitly requires importing &/or executing code written by others. The EthPM spec +guarantees that when using a properly constructed and released EthPM package, the user will have the exact same +code that was included in the package by the package author. However, it is impossible to guarantee that this code +is safe to interact with. Therefore, it is critical that end users only interact with EthPM packages authored and +released by individuals or organizations that they trust to include non-malicious code. + ## Copyright diff --git a/EIPS/eip-2680.md b/EIPS/eip-2680.md new file mode 100644 index 00000000000000..50e9d9b59466b4 --- /dev/null +++ b/EIPS/eip-2680.md @@ -0,0 +1,136 @@ +--- +eip: 2680 +title: Ethereum 2 wallet layout +author: Jim McDonald +discussions-to: https://ethereum-magicians.org/t/eip-2680-ethereum-2-wallet-layout/4323 +status: Draft +type: Standards Track +category: ERC +created: 2020-05-29 +--- + +## Simple Summary + +A standard layout and naming format for walletstore and keystore for both hierarchical (e.g. filesystem, Amazon S3) and non-hierarchical (key/value) storage systems. + +## Abstract + +Ethereum wallets have no standards for their layout in persistent storage, making different wallet implementations incompatible. This defines a standard for the placement of Ethereum walletstores and keystores, making it possible for different software to work with the same wallets and keys. + +## Motivation + +A standard layout for wallets and accounts allows interoperability between validators. This benefits users, as they can move from one validator software to another (and back) without requiring movement of files. This is important because any movement of files containing keys involves danger of either deleting them or duplicating them, both of which could cause loss of access to funds. + +## Specification + +There are four elements for a wallet that need to be addressed. These are defined below. + +### Base location +The base location is required to be well-known, either pre-defined or defined by the storage system's connection parameters. + +For filesystems the pre-defined base location for different operating systems is as follows: + + - Windows: `%APPDATA%\ethereum2\wallets` + - MacOSX: `${HOME}/Library/Application Support/ethereum2/wallets` + - Linux: `${HOME}/.config/ethereum2/wallets` + +For other hierarchical stores, for example Amazon S3, the base location MUST be the lower-case hex string representing the [SHA-256](../assets/eip-2680/sha256-384-512.pdf) hash of the string "Ethereum 2 wallet:" appended with the identifier for the hierarchical store. For example, if the account ID for a user's Amazon S3 account is "AbC0438EB" then: + + - string would be `Ethereum 2 wallet:AbC0438EB` + - SHA-256 hash of string would be the byte array `0x991ec14a8d13836b10d8c3039c9e30876491cb8aa9c9c16967578afc815c9229` + - base location would be the string `991ec14a8d13836b10d8c3039c9e30876491cb8aa9c9c16967578afc815c9229` + +For non-hierarchical stores there is no base location. + +### Wallet container +The wallet container holds the walletstore and related keystores. + +The wallet container is identified by the wallet's UUID. It MUST be a string following the syntactic structure as laid out in [section 3 of RFC 4122](https://tools.ietf.org/html/rfc4122#section-3). + +### Walletstore +The walletstore element contains the walletstore and is held within the wallet container. It is identified by the wallet's UUID. It MUST be a string following the syntactic structure as laid out in [section 3 of RFC 4122](https://tools.ietf.org/html/rfc4122#section-3). + +### Keystore +The keystore element contains the keystore for a given key and is held within the wallet container. It is identified by the key's UUID. It MUST be a string following the syntactic structure as laid out in [section 3 of RFC 4122](https://tools.ietf.org/html/rfc4122#section-3). + +## Hierarchical store example +Hierarchical stores are a common way to store and organize information. The most common example is the filesystem, but a number of object-based stores such as Amazon S3 also provide hierarchical naming. + +Putting these elements together for a sample wallet with wallet UUID `1f031fff-c51d-44fc-8baf-d6b304cb70a7` and key UUIDs `1302106c-8441-4e2e-b687-6c77f49fc624` and `4a320100-83fd-4db7-8126-6d6d205ba834` gives the following layout: + +``` +- 1f031fff-c51d-44fc-8baf-d6b304cb70a7 ++- 1302106c-8441-4e2e-b687-6c77f49fc624 ++- 1f031fff-c51d-44fc-8baf-d6b304cb70a7 ++- 4a320100-83fd-4db7-8126-6d6d205ba834 +``` + +### Non-hierarchical store example +Non-hierarchical stores use a simplified approach where the wallet UUID and key UUIDs are concatenated using the ':' character. Using the same example wallet and key UUIDs as above would result in objects with the following keys: + +``` +1f031fff-c51d-44fc-8baf-d6b304cb70a7:1302106c-8441-4e2e-b687-6c77f49fc624 +1f031fff-c51d-44fc-8baf-d6b304cb70a7:1f031fff-c51d-44fc-8baf-d6b304cb70a7 +1f031fff-c51d-44fc-8baf-d6b304cb70a7:4a320100-83fd-4db7-8126-6d6d205ba834 +``` + +### Protecting against concurrent write access +TBD + +### Iterating over wallets +In the case of hierarchical stores and iteration-capable non-hierarchical stores iteration over wallets is a matter of iterating over the files in the root container. + +An implementer MAY include an index in the base location. If so then it MUST follow the structure as specified in the following "Index format" section. + +### Iterating over accounts +In the case of hierarchical stores iteration over accounts is a matter of iterating over the files in the wallet container. + +An implementer MAY include an index within a wallet container for accounts within that wallet. If so then it MUST follow the structure as specified in the following "Index format" section. + +### Index format +The index format is the same for both wallets and accounts, following a standard JSON schema. + +```json +{ + "type": "array", + "items": { + "type": "object", + "properties": { + "uuid": { + "type": "string" + }, + "name": { + "type": "string" + } + }, + "required": [ + "uuid", + "name" + ] + } +} +``` + +The index MUST use the identifier 'index'. + +Public keys must NOT be stored in the index. + +## Rationale + +A standard for walletstores, similar to that for keystores, provides a higher level of compatibility between wallets and allows for simpler wallet and key interchange between them. + +## Implementation + +A Go implementation of the filesystem layout can be found at [https://github.com/wealdtech/go-eth2-wallet-filesystem](https://github.com/wealdtech/go-eth2-wallet-filesystem). + +A Go implementation of the Amazon S3 layout can be found at [https://github.com/wealdtech/go-eth2-wallet-s3](https://github.com/wealdtech/go-eth2-wallet-s3). + +## Security Considerations + +Locations for wallet stores are defined to be within each user's personal space, reducing the possibility of accidental exposure of information. It is, however, still possible for permissions to be set such that this data is world-readable, and applications implementing this EIP should attempt to set, and reset, permissions to ensure that only the relevant user has access to the information. + +The names for both wallet and key stores are UUIDs, ensuring that no data is leaked from the metadata. + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-2681.md b/EIPS/eip-2681.md index d76dfffa641c85..9e5972f49be38b 100644 --- a/EIPS/eip-2681.md +++ b/EIPS/eip-2681.md @@ -3,7 +3,7 @@ eip: 2681 title: Limit account nonce to 2^64-1 author: Alex Beregszaszi (@axic) discussions-to: https://ethereum-magicians.org/t/eip-2681-limit-account-nonce-to-2-64-1/4324 -status: Draft +status: Review type: Standards Track category: Core created: 2020-04-25 @@ -15,12 +15,11 @@ Limit account nonce to be between `0` and `2^64-1`. ## Motivation -This is motivated by Eth1.x / Stateless Ethereum discussions, more specifically discussion around the ["witness format"](https://github.com/ethereum/stateless-ethereum-specs). -Introducing a restriction would allow storing the nonce in a more optimised way. +Account nonces are currently specified to be arbitrarily long unsigned integers. Dealing with arbitrary length data in the state witnesses is not optimal, therefore this EIP will allow proofs to represent the nonce in a more optimized way. Additionally it could prove beneficial to transaction formats, where some improvements are potentially sought by at least three other proposals. -Lastly this facilitates a minor optimisation in clients, because the nonce no longer needs to be kept as a 256-bit number. +Lastly, this facilitates a minor optimisation in clients, because the nonce no longer needs to be kept as a 256-bit number. ## Specification @@ -34,7 +33,7 @@ If `block.number >= FORK_BLOCK` introduce two new restrictions: 1. It is unlikely for any nonce to reach or exceed the proposed limit. If one would want to reach that limit via external transactions, it would cost at least `21000 * (2^64-1) = 387_381_625_547_900_583_915_000` gas. 2. It must be noted that in the past, in the Morden testnet, each new account had a starting nonce of `2^20` in order to differentiate transactions from mainnet transactions. -This mode of replay protection is out of fashion since [EIP-155](https://eips.ethereum.org/EIPS/eip-155) introduced a more elegant way using chain identifiers. +This mode of replay protection is out of fashion since [EIP-155](./eip-155.md) introduced a more elegant way using chain identifiers. 3. Most clients already consider the nonce field to be 64-bit, such as go-ethereum. @@ -42,21 +41,13 @@ This mode of replay protection is out of fashion since [EIP-155](https://eips.et While this is a breaking change, no actual effect should be visible: -1. There is no account in the state currently which would have a nonce exceeding that value. **Need to double check, but would be very surprised.** +1. There is no account in the state currently which would have a nonce exceeding that value. As of November 2020, the account `0xea674fdde714fd979de3edf0f56aa9716b898ec8` is responsible for the highest account nonce at approximately 29 million. 2. go-ethereum already has this restriction in place (`state.Account.Nonce` and `types.txdata.AccountNonce` it as a 64-bit number). ## Security Considerations -TBA - -## Test Cases - -TBA - -## Implementation - -TBA +None. ## Copyright diff --git a/EIPS/eip-2718.md b/EIPS/eip-2718.md index 65c8fe9aadc72c..c8f37029472191 100644 --- a/EIPS/eip-2718.md +++ b/EIPS/eip-2718.md @@ -3,7 +3,7 @@ eip: 2718 title: Typed Transaction Envelope author: Micah Zoltu (@MicahZoltu) discussions-to: https://ethereum-magicians.org/t/eip-2718-typed-transaction-envelope/4355 -status: Draft +status: Review type: Standards Track category: Core created: 2020-06-13 @@ -36,7 +36,7 @@ As of `FORK_BLOCK_NUMBER`, the transaction root in the block header **MUST** be * `LegacyTransaction` is `rlp([nonce, gasPrice, gasLimit, to, value, data, v, r, s])` All signatures for future transaction types **SHOULD** include the `TransactionType` as the first byte of the signed data. -This makes it so we do not have to worry about signatures for one transaction type being used as signaturese for a different transaction type. +This makes it so we do not have to worry about signatures for one transaction type being used as signatures for a different transaction type. ### Receipts As of `FORK_BLOCK_NUMBER`, the receipt root in the block header **MUST** be the root hash of `patriciaTrie(rlp(Index) => Receipt)` where: @@ -73,14 +73,8 @@ Clients can differentiate between the legacy transactions and typed transactions If it starts with a value in the range `[0, 0x7f]` then it is a new transaction type, if it starts with a value in the range `[0xc0, 0xfe]` then it is a legacy transaction type. `0xff` is not realistic for an RLP encoded transaction, so it is reserved for future use as an extension sentinel value. -## Test Cases -TBD - -## Implementation -TBD - ## Security Considerations -TBD +When designing a new 2718 transaction type, it is **STRONGLY** recommended to include the transaction type as the first byte of the signed payload. If you fail to do this, it is possible that your transaction may be signature compatible with transactions of another type which can introduce security vulnerabilities for users. ## Copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-2733.md b/EIPS/eip-2733.md index da021a4a39a553..57d6d0a749a224 100644 --- a/EIPS/eip-2733.md +++ b/EIPS/eip-2733.md @@ -1,6 +1,6 @@ --- eip: 2733 -title: Transaction package +title: Transaction Package author: Matt Garnett (@lightclient) discussions-to: https://ethereum-magicians.org/t/eip-transaction-package/4365 status: Draft @@ -15,108 +15,247 @@ Creates a new transaction type which executes a package of one or more transactions, while passing status information to subsequent transactions. ## Abstract -After `FORK_BLOCK`, a new [EIP-2718](https://eips.ethereum.org/EIPS/eip-2718) -transaction of type `N` is recognized. Transactions of type `N` will define a -list of transactions, which must be executed serially by clients. Execution -information (e.g. `success`, `gas_used`, etc.) will be propagated forward to -the next transaction. +Introduce a new transaction type which includes a list of transactions that +must be executed serially by clients. Execution information (e.g. success, +gas_used, etc.) will be propagated forward to the next transaction. ## Motivation -Meta-transaction relay contracts have historically been designed to catch -reversions in their inner transactions by only passing a portion of the -available gas to the subcall. This has been considered bad practice for a long -time, but in the case of untrusted subcalls, like the ones relay contracts -make, it is the only available solution. Transaction packages are an -alternative that allow multiple transactions to be bundled into one package and -executed atomically, similarly to how relay contracts operate. Transactions are -able to pass their result to subsequent transactions. This allows for -conditional workflows based on the outcome of previous transactions. Although -this functionality is already possible as described above, workflows using -transaction packages are more robust, because they are protected from future -changes to the gas schedule. +Onboarding new users to Ethereum has been notoriously difficult due to the need +for new users to acquire enough ether to pay for their transactions. This +hurdle has seen a significant allocation of resources over the years to solve. +Today, that solution is meta-transactions. This is, unfortunately, a brittle +solution that requires signatures to be recovered within a smart contract to +authenticate the message. This EIP aims to provide a flexible framework for +relayers to "sponsor" many transactions at once, trustlessly. + +Meta-transactions often use relay contracts to maintain nonces and allow users +to pay for gas using alternative assets. They have historically been designed +to catch reversions in their inner transactions by only passing a portion of +the available gas to the subcall. This allows them to be certain the outer call +will have enough gas to complete any required account, like processing a gas +payment. This type of subcall has been considered bad practice for a long time, +but in the case of where you don't trust the subcalls, it is the only available +solution. + +Transaction packages are an alternative that allow multiple transactions to be +bundled into one package and executed atomically, similarly to how relay +contracts operate. Transactions are able to pass their result to subsequent +transactions. This allows for conditional workflows based on the outcome of +previous transactions. Although this functionality is already possible as +described above, workflows using transaction packages are more robust, because +they are protected from future changes to the gas schedule. + +An important byproduct of this EIP is that it also facilitates bundling +transactions for single users. ## Specification +Introduce a new [EIP-2718](./eip-2718.md) transaction type where `id = 2`. + +#### Structure +``` +struct TransactionPackage { + chain_id: u256, + children: [ChildPackage], + nonce: u64, + gas_price: u256, + v: u256, + r: u256, + s: u256 +} +``` + +##### Hash +`keccak256(rlp([2, chain_id, children, nonce, gas_price, v, r, s])` + +##### Signature Hash +`keccak256(rlp([2, chain_id, children, nonce, gas_price])` + +##### Receipt +Each `ChildTransaction` transaction will generate a `ChildReceipt` after execution. Each +of these receipts will be aggregated into a `Receipt`. -### Definitions ``` -N = TBD transaction type number -INTRINSIC_COST = TBD -TOTAL_COST = INTRINSIC_COST + inner_txs.reduce(|itx, acc| acc += itx.value + tx.gas_price * itx.gas_limit) -TOTAL_GAS_LIMIT = inner_txs.reduce(|itx, acc| acc += itx.gas_limit) -TX_HASH = hash of transaction as defined below -SENDER = ecrecover(hash, v, r, s) -RESULT = result as defined below for the previous transaction, empty if its the first tx in a package +type Receipt = [ChildReceipt] ``` -### Serialization -After `FORK_BLOCK`, a new [EIP-2718](https://eips.ethereum.org/EIPS/eip-2718) -transaction type `N` will be interpreted as follows: +``` +struct ChildReceipt { + status: u256, + cumulative_gas_used: u256, + logs_bloom: [u8; 256], + logs: [u8] +} +``` + +#### Child Transaction +Let `ChildPackage` be interpreted as follows. + +``` +struct ChildPackage { + type: u8, + nonce: u64, + transactions: [ChildTransaction], + max_gas_price: u256, + v: u256, + r: u256, + s: u256 +} +``` + +``` +struct ChildTransaction { + flags: u8, + to: Address, + value: u256, + data: [u8], + extra: [u8], + gas_limit: u256 +} +``` -`rlp([N, [v, r, s, chain_id, nonce, gas_price, [inner_tx_0, ..., inner_tx_n]])` +##### Types +The `type` field is used to denote whether the `Child` signer wishes to +delegate the `max_gas_price` and `gas_limit` choice to the `TransactionPackage` +signer. -where `inner_tx_n` is defined as: +| type | signature hash | +|---|---| +| `0x00` | `keccak256(rlp([0, nonce, transactions, max_gas_price])` | +| `0x01` | `keccak256(rlp([1, nonce, transactions_without_gas_limit])` | -`[to, value, data, gas_limit]` +### Validity -### Hashing -The hash of transaction type `N` is defined to be the Keccak-256 hash of the -rlp encoding of the entire transaction with `v`, `r`, and `s` values set to -zero. +A `TransactionPackage` can be deemed valid or invalid as follows. + +```rust +fn is_valid(config: &Config, state: &State, tx: TransactionPackage) bool { + if ( + config.chain_id() != tx.chain_id || + tx.children.len() == 0 || + state.nonce(tx.from()) + 1 != tx.nonce + ) { + return false; + } + + let cum_limit = tx.children.map(|x| x.gas_limit).sum(); + if state.balance(tx.from()) < cum_limit * tx.gas_price + intrinsic_gas(tx) { + return false; + } + + for child in tx.children { + if ( + child.nonce != state.nonce(child.from()) + 1 || + child.value > state.balance(child.from()) || + child.max_gas_price < tx.gas_price + ) { + return false; + } + + for tx in child.txs { + if ( + tx.flags != 0 || + tx.extra.len() != 0 || + tx.gas_limit < intrinsic_gas(tx) + ) { + return false; + } + } + } + + true +} +``` ### Results -Subsequent transactions will be able to receive the result of the previous -transaction via `RETURNDATACOPY (0x3E)` in first frame of exeuction, before -making any subcalls. Each element, except the last, will be `0`-padded left to -32 bytes. - -| Name | Type | Description | -|---|---|---| -| `success` | bool | Status of the previous transaction | -| `gas_used` | uint256 | Total gas used by the previous transaction | -| `cum_gas_used` | uint256 | Cumulative gas used by previous transactions | -| `return_size` | uint256 | The size of the return value | -| `return_value` | bytes | The return value of the previous transaction - -### Validation -* (v, r, s) are a valid signature of the hash of the transaction -* The nonce is one greater than recovered address' current nonce -* The recovered address has a balance of at least `TOTAL_COST` -* The `TOTAL_GAS_LIMIT` is less than the current block's `gas_limit` + +Subsequent `ChildTransaction`s will be able to receive the result of the +previous `ChildTransaction` via `RETURNDATACOPY (0x3E)` in first frame of +execution, before making any subcalls. Each element, except the last, will be +`0`-padded left to 32 bytes. + +``` +struct Result { + // Status of the previous transaction + success: bool, + + // Total gas used by the previous transaction + gas_used: u256, + + // Cumulative gas used by previous transactions + cum_gas_used: u256, + + // The size of the return value + return_size: u256, + + // The return value of the previous transaction + return_value: [u8] +} +``` + +### Intrinsic Cost +Let the intrinsic cost of the transaction package be defined as follows: + +``` +fn intrinsic_gas(tx: TransactionPackage) u256 { + let data_gas = tx.children.map(|c| c.txs.map(|t| data_cost(&c.data)).sum()).sum(); + 17000 + 8000 * tx.children.len() + data_gas +} +``` ### Execution Transaction packages should be executed as follows: - -1. Deduct `TOTAL_COST` from `SENDER`'s balance -2. Execute the first inner transaction in the list -3. Refund any unused `gas` -4. Record all state changes, logs, and the receipt -5. If there are no more transaction, stop -6. Compute `RESULT` for the previously executed transaction -7. Prepare `RESULT` to be available via return opcodes in the next - transaction's first frame -8. Execute the next transaction -9. Goto `3` +1. Deduct the cumulative cost from the outer signer's balance. +2. Load the first child package, and execute the first child transaction. +3. Record all state changes, logs, the receipt, and refund any unused gas. +4. If there are no more child transactions, goto `8`. +5. Compute `Result` for the previously executed transaction. +6. Prepare `Result` to be available via return opcodes in the next + transaction's first frame. +7. Execute the next transaction, then goto `3`. +8. Load the next child package, then goto `7`. ## Rationale -#### Non-recursive inner transactions -For simplicity, inner transactions are fully defined within this EIP. However, -there is value in supporting recursive transaction definitions. For example, -suppose there is a transaction type which can become invalid after a certain -block number. It would be beneficial to support those types of transactions -within a package, but the complexity of this EIP would dramatically increase. +### Each `Child` has its own signature +For simplicity, the author has chosen to require each child package to specify +its own signature, even if the signer is the same as the package signer. This +choice is made to allow for maximum flexibility, with minimal client changes. +This transaction can still be used by a single user at the cost of only one +additional signature recovery. + +### `ChildPackage` specifies `max_gas_price` instead of `gas_price` +Allowing child packages to specify a range of acceptable gas prices is +strictly more versatile than a static price. It gives relayers more flexibility +in terms of building transaction bundles, and it makes it possible for relayers +to try and achieve the best price for the transaction sender. With a fixed +price, the relayer may require the user to sign multiple different +transactions, with varying prices. This can be avoided by specifying a max +price, and communicating out-of-band how the urgency of the transaction (e.g. +the relayer should package it with the max price immediately vs. slowly +increasing the gas price). +A future transaction type can be specified with only a single +signature, if such an optimization is desired. -#### Appending result data to transaction input data -An alternative to using return opcodes to propagate `RESULT` would be to append -the `RESULT` to the subsequent transaction's `data` field. Unfortunately, in -many cases contracts generated using Solidity [will -fail](https://solidity.readthedocs.io/en/v0.6.0/contracts.html#overload-resolution-and-argument-matching) -to resolve the intended function if additional data is present. +### `ChildPackage` is also typed +The type element serves a modest role in the transaction type, denoting whether +the transaction signer wishes to delegate control of the gas price and gas +limit to the outer signer. This is a useful UX improvement when interacting +with a trusted relayer, as once the user decides to make a transaction the +relayer can ensure it is included on chain by choosing the best gas price and +limit. + +### The `flags` and `extra` fields aren't used +These fields are included to better support future changes to the transaction +type. This would likely be used in conjunction with the `flags` and `type` +fields. A benefit of explicitly defining them is that specialized serialization +of RLP can be avoided, simplifing clients and downstream infrastructure. The +author believe the cost of 2 bytes per transaction is acceptable for smoother +integration of future features. ## Backwards Compatibility Contracts which rely on `ORIGIN (0x32) == CALLER (0x33) && RETURNDATASIZE (0x3D) == 0x00` will now always fail in transaction packages, unless they are -the first executed transaction. It's unknown if any contracts conduct this +the first executed transaction. It’s unknown if any contracts conduct this check. ## Test Cases @@ -126,7 +265,27 @@ TBD TBD ## Security Considerations -TBD +### Managing packages efficiently in the mempool +The introduction of a new transaction type brings along new concerns regarding +the mempool. Done naively, it could turn into a DDoS vector for clients. This +EIP has been written to reduce as much validation complexity as possible. + +An existing invariant in the mempool that is desirable for new transactions to +maintain, is that transactions can be validated in constant time. This is also +possible for packaged transactions. There is an inherent 10Mb limit for RLPx +frames, so that would be the upper bound on transactions that could be included +in a package. On the other hand, clients can also just configure their own +bound locally (e.g. packages must be less than 1Mb). Validity can then be +determined by using the function above. + +Once a package has been validated, it must continuously be monitored for nonce +invalidations within its package. One potential way to achieve this efficiently +is to modify the mempool to operate on thin pointers to the underlying +transaction. This will allow packages to ingest as many "single" transactions, +simplifying the facilities for monitoring changes. These "parts" of the package +can maintain a pointer to a structure with pointers to all the parts of the +package. This way, as soon as one part becomes invalid, it can request the +parent to invalidate all outstanding parts of the package. ## Copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-2746.md b/EIPS/eip-2746.md index 769c6d1b6ccd4a..fc006be63b0731 100644 --- a/EIPS/eip-2746.md +++ b/EIPS/eip-2746.md @@ -214,7 +214,7 @@ The deployer of the contract should be the owner and administrator, allowing for ## References **Standards** -- [EIP-2535 Diamond Standard](https://eips.ethereum.org/EIPS/eip-2535) +- [EIP-2535 Diamond Standard](./eip-2535.md) ## Copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-2767.md b/EIPS/eip-2767.md index d8f1461f464e35..bec3ccc440b141 100644 --- a/EIPS/eip-2767.md +++ b/EIPS/eip-2767.md @@ -7,16 +7,16 @@ status: Draft type: Standards Track category: ERC created: 2020-07-04 -requires: 165, 173, 191 +requires: 20, 165, 173 --- ## Simple Summary -A standard interface for Governance contracts that administratively decentralize the ownership of smart contracts. +A standard for Governance contracts that holds the administrative ownership of other smart contracts with voting power distributed as `ERC-20` tokens. ## Abstract -The following standard allows for the implementation of a standard API for a Governance smart contract. This standard provides basic functionality for on-chain and off-chain governance inheriting equal or privileged voting rights. Existing `ERC-173` compatible contracts can upgrade from private key wallet ownership to a Governance smart contract. Smart contracts that use a Governance contract are more administratively decentralised and adhering to a standard API enables tools to populate governance information to dApp users. +The following standard defines the implementation of a standard API for a Governance smart contract based on `ERC-20`. Existing `ERC-173` compatible contracts can upgrade from private key wallet ownership to a Governance smart contract. Adhering to a standard API enables general tools to populate governance information of various projects, thus increasing transparency. ## Motivation @@ -32,51 +32,33 @@ contract dApp { Often, such administrative rights for a contract are written for maintenance purpose but users need to trust the owner. Rescue operations by an owner have raised questions on decentralised nature of the projects. Also, there is a possibility of compromise of an owner's private key. -At present, there are various implementation ideas for handling governance. Adhering to a standard API would enable general tools (like EtherScan) to populate governance information, thus increasing transparency to users. This can result in a wide adoption for contract governance. +At present, many governance implementations by ambitious projects need users to visit a specific UI to see governance information about their project. Some examples of live implementations having different API that does the same thing are [Compound Governance](https://github.com/compound-finance/compound-protocol/blob/master/contracts/Governance/GovernorAlpha.sol#L27), [Uniswap Governance](https://github.com/Uniswap/governance/blob/master/contracts/GovernorAlpha.sol#L27) and [Sushiswap Governance](https://github.com/sushiswap/sushiswap/blob/master/contracts/GovernorAlpha.sol#L45). It's just like if the ERC-20 standard wasn't finalized, then token projects would have their own block explorer. Adhering to a standard API would enable general tools (like Etherscan) to populate governance information, thus increasing transparency to users. Using widely popular `ERC-20` token as a governance token, existing tools built to work with `ERC-20` can already display voters. This can result in a wide adoption for contract governance over private key based ownership. ## Specification -#### Notes - -- The following specifications use syntax from Solidity 0.6.0 (or above) -- Governor is the board member who has voting right. -- Power represents the voting privilege of a governor. - -A contract that is compliant with `ERC-2767` shall implement the following interface: +A Governance contract that is compliant with `ERC-2767` shall implement the following interfaces: ```solidity -/// @title ERC-2767 Governance with Privileged Voting Rights -/// @dev ERC-165 InterfaceID: 0x4fe54581 -interface ERC2767 { - /// @dev This emits when governor power changes - event GovernorPowerUpdated(address indexed governor, uint256 power); - - /// @notice Gets the consensus power of the governor - /// @param _governor Address of the governor - /// @return The governor's voting power - function powerOf(address _governor) external view returns (uint256); - - /// @notice Gets the sum of the power of all governors - /// @return Sum of the power of all governors - function totalPower() external view returns (uint256); - +/// @title ERC-2767 Governance +/// @dev ERC-165 InterfaceID: 0xd8b04e0e +interface ERC2767 is ERC165 { /// @notice Gets number votes required for achieving consensus - /// @return Required number of consensus votes - function required() external view returns (uint256); - - /// @notice Updates governor statuses - /// @param _governor Governor address - /// @param _newPower New power for the governor - /// @dev Only Governance can call - function setGovernor(address _governor, uint256 _newPower) external; + /// @dev Should cost less than 30000 gas + /// @return Required number of votes for achieving consensus + function quorumVotes() external view returns (uint256); + + /// @notice The address of the Governance ERC20 token + function token() external view returns (address); } ``` -Implementations that require equal governance rights between the governors can simply have equal power values for every governor. +### `ERC-20` Governance Token + +An `ERC-2767` Governance Contract should reference an address through `token()` that implements `ERC-20` interface. `token()` is allowed to return self address (`address(this)`), if `ERC-20` functionalities are implemented in the same contract (one can consider checking out Diamond Standard [`ERC-2535`](https://eips.ethereum.org/EIPS/eip-2535) to optimise contract size). -There is a possibility that `totalPower()` changes rapidly due to adding or removing governors. This can result in having a fixed `required()` return value easier or difficult to achieve. Implementations can have custom logic that affect the return value of `required()`. For example the return value of `required()` can be changed by custom logic in order to maintain `51%` of `totalPower()`. So if more governors are added in such implementations, the `required()` return value would automatically take that into account. +Implementations are allowed to have varying `ERC-20`'s `totalSupply()` (through any standard of minting or burning). But having a fixed `quorumVotes()` return value in this case would cause required votes consensus in `%` with respect to `totalSupply()` to change. To automatically account for this, any custom logic under `quorumVotes()` is allowed to return for e.g. `51%` of `totalSupply()`. -### Interface Identification +### `ERC-165` Interface Identification An `ERC-2767` Governance Contract should also implement `ERC-165`. This helps general tools to identify whether a contract is a `ERC-2767` Governance contract. @@ -92,129 +74,49 @@ interface ERC165 { } ``` -### Transaction execution (Optional) - -There are two optional interfaces for transaction execution: On-chain and Off-chain. A `ERC-2767` compatible governance contract can optionally implement one of them or both. The contract should specify the interfaceID(s) using `ERC-165`'s `supportsInterface` method. - -#### On-chain - -```solidity -/// @title ERC-2767 On-chain Governance -/// @dev ERC-165 InterfaceID: 0x947133b4 -interface IGovernanceOnchain { - struct Transaction { - address destination; - uint256 value; - bytes data; - bool executed; - uint256 votes; - } - - /// @dev Emits when a transaction is proposed - event TransactionCreated(uint256 indexed transactionId); - - /// @dev Emits every time a governor confirms a transaction - event TransactionConfirmed(uint256 indexed transactionId); - - /// @dev Emits whenever a governor takes back their confirmation - event TransactionRevoked(uint256 indexed transactionId); - - /// @dev Emits when a transactions with enough confirmations is executed - event TransactionExecuted(uint256 indexed transactionId); - - /// @notice Gets transaction parameters - /// @param _transactionId TransactionID - /// @return ABIV2 encoded Transaction struct - function getTransaction(uint256 _transactionId) external view returns (Transaction memory); - - /// @notice Allows an governor to submit and confirm a transaction. - /// @param _destination Transaction target address, the governed contract - /// @param _value Transaction ether value - /// @param _data Transaction data payload - /// @return Returns transaction ID - function createTransaction( - address _destination, - uint256 _value, - bytes memory _data - ) external returns (uint256); - - /// @notice Allows a governor to confirm a transaction. - /// @param _transactionId Transaction ID - function confirmTransaction(uint256 _transactionId) external; - - /// @notice Allows a governor to revoke a confirmation for a transaction - /// @param _transactionId Transaction ID - function revokeConfirmation(uint256 _transactionId) external; - - /// @notice Calls the governed contract to perform administrative task - /// @param _transactionId Transaction ID - /// @dev Only Governance can call - function executeTransaction(uint256 _transactionId) external; -} -``` - -A governor proposes a transaction by calling `createTransaction` passing the parameters. Following this, rest of the governors can choose to confirm the transaction by calling `confirmTransaction`. If at later point of time, a governor wishes to take back their vote, they can call `revokeConfirmation`. Once a transaction reaches enough confirmations, it can be executed by calling `confirmTransaction`. The `confirmTransaction` method can internally call `executeTransaction` after it's primary logic if required votes have been registered. - -#### Off-chain - -```solidity -/// @title ERC-2767 Off-chain Governance -/// @dev ERC-165 InterfaceID: 0x32542713 -interface IGovernanceOffchain { - /// @notice Get the transactions count - /// @dev To be used as nonce - /// @return The transactions count - function transactionsCount() external view returns (uint256); - - /// @notice Calls the governed contract to perform an administrative task - /// @param _nonce Serial number of transaction - /// @param _destination Address of contract to make a call to, should be governed contract address - /// @param _data Input data in the transaction - /// @param _signatures Signatures of governors collected off chain - /// @dev The signatures are required to be sorted to prevent duplicates - /// @dev Only Governance can call - function executeTransaction( - uint256 _nonce, - address _destination, - bytes memory _data, - bytes[] memory _signatures - ) external payable; -} -``` - -Anyone can take an initiative to execute a transaction by preparing a `ERC-191` signed data `0x 19 00 <20 bytes address> <32 bytes nonce> <20 bytes to-address> ` and collect signatures from required governors. The contract logic should expect signatures to be sorted, this is to save the expenditure gas to prevent duplicate signatures. If signatures are sorted, valid, and the required number of them (or more), the governance contract will make a call to the governed contract to perform the administrative task. - ## Rationale The goals of this EIP have been the following: -- standardize API of Governance contracts for governed contracts. -- enable existing `ERC-173` ownership smart contracts to become administratively decentralised. +- Standardize API of Governance contracts to make it easy for analysis tools to be built. +- Encourage use of `ERC-20` based weighted governance over existing multi-sig (_generally limited to 50 max owners_) for big projects. +- Encourage existing `ERC-173` ownership smart contracts / projects to move to Governance based ownership by removing the effort needed to host custom UI for their project. +- Encourage availability of publicly audited governance contracts, just like `ERC-20` which anyone can use. +- Make it possible to utilize existing `ERC-20` tools for owners of governance token analysis. +- Make future protocols possible that need to interact with governances of multiple projects. +- Keep this EIP minimal and allow another EIPs to standardize any specific functionalities. ## Backwards Compatibility -Smart contracts that are `ERC-173` compliant can transfer their ownership to a Governance contract. This enables existing contracts to become compatible with `ERC-2767`. +Smart contracts that are `ERC-173` compliant can transfer their ownership to a Governance contract. This enables such contracts to become compatible with `ERC-2767` Governance. + +However, there are some existing projects with governance implementations and most of them have custom APIs ([Compound Governance](https://github.com/compound-finance/compound-protocol/blob/master/contracts/Governance/GovernorAlpha.sol#L27), [Uniswap Governance](https://github.com/Uniswap/governance/blob/master/contracts/GovernorAlpha.sol#L27) and [Sushiswap Governance](https://github.com/sushiswap/sushiswap/blob/master/contracts/GovernorAlpha.sol#L45)), since a standard did not exist. Not having an `ERC-2767` compatible governance contract means only that general tools might not be able to populate their governance information without including some special code for the project. + +For existing governance contracts to get compatible with `ERC-2767`: -However, there are some existing projects with governance implementations and most of them have custom APIs, since a standard did not exist. Such projects need to deploy a new governance contract and transfer ownership to it to be `ERC-2767` compatible. Not having an `ERC-2767` compatible governance contract means only that general tools might be able to populate their governance information. +1. Projects can deploy a new governance contract and transfer ownership to it to be `ERC-2767` compatible. This is suitable for those who use Multi-sig wallets for Governance. +2. It is understood that redeploying governance contracts would be a troublesome task, and contracts who already have functionality similar to `ERC-20` based (weighted votes) have a bit advanced way to avoid it. Basically, they can create a forwarder contract implements `ERC-2767` and forwards all calls to the actual non-standard methods. Projects can list the forwarder contract to display the information project's governance info without requiring any custom code in analysys tool, but this might have certain limitations depending on the project's existing governance implementation. Specification of forwarder contract is out of scope for this EIP and it may be addressed in another EIP if required. ## Implementation -The reference implementations are available in this [repository](https://github.com/zemse/contract-ownership-governance). - -1. Governance Onchain with Equal Voting Rights ([Contract](https://github.com/zemse/contract-ownership-governance/blob/master/contracts/GovernanceOnchainEqual.sol), [Tests](https://github.com/zemse/contract-ownership-governance/blob/master/test/suites/OnchainEqual.test.ts)) -2. Governance Offchain with Privileged Voting Rights ([Contract](https://github.com/zemse/contract-ownership-governance/blob/master/contracts/GovernanceOffchainPrivileged.sol), [Tests](https://github.com/zemse/contract-ownership-governance/blob/master/test/suites/OffchainPrivileged.test.ts)) +The reference implementations are available in this [repository](https://github.com/zemse/contract-ownership-governance). Publicly audited implementations will be included in future. ## Security Considerations -The signatures in off-chain governance implementation should follow recommendations of `ERC-191`. +Implementers are free to choose between On-chain and Off-chain consensus. Exact specification is out of scope for this standard (open for other EIPs to standardize). However, this section mentions points that implementers can consider. -``` -0x 19 00 <20 bytes governance address> <32 bytes nonce> <20 bytes to-address> . -``` +#### On-chain + +In such implementations, community can create transaction proposals and vote on it by sending on-chain transactions. + +- OpenZeppelin Snapshots can be used to prevent double voting. + +#### Off-chain -To prevent repeated signatures in the `signatures` array, it is required that caller of `executeTransaction` should sort the signatures based on increasing addresses. +- The signatures in off-chain governance implementation can follow recommendations of `ERC-191` or `ERC-712`. +- To prevent replaying signatures, it'd be best if executer is required to sort the signatures based on increasing addresses. ## Copyright diff --git a/EIPS/eip-2770.md b/EIPS/eip-2770.md new file mode 100644 index 00000000000000..c8ba49abf93df8 --- /dev/null +++ b/EIPS/eip-2770.md @@ -0,0 +1,207 @@ +--- +eip: 2770 +title: Meta-Transactions Forwarder Contract +author: Alex Forshtat (@forshtat), Dror Tirosh (@drortirosh) +discussions-to: https://ethereum-magicians.org/t/erc-2770-meta-transactions-forwarder-contract/5391 +status: Draft +type: Standards Track +category: ERC +created: 2020-07-01 +requires: 712, 2771 +--- + +## Simple Summary +Standardized contract interface for extensible meta-transaction forwarding. + +## Abstract + +This proposal defines an external API of an extensible Forwarder whose responsibility is to validate transaction +signatures on-chain and expose the signer to the destination contract, that is expected to accommodate all use-cases. +The ERC-712 structure of the forwarding request can be extended allowing wallets to display readable data even +for types not known during the Forwarder contract deployment. + +## Motivation + +There is a growing interest in making it possible for Ethereum contracts to +accept calls from externally owned accounts that do not have ETH to pay for +gas. + +This can be accomplished with meta-transactions, which are transactions that have been signed as plain data by one +externally owned account first and then wrapped into an Ethereum transaction by a different account. + +`msg.sender` is a transaction parameter that can be inspected by a contract to +determine who signed the transaction. The integrity of this parameter is +guaranteed by the Ethereum EVM, but for a meta-transaction verifying +`msg.sender` is insufficient, and signer address must be recovered as well. + +The Forwarder contract described here allows multiple Gas Relays and Relay Recipient contracts to rely +on a single instance of the signature verifying code, improving reliability and security +of any participating meta-transaction framework, as well as avoiding on-chain code duplication. + +## Specification +The Forwarder contract operates by accepting a signed typed data together with it's ERC-712 signature, +performing signature verification of incoming data, appending the signer address to the data field and +performing a call to the target. + +### Forwarder data type registration +Request struct MUST contain the following fields in this exact order: +``` +struct ForwardRequest { + address from; + address to; + uint256 value; + uint256 gas; + uint256 nonce; + bytes data; + uint256 validUntil; +} +``` +`from` - an externally-owned account making the request \ +`to` - a destination address, normally a smart-contract\ +`value` - an amount of Ether to transfer to the destination\ +`gas` - an amount of gas limit to set for the execution\ +`nonce` - an on-chain tracked nonce of a transaction\ +`data` - the data to be sent to the destination\ +`validUntil` - the highest block number the request can be forwarded in, or 0 if request validity is not time-limited + +The request struct MAY include any other fields, including nested structs, if necessary. +In order for the Forwarder to be able to enforce the names of the fields of this struct, only registered types are allowed. + +Registration MUST be performed in advance by a call to the following method: +``` +function registerRequestType(string typeName, string typeSuffix) +``` +`typeName` - a name of a type being registered\ +`typeSuffix` - an ERC-712 compatible description of a type + +For example, after calling +``` +registerRequestType("ExtendedRequest", "uint256 x,bytes z,ExtraData extraData)ExtraData(uint256 a,uint256 b,uint256 c)") +``` +the following ERC-712 type will be registered with forwarder: +``` +/* primary type */ +struct ExtendedRequest { + address from; + address to; + uint256 value; + uint256 gas; + uint256 nonce; + bytes data; + uint256 validUntil; + uint256 x; + bytes z; + ExtraData extraData; +} + +/* subtype */ +struct ExtraData { + uint256 a; + uint256 b; + uint256 c; +} +``` + +### Signature verification + +The following method performs an ERC-712 signature check on a request: +``` +function verify( + ForwardRequest forwardRequest, + bytes32 domainSeparator, + bytes32 requestTypeHash, + bytes suffixData, + bytes signature +) view; +``` +`forwardRequest` - an instance of the `ForwardRequest` struct +`domainSeparator` - caller-provided domain separator to prevent signature reuse across dapps (refer to ERC-712) +`requestTypeHash` - hash of the registered relay request type +`suffixData` - RLP-encoding of the remainder of the request struct +`signature` - an ERC-712 signature on the concatenation of `forwardRequest` and `suffixData` + +### Command execution + +In order for the Forwarder to perform an operation, the following method is to be called: +``` +function execute( + ForwardRequest forwardRequest, + bytes32 domainSeparator, + bytes32 requestTypeHash, + bytes suffixData, + bytes signature +) +public +payable +returns ( + bool success, + bytes memory ret +) +``` + +Performs the ‘verify’ internally and if it succeeds performs the following call: +``` +bytes memory data = abi.encodePacked(forwardRequest.data, forwardRequest.from); +... +(success, ret) = forwardRequest.to.call{gas: forwardRequest.gas, value: forwardRequest.value}(data); +``` +Regardless of whether the inner call succeeds or reverts, the nonce is incremented, invalidating the signature and preventing a replay of the request. + +Note that `gas` parameter behaves according to EVM rules, specifically EIP-150. The forwarder validates internally that +there is enough gas for the inner call. In case the `forwardRequest` specifies non-zero value, extra `40000 gas` is +reserved in case inner call reverts or there is a remaining Ether so there is a need to transfer value from the `Forwarder`: +```solidity +uint gasForTransfer = 0; +if ( req.value != 0 ) { + gasForTransfer = 40000; // buffer in case we need to move Ether after the transaction. +} +... +require(gasleft()*63/64 >= req.gas + gasForTransfer, "FWD: insufficient gas"); +``` +In case there is not enough `value` in the Forwarder the execution of the inner call fails.\ +Be aware that if the inner call ends up transferring Ether to the `Forwarder` in a call that did not originally have `value`, this +Ether will remain inside `Forwarder` after the transaction is complete. + +### ERC-712 and 'suffixData' parameter +`suffixData` field must provide a valid 'tail' of an ERC-712 typed data. +For instance, in order to sign on the `ExtendedRequest` struct, the data will be a concatenation of the following chunks: +* `forwardRequest` fields will be RLP-encoded as-is, and variable-length `data` field will be hashed +* `uint256 x` will be appended entirely as-is +* `bytes z` will be hashed first +* `ExtraData extraData` will be hashed as a typed data + +So a valid `suffixData` is calculated as following: +``` +function calculateSuffixData(ExtendedRequest request) internal pure returns (bytes) { + return abi.encode(request.x, keccak256(request.z), hashExtraData(request.extraData)); +} + +function hashExtraData(ExtraData extraData) internal pure returns (bytes32) { + return keccak256(abi.encode( + keccak256("ExtraData(uint256 a,uint256 b,uint256 c)"), + extraData.a, + extraData.b, + extraData.c + )); +} +``` + +### Accepting Forwarded calls +In order to support calls performed via the Forwarder, the Recipient contract must read the signer address from the +last 20 bytes of `msg.data`, as described in ERC-2771. + +## Rationale +Further relying on `msg.sender` to authenticate end users by their externally-owned accounts is taking the Ethereum dapp ecosystem to a dead end. + +A need for users to own Ether before they can interact with any contract has made a huge portion of use-cases for smart contracts non-viable, +which in turn limits the mass adoption and enforces this vicious cycle. + +`validUntil` field uses a block number instead of timestamp in order to allow for better precision and integration +with other common block-based timers. + +## Security Considerations +All contracts introducing support for the Forwarded requests thereby authorize this contract to perform any operation under any account. +It is critical that this contract has no vulnerabilities or centralization issues. + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-2771.md b/EIPS/eip-2771.md index eaef4457feaa64..0ea7c33f9fe18f 100644 --- a/EIPS/eip-2771.md +++ b/EIPS/eip-2771.md @@ -149,16 +149,16 @@ contract RecipientExample { _trustedForwarder = trustedForwarder; } - function isTrustedForwarder(address forwarder) external returns(bool) { + function isTrustedForwarder(address forwarder) public returns(bool) { return forwarder == _trustedForwarder; } function _msgSender() internal view returns (address payable signer) { signer = msg.sender; - if (isTrustedForwarder(signer)) { - bytes memory data = msg.data; - uint256 length = msg.data.length; - assembly { signer := mload(add(data, length))) } + if (msg.data.length>=20 && isTrustedForwarder(signer)) { + assembly { + signer := shr(96,calldataload(sub(calldatasize(),20))) + } } } diff --git a/EIPS/eip-2786.md b/EIPS/eip-2786.md index 4da90cee8b0a99..f192d335bef354 100644 --- a/EIPS/eip-2786.md +++ b/EIPS/eip-2786.md @@ -3,7 +3,7 @@ eip: 2786 title: Ethereum Provider Connect/Disconnect Events author: Micah Zoltu (@MicahZoltu), Erik Marks (@rekmarks) discussions-to: https://github.com/ethereum/EIPs/issues/2787 -status: Last Call +status: Withdrawn review-period-end: 2020-07-31 type: Standards Track category: Interface @@ -43,7 +43,7 @@ The Provider is considered `disconnected` when it is unable to service RPC reque #### `connect` -The Provider **MUST** emit a `connect` event to all attached [EIP-2700](./eip-2700) listeners if it transitions from a `disconnected` state to a `connected` state. +The Provider **MUST** emit a `connect` event to all attached [EIP-2700](./eip-2700.md) listeners if it transitions from a `disconnected` state to a `connected` state. All attached listeners **MUST** be called with the parameter `{ chainId }`. `chainId` **MUST** specify the integer ID of the connected chain encoded as a hexadecimal string. If the Provider supports the `eth_chainId` JSON-RPC method or a derivation of it, then the `chainId` **MUST** match the return value of `eth_chainId`. diff --git a/EIPS/eip-2831.md b/EIPS/eip-2831.md index 81d229aa9acdcb..04208503a94f81 100644 --- a/EIPS/eip-2831.md +++ b/EIPS/eip-2831.md @@ -154,7 +154,7 @@ ethereum const { oldTx, newTx, nonce, from } = message.data; console.log(`Tx ${oldTx} with nonce ${nonce} from ${from} was sped up, the new hash is ${newTx}`) }); - ethereum.on('txReplacement', (info) => { + ethereum.on('tx_replacement', (info) => { const { oldTx, newTx, nonce, from } = message.data; console.log(`Tx ${oldTx} with nonce ${nonce} from ${from} was replaced, the new hash is ${newTx}`) }); diff --git a/EIPS/eip-2844.md b/EIPS/eip-2844.md index 9a3adf52180cf2..9edc9c64eed582 100644 --- a/EIPS/eip-2844.md +++ b/EIPS/eip-2844.md @@ -10,16 +10,16 @@ created: 2020-08-01 --- ## Simple Summary -Add new methods to the JSON-RPC for signing and decrypting JOSE and COSE objects under a new `did_*` prefix. +Add new methods to the JSON-RPC for signing and decrypting JOSE objects under a new `did_*` prefix. ## Abstract -This EIP describes five new methods to add to the JSON-RPC that enables wallets to support *Decentralized Identifiers* (DIDs) as well as *JSON Object Signing and Encryption* (JOSE) and *CBOR Object Signing and Encryption* (COSE). These standards enables wallets to support data decryption as well as authenticated data, both in standard formats using JOSE and COSE. With these new methods apps can request the DID from a users wallet, from which a DID document can be resolved. The DID document contains public keys that can be used for encryption and signature verification. This enables Alice to discover Bobs public keys by only knowing Bobs DID. This EIP does not enforce the user of any particular DID method or JOSE/COSE algorithms, wallets are free to implement these however they wish. +This EIP describes three new methods to add to the JSON-RPC that enables wallets to support *Decentralized Identifiers* (DIDs) as well as *JSON Object Signing and Encryption* (JOSE). These standards enables wallets to support data decryption as well as authenticated data, both in standard formats using JOSE. With these new methods apps can request the DID from a users wallet, from which a DID document can be resolved. The DID document contains public keys that can be used for encryption and signature verification. This enables Alice to discover Bobs public keys by only knowing Bobs DID. This EIP does not enforce the user of any particular DID method or JOSE algorithms, wallets are free to implement these however they wish. ## Motivation -There has been one main previous effort ([#130](https://github.com/ethereum/EIPs/issues/130), [#1098](https://github.com/ethereum/EIPs/pull/1098)) to add decryption to Ethereum wallets in a standard way. This previous approach used a non standard way to encode and represent data encrypted using `x25519-xsalsa20-poly1305`. While this approach does provide a functional way to add encryption support to wallets, it does not take into account similar work that has gone into standardizing the way encrypted data is represented, namely using [JOSE](https://datatracker.ietf.org/wg/jose/documents/) and [COSE](https://datatracker.ietf.org/wg/cose/documents/). Both of these are standards from IETF for representing signed and encrypted objects. Another shortcoming of the previous approach is that it's impossible to retrieve the `x25519` public key from another user if only an Ethereum address is known. Public key discoverability is at the core of the work that is happening with the [W3C DID standard](https://w3c.github.io/did-core), where given a DID a document which contains public keys can always be discovered. Implementations of this standard already exist and are adopted within the Ethereum community, e.g. [`did:ethr`](https://github.com/decentralized-identity/ethr-did-resolver/) and [`did:3`](https://github.com/3box/3id-resolver). Interoperability between JOSE/COSE and DIDs [already exists](https://github.com/decentralized-identity/did-jwt), and work is being done to [strengthen it](https://github.com/decentralized-identity/did-jose-extensions). Adding support for JOSE/COSE and DIDs will enable Ethereum wallets to support a wide range of new use cases such as more traditional authentication using JWTs, as well as new emerging technologies such as [Secure Data Stores](https://identity.foundation/secure-data-store/) and [encrypted data in IPFS](https://github.com/ipld/specs/pull/269). +There has been one main previous effort ([#130](https://github.com/ethereum/EIPs/issues/130), [#1098](https://github.com/ethereum/EIPs/pull/1098)) to add decryption to Ethereum wallets in a standard way. This previous approach used a non standard way to encode and represent data encrypted using `x25519-xsalsa20-poly1305`. While this approach does provide a functional way to add encryption support to wallets, it does not take into account similar work that has gone into standardizing the way encrypted data is represented, namely using [JOSE](https://datatracker.ietf.org/wg/jose/documents/). This is a standard from IETF for representing signed and encrypted objects. Another shortcoming of the previous approach is that it's impossible to retrieve the `x25519` public key from another user if only an Ethereum address is known. Public key discoverability is at the core of the work that is happening with the [W3C DID standard](https://w3c.github.io/did-core), where given a DID a document which contains public keys can always be discovered. Implementations of this standard already exist and are adopted within the Ethereum community, e.g. [`did:ethr`](https://github.com/decentralized-identity/ethr-did-resolver/) and [`did:3`](https://github.com/3box/3id-resolver). Interoperability between JOSE and DIDs [already exists](https://github.com/decentralized-identity/did-jwt), and work is being done to [strengthen it](https://github.com/decentralized-identity/did-jose-extensions). Adding support for JOSE and DIDs will enable Ethereum wallets to support a wide range of new use cases such as more traditional authentication using JWTs, as well as new emerging technologies such as [Secure Data Stores](https://identity.foundation/secure-data-store/) and [encrypted data in IPFS](https://github.com/ipld/specs/pull/269). ## Specification -Five new JSON-RPC methods are specified under the new `did_*` prefix. +Three new JSON-RPC methods are specified under the new `did_*` prefix. ### Auth @@ -33,20 +33,29 @@ Prompt the user to give permission to the current connection to access the user ##### Params: +* `nonce` - a random string used as a challenge +* `aud` - the intended audience of the authentication response * `paths` - an array of strings ##### Returns: +A JWS with general serialization containing the following properties: + +* `nonce ` - the random string which was given as a challenge + * `did` - the DID which authentication was given for * `paths` - the paths which was given permission for +* `exp` - a unix timestamp after which the JWS should be considered invalid +* `aud` - optional audience for the JWS, should match the domain which made the request +An additional property `kid` with the value which represents the DID, and the `keyFragment` that was used to sign the JWS should be added to the protected header ([details](https://github.com/decentralized-identity/did-jose-extensions/issues/2)). #### CreateJWS Creates a JSON Web Signature (JWS). -An additional property `kid` with the value which represents the DID and the key that was used to sign the JWS ([details](https://github.com/decentralized-identity/did-jose-extensions/issues/2)). +An additional property `kid` with the value which represents the DID, and the `keyFragment` that was used to sign the JWS should be added to the protected header ([details](https://github.com/decentralized-identity/did-jose-extensions/issues/2)). When `revocable` is set to false the JWS signature should not be possible to revoke. For some DID methods like. `did:key` this is always the case. For other methods which support key revocation it is necessary to include the `version-id` in the `kid` to refer to a specific version of the DID document. When `revocable` is set to true `version-id` must not be included in the `kid` for DID methods that support key revocation. ##### Method: @@ -54,39 +63,14 @@ An additional property `kid` with the value which represents the DID and the key ##### Params: -* `payload` - the payload to sign, json object -* `protected` - the protected header, json object -* `did` - the DID that should sign the message, may include the key fragment, string - -##### Returns: - -A JWS with compact serialization, string - -##### Recommendation: - -Use `secp256k1` for signing, alternatively `ed25519`. - - - -#### CreateCWS - -Creates a CBOR Web Signature (CWS). - -An additional property `kid` with the value which represents the DID and the key that was used to sign the CWS. - -##### Method: - -`did_createCWS` - -##### Params: - -* `payload` - the payload to sign, json object +* `payload` - the payload to sign, json object or `base64url` encoded string * `protected` - the protected header, json object * `did` - the DID that should sign the message, may include the key fragment, string +* `revocable` - makes the JWS revocable when rotating keys, boolean default to `false` ##### Returns: -A CWE encoded as base64, string +An object containing a JWS with general serialization on the `jws` property. ##### Recommendation: @@ -106,37 +90,12 @@ If the cleartext object contains a property `paths` that contains an array of st ##### Params: -* `jwe` - a JWE with compact serialization, string +* `jwe` - a JWE with general serialization, string * `did` - the DID that should try to decrypt the JWE, string ##### Returns: -The decrypted cleartext, object - -##### Recommendation: - -Implement decryption using `xchacha20poly1305` and `x25519` for key agreement. - - - -#### DecryptCWE - -Decrypt the given CWE. - -If the cleartext object contains a property `paths` that contains an array of strings and one of the paths in there are already authenticated using `did_authenticate` the decryption should happen without user confirmation. - -##### Method: - -`did_decryptCWE` - -##### Params: - -* `cwe` - a CWE encoded as base64, string -* `did` - the DID that should try to decrypt the CWE, string - -##### Returns: - -The decrypted cleartext, object +An object containing the cleartext, encoded using [`base64pad`](https://github.com/multiformats/multibase), assigned to the `cleartext` property. ##### Recommendation: @@ -145,17 +104,19 @@ Implement decryption using `xchacha20poly1305` and `x25519` for key agreement. ## Rationale -This EIP chooses to rely on DIDs and JOSE/COSE since there is already support for these standards in many places, by current systems and new systems. While most systems today rely on JOSE, support for COSE is also specified because it has growing support due to it's compact encoding of data. By using DIDs and JOSE/COSE wallet implementers can also choose which signing and encryption algorithms that they want to support, since these formats are faily agnostic to specific crypto implementations. +This EIP chooses to rely on DIDs and JOSE since there is already support for these standards in many places, by current systems and new systems. By using DIDs and JOSE wallet implementers can also choose which signing and encryption algorithms that they want to support, since these formats are fairly agnostic to specific crypto implementations. ### Permission system -A simple permission system is proposed where clients can request permissions though path prefixes, e.g. `/some/permission`. When decryption of a JWE/CWE is requested the wallet should check if the decrypted payload contains a `paths` property. If this property doesn't exist the user may be prompted to confirm that the given rpc connection (app) is allowed to read the decrypted data. If the `paths` property is present in the decrypted data it should contain an array of string paths. If one of the these path prefixes matches with one of the path prefixes the user has already granted permission for then decryption should happen automatically without any user confirmation. +A simple permission system is proposed where clients can request permissions though path prefixes, e.g. `/some/permission`. When decryption of a JWE is requested the wallet should check if the decrypted payload contains a `paths` property. If this property doesn't exist the user may be prompted to confirm that the given rpc connection (app) is allowed to read the decrypted data. If the `paths` property is present in the decrypted data it should contain an array of string paths. If one of the these path prefixes matches with one of the path prefixes the user has already granted permission for then decryption should happen automatically without any user confirmation. This simple permission system was inspired by some previous comments ([1](https://github.com/ethereum/EIPs/issues/130#issuecomment-329770999), [2](https://medium.com/@wighawag/3-proposals-for-making-web3-a-better-experience-974f97765700)) but avoids data lock in around origins. ## Implementation -[IdentityWallet](https://github.com/3box/identity-wallet-js/): A partial implementation of the `did_*` methods using the 3ID DID. +[IdentityWallet](https://github.com/3box/identity-wallet-js/): An implementation of the wallet side `did_*` methods using the 3ID DID. + +[key-did-provider-ed25519](https://github.com/ceramicnetwork/key-did-provider-ed25519): An implementation of the wallet side `did_*` methods using the `did:key` method. [js-did](https://github.com/ceramicnetwork/js-did): A small library which consumes the `did_*` methods. @@ -163,7 +124,7 @@ This simple permission system was inspired by some previous comments ([1](https: ## Security Considerations -Both JOSE/COSE and DIDs are standards that have gone though a lot of scrutiny. Their security will not be considered in this document. In the specification section, recommendations are given for which algorithms to use. For signatures `secp256k1` is already used by ethereum and for decryption `xchacha20poly1305` is widely available, very performant, and already used in TLS. +Both JOSE and DIDs are standards that have gone though a lot of scrutiny. Their security will not be considered in this document. In the specification section, recommendations are given for which algorithms to use. For signatures `secp256k1` is already used by ethereum and for decryption `xchacha20poly1305` is widely available, very performant, and already used in TLS. The main security consideration of this EIP is the suggested permission system. Here various threat models could be considered. However, this EIP does not go into details about how it should work other than suggesting an approach. In the end it is up to wallet implementations to choose how to ask their users for consent. diff --git a/EIPS/eip-2926.md b/EIPS/eip-2926.md index 1ddf381337ae94..70aa5b1e3f4b19 100644 --- a/EIPS/eip-2926.md +++ b/EIPS/eip-2926.md @@ -12,107 +12,91 @@ requires: 161, 170, 2584 ## Abstract -Code merkleization, along with binarification of the trie and gas cost bump of state accessing opcodes, are considered as the main levers for decreasing block witness sizes in stateless or partial-stateless Eth1x roadmaps. Here we specify a fixed-sized chunk approach to code merkleization, outline how the transition of existing contracts to this model would look like, and pose some questions to be considered. +Code merkleization, along with binarification of the trie and gas cost bump of state accessing opcodes, are considered as the main levers for decreasing block witness sizes in stateless or partial-stateless Eth1x roadmaps. Here we specify a fixed-sized chunk approach to code merkleization and outline how the transition of existing contracts to this model would look like. ## Motivation -Bytecode is currently the [second contributor](https://github.com/mandrigin/ethereum-mainnet-bin-tries-data) to block witness size, after all the proof hashes. Transitioning the trie from hexary to binary reduce the hash section of the witness by 3x, thereby making code the first contributor. By breaking contract code into chunks and committing to those chunks in a merkle tree, stateless clients would only need the chunks that were touched during a given transaction to execute it. +Bytecode is currently the [second contributor](https://github.com/mandrigin/ethereum-mainnet-bin-tries-data) to block witness size, after the proof hashes. Transitioning the trie from hexary to binary reduces the hash section of the witness by 3x, thereby making code the first contributor. By breaking contract code into chunks and committing to those chunks in a merkle tree, stateless clients would only need the chunks that were touched during a given transaction to execute it. ## Specification -This specification assumes that [EIP-2584](https://eips.ethereum.org/EIPS/eip-2584) is deployed, and the merkleization rules and gas costs are proposed accordingly. What follows is structured to have three sections: +This specification assumes that [EIP-2584](./eip-2584.md) is deployed, and the merkleization rules and gas costs are proposed accordingly. What follows is structured to have two sections: 1. How a given contract code is split into chunks and then merkleized 2. How to merkleize all existing contract codes during a hardfork -3. What EVM changes are required to account for the new way of representing code -### Constants +### Constants and Definitions + +#### Constants - `CHUNK_SIZE`: 32 (bytes) -- `KEY_LENGTH`: 4 (bytes) -- `METADATA_KEY`: `0xffffffff` -- `METADATA_VERSION`: 0 +- `KEY_LENGTH`: 2 (bytes) +- `MAX_CHUNK_COUNT`: `0xfffc` +- `VERSION_KEY`: `0xfffd` +- `CODELEN_KEY`: `0xfffe` +- `CODEHASH_KEY`: `0xffff` +- `VERSION`: 0 - `EMPTY_CODE_ROOT`: `0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470` (==`keccak256('')`) - `HF_BLOCK_NUMBER`: to be defined -### Code merkleization +#### Definitions -The procedure for merkleizing a contract code starts with splitting it into chunks. To do this assume a function that takes the bytecode as input and returns a list of chunks as output, where each chunk is a tuple `(startOffset, firstInstructionOffset, codeChunk)`. *Note that `startOffset` corresponds to the absolute program counter, and `firstInstructionOffset` is the offset within the chunk to the first instruction, as opposed to data.* This function runs in two passes: +- `BE(x, N)`: casts `x` to an unsigned integer of `N` bytes and returns its big-endian representation + +### Code merkleization -- **First Pass**: Divide the bytecode evenly into `CHUNK_SIZE` parts. The last part is allowed to be shorter. For each chunk, create the tuple, leaving `firstInstructionOffset` as `0`, and add the tuple to an array of `chunks`. Also set `chunkCount` to the total number of chunks. +For an account record `A` with code `C`, the field `A.codeHash` is replaced with `codeRoot`. `codeRoot` is `EMPTY_CODE_ROOT` if `C` is empty. Otherwise it contains the root of `codeTrie`, a [binary trie](https://hackmd.io/uCWOpSrUQaytBgcO0MVkTQ) with the following leaves: -- **Second Pass**: Scan the bytecode for instructions with immediates or multi-byte instructions (currently only `PUSHN`, opcodes `0x60 .. 0x7f`). Let `PC` be the current opcode position and `N` the number of immediate bytes following, where `N > 0`. Then: +- Key: `VERSION_KEY`, value: `BE(VERSION, 1)` +- Key: `CODELEN_KEY`, value: `BE(length(C), 4)` +- Key: `CODEHASH_KEY`, value: `keccak256(C)` - - **If** `(PC + N) % CHUNK_SIZE > PC % CHUNK_SIZE` (i.e. instruction does not cross chunk boundary), **continue** to next instruction. - - **Else**, compute the index of the chunk after the current instruction: `chunkIdx = Math.floor((PC + N + 1) / CHUNK_SIZE)`. - - **If** `chunkIdx + 1 >= chunkCount` then **break** the loop. This is to handle the following case: in a malformed bytecode, or the "data section" at the end of a Solidity contract, there could be a byte *resembeling* an instruction whose immediates exceed bytecode length. - - **Else**, assuming `nextChunk = chunks[chunkIdx]`, assign `(PC + N + 1) - nextChunk.startOffset` to `nextChunk.firstInstructionOffset`. +In addition to the above, `codeTrie` commits to a list of code `chunks = [(FIO_0, code_0), ..., (FIO_n, code_n)]` which are derived from `C` in a way that: -The `firstInstructionOffset` fields allows safe jumpdest analysis when a client doesn't have all the chunks, e.g. a stateless clients receiving block witnesses. +- `n < MAX_CHUNK_COUNT`. +- `code_0 || ... || code_n == C`. +- `length(code_i) == CHUNK_SIZE` where `0 <= i < n`. +- `length(code_n) <= CHUNK_SIZE`. +- `FIO_i` is the offset of the first instruction within the chunk. It should only be greater than zero if the last instruction in `code_i-1` is a multi-byte instruction (like `PUSHN`) crossing the chunk boundary. It is set to `CHUNK_SIZE` in the case where all bytes of a chunk are data. -To build a Merkle Patricia Tree we iterate `chunks` and process each entry, `C`, as follows: +The `i`th element of `chunks` is stored in `codeTrie` with: -- Let the MPT key `k` be `C.startOffset` in big-endian extended with zero padding on the left to reach `KEY_LENGTH`. Note that the code trie is not vulnerable to grinding attacks, and therefore the key is not hashed as in the account or storage trie. -- Let the MPT value `v` be `RLP([firstInstructionOffset, C.code])`. -- Insert `(k, v)` into the `codeTrie`. +- Key: `BE(i, KEY_LENGTH)` +- Value: `BE(FIO_i, 1) || code_i`, where `||` stands for byte-wise concatenation -We further insert a metadata leaf into `codeTrie`, with the key being `METADATA_KEY` and value being `RLP([METADATA_VERSION, codeHash, codeLength])`. This metadata is added mostly to facilitate a cheaper implementation of `EXTCODESIZE` and `EXTCODEHASH`. It includes a version to allow for differentiating between bytecode types (e.g. [EVM1.5/EIP-615](https://eips.ethereum.org/EIPS/eip-615), [EIP-2315](https://eips.ethereum.org/EIPS/eip-2315), etc.) or code merkleization schemes (or merkleization settings, such as larger `CHUNK_SIZE`) in the future. +#### Contract creation gas cost -The root of this `codeTrie` is computed according to the [EIP-2584](https://eips.ethereum.org/EIPS/eip-2584) rules (similar to the account trie) and stored in the account record, replacing the current `codeHash` field (henceforth called `codeRoot`). For accounts with empty code (including Externally-owned-Accounts aka EoAs) `codeRoot` will have the value `EMPTY_CODE_ROOT` (as opposed to empty `codeTrie` root hash) to maintain backwards compatibility. +As of now there is a charge of 200 gas per byte of the code stored in state by contract creation operations, be it initiated via `CREATE`, `CREATE2`, or an external transaction. This per byte cost is to be increased from `200` to `TBD` to account for the chunking and merkleization costs. ### Updating existing code (transition process) -The transition process involves reading all contracts in the state and apply the above procedure to them. A benchmark showing how long this process will take is still pending, but intuitively it should take longer than the time between two blocks (in the order of hours). Hence we recommend clients to pre-process the changes before the EIP is activated. +The transition process involves reading all contracts in the state and applying the above procedure to them. A benchmark showing how long this process will take is still pending, but intuitively it should take longer than the time between two blocks (in the order of hours). Hence we recommend clients to pre-process the changes before the EIP is activated. Code has the nice property that it is (mostly) static. Therefore clients can maintain a mapping of `[accountAddress -> codeRoot]` which stores the results for the contracts they have already merkleized. During this pre-computation phase, whenever a new contract is created its `codeRoot` is computed, and added to the mapping. Whenever a contract self-destructs, its corresponding entry is removed. At block `HF_BLOCK_NUMBER` when the EIP gets activated, before executing any transaction the client must update the account record for all contracts with non-empty code in the state to replace the `codeHash` field with the pre-computed `codeRoot`. EoA accounts will keep their `codeHash` value as `codeRoot`. *Accounts with empty code will keep their `codeHash` value as `codeRoot`.* -### Opcode and gas cost changes - -It is not directly a part of consensus how clients store the merkleized code. However the gas cost analysis in this section assumes a specific way of storing it. In this approach clients only merkleize code once during creation to compute `codeRoot`, but then discard the chunks. They instead store the full bytecode as well as its hash and size in the database. Otherwise the gas scheme would have to be modified to charge per chunk accessed or conservatively charge for traversing the whole code trie. We believe per-chunk metering for calls would be more easily solvable by witness metering in the stateless model. - -#### Contract creation cost - -Contract creation –– whether it is initiated via `CREATE`, `CREATE2`, or an external transaction –– will execute an *initcode*, and the bytes returned by that initcode is what becomes the account code stored in the state. As of now there is a charge of 200 gas per byte of that code stored. *We consider this cost to represent the long-term code storage cost, which could be reviewed under the "Stateless Ethereum" paradigm.* - -We introduce an additional charge to account for the chunking and merkleization cost: `(ceil(len(code) / CHUNK_SIZE) + 1) * COST_PER_CHUNK`, where `COST_PER_CHUNK` is **TBD**. We also add a new fixed charge for `COST_OF_METADATA`, which equals to the cost of `rlpEncode([0, codeHash, codeSize])`. - -The exact value of `COST_PER_CHUNK` is to be determined, but we estimate it will be on the order of `CHUNKING_COST + (2 * HASHING_COST) + (ceil(log2(NUM_CHUNKS)) * TREE_BUILDING_COST)`, where `HASHING_COST` is 36 (`Gkeccak256 + Gkeccak256_word`) and we have no estimate about `CHUNKING_COST` and `TREE_BUILDING_COST`. The hash cost could be reduced if the [EIP-2666](https://github.com/ethereum/EIPs/pull/2666) proposal is accepted. - -Preliminary cost comparison with `CHUNKING_COST=60`, `TREE_BUILDING_COST=30` and `COST_OF_METADATA=20` (note these values are *not* informed by benchmarks): - -| | Pre-EIP | Post-EIP | Increase | -|-------------|---------|----------|----------| -| 1 byte | 200 | 353 | 76.50% | -| 16000 bytes | 3200000 | 3401422 | 6.29% | -| 24576 bytes | 4915200 | 5247428 | 6.75% | - -#### CALL, CALLCODE, DELEGATECALL, STATICCALL, EXTCODESIZE, EXTCODEHASH, and EXTCODECOPY - -We expect no gas cost change. Clients have to perform the same lookup as before. +## Rationale -#### CODECOPY and CODESIZE +### Hexary vs binary trie -There should be no change to `CODECOPY` and `CODESIZE`, because the code is already in memory, and the loading cost is paid by the transaction/call which initiated it. +The Ethereum mainnet state is encoded as of now in a hexary Merkle Patricia Tree. As part of the Eth1x roadmap, a transition to a [binary trie](https://ethresear.ch/t/binary-trie-format/7621) has been [investigated](https://medium.com/@mandrigin/stateless-ethereum-binary-tries-experiment-b2c035497768) with the goal of reducing witness sizes. Because code chunks are also stored in the trie, this EIP would benefit from the witness size reduction offered by the binarification. Therefore we have decided to explicitly state [EIP-2584](./eip-2584.md) to be a requirement of this change. Note that if code merkleization is included in a hard-fork beforehand, then all code must be re-merkleized after the binary transition. -### Other remarks +### Chunk size -[EIP-161](https://eips.ethereum.org/EIPS/eip-161) defines: -> An account is considered empty when it has no code and zero nonce and zero balance. +The current recommended chunk size of 32 bytes has been selected based on a few observations. Smaller chunks are more efficient (i.e. have higher [chunk utilization](https://ethresear.ch/t/some-quick-numbers-on-code-merkelization/7260/3)), but incur a larger hash overhead (i.e. number of hashes as part of the proof) due to a higher trie depth. Larger chunks are less efficient, but incur less hash overhead. We plan to run a larger experiment comparing various chunk sizes to arrive at a final recommendation. -We replace this statement with: -> An account is considered empty when its `codeRoot` equals `EMPTY_CODE_ROOT` and has zero nonce and zero balance. +### First instruction offset -## Rationale +The `firstInstructionOffset` fields allows safe jumpdest analysis when a client doesn't have all the chunks, e.g. a stateless clients receiving block witnesses. -### Hexary vs binary trie +Note: there could be an edge case when computing FIO for the chunks where the data bytes at the end of a bytecode (last chunk) resemble a multi-byte instruction. This case can be safely ignored. -The Ethereum mainnet state is encoded as of now in a hexary Merkle Patricia Tree. As part of the Eth1x roadmap, a transition to a [binary trie](https://ethresear.ch/t/binary-trie-format/7621) has been [investigated](https://medium.com/@mandrigin/stateless-ethereum-binary-tries-experiment-b2c035497768) with the goal of reducing witness sizes. Because code chunks are also stored in the trie, this EIP would benefit from the witness size reduction offered by the binarification. Therefore we have decided to explicitly state [EIP-2584](https://eips.ethereum.org/EIPS/eip-2584) to be a requirement of this change. Note that if code merkleization is included in a hard-fork beforehand, then all code must be re-merkleized after the binary transition. +### Gas cost of code-accessing opcodes -### Rationale behind chunk size +How merkleized code is stored in the client database affects the performance of code-accessing opcodes, i.e: CALL, CALLCODE, DELEGATECALL, STATICCALL, EXTCODESIZE, EXTCODEHASH, and EXTCODECOPY. Storing the code trie with all intermediate nodes in the database implies multiple look-ups to fetch the code of the callee, which is more than the current one look-up (excluding the trie traversal to get the account) required. Note CODECOPY and CODESIZE are not affected since the code for the current contract has already been loaded to memory. -The current recommended chunk size of 32 bytes has been selected based on a few observations. Smaller chunks are more efficient (i.e. have higher [chunk utilization](https://ethresear.ch/t/some-quick-numbers-on-code-merkelization/7260/3)), but incur a larger hash overhead (i.e. number of hashes as part of the proof) due to a higher trie depth. Larger chunks are less efficient, but incur less hash overhead. We plan to run a larger experiment comparing various chunk sizes to arrive at a final recommendation. +The gas cost analysis in this section assumes a specific way of storing it. In this approach clients only merkleize code once during creation to compute `codeRoot`, but then discard the chunks. They instead store the full bytecode as well as the metadata fields in the database. We believe per-chunk metering for calls would be more easily solvable by witness metering in the stateless model. ### Different chunking logic @@ -125,31 +109,21 @@ This approach has downsides compared to the one specified: Additionally we have reviewed many other options (basic block based, Solidity subroutines (requires determining the control flow), EIP-2315 subroutines). This EIP however only focuses on the chunk-based option. -### The use of RLP +### RLP and SSZ -RLP was decided for, because it is used extensively in the data structures of Ethereum. Should there be a push for a different serialisation format, this proposal could be easily amended to use that. It must be noted that some have proposed (on the [Stateless Ethereum Call #8](https://github.com/ethereum/pm/issues/199)) to consider a different format at the same time binarification is applied to the chain. +To remain consistent with the binary transition proposal we avoid using RLP for serializing the leaf values. We have furthermore considered SSZ for both serializing data and merkleization and remain open to adopting it, but decided to use the binary trie format for simplicity. -### Alternative to the metadata +### Metadata fields -Instead of encoding `codeHash` and `codeSize` in the metadata, they could be made part of the account. In our opinion, the metadata is a more concise option, because EoAs do not need these fields, resulting in either additional logic (to omit those fields in the accounts) or calculation (to include them in merkleizing the account). +The metadata fields `version`, `codeLen` and `codeHash` are added mostly to facilitate a cheaper implementation of `EXTCODESIZE` and `EXTCODEHASH` in a stateless paradigm. The version field allows for differentiating between bytecode types (e.g. [EVM1.5/EIP-615](./eip-615.md), [EIP-2315](./eip-2315.md), etc.) or code merkleization schemes (or merkleization settings, such as larger `CHUNK_SIZE`) in future. -### Versioning - -This proposal includes a `metadataVersion` field in the metadata, which can be used to distinguish both various merklization rules, as well as bytecodes. +Instead of encoding `codeHash` and `codeSize` in the metadata, they could be made part of the account. In our opinion, the metadata is a more concise option, because EoAs do not need these fields, resulting in either additional logic (to omit those fields in the accounts) or calculation (to include them in merkleizing the account). -An alternative option would be to move this versioning to the account level: either following [EIP-1702](https://eips.ethereum.org/EIPS/eip-1702), or by adding an `accountKind` field (with potential options: `eoa`, `merkleized_evm_chunk32`, `merkleized_eip2315_chunk64`, etc.) as the first member of the account. One benefit this could provide is omitting `codeHash` for EoAs. +An alternative option to the version field would be to add an account-level field: either following [EIP-1702](./eip-1702.md), or by adding an `accountKind` field (with potential options: `eoa`, `merkleized_evm_chunk32`, `merkleized_eip2315_chunk64`, etc.) as the first member of the account. One benefit this could provide is omitting `codeHash` for EoAs. ### The keys in the code trie (and `KEY_LENGTH`) -As explained in the specification above, the keys in the code trie are bytecode offsets. Since valid bytecode offsets start at `0`, there is no natural way to represent a "special key" needed for the metadata. - -Even though the current bytecode limit is `0x6000` (as per [EIP-170](https://eips.ethereum.org/EIPS/eip-170)), we have decided to have a hard cap of `2^32-2` (influenced by [EIP-1985](https://eips.ethereum.org/EIPS/eip-1985)), which makes the proposal compatible with proposals increasing, or "lifting" the code size limit. - -Therefore it is safe to use `0xffffffff` as the key for the metadata. - -### Index-based alternative for the keys in the code trie - -Since the chunks are fixed-size, just by knowing the index of a chunk we can compute its `startOffset = chunk_idx * CHUNK_SIZE`. Therefore it's not a necessity to encode this information in the key. We are reviewing this alternative both for simplicity and potentially lower tree building costs. By using indices as keys the structure of the trie is known only given the number of chunks, which means less analysis. Additionally, the metadata could be included at index 0, removing the need for a large, fixed-size and zero-padded, key. +As explained in the specification above, the keys in the code trie are indices of the `chunks` array. Having a key length of 2 bytes means the trie can address 65536 - 3 (minus metadata fields) chunks, which corresponds to ~2Mb code size. That allows for roughly ~85x increase in the code size limit in future without requiring a change in merkleization. ### Alternate values of codeRoot for EoAs @@ -157,7 +131,7 @@ This proposal changes the meaning of the fourth field (`codeHash`) of the accoun Since `codeHash` is replaced with `codeRoot`, the root hash of the code trie, the value would be different for EoAs under the new rules: the root of the `codeTrie(metadata=[codeHash=keccak256(''), codeSize=0])`. An alternative would be simply using the hash of an empty trie. Or to avoid introducing yet another constant (the result of the above), one could also consider using `codeRoot = 0` for EoAs. -However, we wanted to maintain compatibility with [EIP-1052](https://eips.ethereum.org/EIPS/eip-1052) and decided to keep matters simple by using the hash of empty input (`c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470`) for EoAs. +However, we wanted to maintain compatibility with [EIP-1052](./eip-1052.md) and decided to keep matters simple by using the hash of empty input (`c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470`) for EoAs. ## Backwards Compatibility @@ -177,7 +151,7 @@ Show the `codeRoot` for the following cases: ## Implementation -The implementation of the chunking and merkleization logic in Typescript can be found [here](https://github.com/ewasm/biturbo/blob/merklize-mainnet-blocks/src/relayer/bytecode.ts#L172), and in Python [here](https://github.com/hugo-dc/code-chunks/blob/master/main.py). Please note neither of these examples currently use a binary tree. +The implementation of the chunking and merkleization logic in Typescript can be found [here](https://github.com/ewasm/biturbo/blob/merklize-mainnet-blocks/src/relayer/bytecode.ts#L172), and in Python [here](https://github.com/hugo-dc/code-chunks/). Please note neither of these examples currently use a binary tree. ## Security Considerations diff --git a/EIPS/eip-2929.md b/EIPS/eip-2929.md index 67fa8f8250c599..7810291ff1cebf 100644 --- a/EIPS/eip-2929.md +++ b/EIPS/eip-2929.md @@ -3,7 +3,7 @@ eip: 2929 title: Gas cost increases for state access opcodes author: Vitalik Buterin (@vbuterin), Martin Swende (@holiman) discussions-to: https://ethereum-magicians.org/t/eip-2929-gas-cost-increases-for-state-access-opcodes/4558 -status: Draft +status: Review type: Standards Track category: Core created: 2020-09-01 @@ -15,7 +15,7 @@ Increases gas cost for `SLOAD`, `*CALL`, `BALANCE`, `EXT*` and `SELFEDESTRUCT` w ## Abstract -Increase the gas cost of `SLOAD` (`0x54`) to 2100, and the `*CALL` opcode family (`0xf1`, `f2`, `f4`, `fA`), `BALANCE` `0x31` and the `EXT*` opcode family (`0x3b`, `0x3c`, `0x3f`) to 2600. Exempts (i) precompiles, and (ii) addresses and storage slots that have already been accessed in the same transaction. Additionally reforms `SSTORE` metering and `SELFDESTRUCT` to ensure "de-facto storage loads" inherent in those opcodes are priced correctly. +Increase the gas cost of `SLOAD` (`0x54`) to 2100, and the `*CALL` opcode family (`0xf1`, `f2`, `f4`, `fA`), `BALANCE` `0x31` and the `EXT*` opcode family (`0x3b`, `0x3c`, `0x3f`) to 2600. Exempts (i) precompiles, and (ii) addresses and storage slots that have already been accessed in the same transaction, which get a decreased gas cost. Additionally reforms `SSTORE` metering and `SELFDESTRUCT` to ensure "de-facto storage loads" inherent in those opcodes are priced correctly. ## Motivation @@ -62,13 +62,20 @@ When an address is either the target of a (`EXTCODESIZE` (`0x3B`), `EXTCODECOPY` * If the target is not in `accessed_addresses`, charge `COLD_ACCOUNT_ACCESS_COST` gas, and add the address to `accessed_addresses`. * Otherwise, charge `WARM_STORAGE_READ_COST` gas. -In all cases, the gas cost is charged and the map is updated at the time that the opcode is being called. When a `CREATE` or `CREATE2` opcode is called, immediately (ie. before checks are done to determine whether or not the address is unclaimed) add the address being created to `accessed_addresses`, but gas costs of `CREATE` and `CREATE2` are unchanged. +In all cases, the gas cost is charged and the map is updated at the time that the opcode is being called. +When a `CREATE` or `CREATE2` opcode is called, immediately (ie. before checks are done to determine whether or not the address is unclaimed) add the address being created to `accessed_addresses`, but gas costs of `CREATE` and `CREATE2` are unchanged. +Clarification: If a `CREATE`/`CREATE2` operation fails later on, e.g during the execution of `initcode` or has insufficient gas to store the code in the state, the `address` of the contract itself remains in `access_addresses` (but any additions made within the inner scope are reverted). For `SLOAD`, if the `(address, storage_key)` pair (where `address` is the address of the contract whose storage is being read) is not yet in `accessed_storage_keys`, charge `COLD_SLOAD_COST` gas and add the pair to `accessed_storage_keys`. If the pair is already in `accessed_storage_keys`, charge `WARM_STORAGE_READ_COST` gas. +Note: For call-variants, the `100`/`2600` cost is applied immediately (exactly like how `700` was charged before this EIP), i.e: before calculating the `63/64ths` available for entering the call. + +Note 2: There is currently no way to perform a 'cold sload read/write' on a 'cold account', simply because in order to read/write a `slot`, the execution must already be inside the `account`. Therefore, the behaviour of cold storage reads/writes on cold accounts is undefined as of this EIP. Any future EIP which +proposes to add 'remote read/write' would need to define the pricing behaviour of that change. + ### SSTORE changes -When calling `SSTORE`, check if the `(address, storage_key)` pair is in `accessed_storage_keys`. If it is not, charge an additional `COLD_SLOAD_COST` gas, and add the pair to `accessed_storage_keys`. Additionally, modify the parameters defined in [EIP 2200](https://eips.ethereum.org/EIPS/eip-2200) as follows: +When calling `SSTORE`, check if the `(address, storage_key)` pair is in `accessed_storage_keys`. If it is not, charge an additional `COLD_SLOAD_COST` gas, and add the pair to `accessed_storage_keys`. Additionally, modify the parameters defined in [EIP-2200](./eip-2200.md) as follows: | Parameter | Old value | New value | | - | - | - | @@ -76,11 +83,14 @@ When calling `SSTORE`, check if the `(address, storage_key)` pair is in `accesse | `SSTORE_RESET_GAS` | 5000 | `5000 - COLD_SLOAD_COST` | The other parameters defined in EIP 2200 are unchanged. +Note: The constant `SLOAD_GAS` is used in several places in EIP 2200, e.g `SSTORE_SET_GAS - SLOAD_GAS`. Implementations that are using composite definitions have to ensure to update those definitions too. ### SELFDESTRUCT changes If the ETH recipient of a `SELFDESTRUCT` is not in `accessed_addresses` (regardless of whether or not the amount sent is nonzero), charge an additional `COLD_ACCOUNT_ACCESS_COST` on top of the existing gas costs, and add the ETH recipient to the set. +Note: `SELFDESTRUCT` does not charge a `WARM_STORAGE_READ_COST` in case the recipient is already warm, which differs from how the other call-variants work. The reasoning behind this is to keep the changes small, a `SELFDESTRUCT` already costs `5K` and is a no-op if invoked more than once. + ## Rationale ### Opcode costs vs charging per byte of witness data diff --git a/EIPS/eip-2930.md b/EIPS/eip-2930.md index bc3ee24fbf3b68..4505879aa55643 100644 --- a/EIPS/eip-2930.md +++ b/EIPS/eip-2930.md @@ -3,7 +3,7 @@ eip: 2930 title: Optional access lists author: Vitalik Buterin (@vbuterin), Martin Swende (@holiman) discussions-to: https://ethereum-magicians.org/t/eip-2930-optional-access-lists/4561 -status: Draft +status: Review type: Standards Track category: Core created: 2020-08-29 @@ -16,7 +16,7 @@ Adds a transaction type which contains an access list, a list of addresses and s ## Abstract -We introduce a new [EIP-2718](./eip-2718.md) transaction type, with the format `rlp([3, [nonce, gasPrice, gasLimit, to, value, data, access_list, senderV, senderR, senderS]])`. +We introduce a new [EIP-2718](./eip-2718.md) transaction type, with the format `0x01 || rlp([chainId, nonce, gasPrice, gasLimit, to, value, data, access_list, yParity, senderR, senderS])`. The `access_list` specifies a list of addresses and storage keys; these addresses and storage keys are added into the `accessed_addresses` and `accessed_storage_keys` global sets (introduced in [EIP-2929](./eip-2929.md)). A gas cost is charged, though at a discount relative to the cost of accessing outside the list. @@ -29,6 +29,15 @@ This EIP serves two functions: ## Specification +### Definitions + +**`TransactionType`** `1`. See [EIP-2718](./eip-2718.md) + +**`ChainId`** The transaction only valid on networks with this `chainID`. + +**`YParity`** The parity (0 for even, 1 for odd) of the y-value of a secp256k1 signature. + + ### Parameters | Constant | Value | @@ -37,7 +46,13 @@ This EIP serves two functions: | `ACCESS_LIST_STORAGE_KEY_COST` | 1900 | | `ACCESS_LIST_ADDRESS_COST` | 2400 | -As of `FORK_BLOCK_NUMBER`, we introduce a new transaction type, with the format `rlp([3, [nonce, gasPrice, gasLimit, to, value, data, access_list, senderV, senderR, senderS]])`. The signing hash would be the hash of the RLP of the entire data structure but popping the last three items representing the signature from the inner list: `rlp([3, [nonce, gasPrice, gasLimit, to, value, data, access_list]])`. +As of `FORK_BLOCK_NUMBER`, a new [EIP-2718](./eip-2718.md) transaction is introduced with `TransactionType` `1`. + +The [EIP-2718](./eip-2718.md) `TransactionPayload` for this transaction is `rlp([chainId, nonce, gasPrice, gasLimit, to, value, data, access_list, yParity, senderR, senderS])`. + +The `yParity, senderR, senderS` elements of this transaction represent a secp256k1 signature over `keccak256(0x01 || rlp([chainId, nonce, gasPrice, gasLimit, to, value, data, access_list]))`. + +The [EIP-2718](./eip-2718.md) `ReceiptPayload` for this transaction is `rlp([status, cumulativeGasUsed, logsBloom, logs])`. For the transaction to be valid, `access_list` must be of type `[[{20 bytes}, [{32 bytes}...]]...]`, where `...` means "zero or more of the thing to the left". For example, the following is a valid access list (all hex strings would in reality be in byte representation): @@ -101,7 +116,7 @@ This is done to encourage transactions to use the access list as much as possibl This is done because it maximizes simplicity, avoiding questions of what to prevent duplication against: just between two addresses/keys in the access list, between the access list and the tx sender/recipient/newly created contract, other restrictions? Because gas is charged per item, there is no gain and only cost in including a value in the access list twice, so this should not lead to extra chain bloat in practice. -### Signature signs over the entire envelope including the wrapper +### Signature signs over the transaction type as well as the transaction data This is done to ensure that the transaction cannot be "re-interpreted" as a transaction of a different type. @@ -109,13 +124,6 @@ This is done to ensure that the transaction cannot be "re-interpreted" as a tran This EIP does make it more gas-expensive to perform "unexpected" SLOADs and account accesses. Because gas is prepaid and so does not affect fixed-gas local calls, it does not break contracts in the way that previous gas cost increases would risk. However, it does make applications that heavily rely on storage access much less economically viable. -## Test Cases -TBD - -## Implementation - -TBD - ## Security Considerations ### Access list generation diff --git a/EIPS/eip-2935.md b/EIPS/eip-2935.md index fc4a9f80fa2fc9..22383207384d50 100644 --- a/EIPS/eip-2935.md +++ b/EIPS/eip-2935.md @@ -1,9 +1,9 @@ --- eip: 2935 title: Save historical block hashes in state -author: Vitalik Buterin (@vbuterin) +author: Vitalik Buterin (@vbuterin), Tomasz Stanczak (@tkstanczak) discussions-to: https://ethereum-magicians.org/t/eip-2935-save-historical-block-hashes-in-state/4565 -status: Draft +status: Review type: Standards Track category: Core created: 2020-09-03 @@ -29,9 +29,9 @@ Additional secondary motivations include: | `FORK_BLKNUM` | TBD | | `HISTORY_STORAGE_ADDRESS` | `0xfffffffffffffffffffffffffffffffffffffffe`| -At the start of processing any block where `block.number >= FORK_BLKNUM` (ie. before processing any transactions), run `sstore(HISTORY_STORAGE_ADDRESS, block.number - 1, block.prevhash)`. +At the start of processing any block where `block.number > FORK_BLKNUM` (ie. before processing any transactions), run `sstore(HISTORY_STORAGE_ADDRESS, block.number - 1, block.prevhash)`. -When `block.number >= FORK_BLKNUM + 256`, change the logic of the `BLOCKHASH` opcode as follows: if `FORK_BLKNUM <= arg < block.number`, return `sload(HISTORY_STORAGE_ADDRESS, arg)`. Otherwise return 0. +When `block.number > FORK_BLKNUM + 256`, change the logic of the `BLOCKHASH` opcode as follows: if `FORK_BLKNUM <= arg < block.number`, return `sload(HISTORY_STORAGE_ADDRESS, arg)`. Otherwise return 0. ## Rationale diff --git a/EIPS/eip-2938.md b/EIPS/eip-2938.md index 9cb212aae2f3d8..e6c242237f55c1 100644 --- a/EIPS/eip-2938.md +++ b/EIPS/eip-2938.md @@ -75,7 +75,7 @@ Introduce some new transaction-wide global variables. These variables work simil A new opcode `NONCE (0x48)` is introduced, with gas cost `G_base`, which pushes the `nonce` of the callee onto the stack. -#### `PAYGAS (0x49)` Opcodeissues +#### `PAYGAS (0x49)` Opcode A new opcode `PAYGAS (0x49)` is introduced, with gas cost `G_base`. It takes two arguments off the stack: (top) `version_number`, (second from top) `memory_start`. In the initial implementation, it will `assert version_number == 0` and read: @@ -105,6 +105,22 @@ At the end of execution of an AA transaction, it is mandatory that `globals.tran `PAYGAS` also serves as an EVM execution _checkpoint_: if the top-level execution frame reverts after `PAYGAS` has been called, then the execution only reverts up to the point right after `PAYGAS` was called, and exits there. In that case, the contract receives no refund, and `globals.gas_limit * globals.gas_price` is transferred to the miner. +#### Replay Protection + +One of the two following approaches must be implemented to safeguard against replay attacks. + +##### Require `SET_INDESTRUCTIBLE` + +Require that contracts targeted by AA transactions begin with [EIP-2937]'s `SET_INDESTRUCTIBLE` opcode. AA transactions targeting contracts that do not begin with `SET_INDESTRUCTIBLE` are invalid, and cannot be included in blocks. + +`AA_PREFIX` would need to be modified to include this opcode. + +[EIP-2937]: ./eip-2937.md + +##### Preserve Nonce on `SELFDESTRUCT` + +The other option is to preserve contract nonces across `SELFDESTRUCT` invocations, instead of setting the nonce to zero. + #### Miscellaneous * If `CALLER (0x33)` is invoked in the first frame of @@ -190,6 +206,10 @@ In multi-tenant AA, as mentioned above, nonces are expected to become malleable This is done to allow signature checking done in validation code to validate the nonce. +### Replay Protection + +Whichever option (requiring `SET_INDESTRUCTIBLE` or modifying `SELFDESTRUCT` behavior) is necessary so that nonces cannot be reused. It must be a consensus change, and not simply part of `AA_PREFIX`, so that transaction hash uniqueness is maintained. + ### Miners refuse transactions that access external data or the target's own balance, before PAYGAS An important property of traditional transactions is that activity happening as part of transactions that originate outside of some given account X cannot make transactions whose sender is X invalid. The only state change that an outside transaction can impose on X is increasing its balance, which cannot invalidate a transaction. diff --git a/EIPS/eip-2972.md b/EIPS/eip-2972.md index b2acc9ac1b5170..4fd3ef616145ec 100644 --- a/EIPS/eip-2972.md +++ b/EIPS/eip-2972.md @@ -3,7 +3,7 @@ eip: 2972 title: Wrapped Legacy Transactions author: Micah Zoltu (@MicahZoltu) discussions-to: https://ethereum-magicians.org/t/eip-2972-wrapped-legacy-transactions/4604 -status: Draft +status: Withdrawn type: Standards Track category: Core created: 2020-09-12 @@ -16,8 +16,8 @@ Two new transaction types for wrapping legacy transactions with and without a ch ## Abstract Introduces two new [EIP-2718](./eip-2718.md) transactions that are signature compatible with legacy transactions and can be automatically upgraded by any client. -* `0x00 || yParity || r || s || 0x65000000 || rlp(nonce, gasPrice, gasLimit, to, value, data)` -* `0x01 || yParity || r || s || 0x65000000 || rlp(nonce, gasPrice, gasLimit, to, value, data, chainId, 0, 0)` +* `0x00 || ssz.serialize(yParity, r, s, rlp([nonce, gasPrice, gasLimit, to, value, data]))` +* `0x01 || ssz.serialize(yParity, r, s, rlp([nonce, gasPrice, gasLimit, to, value, data, chainId, 0, 0]))` ## Motivation We would like to eventually deprecate legacy transactions so we no longer have to retain code in the networking and signer layer that deals with them. @@ -30,18 +30,53 @@ This EIP provides a mechanism for transmitting/including transactions in a way t * `yParity` is the parity (0 for even, 1 for odd) of the `y` value of the curve point for which `r` is the `x` value in the secp256k1 signing process. ### Transactions -As of `FORK_BLOCK_NUMBER`, `0x00 || yParity || r || s || 0x65000000 || rlp(nonce, gasPrice, gasLimit, to, value, data)` will be a valid transaction where: +As of `FORK_BLOCK_NUMBER`, `0x00 || ssz.serialize(yParity, r, s, rlp([nonce, gasPrice, gasLimit, to, value, data]))` will be a valid transaction where: * the RLP encoded transaction portion is signed/processed/handled exactly the same as legacy transactions were signed/processed/handled, with the exception of the final encoding +* TODO: Hashing or Merkleizing for block transaction root -As of `FORK_BLOCK_NUMBER`, `0x01 || yParity || r || s || 0x65000000 || rlp(nonce, gasPrice, gasLimit, to, value, data, chainId, 0, 0)` will be a valid transaction where: +As of `FORK_BLOCK_NUMBER`, `0x01 || ssz.serialize(yParity, r, s, rlp([nonce, gasPrice, gasLimit, to, value, data, chainId, 0, 0]))` will be a valid transaction where: * the RLP encoded transaction portion is signed/processed/handled exactly the same as legacy transactions were signed/processed/handled, with the exception of the final encoding +* TODO: Hashing or Merkleizing for block transaction root + +The SSZ schema for both transaction types is: + ``` + Transaction[ + yParity: boolean, + r: bytes32, + s: bytes32, + signedData: bytes, + ] + ``` + +Note: `sszencode(yParity, r, s, rlp(...))` is the same as `yParity || r || s || 0x45000000 || rlp(...)` + +As of `FORK_BLOCK_NUMBER`, `rlp(nonce, gasPrice, gasLimit, to, value, data, v, r, s)` will no longer be a valid transaction in a block. ### Receipts -As of `FORK_BLOCK_NUMBER`, `0 || ssz(status, cumulativeGasUsed, logsBloom, logs)` will be a valid receipt where: +As of `FORK_BLOCK_NUMBER`, `0 || ssz.serialize(status, cumulativeGasUsed, logsBloom, logs)` will be a valid receipt where: * the `ReceiptPayload` will be generated/processed/handled exactly the same as legacy receipts were processed/handled with the exception of its encoding +* TODO: Hashing or Merkleizing for block receipt root -As of `FORK_BLOCK_NUMBER`, `1 || ssz(status, cumulativeGasUsed, logsBloom, logs)` will be a valid receipt where: +As of `FORK_BLOCK_NUMBER`, `1 || ssz.serialize(status, cumulativeGasUsed, logsBloom, logs)` will be a valid receipt where: * the `ReceiptPayload` will be generated/processed/handled exactly the same as legacy receipts were processed/handled with the exception of its encoding +* TODO: Hashing or Merkleizing for block receipt root + +The SSZ schema for both receipt types is: +``` +Log[ + address: bytes20, + topics: List[bytes32, 4], + data: List[uint8, 0xffffff], +] +Receipt[ + status: uint8, + cumulativeGasUsed: uint64, + logsBloom: BitVector[2048], + logs: List[Log, 0xffffff], +] +``` + +As of `FORK_BLOCK_NUMBER`, `rlp(status, cumulativeGasUsed, logsBloom, logs)` will no longer be a valid receipt in a block. ## Rationale ### Signature doesn't include transaction type as first signature byte @@ -57,12 +92,15 @@ In the case of legacy transactions, this was a bit of a burden since you had to EIP-155 made this process even worse by requiring the validator to further decode the `v` signature value to extract the chain ID (if present) and include that in the signed data payload. By having the signed data encoded exactly as it is signed, we make it so one can verify the transaction's signature without having to do any decoding before hand. By having the signature SSZ encoded up front, we can easily extract the signature without even having to use a decoder. -### TransactionType 0/1 0x65000000 element -`0x00 || yParity || r || s || 0x65000000 || rlp(nonce, gasPrice, gasLimit, to, value, data)` is the same as `ssz(0, yParity, r, s, rlp(nonce, gasPrice, gasLimit, to, value, data))`, which may prove convenient for some clients. It costs us 4 extra bytes on the wire (mostly zeros), but the authors deem this a worthwhile trade to be SSZ encodable/decodable. -### SSZ for receipt encoding -There is a weak consensus that RLP is not a particularly encoding scheme for hashed data partially due to its inability to be streamed. +### SSZ for serialization +There is a weak consensus that RLP is not a particularly good encoding scheme for hashed data partially due to its inability to be streamed. SSZ is almost certainly going to be included in Ethereum at some point in the future, so clients likely have access to an SSZ decoder. -For this particular case, manual decoding without a full SSZ decoder isn't too complicated, though it does require doing a bit of "pointer math" since `logs` is an array of variable length items +For this particular case, manual decoding without a full SSZ decoder isn't too complicated, though it does require doing a bit of "pointer math" since `logs` is an array of variable length items. +### Deprecating legacy transactions +By deprecating legacy transactions, we make it easier for clients as they can always deal with typed transactions in blocks. +### Max length of logs and logs data +[EIP-706](./eip-706.md) limits devp2p messages to 24 bit length, which gives us a pragmatic cap at that for any single transaction at the moment. +This number seems to far exceed what is reasonable anytime in the near future, so feels like as reasonable of a cap as any. ## Backwards Compatibility The new transactions are signature compatible with legacy transactions. diff --git a/EIPS/eip-2976.md b/EIPS/eip-2976.md index db4191530fcf45..04ad6dae9117c6 100644 --- a/EIPS/eip-2976.md +++ b/EIPS/eip-2976.md @@ -1,9 +1,9 @@ --- eip: 2976 -title: 'eth/##: Typed Transactions over Gossip' +title: 'Typed Transactions over Gossip' author: Micah Zoltu (@MicahZoltu) discussions-to: https://ethereum-magicians.org/t/eip-2976-eth-typed-transactions-over-gossip/4610 -status: Draft +status: Review type: Standards Track category: Networking created: 2020-09-13 @@ -16,7 +16,8 @@ Adds support for transmission of typed transactions over devp2p. ## Abstract [Typed Transactions](./eip-2718.md) can be sent over devp2p as `TransactionType || TransactionPayload`. The exact contents of the `TransactionPayload` are defined by the `TransactionType` in future EIPs, and clients may start supporting their gossip without incrementing the devp2p version. -If a client receives a `TransactionType` that it doesn't recognize, it should disconnect from the peer who sent it. +If a client receives a `TransactionType` that it doesn't recognize, it **SHOULD** disconnect from the peer who sent it. +Clients **MUST NOT** send new transaction types before they believe the fork block is reached. ## Motivation [EIP-2718](./eip-2718.md) introduced new transaction types for blocks (which presents itself in the makeup of a block header's transaction root and receipts root). @@ -26,23 +27,34 @@ By updating devp2p to support the gossip of Typed Transactions, we can benefit f *Note: See [EIP-2718](./eip-2718.md) for additional motivations of Typed Transactions.* ## Specification -All changes specified below apply to the `eth/TBD` protocol/version and newer. +All changes specified below apply to all protocol/versions retroactively. ### Definitions +* `||` is the byte/byte-array concatenation operator. +* `|` is the type union operator. * `DEVP2P_VERSION = TBD` * `Transaction` is either `TypedTransaction` or `LegacyTransaction` * `TypedTransaction` is a byte array containing `TransactionType || TransactionPayload` +* `TypedTransactionHash` is `keccak256(TypedTransaction)` * `TransactionType` is a positive unsigned 8-bit number between `0` and `0x7f` that represents the type of the transcation * `TransactionPayload` is an opaque byte array whose interpretation is dependent on the `TransactionType` and defined in future EIPs -* `LegacyTransaction` is an RLP encoded array of the form `[nonce, gasPrice, gasLimit, to, value, data, v, r, s]` -* `TransactionHash` is `keccak256(TypedTransaction)` or `keccak256(LegacyTransaction)` +* `LegacyTransaction` is an array of the form `[nonce, gasPrice, gasLimit, to, value, data, v, r, s]` +* `LegacyTransactionHash` is `keccak256(rlp(LegacyTransaction))` +* `TransactionId` is `keccak256(TypedTransactionHash | LegacyTransactionHash)` +* `Receipt` is either `TypedReceipt` or `LegacyReceipt` +* `TypedReceipt` is a byte array containing `TransactionType || ReceiptPayload` +* `ReceiptPayload` is an opaque byte array whose interpretation is dependent on the `TransactionType` and defined in future EIPs +* `LegacyReceipt` is an array of the form `[status, cumulativeGasUsed, logsBloom, logs]` +* `LegacyReceiptHash` is `keccak256(rlp(LegacyReceipt))` ### Protocol Behavior If a client receives a `TransactionType` it doesn't recognize via any message, it **SHOULD** disconnect the peer that sent it. If a client receives a `TransactionPayload` that isn't valid for the `TransactionType`, it **SHOULD** disconnect the peer that sent it. -Clients **SHOULD NOT** start propagating transactions of a new `TransactionType` until that transaction's fork block is reached to avoid being disconnected by their peers. +Clients **MUST NOT** send transactions of a new `TransactionType` until that transaction type's introductory fork block. + +Clients **MAY** disconnect peers who send transactions of a new `TransactionType` significantly before that transaction type's introductory fork block. ### Protocol Messages `Transactions (0x02)`: `[Transaction_0, Transaction_1, ..., Transaction_n]` @@ -58,12 +70,15 @@ Clients **SHOULD NOT** start propagating transactions of a new `TransactionType` * `UnclesList` is defined in previous versions of the devp2p specification * `TotalDifficulty` is defined in previous versions of the devp2p specification -`NewPooledTransactionHashes (0x08)`: `[TransactionHash_0, TransactionHash_1, ..., TransactionHash_n]` +`NewPooledTransactionIds (0x08)`: `[TransactionId_0, TransactionId_1, ..., TransactionId_n]` -`GetPooledTransactions (0x09)`: `[TransactionHash_0, TransactionHash_1, ..., TransactionHash_n]` +`GetPooledTransactions (0x09)`: `[TransactionId_0, TransactionId_1, ..., TransactionId_n]` `PooledTransactions (0x0a)`: `[Transaction_0, Transaction_1, ..., Transaction_n]` +`Receipts (0x10)`: `[ReceiptList_0, ReceiptList_1, ..., ReceiptList_n]` where: +* `ReceiptList` is `[Receipt_0, Receipt_1, ..., Receipt_n]` + ## Rationale ### Why not specify each transaction type at the protocol layer? We could have chosen to make the protocol aware of the shape of the transaction payloads. @@ -76,12 +91,6 @@ Also, in most cases we expect that by the time new transaction types are being s ## Backwards Compatibility Legacy transactions are still supported. -## Test Cases -TBD - -## Implementation -TBD - ## Security Considerations If a client chooses to ignore the **SHOULD** recommendation for disconnecting peers that send unknown transaction types they may be susceptible to DoS attacks. Ignoring this recommendation should be limited to trusted peers only, or other situations where the risk of DoS is extremely low. diff --git a/EIPS/eip-2980.md b/EIPS/eip-2980.md new file mode 100644 index 00000000000000..459c34858e6f1d --- /dev/null +++ b/EIPS/eip-2980.md @@ -0,0 +1,204 @@ +--- +eip: 2980 +title: Swiss Compliant Asset Token +author: Gianluca Perletti (@Perlets9), Alan Scarpellini (@alanscarpellini), Roberto Gorini (@robertogorini), Manuel Olivi (@manvel79) +discussions-to: https://github.com/ethereum/EIPs/issues/2983 +status: Draft +type: Standards Track +category: ERC +created: 2020-09-08 +requires: 20 +--- + +## Simple Summary + +An interface for asset tokens, compliant with Swiss Law and compatible with [ERC-20](./eip-20.md). + +## Abstract + +This new standard is an [ERC-20](./eip-20.md) compatible token with restrictions that comply with the following Swiss laws: the [Stock Exchange Act](../assets/eip-2980/Swiss-Confederation-SESTA.pdf), the [Banking Act](../assets/eip-2980/Swiss-Confederation-BA.pdf), the [Financial Market Infrastructure Act](../assets/eip-2980/Swiss-Confederation-FMIA.pdf), the [Act on Collective Investment Schemes](../assets/eip-2980/Swiss-Confederation-CISA.pdf) and the [Anti-Money Laundering Act](../assets/eip-2980/Swiss-Confederation-AMLA.pdf). The [Financial Services Act](../assets/eip-2980/Swiss-Confederation-FINSA.pdf) and the [Financial Institutions Act](../assets/eip-2980/Swiss-Confederation-FINIA.pdf) must also be considered. The solution achieved meet also the European jurisdiction. + +This new standard meets the new era of asset tokens (known also as "security tokens"). These new methods manage securities ownership during issuance and trading. The issuer is the only role that can manage a white-listing and the only one that is allowed to execute “freeze” or “revoke” functions. + +## Motivation + +In its ICO guidance dated February 16, 2018, FINMA (Swiss Financial Market Supervisory Authority) defines asset tokens as tokens representing assets and/or relative rights ([FINMA ICO Guidelines](../assets/eip-2980/Finma-ICO-Guidelines.pdf)). It explicitly mentions that asset tokens are analogous to and can economically represent shares, bonds, or derivatives. The long list of relevant financial market laws mentioned above reveal that we need more methods than with Payment and Utility Token. + +## 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. + +The words "asset tokens" and "security tokens" can be considered synonymous. + +Every ERC-2980 compliant contract MUST implement the ERC-2980 interface. + +### ERC-2980 (Token Contract) + +``` solidity +interface ERC2980 extends ERC20 { + + /// @dev This emits when funds are reassigned + event FundsReassigned(address from, address to, uint256 amount); + + /// @dev This emits when funds are revoked + event FundsRevoked(address from, uint256 amount); + + /// @dev This emits when an address is frozen + event FundsFrozen(address target); + + /** + * @dev getter to determine if address is in frozenlist + */ + function frozenlist(address _operator) external view returns (bool); + + /** + * @dev getter to determine if address is in whitelist + */ + function whitelist(address _operator) external view returns (bool); + +} +``` + +The ERC-2980 extends [ERC-20](./eip-20.md). Due to the indivisible nature of asset tokens, the decimals number MUST be zero. + +### Whitelist and Frozenlist + +The accomplishment of the Swiss Law requirements is achieved by the use of two distinct lists of address: the Whitelist and the Frozenlist. +Addresses can be added to one or the other list at any time by operators with special privileges, called Issuers, and described below. +Although these lists may look similar, they differ for the following reasons: the Whitelist members are the only ones who can receive tokens from other addresses. There is no restriction on the possibility that these addresses can transfer the tokens already in their ownership. +This can occur when an address, present in the Whitelist, is removed from this list, without however being put in the Frozenlist and remaining in possession of its tokens. +On the other hand, the addresses assigned to the Frozenlist, as suggested by the name itself, have to be considered "frozen", so they cannot either receive tokens or send tokens to anyone. + +Below is an example interface for the implementation of a whitelist-compatible and a frozenlist-compratible contract. + +``` solidity +Interface Whitelistable { + + /** + * @dev add an address to the whitelist + * Throws unless `msg.sender` is an Issuer operator + * @param _operator address to add + * @return true if the address was added to the whitelist, false if the address was already in the whitelist + */ + function addAddressToWhitelist(address _operator) external returns (bool); + + /** + * @dev remove an address from the whitelist + * Throws unless `msg.sender` is an Issuer operator + * @param _operator address to remove + * @return true if the address was removed from the whitelist, false if the address wasn't in the whitelist in the first place + */ + function removeAddressFromWhitelist(address _operator) external returns (bool); + +} + +Interface Freezable { + + /** + * @dev add an address to the frozenlist + * Throws unless `msg.sender` is an Issuer operator + * @param _operator address to add + * @return true if the address was added to the frozenlist, false if the address was already in the frozenlist + */ + function addAddressToFrozenlist(address _operator) external returns (bool); + + /** + * @dev remove an address from the frozenlist + * Throws unless `msg.sender` is an Issuer operator + * @param _operator address to remove + * @return true if the address was removed from the frozenlist, false if the address wasn't in the frozenlist in the first place + */ + function removeAddressFromFrozenlist(address _operator) external returns (bool); + +} +``` + +### Issuers + +A key role is played by the Issuer. This figure has the permission to manage Whitelists and Frozenlists, to revoke tokens and reassign them and to transfer the role to another address. No restrictions on the possibility to have more than one Issuer per contract. Issuers are nominated by the Owner of the contract, who also is in charge of remove the role. The possibility of nominating the Owner itself as Issuer at the time of contract creation (or immediately after) is not excluded. + +Below is an example interface for the implementation of the Issuer functionalities. + +``` solidity +Interface Issuable { + + /** + * @dev getter to determine if address has issuer role + */ + function isIssuer(address _addr) external view returns (bool); + + /** + * @dev add a new issuer address + * Throws unless `msg.sender` is the contract owner + * @param _operator address + * @return true if the address was not an issuer, false if the address was already an issuer + */ + function addIssuer(address _operator) external returns (bool); + + /** + * @dev remove an address from issuers + * Throws unless `msg.sender` is the contract owner + * @param _operator address + * @return true if the address has been removed from issuers, false if the address wasn't in the issuer list in the first place + */ + function removeIssuer(address _operator) external returns (bool); + + /** + * @dev Allows the current issuer to transfer its role to a newIssuer + * Throws unless `msg.sender` is an Issuer operator + * @param _newIssuer The address to transfer the issuer role to + */ + function transferIssuer(address _newIssuer) external; + +} +``` + +### Revoke and Reassign + +Revoke and Reassign methods allow Issuers to move tokens from addresses, even if they are in the Frozenlist. The Revoke method transfers the entire balance of the target address to the Issuer who invoked the method. The Reassign method transfers the entire balance of the target address to another address. These rights for these operations MUST be allowed only to Issuers. + +Below is an example interface for the implementation of the Revoke and Reassign functionalities. + +``` solidity +Interface RevokableAndReassignable { + + /** + * @dev Allows the current Issuer to transfer token from an address to itself + * Throws unless `msg.sender` is an Issuer operator + * @param _from The address from which the tokens are withdrawn + */ + function revoke(address _from) external; + + /** + * @dev Allows the current Issuer to transfer token from an address to another + * Throws unless `msg.sender` is an Issuer operator + * @param _from The address from which the tokens are withdrawn + * @param _to The address who receives the tokens + */ + function reassign(address _from, address _to) external; + +} +``` + +## Rationale + +There are currently no token standards that expressly facilitate conformity to securities law and related regulations. EIP-1404 (Simple Restricted Token Standard) it’s not enough to address FINMA requirements around re-issuing securities to Investors. +In Swiss law, an issuer must eventually enforce the restrictions of their token transfer with a “freeze” function. The token must be “revocable”, and we need to apply a white-list method for AML/KYC checks. + +## Backwards Compatibility + +This EIP does not introduce backward incompatibilities and is backward compatible with the older ERC-20 token standard. +This standard allows the implementation of ERC-20 functions transfer, transferFrom, approve and allowance alongside to make a token fully compatible with ERC-20. +The token MAY implement decimals() for backward compatibility with ERC-20. If implemented, it MUST always return 0. + +## Implementations + +Although an official implementation of the ERC-2980 has not been presented, in the Specifications section some interfaces have been reported which, once implemented correctly and according to the reccomandations, allow to create an asset token compliant with this ERC. + +## Security Considerations + +The security considerations mainly concern the role played by the Issuers. This figure, in fact, is not generally present in common ERC-20 tokens but has very powerful rights that allow him to move tokens without being in possession and freeze other addresses, preventing them from transferring tokens. It must be the responsibility of the owner to ensure that the addresses that receive this charge remain in possession of it only for the time for which they have been designated to do so, thus preventing any abuse. + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-2981.md b/EIPS/eip-2981.md index 71c81b85373044..54bfe0d8b007cb 100644 --- a/EIPS/eip-2981.md +++ b/EIPS/eip-2981.md @@ -1,7 +1,7 @@ --- eip: 2981 title: ERC-721 Royalty Standard -author: Zach Burks (@vexycats) +author: Zach Burks (@vexycats), James Morgan (@jamesmorgan) discussions-to: https://github.com/ethereum/EIPs/issues/2907 status: Draft type: Standards Track @@ -20,10 +20,10 @@ This extension provides even more flexibility to the [ERC-721 specification](./e ## Motivation -There are many marketplaces for NFTs and the ones that support royalties are using their own standard version of royalties that are not compatible with other marketplaces. Just as in the early days of Ethereum, smart contracts are varied by ecosystem and not compatible. This would solve that issue such that an NFT created, purchased, or sold on one marketplace, provides the royalties that the creator is entitled too, regardless of the next marketplace/ecosystem it is sold at. +There are many marketplaces for NFTs and the ones that support royalties are using their own standard version of royalties that are not easily compaitble or usable by other marketplaces. Just as in the early days of Ethereum, smart contracts are varied by ecosystem and not compatible. This would solve that issue such that an NFT created, purchased, or sold on one marketplace, provides the royalties that the creator is entitled too, regardless of the next marketplace/ecosystem it is sold at. -Many of the largest ERC-721 marketplaces have implemented a form of royalties that is not compatible across the board and therefore worthless if the NFT is sold on another marketplace, defeating the purpose of any royalty system. This standard is a proposed way to minimally implement royalties that can be accepted across any type of NFT marketplace smart contracts. This standard allows for a royalty standard to be accepted on all marketplaces - leaving the funds transfer up to the marketplace itself, and only providing a means to fetch the royalty amounts and a event to be fired off when transfer has happened. +Many of the largest ERC-721 marketplaces have implemented a form of royalties that is not compatible across the board and therefore making it much harder to enforce if the NFT is sold on another marketplace, not fulfulling the potential of any royalty system put in place. This standard is a proposed way to minimally implement royalties that can be accepted across any type of NFT marketplace smart contracts. This standard allows for a royalty standard to be accepted on all marketplaces - leaving the funds transfer up to the marketplace itself, and only providing a means to fetch the royalty amounts and a event to be fired off when transfer has happened. This extension provides even more flexibility to the [ERC-721 specification](./eip-721.md). It is possible to set a royalty amount that can be paid to the creator on any marketplace that implements this ERC. If a marketplace chooses not to implement this ERC then of course no funds are paid for secondary sales. But seeing as how most NFT marketplace have developed some sort of royalty system themselves - and all of them are singular and only work on their own contracts - there needs to be an accepted standard way of providing royalties - if the creator so chooses to set royalties on their NFTs. @@ -33,8 +33,6 @@ Without a set standard of way to do royalties, we won't have any effective means This is poor UX and easily fixed with an accepted standard. - - ## Specification The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL @@ -75,7 +73,7 @@ import "./ERC165.sol"; * @dev Implementation of royalties for 721s * */ -abstract contract Royalties is ERC165 { +interface IERC2981 is ERC165 { /* * ERC165 bytes to add to interface array - set in parent contract implementing this standard * @@ -84,19 +82,12 @@ abstract contract Royalties is ERC165 { * _registerInterface(_INTERFACE_ID_ERC721ROYALTIES); */ /** - - /** - * @notice Called to return the royalty amount that was set and only return that amount - * @notice Percentage is calculated as a fixed point with a scaling factor of 10,000, such that 100% would be the value (1000000) where, 1000000/10000 = 100. 1% * would be the value 10000/10000 = 1 - */ - function royaltyAmount(uint256 tokenId) public view returns (uint256) {} - + /** * @notice Called to return both the creator's address and the royalty percentage - this would be the main function called by marketplaces unless they specifically * need just the royaltyAmount * @notice Percentage is calculated as a fixed point with a scaling factor of 10,000, such that 100% would be the value (1000000) where, 1000000/10000 = 100. 1% * would be the value 10000/10000 = 1 */ - function royaltyInfo(uint256 tokenId) external view returns (uint256, address) {} - + function royaltyInfo(uint256 _tokenId) external returns (address receiver, uint256 amount); } diff --git a/EIPS/eip-2982.md b/EIPS/eip-2982.md new file mode 100644 index 00000000000000..3deec8f744e4f9 --- /dev/null +++ b/EIPS/eip-2982.md @@ -0,0 +1,194 @@ +--- +eip: 2982 +title: Serenity Phase 0 +author: Danny Ryan (@djrtwo), Vitalik Buterin (@vbuterin) +discussions-to: https://ethereum-magicians.org/t/serenity-phase-0-eip/4621 +status: Review +type: Informational +created: 2020-09-15 +--- + +## Simple Summary + +Serenity, aka eth2, is the [long-planned](https://blog.ethereum.org/2015/03/03/ethereum-launch-process) upgrade of Ethereum to a scalable, proof-of-stake (PoS) consensus. Specifications, development, and releases are divided into phases to iteratively manage the complexity of the upgrade. This EIP addresses Phase 0 of the release schedule. + +Early phases of eth2 are executed without any breaking consensus changes on current Ethereum mainnet. This EIP serves to document the bootstrapping of this consensus mechanism and note the path for eth2 to supplant Ethereum's current proof-of-work (PoW) consensus. + +## Abstract + +This EIP specifies Phase 0 of Serenity (eth2), a multi-phased upgrade to the consensus mechanism for Ethereum mainnet. In Phase 0, the existing PoW chain and mechanics are entirely unaffected, while a PoS chain -- the beacon chain -- is built in parallel to serve as the core of the upgraded consensus. In subsequent phases, the beacon chain is enhanced to support and secure the consensus of a number of parallel shard chains, ultimately incorporating current Ethereum mainnet as one of those shards. + +At the core of the beacon chain is a proof of stake consensus mechanism called Casper the Friendly Finality Gadget (FFG) and a fork-choice rule called Latest Message Driven Greedy Heaviest Observed Sub-Tree (LMD-GHOST). Phase 0 is centered primarily around the mechanics and incentives of validators executing these algorithms. The detailed specifications for eth2 are contained in an [independent repository](https://github.com/ethereum/eth2.0-specs) from this EIP, and safety and liveness proofs can be found in the [Combining GHOST and Casper](https://arxiv.org/abs/2003.03052) paper. To avoid duplication, this EIP just references relevant spec files and releases. + +## Motivation + +Eth2 aims to fulfill the [original vision](https://blog.ethereum.org/2015/03/03/ethereum-launch-process/) of Ethereum to support an efficient, global-scale, general-purpose transactional platform while retaining high cryptoeconomic security and decentralization. + +Today, Ethereum blocks are consistently full due to increasingly high demand for decentralized applications. Ever since the first serious spikes in adoption in 2017 (cryptokitties), the Ethereum community has consistently and vocally demanded scaling solutions. + +Since day 0 of Ethereum, the investigation and expectation in scaling solutions has been two-pronged -- scale from both Layer 1 upgrades and Layer 2 adoption. This EIP represents the start to a multi-phased rollout of the former. + +### Scaling through sharding + +As the Ethereum network and the applications built upon it have seen increasing usage over the past 5 years, blocks have become regularly full and the gas price market continues to climb. Simple increases to the block gas-limit of the current Ethereum chain are unable to account for the increase in demand of the system without inducing an unsustainably high resource burden (in the form of bandwidth, computational, and disk resources) on consumer nodes. To retain decentralization while scaling up the Ethereum network, another path must be taken. + +To provide more scale to Ethereum, while not inducing a restrictively high burden on both consumer and consensus nodes, eth2 introduces a "sharded" solution in which a number of blockchain shards -- each of similar capacity to Ethereum mainnet today -- run in parallel under a unified consensus mechanism. The core consensus (the beacon chain) and a small number of these shards can be processed via a single consumer machine, while the aggregate of the system provides much higher capacity. + +See the [Ethereum wiki sharding FAQ](https://eth.wiki/sharding/Sharding-FAQs) for an excellent introduction and discussion of scaling through sharding. + +### Decentralization and economic finality through proof-of-stake + +Since the [early days](https://blog.ethereum.org/2015/12/28/understanding-serenity-part-2-casper/) of Ethereum, proof-of-stake has been a long-awaited desideratum for the following: +* Increased decentralization of the core consensus by lowering the barrier to entry and technical requirements of participation +* Increased cryptoeconomic security via in-protocol penalties for misbehaviour and the addition of economic finality +* Elimination of the energy hungry mining of the current PoW consensus mechanism + +In addition to the above, PoS has synergies with the sharding scaling solution. Due to the random sampling requirement of sharding, PoS provides a more simple and direct access to the ["active validator set"](https://eth.wiki/sharding/Sharding-FAQs#how-do-you-actually-do-this-sampling-in-proof-of-work-and-in-proof-of-stake) than PoW and thus allows for a more direct sharded protocol construction. + +See the [Ethereum wiki proof-of-stake FAQ](https://eth.wiki/en/concepts/proof-of-stake-faqs) for an excellent introduction and discussion of proof-of-stake consensus. + +## Specification + +Phase 0 is designed to require _no breaking consensus changes_ to existing Ethereum mainnet. Instead, this is the bootstraping a new PoS consensus that can, once stable, supplant the current PoW consensus. + +Phase 0 specifications are maintained in a [repository](https://github.com/ethereum/eth2.0-specs) independent of this EIP. `SPEC_RELEASE_VERSION` release (TBD) of the specs at `SPEC_RELEASE_COMMIT` are considered the canonical Phase 0 specs for this EIP. + +This EIP provides a high level view on the Phase 0 mechanisms, especially those that are relevant to Ethereum mainnet (e.g. the deposit contract) and users (e.g. validator mechanics and eth2 issuance). The extended and low level details remain in the [specs repository](https://github.com/ethereum/eth2.0-specs). + +### Parameters + +| Parameter | Value | +| - | - | +| `SPEC_RELEASE_VERSION` | `v1.0.0` | +| `SPEC_RELEASE_COMMIT` | `579da6d2dc734b269dbf67aa1004b54bb9449784` | +| `DEPOSIT_CONTRACT_ADDRESS` | `0x00000000219ab540356cBB839Cbe05303d7705Fa` | +| `MIN_GENESIS_TIME` | `1606824000` | +| `BASE_REWARD_FACTOR` | `2**6` (64) | +| `INACTIVITY_PENALTY_QUOTIENT` | `2**26` (67,108,864) | +| `PROPORTIONAL_SLASHING_MULTIPLIER` | `1` | +| `MIN_SLASHING_PENALTY_QUOTIENT` | `2**7` (128) | + +_Note:_ Eth2 has many more [Phase 0 configuration parameters](https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/configs/mainnet/phase0.yaml) but the majority are left out of this EIP for brevity. + +### Validator deposit contract + +In Phase 0, eth2 uses a contract deployed on Ethereum mainnet -- the [Deposit Contract](https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/deposit-contract.md) -- at `DEPOSIT_CONTRACT_ADDRESS` to onboard validators into the PoS consensus of the beacon chain. + +To participate in the PoS consensus, users submit validator deposits to the deposit contract. The beacon chain comes to consensus on the state of this contract and processes new validator deposits. This uni-directional deposit mechanism is the only technical link between the two components of the system (Ethereum mainnet and beacon chain) in Phase 0. + +More on this mechanism: +* [Deposit Contract](https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/deposit-contract.md) +* [Beacon Chain -- `Deposit` processing](https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#deposits) +* [Validator -- Becoming a validator](https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/validator.md#becoming-a-validator) + +### Beacon chain and validator mechanics + +Users who choose to participate in eth2 consensus deposit ETH collateral into the [deposit contract](https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/deposit-contract.md) in order to be inducted into the beacon chain validator set. From there, these validators are responsible for constructing the **beacon chain** (note that these consensus participants in PoS are akin to miners in PoW). + +The beacon chain is a pure PoS chain that in Phase 0 is primarily concerned with maintaining its own consensus and managing the registry of validators. The consensus rules define _roles_ (e.g. block proposal, block attesting) that validators are expected to participate in; validators who perform their roles well are rewarded, and validators who perform their roles poorly or are offline are penalized. Phase 0 does not yet include any ETH transfer, sharding or smart contract / VM execution capabilities. + +In subsequent phases, additional mechanisms and validator responsibilities will be added to the beacon chain to manage the consensus of a number of parallel shard chains ("Phase 1"), to integrate the existing Ethereum system ("Phase 1.5") and to add full support for sharded smart contract execution ("Phase 2"). + +More on the beacon chain and validator mechanics: +* [Beacon Chain -- State transition function](https://github.com/ethereum/eth2.0-specs/blob/dev/specs/phase0/beacon-chain.md#beacon-chain-state-transition-function) +* [Beacon chain -- Operations](https://github.com/ethereum/eth2.0-specs/blob/dev/specs/phase0/beacon-chain.md#operations) +* [Beacon chain -- Rewards and Penalties](https://github.com/ethereum/eth2.0-specs/blob/dev/specs/phase0/beacon-chain.md#rewards-and-penalties-1) +* [Validator -- Beacon chain responsibilities](https://github.com/ethereum/eth2.0-specs/blob/dev/specs/phase0/validator.md#beacon-chain-responsibilities) + +### Issuance + +To incentivize validators to deposit ether collateral and participate in the eth2 consensus, we propose that rewards (in the form of Ethereum's native asset, ether) be regularly issued to consensus participants. Due to the beacon chain operating in parallel to the existing PoW chain in early phases of eth2, this issuance is _in addition to_ any PoW rewards until the existing chain is merged into eth2 as a shard. + +The amount of ether issued to validators on the beacon chain is proportional to the square root of the total ether deposited. This issuance curve was chosen as a more stable and sustainable curve to the two obvious alternatives -- fixed total issuance and fixed issuance per ether staked. For a more technical discussion on this choice see [here](https://github.com/ethereum/research/blob/master/papers/discouragement/discouragement.pdf). + +In eth2, this curve is parameterized by `BASE_REWARD_FACTOR` in the context of slot time and epoch length. Below is the issuance curve as a function of ether staked, along with a table of examples for illustration. Note, all figures shown are annualized. + +![](https://storage.googleapis.com/ethereum-hackmd/upload_953c502d09928c0b306cc078268945c1.png) + +| Active Deposits | Max Annual Validator Reward\* | Max Annual ETH Issued\* | +| -------- | -------: | --------: | +| 0.5M ETH | 23.50% | 117,527 | +| 1M ETH | 16.60% | 166,208 | +| 2M ETH | 11.75% | 235,052 | +| 4M ETH | 8.31% | 332,411 | +| 8M ETH | 5.88% | 470,104 | +| 16M ETH | 4.16% | 664,801 | +| 32M ETH | 2.94% | 940,167 | +| 64M ETH | 2.08% | 1,329,603 | +| 128M ETH | 1.47% | 1,880,334 | + +_\*Assuming validators are online 100% of the time and behaving optimally. Suboptimal validator behavior will lead to reduced rewards and/or penalties that reduce total issuance._ + +For more details, see this [eth2 calculator](https://docs.google.com/spreadsheets/d/15tmPOvOgi3wKxJw7KQJKoUe-uonbYR6HF7u83LR5Mj4/edit#gid=842896204) maintained by _ConsenSys Activate_. + +### Initial punitive parameters + +For PoS protocols to be crypto-economically secure, in-protocol penalties are required (see discussion of ["Nothing at Stake"](https://blog.ethereum.org/2014/11/25/proof-stake-learned-love-weak-subjectivity/)). Small offline penalties incentivize validator liveness, whereas (potentially) much larger penalties provide protocol security in the event of tail-risk scenarios. + +Specifically, the following significant penalties exist: +* **Inactivity Leak**: an offline penalty that increases each epoch is applied to validators during extended times of no finality (e.g. if one-third or more are offline or not on the canonical chain). This ensures the chain can eventually regain finality even under catastrophic conditions. +* **Slashing**: a penalty applied to validators that sign _explicitly malicious_ messages that could lead to the construction and finalization of two conflicting chains (e.g. two blocks or attestations in the same slot). This penalty is designed to scale up in proportion to the number of slashable validators in the same time period such that if a critical number (wrt chain safety) of slashings have occurred, validators are _maximally_ punished. + +For the initial launch of Phase 0, the parameters defining the magnitude of these penalties -- `INACTIVITY_PENALTY_QUOTIENT`, `PROPORTIONAL_SLASHING_MULTIPLIER`, and `MIN_SLASHING_PENALTY_QUOTIENT` -- have been tuned to be less punitive than their final intended values. This provides a more forgiving environment for early validators and client software in an effort to encourage validation in this early, higher technical-risk stage. + +_`INACTIVITY_PENALTY_QUOTIENT` is configured initially to four times its final value_. This results in a slower inactivity leak during times of non-finality, which means the chain is less responsive to such an event. If there is an extended time of non-finality during the early months of eth2, it is far more likely to be due to technical issues with client software rather than some sort of global catastrophic event. + +_`PROPORTIONAL_SLASHING_MULTIPLIER` is configured initially to one-third of its final value_. This results in a lower accountable safety margin in the event of an attack. If any validators are slashed in the early months of eth2, it is far more likely to be the result of user mismanagement of keys and/or issues with client software than an organized attack. + +_`MIN_SLASHING_PENALTY_QUOTIENT` configured initially to four times its final value_. This results in a lower guaranteed minimum penalty for a slashable offense and thus reduces the baseline punitive incentive to keep an individual validator's system secure. As with `PROPORTIONAL_SLASHING_MULTIPLIER`, slashings during the early months of eth2 are far more likely to be due to user mismanagement, or issues with client software, than an organized attack. + +___A hard fork of the eth2 beacon chain is planned for 5 months after genesis. This hard fork will adjust `INACTIVITY_PENALTY_QUOTIENT`, `PROPORTIONAL_SLASHING_MULTIPLIER`, and `MIN_SLASHING_PENALTY_QUOTIENT` to their final, more secure values.___ + +## Rationale + +For details regarding specification design rationale and decisions, see the following: +* [Serenity Design Rationale](https://notes.ethereum.org/@vbuterin/rkhCgQteN) +* [Ben Edgington's Eth2 Annotated Spec](https://benjaminion.xyz/eth2-annotated-spec/) +* [Vitalik Buterin's Eth2 Annotated Spec](https://github.com/ethereum/annotated-spec/blob/master/phase0/beacon-chain.md) + +## Backwards Compatibility + +Although this EIP does not introduce any immediate changes to the current Ethereum mainnet, this EIP lays the groundwork for future backwards incompatibilities through the introduction of the new eth2 consensus mechanism in which Ethereum will be integrated in subsequent phases. To secure this mechanism, users move ether into the beacon chain and additional ether is issued. This EIP is a commitment to this path being canonical, as well as directly informing the future and roadmap of Ethereum mainnet. + +## Implementation + +The following implementations of eth2 Phase 0 exist. At the time of writing at least five are near production-ready and in testnet/audit phase: + +* [Cortex](https://github.com/NethermindEth/cortex) (.net) +* [Lighthouse](https://github.com/sigp/lighthouse) (rust) +* [Lodestar](https://github.com/ChainSafe/lodestar) (javascript) +* [Nimbus](https://github.com/status-im/nim-beacon-chain) (nim) +* [Prysm](https://github.com/prysmaticlabs/prysm/) (go) +* [Teku](https://github.com/pegasyseng/teku) (java) +* [Trinity](https://github.com/ethereum/trinity/) (python) + +In addition to implementations of the spec, the deposit contract is [implemented in Solidity](), along with a [formal verification](https://github.com/runtimeverification/verified-smart-contracts/blob/master/deposit/deposit-formal-verification.pdf) of the bytecode. + +## Security Considerations + +Eth2 is a major overhaul of the Ethereum's core consensus from PoW to a sharded PoS. There are inherent risks in this migration but there is extensive research literature analyzing security and trade-offs. _The following only represents a high level selection of the resources available:_ + +* [Casper FFG](https://arxiv.org/abs/1710.09437) +* [Combining GHOST and Casper](https://arxiv.org/abs/2003.03052) +* [Sharding FAQ](https://eth.wiki/sharding/Sharding-FAQs) +* [PoS FAQ](https://eth.wiki/en/concepts/proof-of-stake-faqs) +* [Eth2 research compendium](https://notes.ethereum.org/@serenity/H1PGqDhpm?type=view) + +In addition to the research supporting this path, a number of audits and formal verification of specs, cryptography, and client implementations have been performed. _Many client and utility library audits are currently in progress and will be appended here upon completion._ + +* [Eth2 Phase 0 Spec audit by Least Authority](https://leastauthority.com/blog/ethereum-2-0-specifications/) +* [Gossipsub v1.1 audit by Least Authority](https://leastauthority.com/blog/audit-of-gossipsub-v1-1-protocol-design-implementation-for-protocol-labs/) +* [Discv5 audit by Least Authority](https://leastauthority.com/blog/audit-of-gossipsub-v1-1-protocol-design-implementation-for-protocol-labs/) +* [Formal Verification of Finality in eth2 by Runtime Verification](https://runtimeverification.com/blog/formally-verifying-finality-in-gasper-the-core-of-the-beacon-chain/) +* [Formal Verification of Deposit Contract by Runtime Verification](https://github.com/runtimeverification/deposit-contract-verification/blob/master/deposit-contract-verification.pdf) +* [Prysm client audit by Quantstamp](https://quantstamp.com/blog/ethereum-2-0-moves-closer-to-launch-with-quantstamp-audit-of-prysm) and [the results](https://medium.com/prysmatic-labs/quantstamp-security-audit-results-for-the-prysm-eth2-client-7f949c6c866f) +* [Lodestar utility libraries audit by Least Authority](https://leastauthority.com/blog/audit-of-chainsafe-utility-libraries/) + +Finally, the EF maintains bounty programs for the eth2 spec, attacknets, and clients. + +* [Eth2 Phase 0 bug bounty program](https://notes.ethereum.org/@djrtwo/phase0-bounty) +* [Eth2 public attacknets](https://github.com/ethresearch/public-attacknets) +* _Eth2 Client Bounty Program to be released soon_ + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-2997.md b/EIPS/eip-2997.md new file mode 100644 index 00000000000000..13197c2f4e0d90 --- /dev/null +++ b/EIPS/eip-2997.md @@ -0,0 +1,103 @@ +--- +eip: 2997 +title: IMPERSONATECALL Opcode +author: Sergio Demian Lerner (@SergioDemianLerner) +discussions-to: https://ethresear.ch/t/impersonatecall-opcode/8020 +category: Core +type: Standards Track +status: Draft +created: 2020-09-24 +--- + +## Abstract + +Add a new opcode, `IMPERSONATECALL` at `0xf6`, which is similar in idea to `CALL (0xF1)`, except that it impersonates a sender, i.e. the callee sees a sender different from the real caller. The impersonated sender address is derived from the real caller address and a salt. + +## Motivation + +This proposal enables native multi-user wallets (wallets that serve multiple users) that can be commanded by EIP-712 based messages and therefore enable meta-transactions. Multi-user wallets also enable the aggregation of transfer operations in batches similar to rollups, but maintaining the same address space as normal onchain transactions, so the sender's wallet does not need to be upgraded to support sinding ether or tokens to a user of a multi-user wallet. +Additionally, many times a sponsor company wants to deploy non-custodial smart wallets for all its users. The sponsor does not want to pay the deployment cost of each user contract in advance. Counterfactual contract creation enables this, yet it forces the sponsor to create the smart wallet (or a proxy contract to it) when the user wants to transfer ether or tokens out of his/her account for the first time. This proposal avoids this extra cost, which is at least 42000 gas per user. + + +## Specification + +`IMPERSONATECALL`: `0xf6`, takes 7 operands: + +- `gas`: the amount of gas the code may use in order to execute; +- `to`: the destination address whose code is to be executed; +- `in_offset`: the offset into memory of the input; +- `in_size`: the size of the input in bytes; +- `ret_offset`: the offset into memory of the output; +- `ret_size`: the size of the scratch pad for the output. +- `salt` is a `32` bytes value (a stack item). + +### Computation of impersonated sender + +The impersonated sender address is computed as `keccak256( 0xff ++ address ++ salt ++ zeros32)[12:]`. + +- `0xff` is a single byte, +- `address` is always `20` bytes, and represents the address of the real caller contract. +- `salt` is always `32` bytes. + +- The field zeros32 corresponds to 32 zero bytes. + +This scheme emulates `CREATE2` address derivation, but it cannot practically collude with the `CREATE2` address space. + +### Notes +- The opcode behaves exactly as `CALL` in terms of gas consumption. +- In the called context `CALLER (0x33)` returns the impersonated address. +- If value transfer is non-zero in the call, the value is transferred from the impersonated account, and not from the real caller. This can be used to transfer ether out of an impersonated account. + +## Rationale + +Even if `IMPERSONATECALL` requires hashing 3 words, implying an additional cost of 180 gas, we think the benefit of accounting for hashing doesn't not compensate increasing the complexity of the implementation. + +We use the zeros32 field to base address derivation in a pre-image of similar size than CREATE2 and reuse the existing address derivation functions. We also avoid worrying about address collisions between EOA derivation (65 bytes pre-image), CREATE derivation (from 23 to 27 bytes pre-image, for a 32bit nonce) and CREATE2 derivation (85 bytes pre-image). + +An option is to omit the zeros32 field: the resulting length of the Keccak pre-image for IMPERSONATECALL address is 53 bytes , which does not generate address collision. + +While the same functionality could be provided in a pre-compiled contract, we believe using a new opcode is a cleaner solution. + + +## Clarifications + +- This EIP makes address collisions possible, yet practically impossible. + +- If a contract already exists with an impersonated address, the `IMPERSONATECALL` is executed in the same way, and the existing code will not be executed. It should be noted that `SELFDESTRUCT` (`0xff`) cannot be executed directly with `IMPERSONATECALL` as no opcode is executed in the context of the impersonated account. + +## Backward Compatibility + +The opcode number `0xf6` is currently unused and results in an out-of-gas (OOG) exception. Solidity uses the `INVALID (0xfe)` opcode (called `ABORT` by EIP-1803) to raise OOG exceptions, so the `0xf6` opcode does not appear in normal Solidity programs. Programmers are already advised not to include this opcode in contracts written in EVM assembly. Therefore is does not pose any backward compatibility risk. + +## Test Cases + +We present 4 examples of impersonated address derivation: + +Example 0 + +* address `0x0000000000000000000000000000000000000000` +* salt `0x0000000000000000000000000000000000000000000000000000000000000000` +* result: `0xFFC4F52F884A02BCD5716744CD622127366F2EDF` + +Example 1 +* address `0xdeadbeef00000000000000000000000000000000` +* salt `0x0000000000000000000000000000000000000000000000000000000000000000` +* result: `0x85F15E045E1244AC03289B48448249DC0A34AA30` + +Example 2 +* address `0xdeadbeef00000000000000000000000000000000` +* salt `0x000000000000000000000000feed000000000000000000000000000000000000` +* result: `0x2DB27D1D6BE32C9ABFA484BA3D591101881D4B9F` + +Example 3 +* address `0x00000000000000000000000000000000deadbeef` +* salt `0x00000000000000000000000000000000000000000000000000000000cafebabe` +* result: `0x5004E448F43EFE3C7BF32F94B83B843D03901457` + +## Security Considerations + +The address derivation scheme prevents address collision with another deployed contract or an externally owned account, as the impersonated sender address is derived from the real caller address and a salt. + +## 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 842e3e3d6c0f49..3d7c9699847ea7 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: Abandoned +status: Withdrawn type: Standards Track category: Core created: 2015-11-19 diff --git a/EIPS/eip-3000.md b/EIPS/eip-3000.md new file mode 100644 index 00000000000000..9f3f17c5799725 --- /dev/null +++ b/EIPS/eip-3000.md @@ -0,0 +1,154 @@ +--- +eip: 3000 +title: Optimistic enactment governance standard +author: Jorge Izquierdo (@izqui), Fabien Marino (@bonustrack) +discussions-to: https://github.com/ethereum/EIPs/issues/3042 +status: Draft +type: Standards Track +category: ERC +created: 2020-09-24 +--- + +## Simple Summary + +Interface for scheduling, executing and challenging contract executions based on off-chain approval + +## Abstract + +ERC-3000 presents a basic on-chain spec for contracts to optimistically enact governance decisions made off-chain. + +The standard is opinionated in defining the 6 entrypoint functions to contracts supporting the standard. But it allows for any sort of resolver mechanism for the challenge/response games characteristic of optimistic contracts. + +While the authors currently believe resolving challenges [using a subjective oracle](https://aragon.org/blog/snapshot) is the right tradeoff, the standard has been designed such that changing to another mechanism is possible (a deterministic resolver like [Optimism's OVM](https://optimism.io) uses), even allowing to hot-swap it in the same live instance. + +## Specification + +### Data structures + +Some data structures are defined which are later used in the standard interfaces: + +```solidity +library ERC3000Data { + struct Container { + Payload payload; + Config config; + } + + struct Payload { + uint256 nonce; + uint256 executionTime; + address submitter; + IERC3000Executor executor; + Action[] actions; + bytes proof; + } + + struct Action { + address to; + uint256 value; + bytes data; + } + + struct Config { + uint256 executionDelay; + Collateral scheduleDeposit; + Collateral challengeDeposit; + Collateral vetoDeposit; + address resolver; + bytes rules; + } + + struct Collateral { + address token; + uint256 amount; + } +} +``` + +### Interface and events + +Given the data structures above, by taking advantage of the Solidity ABI encoder v2, we define four required functions and two optional functions as the interface for contracts to comply with ERC-3000. + +All standard functions are expected to revert (whether to include error messages/revert reasons as part of the standard is yet to be determined) when pre-conditions are not met or an unexpected error occurs. On success, each function must emit its associated event once and only once. + +```solidity +abstract contract IERC3000 { + /** + * @notice Schedules an action for execution, allowing for challenges and vetos on a defined time window + * @param container A Container struct holding both the paylaod being scheduled for execution and + the current configuration of the system + */ + function schedule(ERC3000Data.Container memory container) virtual public returns (bytes32 containerHash); + event Scheduled(bytes32 indexed containerHash, ERC3000Data.Payload payload, ERC3000Data.Collateral collateral); + + /** + * @notice Executes an action after its execution delayed has passed and its state hasn't been altered by a challenge or veto + * @param container A ERC3000Data.Container struct holding both the paylaod being scheduled for execution and + the current configuration of the system + * should be a MUST payload.executor.exec(payload.actions) + */ + function execute(ERC3000Data.Container memory container) virtual public returns (bytes[] memory execResults); + event Executed(bytes32 indexed containerHash, address indexed actor, bytes[] execResults); + + /** + * @notice Challenge a container in case its scheduling is illegal as per Config.rules. Pulls collateral and dispute fees from sender into contract + * @param container A ERC3000Data.Container struct holding both the paylaod being scheduled for execution and + the current configuration of the system + * @param reason Hint for case reviewers as to why the scheduled container is illegal + */ + function challenge(ERC3000Data.Container memory container, bytes memory reason) virtual public returns (uint256 resolverId); + event Challenged(bytes32 indexed containerHash, address indexed actor, bytes reason, uint256 resolverId, ERC3000Data.Collateral collateral); + + /** + * @notice Apply arbitrator's ruling over a challenge once it has come to a final ruling + * @param container A ERC3000Data.Container struct holding both the paylaod being scheduled for execution and + the current configuration of the system + * @param resolverId disputeId in the arbitrator in which the dispute over the container was created + */ + function resolve(ERC3000Data.Container memory container, uint256 resolverId) virtual public returns (bytes[] memory execResults); + event Resolved(bytes32 indexed containerHash, address indexed actor, bool approved); + + /** + * @dev OPTIONAL + * @notice Apply arbitrator's ruling over a challenge once it has come to a final ruling + * @param payloadHash Hash of the payload being vetoed + * @param config A ERC3000Data.Config struct holding the config attached to the payload being vetod + */ + function veto(bytes32 payloadHash, ERC3000Data.Config memory config, bytes memory reason) virtual public; + event Vetoed(bytes32 indexed containerHash, address indexed actor, bytes reason, ERC3000Data.Collateral collateral); + + /** + * @dev OPTIONAL: implementer might choose not to implement (initial Configured event MUST be emitted) + * @notice Apply a new configuration for all *new* containers to be scheduled + * @param config A ERC3000Data.Config struct holding all the new params that will control the queue + */ + function configure(ERC3000Data.Config memory config) virtual public returns (bytes32 configHash); + event Configured(bytes32 indexed containerHash, address indexed actor, ERC3000Data.Config config); +} +``` + +## Rationale + +The authors believe that it is very important that this standard leaves the other open to any resolver mechanism to be implemented and adopted. + +That's why a lot of the function and variable names were left intentionally bogus to be compatible with future resolvers without changing the standard. + +ERC-3000 should be seen as a public good of top of which public infrastrastructure will be built, being way more important than any particular implementation or the interests of specific companies or projects. + +## Security Considerations + +The standard allows for the resolver for challenges to be configured, and even have different resolvers for coexisting scheduled payloads. Choosing the right resolver requires making the right tradeoff between security, time to finality, implementation complexity, and external dependencies. + +Using a subjective oracle as resolver has its risks, since security depends on the crypto-economic properties of the system. For an analysis of crypto-economic considerations of Aragon Court, you can check [the following doc](https://github.com/aragon/aragon-court/tree/master/docs/3-cryptoeconomic-considerations). + +On the other hand, implementing a deterministic resolver is prone to dangerous bugs given its complexity, and will rely on a specific version of the off-chain protocol, which could rapidly evolve while the standard matures and gets adopted. + +## Implementations + +### 1. Aragon Govern + +- [ERC-3000 interface (MIT license)](https://github.com/aragon/govern/blob/master/packages/erc3k) +- [Implementation (GPL-3.0 license)](https://github.com/aragon/govern/blob/master/packages/govern-core) + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-3005.md b/EIPS/eip-3005.md new file mode 100644 index 00000000000000..58c8b85e9f63ee --- /dev/null +++ b/EIPS/eip-3005.md @@ -0,0 +1,416 @@ +--- +eip: 3005 +title: Batched meta transactions +author: Matt (@defifuture) +discussions-to: https://ethereum-magicians.org/t/eip-3005-the-economic-viability-of-batched-meta-transactions/4673 +status: Draft +type: Standards Track +category: ERC +created: 2020-09-25 +--- + +## Simple Summary + +Defines an extension function for ERC-20 (and other fungible token standards), which allows receiving and processing a batch of meta transactions. + +## Abstract + +This EIP defines a new function called `processMetaBatch()` that extends any fungible token standard, and enables batched meta transactions coming from many senders in one on-chain transaction. + +The function must be able to receive multiple meta transactions data and process it. This means validating the data and the signature, before proceeding with token transfers based on the data. + +The function enables senders to make gasless transactions, while reducing the relayer's gas cost due to batching. + +## Motivation + +Meta transactions have proven useful as a solution for Ethereum accounts that don't have any ether, but hold ERC-20 tokens and would like to transfer them (gasless transactions). + +The current meta transaction relayer implementations only allow relaying one meta transaction at a time. Some also allow batched meta transactions from the same sender. But none offers batched meta transactions from **multiple** senders. + +The motivation behind this EIP is to find a way to allow relaying batched meta transactions from **many senders** in **one on-chain transaction**, which also **reduces the total gas cost** that a relayer needs to cover. + +![](../assets/eip-3005/meta-txs-directly-to-token-smart-contract.png) + +## 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. + +The key words "MUST (BUT WE KNOW YOU WON'T)", "SHOULD CONSIDER", "REALLY SHOULD NOT", "OUGHT TO", "WOULD PROBABLY", "MAY WISH TO", "COULD", "POSSIBLE", and "MIGHT" in this document are to be interpreted as described in RFC 6919. + +### Meta transaction data + +In order to successfully validate and transfer tokens, the `processMetaBatch()` function MUST process the following data about a meta transaction: + +- sender address +- receiver address +- token amount +- relayer fee +- a (meta tx) nonce +- an expiration date (this COULD be a block number, or it COULD be a block timestamp) +- a token address +- a relayer address +- a signature + +Not all of the data needs to be sent to the function by the relayer (see the function interface specification). Some of the data can be deduced or extracted from other sources (from transaction data and contract state). + +### `processMetaBatch()` function input data + +The `processMetaBatch()` function MUST receive the following data: + +- sender address +- receiver address +- token amount +- relayer fee +- an expiration date (this COULD be a block number, or it COULD be a block timestamp) +- a signature + +The following data is OPTIONAL to be sent to the function, because it can be extracted or derived from other sources: + +- a (meta tx) nonce +- a token address +- a relayer address + +### Meta transaction data hash + +The pseudocode for creating a hash of meta transaction data is the following: + +``` +keccak256(address(sender) + ++ address(recipient) + ++ uint256(amount) + ++ uint256(relayerFee) + ++ uint256(nonce) + ++ uint256(expirationDate) + ++ address(tokenContract) + ++ address(relayer) +) +``` + +The created hash MUST then be signed with the sender's private key. + +### Validation rules + +- Nonce of a new transaction MUST always be bigger by exactly 1 from the nonce of the last successfully processed meta transaction of the same sender to the same token contract. +- Sending to and from a 0x0 address MUST be prohibited. +- A meta transaction MUST be processed before the expiration date. +- Each sender's token balance MUST be equal or greater than the sum of their respective meta transaction token amount and relayer fee. +- A transaction where at least one meta transaction in the batch does not satisfy the above requirements MUST not be reverted. Instead, a failed meta transaction MUST be skipped or ignored. + +### `processMetaBatch()` function interface + +The `processMetaBatch()` function MUST have the following interface: + +```solidity +function processMetaBatch(address[] memory senders, + address[] memory recipients, + uint256[] memory amounts, + uint256[] memory relayerFees, + uint256[] memory blocks, + uint8[] memory sigV, + bytes32[] memory sigR, + bytes32[] memory sigS) public returns (bool); +``` + +The overview of parameters that are passed: + +- `senders`: an array of meta transaction sender addresses (token senders) +- `recipients `: an array of token recipients addresses +- `amounts`: an array of token amounts that are sent from each sender to each recipient, respectively +- `relayerFees`: an array of the relayer fees paid in tokens by senders. The fee receiver is a relayer (`msg.address`) +- `blocks`: an array of block numbers that represent an expiration date by which the meta transaction must be processed (alternatively, a timestamp could be used instead of a block number) +- `sigV`, `sigR`, `sigS`: three arrays that represent parts of meta transaction signatures + +Each entry in each of the arrays MUST represent data from one meta transaction. The order of the data is very important. Data from a single meta transaction MUST have the same index in every array. + +### Meta transaction nonce + +The token smart contract must keep track of a meta transaction nonce for each token holder. + +```solidity +mapping (address => uint256) private _metaNonces; +``` + +The interface for the `nonceOf()` function is the following: + +```solidity +function nonceOf(address account) public view returns (uint256); +``` + +### Token transfers + +After a meta transaction is successfully validated, the meta nonce of the meta transaction sender MUST be increased by 1. + +Then two token transfers MUST occur: + +- The specified token amount MUST go to the recipient. +- The relayer fee MUST go to the relayer (`msg.sender`). + +## Implementation + +The **reference implementation** adds a couple of functions to the existing ERC-20 token standard: + +- `processMetaBatch()` +- `nonceOf()` + +You can see the implementation of both functions in this file: [ERC20MetaBatch.sol](https://github.com/defifuture/erc20-batched-meta-transactions/blob/master/contracts/ERC20MetaBatch.sol). This is an extended ERC-20 contract with added meta transaction batch transfer capabilities. + +### `processMetaBatch()` + +The `processMetaBatch()` function is responsible for receiving and processing a batch of meta transactions that change token balances. + +```solidity +function processMetaBatch(address[] memory senders, + address[] memory recipients, + uint256[] memory amounts, + uint256[] memory relayerFees, + uint256[] memory blocks, + uint8[] memory sigV, + bytes32[] memory sigR, + bytes32[] memory sigS) public returns (bool) { + + address sender; + uint256 newNonce; + uint256 relayerFeesSum = 0; + bytes32 msgHash; + uint256 i; + + // loop through all meta txs + for (i = 0; i < senders.length; i++) { + sender = senders[i]; + newNonce = _metaNonces[sender] + 1; + + if(sender == address(0) || recipients[i] == address(0)) { + continue; // sender or recipient is 0x0 address, skip this meta tx + } + + // the meta tx should be processed until (including) the specified block number, otherwise it is invalid + if(block.number > blocks[i]) { + continue; // if current block number is bigger than the requested number, skip this meta tx + } + + // check if meta tx sender's balance is big enough + if(_balances[sender] < (amounts[i] + relayerFees[i])) { + continue; // if sender's balance is less than the amount and the relayer fee, skip this meta tx + } + + // check if the signature is valid + msgHash = keccak256(abi.encode(sender, recipients[i], amounts[i], relayerFees[i], newNonce, blocks[i], address(this), msg.sender)); + if(sender != ecrecover(keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", msgHash)), sigV[i], sigR[i], sigS[i])) { + continue; // if sig is not valid, skip to the next meta tx + } + + // set a new nonce for the sender + _metaNonces[sender] = newNonce; + + // transfer tokens + _balances[sender] -= (amounts[i] + relayerFees[i]); + _balances[recipients[i]] += amounts[i]; + relayerFeesSum += relayerFees[i]; + } + + // give the relayer the sum of all relayer fees + _balances[msg.sender] += relayerFeesSum; + + return true; +} +``` + +### `nonceOf()` + +Nonces are needed due to the replay protection (see *Replay attacks* under *Security Considerations*). + +```solidity +mapping (address => uint256) private _metaNonces; + +// ... + +function nonceOf(address account) public view returns (uint256) { + return _metaNonces[account]; +} +``` + +The link to the complete implementation (along with gas usage results) is here: [https://github.com/defifuture/erc20-batched-meta-transactions](https://github.com/defifuture/erc20-batched-meta-transactions). + +> Note that the OpenZeppelin ERC-20 implementation was used here. Some other implementation may have named the `_balances` mapping differently, which would require minor changes in the `processMetaBatch()` function. + +## Rationale + +### All-in-one + +Alternative implementations (like GSN) use multiple smart contracts to enable meta transactions, although this increases gas usage. This implementation (EIP-3005) intentionally keeps everything within one function which reduces complexity and gas cost. + +The `processMetaBatch()` function thus does the job of receiving a batch of meta transactions, validating them, and then transferring tokens from one address to another. + +### Function parameters + +As you can see, the `processMetaBatch()` function in the reference implementation takes the following parameters: + +- an array of **sender addresses** (meta txs senders, not relayers) +- an array of **receiver addresses** +- an array of **amounts** +- an array of **relayer fees** (relayer is `msg.sender`) +- an array of **block numbers** (a due "date" for meta tx to be processed) +- Three arrays that represent parts of a **signature** (v, r, s) + +**Each item** in these arrays represents **data of one meta transaction**. That's why the **correct order** in the arrays is very important. + +If a relayer gets the order wrong, the `processMetaBatch()` function would notice that (when validating a signature), because the hash of the meta transaction values would not match the signed hash. A meta transaction with an invalid signature is **skipped**. + +### The alternative way of passing meta transaction data into the function + +The reference implementation takes parameters as arrays. There's a separate array for each meta transaction data category (the ones that cannot be deduced or extracted from other sources). + +A different approach would be to bitpack all data of a meta transaction into one value and then unpack it within the smart contract. The data for a batch of meta transactions would be sent in an array, but there would need to be only one array (of packed data), instead of multiple arrays. + +### Why is nonce not one of the parameters in the reference implementation? + +Meta nonce is used for constructing a signed hash (see the `msgHash` line where a `keccak256` hash is constructed - you'll find a nonce there). + +Since a new nonce has to always be bigger than the previous one by exactly 1, there's no need to include it as a parameter array in the `processMetaBatch()` function, because its value can be deduced. + +This also helps avoid the "Stack too deep" error. + +### Can EIP-2612 nonces mapping be re-used? + +The EIP-2612 (`permit()` function) also requires a nonce mapping. At this point, I'm not sure yet if this mapping should be **re-used** in case a smart contract implements both EIP-3005 and EIP-2612. + +At the first glance, it seems the `nonces` mapping from EIP-2612 could be re-used, but this should be thought through (and tested) for possible security implications. + +### Token transfers + +Token transfers in the reference implementation could alternatively be done by calling the `_transfer()` function (part of the OpenZeppelin ERC-20 implementation), but it would increase the gas usage and it would also revert the whole batch if some meta transaction was invalid (the current implementation just skips it). + +Another gas usage optimization is to assign total relayer fees to the relayer at the end of the function, and not with every token transfer inside the for loop (thus avoiding multiple SSTORE calls that cost 5'000 gas). + +## Backwards Compatibility + +The code implementation of batched meta transactions is backwards compatible with any fungible token standard, for example, ERC-20 (it only extends it with one function). + +## Test Cases + +Link to tests: [https://github.com/defifuture/erc20-batched-meta-transactions/tree/master/test](https://github.com/defifuture/erc20-batched-meta-transactions/tree/master/test). + +## Security Considerations + +Here is a list of potential security issues and how are they addressed in this implementation. + +### Forging a meta transaction + +The solution against a relayer forging a meta transaction is for a user to sign the meta transaction with their private key. + +The `processMetaBatch()` function then verifies the signature using `ecrecover()`. + +### Replay attacks + +The `processMetaBatch()` function is secure against two types of a replay attack: + +**Using the same meta transaction twice in the same token smart contract** + +A nonce prevents a replay attack where a relayer would send the same meta transaction more than once. + +**Using the same meta transaction twice in different token smart contracts** + +A token smart contract address must be added into the signed hash (of a meta transaction). + +This address does not need to be sent as a parameter into the `processMetaBatch()` function. Instead, the function uses `address(this)` when constructing a hash in order to verify the signature. This way a meta transaction not intended for the token smart contract would be rejected (skipped). + +### Signature validation + +Signing a meta transaction and validating the signature is crucial for this whole scheme to work. + +The `processMetaBatch()` function validates a meta transaction signature, and if it's **invalid**, the meta transaction is **skipped** (but the whole on-chain transaction is **not reverted**). + +```solidity +msgHash = keccak256(abi.encode(sender, recipients[i], amounts[i], relayerFees[i], newNonce, blocks[i], address(this), msg.sender)); + +if(sender != ecrecover(keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", msgHash)), sigV[i], sigR[i], sigS[i])) { + continue; // if sig is not valid, skip to the next meta tx +} +``` + +Why not reverting the whole on-chain transaction? Because there could be only one problematic meta transaction, and the others should not be dropped just because of one rotten apple. + +That said, it is expected of relayers to validate meta transactions in advance before relaying them. That's why relayers are not entitled to a relayer fee for an invalid meta transaction. + +### Malicious relayer forcing a user into over-spending + +A malicious relayer could delay sending some user's meta transaction until the user would decide to make the token transaction on-chain. + +After that, the relayer would relay the delayed meta transaction which would mean that the user would have made two token transactions (over-spending). + +**Solution:** Each meta transaction should have an "expiry date". This is defined in a form of a block number by which the meta transaction must be relayed on-chain. + +```solidity +function processMetaBatch(... + uint256[] memory blocks, + ...) public returns (bool) { + + //... + + // loop through all meta txs + for (i = 0; i < senders.length; i++) { + + // the meta tx should be processed until (including) the specified block number, otherwise it is invalid + if(block.number > blocks[i]) { + continue; // if current block number is bigger than the requested number, skip this meta tx + } + + //... +``` + +### Front-running attack + +A malicious relayer could scout the Ethereum mempool to steal meta transactions and front-run the original relayer. + +**Solution:** The protection that `processMetaBatch()` function uses is that it requires the meta transaction sender to add the relayer's Ethereum address as one of the values in the hash (which is then signed). + +When the `processMetaBatch()` function generates a hash it includes the `msg.sender` address in it: + +```solidity +msgHash = keccak256(abi.encode(sender, recipients[i], amounts[i], relayerFees[i], newNonce, blocks[i], address(this), msg.sender)); + +if(sender != ecrecover(keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", msgHash)), sigV[i], sigR[i], sigS[i])) { + continue; // if sig is not valid, skip to the next meta tx +} +``` + +If the meta transaction was "stolen", the signature check would fail because the `msg.sender` address would not be the same as the intended relayer's address. + +### A malicious (or too impatient) user sending a meta transaction with the same nonce through multiple relayers at once + +A user that is either malicious or just impatient could submit a meta transaction with the same nonce (for the same token contract) to various relayers. Only one of them would get the relayer fee (the first one on-chain), while the others would get an invalid meta transaction. + +**Solution:** Relayers could **share a list of their pending meta transactions** between each other (sort of an info mempool). + +The relayers don't have to fear that someone would steal their respective pending transactions, due to the front-running protection (see above). + +If relayers see meta transactions from a certain sender address that have the same nonce and are supposed to be relayed to the same token smart contract, they can decide that only the first registered meta transaction goes through and others are dropped (or in case meta transactions were registered at the same time, the remaining meta transaction could be randomly picked). + +At a minimum, relayers need to share this meta transaction data (in order to detect meta transaction collision): + +- sender address +- token address +- nonce + +### Too big due block number + +The relayer could trick the meta transaction sender into adding too big due block number - this means a block by which the meta transaction must be processed. The block number could be far in the future, for example, 10 years in the future. This means that the relayer would have 10 years to submit the meta transaction. + +**One way** to solve this problem is by adding an upper bound constraint for a block number within the smart contract. For example, we could say that the specified due block number must not be bigger than 100'000 blocks from the current one (this is around 17 days in the future if we assume 15 seconds block time). + +```solidity +// the meta tx should be processed until (including) the specified block number, otherwise it is invalid +if(block.number > blocks[i] || blocks[i] > (block.number + 100000)) { + // If current block number is bigger than the requested due block number, skip this meta tx. + // Also skip if the due block number is too big (bigger than 100'000 blocks in the future). + continue; +} +``` + +This addition could open new security implications, that's why it is left out of this proof-of-concept. But anyone who wishes to implement it should know about this potential constraint, too. + +**The other way** is to keep the `processMetaBatch()` function as it is and rather check for the too big due block number **on the relayer level**. In this case, the user could be notified about the problem and could issue a new meta transaction with another relayer that would have a much lower block parameter (and the same nonce). + +## Copyright + +Copyright and related rights are waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). \ No newline at end of file diff --git a/EIPS/eip-3009.md b/EIPS/eip-3009.md new file mode 100644 index 00000000000000..588a4a3bb257ff --- /dev/null +++ b/EIPS/eip-3009.md @@ -0,0 +1,536 @@ +--- +eip: 3009 +title: Transfer With Authorization +author: Peter Jihoon Kim (@petejkim), Kevin Britz (@kbrizzle), David Knott (@DavidLKnott) +discussions-to: https://github.com/ethereum/EIPs/issues/3010 +status: Draft +type: Standards Track +category: ERC +created: 2020-09-28 +requires: 20, 712 +--- + +## Simple Summary + +A contract interface that enables transferring of fungible assets via a signed authorization. + +## Abstract + +A set of functions to enable meta-transactions and atomic interactions with [ERC-20](./eip-20.md) token contracts via signatures conforming to the [EIP-712](./eip-712.md) typed message signing specification. + +This enables the user to: + +- delegate the gas payment to someone else, +- pay for gas in the token itself rather than in ETH, +- perform one or more token transfers and other operations in a single atomic transaction, +- transfer ERC-20 tokens to another address, and have the recipient submit the transaction, +- batch multiple transactions with minimal overhead, and +- create and perform multiple transactions without having to worry about them failing due to accidental nonce-reuse or improper ordering by the miner. + +## Motivation + +There is an existing spec, [EIP-2612](./eip-2612), that also allows meta-transactions, and it is encouraged that a contract implements both for maximum compatibility. The two primary differences between this spec and EIP-2612 are that: + +- EIP-2612 uses sequential nonces, but this uses random 32-byte nonces, and that +- EIP-2612 relies on the ERC-20 `approve`/`transferFrom` ("ERC-20 allowance") pattern. + +The biggest issue with the use of sequential nonces is that it does not allow users to perform more than one transaction at time without risking their transactions failing, because: + +- DApps may unintentionally reuse nonces that have not yet been processed in the blockchain. +- Miners may process the transactions in the incorrect order. + +This can be especially problematic if the gas prices are very high and transactions often get queued up and remain unconfirmed for a long time. Non-sequential nonces allow users to create as many transactions as they want at the same time. + +The ERC-20 allowance mechanism is susceptible to the [multiple withdrawal attack](https://blockchain-projects.readthedocs.io/multiple_withdrawal.html)/[SWC-114](https://swcregistry.io/docs/SWC-114), and encourages antipatterns such as the use of the "infinite" allowance. The wide-prevalence of upgradeable contracts have made the conditions favorable for these attacks to happen in the wild. + +The deficiencies of the ERC-20 allowance pattern brought about the development of alternative token standards such as the [ERC-777](./eip-777) and [ERC-677](https://github.com/ethereum/EIPs/issues/677). However, they haven't been able to gain much adoption due to compatibility and potential security issues. + +## Specification + +### Event + +```solidity +event AuthorizationUsed( + address indexed authorizer, + bytes32 indexed nonce +); + +// keccak256("TransferWithAuthorization(address from,address to,uint256 value,uint256 validAfter,uint256 validBefore,bytes32 nonce)") +bytes32 public constant TRANSFER_WITH_AUTHORIZATION_TYPEHASH = 0x7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a2267; + +// keccak256("ReceiveWithAuthorization(address from,address to,uint256 value,uint256 validAfter,uint256 validBefore,bytes32 nonce)") +bytes32 public constant RECEIVE_WITH_AUTHORIZATION_TYPEHASH = 0xd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de8; + +/** + * @notice Returns the state of an authorization + * @dev Nonces are randomly generated 32-byte data unique to the authorizer's + * address + * @param authorizer Authorizer's address + * @param nonce Nonce of the authorization + * @return True if the nonce is used + */ +function authorizationState( + address authorizer, + bytes32 nonce +) external view returns (bool); + +/** + * @notice Execute a transfer with a signed authorization + * @param from Payer's address (Authorizer) + * @param to Payee's address + * @param value Amount to be transferred + * @param validAfter The time after which this is valid (unix time) + * @param validBefore The time before which this is valid (unix time) + * @param nonce Unique nonce + * @param v v of the signature + * @param r r of the signature + * @param s s of the signature + */ +function transferWithAuthorization( + address from, + address to, + uint256 value, + uint256 validAfter, + uint256 validBefore, + bytes32 nonce, + uint8 v, + bytes32 r, + bytes32 s +) external; + +/** + * @notice Receive a transfer with a signed authorization from the payer + * @dev This has an additional check to ensure that the payee's address matches + * the caller of this function to prevent front-running attacks. (See security + * considerations) + * @param from Payer's address (Authorizer) + * @param to Payee's address + * @param value Amount to be transferred + * @param validAfter The time after which this is valid (unix time) + * @param validBefore The time before which this is valid (unix time) + * @param nonce Unique nonce + * @param v v of the signature + * @param r r of the signature + * @param s s of the signature + */ +function receiveWithAuthorization( + address from, + address to, + uint256 value, + uint256 validAfter, + uint256 validBefore, + bytes32 nonce, + uint8 v, + bytes32 r, + bytes32 s +) external; +``` + +**Optional:** + +``` +event AuthorizationCanceled( + address indexed authorizer, + bytes32 indexed nonce +); + +// keccak256("CancelAuthorization(address authorizer,bytes32 nonce)") +bytes32 public constant CANCEL_AUTHORIZATION_TYPEHASH = 0x158b0a9edf7a828aad02f63cd515c68ef2f50ba807396f6d12842833a1597429; + +/** + * @notice Attempt to cancel an authorization + * @param authorizer Authorizer's address + * @param nonce Nonce of the authorization + * @param v v of the signature + * @param r r of the signature + * @param s s of the signature + */ +function cancelAuthorization( + address authorizer, + bytes32 nonce, + uint8 v, + bytes32 r, + bytes32 s +) external; +``` + + +The arguments `v`, `r`, and `s` must be obtained using the [EIP-712](./eip-712.md) typed message signing spec. + +**Example:** + +``` +DomainSeparator := Keccak256(ABIEncode( + Keccak256( + "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" + ), + Keccak256("USD Coin"), // name + Keccak256("2"), // version + 1, // chainId + 0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48 // verifyingContract +)) +``` + +With the domain separator, the typehash, which is used to identify the type of the EIP-712 message being used, and the values of the parameters, you are able to derive a Keccak-256 hash digest which can then be signed using the token holder's private key. + +**Example:** + +``` +// Transfer With Authorization +TypeHash := Keccak256( + "TransferWithAuthorization(address from,address to,uint256 value,uint256 validAfter,uint256 validBefore,bytes32 nonce)" +) +Params := { From, To, Value, ValidAfter, ValidBefore, Nonce } + +// ReceiveWithAuthorization +TypeHash := Keccak256( + "ReceiveWithAuthorization(address from,address to,uint256 value,uint256 validAfter,uint256 validBefore,bytes32 nonce)" +) +Params := { From, To, Value, ValidAfter, ValidBefore, Nonce } + +// CancelAuthorization +TypeHash := Keccak256( + "CancelAuthorization(address authorizer,bytes32 nonce)" +) +Params := { Authorizer, Nonce } +``` + +``` +// "‖" denotes concatenation. +Digest := Keecak256( + 0x1901 ‖ DomainSeparator ‖ Keccak256(ABIEncode(TypeHash, Params...)) +) + +{ v, r, s } := Sign(Digest, PrivateKey) +``` + +Smart contract functions that wrap `receiveWithAuthorization` call may choose to reduce the number of arguments by accepting the full ABI-encoded set of arguments for the `receiveWithAuthorization` call as a single argument of the type `bytes`. + +**Example:** + +```solidity +// keccak256("receiveWithAuthorization(address,address,uint256,uint256,uint256,bytes32,uint8,bytes32,bytes32)")[0:4] +bytes4 private constant _RECEIVE_WITH_AUTHORIZATION_SELECTOR = 0xef55bec6; + +function deposit(address token, bytes calldata receiveAuthorization) + external + nonReentrant +{ + (address from, address to, uint256 amount) = abi.decode( + receiveAuthorization[0:96], + (address, address, uint256) + ); + require(to == address(this), "Recipient is not this contract"); + + (bool success, ) = token.call( + abi.encodePacked( + _RECEIVE_WITH_AUTHORIZATION_SELECTOR, + receiveAuthorization + ) + ); + require(success, "Failed to transfer tokens"); + + ... +} +``` + +### Use with web3 providers + +The signature for an authorization can be obtained using a web3 provider with the `eth_signTypedData{_v4}` method. + +**Example:** + +```javascript +const data = { + types: { + EIP712Domain: [ + { name: "name", type: "string" }, + { name: "version", type: "string" }, + { name: "chainId", type: "uint256" }, + { name: "verifyingContract", type: "address" }, + ], + TransferWithAuthorization: [ + { name: "from", type: "address" }, + { name: "to", type: "address" }, + { name: "value", type: "uint256" }, + { name: "validAfter", type: "uint256" }, + { name: "validBefore", type: "uint256" }, + { name: "nonce", type: "bytes32" }, + ], + }, + domain: { + name: tokenName, + version: tokenVersion, + chainId: selectedChainId, + verifyingContract: tokenAddress, + }, + primaryType: "TransferWithAuthorization", + message: { + from: userAddress, + to: recipientAddress, + value: amountBN.toString(10), + validAfter: 0, + validBefore: Math.floor(Date.now() / 1000) + 3600, // Valid for an hour + nonce: Web3.utils.randomHex(32), + }, +}; + +const signature = await ethereum.request({ + method: "eth_signTypedData_v4", + params: [userAddress, JSON.stringify(data)], +}); + +const v = "0x" + signature.slice(130, 132); +const r = signature.slice(0, 66); +const s = "0x" + signature.slice(66, 130); +``` + +## Rationale + +### Unique Random Nonce, Instead of Sequential Nonce + +One might say transaction ordering is one reason why sequential nonces are preferred. However, sequential nonces do not actually help achieve transaction ordering for meta transactions in practice: + +- For native Ethereum transactions, when a transaction with a nonce value that is too-high is submitted to the network, it will stay pending until the transactions consuming the lower unused nonces are confirmed. +- However, for meta-transactions, when a transaction containing a sequential nonce value that is too high is submitted, instead of staying pending, it will revert and fail immediately, resulting in wasted gas. +- The fact that miners can also reorder transactions and include them in the block in the order they want (assuming each transaction was submitted to the network by different meta-transaction relayers) also makes it possible for the meta-transactions to fail even if the nonces used were correct. (e.g. User submits nonces 3, 4 and 5, but miner ends up including them in the block as 4,5,3, resulting in only 3 succeeding) +- Lastly, when using different applications simultaneously, in absence of some sort of an off-chain nonce-tracker, it is not possible to determine what the correct next nonce value is if there exists nonces that are used but haven't been submitted and confirmed by the network. +- Under high gas price conditions, transactions can often "get stuck" in the pool for a long time. Under such a situation, it is much more likely for the same nonce to be unintentionally reused twice. For example, if you make a meta-transaction that uses a sequential nonce from one app, and switch to another app to make another meta-transaction before the previous one confirms, the same nonce will be used if the app relies purely on the data available on-chain, resulting in one of the transactions failing. +- In conclusion, the only way to guarantee transaction ordering is for relayers to submit transactions one at a time, waiting for confirmation between each submission (and the order in which they should be submitted can be part of some off-chain metadata), rendering sequential nonce irrelevant. + +### Valid After and Valid Before + +- Relying on relayers to submit transactions for you means you may not have exact control over the timing of transaction submission. +- These parameters allow the user to schedule a transaction to be only valid in the future or before a specific deadline, protecting the user from potential undesirable effects that may be caused by the submission being made either too late or too early. + +### EIP-712 + +- EIP-712 ensures that the signatures generated are valid only for this specific instance of the token contract and cannot be replayed on a different network with a different chain ID. +- This is achieved by incorporating the contract address and the chain ID in a Keccak-256 hash digest called the domain separator. The actual set of parameters used to derive the domain separator is up to the implementing contract, but it is highly recommended that the fields `verifyingContract` and `chainId` are included. + +## Backwards Compatibility + +New contracts benefit from being able to directly utilize EIP-3009 in order to create atomic transactions, but existing contracts may still rely on the conventional ERC-20 allowance pattern (`approve`/`transferFrom`). + +In order to add support for EIP-3009 to existing contracts ("parent contract") that use the ERC-20 allowance pattern, a forwarding contract ("forwarder") can be constructed that takes an authorization and does the following: + +1. Extract the user and deposit amount from the authorization +2. Call `receiveWithAuthorization` to transfer specified funds from the user to the forwarder +3. Approve the parent contract to spend funds from the forwarder +4. Call the method on the parent contract that spends the allowance set from the forwarder +5. Transfer the ownership of any resulting tokens back to the user + +**Example:** + +```solidity +interface IDeFiToken { + function deposit(uint256 amount) external returns (uint256); + + function transfer(address account, uint256 amount) + external + returns (bool); +} + +contract DepositForwarder { + bytes4 private constant _RECEIVE_WITH_AUTHORIZATION_SELECTOR = 0xef55bec6; + + IDeFiToken private _parent; + IERC20 private _token; + + constructor(IDeFiToken parent, IERC20 token) public { + _parent = parent; + _token = token; + } + + function deposit(bytes calldata receiveAuthorization) + external + nonReentrant + returns (uint256) + { + (address from, address to, uint256 amount) = abi.decode( + receiveAuthorization[0:96], + (address, address, uint256) + ); + require(to == address(this), "Recipient is not this contract"); + + (bool success, ) = address(_token).call( + abi.encodePacked( + _RECEIVE_WITH_AUTHORIZATION_SELECTOR, + receiveAuthorization + ) + ); + require(success, "Failed to transfer to the forwarder"); + + require( + _token.approve(address(_parent), amount), + "Failed to set the allowance" + ); + + uint256 tokensMinted = _parent.deposit(amount); + require( + _parent.transfer(from, tokensMinted), + "Failed to transfer the minted tokens" + ); + + uint256 remainder = _token.balanceOf(address(this); + if (remainder > 0) { + require( + _token.transfer(from, remainder), + "Failed to refund the remainder" + ); + } + + return tokensMinted; + } +} +``` + +## Test Cases + +See [EIP3009.test.ts](https://github.com/CoinbaseStablecoin/eip-3009/blob/master/test/EIP3009.test.ts). + +## Implementation + +**EIP3009.sol** +```solidity +abstract contract EIP3009 is IERC20Transfer, EIP712Domain { + // keccak256("TransferWithAuthorization(address from,address to,uint256 value,uint256 validAfter,uint256 validBefore,bytes32 nonce)") + bytes32 public constant TRANSFER_WITH_AUTHORIZATION_TYPEHASH = 0x7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a2267; + + // keccak256("ReceiveWithAuthorization(address from,address to,uint256 value,uint256 validAfter,uint256 validBefore,bytes32 nonce)") + bytes32 public constant RECEIVE_WITH_AUTHORIZATION_TYPEHASH = 0xd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de8; + + mapping(address => mapping(bytes32 => bool)) internal _authorizationStates; + + event AuthorizationUsed(address indexed authorizer, bytes32 indexed nonce); + + string internal constant _INVALID_SIGNATURE_ERROR = "EIP3009: invalid signature"; + + function authorizationState(address authorizer, bytes32 nonce) + external + view + returns (bool) + { + return _authorizationStates[authorizer][nonce]; + } + + function transferWithAuthorization( + address from, + address to, + uint256 value, + uint256 validAfter, + uint256 validBefore, + bytes32 nonce, + uint8 v, + bytes32 r, + bytes32 s + ) external { + require(now > validAfter, "EIP3009: authorization is not yet valid"); + require(now < validBefore, "EIP3009: authorization is expired"); + require( + !_authorizationStates[from][nonce], + "EIP3009: authorization is used" + ); + + bytes memory data = abi.encode( + TRANSFER_WITH_AUTHORIZATION_TYPEHASH, + from, + to, + value, + validAfter, + validBefore, + nonce + ); + require( + EIP712.recover(DOMAIN_SEPARATOR, v, r, s, data) == from, + "EIP3009: invalid signature" + ); + + _authorizationStates[from][nonce] = true; + emit AuthorizationUsed(from, nonce); + + _transfer(from, to, value); + } +} +``` + +**IERC20Transfer.sol** +```solidity +abstract contract IERC20Transfer { + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual; +} +``` + +**EIP712Domain.sol** +```solidity +abstract contract EIP712Domain { + bytes32 public DOMAIN_SEPARATOR; +} +``` + +**EIP712.sol** +```solidity +library EIP712 { + // keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)") + bytes32 public constant EIP712_DOMAIN_TYPEHASH = 0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f; + + function makeDomainSeparator(string memory name, string memory version) + internal + view + returns (bytes32) + { + uint256 chainId; + assembly { + chainId := chainid() + } + + return + keccak256( + abi.encode( + EIP712_DOMAIN_TYPEHASH, + keccak256(bytes(name)), + keccak256(bytes(version)), + address(this), + bytes32(chainId) + ) + ); + } + + function recover( + bytes32 domainSeparator, + uint8 v, + bytes32 r, + bytes32 s, + bytes memory typeHashAndData + ) internal pure returns (address) { + bytes32 digest = keccak256( + abi.encodePacked( + "\x19\x01", + domainSeparator, + keccak256(typeHashAndData) + ) + ); + address recovered = ecrecover(digest, v, r, s); + require(recovered != address(0), "EIP712: invalid signature"); + return recovered; + } +} +``` + +A fully working implementation of EIP-3009 can be found in [this repository](https://github.com/CoinbaseStablecoin/eip-3009/blob/master/contracts/lib/EIP3009.sol). The repository also includes [an implementation of EIP-2612](https://github.com/CoinbaseStablecoin/eip-3009/blob/master/contracts/lib/EI32612.sol) that uses the EIP-712 library code presented above. + +## Security Considerations + +Use `receiveWithAuthorization` instead of `transferWithAuthorization` when calling from other smart contracts. It is possible for an attacker watching the transaction pool to extract the transfer authorization and front-run the `transferWithAuthorization` call to execute the transfer without invoking the wrapper function. This could potentially result in unprocessed, locked up deposits. `receiveWithAuthorization` prevents this by performing an additional check that ensures that the caller is the payee. Additionally, if there are multiple contract functions accepting receive authorizations, the app developer could dedicate some leading bytes of the nonce could as the identifier to prevent cross-use. + +When submitting multiple transfers simultaneously, be mindful of the fact that relayers and miners will decide the order in which they are processed. This is generally not a problem if the transactions are not dependent on each other, but for transactions that are highly dependent on each other, it is recommended that the signed authorizations are submitted one at a time. + +The zero address must be rejected when using `ecrecover` to prevent unauthorized transfers and approvals of funds from the zero address. The built-in `ecrecover` returns the zero address when a malformed signature is provided. + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-3014.md b/EIPS/eip-3014.md new file mode 100644 index 00000000000000..b43e21ad6a5450 --- /dev/null +++ b/EIPS/eip-3014.md @@ -0,0 +1,48 @@ +--- +eip: 3014 +title: `eth_symbol` JSON-RPC method +author: Peter Grassberger (@PeterTheOne) +discussions-to: https://github.com/ethereum/EIPs/issues/3012 +status: Draft +type: Standards Track +category: Interface +created: 2020-09-30 +--- + +## Simple Summary +Add `eth_symbol` method to the JSON-RPC that returns the symbol of the native coin of the network. + +## Abstract +The new method `eth_symbol` (`eth_`-namespaced) has no parameters and returns a string of the native coin of the network. For the Ethereum mainnet this will be `ETH`, other networks will have other symbols. + +## Motivation +Wallets that deal with multiple networks need some basic information for every blockchain that they connect to. One of those things is the symbol of the native coin of the network. Instead of requiring the user to research and manually add the symbol it could be provided to the wallet via this proposed JSON-RPC endpoint and used automatically. There are lists of networks with symbols like https://github.com/ethereum-lists/chains where a user can manually look up the correct values. But this information could easily come from the network itself. + +## Specification +Method: `eth_symbol`. + +Params: none. + +Returns: `result` - the native coin symbol, string + +Example: + +```js +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_symbol","params":[],"id":1}' + +// Result +{ + "id": 1, + "jsonrpc": "2.0", + "result": "ETH" +} +``` + +## Rationale +This endpoint is similar to [EIP-695](./eip-695.md) but it provides the symbol instead of `chainId`. It provides functionality that is already there for [ERC-20](./eip-20.md) tokens, but not yet for the native coin of the network. Alternative naming of `eth_nativeCurrencySymbol` was considered, but the context and the fact that it just returns one value makes it clear that that it returns the symbol for the native coin of the network. + +## Security Considerations +It is a read only endpoint. The information is only as trusted as the JSON-RPC node itself, it could supply wrong information and thereby trick the user in believing he/she is dealing with another native coin. + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-3026.md b/EIPS/eip-3026.md new file mode 100644 index 00000000000000..6af4f5d59df72a --- /dev/null +++ b/EIPS/eip-3026.md @@ -0,0 +1,277 @@ +--- +eip: 3026 +title: BW6-761 curve operations +author: Youssef El Housni (@yelhousni), Michael Connor (@iAmMichaelConnor), Aurore Guillevic +discussions-to: https://ethereum-magicians.org/t/eip-3026-bw6-761-curve-operations/4790 +status: Draft +type: Standards Track +category: Core +requires: 2539 +created: 2020-10-05 +--- + +## Simple Summary +This precompile adds operations for the BW6-761 curve (from the EY/Inria [research paper](https://eprint.iacr.org/2020/351.pdf)) as a precompile in a set necessary to *efficiently* perform verification of one-layer composed zkSNARKs proofs. + +## Abstract + +If `block.number >= X` we introduce *seven* separate precompiles to perform the following operations (addresses to be determined): + +- BW6_G1_ADD - to perform point addition on a curve defined over a prime field +- BW6_G1_MUL - to perform point multiplication on a curve defined over a prime field +- BW6_G1_MULTIEXP - to perform multiexponentiation on a curve defined over a prime field +- BW6_G2_ADD - to perform point addition on a curve twist defined the base a prime field +- BW6_G2_MUL - to perform point multiplication on a curve twist defined over a prime field +- BW6_G2_MULTIEXP - to perform multiexponentiation on a curve twist defined over a prime field +- BW6_PAIRING - to perform a pairing operations between a set of *pairs* of (G1, G2) points + +The multiexponentiation operations are a generalization of point multiplication, but separate precompiles are prosposed because running a single MUL through MULTIEXP seems to be 20% more expensive. + +## Motivation + +This EIP is based on and tends to replace [EIP-2541](https://github.com/matter-labs/EIPs/blob/sw6_wrapping/EIPS/eip-2541.md) for significant performance reasons. In most applications, BW6-761 is used as an outer curve to BLS12-377 considered in [EIP-2539](https://github.com/ethereum/EIPs/pull/2539). +The motivation of this precompile is to allow efficient one-layer composition of SNARK proofs. Currently this is done by Zexe using the BLS12-377/CP6-782 pair of curves. This precompile proposes a replacement of CP6-782 by BW6-761, which allows much faster operations. For example, it was shown that verifying a Groth16 proof with BW6-761 is 30 times faster than with CP6-782. + +### Proposed addresses table + +|Precompile |Address | +|---|---| +|BW6_G1_ADD | 0x13 | +|BW6_G1_MUL | 0x14 | +|BW6_G1_MULTIEXP | 0x15 | +|BW6_G2_ADD | 0x16 | +|BW6_G2_MUL | 0x17 | +|BW6_G2_MULTIEXP | 0x18 | +|BW6_PAIRING | 0x19 | + +## Specification + +Curve parameters: + +The BW6-761 `y^2=x^3-1` curve is fully defined by the following set of parameters: + +``` +Base field modulus = 0x122e824fb83ce0ad187c94004faff3eb926186a81d14688528275ef8087be41707ba638e584e91903cebaff25b423048689c8ed12f9fd9071dcd3dc73ebff2e98a116c25667a8f8160cf8aeeaf0a437e6913e6870000082f49d00000000008b +A coefficient = 0x0 +B coefficient = 0x122e824fb83ce0ad187c94004faff3eb926186a81d14688528275ef8087be41707ba638e584e91903cebaff25b423048689c8ed12f9fd9071dcd3dc73ebff2e98a116c25667a8f8160cf8aeeaf0a437e6913e6870000082f49d00000000008a +Main subgroup order = 0x1ae3a4617c510eac63b05c06ca1493b1a22d9f300f5138f1ef3622fba094800170b5d44300000008508c00000000001 +Extension tower: +Fp3 construction: (Fp3 = Fp[u]/u^3+4) +Fp cubic non-residue = 0x122e824fb83ce0ad187c94004faff3eb926186a81d14688528275ef8087be41707ba638e584e91903cebaff25b423048689c8ed12f9fd9071dcd3dc73ebff2e98a116c25667a8f8160cf8aeeaf0a437e6913e6870000082f49d000000000087 +Twist parameters: +Twist type: M +twist curve A coefficient c0 = 0x0 + c1 = 0x0 +twist curve B coefficient c0 = 0x4 + c1 = 0x0 +Generators: +G1: +X = 0x1075b020ea190c8b277ce98a477beaee6a0cfb7551b27f0ee05c54b85f56fc779017ffac15520ac11dbfcd294c2e746a17a54ce47729b905bd71fa0c9ea097103758f9a280ca27f6750dd0356133e82055928aca6af603f4088f3af66e5b43d +Y = 0x58b84e0a6fc574e6fd637b45cc2a420f952589884c9ec61a7348d2a2e573a3265909f1af7e0dbac5b8fa1771b5b806cc685d31717a4c55be3fb90b6fc2cdd49f9df141b3053253b2b08119cad0fb93ad1cb2be0b20d2a1bafc8f2db4e95363 +G2: +X = 0x110133241d9b816c852a82e69d660f9d61053aac5a7115f4c06201013890f6d26b41c5dab3da268734ec3f1f09feb58c5bbcae9ac70e7c7963317a300e1b6bace6948cb3cd208d700e96efbc2ad54b06410cf4fe1bf995ba830c194cd025f1c +Y = 0x17c3357761369f8179eb10e4b6d2dc26b7cf9acec2181c81a78e2753ffe3160a1d86c80b95a59c94c97eb733293fef64f293dbd2c712b88906c170ffa823003ea96fcd504affc758aa2d3a3c5a02a591ec0594f9eac689eb70a16728c73b61 +Pairing parameters: +e(P,Q)=(ML1(P,Q)*ML2(P,Q)^q)^FE +|loop_count_1| (first miller loop ML1 count) = 0x8508c00000000002 +|loop_count_2| (second miller loop ML2 count) = 0x23ed1347970dec008a442f991fffffffffffffffffffffff +loop_count_1 is negative = false +loop_count_2 is negative = false +``` + +#### Encoding + +##### Field elements encoding: + +To encode points involved in the operation one has to encode elements of only the base field. + +The base field element (Fp) is encoded as `96` bytes by performing BigEndian encoding of the corresponding (unsigned) integer. The corresponding integer **MUST** be less than the base field modulus. + +If encodings do not follow this spec anywhere during parsing in the precompile, the precompile **MUST** revert with "endoding error". + +##### Encoding of uncompressed points: + +Points in both G1 and G2 can be expressed as `(x, y)` affine coordinates, where `x` and `y` are elements of the base field. +Therefore, points in both G1 and G2 are encoded as the byte concatenation of the field element encodings of the `x` and `y` affine coordinates. The total encoding length for a G1/G2 point is thus `192` bytes. + +##### Point at infinity encoding: + +Also referred as the "zero point". For BW6-761 (`y^2=x^3-1`) and its M-twisted curves (`y^3=x^3+4`), the point with coordinates `(0, 0)` (formal zeros in Fp) is *not* on the curve, and so the encoding of `(0, 0)` is used as a convention to encode the point at infinity. + +##### Encoding of scalars for multiplication and multiexponentiation operations: + +For multiplication and multiexponentiation operations, a scalar is encoded as `64` bytes by performing BigEndian encoding of the corresponding (unsigned) integer. + +Note that the main subgroup order for BW6-761 is actually only `377` bits (`48` bytes), but an encoding of `64` bytes has been chosen to have a `32`-byte-aligned ABI (representable as e.g. `bytes32[2]` or `uint256[2]`). + +The corresponding integer **MAY** be greater than the main subgroup order. + +#### ABI for operations + +##### ABI for G1 addition + +G1 addition call expects `384` bytes as an input that is interpreted as the byte concatenation of two G1 points (point-encoded as `192` bytes each). Output is a point-encoding of the addition operation result. + +Error cases: +- Either of the points being not on the curve +- Input has invalid length +- Field element encoding rules apply (obviously) + +##### ABI for G1 multiplication +G1 multiplication call expects `256` bytes as an input that is interpreted as the byte concatenation of the point-encoding of a G1 point (`192` bytes) and the encoding of a scalar value (`64` bytes). Output is a point-encoding of the multiplication operation result. + +Error cases: +- Point being not on the curve +- Input has invalid length +- Field element encoding rules apply (obviously) +- Scalar encoding rules apply (obviously) + +##### ABI for G1 multiexponentiation + +G1 multiplication call expects `256*k` bytes as an input that is interpreted as the byte concatenation of `k` slices, each of them being a byte concatenation of the point-encoding of a G1 point (`192` bytes) and the encoding of a scalar value (`64` bytes). Output is an encoding of the multiexponentiation operation result. + +Error cases: +- Any of the G1 points being not on the curve +- Input has invalid length +- Field element encoding rules apply (obviously) +- Scalar encoding rules apply (obviously) + +##### ABI for G2 addition + +G2 addition call expects `384` bytes as an input that is interpreted as the byte concatenation of two G2 points (point-encoded as `192` bytes each). Output is a point-encoding of the addition operation result. + +Error cases: +- Either of points being not on the curve +- Input has invalid length +- Field elements encoding rules apply (obviously) + +##### ABI for G2 multiplication +G2 multiplication call expects `256` bytes as an input that is interpreted as the byte concatenation of the point-encoding of a G2 point (`192` bytes) and the encoding of a scalar value (`64` bytes). Output is an encoding of multiplication operation result. + +Error cases: +- Point being not on the curve must result in error +- Field elements encoding rules apply (obviously) +- Input has invalid length + +##### ABI for G2 multiexponentiation + +G2 multiplication call expects `240*k` bytes as an input that is interpreted as byte concatenation of `k` slices each of them being a byte concatenation of encoding of G2 point (`192` bytes) and encoding of a scalar value (`48` bytes). Output is an encoding of multiexponentiation operation result. + +Error cases: +- Any of G2 points being not on the curve must result in error +- Field elements encoding rules apply (obviously) +- Input has invalid length + +##### ABI for pairing + +Pairing call expects `384*k` bytes as an input, that is interpreted as the byte concatenation of `k` slices. Each slice has the following structure: +- `192` bytes G1 point encoding +- `192` bytes G2 point encoding + +Output is `32` bytes representing a boolean: + +- `0x0000000000000000000000000000000000000000000000000000000000000001` if the pairing result is equal the to multiplicative identity in the pairing target field; and +- `0x0000000000000000000000000000000000000000000000000000000000000000` otherwise. + +Error cases: +- Any of the G1 or G2 points being not on the curve +- Any of the G1 or G2 points being not in the correct subgroup +- Input has invalid length +- Field elements encoding rules apply (obviously) + +#### Prevention of DDoS on error handling + +This precompile performs extensive computations and in case of any errors during execution it **MUST** consume all gas from the the gas schedule for the corresponding operation. + +#### Gas schedule + +##### G1 addition +`` gas + +##### G1 multiplication +`` gas + +##### G2 addition +`` gas + +##### G2 multiplication +`` gas + +##### G1/G2 Multiexponentiation +Discounts table as a vector of pairs `[k, discount]`: + +``` + +``` + +`max_discount = ` + +##### Pairing operation +Base cost of the pairing operation is `*k + ` where `k` is a number of pairs. + +## Rationale +Gas costs are based on EIP1962 estimation strategy (but do not fully include yet parsing of ABI, decoding and encoding of the result as a byte array). + +#### Gas estimation strategy +Gas cost is derived by taking the average timing of the same operations over different implementations and assuming a constant `30 MGas/second`. Since the execution time is machine-specific, this constant is determined based on execution times of [ECRECOVER](https://github.com/matter-labs/eip1962/blob/master/run_bn_pairing_estimate.sh) and [BNPAIR](https://github.com/matter-labs/eip1962/blob/master/run_bn_pairing_estimate.sh) precompiles on my machine and their proposed gas price (`43.5 MGas/s` for ECRECOVER and `16.5 MGas/s` for BNPAIR). Following are the proposed methods to time the precompile operations: + +- G1 addition: Average timing of 1000 random samples. +- G1 multiplication: Average timing of 1000 samples of random worst-case of double-and-add algorithm (scalar of max bit length and max hamming weight and random base points in G1) +- G2 addition: Average timing of 1000 random samples +- G2 multiplication: Average timing of 1000 samples of radnom worst-case of double-and-add algorithm (scalar of max bit length and max hamming weight and random base points in G2) +- G1 and G2 multiexponentiations: Expected to be performed by the Peppinger algorithm, with a table prepared for discount in case of `k <= 128` points in the multiexponentiation with a discount cup `max_discount` for `k > 128`. To avoid non-integer arithmetic call cost is calculated as `k * multiplication_cost * discount / multiplier` where `multiplier = 1000`, `k` is a number of (scalar, point) pairs for the call, `multiplication_cost` is a corresponding single multiplication call cost for G1/G2. +- Pairing: Average timing of 1000 random samples (random points in G1 and G2) for different number of pairs with linear lifting. + +#### Multiexponentiation as a separate call +Explicit separate multiexponentiation operation that allows one to save execution time (so gas) by both the algorithm used (namely Peppinger algorithm) and (usually forgotten) by the fact that `CALL` operation in Ethereum is expensive (at the time of writing), so one would have to pay non-negigible overhead if e.g. for multiexponentiation of `100` points would have to call the multipication precompile `100` times and addition for `99` times (roughly `138600` would be saved). + +#### Explicit subgroup checks +G2 subgroup check has the same cost as G1 subgroup check. Endomorphisms can be leverages to optimize this operation. + +## Backwards Compatibility +There are no backward compatibility questions. + +## Test Cases + +Due to the large test parameters space we first provide properties that various operations must satisfy. We use additive notation for point operations, capital letters (`P`, `Q`) for points, small letters (`a`, `b`) for scalars. Generator for G1 is labeled as `G`, generator for G2 is labeled as `H`, otherwise we assume random point on a curve in a correct subgroup. `0` means either scalar zero or point of infinity. `1` means either scalar one or multiplicative identity. `group_order` is a main subgroup order. `e(P, Q)` means pairing operation where `P` is in G1, `Q` is in G2. + +Requeired properties for basic ops (add/multiply): + +- Commutativity: `P + Q = Q + P` +- Additive negation: `P + (-P) = 0` +- Doubling `P + P = 2*P` +- Subgroup check: `group_order * P = 0` +- Trivial multiplication check: `1 * P = P` +- Multiplication by zero: `0 * P = 0` +- Multiplication by the unnormalized scalar `(scalar + group_order) * P = scalar * P` + +Required properties for pairing operation: +- Degeneracy `e(P, 0*Q) = e(0*P, Q) = 1` +- Bilinearity `e(a*P, b*Q) = e(a*b*P, Q) = e(P, a*b*Q)` (internal test, not visible through ABI) + +Test vector for all operations are expanded in this [gist](https://gist.github.com/shamatar/506ab3193a7932fe9302a2f3a31a23e8) until it's final. + +## Implementation +There is a various choice of existing implementations: + +**Libraries:** +- Rust implementation (EY/Zexe): https://github.com/yelhousni/zexe/tree/youssef/BW6-761-Fq-ABLR-2ML-M +- C++ implementation (EY/libff): https://github.com/EYBlockchain/zk-swap-libff +- Golang implementation (Consensys/gurvy): https://github.com/ConsenSys/gurvy + +**Stand-alone implementation:** +- Golang implementation with Intel assembly (Onur Kilic): https://github.com/kilic/bw6 + +**Precompiles:** +- OpenEthereum (EY/Parity): https://github.com/EYBlockchain/solidity-elliptic-curves + +**Sripts:** +- SageMath and Magma scripts: https://gitlab.inria.fr/zk-curves/bw6-761/ + +## Security Considerations +Strictly following the spec will eliminate security implications or consensus implications in a contrast to the previous BN254 precompile. + +Important topic is a "constant time" property for performed operations. We explicitly state that this precompile **IS NOT REQUIRED** to perform all the operations using constant time algorithms. + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-3030.md b/EIPS/eip-3030.md new file mode 100644 index 00000000000000..25da7195c9be2d --- /dev/null +++ b/EIPS/eip-3030.md @@ -0,0 +1,361 @@ +--- +eip: 3030 +title: BLS Remote Signer HTTP API +author: Herman Junge (@hermanjunge) +discussions-to: https://ethereum-magicians.org/t/eip-3030-bls-remote-signer-http-api-standard/4810 +status: Draft +type: Standards Track +category: Interface +created: 2020-09-30 +--- + +## Simple Summary +This EIP defines a HTTP API standard for a BLS remote signer, consumed by validator clients to sign block proposals and attestations in the context of Ethereum 2.0 (eth2). + +## Abstract +A [validator](https://github.com/ethereum/eth2.0-specs/blob/dev/specs/phase0/validator.md) client contributes to the consensus of the Eth2 blockchain by signing proposals and attestations of blocks, using a BLS private key which must be available to this client at all times. + +The BLS remote signer API is designed to be consumed by validator clients, looking for a more secure avenue to store their BLS12-381 private key(s), enabling them to run in more permissive and scalable environments. + +## Motivation +Eth2 utilizes [BLS12-381](https://github.com/cfrg/draft-irtf-cfrg-bls-signature/) signatures. + +Consensus on the eth2 Blockchain is achieved via the proposal and attestation of blocks from validator clients, using a BLS private key (_signing_ key) which must be available each time a message is signed: that is, at least once every epoch (6.4 minutes), during a small window of time within this epoch (a _slot_, i.e. 12 seconds), as each validator is expected to attest exactly once per epoch. + +The [eth2 specification](https://github.com/ethereum/eth2.0-specs) does not explicitly provide a directive on where this BLS private key must/should be stored, leaving this implementation detail to the client teams, who assume that this cryptographic secret is stored on the same host as the validator client. + +This assumption is sufficient in the use case where the validator client is running in a physically secure network (i.e. nobody, but the operator, has a chance to log-in into the machine hosting the validator client), as such configuration would only allow _outbound_ calls from the validator client. In this situation, only a physical security breach, or a Remote Code Execution (RCE) vulnerability can allow an attacker to either have arbitrary access to the storage or to the memory of the device. + +There are, however, use cases where it is required by the operator to run a validator client node in less constrained security environments, as the ones given by a cloud provider. Notwithstanding any security expectation, nothing prevents a rogue operator from gaining arbitrary access to the assets running inside a node. + +The situation is not better when the requirement is to execute the validators by leveraging a container orchestration solution (e.g. Kubernetes). The handling of secret keys across nodes can become a burden both from an operational as well as a security perspective. + +The proposed solution comprises running a specialized node with exclusive access to the secret keys, listening to a simple API (defined in the [Specification](#specification) section), and returning the requested signatures. Operators working under this schema must utilize clients with the adequate feature supporting the consumption of this API. + +The focus of this specification is the supply of BLS signatures _on demand_. The aspects of authentication, key management (creation, update, and deletion), and transport encryption are discussed in the [Rationale](#rationale) section of this document. Moreover, the [Threat Model](#threat-model) section of this document provides a (non-exhaustive) list of threats and attack vectors, along with the suggested related mitigation strategy. + +## Specification + +### `GET /upcheck` + +_**Responses**_ + +Success |
+--- | --- +Code | `200` +Content | `{"status": "OK"}` + +--- + +### `GET /keys` + +Returns the identifiers of the keys available to the signer. + +_**Responses**_ + +Success |
+--- | --- +Code | `200` +Content | `{"keys": "[identifier]"}` + +--- + +### `POST /sign/:identifier` + +URL Parameter |
+--- | --- +`:identifier` | `public_key_hex_string_without_0x` + +_**Request**_ + +JSON Body |
|
+--- | --- | --- +`bls_domain` | **Required** | The BLS Signature domain.
As defined in the [specification](https://github.com/ethereum/eth2.0-specs/blob/dev/specs/phase0/beacon-chain.md#domain-types), in lowercase, omitting the `domain` prefix.
Supporting `beacon_proposer`, `beacon_attester`, and `randao`. +`data` | **Required** | The data to be signed.
As defined in the specifications for [block](https://github.com/ethereum/eth2.0-APIs/blob/master/types/block.yaml), [attestation](https://github.com/ethereum/eth2.0-APIs/blob/master/types/attestation.yaml), and [epoch](https://github.com/ethereum/eth2.0-APIs/blob/master/types/misc.yaml). +`fork` | **Required** | A `Fork` object containing previous and current versions.
As defined in the [specification](https://github.com/ethereum/eth2.0-APIs/blob/master/types/misc.yaml) +`genesis_validators_root` | **Required** | A `Hash256` for domain separation and chain versioning. +
| Optional | Any other field will be ignored by the signer + +_**Responses**_ + +Success |
+--- | --- +Code | `200` +Content | `{"signature": ""}` + +Where signature is a [BLS signature](https://github.com/ethereum/eth2.0-specs/blob/dev/specs/phase0/beacon-chain.md#bls-signatures) byte array encoded as a hexadecimal string. + +_or_ + +Error |
+--- | --- +Code | `400` +Content | `{"error": ""}` + +_or_ + +Error |
+--- | --- +Code | `404` +Content | `{"error": "Key not found: "}` + +--- + +## Rationale + +### UNIX philosophy: Simple API + +This API specification contains only three methods: one for **status**, one for **listing the available keys**, and one to **produce a signature**. There are no methods for authentication, key management, nor transport encryption. + +The following subsections discuss aspects to be considered by the client implementers relative to these subjects. + +#### Implementation of additional features + +From an API pipeline view, we have two nodes: The validator client (1) that makes requests to the remote signer (2). A more sophisticated chain can be built by introducing elements between these two nodes. Either by setting up reverse proxy services, or by adding plugins to the remote signer implementation. + +#### Authentication + +Can be accomplished through the use of an HTTP Request Header. There are several ways to negotiate and issue a valid token to authenticate the communication between the validator client and the remote signer, each of them with potential drawbacks (e.g replay attacks, challenges in distributing the token to the validator client, etc.). In general, any method of authentication must be combined with transport encryption to be effective. + +The operator can also implement network Access Control Lists (ACLs) between the validator client's network and the remote signer's network, reducing the attack surface by requiring a potential attacker to be positioned in the same network as the validator client. + +#### Key management + +There are several ways to store secret keys, namely Hardware Security Modules (HSM), Secrets management applications (e.g. Hashicorp Vault), cloud storage with tight private network ACL rules, or even raw files in a directory. In general the remote signer implementers will abstract the storage medium from the HTTP API. + +It is in this perspective, that any procedure to create, update, or delete keys should be built separate from the client implementation. + +#### Transport Encryption + +If the operator is working with self-signed certificates, it is required that the client enhancement consuming the remote signer allows this option. + +## Test Cases + +### Test Data + +* BLS Pair + * Public key: `0xb7354252aa5bce27ab9537fd0158515935f3c3861419e1b4b6c8219b5dbd15fcf907bddf275442f3e32f904f79807a2a`. + * Secret key: `0x68081afeb7ad3e8d469f87010804c3e8d53ef77d393059a55132637206cc59ec`. +* Signing root: `0xb6bb8f3765f93f4f1e7c7348479289c9261399a3c6906685e320071a1a13955c`. +* Expected signature: `0xb5d0c01cef3b028e2c5f357c2d4b886f8e374d09dd660cd7dd14680d4f956778808b4d3b2ab743e890fc1a77ae62c3c90d613561b23c6adaeb5b0e288832304fddc08c7415080be73e556e8862a1b4d0f6aa8084e34a901544d5bb6aeed3a612`. + +### `GET /upcheck` + +```bash +# Success + +## Request +curl -v localhost:9000/upcheck + +## Response +* Trying 127.0.0.1:9000... +* TCP_NODELAY set +* Connected to localhost (127.0.0.1) port 9000 (#0) +> GET /upcheck HTTP/1.1 +> Host: localhost:9000 +> User-Agent: curl/7.68.0 +> Accept: */* +> +* Mark bundle as not supporting multiuse +< HTTP/1.1 200 OK +< content-type: application/json +< content-length: 15 +< date: Wed, 30 Sep 2020 02:25:08 GMT +< +* Connection #0 to host localhost left intact +{"status":"OK"} +``` + +### `GET /keys` + +```bash +# Success + +## Request +curl -v localhost:9000/keys + +## Response +* Trying 127.0.0.1:9000... +* TCP_NODELAY set +* Connected to localhost (127.0.0.1) port 9000 (#0) +> GET /publicKeys HTTP/1.1 +> Host: localhost:9000 +> User-Agent: curl/7.68.0 +> Accept: */* +> +* Mark bundle as not supporting multiuse +< HTTP/1.1 200 OK +< content-type: application/json +< content-length: 116 +< date: Wed, 30 Sep 2020 02:25:36 GMT +< +* Connection #0 to host localhost left intact +{"keys":["b7354252aa5bce27ab9537fd0158515935f3c3861419e1b4b6c8219b5dbd15fcf907bddf275442f3e32f904f79807a2a"]} + +# Server Error + +## Preparation +## `chmod` keys directory to the octal 311 (-wx--x--x). + +## Request +curl -v localhost:9000/keys + +## Response +* Trying 127.0.0.1:9000... +* TCP_NODELAY set +* Connected to localhost (127.0.0.1) port 9000 (#0) +> GET /publicKeys HTTP/1.1 +> Host: localhost:9000 +> User-Agent: curl/7.68.0 +> Accept: */* +> +* Mark bundle as not supporting multiuse +< HTTP/1.1 500 Internal Server Error +< content-length: 43 +< date: Wed, 30 Sep 2020 02:26:09 GMT +< +* Connection #0 to host localhost left intact +{"error":"Storage error: PermissionDenied"} +``` + +### `POST /sign/:identifier` + +```bash +# Success + +## Request +curl -v -X POST -d @payload.json -H 'Content-Type: application/json' localhost:9000/sign/b7354252aa5bce27ab9537fd0158515935f3c3861419e1b4b6c8219b5dbd15fcf907bddf275442f3e32f904f79807a2a + +## Response +Note: Unnecessary use of -X or --request, POST is already inferred. +* Trying 127.0.0.1:9000... +* TCP_NODELAY set +* Connected to localhost (127.0.0.1) port 9000 (#0) +> POST /sign/b7354252aa5bce27ab9537fd0158515935f3c3861419e1b4b6c8219b5dbd15fcf907bddf275442f3e32f904f79807a2a HTTP/1.1 +> Host: localhost:9000 +> User-Agent: curl/7.68.0 +> Accept: */* +> Content-Type: application/json +> Content-Length: 84 +> +* upload completely sent off: 84 out of 84 bytes +* Mark bundle as not supporting multiuse +< HTTP/1.1 200 OK +< content-type: application/json +< content-length: 210 +< date: Wed, 30 Sep 2020 02:16:02 GMT +< +* Connection #0 to host localhost left intact +{"signature":"0xb5d0c01cef3b028e2c5f357c2d4b886f8e374d09dd660cd7dd14680d4f956778808b4d3b2ab743e890fc1a77ae62c3c90d613561b23c6adaeb5b0e288832304fddc08c7415080be73e556e8862a1b4d0f6aa8084e34a901544d5bb6aeed3a612"} + +# Bad Request Error + +## Request +curl -v -X POST -d 'foobar' -H 'Content-Type: application/json' localhost:9000/sign/b7354252aa5bce27ab9537fd0158515935f3c3861419e1b4b6c8219b5dbd15fcf907bddf275442f3e32f904f79807a2a + +## Response +Note: Unnecessary use of -X or --request, POST is already inferred. +* Trying 127.0.0.1:9000... +* TCP_NODELAY set +* Connected to localhost (127.0.0.1) port 9000 (#0) +> POST /sign/b7354252aa5bce27ab9537fd0158515935f3c3861419e1b4b6c8219b5dbd15fcf907bddf275442f3e32f904f79807a2a HTTP/1.1 +> Host: localhost:9000 +> User-Agent: curl/7.68.0 +> Accept: */* +> Content-Type: application/json +> Content-Length: 23 +> +* upload completely sent off: 23 out of 23 bytes +* Mark bundle as not supporting multiuse +< HTTP/1.1 400 Bad Request +< content-length: 38 +< date: Wed, 30 Sep 2020 02:15:05 GMT +< +* Connection #0 to host localhost left intact +{"error":"Unable to parse body message from JSON: Error(\"expected ident\", line: 1, column: 2)"} + +# No Keys Available + +## Request +curl -v -X POST -d @payload.json -H 'Content-Type: application/json' localhost:9000/sign/000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +## Response +Note: Unnecessary use of -X or --request, POST is already inferred. +* Trying 127.0.0.1:9000... +* TCP_NODELAY set +* Connected to localhost (127.0.0.1) port 9000 (#0) +> POST /sign/000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 HTTP/1.1 +> Host: localhost:9000 +> User-Agent: curl/7.68.0 +> Accept: */* +> Content-Type: application/json +> Content-Length: 84 +> +* upload completely sent off: 84 out of 84 bytes +* Mark bundle as not supporting multiuse +< HTTP/1.1 404 Not Found +< content-length: 123 +< date: Wed, 30 Sep 2020 02:18:53 GMT +< +* Connection #0 to host localhost left intact +{"error":"Key not found: 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"} + +# Server Error + +## Preparation +## `chmod` both keys directory and file to the octal 311 (-wx--x--x). +## `chmod` back to 755 to delete them afterwards. + +## Request +curl -v -X POST -d @payload.json -H 'Content-Type: application/json' localhost:9000/sign/b7354252aa5bce27ab9537fd0158515935f3c3861419e1b4b6c8219b5dbd15fcf907bddf275442f3e32f904f79807a2a + +## Response +Note: Unnecessary use of -X or --request, POST is already inferred. +* Trying 127.0.0.1:9000... +* TCP_NODELAY set +* Connected to localhost (127.0.0.1) port 9000 (#0) +> POST /sign/b7354252aa5bce27ab9537fd0158515935f3c3861419e1b4b6c8219b5dbd15fcf907bddf275442f3e32f904f79807a2a HTTP/1.1 +> Host: localhost:9000 +> User-Agent: curl/7.68.0 +> Accept: */* +> Content-Type: application/json +> Content-Length: 84 +> +* upload completely sent off: 84 out of 84 bytes +* Mark bundle as not supporting multiuse +< HTTP/1.1 500 Internal Server Error +< content-length: 43 +< date: Wed, 30 Sep 2020 02:21:08 GMT +< +* Connection #0 to host localhost left intact +{"error":"Storage error: PermissionDenied"} +``` + +## Implementation + +Repository Url | Language | Organization | Commentary +--- | --- | --- | --- +[BLS Remote Signer](https://github.com/sigp/rust-bls-remote-signer) | Rust | Sigma Prime | Supports proposed specification. +[Web3signer](https://github.com/PegaSysEng/web3signer) | Java | PegaSys | Supports proposed specification, although with [slightly different methods](https://pegasyseng.github.io/web3signer/web3signer-eth2.html):
{`/sign` => `/api/v1/eth2/sign`, `/publicKeys` => `/api/v1/eth2/publicKeys`}. +[Remote Signing Wallet](https://docs.prylabs.network/docs/wallet/remote/) | Golang | Prysmatics Labs | Supports both gRPC and JSON over HTTP. + +## Security Considerations + +### Threat model + +Let's consider the following threats and their mitigations: + +Threat | Mitigation(s) +--- | --- +An attacker can spoof the validator client. | See the discussion at [Authentication](#authentication). +An attacker can send a crafted message to the signer, leading to a slashing offense. | It is the responsibility of the operator of the remote signer to add a validation module, as discussed at [Implementation of additional features](#implementation-of-additional-features). +An attacker can create, update, or delete secret keys. | Keys are not to be writable via any interface of the remote signer. +An attacker can repudiate a sent message. | Implement logging in the signer. Enhance it by sending logs to a syslog box. +An attacker can disclose the contents of a private key by retrieving the key from storage. | Storage in Hardware security module (HSM).
_or_
Storage in Secrets management applications (e.g. Hashicorp Vault). +An attacker can eavesdrop on the uploading of a secret key. | Upload the keys using a secure channel, based on each storage specification. +An attacker can eavesdrop on the retrieval of a key from the remote signer. | Always pass the data between storage and remote signer node using a secure channel. +An attacker can dump the memory in the remote signer to disclose a secret key. | Prevent physical access to the node running the remote signer.
_or_
Prevent access to the terminal of the node running the remote signer: Logs being sent to a syslog box. Deployments triggered by a simple, non-parameterized API.
_or_
Implement zeroization of the secret key at memory.
_or_
Explore the compilation and running of the remote signer in a Trusted execution environment (TEE). +An attacker can DoS the remote signer. | Implement IP filtering.
_or_
Implement Rate limiting. + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-3041.md b/EIPS/eip-3041.md new file mode 100644 index 00000000000000..20fb247014f386 --- /dev/null +++ b/EIPS/eip-3041.md @@ -0,0 +1,94 @@ +--- +eip: 3041 +title: Adds `baseFee` to `eth_getBlockByHash` +author: Abdelhamid Bakhta (@abdelhamidbakhta) +discussions-to: https://ethereum-magicians.org/t/eip-3041-add-basefee-in-eth-getblockbyhash-response/4825 +status: Draft +type: Standards Track +category: Interface +created: 2020-10-13 +requires: 1474, 1559 +--- + +## Simple Summary +Add basefee field to `eth_getBlockByHash` RPC endpoint response. + +## Abstract +Adds `baseFee` property to the `eth_getBlockByHash` JSON-RPC request `result` object. This property will contain the value of the base fee for any block after the EIP-1559 fork. + +## Motivation +[EIP-1559](./eip-1559.md) introduces a base fee per gas in protocol. +This value is maintained under consensus as a new field in the block header structure. +Users may need value of the base fee at a given block. Base fee value is important to make gas price predictions more accurate. + +## Specification + +### `eth_getBlockByHash` + +#### Description + +Returns information about a block specified by hash. +Every block returned by this endpoint whose block number is before the [EIP-1559](./eip-1559.md) fork block **MUST NOT** include a `baseFee` field. +Every block returned by this endpoint whose block number is on or after the [EIP-1559](./eip-1559.md) fork block **MUST** include a `baseFee` field. + +#### Parameters + +Parameters remain unchanged. + +#### Returns +For the full specification of `eth_getBlockByHash` see [EIP-1474](./eip-1474.md). +Add a new JSON field to the `result` object for block headers containing a base fee (post [EIP-1559](./eip-1559.md) fork block). + +- {[`Quantity`](./eip-1474.md#quantity)} `baseFee` - base fee for this block + +#### Example + +```sh +# Request +curl -X POST --data '{ + "id": 1559, + "jsonrpc": "2.0", + "method": "eth_getBlockByHash", + "params":["0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331", true] +}' + +# Response +{ + "id": 1559, + "jsonrpc": "2.0", + "result": { + "difficulty": "0x027f07", + "extraData": "0x0000000000000000000000000000000000000000000000000000000000000000", + "baseFee": "0x7" + "gasLimit": "0x9f759", + "gasUsed": "0x9f759", + "hash": "0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331", + "logsBloom": "0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331", + "miner": "0x4e65fda2159562a496f9f3522f89122a3088497a", + "nonce": "0xe04d296d2460cfb8472af2c5fd05b5a214109c25688d3704aed5484f9a7792f2", + "number": "0x1b4", + "parentHash": "0x9646252be9520f6e71339a8df9c55e4d7619deeb018d2a3f2d21fc165dde5eb5", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "size": "0x027f07", + "stateRoot": "0xd5855eb08b3387c0af375e9cdb6acfc05eb8f519e419b874b6ff2ffda7ed1dff", + "timestamp": "0x54e34e8e" + "totalDifficulty": "0x027f07", + "transactions": [] + "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncles": [] + } +} +``` + +## Rationale +The addition of a single parameter instead of introducing a whole new endpoint was the simplest change that would be easiest to get integrated. +For backward compatibility we decided to not include the base fee in the response for pre-1559 blocks. + +## Backwards Compatibility +Backwards compatible. Calls related to block prior to [EIP-1559](./eip-1559.md) fork block will omit the base fee field in the response. + +## Security Considerations +The added field (`baseFee`) 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-3044.md b/EIPS/eip-3044.md new file mode 100644 index 00000000000000..9dcd9870214c6d --- /dev/null +++ b/EIPS/eip-3044.md @@ -0,0 +1,94 @@ +--- +eip: 3044 +title: Adds `baseFee` to `eth_getBlockByNumber` +author: Abdelhamid Bakhta (@abdelhamidbakhta) +discussions-to: https://ethereum-magicians.org/t/eip-3044-add-basefee-to-eth-getblockbynumber/4828 +status: Draft +type: Standards Track +category: Interface +created: 2020-10-14 +requires: 1474, 1559 +--- + +## Simple Summary +Add basefee field to `eth_getBlockByNumber` RPC endpoint response. + +## Abstract +Adds `baseFee` property to the `eth_getBlockByNumber` JSON-RPC request `result` object. This property will contain the value of the base fee for any block after the EIP-1559 fork. + +## Motivation +[EIP-1559](./eip-1559.md) introduces a base fee per gas in protocol. +This value is maintained under consensus as a new field in the block header structure. +Users may need value of the base fee at a given block. Base fee value is important to make gas price predictions more accurate. + +## Specification + +### `eth_getBlockByNumber` + +#### Description + +Returns information about a block specified by number. +Every block returned by this endpoint whose block number is before the [EIP-1559](./eip-1559.md) fork block **MUST NOT** include a `baseFee` field. +Every block returned by this endpoint whose block number is on or after the [EIP-1559](./eip-1559.md) fork block **MUST** include a `baseFee` field. + +#### Parameters + +Parameters remain unchanged. + +#### Returns +For the full specification of `eth_getBlockByNumber` see [EIP-1474](./eip-1474.md). +Add a new JSON field to the `result` object for block headers containing a base fee (post [EIP-1559](./eip-1559.md) fork block). + +- {[`Quantity`](./eip-1474.md#quantity)} `baseFee` - base fee for this block + +#### Example + +```sh +# Request +curl -X POST --data '{ + "id": 1559, + "jsonrpc": "2.0", + "method": "eth_getBlockByNumber", + "params":["latest", true] +}' + +# Response +{ + "id": 1559, + "jsonrpc": "2.0", + "result": { + "difficulty": "0x027f07", + "extraData": "0x0000000000000000000000000000000000000000000000000000000000000000", + "baseFee": "0x7" + "gasLimit": "0x9f759", + "gasUsed": "0x9f759", + "hash": "0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331", + "logsBloom": "0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331", + "miner": "0x4e65fda2159562a496f9f3522f89122a3088497a", + "nonce": "0xe04d296d2460cfb8472af2c5fd05b5a214109c25688d3704aed5484f9a7792f2", + "number": "0x1b4", + "parentHash": "0x9646252be9520f6e71339a8df9c55e4d7619deeb018d2a3f2d21fc165dde5eb5", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "size": "0x027f07", + "stateRoot": "0xd5855eb08b3387c0af375e9cdb6acfc05eb8f519e419b874b6ff2ffda7ed1dff", + "timestamp": "0x54e34e8e" + "totalDifficulty": "0x027f07", + "transactions": [] + "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncles": [] + } +} +``` + +## Rationale +The addition of a single parameter instead of introducing a whole new endpoint was the simplest change that would be easiest to get integrated. +For backward compatibility we decided to not include the base fee in the response for pre-1559 blocks. + +## Backwards Compatibility +Backwards compatible. Calls related to block prior to [EIP-1559](./eip-1559.md) fork block will omit the base fee field in the response. + +## Security Considerations +The added field (`baseFee`) 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-3045.md b/EIPS/eip-3045.md new file mode 100644 index 00000000000000..07f0c4ab9945fd --- /dev/null +++ b/EIPS/eip-3045.md @@ -0,0 +1,94 @@ +--- +eip: 3045 +title: Adds `baseFee` to `eth_getUncleByBlockHashAndIndex` +author: Abdelhamid Bakhta (@abdelhamidbakhta) +discussions-to: https://ethereum-magicians.org/t/add-basefee-to-eth-getunclebyblockhashandindex/4829 +status: Draft +type: Standards Track +category: Interface +created: 2020-10-14 +requires: 1474, 1559 +--- + +## Simple Summary +Add basefee field to `eth_getUncleByBlockHashAndIndex` RPC endpoint response. + +## Abstract +Adds `baseFee` property to the `eth_getUncleByBlockHashAndIndex` JSON-RPC request `result` object. This property will contain the value of the base fee for any block after the EIP-1559 fork. + +## Motivation +[EIP-1559](./eip-1559.md) introduces a base fee per gas in protocol. +This value is maintained under consensus as a new field in the block header structure. +Users may need value of the base fee at a given block. Base fee value is important to make gas price predictions more accurate. + +## Specification + +### `eth_getUncleByBlockHashAndIndex` + +#### Description + +Returns information about an uncle specified by block hash and uncle index position +Every block returned by this endpoint whose block number is before the [EIP-1559](./eip-1559.md) fork block **MUST NOT** include a `baseFee` field. +Every block returned by this endpoint whose block number is on or after the [EIP-1559](./eip-1559.md) fork block **MUST** include a `baseFee` field. + +#### Parameters + +Parameters remain unchanged. + +#### Returns +For the full specification of `eth_getUncleByBlockHashAndIndex` see [EIP-1474](./eip-1474.md). +Add a new JSON field to the `result` object for block headers containing a base fee (post [EIP-1559](./eip-1559.md) fork block). + +- {[`Quantity`](./eip-1474.md#quantity)} `baseFee` - base fee for this block + +#### Example + +```sh +# Request +curl -X POST --data '{ + "id": 1559, + "jsonrpc": "2.0", + "method": "eth_getUncleByBlockHashAndIndex", + "params":["0xc6ef2fc5426d6ad6fd9e2a26abeab0aa2411b7ab17f30a99d3cb96aed1d1055b", "0x0"] +}' + +# Response +{ + "id": 1559, + "jsonrpc": "2.0", + "result": { + "difficulty": "0x027f07", + "extraData": "0x0000000000000000000000000000000000000000000000000000000000000000", + "baseFee": "0x7" + "gasLimit": "0x9f759", + "gasUsed": "0x9f759", + "hash": "0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331", + "logsBloom": "0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331", + "miner": "0x4e65fda2159562a496f9f3522f89122a3088497a", + "nonce": "0xe04d296d2460cfb8472af2c5fd05b5a214109c25688d3704aed5484f9a7792f2", + "number": "0x1b4", + "parentHash": "0x9646252be9520f6e71339a8df9c55e4d7619deeb018d2a3f2d21fc165dde5eb5", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "size": "0x027f07", + "stateRoot": "0xd5855eb08b3387c0af375e9cdb6acfc05eb8f519e419b874b6ff2ffda7ed1dff", + "timestamp": "0x54e34e8e" + "totalDifficulty": "0x027f07", + "transactions": [] + "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncles": [] + } +} +``` + +## Rationale +The addition of a single parameter instead of introducing a whole new endpoint was the simplest change that would be easiest to get integrated. +For backward compatibility we decided to not include the base fee in the response for pre-1559 blocks. + +## Backwards Compatibility +Backwards compatible. Calls related to block prior to [EIP-1559](./eip-1559.md) fork block will omit the base fee field in the response. + +## Security Considerations +The added field (`baseFee`) 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-3046.md b/EIPS/eip-3046.md new file mode 100644 index 00000000000000..0804a25defda1e --- /dev/null +++ b/EIPS/eip-3046.md @@ -0,0 +1,94 @@ +--- +eip: 3046 +title: Adds `baseFee` to `eth_getUncleByBlockNumberAndIndex` +author: Abdelhamid Bakhta (@abdelhamidbakhta) +discussions-to: https://ethereum-magicians.org/t/add-basefee-to-eth-getunclebyblocknumberandindex/4830 +status: Draft +type: Standards Track +category: Interface +created: 2020-10-14 +requires: 1474, 1559 +--- + +## Simple Summary +Add basefee field to `eth_getUncleByBlockNumberAndIndex` RPC endpoint response. + +## Abstract +Adds `baseFee` property to the `eth_getUncleByBlockNumberAndIndex` JSON-RPC request `result` object. This property will contain the value of the base fee for any block after the EIP-1559 fork. + +## Motivation +[EIP-1559](./eip-1559.md) introduces a base fee per gas in protocol. +This value is maintained under consensus as a new field in the block header structure. +Users may need value of the base fee at a given block. Base fee value is important to make gas price predictions more accurate. + +## Specification + +### `eth_getUncleByBlockNumberAndIndex` + +#### Description + +Returns information about an uncle specified by block number and uncle index position +Every block returned by this endpoint whose block number is before the [EIP-1559](./eip-1559.md) fork block **MUST NOT** include a `baseFee` field. +Every block returned by this endpoint whose block number is on or after the [EIP-1559](./eip-1559.md) fork block **MUST** include a `baseFee` field. + +#### Parameters + +Parameters remain unchanged. + +#### Returns +For the full specification of `eth_getUncleByBlockNumberAndIndex` see [EIP-1474](./eip-1474.md). +Add a new JSON field to the `result` object for block headers containing a base fee (post [EIP-1559](./eip-1559.md) fork block). + +- {[`Quantity`](./eip-1474.md#quantity)} `baseFee` - base fee for this block + +#### Example + +```sh +# Request +curl -X POST --data '{ + "id": 1559, + "jsonrpc": "2.0", + "method": "eth_getUncleByBlockNumberAndIndex", + "params":["latest", "0x0"] +}' + +# Response +{ + "id": 1559, + "jsonrpc": "2.0", + "result": { + "difficulty": "0x027f07", + "extraData": "0x0000000000000000000000000000000000000000000000000000000000000000", + "baseFee": "0x7" + "gasLimit": "0x9f759", + "gasUsed": "0x9f759", + "hash": "0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331", + "logsBloom": "0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331", + "miner": "0x4e65fda2159562a496f9f3522f89122a3088497a", + "nonce": "0xe04d296d2460cfb8472af2c5fd05b5a214109c25688d3704aed5484f9a7792f2", + "number": "0x1b4", + "parentHash": "0x9646252be9520f6e71339a8df9c55e4d7619deeb018d2a3f2d21fc165dde5eb5", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "size": "0x027f07", + "stateRoot": "0xd5855eb08b3387c0af375e9cdb6acfc05eb8f519e419b874b6ff2ffda7ed1dff", + "timestamp": "0x54e34e8e" + "totalDifficulty": "0x027f07", + "transactions": [] + "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncles": [] + } +} +``` + +## Rationale +The addition of a single parameter instead of introducing a whole new endpoint was the simplest change that would be easiest to get integrated. +For backward compatibility we decided to not include the base fee in the response for pre-1559 blocks. + +## Backwards Compatibility +Backwards compatible. Calls related to block prior to [EIP-1559](./eip-1559.md) fork block will omit the base fee field in the response. + +## Security Considerations +The added field (`baseFee`) 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-3068.md b/EIPS/eip-3068.md new file mode 100644 index 00000000000000..6a27b8bbf416dc --- /dev/null +++ b/EIPS/eip-3068.md @@ -0,0 +1,297 @@ +--- +eip: 3068 +title: Precompile for BN256 HashToCurve Algorithms +author: Dr. Christopher Gorman (@chgormanMH) +discussions-to: https://ethereum-magicians.org/t/pre-compile-for-bls/3973 +status: Draft +type: Standards Track +category: Core +created: 2020-10-23 +requires: 198, 1108 +--- + +## Simple Summary +This EIP defines a hash-to-curve precompile for use in BN256 +and would allow for cheaper BLS signature verification. + +## Abstract +There is currently no inexpensive way to perform BLS signature +verification for arbitrary messages. +This stems from the fact that there is no precompiled contract +in the EVM for a hash-to-curve algorithm for the BN256 elliptic curve. +The gas cost of calling a deterministic hash-to-curve algorithm +written in Solidity is approximately that of one pairing check, +although the latter requires an order of magnitude +more computation. +This EIP remedies this by implementing a hash-to-curve algorithm +for the BN256 G1 curve, which would reduce the cost of +signature verification to essentially that of the pairing check +precompiled contract. +We also include a hash-to-curve algorithm for the BN256 G2 group. + +## Motivation +The precompiled contracts in +[EIP-198](./eip-198.md) and +[EIP-1108](./eip-1108.md) +increased usage of cryptographic operations in the EVM +by reducing the gas costs. +In particular, the cost reduction from +[EIP-1108](./eip-1108.md) +helps increase the use of SNARKs in Ethereum +via an elliptic curve pairing check; +however, a hash-to-curve algorithm enabling arbitrary +BLS signature verification on BN256 in the EVM was noticeably missing. +There is interest in having a precompiled contract which would allow +for signature verification, as noted +[here](https://ethereum-magicians.org/t/pre-compile-for-bls/3973). + +At this time, we are able to perform addition, scalar multiplication, +and pairing checks in BN256. +Reducing these costs in +[EIP-1108](./eip-1108.md) +made [ETHDKG](https://github.com/PhilippSchindler/ethdkg), +a distributed key generation protocol in Ethereum, +less expensive. +ETHDKG by itself is useful; however, what it is lacking is +the ability to verify arbitrary BLS signatures. +Creating group signatures by aggregating partial signatures +is one goal of a DKG protocol. +The DKG enables the computation of partial signatures to be +combined into a group signature offline, but there is no +easy way to verify partial signatures or group signatures +in the EVM. + +In order to perform BLS signature validation, a hash-to-curve +algorithm is required. +While the MapToGroup method initially discussed in the original BLS +[paper](../assets/eip-3068/weilsigs.pdf) +works in practice, the nondeterministic nature of the algorithm +leaves something to be desired as we would like to bound +the overall computational cost in the EVM. +A deterministic method for mapping to BN curves is given +[here](../assets/eip-3068/latincrypt12.pdf); +in the paper, Fouque and Tibouchi proved their mapping +was indifferentiable from a random oracle. +This gives us the desired algorithm. + +## Specification +Here is the pseudocode for the `HashToG1` function: + +``` +function HashToG1(msg) + fieldElement0 = HashToBase(msg, 0x00, 0x01) + fieldElement1 = HashToBase(msg, 0x02, 0x03) + curveElement0 = BaseToG1(fieldElement0) + curveElement1 = BaseToG1(fieldElement1) + g1Element = ECAdd(curveElement0, curveElement1) + return g1Element +end function +``` + +Here is the pseudocode for `HashToBase`; +`msg` is the byte slice to be hashed while `dsp1` and `dsp2` +are domain separation parameters. +`fieldPrime` is the prime of the underlying field. + +``` +function HashToBase(msg, dsp1, dsp2) + hashResult0 = uint256(Keccak256(dsp1||msg)) + hashResult1 = uint256(Keccak256(dsp2||msg)) + constant = 2^256 mod fieldPrime + fieldElement0 = hashResult0*constant mod fieldPrime + fieldElement1 = hashResult1 mod fieldPrime + fieldElement = fieldElement0 + fieldElement1 mod fieldPrime + return fieldElement +end function +``` + +Here is the pseudocode for `BaseToG1`. +All of these operations are performed in the finite field. +`inverse` computes the multiplicative inverse in the underlying +finite field; we have the convention `inverse(0) == 0`. +`is_square(a)` computes the Legendre symbol of the element, +returning 1 if `a` is a square, -1 if `a` is not a square, +and 0 if `a` is 0. +`sqrt` computes the square root of the element in the finite +field; a square root is assumed to exist. +`sign0` returns the sign of the finite field element. + +``` +function BaseToG1(t) + # All operations are done in the finite field GF(fieldPrime) + # Here, the elliptic curve satisfies the equation + # y^2 == g(x) == x^3 + curveB + constant1 = (-1 + sqrt(-3))/2 + constant2 = -3 + constant3 = 1/3 + constant4 = g(1) + s = (constant4 + t^2)^3 + alpha = inverse(t^2*(constant4 + t^2)) + x1 = constant1 - constant2*t^4*alpha + x2 = -1 - x1 + x3 = 1 - constant3*s*alpha + a1 = x1^3 + curveB + a2 = x2^3 + curveB + residue1 = is_square(a1) + residue2 = is_square(a2) + index = (residue1 - 1)*(residue2 - 3)/4 + 1 + coef1 = ConstantTimeEquality(1, index) + coef2 = ConstantTimeEquality(2, index) + coef3 = ConstantTimeEquality(3, index) + x = coef1*x1 + coef2*x2 + coef3*x3 + y = sign0(t)*sqrt(x^3 + curveB) + return (x, y) +end function + +function sign0(t) + if t <= (fieldPrime-1)/2 + return 1 + else + return fieldPrime-1 + end if +end function + +function ConstantTimeEquality(a, b) + # This function operates in constant time + if a == b + return 1 + else + return 0 + end if +end function +``` + +In `HashToG2`, we first map to the underlying twist curve +and then clear the cofactor to map to G2. +Here is the pseudocode for `HashToG2`: + +``` +function HashToG2(msg) + fieldElement00 = HashToBase(msg, 0x04, 0x05) + fieldElement01 = HashToBase(msg, 0x06, 0x07) + fieldElement10 = HashToBase(msg, 0x08, 0x09) + fieldElement11 = HashToBase(msg, 0x0a, 0x0b) + fieldElement0 = (fieldElement00, fieldElement01) + fieldElement1 = (fieldElement10, fieldElement11) + twistElement0 = BaseToTwist(fieldElement0) + twistElement1 = BaseToTwist(fieldElement1) + twistElement = ECAdd(twistElement0, twistElement1) + g2Element = ClearCofactor(twistElement) + return g2Element +end function + +function ClearCofactor(twistElement) + return ECMul(twistElement, cofactor) +end function +``` + +Here is the pseudocode for `BaseToTwist`. + +``` +function BaseToTwist(t) + # All operations are done in the finite field GF(fieldPrime^2) + # Here, the twist curve satisfies the equation + # y^2 == g'(x) == x^3 + curveBPrime + constant1 = (-1 + sqrt(-3))/2 + constant2 = -3 + constant3 = 1/3 + constant4 = g'(1) + s = (constant4 + t^2)^3 + alpha = inverse(t^2*(constant4 + t^2)) + x1 = constant1 - constant2*t^4*alpha + x2 = -1 - x1 + x3 = 1 - constant3*s*alpha + a1 = x1^3 + curveBPrime + a2 = x2^3 + curveBPrime + residue1 = is_square(a1) + residue2 = is_square(a2) + index = (residue1 - 1)*(residue2 - 3)/4 + 1 + coef1 = ConstantTimeEquality(1, index) + coef2 = ConstantTimeEquality(2, index) + coef3 = ConstantTimeEquality(3, index) + x = coef1*x1 + coef2*x2 + coef3*x3 + y = sign0(t)*sqrt(x^3 + curveBPrime) + return (x, y) +end function +``` + +## Rationale +The BaseToG1 algorithm is based on the original Fouque and Tibouchi +[paper](../assets/eip-3068/latincrypt12.pdf) +with modifications based on Wahby and Boneh's +[paper](../assets/eip-3068/2019-403_BLS12_H2C.pdf). +There is freedom in choosing the HashToBase function +and this could easily be changed. +Within HashToBase, the particular hashing algorithm +(Keccak256 in our case) could also be modified. +It may be desired to change the call to `sign0` +at the end of BaseToG1 and BaseToTwist with `is_square`, +as this would result in the same deterministic map to curve from the +Fouque and Tibouchi +[paper](../assets/eip-3068/latincrypt12.pdf) +and ensure HashToG1 is indifferentiable from a random oracle; +they proved this result in their paper. +It may be possible to show that switching the `is_square` +call with `sign0` does not affect indifferentiability, +although this has not been proven. + +The HashToG2 algorithm follows from the Wahby and Boneh +[paper](../assets/eip-3068/2019-403_BLS12_H2C.pdf). +Algorithms for computing `inverse`, `is_square`, and `sqrt` +in finite field GF(fieldPrime^2) can be found +[here](../assets/eip-3068/2012-685_Square_Root_Even_Ext.pdf). + +We now discuss the potential gas cost for the HashToG1 +and HashToG2 operations. +On a local machine, ECMul was clocked at 68 microseconds +per operation. +The same machine clocked HashToG1 at 94 microseconds per operation +when hashing 32 bytes into G1 and 105 microseconds per operation +when hashing 1024 bytes into G1. +Given that it currently costs 6000 gas for ECMul, this gives us +an estimated gas cost for HashToG1 at `8500 + len(bytes)`. +Similarly, HashToG2 was clocked at 886 microseconds per operation +when hashing 32 bytes into G2 and 912 microseconds per operation when +hashing 1024 bytes into G2. +This allows us to estimate the gas cost at `80000 + 3*len(bytes)`. + +## Backwards Compatibility +There are no backward compatibility concerns. + +## Test Cases +TBD + +## Implementation +TBD + +## Security Considerations +Due to recent [work](../assets/eip-3068/2015-1027_exTNFS.pdf), the +128-bit security promised by the BN256 elliptic curve no longer applies; +this was mentioned in the Cloudflare BN256 +[library](https://github.com/cloudflare/bn256). +There has been some discussion on the exact security decrease +from this advancement; see these +[two](../assets/eip-3068/2016-1102_Assessing_NFS_Advances.pdf) +[papers](../assets/eip-3068/2017-334.pdf) +for different estimates. +The more conservative estimate puts the security of BN256 at +100-bits. +While this is likely still out of reach for many adversaries, +it should give us pause. +This reduced security was noted in the recent MadNet +[whitepaper](../assets/eip-3068/madnet.pdf), +and this security concern was partially mitigated by +requiring Secp256k1 signatures of the partial group signatures +in order for those partial signatures to be valid. +Full disclosure: the author of this EIP works for MadHive, +assisted in the development of MadNet, and +helped write the MadNet whitepaper. + +The security concerns of the BN256 elliptic curve +affect any operation using pairing check because it is +related to the elliptic curve pairing; +they are independent of this EIP. + +## Copyright +Copyright and related rights waived via +[CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-3074.md b/EIPS/eip-3074.md new file mode 100644 index 00000000000000..90c5c64f361573 --- /dev/null +++ b/EIPS/eip-3074.md @@ -0,0 +1,196 @@ +--- +eip: 3074 +title: Native Sponsored Transactions +author: Sam Wilson (@SamWilsn) +discussions-to: https://ethereum-magicians.org/t/eip-3074-sponsored-transaction-precompile/4880 +status: Draft +type: Standards Track +category: Core +created: 2020-10-15 +--- + +## Simple Summary + +Creates a new EVM instruction, analogous to `CALL` (`0xF1`), that sets `CALLER` (`0x33`) based on an ECDSA signature. + +## Abstract + +This EIP creates an EVM instruction (`TXCALL`) which forwards a `CALL`, setting `CALLER` according to an ECDSA signature. + +## Motivation + +Sponsored transactions—the separation of fee payment from transaction content—have been a long standing feature request. Unlike similar proposals, this EIP specifies a method of implementing sponsored transactions that allows both externally owned accounts (EOAs) and [EIP-2938](./eip-2938.md) contracts to act as sponsors. + +With the explosion of tokens built on Ethereum, especially stable coins, it has become common for EOAs to hold valuable assets without holding any Ether at all. These assets must be converted to Ether before they can be used to pay gas fees, but without Ether to pay for the conversion, it's impossible to convert them. Sponsored transactions break the circular dependency. + +While it is possible to emulate sponsored transactions (ex. [Gas Station Network](https://www.opengsn.org/)), these solutions require specific support in callee contracts. + +## Specification + +An opcode, at `0xf9`, functions like a `CALL` instruction that additionally: + + - sets the caller addresses based on an ECDSA signature, and + - optionally transfers Ether from the recovered account. + +### Definitions + + - **`TXCALL`** - the specific instruction encoded as `0xf9`, introduced by this EIP, which implements the `CALL` analogue. + - **Transaction-like Package** - the signed arguments passed to `TXCALL`. + - **Sponsor** - the account which is responsible for paying gas fees and sending the transaction. + - **Sponsee** - the account which signed the transaction-like package. + - **Invoker** - the account or contract which contains `TXCALL`. + - **Callee** - the target of the call from `TXCALL`. + +### Constants + +| Constant | Value | Description | +| ---------------- | ------ |:----------------------------------------------------------------------------------- | +| `SPONSORED_TYPE` | `0x03` | [EIP-2718](./eip-2718.md) transaction type reserved for transaction-like packages. | + +### API + +#### Inputs + +`TXCALL` requires the following stack arguments: + +| `top - 0` | `top - 1` | `top - 2` | `top - 3` | `top - 4` | `top - 5` | +| --------- | --------- | ------------ | ------------ | ----------- | ----------- | +| `gas` | `value` | `argsOffset` | `argsLength` | `retOffset` | `retLength` | + + +The arguments memory region shall be encoded as `type || abi.encode(v, r, s, sponsee, nextra, mingas, to, data)`. + +The signature (`v`, `r`, `s`) arguments are computed from `secp256k1(keccak256(type || abi.encode(invoker, chainid, value, nextra, mingas, to, data)))`. + +The arguments are: + + - `type: uint8` - [EIP-2718](./eip-2718.md) transaction type (currently always `SPONSORED_TYPE`); + - `sponsee: address` - address of the sponsee; + - `nextra: uint256` - extra data, which can be used in the invoker to implement replay protection; + - `to: address` - address of the callee; + - `mingas: uint256` - minimum gas limit which must be provided with the call into `TXCALL`; + - `value: uint256` - exact amount of Ether in wei to be received by the callee; + - `data: bytes` - the calldata for the call into `to`; and + - `v: uint8`, `r: bytes32`, `s: bytes32` - signature for the package, including chain id as specified in [EIP-155](./eip-155.md). + +#### Outputs + +`TXCALL` pushes the following two values onto the stack: + +| `top - 0` | `top - 1` | +| ------------- | ----------------- | +| `success` | `calleeSuccess` | + + +##### `success` + +`success` shall be zero in the following cases: + - `type != SPONSORED_TYPE` + - Invalid signature + - The address recovered from `v`, `r`, and `s` does not match `sponsee` + - Gas limit supplied with the call into `TXCALL` is less than the signed `mingas` + - The transaction's remaining gas is less than the signed `mingas` + - The value sent with the call is not equal to the signed `value` + - The current execution context is static (i.e. `STATICCALL`) and `value` is non-zero + +`success` shall be a one in all other cases. + +##### `calleeSuccess` + +`calleeSuccess` shall be zero in the following cases: + - `success == 0` + - the code execution failed due to an exceptional halting or revert + - call depth limit has been reached + +`calleeSuccess` shall be a one in all other cases. + +##### Return Data + +The memory region defined by `retOffset` and `retLength` shall be filled in the same way as the `CALL` instruction with similar arguments. + +The return data area accessed with `RETURNDATASIZE` (`0x3d`) and `RETURNDATACOPY` (`0x3e`) shall be set in the same way as the `CALL` instruction. + +### Gas Fees + +The gas fees for `TXCALL` are calculated according to the following pseudo-code: + +```python +S_cd = len(data) # In 256-bit words, rounded up + +fees = 3200 + (6 * S_cd) + +if preconditions_good(...): + return fees + cost_of_call(...) +else: + return fees +``` + +Where `len(data)` is the length of the region of memory defined by `argsOffset` and `argsLength`, rounded up to the nearest 256-bit word, and `cost_of_call(...)` is the cost of a `CALL` (`0xF1`) instruction with the same `gas`, `value`, `argsOffset`, `argsLength`, `retOffset`, and `retLength` arguments. + +## Rationale + +### Omitting Arguments + +The signature arguments `value`, `chainid`, and `invoker` are not included in the memory region arguments to the instruction because they can be calculated by the instruction itself. + +### Two Return Values + +It is important to differentiate between a failure in `TXCALL`'s preconditions versus a failure in the callee. Correctly implementing replay protection requires the invoker to change its state even if the callee fails (to burn the nonce) but doing so if, for example, the signature failed would be nonsensical. Several options exist for encoding these two failure cases: returning two stack elements, reserving a specific revert reason, or choosing different values in a single stack element. + +First, it's important to note that all three options are a deviation from the semantics of other `CALL` opcodes, but this deviation is unavoidable. + +Reserving a specific revert reason, for example `txcall failed`, is a large departure from other instructions. An invoker would need to inspect the revert reason to determine whether the callee reverted, or the `TXCALL` pre-conditions were invalidated, which implies reading and comparing memory values. Further, to remain sound when a callee reverts with `txcall failed`, `TXCALL` would need to replace the return data with some other value. + +Returning a single stack element with different values depending on the situation (ex. `0` on success, `1` when the pre-conditions are violated, and `2` when the callee reverts) introduces the opportunity for a subtle bug: it's trivially easy to misinterpret the return value (`CALL` returns non-zero on success), but it's much harder to ignore a whole new stack value. + +### Sponsee in Arguments + +Including `sponsee` in the arguments to `TXCALL` is a gas optimization. Without it, invokers would have to do their own `ecrecover` before calling into `TXCALL` to verify/adjust any state for replay protection. + +### Reserving an [EIP-2718](./eip-2718.md) Transaction Type + +While clients should never directly interpret transaction-like packages as true transactions, reserving an [EIP-2718](./eip-2718.md) transaction type for transaction-like packages reduces the likelihood of a transaction-like package being misinterpreted as a true transaction. + +### Another Sponsored Transaction EIP + +Other approaches to sponsored transactions, which rely on introducing a new transaction type, are not immediately compatible with account abstraction (AA). These proposals require a _signed_ transaction from the sponsor's account, which is not possible from an AA contract, because it has no private key to sign with. + +Besides better compatibility with AA, an instruction is a much less intrusive change than a new transaction type. This approach requires no changes in existing wallets, and little change in other tooling. + +`TXCALL`'s single purpose is to set `CALLER`. It implements the minimal functionality to enable sender abstraction for sponsored transactions. This single mindedness makes `TXCALL` significantly more composable with existing Ethereum features. + +More logic can be implemented around the call into `TXCALL`, giving more control to invokers and sponsors without sacrificing security or user experience for sponsees. + +### Lack of Replay Protection + +Earlier approaches to this problem included mechanisms for replay protection. This proposal explicitly does not handle replay protection, but instead includes a signed-but-unused field (`nextra`) which is expected to be used by invoker contracts to implement replay protection. Delegating replay protection to the invoker sidesteps the issue of giving a precompile contract its own storage, while opening the door to more innovative replay protection methods in the future. + +## Backwards Compatibility + +No known issues. + +## Test Cases + +TODO + +## Implementation + +TODO + +## Security Considerations + +### Reentrancy + + - Checking `msg.sender == tx.origin` no longer prevents reentrancy. _Adding the pre-condition that `sponsor != sponsee` would restore this property._ + +### Signature Verification & Reply Protection + + - Potential impersonation attacks if there is a bug in the signature verification. + - Replay protection can be poorly implemented (or even maliciously broken) in the invoker. + +### Frontrunning + + - Transaction-like packages can be extracted from the original sponsor's transaction and resent by another sponsor. + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-3076.md b/EIPS/eip-3076.md new file mode 100644 index 00000000000000..c55c8ae9dbbd0a --- /dev/null +++ b/EIPS/eip-3076.md @@ -0,0 +1,266 @@ +--- +eip: 3076 +title: Slashing Protection Interchange Format +author: Michael Sproul (@michaelsproul), Sacha Saint-Leger (@sachayves), Danny Ryan (@djrtwo) +discussions-to: https://ethereum-magicians.org/t/eip-3076-validator-client-interchange-format-slashing-protection/ +status: Review +type: Standards Track +category: Core +created: 2020-10-27 +updated: 2021-02-08 +--- + +## Simple Summary + +A JSON interchange format for proof of stake validators to migrate slashing protection data between clients. + +## Abstract + +A standard format for transferring a key's signing history allows validators to easily switch between clients without the risk of signing conflicting messages. While a [common keystore format](https://eips.ethereum.org/EIPS/eip-2335) provides part of the solution, it does not contain any information about a key's signing history. For a validator moving their keys from client A to client B, this could lead to scenarios in which client B inadvertently signs a message that conflicts with an earlier message signed with client A. The interchange format described here provides a solution to this problem. + +## Motivation + +The proof of stake (PoS) protocol penalises validators for voting in ways that could result in two different versions of the chain being finalised. These types of penalties are called slashings. + +For a validator following the protocol correctly, there is, in principle, no risk of being slashed. However, changing clients (from client A to client B, say) can result in a slashing risk if client B is unaware of the blocks and attestations that were signed with client A. + +This can can occur if client A and client B do not agree on what the present time is. For example, say client A's time is accidentally set to a day in the future (225 epochs), and a validator switches from client A to client B without giving B a record of the blocks and attestations signed with A. The validator in question now runs the risk of attesting to two different blocks in the same epoch (a slashable offence) for the next 225 epochs (since they've already voted on these epochs with client A, and now stand to vote on them again with client B). Such time-skew bugs have been observed in the wild. + +Another situation in which slashing protection is critical is in the case of re-orgs. During a re-org it is possible for a validator to be assigned new attestation duties for an epoch in which it has already signed an attestation. In this case it is essential that the record of the previous attestation is available, even if the validator just moved from one client to another in the space of a single epoch. + +## Specification + +### JSON Schema + +A valid interchange file is one that adheres to the following JSON schema, and is interpreted according to the [Conditions](#conditions). + +```json +{ + "title": "Signing history", + "description": "This schema provides a record of the blocks and attestations signed by a set of validators", + "type": "object", + "properties": { + "metadata": { + "type": "object", + "properties": { + "interchange_format_version": { + "type": "string", + "description": "The version of the interchange format that this document adheres to" + }, + "genesis_validators_root": { + "type": "string", + "description": "Calculated at Genesis time; serves to uniquely identify the chain" + } + }, + "required": [ + "interchange_format_version", + "genesis_validators_root" + ] + }, + "data": { + "type": "array", + "items": [ + { + "type": "object", + "properties": { + "pubkey": { + "type": "string", + "description": "The BLS public key of the validator (encoded as a 0x-prefixed hex string)" + }, + "signed_blocks": { + "type": "array", + "items": [ + { + "type": "object", + "properties": { + "slot": { + "type": "string", + "description": "The slot number of the block that was signed" + }, + "signing_root": { + "type": "string", + "description": "The output of compute_signing_root(block, domain)" + } + }, + "required": [ + "slot" + ] + } + ] + }, + "signed_attestations": { + "type": "array", + "items": [ + { + "type": "object", + "properties": { + "source_epoch": { + "type": "string", + "description": "The attestation.data.source.epoch of the signed attestation" + }, + "target_epoch": { + "type": "string", + "description": "The attestation.data.target.epoch of the signed attestation" + }, + "signing_root": { + "type": "string", + "description": "The output of compute_signing_root(attestation, domain)" + } + }, + "required": [ + "source_epoch", + "target_epoch" + ] + } + ] + } + }, + "required": [ + "pubkey", + "signed_blocks", + "signed_attestations" + ] + } + ] + } + }, + "required": [ + "metadata", + "data" + ] +} +``` + +### Example JSON Instance + +```json +{ + "metadata": { + "interchange_format_version": "5", + "genesis_validators_root": "0x04700007fabc8282644aed6d1c7c9e21d38a03a0c4ba193f3afe428824b3a673" + }, + "data": [ + { + "pubkey": "0xb845089a1457f811bfc000588fbb4e713669be8ce060ea6be3c6ece09afc3794106c91ca73acda5e5457122d58723bed", + "signed_blocks": [ + { + "slot": "81952", + "signing_root": "0x4ff6f743a43f3b4f95350831aeaf0a122a1a392922c45d804280284a69eb850b" + }, + { + "slot": "81951" + } + ], + "signed_attestations": [ + { + "source_epoch": "2290", + "target_epoch": "3007", + "signing_root": "0x587d6a4f59a58fe24f406e0502413e77fe1babddee641fda30034ed37ecc884d" + }, + { + "source_epoch": "2290", + "target_epoch": "3008" + } + ] + } + ] +} +``` + +### Conditions + +After importing an interchange file with data field `data`, a signer must respect the following conditions: + +1. Refuse to sign any block that is slashable with respect to the blocks contained in `data.signed_blocks`. For details of what constitutes a slashable block, see [process_proposer_slashing][pps]. If the `signing_root` is absent from a block, a signer must assume that any new block with the same `slot` is slashable with respect to the imported block. + +2. Refuse to sign any block with `slot <= min(b.slot for b in data.signed_blocks if b.pubkey == proposer_pubkey)`, except if it is a repeat signing as determined by the `signing_root`. + +3. Refuse to sign any attestation that is slashable with respect to the attestations contained in `data.signed_attestations`. For details of what constitutes a slashable attestation, see [is_slashable_attestation_data][isad]. +4. Refuse to sign any attestation with source epoch less than the minimum source epoch present in that signer's attestations (as seen in `data.signed_attestations`). In pseudocode: +```python3 +source.epoch < + min(att.source_epoch + for att in data.signed_attestations + if att.pubkey == attester_pubkey) +``` + +5. Refuse to sign any attestation with target epoch less than or equal to the minimum target epoch present in that signer's attestations (as seen in `data.signed_attestations`). In pseudocode: + +```python3 +target_epoch <= + min(att.target_epoch + for att in data.signed_attestations + if att.pubkey == attester_pubkey) +``` + +### Additional Information + +- The `interchange_format_version` version is set to 5. + +- A signed block or attestation's `signing_root` refers to the message data (hash tree root) that gets signed with a BLS signature. It allows validators to re-sign and re-broadcast blocks or attestations if asked. + +- The `signed_blocks` `signing_root`s are calculated using [`compute_signing_root(block, domain)`][csr]: where `block` is the block (of type `BeaconBlock` or `BeaconBlockHeader`) that was signed, and `domain` is equal to [`compute_domain(DOMAIN_BEACON_PROPOSER, fork, metadata.genesis_validators_root)`][cd]. + +- The `signed_attestations` `signing_root`s are calculated using [`compute_signing_root(attestation, domain)`][csr]: where `attestation` is the attestation (of type `AttestationData`) that was signed, and `domain` is equal to [`compute_domain(DOMAIN_BEACON_ATTESTER, fork, metadata.genesis_validators_root)`][cd]. + +[pps]: https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#proposer-slashings +[isad]: https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#is_slashable_attestation_data +[csr]: https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#compute_signing_root +[cd]: https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#compute_domain + + +## Rationale + +### Supporting Different Strategies + +The interchange format is designed to be flexible enough to support the full variety of slashing protection strategies that clients may implement, which may be categorised into two main types: + +1. **Complete**: a database containing every message signed by each validator. +2. **Minimal**: a database containing only the latest messages signed by each validator. + +The advantage of the minimal strategy is its simplicity and succinctness. Using only the latest messages for each validator, safe slashing protection can be achieved by refusing to sign messages for slots or epochs prior. + +On the other hand, the complete strategy can provide safe slashing protection while also avoiding false positives (meaning that it only prevents a validator from signing if doing so would guarantee a slashing). + +The two strategies are unified in the interchange format through the inclusion of [conditions](#conditions) (2), (4) and (5). This allows the interchange to transfer detailed or succinct information, as desired. + +### Integer Representation + +Most fields in the JSON schema are strings. For fields in which it is possible to encode the value as either a string or an integer, strings were chosen. This choice was made in order to avoid issues with different languages supporting different ranges of integers (specifically JavaScript, where the `number` type is a 64-bit float). If a validator is yet to sign a block or attestation, the relevant list is simply left empty. + +### Versioning + +The `interchange_format_version` is set to 5 because the specification went through several breaking changes during its design, incorporating feedback from implementers. + + +## Backwards Compatibility + +This specification is not backwards-compatible with previous draft versions that used version numbers less than 5. + + +## Security Considerations + +In order to minimise risk and complexity, the format has been designed to map cleanly onto the internal database formats used by implementers. Nevertheless, there are a few pitfalls worth illuminating. + +### Advice for Complete Databases + +For implementers who use a complete record of signed messages to implement their slashing protection database, we make the following recommendations: + +* You MUST ensure that, in addition to importing all of the messages from an interchange, all the [conditions](#conditions) are enforced. In particular, conditions (2), (4) and (5) may not have been enforced by your implementation before adopting the interchange format. Our recommendation is to enforce these rules at all times, to keep the implementation clean and minimise the attack surface. For example: your slashing protection mechanism should not sign a block with a slot number less than, or equal to, the minimum slot number of a previously signed block, _irrespective_ of whether that minimum-slot block was imported from an interchange file, or inserted as part of your database's regular operation. +* If your database records the signing roots of messages in addition to their slot/epochs, you should ensure that imported messages without signing roots are assigned a suitable dummy signing root internally. We suggest using a special "null" value which is distinct from all other signing roots, although a value like `0x0` may be used instead (as it is extremely unlikely to collide with any real signing root). +* Care must be taken to avoid signing messages within a gap in the database (an area of unknown signing activity). This could occur if two interchanges were imported with a large gap between the last entry of the first and the first entry of the second. Signing in this gap is not safe, and would violate conditions (2), (4) and (5). It can be avoided by storing an explicit low watermark in addition to the actual messages of the slashing protection database, or by pruning on import so that the oldest messages from the interchange become the oldest messages in the database. + +### Advice for Minimal Databases + +For implementers who wish to implement their slashing protection database by storing only the latest block and attestation for each validator, we make the following recommendations: + +* During import, make sure you take the _maximum_ slot block and _maximum_ source and target attestations for each validator. Although the [conditions](#conditions) require the minimums to be enforced, taking the maximums from an interchange file and merging them with any existing values in the database is the recommended approach. For example, if the interchange file includes blocks for validator `V` at slots 4, 98 and 243, then the latest signed block for validator `V` should be updated to the one from slot 243. However, if the database has already included a block for this validator at a slot greater than 243, for example, slot 351, then the database's existing value should remain unchanged. + +### General Recommendations + +* To avoid exporting an outdated interchange file -- an action which creates a slashing risk -- your implementation should only allow the slashing protection database to be exported when the validator client or signer is _stopped_ -- in other words, when the client or signer is no longer adding new messages to the database. +* Similarly, your implementation should only allow an interchange file to be imported when the validator client is stopped. + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-3085.md b/EIPS/eip-3085.md new file mode 100644 index 00000000000000..964d3697a95aa8 --- /dev/null +++ b/EIPS/eip-3085.md @@ -0,0 +1,249 @@ +--- +eip: 3085 +title: Wallet Add Ethereum Chain RPC Method (`wallet_addEthereumChain`) +author: Erik Marks (@rekmarks), Pedro Gomes (@pedrouid) +discussions-to: https://ethereum-magicians.org/t/eip-3085-wallet-addethereumchain/5469 +status: Review +type: Standards Track +category: Interface +created: 2020-11-01 +requires: 155, 695 +--- + +## Simple Summary + +An RPC method for adding Ethereum chains to wallet applications. + +## Abstract + +The `wallet_addEthereumChain` RPC method allows Ethereum applications ("dapps") to suggest chains to be added to the user's wallet application. +The caller must specify a chain ID and some chain metadata. +The wallet application may arbitrarily refuse or accept the request. +`null` is returned if the chain was added, and an error otherwise. + +## Motivation + +All dapps require the user to interact with one or more Ethereum chains in order to function. +Any given chain may or may not be supported by the user's wallet application. +`wallet_addEthereumChain` enables dapps to request chains to be added to the user's wallet. +This enables UX improvements for both dapps and wallets. + +## 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](https://www.ietf.org/rfc/rfc2119.txt). + +### `wallet_addEthereumChain` + +The method accepts a single object parameter, with a `chainId` and some chain metadata. +The method returns `null` if the chain was added to the wallet, and an error otherwise. + +The wallet **MAY** reject the request for any reason. + +> Note that this method makes **no** statement about whether the wallet should change the user's currently selected chain, if the wallet has a concept thereof. + +#### Parameters + +`wallet_addEthereumChain` accepts a single object parameter, specified by the following TypeScript interface: + +```typescript +interface AddEthereumChainParameter { + chainId: string; + blockExplorerUrls?: string[]; + chainName?: string; + iconUrls?: string[]; + nativeCurrency?: { + name: string; + symbol: string; + decimals: number; + }; + rpcUrls?: string[]; +} +``` + +Only the `chainId` is required per this specification, but a wallet **MAY** require any other fields listed, impose additional requirements on them, or ignore them outright. +If a field does not meet the requirements of this specification and the wallet does not ignore the field, the wallet **MUST** reject the request. + +- `chainId` + - **MUST** specify the integer ID of the chain as a hexadecimal string, per the [`eth_chainId`](./eip-695.md) Ethereum RPC method. + - The wallet **SHOULD** compare the specified `chainId` value with the `eth_chainId` return value from the endpoint. + If these values are not identical, the wallet **MUST** reject the request. +- `blockExplorerUrls` + - If provided, **MUST** specify one or more URLs pointing to block explorer web sites for the chain. +- `chainName` + - If provided, **MUST** specify a human-readable name for the chain. +- `iconUrls` + - If provided, **MUST** specify one or more URLs pointing to reasonably sized images that can be used to visually identify the chain. +- `nativeCurrency` + - If provided, **MUST** describe the native currency of the chain using the `name`, `symbol`, and `decimals` fields. + - `decimals` **MUST** be a non-negative integer. + - `name` and `symbol` **SHOULD** be human-readable strings. +- `rpcUrls` + - If provided, **MUST** specify one or more URLs pointing to RPC endpoints that can be used to communicate with the chain. + +All URL strings **MUST** include the protocol component of the URL. +HTTPS **SHOULD** always be used over HTTP. + +#### Returns + +The method **MUST** return `null` if the request was successful, and an error otherwise. + +A request to add a chain that was already added **SHOULD** be considered successful. + +The wallet **MUST NOT** allow the same `chainId` to be added multiple times. +See [Security Considerations](#security-considerations) for more information. + +### Examples + +These examples use JSON-RPC, but the method could be implemented using other RPC protocols. + +To add the Goerli test chain: + +```json +{ + "id": 1, + "jsonrpc": "2.0", + "method": "wallet_addEthereumChain", + "params": [ + { + "chainId": "0x5", + "chainName": "Goerli", + "rpcUrls": ["https://goerli.infura.io/v3/INSERT_API_KEY_HERE"], + "nativeCurrency": { + "name": "Goerli ETH", + "symbol": "gorETH", + "decimals": 18 + }, + "blockExplorerUrls": ["https://goerli.etherscan.io"] + } + ] +} +``` + +To add POA Network's xDAI chain: + +```json +{ + "id": 1, + "jsonrpc": "2.0", + "method": "wallet_addEthereumChain", + "params": [ + { + "chainId": "0x64", + "chainName": "xDAI Chain", + "rpcUrls": ["https://dai.poa.network"], + "iconUrls": [ + "https://xdaichain.com/fake/example/url/xdai.svg", + "https://xdaichain.com/fake/example/url/xdai.png" + ], + "nativeCurrency": { + "name": "xDAI", + "symbol": "xDAI", + "decimals": 18 + } + } + ] +} +``` + +In the above example, notice that the `iconUrls` array contains URLs pointing to two different image formats. + +A success response: + +```json +{ + "id": 1, + "jsonrpc": "2.0", + "result": null +} +``` + +A failure response: + +```json +{ + "id": 1, + "jsonrpc": "2.0", + "error": { + "code": 4001, + "message": "The user rejected the request." + } +} +``` + +## Rationale + +The design of `wallet_addEthereumChain` is deliberately ignorant of what it means to "add" a chain to a wallet. +The meaning of "adding" a chain to a wallet depends on the wallet implementation. + +When calling the method, specifying the `chainId` will always be necessary, since in the universe of Ethereum chains, the [EIP-155](./eip-155.md) chain ID is effectively the chain GUID. +The remaining parameters amount to what, in the estimation of the authors, a wallet will minimally require in order to effectively support a chain and represent it to the user. +The network ID (per the `net_version` RPC method) is omitted since it is effectively superseded by the chain ID. + +For [security reasons](#security-considerations), a wallet should always attempt to validate the chain metadata provided by the requester, and may choose to fetch the metadata elsewhere entirely. +Either way, only the wallet can know which chain metadata it needs from the requester in order to "add" the chain. +Therefore, all parameters except `chainId` are specified as optional, even though a wallet may require them in practice. + +This specification does not mandate that the wallet "switches" its "active" or "currently selected" chain after a successful request, if the wallet has a concept thereof. +Just like the meaning of "adding" a chain, "switching" between chains is a wallet implementation detail, and therefore out of scope. + +For related work, see [EIP-2015](./eip-2015.md). + +## Security Considerations + +`wallet_addEthereumChain` is a powerful method that exposes the end user to serious risks if implemented incorrectly. +Many of these risks can be avoided by validating the request data in the wallet, and clearly disambiguating different chains in the wallet UI. + +### Chain IDs + +Since the chain ID used for transaction signing determines which chain the transaction is valid for, handling the chain ID correctly is of utmost importance. +The wallet should: + +- Ensure that a submitted chain ID is valid. + - It should be a `0x`-prefixed hexadecimal string per [EIP-695](./eip-695.md), and parse to an integer number. +- Prevent the same chain ID from being added multiple times. + - See the next section for how to handle multiple RPC endpoints. +- Only use the submitted chain ID to sign transactions, **never** a chain ID received from an RPC endpoint. + - A malicious or faulty endpoint could return arbitrary chain IDs, and potentially cause the user to sign transactions for unintended chains. +- Verify that the specified chain ID matches the return value of `eth_chainId` from the endpoint, as described [above](#parameters). + +### RPC Endpoints and RPC URLs + +Wallets generally interact with chains via an RPC endpoint, identified by some URL. +Most wallets ship with a set of chains and corresponding trusted RPC endpoints. +The endpoints identified by the `rpcUrls` parameter cannot be assumed to be honest, correct, or even pointing to the same chain. +Moreover, even trusted endpoints can expose users to privacy risks depending on their data collection practices. + +Therefore, the wallet should: + +- Inform users that their on-chain activity and IP address will be exposed to RPC endpoints. +- If an endpoint is unknown to the wallet, inform users that the endpoint may behave in unexpected ways. +- Observe good web security practices when interacting with the endpoint, such as require HTTPS. +- Clearly inform the user which RPC URL is being used to communicate with a chain at any given moment, and inform the user of the risks of using multiple RPC endpoints to interact with the same chain. + +### Validating Chain Data + +A wallet that implements `wallet_addEthereumChain` should expect to encounter requests for chains completely unknown to the wallet maintainers. +That said, community resources exist that can be leveraged to verify requests for many Ethereum chains. +The wallet should maintain a list of known chains, and verify requests to add chains against that list. +Indeed, a wallet may even prefer its own chain metadata over anything submitted with a `wallet_addEthereumChain` request. + +### UX + +Adding a new chain to the wallet can have significant implications for the wallet's functionality and the experience of the user. +A chain should never be added without the explicit consent of the user, and different chains should be clearly differentiated in the wallet UI. +In service of these goals, the wallet should: + +- When receiving a `wallet_addEthereumChain` request, display a confirmation informing the user that a specific requester has requested that the chain be added. +- Ensure that any chain metadata, such as `nativeCurrency` and `blockExplorerUrls`, are validated and used to maximum effect in the UI. +- If any images are provided via `iconUrls`, ensure that the user understands that the icons could misrepresent the actual chain added. +- If the wallet UI has a concept of a "currently selected" or "currently active" chain, ensure that the user understands when a chain added using `wallet_addEthereumChain` becomes selected. + +### Preserving User Privacy + +Although a request to add a chain that was already added should generally be considered a success, treating such requests as _automatic_ successes leaks information to requesters about the chains a user has added to their wallet. +In the interest of preserving user privacy, implementers of `wallet_addEthereumChain` should consider displaying user confirmations even in these cases. +If the user denies the request, the wallet should return the same user rejection error as normal so that requesters cannot learn which chains are supported by the wallet without explicit permission to do so. + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-3091.md b/EIPS/eip-3091.md new file mode 100644 index 00000000000000..24495eef755e30 --- /dev/null +++ b/EIPS/eip-3091.md @@ -0,0 +1,45 @@ +--- +eip: 3091 +title: Block Explorer API Routes +author: Pedro Gomes (@pedrouid) +discussions-to: https://ethereum-magicians.org/t/eip-3091-block-explorer-api-routes/4907 +status: Draft +type: Standards Track +category: Interface +created: 2020-11-02 +--- + +## Simple Summary +Standard API Routes for Blockchain explorers + +## Abstract +This proposal brings standardization between block explorers API routes when linking transactions, blocks, accounts and tokens. + +## Motivation +Currently wallets will link transactions and accounts to block explorers web pages but as chain diversity and layer two solutions grow it becomes harder to maintain a consistent user experience. Adding new chains or layer two solutions becomes harder given these endpoints are inconsistent. Standardizing the API routes to these links improves interoperability between wallets and block explorers. This EIP makes RPC endpoints like [EIP-2015](./eip-2015.md) more feasible. + +## Specification +Block explorers will route their webpages accordingly for the following data: + +### Blocks +/block/ + + +### Transactions +/tx/ + +### Accounts +/address/ + + +### ERC-20 Tokens +/token/ + +## Backward Compatibility +This EIP was designed with existing API routes in mind to reduce disruption. Incompatible block explorers should include either 301 redirects to their existing API routes to match this EIP. + +## Security Considerations +TBD + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-3102.md b/EIPS/eip-3102.md new file mode 100644 index 00000000000000..54442ddd2d1bc1 --- /dev/null +++ b/EIPS/eip-3102.md @@ -0,0 +1,183 @@ +--- +eip: 3102 +title: Binary trie structure +author: Guillaume Ballet (@gballet), Vitalik Buterin (@vbuterin) +status: Draft +discussions-to: https://ethresear.ch/t/binary-trie-format/7621 +status: Draft +type: Standards Track +category: Core +created: 2020-09-01 +--- + +## Simple Summary + +Change the storage structure from hexary to binary, merge the account and storage tries, and use blake2b. + +## Abstract + +This proposal presents a binary structure and merkelization rule for the account and storage tries, which are merged into a single “state” trie. RLP and most of the MPT’s optimizations are dropped to simplify the design. Keccak256 is replaced with blake2b. + +## Motivation + +The current design of the Merkle Patricia Trie (MPT) uses an hexary trie. Hexary Merkle trees are more shallow than their binary counterparts, which means less hashing. +Over the course of the 5 years of Ethereum’s existence, it has become apparent that disk accesses are a greater bottleneck than hashing. Clients are therefore moving away from a storage model in which all internal nodes are stored, in favor of a flat (key, value) storage model first used by turbo-geth, in which the intermediate nodes are recalculated only when needed. + +There is a push for making Ethereum easier to use in a stateless fashion. Binary tries make for smaller (~4x) proofs than hexary tries, making it the design of choice for a stateless-friendly Ethereum. + +For that same reason, the account and storage tries are merged in order to have a single proof for all changes. + +The MPT design is also rife with uncanny optimizations for size, that have a limited effect - at the cost of prohibitive complexity. For example, nesting for children whose RLP is less than 32 bytes saves an estimated 1MB of disk space. A paltry compared to the 300GB required by a fast sync at the time of this writing. These optimizations are a significant source of errors, and therefore a consensus-breaking risk. +The reliance on RLP has also been criticized for its complexity, while the overhead of a general-purpose encoding scheme isn’t warranted for the rigid structure of a Merkle trie. + +The desire to switch the storage model from an hexary trie to a binary trie provides an opportunity to adopt a simpler trie architecture that pushes optimizations from the protocol level down to that of the client implementors. + +## Specification + +### Conventions + +| Code | Description | +| :-: | - | +| `u256(x)` | Big endian, 32-byte representation of number _x_ | +|`||` | Byte-wise concatenation operator| +| `++` | Bit-wise concatenation operator | +| `0b0101` | The binary string `0101` | +| `hash()` | The usual hashing function | +| `empty_hash` | The empty hash: `hash("")` | +| `length(x)` | The byte length of object `x` | +| `d[a..b]` | The big-endian bit sequence taken from byte sequence `d`, starting at bit index `a`, up to and including the bit at index `b`. | + +### Notable changes from the hexary structure + + * Account and storage tries are merged, with key length between 32 and 64 bytes; + * RLP is no longer used; + * The "leaf marker" bit used in the hex prefix is also dropped. Leaves are identified as nodes with no children; + * Serialized nodes are hashed, no matter how small the byte length of the serialized nodes. + +### The trie + +#### Structure + +The trie structure is made up of _nodes_. A node `N ≡ (N_l,N_r,N_p,N_v)` has the following 4 components: + + * `N_l` is the hash to the node's _left child_. If the node does not have a left child, then `N_l` is the empty hash `empty_hash`; + * `N_r` is the hash to the node's _right child_. If the node does not have a right child, then `N_r` is the empty hash `empty_hash`; + * the optional `N_p` is the node's _prefix_ : every key into the subtrie rooted at `N` is prefixed by this bit string; + * `N_v` is the _value_ stored at this node. The value is **only present in leaf nodes**. + +Nodes with `empty_hash` as both children are called _leaf nodes_, and the remaining nodes are known as _internal nodes_. + +#### Accessing account's balance, nonce, code, storage root and storage slots + +Assuming an account `A ≡ (A_b, A_n, A_c, A_s)` at address `A_a`, the following elements can be found at the following addresses: + + * The account balance `A_b` can be found at key `hash(A_a)[0..253] ++ 0b00` and is of type `uint256`; + * The account nonce `A_n` can be found at key `hash(A_a)[0..253] ++ 0b01` and is of type `uint64`; + * The code `A_c` is an arbitrary-length byte sequence that can be found at key `hash(A_a)[0..253] ++ 0b10`; + * The root of the storage trie `A_s` can be found at key `hash(A_a)[0..253] ++ 0b11` + * The storage slot number `k` can be found at key `hash(A_a)[0..253] ++ 0b11 ++ hash(k)`. + +After [EIP-2926](./eip-2926.md) has been rolled out, `A_c` will represent the root of the code merkelization tree. The key accessing code chunk number `c` is `hash(A_a)[0..253] ++ 0b10 ++ u256(c)`. + +In the unlikely future case that extra items are to be added to the trie at account level, a third bit can be reserved for future use. + +### Node merkelization rule + +Leaves and nodes that have no prefix are hashed according to the rule below: + +``` +internal_hash = hash(left_child_hash || right_child_hash) +leaf_hash = hash(hash(key) || hash(leaf_value)) +``` + +If a prefix is present, the length of the path from the root to the prefixed node is further concatenated with the output of the prefix-less rule, and hashed again: + +``` +internal_hash_with_prefix = hash(u256(path_length_u256 - 1) || internal_hash) +leaf_hash_with_prefix = hash(u256(path_length_u256 - 1) || leaf_hash) +``` + +## Rationale + +### blake2b + +BLAKE2 offers better performance, which is key to compensate for the loss of performance associated to a ~4x increase in the number of nodes. + +BLAKE3 offers even better performance. No official golang release exists at the time of the writing of this document. This presents a security risk, and therefore BLAKE2 is considered instead. + +### Merging of the account and storage tries + +The trend in clients is to store the keys and values in a "flat" database. Having the key of any storage slot prefixed with the address key of the account it belongs to helps grouping all of an account's data on disk, as well as simplifying the witness structure. + +### Prefixes and extension nodes + +An alternative proposal has been made, which provides optimal witnesses. The trade-off is that extension nodes must be removed. + +``` +node_hash = hash(left_child_hash || right_child_hash) +leaf_hash = hash(0 || leaf_value) +``` + +The removal of extension nodes induces 40x higher hashing costs (on the order of 25ms for a trie with only 1k leaves) and as a result they have been kept. + +An attempt to keep extension nodes for witness and not the merkelization rule can be found [here](https://notes.ethereum.org/m5VMkX8FRvi0Q_OOR7TF4A). + +Getting rid of complex methods like RLP, the hex prefix and children nesting is already offering great simplification. + +### 2x32-byte inputs + +It has been requested to keep each node hash calculation as a function that takes two 256-bit integer as an input and outputs one 256-bit integer. This property is expected to play nice with circuit constructions and is therefore expected to greatly help with future zero-knowledge applications. + +### Binary tries + +Binary tries have been chosen primarily because they reduce the witness size. In general, in an `N`-element tree with each element having `k` children, the average length of a branch is roughly `32 * (k-1) * log(N) / log(k)` plus a few percent for overhead. 32 is the length of a hash; the `k-1` refers to the fact that a Merkle proof needs to provide all `k-1` sister nodes at each level, and `log(N) / log(k)` is an approximation of the number of levels in the tree (eg. a tree where each node has 5 children, with 625 nodes total, would have depth 4, as `625 = 5**4` and so `log(625) / log(5) = 4`). + +For any `N`, the expression is minimized at `k = 2`. Here's a table of branch lengths for different `k` values assuming `N = 2**24`: + +| `k` (children per node) | Branch length (chunks) | Branch length (bytes) | +| - | - | - | +| 2 | 1 * 24 = 24 | 768 | +| 4 | 3 * 12 = 36 | 1152 | +| 8 | 7 * 8 = 56 | 1792 | +| 16 | 15 * 6 = 90 | 2880 | + +Actual branch lengths will be slightly larger than this due to uneven distribution and overhead, but the pattern of `k=2` being by far the best remains. + +The ethereum tree was originally hexary because this would reduce the number of database reads (eg. 6 instead of 24 in the above example). It is now understood that this reasoning was flawed, because nodes can still "pretend" that a binary tree is a hexary (or even 256-ary) tree at the database layer (eg. see https://ethresear.ch/t/optimizing-sparse-merkle-trees/3751), and thereby get the best-of-both-worlds of having the low proof sizes of the tree being binary from a hash-structure perspective and at the same time a much more efficient representation in the database. + +Additionally, binary trees are expected to be widely used in Eth2, so this path improves forward-compatibility and reduces long-run total complexity for the protocol. + +### Path length instead of bit prefix + +In order to remove the complexity associated with byte manipulation, only the bit-length of the extension is used to merkelize a node with a prefix. + +Storing the length of the path from the root node instead of that from the parent node has the nice property that siblings need not be hashed when deleting a leaf. + +![Sibling deletion diagram](../assets/eip-3102/sibling.svg) + +_On the left, a trie with the prefix length, and on the right, a trie with the full path length. Each both have values `10000100` and `10000000`. After deleting `10000100`,the sibling node has to be updated in the left tree, while it need not be in the case on the right._ + +### Value hashing + +Except for the code, all values in the trie are less than 32 bytes. EIP-2926 introduces code chunks, with `CHUNK_SIZE = 32 bytes`. The hashing of the leaf's value could therefore be saved. The authors of the EIP are however considering a future increase of `CHUNK_SIZE`, making `hash(value)` the future-proof choice. + +## Backwards Compatibility + +A hard fork is required in order for blocks to have a trie root using a different structure. + +## Test Cases + +TBD + +## Implementation + + * As of [commit 0db87e187dc0bfb96046a47e3d6768c93a2e3331](https://github.com/gballet/multiproof-rs/commit/6d22b1aef9548581826b3c04b3e00d6cc709388c), [multiproof-rs](https://github.com/gballet/multiproof-rs) implements this merkelization rule in the `hash_m5()` function, found in file `src/binary_tree.rs`. + * An implementation of this structure for go-ethereum is available [in this branch](https://github.com/gballet/go-ethereum/tree/rebased-binary-trie-m5-full-path). + +## Security Considerations + +Issues could arise when performing the transition. In particular, a heavy conversion process could incentivize clients to wait the transition out. This could lead to a lowered network security at the time of the transition. A transition process has been proposed with [EIP-2584](./eip-2584.md). + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-3135.md b/EIPS/eip-3135.md new file mode 100644 index 00000000000000..5dbe26b3773e45 --- /dev/null +++ b/EIPS/eip-3135.md @@ -0,0 +1,268 @@ +--- +eip: 3135 +title: Exclusive Claimable Token +author: Zhenyu Sun (@Ungigdu) +discussions-to: https://github.com/ethereum/EIPs/issues/3132 +status: Draft +type: Standards Track +category: ERC +created: 2020-08-10 +requires: 20 +--- + +## Simple Summary + +This standard defines a token which can be claimed only by token issuer with payer's signature. + +## Abstract + +This EIP defines a set of additions to the default token standard such as ERC-20, that allows online/offline service providers establish micropayment channels with any number of users by signing and verifying messages about the consumption of token off chain. Using this mechanism will reduce interactions with blockchain to minimal for both participants, thus saving gas and improve performance. + +## Motivation + +There are two main purposes of this EIP, one is to reduce interactions with blockchain, the second is to link Ethereum to real-world payment problems. + +Many small businesses want to build payment system based on blockchain but find it difficult. There are basically two ways: + +1. Directly pay with token. There are many wallet can receive and transfer token but transactions on Ethereum cost gas and take time to confirm. +2. User lock token on payment smart contract and service provider use payment messages signed by user to release token, establishing a micropayment channel. The advantage is interactions with blockchain is reduced and the signing/verifying process is off-chain. But interact with payment contract needs service provider to build a DApp, which require resources many small businesses do not have. Even if they managed to build DApps, they are all different, not standardized. Also, user should have a wallet with DApp browser and has to learn how to use it. + +This EIP helps to standardize the interactions of micropayment system, and make it possible for wallet build a universal UI in the future. + +## Specification + +```solidity + +/// @return Image url of this token or descriptive resources +function iconUrl() external view returns (string memory); + +/// @return Issuer of this token. Only issuer can execute claim function +function issuer() external view returns (address); + +/** + * @notice Remove consumption from payer's deposite + * @dev Check if msg.sender == issuer + * @param from Payer's address + * @param consumption How many token is consumed in this epoch, specified + * @param epoch Epoch increased by 1 after claim or withdraw, at the beginning of each epoch, consumption goes back to 0 + * @param signature Signature of payment message signed by payer +*/ +function claim(address from, uint256 consumption, uint256 epoch, bytes calldata signature) external; + +function transferIssuer(address newIssuer) external; + +/// @notice Move amount from payer's token balance to deposite balance to ensure payment is sufficient +function deposit(uint256 amount) external; + +/** + * @notice Give remaining deposite balance back to "to" account, act as "refund" function + * @dev In prepayment module, withdraw is executed from issuer account + * In lock-release module, withdraw is executed from user account + * @param to the account receiving remaining deposite + * @param amount how many token is returned +*/ +function withdraw(address to, uint256 amount) external; + +function depositBalanceOf(address user) external view returns(uint256 depositBalance, uint256 epoch); + +event Deposit( + address indexed from, + uint256 amount +); + +event Withdraw( + address indexed to, + uint256 amount +); + +event TransferIssuer( + address indexed oldIssuer, + address indexed newIssuer +); + +event Claim( + address indexed from, + address indexed to, + uint256 epoch, + uint256 consumption +); + +``` + +### signature + +the pseudo code generating an ECDSA signature: +``` +sign(keccak256(abi_encode( + "\x19Ethereum Signed Message:\n32", + keccak256(abi_encode( + token_address, + payer_address, + token_issuer, + token_consumption, //calculated by user client + epoch + )) + )) +,private_key) + +``` + +### verification process + +the verification contains check about both signature and token_consumption + +the pseudo code run by verification server is as follows: + +``` + +serving_loop: + + for { + /** + * unpaied_consumption is calculated by provider + * signed_consumption is claimable amount + * tolerance allows payer "owes" provider to a certain degree + */ + //getSignedConsumption returns amount that are already claimable + if(unpaied_consumption < signed_consumption + tolerance){ + informUser("user need charge", unpaied_consumption) + interruptService() + }else{ + isServing() || recoverService() + } + } + +verification_loop: + + for { + message = incomingMessage() + if(recover_signer(message, signature) != payer_address){ + informUser("check signature failed", hash(message)) + continue + } + + /** + * optional: when using echo server to sync messages between verification servers + * more info about this in Security Considerations section + */ + if(query(message) != message){ + informUser("message outdate", hash(message)) + continue + } + + if(epoch != message.epoch || message.consumption > getDepositBalance()){ + informUser("invalid message", epoch, unpaied_consumption) + continue + } + + signed_consumption = message.consumption + save(message) + } + +claim_process: + + if(claim()){ + unpaied_consumption -= signed_consumption + signed_consumption = 0 + epoch+=1 + } + +``` +### About withdraw + +The withdraw function is slightly different based on business models + +1. prepayment model + +In prepayment business model such as using token as recharge card of general store, the user pays (crypto)currency to store in advance for claimable token as recharge card (with bonus or discount). When checking out, the customer signs a message with updated consumption (old consumption + consumption this time) to store and store verifies this message off chain. The shopping process loops without any blockchain involved, until the customer wants to return the card and get money back. Because the store already holds all currency, the withdraw function should be executed by token issuer (store) to return remaining deposit balance after claim. The prepayment model can easily be built into a wallet with QR-code scanning function. + +2. lock-release model + +If we run a paid end-to-end encrypted e-mail service that accepts token as payment, we can use lock-release model. Unlike prepayment, we charge X * N token for an e-mail sent to N recipients. In this "pay for usage" scenario, the counting of services happens on both client and server side. The client should not trust charge amount given by server in case the it's malfunctioning or malicious. When client decide not to trust server, it stops signing messages, but some of token is taken hostage in deposit balance. To fix this problem, the withdraw function should be executed by payer account with limitation such as epoch didn't change in a month. + +## Rationale + +This EIP targets on ERC-20 tokens due to its widespread adoption. However, this extension is designed to be compatible with other token standard. + +The reason we chose to implement those functions in token contract rather than a separate record contract is as follows: +- Token can transfer is more convenient and more general than interact with DApp +- Token is more standardized and has better UI support +- Token is equal to service, make token economy more prosperous +- Remove the approve process + +## Backwards Compatibility + +This EIP is fully backwards compatible as its implementation extends the functionality of [ERC-20](./eip-20.md). + +## Implementation + +```solidity + +mapping (address => StampBalance) private _depositBalance; + +struct StampBalance{ + uint256 balance; + uint256 epoch; +} + +function deposit(uint256 value) override external{ + require(value <= _balances[msg.sender]); + _balances[msg.sender] = _balances[msg.sender].sub(value); + _depositBalance[msg.sender].balance = _depositBalance[msg.sender].balance.add(value); + emit Deposit(msg.sender, value); +} + +function withdraw(address to, uint256 value) override onlyIssuer external{ + require(value <= _depositBalance[to].balance); + _depositBalance[to].balance = _depositBalance[to].balance.sub(value); + _depositBalance[to].epoch += 1; + _balances[to] = _balances[to].add(value); + emit Withdraw(to, value); +} + +function depositBalanceOf(address user) override public view returns(uint256 depositBalance, uint256 epoch){ + return (_depositBalance[user].balance, _depositBalance[user].epoch); +} + +// prepayment model +function claim(address from, uint credit, uint epoch, bytes memory signature) override onlyIssuer external{ + require(credit > 0); + require(_depositBalance[from].epoch + 1 == epoch); + require(_depositBalance[from].balance >= credit); + bytes32 message = keccak256(abi.encode(this, from, _issuer, credit, epoch)); + bytes32 msgHash = prefixed(message); + require(recoverSigner(msgHash, signature) == from); + _depositBalance[from].balance = _depositBalance[from].balance.sub(credit); + _balances[_issuer] = _balances[_issuer].add(credit); + _depositBalance[from].epoch += 1; + emit Claim(from, msg.sender, credit, epoch); +} + +function prefixed(bytes32 hash) internal pure returns (bytes32) { + return keccak256(abi.encode("\x19Ethereum Signed Message:\n32", hash)); +} + +function recoverSigner(bytes32 message, bytes memory sig) internal pure returns (address) { + (uint8 v, bytes32 r, bytes32 s) = splitSignature(sig); + return ecrecover(message, v, r, s); +} + +function splitSignature(bytes memory sig) internal pure returns (uint8 v, bytes32 r, bytes32 s) { + require(sig.length == 65); + assembly { + r := mload(add(sig, 32)) + s := mload(add(sig, 64)) + v := byte(0, mload(add(sig, 96))) + } + return (v, r, s); +} + +``` + +## Security Considerations + +By restricting claim function to issuer, there is no race condition on chain layer. However double spending problem may occur when the issuer use multiple verifiers and payer signs many payment messages simultaneously. Some of those messages may get chance to be checked valid though only the message with the largest consumption can be claimed. This problem can be fixed by introducing an echo server which accepts messages from verifiers, returns the message sequentially with largest consumption and biggest epoch number. If a verifier gets an answer different from the message he send, it updates the message from echo server as the last message it receives along with local storage of the status about this payer. Then the verifier asks the payer again for a new message. + +## 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-3143.md b/EIPS/eip-3143.md new file mode 100644 index 00000000000000..af60a8a77d5b79 --- /dev/null +++ b/EIPS/eip-3143.md @@ -0,0 +1,53 @@ +--- +eip: 3143 +title: Increase block rewards to 5 ETH +author: Ben Tinner (@Terra854) +discussions-to: https://ethereum-magicians.org/t/eip-3143-increase-block-rewards-to-5-eth/5061 +status: Draft +type: Standards Track +category: Core +created: 2020-12-01 +--- + +## Simple Summary +Changes the block reward paid to proof-of-work (POW) miners to 5 ETH. + +## Abstract +Starting with `FORK_BLKNUM` block rewards will be increased to a base of 5 ETH, uncle and nephew rewards will be adjusted accordingly. + +## Motivation +Currently, the transaction fees (tx fees) portion of the mining rewards makes up a significant portion of the total rewards per block, at times almost exceeded the block reward of 2 ETH. This have resulted in situations where at times of low tx fees, POW miners decide to point their rigs away from ETH as they will always prefer to mine coins that are the most profitable at any point in time, reducing the security of the ETH network till transaction activity picks up again. By increasing the block rewards back to the original 5 ETH when the network first started, the voliatility will be reduced in terms of the percentage of tx fees that make up the mining rewards per block while increasing the total rewards per block, making it more financially attractive to POW miners to mine ETH barring any gigantic ETH price drops. The increase in block rewards will also allow smaller POW miners ample opporturnity to build up their stores of ETH so that when the time comes to fully transition to ETH 2.0, they may be more willing to become validators as they already have earned the requite amount of ETH needed to do so as opposed to having to spend tens of thousands of dollars to purchase the required ETH directly, increasing the number of validators in the network and therefore strengthening network security. + +Therefore, the ultimate end goal for this EIP is to give POW miners more incentive to switch to POS once ETH 2.0 is fully implemented since the transition will take a few years to complete and during that time, they will be incentivised to hold on to the tokens instead of selling it straight away in order to prepare to be a validator for ETH 2.0, reducing the selling pressure on ETH and increasing it's value in the long run. A side effect of miners staying on Ethereum is that network security will be assured during the transition period. + +## Specification +#### Adjust Block, Uncle, and Nephew rewards +Adjust the block reward to `new_block_reward`, where + + new_block_reward = 5_000_000_000_000_000_000 if block.number >= FORK_BLKNUM else block.reward + +(5E18 wei, or 5,000,000,000,000,000,000 wei, or 5 ETH). + +Analogue, if an uncle is included in a block for `block.number >= FORK_BLKNUM` such that `block.number - uncle.number = k`, the uncle reward is + + new_uncle_reward = (8 - k) * new_block_reward / 8 + +This is the existing formula for uncle rewards, simply adjusted with `new_block_reward`. + +The nephew reward for `block.number >= FORK_BLKNUM` is + + new_nephew_reward = new_block_reward / 32 + +This is the existing formula for nephew rewards, simply adjusted with `new_block_reward`. + +## Rationale +A 5 ETH base reward was chosen as a middle ground between wanting to prevent too high of an inflation rate (10.4% per annum for the first year at 5 ETH per block) and converting as many POW miners as possible into POS validators by making it easier to amass the required ETH needed through POW mining. + +## Backwards Compatibility +There are no known backward compatibility issues with the introduction of this EIP. + +## Security Considerations +There are no known security issues presented by this change. + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-3155.md b/EIPS/eip-3155.md new file mode 100644 index 00000000000000..5bf68b5d03a140 --- /dev/null +++ b/EIPS/eip-3155.md @@ -0,0 +1,167 @@ +--- +eip: 3155 +title: EVM trace specification +author: Martin Holst Swende (@holiman), Marius van der Wijden (@MariusVanDerWijden) +discussions-to: https://ethereum-magicians.org/t/eip-3155-create-evm-trace-specification/5007 +status: Draft +type: Standards Track +category: Interface +created: 2020-12-07 +--- + + +## Simple Summary +Introduce a new JSON standard for EVM traces during execution of state tests. + +## Motivation +The Ethereum Virtual Machine executes all smart contract code on ethereum. +In order to debug smart contracts and state tests better, a common format was introduced to log every execution step of the EVM. +This format was implemented by go-ethereum, parity, nethermind and Besu. +Since the common format was not well defined, the implementations differed slightly making it hard to develop adequate tooling which reduces the usefulness of tracing significantly. + +This EIP has multiple objectives: +- Move the specification to a more visible place to encourage new clients to implement it +- Strictly define corner cases that were not addressed in the previous version +- Allow for updates to the specification in case new fields are introduced during execution +- Provide sample output + +Implementing this EIP in all major clients allows us to create meaningful differential fuzzers that fuzz EVM implementations for the mainnet and all upcoming hardforks. +It also helps finding differences in execution quickly in the case of a chain split. + +This EIP will enable users to create better differential fuzzing infrastructure to compare the EVM implementations of all major Ethereum clients against each other. +This could help to find bugs that are currently present in the client implementations. + +## Specification +Clients should be able to execute simple transactions as well as code and return traces. In the following, we will call this client CUT (client under test) and use go-ethereums `evm` binary for code examples. + +### Datatypes + +| Type | Explanation | Example | +|---|---|---| +| Number | Plain json number | "pc":0 | +| Hex-Number | Hex-encoded number | "gas":"0x2540be400" | +| String | Plain string | "opName":"PUSH1" | +| Hex-String | Hex-encoded string | | +| Array of x | Array of x encoded values | | +| Key-Value | Key-Value structure with key and values encoded as hex strings | | +| Boolean | Json bool can either be true or false | "pass": true | + +### Output + +The CUT MUST output a `json` object for EACH operation. + +Required Fields: + +| Name | Type | Explanation | +|---|---|---| +| `pc` | Number | Program Counter | +| `op` | Number | OpCode | +| `gas` | Hex-Number | Gas left before executing this operation | +| `gasCost` | Hex-Number | Gas cost of this operation | +| `stack` | Array of Hex-Numbers | Array of all values on the stack | +| `depth` | Number | Depth of the call stack | +| `returnData` | Hex-String | Data returned by function call | +| `refund` | Hex-Number | Amount of **global** gas refunded | +| `memSize` | Number | Size of memory array | + +Optional Fields: + +| Name | Type | Explanation | +|---|---|---| +| `opName` | String | Name of the operation | +| `error` | Hex-String | Description of an error (should contain revert reason if supported) | +| `memory` | Array of Hex-Strings | Array of all allocated values | +| `storage` | Key-Value | Array of all stored values | +| `returnStack` | Array of Hex-Numbers | Array of values, Stack of the called function | + +*Example:* +``` +{"pc":0,"op":96,"gas":"0x2540be400","gasCost":"0x3","memory":"0x","memSize":0,"stack":[],"depth":1,"error":null,"opName":"PUSH1"} +``` + +The `stack`, `memory` and `memSize` are the values _before_ execution of the op. +All array attributes (`stack`, `returnStack`, `memory`) MUST be initialized to empty arrays ("stack":[],) NOT to null. +If the CUT will not output values for `memory` or `storage` then the `memory` and `storage` fields are omitted. +This can happen either because the CUT does not support tracing these fields or it has been configured not to trace it. +The `memSize` field MUST be present regardless of `memory` support. +Clients SHOULD implement a way to disable recording the storage as the stateroot includes all storage updates. +Clients SHOULD output the fields in the same order as listed in this EIP. + +The CUT MUST NOT output a line for the `STOP` operation if an error occurred: +*Example:* +``` +{"pc":2,"op":0,"gas":"0x2540be3fd","gasCost":"0x0","memory":"0x","memSize":0,"stack":["0x40"],"depth":1,"error":null,"opName":"STOP"} +``` + +### Summary and error handling + +At the end of execution, the CUT MUST print some summerical info, this info SHOULD have the following fields. +The summary should be a single `jsonl` object. + +Required Fields: + +| Name | Type | Explanation | +|---|---|---| +| `stateRoot` | Hex-String | Root of the state trie after executing the transaction | +| `output` | | Return values of the function | +| `gasUsed` | Hex-Number | All gas used by the transaction | +| `pass` | Boolean | Bool whether transaction was executed successfully | + +OptionalFields: + +| Name | Type | Explanation | +|---|---|---| +| `time` | Number | Time in nanoseconds needed to execute the transaction | +| `fork` | String | Name of the fork rules used for execution | +``` +{"stateRoot":"0xd4c577737f5d20207d338c360c42d3af78de54812720e3339f7b27293ef195b7","output":"","gasUsed":"0x3","successful":"true","time":141485} +``` + +## Rationale +This EIP is largely based on the previous non-official documentation for EVM tracing. +It tries to cover as many corner cases as possible to enable true client compatibility. +The datatypes and if a field is optional is chosen to be as compatible with current implementations as possible. + +## Backwards Compatibility +This EIP is fully backward compatible with ethereum as it only introduces a better tracing infrastructure that is optional for clients to implement. + +### Clients +This EIP is fully backward compatible with go-ethereum. OpenEthereum, Besu and Nethermind clients would have to change their JSON output of `openethereum-evm` `evmtool` and `nethtest` slightly do adhere to the new and stricter specs. New clients would need to implement this change if they want to be part of the differential fuzzing group. + +## Test Cases + +```bash + ~/go/src/github.com/ethereum/go-ethereum/build/bin/evm --code 604080536040604055604060006040600060025afa6040f3 --json run +{"pc":0,"op":96,"gas":"0x2540be400","gasCost":"0x3","memory":"0x","memSize":0,"stack":[],"returnStack":[],"returnData":"0x","depth":1,"refund":0,"opName":"PUSH1","error":""} +{"pc":2,"op":128,"gas":"0x2540be3fd","gasCost":"0x3","memory":"0x","memSize":0,"stack":["0x40"],"returnStack":[],"returnData":"0x","depth":1,"refund":0,"opName":"DUP1","error":""} +{"pc":3,"op":83,"gas":"0x2540be3fa","gasCost":"0xc","memory":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","memSize":96,"stack":["0x40","0x40"],"returnStack":[],"returnData":"0x","depth":1,"refund":0,"opName":"MSTORE8","error":""} +{"pc":4,"op":96,"gas":"0x2540be3ee","gasCost":"0x3","memory":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000","memSize":96,"stack":[],"returnStack":[],"returnData":"0x","depth":1,"refund":0,"opName":"PUSH1","error":""} +{"pc":6,"op":96,"gas":"0x2540be3eb","gasCost":"0x3","memory":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000","memSize":96,"stack":["0x40"],"returnStack":[],"returnData":"0x","depth":1,"refund":0,"opName":"PUSH1","error":""} +{"pc":8,"op":85,"gas":"0x2540be3e8","gasCost":"0x4e20","memory":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000","memSize":96,"stack":["0x40","0x40"],"returnStack":[],"returnData":"0x","depth":1,"refund":0,"opName":"SSTORE","error":""} +{"pc":9,"op":96,"gas":"0x2540b95c8","gasCost":"0x3","memory":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000","memSize":96,"stack":[],"returnStack":[],"returnData":"0x","depth":1,"refund":0,"opName":"PUSH1","error":""} +{"pc":11,"op":96,"gas":"0x2540b95c5","gasCost":"0x3","memory":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000","memSize":96,"stack":["0x40"],"returnStack":[],"returnData":"0x","depth":1,"refund":0,"opName":"PUSH1","error":""} +{"pc":13,"op":96,"gas":"0x2540b95c2","gasCost":"0x3","memory":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000","memSize":96,"stack":["0x40","0x0"],"returnStack":[],"returnData":"0x","depth":1,"refund":0,"opName":"PUSH1","error":""} +{"pc":15,"op":96,"gas":"0x2540b95bf","gasCost":"0x3","memory":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000","memSize":96,"stack":["0x40","0x0","0x40"],"returnStack":[],"returnData":"0x","depth":1,"refund":0,"opName":"PUSH1","error":""} +{"pc":17,"op":96,"gas":"0x2540b95bc","gasCost":"0x3","memory":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000","memSize":96,"stack":["0x40","0x0","0x40","0x0"],"returnStack":[],"returnData":"0x","depth":1,"refund":0,"opName":"PUSH1","error":""} +{"pc":19,"op":90,"gas":"0x2540b95b9","gasCost":"0x2","memory":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000","memSize":96,"stack":["0x40","0x0","0x40","0x0","0x2"],"returnStack":[],"returnData":"0x","depth":1,"refund":0,"opName":"GAS","error":""} +{"pc":20,"op":250,"gas":"0x2540b95b7","gasCost":"0x24abb676c","memory":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000","memSize":96,"stack":["0x40","0x0","0x40","0x0","0x2","0x2540b95b7"],"returnStack":[],"returnData":"0x","depth":1,"refund":0,"opName":"STATICCALL","error":""} +{"pc":21,"op":96,"gas":"0x2540b92a7","gasCost":"0x3","memory":"0xf5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b00000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000","memSize":96,"stack":["0x1"],"returnStack":[],"returnData":"0xf5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b","depth":1,"refund":0,"opName":"PUSH1","error":""} +{"pc":23,"op":243,"gas":"0x2540b92a4","gasCost":"0x0","memory":"0xf5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b00000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000","memSize":96,"stack":["0x1","0x40"],"returnStack":[],"returnData":"0xf5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b","depth":1,"refund":0,"opName":"RETURN","error":""} +{"stateRoot":"2eef130ec61805516c1f050720b520619787704a5dd826a39aeefb850f83acfd", "output":"40","gasUsed":"0x515c","time":350855} +``` + + +## Implementation +Implementation in [go-ethereum](https://github.com/ethereum/go-ethereum/tree/master/cmd/evm) +Implementation in [OpenEthereum](https://github.com/openethereum/openethereum/tree/master/evmbin) +Implementation in [Besu](https://github.com/hyperledger/besu/tree/master/ethereum/evmtool) +Implementation in [Nethermind](https://github.com/NethermindEth/nethermind/tree/master/src/Nethermind/Nethermind.State.Test.Runner) + + +## Security Considerations +Tracing is expensive. +Exposing an endpoint for creating traces publicly could open up a denial of service vector. +Clients should consider putting trace endpoints behind a separate flag from other endpoints. + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-3156.md b/EIPS/eip-3156.md new file mode 100644 index 00000000000000..1da3825ad8efe8 --- /dev/null +++ b/EIPS/eip-3156.md @@ -0,0 +1,515 @@ +--- +eip: 3156 +title: Flash Loans +author: Alberto Cuesta Cañada (@albertocuestacanada), Fiona Kobayashi (@fifikobayashi), fubuloubu (@fubuloubu), Austin Williams (@onewayfunction) +discussions-to: https://ethereum-magicians.org/t/erc-3156-flash-loans-review-discussion/5077 +status: Final +type: Standards Track +category: ERC +created: 2020-11-15 +--- + +## Simple Summary + +This ERC provides standard interfaces and processes for single-asset flash loans. + +## Abstract + +A flash loan is a smart contract transaction in which a lender smart contract lends assets to a borrower smart contract with the condition that the assets are returned, plus an optional fee, before the end of the transaction. This ERC specifies interfaces for lenders to accept flash loan requests, and for borrowers to take temporary control of the transaction within the lender execution. The process for the safe execution of flash loans is also specified. + +## Motivation + +Flash loans allow smart contracts to lend an amount of tokens without a requirement for collateral, with the condition that they must be returned within the same transaction. + +Early adopters of the flash loan pattern have produced different interfaces and different use patterns. The diversification is expected to intensify, and with it the technical debt required to integrate with diverse flash lending patterns. + +Some of the high level diferences in the approaches across the protocols include: +- Repayment approaches at the end of the transaction, where some pull the principal plus the fee from the loan receiver, and others where the loan receiver needs to manually return the principal and the fee to the lender. +- Some lenders offer the ability to repay the loan using a token that is different to what was originally borrowed, which can reduce the overall complexity of the flash transaction and gas fees. +- Some lenders offer a single entry point into the protocol regardless of whether you're buying, selling, depositing or chaining them together as a flash loan, whereas other protocols offer discrete entry points. +- Some lenders allow to flash mint any amount of their native token without charging a fee, effectively allowing flash loans bounded by computational constraints instead of asset ownership constraints. + +## Specification + +A flash lending feature integrates two smart contracts using a callback pattern. These are called the LENDER and the RECEIVER in this EIP. + +### Lender Specification + +A `lender` MUST implement the IERC3156FlashLender interface. +``` +pragma solidity ^0.7.0 || ^0.8.0; +import "./IERC3156FlashBorrower.sol"; + + +interface IERC3156FlashLender { + + /** + * @dev The amount of currency available to be lent. + * @param token The loan currency. + * @return The amount of `token` that can be borrowed. + */ + function maxFlashLoan( + address token + ) external view returns (uint256); + + /** + * @dev The fee to be charged for a given loan. + * @param token The loan currency. + * @param amount The amount of tokens lent. + * @return The amount of `token` to be charged for the loan, on top of the returned principal. + */ + function flashFee( + address token, + uint256 amount + ) external view returns (uint256); + + /** + * @dev Initiate a flash loan. + * @param receiver The receiver of the tokens in the loan, and the receiver of the callback. + * @param token The loan currency. + * @param amount The amount of tokens lent. + * @param data Arbitrary data structure, intended to contain user-defined parameters. + */ + function flashLoan( + IERC3156FlashBorrower receiver, + address token, + uint256 amount, + bytes calldata data + ) external returns (bool); +} +``` + +The `maxFlashLoan` function MUST return the maximum loan possible for `token`. If a `token` is not currently supported `maxFlashLoan` MUST return 0, instead of reverting. + +The `flashFee` function MUST return the fee charged for a loan of `amount` `token`. If the token is not supported `flashFee` MUST revert. + +The `flashLoan` function MUST include a callback to the `onFlashLoan` function in a `IERC3156FlashBorrower` contract. + +``` +function flashLoan( + IERC3156FlashBorrower receiver, + address token, + uint256 amount, + bytes calldata data +) external returns (bool) { + ... + require( + receiver.onFlashLoan(msg.sender, token, amount, fee, data) == keccak256("ERC3156FlashBorrower.onFlashLoan"), + "IERC3156: Callback failed" + ); + ... +} +``` + +The `flashLoan` function MUST transfer `amount` of `token` to `receiver` before the callback to the borrower. + +The `flashLoan` function MUST include `msg.sender` as the `initiator` to `onFlashLoan`. + +The `flashLoan` function MUST NOT modify the `token`, `amount` and `data` parameter received, and MUST pass them on to `onFlashLoan`. + +The `flashLoan` function MUST include a `fee` argument to `onFlashLoan` with the fee to pay for the loan on top of the principal, ensuring that `fee == flashFee(token, amount)`. + +The `lender` MUST verify that the `onFlashLoan` callback returns the keccak256 hash of "ERC3156FlashBorrower.onFlashLoan". + +After the callback, the `flashLoan` function MUST take the `amount + fee` `token` from the `receiver`, or revert if this is not successful. + +If successful, `flashLoan` MUST return `true`. + +### Receiver Specification + +A `receiver` of flash loans MUST implement the IERC3156FlashBorrower interface: + +``` +pragma solidity ^0.7.0 || ^0.8.0; + + +interface IERC3156FlashBorrower { + + /** + * @dev Receive a flash loan. + * @param initiator The initiator of the loan. + * @param token The loan currency. + * @param amount The amount of tokens lent. + * @param fee The additional amount of tokens to repay. + * @param data Arbitrary data structure, intended to contain user-defined parameters. + * @return The keccak256 hash of "ERC3156FlashBorrower.onFlashLoan" + */ + function onFlashLoan( + address initiator, + address token, + uint256 amount, + uint256 fee, + bytes calldata data + ) external returns (bytes32); +} +``` + +For the transaction to not revert, `receiver` MUST approve `amount + fee` of `token` to be taken by `msg.sender` before the end of `onFlashLoan`. + +If successful, `onFlashLoan` MUST return the keccak256 hash of "ERC3156FlashBorrower.onFlashLoan". + +## Rationale + +The interfaces described in this ERC have been chosen as to cover the known flash lending use cases, while allowing for safe and gas efficient implementations. + +`flashFee` reverts on unsupported tokens, because returning a numerical value would be incorrect. + +`flashLoan` has been chosen as a function name as descriptive enough, unlikely to clash with other functions in the lender, and including both the use cases in which the tokens lent are held or minted by the lender. + +`receiver` is taken as a parameter to allow flexibility on the implementation of separate loan initiators and receivers. + +Existing flash lenders all provide flash loans of several token types from the same contract. Providing a `token` parameter in both the `flashLoan` and `onFlashLoan` functions matches closely the observed functionality. + +A `bytes calldata data` parameter is included for the caller to pass arbitrary information to the `receiver`, without impacting the utility of the `flashLoan` standard. + +`onFlashLoan` has been chosen as a function name as descriptive enough, unlikely to clash with other functions in the `receiver`, and following the `onAction` naming pattern used as well in EIP-667. + +A `initiator` will often be required in the `onFlashLoan` function, which the lender knows as `msg.sender`. An alternative implementation which would embed the `initiator` in the `data` parameter by the caller would require an additional mechanism for the receiver to verify its accuracy, and is not advisable. + +The `amount` will be required in the `onFlashLoan` function, which the lender took as a parameter. An alternative implementation which would embed the `amount` in the `data` parameter by the caller would require an additional mechanism for the receiver to verify its accuracy, and is not advisable. + +A `fee` will often be calculated in the `flashLoan` function, which the `receiver` must be aware of for repayment. Passing the `fee` as a parameter instead of appended to `data` is simple and effective. + +The `amount + fee` are pulled from the `receiver` to allow the `lender` to implement other features that depend on using `transferFrom`, without having to lock them for the duration of a flash loan. An alternative implementation where the repayment is transferred to the `lender` is also possible, but would need all other features in the lender to be also based in using `transfer` instead of `transferFrom`. Given the lower complexity and prevalence of a "pull" architecture over a "push" architecture, "pull" was chosen. + +## Backwards Compatibility + +No backwards compatibility issues identified. + +## Implementation + +### Flash Borrower Reference Implementation + +``` +pragma solidity ^0.8.0; + +import "./interfaces/IERC20.sol"; +import "./interfaces/IERC3156FlashBorrower.sol"; +import "./interfaces/IERC3156FlashLender.sol"; + + +contract FlashBorrower is IERC3156FlashBorrower { + enum Action {NORMAL, OTHER} + + IERC3156FlashLender lender; + + constructor ( + IERC3156FlashLender lender_ + ) { + lender = lender_; + } + + /// @dev ERC-3156 Flash loan callback + function onFlashLoan( + address initiator, + address token, + uint256 amount, + uint256 fee, + bytes calldata data + ) external override returns(bool) { + require( + msg.sender == address(lender), + "FlashBorrower: Untrusted lender" + ); + require( + initiator == address(this), + "FlashBorrower: Untrusted loan initiator" + ); + (Action action) = abi.decode(data, (Action)); + if (action == Action.NORMAL) { + // do one thing + } else if (action == Action.OTHER) { + // do another + } + return keccak256("ERC3156FlashBorrower.onFlashLoan"); + } + + /// @dev Initiate a flash loan + function flashBorrow( + address token, + uint256 amount + ) public { + bytes memory data = abi.encode(Action.NORMAL); + uint256 _allowance = IERC20(token).allowance(address(this), address(lender)); + uint256 _fee = lender.flashFee(token, amount); + uint256 _repayment = amount + _fee; + IERC20(token).approve(address(lender), _allowance + _repayment); + lender.flashLoan(this, token, amount, data); + } +} +``` + +### Flash Mint Reference Implementation + +``` +pragma solidity ^0.8.0; + +import "../ERC20.sol"; +import "../interfaces/IERC20.sol"; +import "../interfaces/IERC3156FlashBorrower.sol"; +import "../interfaces/IERC3156FlashLender.sol"; + + +/** + * @author Alberto Cuesta Cañada + * @dev Extension of {ERC20} that allows flash minting. + */ +contract FlashMinter is ERC20, IERC3156FlashLender { + + bytes32 public constant CALLBACK_SUCCESS = keccak256("ERC3156FlashBorrower.onFlashLoan"); + uint256 public fee; // 1 == 0.0001 %. + + /** + * @param fee_ The percentage of the loan `amount` that needs to be repaid, in addition to `amount`. + */ + constructor ( + string memory name, + string memory symbol, + uint256 fee_ + ) ERC20(name, symbol) { + fee = fee_; + } + + /** + * @dev The amount of currency available to be lent. + * @param token The loan currency. + * @return The amount of `token` that can be borrowed. + */ + function maxFlashLoan( + address token + ) external view override returns (uint256) { + return type(uint256).max - totalSupply(); + } + + /** + * @dev The fee to be charged for a given loan. + * @param token The loan currency. Must match the address of this contract. + * @param amount The amount of tokens lent. + * @return The amount of `token` to be charged for the loan, on top of the returned principal. + */ + function flashFee( + address token, + uint256 amount + ) external view override returns (uint256) { + require( + token == address(this), + "FlashMinter: Unsupported currency" + ); + return _flashFee(token, amount); + } + + /** + * @dev Loan `amount` tokens to `receiver`, and takes it back plus a `flashFee` after the ERC3156 callback. + * @param receiver The contract receiving the tokens, needs to implement the `onFlashLoan(address user, uint256 amount, uint256 fee, bytes calldata)` interface. + * @param token The loan currency. Must match the address of this contract. + * @param amount The amount of tokens lent. + * @param data A data parameter to be passed on to the `receiver` for any custom use. + */ + function flashLoan( + IERC3156FlashBorrower receiver, + address token, + uint256 amount, + bytes calldata data + ) external override returns (bool){ + require( + token == address(this), + "FlashMinter: Unsupported currency" + ); + uint256 fee = _flashFee(token, amount); + _mint(address(receiver), amount); + require( + receiver.onFlashLoan(msg.sender, token, amount, fee, data) == CALLBACK_SUCCESS, + "FlashMinter: Callback failed" + ); + uint256 _allowance = allowance(address(receiver), address(this)); + require( + _allowance >= (amount + fee), + "FlashMinter: Repay not approved" + ); + _approve(address(receiver), address(this), _allowance - (amount + fee)); + _burn(address(receiver), amount + fee); + return true; + } + + /** + * @dev The fee to be charged for a given loan. Internal function with no checks. + * @param token The loan currency. + * @param amount The amount of tokens lent. + * @return The amount of `token` to be charged for the loan, on top of the returned principal. + */ + function _flashFee( + address token, + uint256 amount + ) internal view returns (uint256) { + return amount * fee / 10000; + } +} +``` + +### Flash Loan Reference Implementation + +``` +pragma solidity ^0.8.0; + +import "../interfaces/IERC20.sol"; +import "../interfaces/IERC3156FlashBorrower.sol"; +import "../interfaces/IERC3156FlashLender.sol"; + + +/** + * @author Alberto Cuesta Cañada + * @dev Extension of {ERC20} that allows flash lending. + */ +contract FlashLender is IERC3156FlashLender { + + bytes32 public constant CALLBACK_SUCCESS = keccak256("ERC3156FlashBorrower.onFlashLoan"); + mapping(address => bool) public supportedTokens; + uint256 public fee; // 1 == 0.0001 %. + + + /** + * @param supportedTokens_ Token contracts supported for flash lending. + * @param fee_ The percentage of the loan `amount` that needs to be repaid, in addition to `amount`. + */ + constructor( + address[] memory supportedTokens_, + uint256 fee_ + ) { + for (uint256 i = 0; i < supportedTokens_.length; i++) { + supportedTokens[supportedTokens_[i]] = true; + } + fee = fee_; + } + + /** + * @dev Loan `amount` tokens to `receiver`, and takes it back plus a `flashFee` after the callback. + * @param receiver The contract receiving the tokens, needs to implement the `onFlashLoan(address user, uint256 amount, uint256 fee, bytes calldata)` interface. + * @param token The loan currency. + * @param amount The amount of tokens lent. + * @param data A data parameter to be passed on to the `receiver` for any custom use. + */ + function flashLoan( + IERC3156FlashBorrower receiver, + address token, + uint256 amount, + bytes calldata data + ) external override returns(bool) { + require( + supportedTokens[token], + "FlashLender: Unsupported currency" + ); + uint256 fee = _flashFee(token, amount); + require( + IERC20(token).transfer(address(receiver), amount), + "FlashLender: Transfer failed" + ); + require( + receiver.onFlashLoan(msg.sender, token, amount, fee, data) == CALLBACK_SUCCESS, + "FlashLender: Callback failed" + ); + require( + IERC20(token).transferFrom(address(receiver), address(this), amount + fee), + "FlashLender: Repay failed" + ); + return true; + } + + /** + * @dev The fee to be charged for a given loan. + * @param token The loan currency. + * @param amount The amount of tokens lent. + * @return The amount of `token` to be charged for the loan, on top of the returned principal. + */ + function flashFee( + address token, + uint256 amount + ) external view override returns (uint256) { + require( + supportedTokens[token], + "FlashLender: Unsupported currency" + ); + return _flashFee(token, amount); + } + + /** + * @dev The fee to be charged for a given loan. Internal function with no checks. + * @param token The loan currency. + * @param amount The amount of tokens lent. + * @return The amount of `token` to be charged for the loan, on top of the returned principal. + */ + function _flashFee( + address token, + uint256 amount + ) internal view returns (uint256) { + return amount * fee / 10000; + } + + /** + * @dev The amount of currency available to be lent. + * @param token The loan currency. + * @return The amount of `token` that can be borrowed. + */ + function maxFlashLoan( + address token + ) external view override returns (uint256) { + return supportedTokens[token] ? IERC20(token).balanceOf(address(this)) : 0; + } +} + +``` + +## Security Considerations + + +### Verification of callback arguments + +The arguments of `onFlashLoan` are expected to reflect the conditions of the flash loan, but cannot be trusted unconditionally. They can be divided in two groups, that require different checks before they can be trusted to be genuine. + +0. No arguments can be assumed to be genuine without some kind of verification. `initiator`, `token` and `amount` refer to a past transaction that might not have happened if the caller of `onFlashLoan` decides to lie. `fee` might be false or calculated incorrectly. `data` might have been manipulated by the caller. +1. To trust that the value of `initiator`, `token`, `amount` and `fee` are genuine a reasonable pattern is to verify that the `onFlashLoan` caller is in a whitelist of verified flash lenders. Since often the caller of `flashLoan` will also be receiving the `onFlashLoan` callback this will be trivial. In all other cases flash lenders will need to be approved if the arguments in `onFlashLoan` are to be trusted. +2. To trust that the value of `data` is genuine, in addition to the check in point 1, it is recommended to verify that the `initiator` belongs to a group of trusted addresses. Trusting the `lender` and the `initiator` is enough to trust that the contents of `data` are genuine. + +### Flash lending security considerations + +#### Automatic approvals for untrusted borrowers +The safest approach is to implement an approval for `amount+fee` before the `flashLoan` is executed. + +Including in `onFlashLoan` the approval for the `lender` to take the `amount + fee` needs to be combined with a mechanism to verify that the borrower is trusted, such as those described above. + +If an unsuspecting contract with a non-reverting fallback function, or an EOA, would approve a `lender` implementing ERC3156, and not immediately use the approval, and if the `lender` would not verify the return value of `onFlashLoan`, then the unsuspecting contract or EOA could be drained of funds up to their allowance or balance limit. This would be executed by a `borrower` calling `flashLoan` on the victim. The flash loan would be executed and repaid, plus any fees, which would be accumulated by the `lender`. For this reason, it is important that the `lender` implements the specification in full and reverts if `onFlashLoan` doesn't return the keccak256 hash for "ERC3156FlashBorrower.onFlashLoan". + +### Flash minting external security considerations + +The typical quantum of tokens involved in flash mint transactions will give rise to new innovative attack vectors. + +#### Example 1 - interest rate attack +If there exists a lending protocol that offers stable interests rates, but it does not have floor/ceiling rate limits and it does not rebalance the fixed rate based on flash-induced liquidity changes, then it could be susceptible to the following scenario: + +FreeLoanAttack.sol +1. Flash mint 1 quintillion STAB +2. Deposit the 1 quintillion STAB + $1.5 million worth of ETH collateral +3. The quantum of your total deposit now pushes the stable interest rate down to 0.00001% stable interest rate +4. Borrow 1 million STAB on 0.00001% stable interest rate based on the 1.5M ETH collateral +5. Withdraw and burn the 1 quint STAB to close the original flash mint +6. You now have a 1 million STAB loan that is practically interest free for perpetuity ($0.10 / year in interest) + +The key takeaway being the obvious need to implement a flat floor/ceiling rate limit and to rebalance the rate based on short term liquidity changes. + +#### Example 2 - arithmetic overflow and underflow +If the flash mint provider does not place any limits on the amount of flash mintable tokens in a transaction, then anyone can flash mint 2^256-1 amount of tokens. + +The protocols on the receiving end of the flash mints will need to ensure their contracts can handle this, either by using a compiler that embeds overflow protection in the smart contract bytecode, or by setting explicit checks. + +### Flash minting internal security considerations + +The coupling of flash minting with business specific features in the same platform can easily lead to unintended consequences. + +#### Example - Treasury draining +Assume a smart contract that flash lends its native token. The same smart contract borrows from a third party when users burn the native token. This pattern would be used to aggregate in the smart contract the collateralized debt of several users into a single account in the third party. The flash mint could be used to cause the lender to borrow to its limit, and then pushing interest rates in the underlying lender, liquidate the flash lender: +1. Flash mint from `lender` a very large amount of FOO. +2. Redeem FOO for BAR, causing `lender` to borrow from `underwriter` all the way to its borrowing limit. +3. Trigger a debt rate increase in `underwriter`, making `lender` undercollateralized. +4. Liquidate the `lender` for profit. + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-3198.md b/EIPS/eip-3198.md new file mode 100644 index 00000000000000..80640184d1b8e0 --- /dev/null +++ b/EIPS/eip-3198.md @@ -0,0 +1,56 @@ +--- +eip: 3198 +title: BASEFEE opcode +author: Abdelhamid Bakhta (@abdelhamidbakhta), Vitalik Buterin (@vbuterin) +discussions-to: https://ethereum-magicians.org/t/eip-3198-basefeeopcode/5162 +status: Draft +type: Standards Track +category: Core +created: 2021-01-13 +requires: 1559 +--- + +## Simple Summary +Add a `BASEFEE (0x48)` that returns the value of the base fee of the current block it is executing in. + +## Abstract + + +## Motivation +The intended use case would be for contracts to get the value of the base fee. This feature would enable or improve existing use cases, such as: +- Contracts that need to set bounties for anyone to "poke" them with a transaction could set the bounty to be `BASEFEE + x`, or `BASEFEE * (1 + x)`. This makes the mechanism more reliable, because they will always pay "enough" regardless of market conditions. +- Gas futures can be implemented based on it. This would be more precise than gastokens. +- Improve the security for state channels, plasma, optirolls and other fraud proof driven solutions. Having the `BASEFEE` as an input allows you to lengthen the challenge period automatically if you see that the `BASEFEE` is high. + +## Specification +Add a `BASEFEE` opcode at `(0x48)`, with gas cost `G_base`. + +| Op | Input | Output | Cost | +|:----: |:-----: |:------: |:----: | +| 0x48 | 0 | 1 | 2 | + +## Rationale + +## Backwards Compatibility +This EIP is backwards-compatible. + +## Test Cases + +### Nominal case +Assuming current block base fee is `7 wei`. +This should push the value `7` (left padded byte32) to the stack. + +Bytecode: `0x4800` (`BASEFEE, STOP`) + +| Pc | Op | Cost | Stack | RStack | +|-------|-------------|------|-----------|-----------| +| 0 | BASEFEE | 2 | [] | [] | +| 1 | STOP | 0 | [7] | [] | + +Output: 0x +Consumed gas: `2` + +## Security Considerations + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-3220.md b/EIPS/eip-3220.md new file mode 100644 index 00000000000000..8aef74d1759ea6 --- /dev/null +++ b/EIPS/eip-3220.md @@ -0,0 +1,75 @@ +--- +eip: 3220 +title: Crosschain Identifier Specification +author: Weijia Zhang (@weijia31415), Peter Robinson (@drinkcoffee) +discussions-to: https://ethereum-magicians.org/t/eip-3220-crosschain-id-specification/5446 +status: Draft +type: Standards Track +category: Core +created: 2020-10-21 +--- + +## Simple Summary + +A self-verifying unique blockchain identifier that deals with forks. + +## Abstract + +The crosschain-id is a 32 byte hex string and with some bytes extracted from blockchain hash and some manually defined to characterize a blockchain. +We also propose a registration and lookup service to retrieve blockchain metadata from the crosschain-id. + +## Motivation + +With the success of Bitcoin and Ethereum, various blockchains such as EOS, Ripple, Litecoin, Besu, Wanchain and the like have been developed and are growing at a fast pace. There are also other private and consortium blockchains such as Hyperledger Fabric, Hyperledger Besu, Stellar, Corda, Quorum that only allow nodes with permitted identities to join the blockchain network. The growth of public and private blockchains imposes challenges for inter-chain interoperability, particularly when these chains are heterogeneous and incompatible. Enterprise Ethereum Alliance formed Crosschain Interoperability Task Force (CITF) to look into common crosschain problems and solutions. CITF team noticed that there is a lack of unique identifier to charaterise and describe a blockchain. Several proprosals were discussed in EEA Crosschain Interoperability Task Force meetings and discussions. + +[EIP-155](./eip-155.md) provides a unique identifier to a blockchain to provide simple relay attack protection. This specification defines an integer for Chainid for a blockchain and sign the chainid into a transaction data and hence present attackers to send same transaction to different blockchains. This specification will require blockchains to define a chainid and register the chainid in a public repository. + +The challenge of using an integer for chainid is that it is not broad enough to cover all blockchains and it does not prevent different blockchains using the same chainid. Also, it does not address the issue for two forked blockchains having the same chainid. + +Hence there is need for a more robust blockchain identifier that will overcome these drawbacks, especially for crosschain operations where multiple chains are involved. A blockchain identifier (crosschain id) should be unique and satisfy the following requirements: + +* should provide identification, description, and discovery of blockchains. +* should provide unique identification of each blockchain in the crosschain service ecosystem. +* should provide descriptions for a blockchain identities such as chainId, name, type, consensus scheme etc. +* should provide discovery mechanism for supported blockchains and also for new blockchains in the ecosystem. +* should provide a mechanism for a joining blockchain to register to the ecosystem. +* should provide a mechanism for a blockchain to edit properties or unregister from the crosschain ecosystem. +* should provide a mechanism to get some critical information of the blockchain +* should provide a mechanism to differentiate an original blockchain and a forked blockchain +* should provide a mechanism to verify a chainid without external registration service + +## Specification + +### Definition of a 32 byte crosschain id + +| Name | Size(bytes) | Description | +|---------------|-------------|-------------| +| Truncated Block Hash | 16 | This is the block hash of the genesis block or the block hash of of the block immediate prior to the fork for a fork of a blockchain. The 16 bytes is the 16 least significant bytes, assuming network byte order.| +|Native Chain ID| 4 | This is the **Chain Id** value that should be used with the blockchain when signing transactions. For blockchains that do not have a concept of **Chain Id**, this value is zero.| +|Chain Type| 2 | Researve 0x00 as undefined chaintype. 0x01 as mainnet type. 0x1[0-A]: testnet, 0x2[0-A]: private development network| +| Governance Identifier | 2 | For new blockchains, a governance_identifier can be specified to identify an original **owner** of a blockchain, to help settle forked / main chain disputes. For all existing blockchains and for blockchains that do not have the concept of an **owner**, this field is zero. | +| Reserved | 7 | Reserved for future use. Use 000000 for now. | +| Checksum | 1 | Used to verify the integrity of the identifier. This integrity check is targeted at detecting Crosschain Identifiers mis-typed by human users. The value is calculated as the truncated SHA256 message digest of the rest of the identifier, using the least significant byte, assuming network byte order. Note that this checksum byte only detects integrity with a probability of one in 256. This probability is adequate for the intended usage of detecting typographical errors by people manually entering the Crosschain Identifier. | + + +## Rationale + +We have considered various alternative specifications such as using a random unique hex string to represent a blockchain. The drawback of this method is that the random id can not be used to verify a blockchain's intrinsic identity such as the blockhash of the genesis block. A second alternative is simply using a genesis blockhash to represent a blockchain id for crosschain operations. The drawback of this is that this id does not have information about the property of the blockchain and it has problem when a blockchain is forked into two blockchain. + +## Backwards Compatibility + +Crosschainid can be backward compatible with EIP-155. The crosschain id contains a 4 byte segment to record the chainid based on EIP-155. + +## Security Considerations + +Collision of crosschain id: Two blockchains can contain the same crosschain id and hence making the mistakenly transfer assets to a wrong blockchain. +This security concern is addressed by comparing the hash of the crosschain id with the hash of the genesis block. If it matches, then the crosschain id is verified. If not, the crosschain id can be compared with the forked blockhash. If none of the blockhash match the crosschain id hash, then the crosschain id cannot be verified. + +Preventing relay attack: Although crosschain id by itself is different from chainid and it is not signed into blockchain transaction, the crosschain id can still be used for presenting relay attack. An application that handles crosschain transaction can verified the crosschain id with its blockhash and decide whether the transaction is valid or not. Any transaction with a non-verifiable crosschain id should be rejected. + +The crosschain-id are not required to be signed into blockchaid tx. +For blockchains that do not cryptographically sign crosschain id into the blocks, the crosschain id cannot be verified with the blocks itself and have to be verified with external smart contract address and offchain utilities implemented based on the crosschain id specification. + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-3224.md b/EIPS/eip-3224.md new file mode 100644 index 00000000000000..94b48a572b15f6 --- /dev/null +++ b/EIPS/eip-3224.md @@ -0,0 +1,447 @@ +--- +eip: 3224 +title: Described Data and Described Transactions +author: Richard Moore (@ricmoo), Nick Johnson (@arachnid) +discussions-to: https://github.com/ethereum/EIPs/issues/3225 +status: Draft +type: Standards Track +category: ERC +created: 2021-01-23 +requires: 191 +--- + +## Simple Summary + +A technique for contract authors to enable wallets to provide +a human-readable description of what a given contract +interaction (via a transaction or signed message) will perform. + + +## Abstract + +Human-readable descriptions for machine executable operations, +described in higher level machine readable data, so that wallets +can provide meaningful feedback to the user describing the +action the user is about to perform. + + +## Motivation + +When using an Ethereum Wallet (e.g. MetaMask, Clef, Hardware +Wallets) users must accept and authorize signing messages or +sending transactions. + +Due to the complexity of Ethereum transactions, wallets are very +limitd in their ability to provide insight into the contents of +transactions user are approving; outside special-cased support +for common transactions such as ERC20 transfers, this often amounts +to asking the user to sign an opaque blob of binary data. + +This EIP presents a method for dapp developers to enable a more +comfortable user experience by providing wallets with a means +to generate a better description about what the contract claims +will happen. + +It does not address malicious contracts which wish to lie, it +only addresses honest contracts that want to make their user's +life better. We believe that this is a reasonable security model, +as transaction descriptions can be audited at the same time as +contract code, allowing auditors and code reviewers to check that +transaction descriptions are accurate as part of their review. + + +## Specification + +The **description string** and **described data** are generated +simultaneously by evaluating the contract +(i.e. the **describer**), passing the **describer inputs** to the +method: + +```solidity +function eipXXXDescribe(bytes describer_inputs) view returns (string description_string, bytes described_data); +``` + +The method must be executable in a static context, (i.e. any +side effects, such as logX, sstore, etc.), including through +indirect calls may be ignored. + +During evaluation, the `ADDRESS` (i.e. `to`), `CALLER` +(i.e. `from`), `VALUE`, and `GASPRICE` must be the same as the +values for the transaction being described, so that the +code generating the description can rely on them. For signing +**described messages**, `VALUE` should always be 0. + +When executing the bytecode, best efforts should be made to +ensure `BLOCKHASH`, `NUMBER`, `TIMESTAMP` and `DIFFICULTY` +match the `"latest"` block. The `COINBASE` should be the zero +address. + +The method may revert, in which case the signing must be aborted. + + +### New JSON-RPC Methods + +Clients which manage private keys should expose additional +methods for interacting with the related accounts. + +If an user interface is not present or expected for any other +account-based operations, the description strings should be +ignored and the described data used directly. + +These JSON-RPC methods will also be implemented in standard +Ethereum libraries, so the JSON-RPC description is meant more +of a canonical way to describe them. + + +### Signing Described Messages + +```solidity +eth_signDescribedMessage(address, describer, describerInput) +// Result: { +// description: "text/plain;Hello World", +// data: "0x...", // described data +// signature: "0x..." +// } +``` + +Compute the **description string** and **described data** by +evaluating the call to **describer**, with the +**describerInput** passed to the ABI encoded call to +`eipXXXDescription(bytes)`. The `VALUE` during execution must +be 0. + +If the wallet contains a user interface for accepting or +denying signing a message, it should present the description +string to the user. Optionally, a wallet may wish to +additionally provide a way to examine the described data. + +If accepted, the computed **described data** is signed +according to [EIP-191](./eip-191.md), with the *version +byte* of `0x00` and the *version specific data* of describer +address. + +That is: + +``` +0x19 0x00 DESCRIBER_ADDRESS 0xDESCRIBED_DATA +``` + +The returned result includes the **described data**, allowing +dapps that use parameters computed in the contract to be +available. + +### Sending Described Transactions + +```solidity +eth_sendDescribedTransaction(address, { + to: "0x...", + value: 1234, + nonce: 42, + gas: 42000, + gasPrice: 9000000000, + describerInput: "0x1234...", +}) +// Result: { +// description: "text/plain;Hello World", +// transaction: "0x...", // serialized signed transaction +// } +``` + +Compute the **description string** and **described data** by +evaluating the call to the **describer** `to`, with the +**describerInput** passed to the ABI encoded call to +`eipXXXDescription(bytes)`. + +If the wallet contains a user interface for accepting or +denying a transaction, it should present the description string +along with fee and value information. Optionally, a wallet may +wish to additionally provide a way to further examine the +transaction. + +If accepted, the transaction data is set to the computed +**described data**, the derived transaction is signed and sent, +and the **description string** and serialized signed +transaction is returned. + + +### Signing Described Transaction + +```solidity +eth_signDescribedTransaction(address, { + to: "0x...", + value: 1234, + nonce: 42, + gas: 42000, + gasPrice: 9000000000, + describerInput: "0x1234...", +}) +// Result: { +// description: "text/plain;Hello World", +// transaction: "0x...", // serialized signed transaction +// } +``` + +Compute the **description string** and **described data** by +evaluating the call to the **describer** `to`, with the +**describerInput** passed to the ABI encoded call to +`eipXXXDescription(bytes)`. + +If the wallet contains a user interface for accepting or +denying a transaction, it should present the description string +along with fee and value information. Optionally, a wallet may +wish to additionally provide a way to further examine the +transaction. + +If accepted, the transaction data is set to the computed +**described data**, the derived transaction is signed (and not +sent) and the **description string** and serialized signed +transaction is returned. + +### Description Strings + +A **description string** must begin with a mime-type followed +by a semi-colon (`;`). This EIP specifies only the `text/plain` +mime-type, but future EIPs may specify additional types to +enable more rich processing, such as `text/markdown` so that +addresses can be linkable within clients or to enable +multi-locale options, similar to multipart/form-data. + + +## Rationale + +### Meta Description + +There have been many attempts to solve this problem, many of +which attempt to examine the encoded transaction data or +message data directly. + +In many cases, the information that would be necessary for a +meaningful description is not present in the final encoded +transaction data or message data. + +Instead this EIP uses an indirect description of the data. + +For example, the `commit(bytes32)` method of ENS places a +commitement **hash** on-chain. The hash contains the +**blinded** name and address; since the name is blinded, the +encoded data (i.e. the hash) no longer contains the original +values and is insufficient to access the necessary values to +be included in a description. + +By instead describing the commitment indirectly (with the +original information intact: NAME, ADDRESS and SECRET) a +meaningful description can be computed (e.g. "commit to NAME for ADDRESS (with SECRET)") +and the matching data can be computed (i.e. `commit(hash(name, owner, secret))`). + +### Entangling the Contract Address + +To prevent data being signed from one contract being used +against another, the contract address is entanlged into +both the transaction (implicitly via the `to` field) and +in messages by the EIP-191 versions specific data. + +The use of the zero address is reserved. + +### Alternatives + +- NatSpec and company are a class of more complex languages that attempt to describe the encoded data directly. Because of the language complexity they often end up being quite large requiring entire runtime environments with ample processing power and memory, as well as additional sandboxing to reduce security concerns. One goal of this is to reduce the complexity to something that could execute on hardware wallets and other simple wallets. These also describe the data directly, which in many cases (such as blinded data), cannot adequately describe the data at all + +- Custom Languages; due to the complexity of Ethereum transactions, any language used would require a lot of expressiveness and re-inventing the wheel. The EVM already exists (it may not be ideal), but it is there and can handle everything necessary. + +- Format Strings (e.g. Trustless Signing UI Protocol; format strings can only operate on the class of regular languages, which in many cases is insufficient to describe an Ethereum transaction. This was an issue quite often during early attempts at solving this problem. + +- The signTypedData [EIP-712](./eip-712.md) has many parallels to what this EIP aims to solve + +- @TODO: More + + +## Backwards Compatibility + +All signatures for messages are generated using [EIP-191](./eip-191.md) +which had a previously compatible version byte of `0x00`, so +there should be no concerns with backwards compatibility. + + +## Test Cases + +All test cases operate against the published and verified contracts: + +- [Formatter](https://ropsten.etherscan.io/address/0x7a89c0521604008c93c97aa76950198bca73d933#code) +- [TestFormatter](https://ropsten.etherscan.io/address/0xab3045aa85cbcabb06ed3f3fe968fa5457727270#code) + +The private key used for signing messages and transactions is: + +``` +privateKey = "0x6283185307179586476925286766559005768394338798750211641949889184" +``` + + +### Messages + +**Example: login with signed message** + +- sends selector login() +- received data with selector doLogin(bytes32 timestamp) + +``` +Input: + Address: 0xab3045AA85cBCaBb06eD3F3FE968fA5457727270 + Describer Input: 0xb34e97e800000000000000000000000000000000000000000000000000000000 + i.e. encode( + [ "bytes4" ], + [ SEL("login()") ] + ) + +Output: + Description: text/plain;Log into ethereum.org? + Data: 0x14629d78000000000000000000000000000000000000000000000000000000006010d607 + i.e. encodeWithSelector("doLogin(bytes32)", "0x000000000000000000000000000000000000000000000000000000006010d607" ] + +Signing: + Preimage: 0x1900ab3045aa85cbcabb06ed3f3fe968fa545772727014629d78000000000000000000000000000000000000000000000000000000006010d607 + Signature: 0x8b9def29343c85797a580c5cd3607c06e78a53351219f9ba706b9985c1a3c91e702bf678e07f5daf5ef48b3e3cc581202de233904b72cf2c4f7d714ce92075b21c +``` + +### Transactions + +All transaction test cases use the ropsten network (chainId: 3) +and for all unspecified properties use 0. + +**Example: ERC-20 transfer** + +``` +Input: + Address: 0xab3045AA85cBCaBb06eD3F3FE968fA5457727270 + Describer Input: 0xa9059cbb000000000000000000000000000000000000000000000000000000000000000000000000000000008ba1f109551bd432803012645ac136ddd64dba720000000000000000000000000000000000000000000000002b992b75cbeb6000 + i.e. encode( + [ "bytes4", "address", "uint"], + [ SEL("transfer(address,uint256)"), "0x8ba1f109551bD432803012645Ac136ddd64DBA72", 3.14159e18 ] + ) +Output: + Description: text/plain;Send 3.14159 TOKN to "ricmoose.eth" (0x8ba1f109551bD432803012645Ac136ddd64DBA72)? + Described Data: 0xa9059cbb0000000000000000000000000000000000000000000000002b992b75cbeb60000000000000000000000000008ba1f109551bd432803012645ac136ddd64dba72 + i.e. encodeWithSelector("transfer(address,uint256)", "0x8ba1f109551bD432803012645Ac136ddd64DBA72", 3.14159e18) + +Signing: + Signed Transaction: 0xf8a280808094ab3045aa85cbcabb06ed3f3fe968fa545772727080b844a9059cbb0000000000000000000000000000000000000000000000002b992b75cbeb60000000000000000000000000008ba1f109551bd432803012645ac136ddd64dba7229a0f33ea492d326ac32d9b7ae203c61bf7cf0ac576fb0cf8be8e4c63dc89c90de12a06c8efb28aaf3b70c032b3bd1edfc664578c49f040cf749bb19b000da56507fb2 +``` + +**Example: ERC-20 approve** + +``` +Input: + Address: 0xab3045AA85cBCaBb06eD3F3FE968fA5457727270 + Describer Input: 0x095ea7b3000000000000000000000000000000000000000000000000000000000000000000000000000000008ba1f109551bd432803012645ac136ddd64dba720000000000000000000000000000000000000000000000002b992b75cbeb6000 + i.e. encode( + [ "bytes4", "address", "uint"], + [ SEL("approve(address,uint256)"), "0x8ba1f109551bD432803012645Ac136ddd64DBA72", 3.14159e18 ] + ) + +Output: + Description: text/plain;Approve "ricmoose.eth" (0x8ba1f109551bD432803012645Ac136ddd64DBA72) to manage 3.14159 TOKN tokens? + Described Data: 0xa9059cbb0000000000000000000000000000000000000000000000002b992b75cbeb60000000000000000000000000008ba1f109551bd432803012645ac136ddd64dba72 + i.e. encodeWithSelector("approve(address,uint256)", "0x8ba1f109551bD432803012645Ac136ddd64DBA72", 3.14159e18) + +Signing: + Signed Transaction: 0xf8a280808094ab3045aa85cbcabb06ed3f3fe968fa545772727080b844a9059cbb0000000000000000000000000000000000000000000000002b992b75cbeb60000000000000000000000000008ba1f109551bd432803012645ac136ddd64dba7229a0f33ea492d326ac32d9b7ae203c61bf7cf0ac576fb0cf8be8e4c63dc89c90de12a06c8efb28aaf3b70c032b3bd1edfc664578c49f040cf749bb19b000da56507fb2 +``` + +**Example: ENS commit** + +``` +Input: + Address: 0xab3045AA85cBCaBb06eD3F3FE968fA5457727270 + Describer Input: 0x0f0e373f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000e31f43c1d823afaa67a8c5fbb8348176d225a79e65462b0520ef7d3df61b9992ed3bea0c56ead753be7c8b3614e0ce01e4cac41b00000000000000000000000000000000000000000000000000000000000000087269636d6f6f7365000000000000000000000000000000000000000000000000 + i.e. encode( + [ "bytes4", "string", "address", "bytes32"], + [ SEL("commit(string,address,bytes32)"), "ricmoose", "0xE31f43C1d823AfAA67A8C5fbB8348176d225A79e", "0x65462b0520ef7d3df61b9992ed3bea0c56ead753be7c8b3614e0ce01e4cac41b" ] + ) + +Output: + Description: text/plain;Commit to the ENS name "ricmoose.eth" for 0xE31f43C1d823AfAA67A8C5fbB8348176d225A79e? + Described Data: 0xf14fcbc8e4a4f2bb818545497be34c7ab30e6e87e0001df4ba82e7c8b3f224fbaf255b91 + i.e. encodeWithSelector("commit(bytes32)", makeCommitment("ricmoose", "0xE31f43C1d823AfAA67A8C5fbB8348176d225A79e", "0x65462b0520ef7d3df61b9992ed3bea0c56ead753be7c8b3614e0ce01e4cac41b")) + +Signing: + Signed Transaction: 0xf88180808094ab3045aa85cbcabb06ed3f3fe968fa545772727080a4f14fcbc8e4a4f2bb818545497be34c7ab30e6e87e0001df4ba82e7c8b3f224fbaf255b912aa0a62b41d1ebda584fe84cf8a05f61b429fe4ec361e13c17f30a23281106b38a8da00bcdd896fe758d8f0cfac46445a48f76f5e9fe27790d67c51412cb98a12a0844 +``` + +**Example: WETH mint()** + +``` +Input: + Address: 0xab3045AA85cBCaBb06eD3F3FE968fA5457727270 + Describer Input: 0x1249c58b00000000000000000000000000000000000000000000000000000000 + i.e. encode( + [ "bytes4" ], + [ SEL("mint()") ] + ) + Value: 1.23 ether + +Output: + Description: text/plain;Mint 1.23 WETH (spending 1.23 ether)? + Described Data: 0x1249c58b + i.e. encodeWithSelector("mint()") + +Signing: + Signed Transaction: 0xf86980808094ab3045aa85cbcabb06ed3f3fe968fa5457727270881111d67bb1bb0000841249c58b29a012df802e1394a97caab23c15c3a8c931668df4b2d6d604ca23f3f6b836d0aafca0071a2aebef6a9848616b4d618912f2003fb4babde3dba451b5246f866281a654 +``` + +## Reference Implementation + +@TODO (consider adding it as one or more files in `../assets/eip-####/`) + +I will add examples in Solidity and JavaScript. + + +## Security Considerations + +### Escaping Text + +Wallets must be careful when displaying text provided by +contracts and proper efforts must be taken to sanitize +it, for example, be sure to consider: + +- HTML could be enbedded to attempt to trick web-based wallets into [executing code](https://en.wikipedia.org/wiki/Code_injection) using the script tag (possibly uploading any private keys to a server) +- In general, extreme care must be used when rendering HTML; consider the ENS names `not-ricmoo.eth` or ` ricmoo.eth`, which if rendered without care would appear as `ricmoo.eth`, which it is not +- Other marks which require escaping could be included, such as quotes (`"`), formatting (`\n` (new line), `\f` (form feed), `\t` (tab), any of many [non-standard whitespaces](https://en.wikipedia.org/wiki/Whitespace_character#Spaces_in_Unicode)), back-slassh (`\`) +- UTF-8 has had bugs in the past which could allow arbitrary code execution and [crashing renderers](https://osxdaily.com/2015/05/27/bug-crashes-messages-app-ios-workaround/); consider using the UTF-8 replacement character (or *something*) for code-points outside common planes or common sub-sets within planes +- [Homoglyphs attacks](https://en.wikipedia.org/wiki/IDN_homograph_attack) +- [Right-to-left](https://en.wikipedia.org/wiki/Right-to-left_mark) mark may affect rendering +- Many other things, deplnding on your environment + +### Distinguished Signed Data + +Applications implementing this EIP to sign message data should +ensure there are no collisions within the data which could +result in ambiguously signed data. + +@TODO: Expand on this; compare packed data to ABI encoded data? + +### Enumeration + +If an abort occurs during signing, the response from this call +should match the response from a declined signing request; +otherwise this could be used for enumeration attacks, etc. A +random interactive-scale delay should also be added, otherwise +a < 10ms response could be interpreted as an error. + +### Replayablility + +Transactions contain an explicit nonce, but signed messages do +not. + +For many purposes, such as signing in, a nonce could be +injected (using block.timestamp) into the data. The log in +service can verify this is a recent timestamp. The timestamp +may or may not be omitted from the description string in this +case, as it it largely useful internally only. + +In general, when signing messages a nonce often makes sense to +include to prevent the same signed data from being used in the +future. + + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-3234.md b/EIPS/eip-3234.md new file mode 100644 index 00000000000000..e1ecaf35586702 --- /dev/null +++ b/EIPS/eip-3234.md @@ -0,0 +1,220 @@ +--- +eip: 3234 +title: Batch Flash Loans +author: Alberto Cuesta Cañada (@albertocuestacanada), Fiona Kobayashi (@fifikobayashi), fubuloubu (@fubuloubu), Austin Williams (@onewayfunction) +discussions-to: https://ethereum-magicians.org/t/erc-3234-batch-flash-loans/5271 +status: Draft +type: Standards Track +category: ERC +created: 2021-01-31 +--- + +## Simple Summary + +This ERC provides standard interfaces and processes for multiple-asset flash loans. + +## Motivation + +Flash loans of multiple assets, or batch flash loans, are a common offering of flash lenders, and have a strong use case in the simultaneous refinance of several positions between platforms. At the same time, batch flash loans are more complicated to use than single asset flash loans (ER3156). This divergence of use cases and user profiles calls for independent, but consistent, standards for single asset flash loans and batch flash loans. + + +## Specification + +A batch flash lending feature integrates two smart contracts using a callback pattern. These are called the LENDER and the RECEIVER in this EIP. + +### Lender Specification + +A `lender` MUST implement the IERC3234BatchFlashLender interface. +``` +pragma solidity ^0.7.0 || ^0.8.0; +import "./IERC3234BatchFlashBorrower.sol"; + + +interface IERC3234BatchFlashLender { + + /** + * @dev The amount of currency available to be lended. + * @param tokens The currency for each loan in the batch. + * @return The maximum amount that can be borrowed for each loan in the batch. + */ + function maxFlashLoan( + address[] calldata tokens + ) external view returns (uint256[]); + + /** + * @dev The fees to be charged for a given batch loan. + * @param tokens The loan currencies. + * @param amounts The amounts of tokens lent. + * @return The amount of each `token` to be charged for each loan, on top of the returned principal. + */ + function flashFee( + address[] calldata tokens, + uint256[] calldata amounts + ) external view returns (uint256[]); + + /** + * @dev Initiate a batch flash loan. + * @param receiver The receiver of the tokens in the loan, and the receiver of the callback. + * @param tokens The loan currencies. + * @param amounts The amount of tokens lent. + * @param data Arbitrary data structure, intended to contain user-defined parameters. + */ + function batchFlashLoan( + IERC3234BatchFlashBorrower receiver, + address[] calldata token, + uint256[] calldata amount, + bytes[] calldata data + ) external returns (bool); +} +``` + +The `maxFlashLoan` function MUST return the maximum loan possible for each `token`. If a `token` is not currently supported `maxFlashLoan` MUST return 0, instead of reverting. + +The `flashFee` function MUST return the fees charged for each loan of `amount` `token`. If a token is not supported `flashFee` MUST revert. + +The `batchFlashLoan` function MUST include a callback to the `onBatchFlashLoan` function in a `IERC3234BatchFlashBorrower` contract. + +``` +function batchFlashLoan( + IERC3234BatchFlashBorrower receiver, + address[] calldata tokens, + uint256[] calldata amounts, + bytes calldata data +) external returns (bool) { + ... + require( + receiver.onBatchFlashLoan(msg.sender, tokens, amounts, fees, data), + "IERC3234: Callback failed" + ); + ... +} +``` + +The `batchFlashLoan` function MUST transfer `amounts[i]` of each `tokens[i]` to `receiver` before the callback to the borrower. + +The `batchFlashLoan` function MUST include `msg.sender` as the `initiator` to `onBatchFlashLoan`. + +The `batchFlashLoan` function MUST NOT modify the `tokens`, `amounts` and `data` parameters received, and MUST pass them on to `onBatchFlashLoan`. + +The `lender` MUST verify that the `onBatchFlashLoan` callback returns the keccak256 hash of "ERC3234BatchFlashBorrower.onBatchFlashLoan". + +The `batchFlashLoan` function MUST include a `fees` argument to `onBatchFlashLoan` with the fee to pay for each individual `token` and `amount` lent, ensuring that `fees[i] == flashFee(tokens[i], amounts[i])`. + +After the callback, for each `token` in `tokens`, the `batchFlashLoan` function MUST take the `amounts[i] + fees[i]` of `tokens[i]` from the `receiver`, or revert if this is not successful. + +If successful, `batchFlashLoan` MUST return `true`. + +### Receiver Specification + +A `receiver` of flash loans MUST implement the IERC3234FlashBorrower interface: + +``` +pragma solidity ^0.7.0 || ^0.8.0; + + +interface IERC3234FlashBorrower { + + /** + * @dev Receive a flash loan. + * @param initiator The initiator of the loan. + * @param token The loan currency. + * @param amount The amount of tokens lent. + * @param fee The additional amount of tokens to repay. + * @param data Arbitrary data structure, intended to contain user-defined parameters. + * @return The keccak256 hash of "ERC3234BatchFlashBorrower.onBatchFlashLoan" + */ + function onBatchFlashLoan( + address initiator, + address[] calldata tokens, + uint256[] calldata amounts, + uint256[] calldata fees, + bytes calldata data + ) external returns (bytes32); +} +``` + +For the transaction to not revert, for each `token` in `tokens`, `receiver` MUST approve `amounts[i] + fees[i]` of `tokens[i]` to be taken by `msg.sender` before the end of `onBatchFlashLoan`. + +If successful, `onBatchFlashLoan` MUST return the keccak256 hash of "ERC3156BatchFlashBorrower.onBatchFlashLoan". + +## Rationale + +The interfaces described in this ERC have been chosen as to cover the known flash lending use cases, while allowing for safe and gas efficient implementations. + +`flashFee` reverts on unsupported tokens, because returning a numerical value would be incorrect. + +`batchFlashLoan` has been chosen as a function name as descriptive enough, unlikely to clash with other functions in the lender, and including both the use cases in which the tokens lended are held or minted by the lender. + +`receiver` is taken as a parameter to allow flexibility on the implementation of separate loan initiators and receivers. + +Existing flash lenders (Aave, dYdX and Uniswap) all provide flash loans of several token types from the same contract (LendingPool, SoloMargin and UniswapV2Pair). Providing a `token` parameter in both the `batchFlashLoan` and `onBatchFlashLoan` functions matches closely the observed functionality. + +A `bytes calldata data` parameter is included for the caller to pass arbitrary information to the `receiver`, without impacting the utility of the `batchFlashLoan` standard. + +`onBatchFlashLoan` has been chosen as a function name as descriptive enough, unlikely to clash with other functions in the `receiver`, and following the `onAction` naming pattern used as well in EIP-667. + +An `initiator` will often be required in the `onBatchFlashLoan` function, which the lender knows as `msg.sender`. An alternative implementation which would embed the `initiator` in the `data` parameter by the caller would require an additional mechanism for the receiver to verify its accuracy, and is not advisable. + +The `amounts` will be required in the `onBatchFlashLoan` function, which the lender took as a parameter. An alternative implementation which would embed the `amounts` in the `data` parameter by the caller would require an additional mechanism for the receiver to verify its accuracy, and is not advisable. + +The `fees` will often be calculated in the `batchFlashLoan` function, which the `receiver` must be aware of for repayment. Passing the `fees` as a parameter instead of appended to `data` is simple and effective. + +The `amount + fee` are pulled from the `receiver` to allow the `lender` to implement other features that depend on using `transferFrom`, without having to lock them for the duration of a flash loan. An alternative implementation where the repayment is transferred to the `lender` is also possible, but would need all other features in the lender to be also based in using `transfer` instead of `transferFrom`. Given the lower complexity and prevalence of a "pull" architecture over a "push" architecture, "pull" was chosen. + +## Security Considerations + +### Verification of callback arguments + +The arguments of `onBatchFlashLoan` are expected to reflect the conditions of the flash loan, but cannot be trusted unconditionally. They can be divided in two groups, that require different checks before they can be trusted to be genuine. + +0. No arguments can be assumed to be genuine without some kind of verification. `initiator`, `tokens` and `amounts` refer to a past transaction that might not have happened if the caller of `onBatchFlashLoan` decides to lie. `fees` might be false or calculated incorrectly. `data` might have been manipulated by the caller. +1. To trust that the value of `initiator`, `tokens`, `amounts` and `fees` are genuine a reasonable pattern is to verify that the `onBatchFlashLoan` caller is in a whitelist of verified flash lenders. Since often the caller of `batchFlashLoan` will also be receiving the `onBatchFlashLoan` callback this will be trivial. In all other cases flash lenders will need to be approved if the arguments in `onBatchFlashLoan` are to be trusted. +2. To trust that the value of `data` is genuine, in addition to the check in point 1, it is recommended that the `receiver` verifies that the `initiator` is in some list of trusted addresses. Trusting the `lender` and the `initiator` is enough to trust that the contents of `data` are genuine. + +### Flash lending security considerations + +#### Automatic approvals for untrusted borrowers +The safest approach is to implement an approval for `amount+fee` before the `batchFlashLoan` is executed. + +Including in `onBatchFlashLoan` the approval for the `lender` to take the `amount + fee` needs to be combined with a mechanism to verify that the borrower is trusted, such as those described above. + +If an unsuspecting contract with a non-reverting fallback function, or an EOA, would approve a `lender` implementing ERC3156, and not immediately use the approval, and if the `lender` would not verify the return value of `onBatchFlashLoan`, then the unsuspecting contract or EOA could be drained of funds up to their allowance or balance limit. This would be executed by a `borrower` calling `batchFlashLoan` on the victim. The flash loan would be executed and repaid, plus any fees, which would be accumulated by the `lender`. For this reason, it is important that the `lender` implements the specification in full and reverts if `onBatchFlashLoan` doesn't return the keccak256 hash for "ERC3156FlashBorrower.onBatchFlashLoan". + +### Flash minting external security considerations + +The typical quantum of tokens involved in flash mint transactions will give rise to new innovative attack vectors. + +#### Example 1 - interest rate attack +If there exists a lending protocol that offers stable interests rates, but it does not have floor/ceiling rate limits and it does not rebalance the fixed rate based on flash-induced liquidity changes, then it could be susceptible to the following scenario: + +FreeLoanAttack.sol +1. Flash mint 1 quintillion DAI +2. Deposit the 1 quintillion DAI + $1.5 million worth of ETH collateral +3. The quantum of your total deposit now pushes the stable interest rate down to 0.00001% stable interest rate +4. Borrow 1 million DAI on 0.00001% stable interest rate based on the 1.5M ETH collateral +5. Withdraw and burn the 1 quint DAI to close the original flash mint +6. You now have a 1 million DAI loan that is practically interest free for perpetuity ($0.10 / year in interest) + +The key takeaway being the obvious need to implement a flat floor/ceiling rate limit and to rebalance the rate based on short term liquidity changes. + +#### Example 2 - arithmetic overflow and underflow +If the flash mint provider does not place any limits on the amount of flash mintable tokens in a transaction, then anyone can flash mint 2^256-1 amount of tokens. + +The protocols on the receiving end of the flash mints will need to ensure their contracts can handle this. One obvious way is to leverage OpenZeppelin's SafeMath libraries as a catch-all safety net, however consideration should be given to when it is or isn't used given the gas tradeoffs. + +If you recall there was a series of incidents in 2018 where exchanges such as OKEx, Poloniex, HitBTC and Huobi had to shutdown deposits and withdrawls of ERC20 tokens due to integer overflows within the ERC20 token contracts. + + +### Flash minting internal security considerations + +The coupling of flash minting with business specific features in the same platform can easily lead to unintended consequences. + +#### Example - Treasury draining +In early implementations of the Yield Protocol flash loaned fyDai could be redeemed for Dai, which could be used to liquidate the Yield Protocol CDP vault in MakerDAO: +1. Flash mint a very large amount of fyDai. +2. Redeem for Dai as much fyDai as the Yield Protocol collateral would allow. +3. Trigger a stability rate increase with a call to `jug.drip` which would make the Yield Protocol uncollateralized. +4. Liquidate the Yield Protocol CDP vault in MakerDAO. + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-3238.md b/EIPS/eip-3238.md new file mode 100644 index 00000000000000..7c27597b7e673d --- /dev/null +++ b/EIPS/eip-3238.md @@ -0,0 +1,39 @@ +--- +eip: 3238 +title: Difficulty Bomb Delay to Summer 2022 +author: Afri Schoedon (@q9f) +discussions-to: https://github.com/ethereum/EIPs/issues/3239 +type: Standards Track +category: Core +status: Draft +created: 2021-01-25 +--- + +## Simple Summary +Delays the difficulty bomb so 30 second blocks won't happen until around summer 2022. + +## Abstract +Starting with `FORK_BLOCK_NUMBER` the client will calculate the difficulty based on a fake block number suggesting to the client that the difficulty bomb is adjusting eleven million blocks later than the actual block number. + +## Motivation +Even after the Ethereum 2.0 mainnet launch, Ethash proof-of-work mining on the legacy chain should be feasible. It should allow miners sealing new blocks every 13~15 seconds on average for another ten months and allow both Ethereum 1.x and Ethereum 2.0 developers to conclude the merge. + +## Specification +#### Relax Difficulty with Fake Block Number +For the purposes of `calc_difficulty`, simply replace the use of `block.number`, as used in the exponential ice age component, with the formula: + + fake_block_number = max(0, block.number - 11_000_000) if block.number >= FORK_BLOCK_NUMBER else block.number + +## Rationale +This will delay the ice age by another ~26 million seconds (approximately ~9.89 months), so the chain would be back at ~30 second block times in summer 2022. Hopefully, by then the Eth1-to-Eth2 merge will be concluded and the ice age fulfilled its task. + +## Backwards Compatibility +This EIP is not forward compatible and introduces backwards incompatibilities in the difficulty calculation. Therefore, it should be included in a scheduled hardfork at a certain block number. It's suggested to consider this EIP either with or shortly after the Berlin hard-fork but not later than July 2021. + +Alternatively, in order to maintain stability of the system, a it can be considered to activate this EIP along with EIP-1559 fee market changes in a bundle. With the delay of the ice age, there is a desire to no further increase inflation and rather incentivize users to participate in proof-of-stake consensus instead. + +## Security Considerations +There are no known security issues with this proposal. + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-3267.md b/EIPS/eip-3267.md new file mode 100644 index 00000000000000..fc489da16a4996 --- /dev/null +++ b/EIPS/eip-3267.md @@ -0,0 +1,69 @@ +--- +eip: 3267 +title: Giving Ethereum fees to Future Salaries +author: Victor Porton (@vporton), Victor Porton +discussions-to: https://ethereum-magicians.org/t/discussion-of-eip-3267/5343 +status: Draft +type: Standards Track +category: Core +created: 2021-02-13 +--- + +## Simple Summary +Transfer a part of Ethereum transfer/mining fees to Future Salaries contract + +## Abstract +Transfer a part (exact fractions - TBD) of mining/transfer fees + (probably: TBD) some minted ETH to the `DonateETH` contract configured to transfer to `SalaryWithDAO` contract. + +## Motivation +This proposal solves two problems at once: + +1. It provides a big amount of "money" to common good producers. That obviously personally benefits common good producers, allowing them to live better human lives, it increases peoples' and organizations' both abilities and incentives to produce common goods. That benefits the humanity as a whole and the Ethereum ecosystem in particular. See more in the discussion why it's crucial. + +2. This would effectively decrease circulating ETH supply. The necessity to decrease the (circulating) ETH supply (by locking ETH in Future Salaries system for a long time) is a well-known important thing to be done. + +Paradoxically, it will directly benefit miners/validators, see the discussion. + +## Specification +(TBD) + +`SalaryWithDAO` = `TBD` (`address`) + +`DefaultDAOInterface` = `TBD` (`address`) + +`MintPerPeriod` = `TBD` (`uint256`) + +`TransferFraction` = `TBD` (0..1) + +`MineFraction` = `TBD` (0..1) + +[The contracts source](../assets/eip-3267/contracts/README.md) + +Prior to `FORK_BLOCK_NUMBER`, `SalaryWithDAO` and `DefaultDAOInterface` contracts will be deployed to the network and exist at the above specified addresses. + +Change the Ethereum clients to transfer at every ETH transfer and every ETH mine a fixed fraction `TransferFraction` of the transferred ETH and `MineFraction` of the mined ETH to a fixed account (decide the account number, it can be for example `0x00000000000000000000000000000000000000001` or even `0x00000000000000000000000000000000000000000` or a random account). + +Change the Ethereum clients to mint `MintPerPeriod` ETH to the contract `DonateETH` every some time (e.g. the first transaction of the first block every UTC day - TBD how often). + +Change the Ethereum clients to every some time (e.g. the second transaction of the first block every UTC day - TBD how often) transfer the entire ETH from this account to the contract `DonateETH`. + +Because this EIP solves a similar problem, cancel any other EIPs that burn ETH (except gas fees) during transfers or mining. (TBD: We should transfer more ETH in this EIP than we burned accordingly older accepted EIPs, because this EIP has the additional advantages of: 1. funding common goods; 2. better aligning values of ETH and values of tokens). + +## Rationale +The Future Salaries is the _only_ known system of distributing significant funds to common good producers. (Quadratic funding aimed to do a similar thing, but in practice as we see on GitCoin it favors a few developers, ignores project of highly advanced scientific research that is hard to explain to an average developer, and encourages colluding, and it just highly random due to small number of donors. Also quadratic funding simply does not gather enough funds to cover common good needs). So this EIP is the only known way to recover the economy. + +The economical model of Future Salaries is described in [this research article preprint](../assets/eip-3267/science-salaries.pdf). + +Funding multiple oracles with different finish time would alleviate the future trouble that the circulating ETH (or other tokens) supply would suddenly increase when the oracle finishes. It would effectively exclude some ETH from the circulation forever. + +## Backwards Compatibility +Because transferring to the aforementioned account is neither mining nor a transaction, we get a new kinds of ETH transfers, so there may be some (expected moderate impact) troubles with applications that have made assumptions about ETH transfers all occurring either as miner payments or transactions. + +## Security Considerations +The security considerations are: +- The DAO that controls account restoration may switch to a non-effective or biased way of voting (for example to being controlled by one human) thus distributing funds unfairly. This problem could be solved by a future fork of Ethereum that would "confiscate" control from the DAO. + +See more in the discussion. + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-3298.md b/EIPS/eip-3298.md new file mode 100644 index 00000000000000..fa32af840a2ee5 --- /dev/null +++ b/EIPS/eip-3298.md @@ -0,0 +1,95 @@ +--- +eip: 3298 +title: Removal of refunds +author: Vitalik Buterin (@vbuterin), Martin Swende (@holiman) +discussions-to: https://ethereum-magicians.org/t/eip-3298-removal-of-refunds/5430 +status: Draft +type: Standards Track +category: Core +created: 2021-02-26 +--- + +## Simple Summary + +Remove gas refunds for SSTORE and SELFDESTRUCT. + +## Motivation + +Gas refunds for SSTORE and SELFDESTRUCT were originally introduced to motivate application developers to write applications that practice "good state hygiene", clearing storage slots and contracts that are no longer needed. However, they are not widely used for this, and poor state hygiene continues to be the norm. It is now widely accepted that the only solution to state growth is some form of [statelessness or state expiry](https://hackmd.io/@HWeNw8hNRimMm2m2GH56Cw/state_size_management), and if such a solution is implemented, then disused storage slots and contracts would start to be ignored automatically. + +Gas refunds additionally have multiple harmful consequences: + +* Refunds give rise to [GasToken](https://gastoken.io/). GasToken has benefits in moving gas space from low-fee periods to high-fee periods, but it also has downsides to the network, particularly in exacerbating state size (as state slots are effectively used as a "battery" to save up gas) and inefficiently clogging blockchain gas usage +* Refunds increase block size variance. The theoretical maximum amount of actual gas consumed in a block is nearly twice the on-paper gas limit (as refunds add gas space for subsequent transactions in a block, though refunds are capped at 50% of a transaction's gas used). This is [not fatal](https://notes.ethereum.org/@vbuterin/eip_1559_spikes), but is still undesirable, especially given that refunds can be used to maintain 2x usage spikes for far longer than EIP 1559 can. + +## Specification + +### Parameters + +| Constant | Value | +| - | - | +| `FORK_BLOCK` | TBD | + +For blocks where `block.number >= FORK_BLOCK`, the following changes apply. + +Do not apply the `refund`. + +The description above is sufficient to describe the change, but for the sake of clarity we enumerate all places where gas refunds are currently used and which should/could be removed within a node implementation. + +1. Remove all use of the "refund counter" in SSTORE gas accounting, as defined in [EIP 2200](https://eips.ethereum.org/EIPS/eip-2200). Particularly: + + * If a storage slot is changed and the _current value_ equals the _original value_, but does not equal the _new value_, `SSTORE_RESET_GAS` is deducted (plus `COLD_SLOAD_COST` if [prescribed by EIP 2929 rules](https://eips.ethereum.org/EIPS/eip-2929#sstore-changes)), but no modifications to the refund counter are made. + * If a storage slot is changed and the _current value_ equals neither the _new value_ nor the _original value_ (regardless of whether or not the latter two are equal), `SLOAD_GAS` is deducted (plus `COLD_SLOAD_COST` if [prescribed by EIP 2929 rules](https://eips.ethereum.org/EIPS/eip-2929#sstore-changes)), but no modifications to the refund counter are made. + +2. Remove the `SELFDESTRUCT` refund. + +## Rationale + +A full removal of refunds is the simplest way to solve the issues with refunds; any gains from partial retention of the refund mechanism are not worth the complexity that that would leave remaining in the Ethereum protocol. + +## Backwards Compatibility + +Refunds are currently only applied _after_ transaction execution, so they cannot affect how much gas is available to any particular call frame during execution. Hence, removing them will not break the ability of any code to execute, though it will render some applications economically nonviable. + +[GasToken](https://gastoken.io/) in particular will become valueless. DeFi arbitrage bots, which today frequently use either established GasToken schemes or a custom alternative to reduce on-chain costs, would benefit from rewriting their code to remove calls to these no-longer-functional gas storage mechanisms. + +## Implementation + +An implementation can be found here: https://gist.github.com/holiman/460f952716a74eeb9ab358bb1836d821#gistcomment-3642048 + +## Test case changes + +* The "original", "1st", "2nd", "3rd" columns refer to the value of storage slot 0 before the execution and after each SSTORE. +* The "Berlin (cold)" column gives the post-Berlin (EIP 2929) gas cost assuming the storage slot had not yet been accessed. +* The "Berlin (hot)" column gives the post-Berlin gas cost assuming the storage slot has already been accessed. +* The "Berlin (hot) + norefund" column gives the post-Berlin gas cost assuming the storage slot has already been accessed, **and assuming this EIP has been implemented**. + +Gas costs are provided with refunds subtracted; if the number is negative this means that refunds exceed gas costs. The 50% refund limit is not applied (due to the implied assumption that this code is only a small fragment of a much larger execution). + +If refunds were to be removed, this would be the comparative table +| Code | Original | 1st | 2nd | 3rd | Istanbul | Berlin (cold) | Berlin (hot)| Berlin (hot)+norefund | +| -- | -- | -- | -- | -- | -- | -- | -- | -- | +| `0x60006000556000600055` | 0 | 0 | 0 | | 1612 | 2312 | 212 | 212 | +| `0x60006000556001600055` | 0 | 0 | 1 | | 20812 | 22212 | 20112 | 20112 | +| `0x60016000556000600055` | 0 | 1 | 0 | | 1612 | 2312 | 212 | 20112 | +| `0x60016000556002600055` | 0 | 1 | 2 | | 20812 | 22212 | 20112 | 20112 | +| `0x60016000556001600055` | 0 | 1 | 1 | | 20812 | 22212 | 20112 | 20112 | +| `0x60006000556000600055` | 1 | 0 | 0 | | -9188 | -9888 | -11988 | 3012 | +| `0x60006000556001600055` | 1 | 0 | 1 | | 1612 | 2312 | 212 | 3012 | +| `0x60006000556002600055` | 1 | 0 | 2 | | 5812 | 5112 | 3012 | 3012 | +| `0x60026000556000600055` | 1 | 2 | 0 | | -9188 | -9888 | -11988 | 3012 | +| `0x60026000556003600055` | 1 | 2 | 3 | | 5812 | 5112 | 3012 | 3012 | +| `0x60026000556001600055` | 1 | 2 | 1 | | 1612 | 2312 | 212 | 3012 | +| `0x60026000556002600055` | 1 | 2 | 2 | | 5812 | 5112 | 3012 | 3012 | +| `0x60016000556000600055` | 1 | 1 | 0 | | -9188 | -9888 | -11988 | 3012 | +| `0x60016000556002600055` | 1 | 1 | 2 | | 5812 | 5112 | 3012 | 3012 | +| `0x60016000556001600055` | 1 | 1 | 1 | | 1612 | 2312 | 212 | 212 | +| `0x600160005560006000556001600055` | 0 | 1 | 0 | 1 | 21618 | 22318 | 20218 | 40118 | +| `0x600060005560016000556000600055` | 1 | 0 | 1 | 0 | -8382 | -9782 | -11882 | 5918 | + +## Security Considerations + +TBD + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-3300.md b/EIPS/eip-3300.md new file mode 100644 index 00000000000000..8ca17c5ee7770d --- /dev/null +++ b/EIPS/eip-3300.md @@ -0,0 +1,78 @@ +--- +eip: 3300 +title: Phase out refunds +author: William Morriss (@wjmelements) +discussions-to: https://ethereum-magicians.org/t/eip-3300-phase-out-refunds/5434 +status: Draft +type: Standards Track +category: Core +created: 2020-02-26 +--- + +## Simple Summary +Phases out the `SSTORE` and `SELFDESTRUCT` gas refunds. + +## Abstract +This EIP would define a block when the `SSTORE` and `SELFDESTRUCT` refunds would begin to diminish. +The refund would step linearly downward, eroding the implicit value of such refunds at an accelerating pace. + +## Motivation +Refunds increase block elasticity, so the block gas target can exceed the number established by miners by up to 2x. +This can cause hesitancy for miners to increase the block gas target. + +Refunds, tokenized or not, are valuable to their holders, especially during congestion. +If refunds must be removed, a gradual change in their value would be less-disruptive to the gas market than sudden abolition. +Refund consumption would proceed, especially during periods of congestion, and the refunds would be cleaned up from the state. +Refund creation, driven by demand, would naturally diminish as the efficiency of the refunds fall. +As the refund value approaches the activation cost, the implicit value of the refunds will approach zero, but in periods of congestion they will be cleaned up. + +This change is less work for the protocol developers than compensation and cleanup, while likely still achieving cleanup. + + +## Specification +Parameters: +* `FORK_BLOCK_NUM`: EIP-3300 activation block +* `REFUND_DECAY_STEP`: 1 gas +* `REFUND_DECAY_FREQUENCY`: 100 blocks + +Computed: +* `REFUND_DECAY`: `REFUND_DECAY_STEP * ceil((block.number + 1 - FORK_BLOCK_NUM) / REFUND_DECAY_FREQUENCY)` + + +On the block this EIP activates, and again every `REFUND_DECAY_FREQUENCY` blocks, all gas refunds, including `SELFDESTRUCT` and `SSTORE` would diminish by `REFUND_DECAY_STEP`, until 0. +The current difference is called the `REFUND_DECAY`, which shall be subtracted from each gas refund. + +For gas-cost regimes with refund removals that cancel prior refunds, the invariant that the refund counter cannot go negative will be preserved by diminishing the magnitude of those removals by `REFUND_DECAY`, until 0. + + +### EIP-2929 +The refunds as of EIP-2929 are as follows: + +* 24000 for SELFDESTRUCT +* `SSTORE_RESET_GAS - SLOAD_GAS` (5000 - 100) +* `SSTORE_SET_GAS - SLOAD_GAS` (20000 - 100) +* `SSTORE_SET_GAS - SLOAD_GAS` (20000 - 100) +* `SSTORE_CLEARS_SCHEDULE` (15000) + + +Each of these refunds would be decreased by the current `REFUND_DECAY`. + +There is also a case where `SSTORE_CLEARS_SCHEDULE` is removed from the refund counter. +That removal will also diminish by `REFUND_DECAY_STEP` until 0, maintaining the non-negative refund counter invariant. + + +## Rationale +Persisted refunds would become worthless before they fall below their activation cost. +Once the refunds are worthless, they can be removed by another hard fork without waiting for 0. +The rate of diminishing specified would currently require (24000-5000) * 100 = 1,900,000 blocks for `SELFDESTRUCT` and (15000-5000) * 100 = 1,000,000 blocks for `SSTORE`. +This timeframe is currently about a year, which should be enough flexibility for the remaining refunds to be consumed. + + +## Backwards Compatibility +This proposal breaks gas refunds, which contribute to block elasticity. +The effect of this will be increased gas price volatility: higher highs and lower lows. + +Because the refund counter is separate from the gas counter, the block-to-block gas changes will not break `eth_estimateGas`. + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-3322.md b/EIPS/eip-3322.md new file mode 100644 index 00000000000000..4159cdc6502960 --- /dev/null +++ b/EIPS/eip-3322.md @@ -0,0 +1,68 @@ +--- +eip: 3322 +title: Account gas storage opcodes +author: William Morriss (@wjmelements) +discussions-to: https://ethereum-magicians.org/t/eip-3322-efficient-gas-storage/5470 +status: Draft +type: Standards Track +category: Core +created: 2020-03-04 +--- + +## Simple Summary +Allows contract accounts to store gas that can be transferred to the refund counter. + +## Abstract +Contracts can persist gas for later transfer to the refund counter. +Three opcodes are introduced to read, add to, and use this gas counter. + +## Motivation +The refund mechanism is currently being used by gas tokens to arbitrage gas price. +This brings gas supply elasticity and price stability by moving gas from blocks with less demand to blocks with more demand. +Unfortunately this rewards unnecessary state growth. +By introducing a superior gas storage mechanism, the gas market will require less storage and computation. + +## Specification +Contract accounts gain an unsigned gas refund counter, initially zero. + +Three new opcodes are introduced to manage this state. + +* `SELFGAS` (`0x48`): Pushes the current account's gas refund counter onto the stack. +Shares gas pricing with `SELFBALANCE`. +* `USEGAS` (`0x49`): Pops `amount` from the stack. +The minimum of `amount` and the current account's gas refund counter is transferred to the execution context's refund counter. +Costs `5000` gas. +* `STOREGAS` (`0x4a`): Pops `amount` from the stack. +Costs `5000 + amount` gas. +Increases the current account's gas refund counter by `amount`. + +## Rationale +By reusing the execution context's refund counter we can reuse its 50% DoS protection, which limits its block elasticity contribution to 2x. + +The gas costs are based on similar opcodes `SELFBALANCE` and `SSTORE`. + +Most accounts will store no gas, so the per-account storage overhead should be minimal or even zero in the normal case. + +The opcode numbers chosen are in the same `0x4X` range as `SELFBALANCE` and `GASLIMIT`. + +## Backwards Compatibility +Because the gas is added to the refund counter, no compatibility issues are anticipated. + +## Test Cases +| Code | Used Gas | Refund | Original | Final | +|------------------|----------|--------|----------|-------| +| 0x60004900 | 5003 | 0 | 0 | 0 | +| 0x60034900 | 5003 | 2 | 2 | 0 | +| 0x60034900 | 5003 | 3 | 3 | 0 | +| 0x60034900 | 5003 | 3 | 4 | 1 | +| 0x60034960034900 | 10006 | 4 | 4 | 0 | +| 0x60034960034900 | 10006 | 6 | 6 | 0 | +| 0x484900 | 5010 | 100000 | 100000 | 0 | +| 0x61ffff4a00 | 70538 | 0 | 0 | 65535 | + + +## Security Considerations +DoS is already limited by the 50% refund limit. + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-3336.md b/EIPS/eip-3336.md new file mode 100644 index 00000000000000..abc79a0725f35f --- /dev/null +++ b/EIPS/eip-3336.md @@ -0,0 +1,71 @@ +--- +eip: 3336 +title: Paged memory allocation for the EVM +author: Nick Johnson (@arachnid) +discussions-to: https://ethereum-magicians.org/t/eips-3336-and-3337-improving-the-evms-memory-model/5482 +status: Draft +type: Standards Track +category: Core +created: 2021-03-06 +--- + +## Simple Summary +Changes the memory model for the EVM to use pagination. + +## Abstract +Presently, the EVM charges for memory as a linear array starting at address 0 and extending to the highest address that has been read from or written to. This suffices for simple uses, but means that compilers have to generate programs that use memory compactly, which leads to wasted gas with reallocation of memory elements, and makes some memory models such as separate heap and stack areas impractical. This EIP proposes changing to a page-based billing model, which adds minimal complexity to implementations, while providing for much more versatility in EVM programs. + +## Motivation +Most modern computers implement "virtual memory" for userspace programs, where programs have access to a large address space, with pages of RAM that are allocated as needed by the OS. This allows them to distribute data throughout memory in ways that minimises the amount of reallocation and copying that needs to go on, and permits flexible use of memory for data with different lifetimes. Implementing a simple version of paged memory inside the EVM will provide the same flexibility to compilers targeting the EVM. + +## Specification +### Parameters + +| Constant | Value | +| - | - | +| `FORK_BLOCK` | TBD | +| `PAGE_BITS` | 10 | +| `PAGE_BASE_COST` | 96 | + +For blocks where `block.number >= FORK_BLOCK`, the following changes apply. + +### Changes to memory allocation in EVM implementations +Memory is now allocated in pages of `2**PAGE_BITS` bytes each. The most significant `256 - PAGE_BITS` bits of each memory address denote the page number, while the least significant `PAGE_BITS` bits of the memory address denote the location in the page. Pages are initialized to contain all zero bytes and allocated when the first byte from a page is read or written. + +EVM implementations are encouraged to store the pagetable as an associative array (eg, hashtable or dict) mapping from page number to an array of bytes for the page. + +### Changes to memory expansion gas cost +Presently, the total cost to extend the memory to `a` words long is `Cmem(a) = 3 * a + floor(a ** 2 / 512)`. If the memory is already `b` words long, the incremental cost is `Cmem(a) - Cmem(b)`. `a` is the number of words required to cover the range from memory address 0 to the last word that has been read or written by the EVM. + +Under this EIP, we define a new memory cost function, based on the number of allocated pages. This function is `Cmem'(p) = max(PAGE_BASE_COST * (p - 1) + floor(2 * (p - 1) ** 2), 0)`. As above, if the memory already contains `q` pages, the incremental cost is `Cmem'(p) - Cmem'(q)`. + +### Changes to `MLOAD` and `MSTORE` +Loading a word from memory or storing a word to memory requires instantiating any pages that it touches that do not already exist, with the resulting gas cost as described above. If the word being loaded or stored resides in a single page, the gas cost remains unchanged at 3 gas. If the word being loaded spans two pages, the cost is 6 gas. + +### Changes to other memory-touching opcodes +`CALLDATACOPY`, `CODECOPY`, `EXTCODECOPY`, `CALL`, `CALLCODE`, `DELEGATECALL`, `STATICCALL`, `CREATE`, `MSTORE8` and any other opcodes that read or write memory are modified as follows: + - Any page they touch for reading or writing is instantiated if it is not already. + - Memory expansion gas is charged as described above. + +## Rationale +### Memory expansion gas cost +The new gas cost follows the same curve as the previous one, while ensuring that the new gas cost is always less than or equal to the previous cost. This prevents existing programs that make assumptions about memory allocation gas costs from resulting in errors, without unduly discounting memory below what it costs today. Intuitively, a program that uses up to a page boundary pays for one page less than they would under the old model, while a program that uses one word more than a page boundary pays for one word less than they would under the old model. + +We believe that this incremental reduction will not have a significant impact on the effective gas limit, as it gets proportionally smaller as programs use more RAM. + +### Additional cost for MLOADs and MSTOREs spanning two pages +Loading or storing data spanning two memory pages requires more work from the EVM implementation, which must split the word at the page boundary and update the two (possibly disjoint) pages. Since we cannot guarantee loads and stores in existing EVM programs are page-aligned, we cannot prohibit this behaviour for efficiency. Instead, we propose treating each as two loads or stores for gas accounting purposes. This discourages the use of this functionality, and accounts for the additional execution cost, without prohibiting it outright. + +This will result in additional gas costs for any programs that perform these operations. We believe this to be minimal, and hope to do future analysis to confirm this. + +## Backwards Compatibility +The new function for memory expansion gas cost is designed specifically to avoid backwards compatibility issues by always charging less than or equal to the amount the current EVM would charge. Under some circumstances existing programs will be charged more for MLOADs and MSTOREs that span page boundaries as described above; we believe these changes will affect a minimum of programs and have only a small impact on their gas consumption. + +## Test Cases +TBD + +## Security Considerations +Potential CPU DoS issues arising from additional work done under the new model are alleviated by charging more for non-page-aligned reads and writes. Charges for memory expansion asymptotically approach those currently in force, so this change will not permit programs to allocate substantially more memory than they can today. + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-3337.md b/EIPS/eip-3337.md new file mode 100644 index 00000000000000..6a93ee2bd7281d --- /dev/null +++ b/EIPS/eip-3337.md @@ -0,0 +1,99 @@ +--- +eip: 3337 +title: Frame pointer support for memory load and store operations +author: Nick Johnson (@arachnid) +discussions-to: https://ethereum-magicians.org/t/eips-3336-and-3337-improving-the-evms-memory-model/5482 +status: Draft +type: Standards Track +category: Core +created: 2021-03-06 +requires: 3336 +--- + +## Simple Summary +Introduces four new opcodes for loading data from and storing data to memory offset by a frame pointer. + +## Abstract +This EIP introduces four new opcodes, `MLOADFP`, `MSTOREFP`, `GETFP` and `SETFP` that allow for more efficient memory access offset by a user-controlled quantity called the "frame pointer". This permits compilers to more efficiently offload ephemeral data such as local variables to memory instead of the EVM's evaluation stack, which has a number of benefits, including the effective elimination of restrictions on the number of local variables in a function. + +## Motivation +In most commonly used VMs, ephemeral data such as local variables, function arguments, and return addresses is stored in a region of memory called the stack. In contrast to the EVM's evaluation stack, this area of memory is randomly accessible, and thus can store an arbitrary amount of data, which can be referenced from anywhere they remain in scope. Although this model is possible in the current EVM design, it is made difficult by the linear model of memory (addressed in [EIP-3336](./eip-3336.md)) and by the lack of opcodes for relative memory access commonly found in other architectures. This EIP proposes new opcodes that permit this form of memory use, without imposing undue burden on EVM implementers or on runtime efficiency. + +In the current EVM model, a compiler wishing to use this pattern would have to store the frame pointer - which points to the start or end of the current memory stack frame - in memory, and load it each time they wish to reference it. For example, loading a value from memory offset by the frame pointer would require the following sequence of operations: + +| Opcode | Gas used | +|-----------|----------| +| `PUSHn x` | 3 | +| `PUSH1 0` | 3 | +| `MLOAD` | 3 | +| `ADD` | 3 | +| `MLOAD` | 3 | + +This consumes a total of 15 gas, and takes up at least 7 bytes of bytecode each time it is referenced. In contrast, after this EIP, the equivalent sequence of operations is: + +| Opcode | Gas used | +|-----------|----------| +| `PUSH1 x` | 3 | +| `MLOADFP` | 3 | + +This consumes only 6 gas, and takes at least 3 bytes of bytecode. The effort required from the EVM implementation is equivalent, costing only one extra addition operation over a regular `MLOAD`. The alternative of storing values on the stack, which requires 3 gas and 1 byte of bytecode for a `DUPn` operation, but it is now at most twice as efficient rather than 5 times as efficient, making storing values in memory a viable alternative. + +Likewise, before this EIP a frame-pointer relative store requires the following sequence of operations: +| Opcode | Gas used | +|-----------|----------| +| `PUSHn x` | 3 | +| `PUSH1 0` | 3 | +| `MLOAD` | 3 | +| `ADD` | 3 | +| `MSTORE` | 3 | + +This consumes 15 gas and at least 7 bytes of bytecode. After this EIP, the equivalent sequence of operations is: + +| Opcode | Gas used | +|-----------|----------| +| `PUSHn x` | 3 | +| `MSTOREFP`| 3 | + +Consuming only 6 gas and at least 3 bytes of bytecode, while once again only requiring EVM implementations to do one extra addition operation. The alternative of storing values on the stack requires 6 gas and 2 bytes of bytecode for the sequence `SWAPn POP`, making it no more efficient than memory storage. + +## Specification +### Parameters + +| Constant | Value | +| - | - | +| `FORK_BLOCK` | TBD | + +For blocks where `block.number >= FORK_BLOCK`, the following changes apply. + +### Frame pointer +A new EVM internal state variable called the "frame pointer" is introduced. This is a signed integer that starts at 0. + +### `SETFP` opcode +A new opcode, `SETFP` is introduced with value `0x5c`. This opcode costs `G_low` (3 gas) and takes one argument from the stack. The argument is stored as the new value of the frame pointer. + +### `GETFP` opcode +A new opcode, `GETFP` is introduced with value `0x5d`. This opcode costs `G_low` (3 gas) and takes no arguments. It takes the current value of the frame pointer and pushes it to the stack. + +### `MLOADFP` opcode +A new opcode `MLOADFP` is introduced with value `0x5e`. This opcode acts in all ways identical to `MLOAD`, except that the value of the frame pointer is added to the address before loading data from memory. An attempt to load data from a negative address should be treated identically to an invalid opcode, consuming all gas and reverting the current execution context. + +### `MSTOREFP` opcode +A new opcode `MSTOREFP` is introduced with value `0x5f`. This opcode acts in all ways identical to `MSTORE`, except that the value of the frame pointer is added to the address before storing data to memory. An attempt to store data to a negative address should be treated identically to an invalid opcode, consuming all gas and reverting the current execution context. + +## Rationale +### Cost of new opcodes +The cost of the new opcodes `MLOADFP` and `MSTOREFP` reflects the cost of `MLOAD` and `MSTORE`. They are generally equivalent in cost with the exception of an extra addition operation, which imposes negligible cost. + +The cost of the new opcodes `SETFP` and `GETFP` is based on other common low-cost opcodes such as `PUSH` and `POP`. + +### Absence of `MSTORE8FP` +`MSTORE8FP` opcode was not included because it is expected that it would be used infrequently, and there is a desire to minimise the size of the instruction set and to conserve opcodes for future use. + +## Backwards Compatibility +This EIP exclusively introduces new opcodes, and as a result should not impact any existing programs unless they operate under the assumption that these opcodes are undefined, which we believe will not be the case. + +## Security Considerations +DoS risks are mitigated by correct pricing of opcodes to reflect current execution costs. No other security considerations pertain to this EIP. + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-3338.md b/EIPS/eip-3338.md new file mode 100644 index 00000000000000..0a8d6527673f7b --- /dev/null +++ b/EIPS/eip-3338.md @@ -0,0 +1,54 @@ +--- +eip: 3338 +title: Limit account nonce to 2^52 +author: Micah Zoltu (@MicahZoltu), Alex Beregszaszi (@axic) +discussions-to: https://ethereum-magicians.org/t/eip-2681-limit-account-nonce-to-2-64-1/4324 +status: Review +type: Standards Track +category: Core +created: 2021-03-07 +--- + +## Abstract + +Limit account nonce to be between `0` and `2^52`. + +## Motivation + +Account nonces are currently specified to be arbitrarily long unsigned integers. Dealing with arbitrary length data in the state witnesses is not optimal, therefore this EIP will allow proofs to represent the nonce in a more optimized way. + +Additionally it could prove beneficial to transaction formats, where some improvements are potentially sought by at least three other proposals. + +Lastly, this facilitates a minor optimisation in clients, because the nonce no longer needs to be kept as a 256-bit number. + +## Specification + +If `block.number >= FORK_BLOCK` introduce two new restrictions: + +1. Consider any transaction invalid, where the nonce exceeds `2^52`. +2. The `CREATE` instruction to abort with an exceptional halt, where the account nonce is `2^52`. + +## Rationale + +1. It is unlikely for any nonce to reach or exceed the proposed limit. If one would want to reach that limit via external transactions, it would cost at least `21000 * (2^64-1) = 387_381_625_547_900_583_915_000` gas. + +2. It must be noted that in the past, in the Morden testnet, each new account had a starting nonce of `2^20` in order to differentiate transactions from mainnet transactions. +This mode of replay protection is out of fashion since [EIP-155](./eip-155.md) introduced a more elegant way using chain identifiers. + +3. Most clients already consider the nonce field to be 64-bit, such as go-ethereum. + +4. All integer values <= 2^52 can be encoded in a 64-bit floating point without any loss of precision, making this value easy to work with in languages that only have floating point number support. + +## Backwards Compatibility + +While this is a breaking change, no actual effect should be visible: + +1. There is no account in the state currently which would have a nonce exceeding that value. As of November 2020, the account `0xea674fdde714fd979de3edf0f56aa9716b898ec8` is responsible for the highest account nonce at approximately 29 million. + +## Security Considerations + +None. + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-4.md b/EIPS/eip-4.md index 44966a8cdfd10f..7ee67e529f41a0 100644 --- a/EIPS/eip-4.md +++ b/EIPS/eip-4.md @@ -2,7 +2,7 @@ eip: 4 title: EIP Classification author: Joseph Chow (@ethers) -status: Superseded +status: Final type: Meta created: 2015-11-17 superseded-by: 1 diff --git a/EIPS/eip-5.md b/EIPS/eip-5.md index bb47fbe6d93009..f7c3c47dfbdc99 100644 --- a/EIPS/eip-5.md +++ b/EIPS/eip-5.md @@ -2,7 +2,7 @@ eip: 5 title: Gas Usage for `RETURN` and `CALL*` author: Christian Reitwiessner -status: Superseded +status: Final type: Standards Track category: Core created: 2015-11-22 diff --git a/EIPS/eip-55.md b/EIPS/eip-55.md index 9e45f2bef335c9..325a70f9683ef0 100644 --- a/EIPS/eip-55.md +++ b/EIPS/eip-55.md @@ -2,6 +2,7 @@ eip: 55 title: Mixed-case checksum address encoding author: Vitalik Buterin , Alex Van de Sande +discussions-to: https://github.com/ethereum/eips/issues/55 type: Standards Track category: ERC status: Final @@ -116,37 +117,3 @@ Note that the input to the Keccak256 hash is the lowercase hexadecimal string (i 0xdbF03B407c01E7cD3CBea99509d93f8DDDC8C6FB 0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb ``` - -# Adoption - -| Wallet | displays checksummed addresses | rejects invalid mixed-case | rejects too short | rejects too long | -|--------------------------|--------------------------------|----------------------------|-------------------|------------------| -| Etherwall 2.0.1 | Yes | Yes | Yes | Yes | -| Jaxx 1.2.17 | No | Yes | Yes | Yes | -| MetaMask 3.7.8 | Yes | Yes | Yes | Yes | -| Mist 0.8.10 | Yes | Yes | Yes | Yes | -| MyEtherWallet v3.9.4 | Yes | Yes | Yes | Yes | -| Parity 1.6.6-beta (UI) | Yes | Yes | Yes | Yes | -| Jaxx Liberty 2.0.0 | Yes | Yes | Yes | Yes | -| Coinomi 1.10 | Yes | Yes | Yes | Yes | -| Trust Wallet | Yes | Yes | Yes | Yes | - -### Exchange support for mixed-case address checksums, as of 2017-05-27: - -| Exchange | displays checksummed deposit addresses | rejects invalid mixed-case | rejects too short | rejects too long | -|--------------|----------------------------------------|----------------------------|-------------------|------------------| -| Bitfinex | No | Yes | Yes | Yes | -| Coinbase | Yes | No | Yes | Yes | -| GDAX | Yes | Yes | Yes | Yes | -| Kraken | No | No | Yes | Yes | -| Poloniex | No | No | Yes | Yes | -| Shapeshift | No | No | Yes | Yes | - -# References - -1. EIP 55 issue and discussion https://github.com/ethereum/eips/issues/55 -2. Python example by @Recmo https://github.com/ethereum/eips/issues/55#issuecomment-261521584 -3. Python implementation in [`ethereum-utils`](https://github.com/pipermerriam/ethereum-utils#to_checksum_addressvalue---text) -4. Ethereumjs-util implementation https://github.com/ethereumjs/ethereumjs-util/blob/75f529458bc7dc84f85fd0446d0fac92d991c262/index.js#L452-L466 -5. Swift implementation in [`EthereumKit`](https://github.com/yuzushioh/EthereumKit/blob/master/EthereumKit/Helper/EIP55.swift) -6. Kotlin implementation in [`KEthereum`](https://github.com/walleth/kethereum/tree/master/erc55) diff --git a/EIPS/eip-606.md b/EIPS/eip-606.md index 74920a856e019c..a43eaed1e6caaf 100644 --- a/EIPS/eip-606.md +++ b/EIPS/eip-606.md @@ -20,9 +20,9 @@ This specifies the changes included in the hard fork named Homestead. - Block >= 494,000 on Morden - Block >= 0 on future testnets - Included EIPs: - - [EIP 2](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2.md) (Homestead Hard-fork Changes) - - [EIP 7](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-7.md) (DELEGATECALL) - - [EIP 8](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-8.md) (Networking layer: devp2p Forward Compatibility Requirements for Homestead) + - [EIP-2](./eip-2.md) (Homestead Hard-fork Changes) + - [EIP-7](./eip-7.md) (DELEGATECALL) + - [EIP-8](./eip-8.md) (Networking layer: devp2p Forward Compatibility Requirements for Homestead) ## References diff --git a/EIPS/eip-607.md b/EIPS/eip-607.md index fe11ea7aac832f..668a85771bbb2c 100644 --- a/EIPS/eip-607.md +++ b/EIPS/eip-607.md @@ -20,10 +20,10 @@ This specifies the changes included in the hard fork named Spurious Dragon. - Block >= 2,675,000 on Mainnet - Block >= 1,885,000 on Morden - Included EIPs: - - [EIP 155](https://eips.ethereum.org/EIPS/eip-155) (Simple replay attack protection) - - [EIP 160](https://eips.ethereum.org/EIPS/eip-160) (EXP cost increase) - - [EIP 161](https://eips.ethereum.org/EIPS/eip-161) (State trie clearing) - - [EIP 170](https://eips.ethereum.org/EIPS/eip-170) (Contract code size limit) + - [EIP-155](./eip-155.md) (Simple replay attack protection) + - [EIP-160](./eip-160.md) (EXP cost increase) + - [EIP-161](./eip-161.md) (State trie clearing) + - [EIP-170](./eip-170.md) (Contract code size limit) ## References diff --git a/EIPS/eip-608.md b/EIPS/eip-608.md index 2b300b4fe6f72d..4d91f549538d68 100644 --- a/EIPS/eip-608.md +++ b/EIPS/eip-608.md @@ -19,7 +19,7 @@ This specifies the changes included in the hard fork named Tangerine Whistle (EI - Activation: - Block >= 2,463,000 on Mainnet - Included EIPs: - - [EIP 150](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-150.md) (Gas cost changes for IO-heavy operations) + - [EIP-150](./eip-150.md) (Gas cost changes for IO-heavy operations) ## References diff --git a/EIPS/eip-609.md b/EIPS/eip-609.md index daa5c6099e045c..5d942c311a58a5 100644 --- a/EIPS/eip-609.md +++ b/EIPS/eip-609.md @@ -20,15 +20,15 @@ This specifies the changes included in the hard fork named Byzantium. - Block >= 4,370,000 on Mainnet - Block >= 1,700,000 on Ropsten testnet - Included EIPs: - - [EIP 100](https://eips.ethereum.org/EIPS/eip-100) (Change difficulty adjustment to target mean block time including uncles) - - [EIP 140](https://eips.ethereum.org/EIPS/eip-140) (REVERT instruction in the Ethereum Virtual Machine) - - [EIP 196](https://eips.ethereum.org/EIPS/eip-196) (Precompiled contracts for addition and scalar multiplication on the elliptic curve alt_bn128) - - [EIP 197](https://eips.ethereum.org/EIPS/eip-197) (Precompiled contracts for optimal ate pairing check on the elliptic curve alt_bn128) - - [EIP 198](https://eips.ethereum.org/EIPS/eip-198) (Precompiled contract for bigint modular exponentiation) - - [EIP 211](https://eips.ethereum.org/EIPS/eip-211) (New opcodes: RETURNDATASIZE and RETURNDATACOPY) - - [EIP 214](https://eips.ethereum.org/EIPS/eip-214) (New opcode STATICCALL) - - [EIP 649](https://eips.ethereum.org/EIPS/eip-649) (Difficulty Bomb Delay and Block Reward Reduction) - - [EIP 658](https://eips.ethereum.org/EIPS/eip-658) (Embedding transaction status code in receipts) + - [EIP-100](./eip-100.md) (Change difficulty adjustment to target mean block time including uncles) + - [EIP-140](./eip-140.md) (REVERT instruction in the Ethereum Virtual Machine) + - [EIP-196](./eip-196.md) (Precompiled contracts for addition and scalar multiplication on the elliptic curve alt_bn128) + - [EIP-197](./eip-197.md) (Precompiled contracts for optimal ate pairing check on the elliptic curve alt_bn128) + - [EIP-198](./eip-198.md) (Precompiled contract for bigint modular exponentiation) + - [EIP-211](./eip-211.md) (New opcodes: RETURNDATASIZE and RETURNDATACOPY) + - [EIP-214](./eip-214.md) (New opcode STATICCALL) + - [EIP-649](./eip-649.md) (Difficulty Bomb Delay and Block Reward Reduction) + - [EIP-658](./eip-658.md) (Embedding transaction status code in receipts) ## References diff --git a/EIPS/eip-615.md b/EIPS/eip-615.md index da50d218eeb5e2..71d4231448c65b 100644 --- a/EIPS/eip-615.md +++ b/EIPS/eip-615.md @@ -4,7 +4,7 @@ title: Subroutines and Static Jumps for the EVM status: Draft type: Standards Track category: Core -author: Greg Colvin , Brooklyn Zelenka (@expede), Paweł Bylica (@chfast), Christian Reitwiessner(@chriseth) +author: Greg Colvin , Brooklyn Zelenka (@expede), Paweł Bylica (@chfast), Christian Reitwiessner (@chriseth) discussions-to: https://ethereum-magicians.org/t/eip-615-subroutines-and-static-jumps-for-the-evm-last-call/3472 created: 2016-12-10 --- @@ -44,7 +44,7 @@ The result is that all of the following validations and optimizations can be don ### Dependencies -> **[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. +> **[EIP-1702](./eip-1702.md). 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 @@ -316,7 +316,7 @@ These changes would need to be implemented in phases at decent intervals: If desired, the period of deprecation can be extended indefinitely by continuing to accept code not versioned as new—but without validation. That is, by delaying or canceling phase 2. -Regardless, we will need a versioning scheme like [EIP-1702](https://github.com/ethereum/EIPs/pull/1702) to allow current code and EIP-615 code to coexist on the same blockchain. +Regardless, we will need a versioning scheme like [EIP-1702](./eip-1702.md) to allow current code and EIP-615 code to coexist on the same blockchain. ## Rationale diff --git a/EIPS/eip-616.md b/EIPS/eip-616.md index 43c4e19f1e2606..91ac3073019bd1 100644 --- a/EIPS/eip-616.md +++ b/EIPS/eip-616.md @@ -103,7 +103,7 @@ Extended operations other than XSHUFFLE and XCAST are only valid on vectors of t ### Subroutines -If [EIP 187](https://github.com/ethereum/EIPs/pull/187) is accepted a type-safe syntax for declaring subroutines taking vector arguments will be needed. +If [EIP-187](https://github.com/ethereum/EIPs/pull/187) is accepted a type-safe syntax for declaring subroutines taking vector arguments will be needed. * `BEGINSUBX n_args, arg_types... n_results, result_types...` marks the **single** entry to a subroutine. `n_args` items are taken off of the stack at entry to, and `n_results` items are placed on the stack at return from the subroutine. `n_args` and `n_results` are given as one immediate byte each. The `arg_types` and `result_types` are given in the same encoding as second byte of the SIMD opcodes, and must match the values on the stack. The bytecode for a subroutine ends at the next `BEGINSUB`, `BEGINSUBX` or `BEGINDATA` instruction or at the end of the bytecode. diff --git a/EIPS/eip-634.md b/EIPS/eip-634.md index e785b8310a39c3..6a03009113b0ff 100644 --- a/EIPS/eip-634.md +++ b/EIPS/eip-634.md @@ -26,6 +26,7 @@ associate arbitrary key-value text. ## Specification ### Resolver Profile + A new resolver interface is defined, consisting of the following method: function text(bytes32 node, string key) constant returns (string text); @@ -36,36 +37,80 @@ The `text` data may be any arbitrary UTF-8 string. If the key is not present, th must be returned. -### Initial Recommended Keys +### Global Keys -Keys must be made up of lowercase letters, numbers and the hyphen (-). Vendor specific -services must be prefixed with `vnd.`. +Global Keys must be made up of lowercase letters, numbers and +the hyphen (-). -- **email** - an e-mail address -- **url** - a URL - **avatar** - a URL to an image used as an avatar or logo - **description** - A description of the name -- **notice** - A notice regarding this name; +- **display** - a canonical display name for the ENS name; this MUST match the ENS name when its case is folded, and clients should ignore this value if it does not (e.g. `"ricmoo.eth"` could set this to `"RicMoo.eth"`) +- **email** - an e-mail address - **keywords** - A list of comma-separated keywords, ordered by most significant first; clients that interpresent this field may choose a threshold beyond which to ignore +- **mail** - A physical mailing address +- **notice** - A notice regarding this name +- **location** - A generic location (e.g. `"Toronto, Canada"`) +- **phone** - A phone number as an [E.164](https://en.wikipedia.org/wiki/E.164) string +- **url** - a website URL + +### Service Keys + +Service Keys must be made up of a *reverse dot notation* for +a namespace which the service owns, for example, DNS names +(e.g. `.com`, `.io`, etc) or ENS name (i.e. `.eth`). Service +Keys must contain at least one dot. + +This allows new services to start using their own keys without +worrying about colliding with existing services and also means +new services do not need to update this document. + +The following services are common, which is why recommendations are +provided here, but ideally a service would declare its own key. + +- **com.github** - a GitHub username +- **com.peepeth** - a Peepeth username +- **com.linkedin** - a LinkedIn username +- **com.twitter** - a Twitter username +- **io.keybase** - a Keybase username +- **org.telegram** - a Telegram username -- **vnd.github** - a GitHub username -- **vnd.peepeth** - a peepeth username -- **vnd.twitter** - a twitter username +This technique also allows for a service owner to specify a hierarchy +for their keys, such as: +- **com.example.users** +- **com.example.groups** +- **com.example.groups.public** +- **com.example.groups.private** + + +### Legacy Keys + +The following keys were specified in earlier versions of this EIP, +which is still in draft. + +Their use is not likely very wide, but applications attempting +maximal compatibility may wish to query these keys as a fallback +if the above replacement keys fail. + +- **vnd.github** - a GitHub username (renamed to `com.github`) +- **vnd.peepeth** - a peepeth username (renamced to `com.peepeth`) +- **vnd.twitter** - a twitter username (renamed to `com.twitter`) -Usernames SHOULD not be prefixed with the @ symbol. ## Rationale ### Application-specific vs general-purpose record types + Rather than define a large number of specific record types (each for generally human-readable data) such as `url` and `email`, we follow an adapted model of DNS's `TXT` records, which allow for a general keys and values, allowing future extension without adjusting the resolver, while allowing applications to use custom keys for their own purposes. + ## Backwards Compatibility Not applicable. + ## Test Cases TBD diff --git a/EIPS/eip-681.md b/EIPS/eip-681.md index 9d4061d39665d4..4030a77dfac78c 100644 --- a/EIPS/eip-681.md +++ b/EIPS/eip-681.md @@ -1,16 +1,17 @@ --- eip: 681 title: URL Format for Transaction Requests -author: Daniel A. Nagy +author: Daniel A. Nagy (@nagydani) type: Standards Track category: ERC -status: Draft +status: Review +discussions-to: https://ethereum-magicians.org/t/erc-681-representing-various-transactions-as-urls created: 2017-08-01 -requires: 20, 137, 831 +requires: 20, 137 --- ## Simple Summary -A standard way of representing various transactions, especially payment requests in Ethers and ERC #20 tokens as URLs. +A standard way of representing various transactions, especially payment requests in ether and [ERC-20](./eip-20.md) tokens as URLs. ## Abstract URLs embedded in QR-codes, hyperlinks in web-pages, emails or chat messages provide for robust cross-application signaling between very loosely coupled applications. A standardized URL format for payment requests allows for instant invocation of the user's preferred wallet application (even if it is a webapp or a swarm đapp), with the correct parameterization of the payment transaction only to be confirmed by the (authenticated) user. @@ -18,39 +19,34 @@ URLs embedded in QR-codes, hyperlinks in web-pages, emails or chat messages prov ## Motivation The convenience of representing payment requests by standard URLs has been a major factor in the wide adoption of Bitcoin. Bringing a similarly convenient mechanism to Ethereum would speed up its acceptance as a payment platform among end-users. In particular, URLs embedded in broadcast Intents are the preferred way of launching applications on the Android operating system and work across practically all applications. Desktop web browsers have a standardized way of defining protocol handlers for URLs with specific protocol specifications. Other desktop applications typically launch the web browser upon encountering a URL. Thus, payment request URLs could be delivered through a very broad, ever growing selection of channels. -This specification supersedes ERC #67, which is a URL format for representing arbitrary transactions in a low-level fashion. This ERC focuses specifically on the important special case of payment requests, while allowing for other, ABI-specified transactions. +This specification supersedes the defunct ERC-67, which is a URL format for representing arbitrary transactions in a low-level fashion. This ERC focuses specifically on the important special case of payment requests, while allowing for other, ABI-specified transactions. ## Specification ### Syntax Payment request URLs contain "ethereum" in their schema (protocol) part and are constructed as follows: - request = erc831_part target_address [ "@" chain_id ] [ "/" function_name ] [ "?" parameters ] - erc831_part = schema and optional prefix as defined in #831 - typically "ethereum" ":" [ "pay-" ] in this case + request = schema_prefix target_address [ "@" chain_id ] [ "/" function_name ] [ "?" parameters ] + schema_prefix = "ethereum" ":" [ "pay-" ] target_address = ethereum_address chain_id = 1*DIGIT function_name = STRING - ethereum_address = ( "0x" 40*40HEXDIG ) / ENS_NAME + ethereum_address = ( "0x" 40*HEXDIG ) / ENS_NAME parameters = parameter *( "&" parameter ) parameter = key "=" value key = "value" / "gas" / "gasLimit" / "gasPrice" / TYPE value = number / ethereum_address / STRING - number = [ "-" / "+" ] *DIGIT [ "." 1*DIGIT ] [ ( "e" / "E" ) [ 1*DIGIT ] [ "+" UNIT ] + number = [ "-" / "+" ] *DIGIT [ "." 1*DIGIT ] [ ( "e" / "E" ) [ 1*DIGIT ] Where `TYPE` is a standard ABI type name, as defined in [Ethereum Contract ABI specification](https://solidity.readthedocs.io/en/develop/abi-spec.html). `STRING` is a URL-encoded unicode string of arbitrary length, where delimiters and the percentage symbol (`%`) are mandatorily hex-encoded with a `%` prefix. -`UNIT` is a URL-encoded unicode string. If `UNIT` is ETH, it always means a multiplier of 1018. If it is something -else AND the addressed contract has a `symbol` field exactly matching this string AND the contract has a `decimals` field, then -10 to that power is used as a multiplier. Otherwise, the payment request is deemed invalid. Applications that have no access to -the blockchain should refuse accepting requests with a non-empty `UNIT`, if it is not ETH. - -Note that a `number` can be expressed in *scientific notation*, with a multiplier of a power of 10. The use of this notation is strongly encouraged when expressing monetary value in Ethers or ERC #20 tokens in atomic units (e. g. Wei, in case of Ether). +Note that a `number` can be expressed in *scientific notation*, with a multiplier of a power of 10. Only integer numbers are allowed, so the exponent MUST be greater or equal to the number of decimals after the point. If *key* in the parameter list is `value`, `gasLimit`, `gasPrice` or `gas` then *value* MUST be a `number`. Otherwise, it must correspond to the `TYPE` string used as *key*. -For the syntax of ENS_NAME, please consult ERC #137 defining Ethereum Name Service. +For the syntax of ENS_NAME, please consult [ERC-137](./eip-137.md) defining Ethereum Name Service. ### Semantics @@ -58,27 +54,39 @@ For the syntax of ENS_NAME, please consult ERC #137 defining Ethereum Name Servi `chain_id` is optional and contains the decimal chain ID, such that transactions on various test- and private networks can be requested. If no `chain_id` is present, the client's current network setting remains effective. -If `function_name` is missing, then the URL is requesting payment in the native token of the blockchain, which is Ether in our case. The amount is specified in `value` parameter, in the atomic unit (i.e. Wei). The use of scientific notation is strongly encouraged. For example, requesting 2.014 ETH to address `0xfb6916095ca1df60bb79Ce92ce3ea74c37c5d359` would look as follows: +If `function_name` is missing, then the URL is requesting payment in the native token of the blockchain, which is ether in our case. The amount is specified in `value` parameter, in the atomic unit (i.e. wei). The use of scientific notation is strongly encouraged. For example, requesting 2.014 ETH to address `0xfb6916095ca1df60bb79Ce92ce3ea74c37c5d359` would look as follows: [ethereum:0xfb6916095ca1df60bb79Ce92ce3ea74c37c5d359?value=2.014e18](ethereum:0xfb6916095ca1df60bb79Ce92ce3ea74c37c5d359?value=2.014e18) -Requesting payments in ERC #20 tokens involves a request to call the `transfer` function of the token contract with an `address` and a `uint256` typed parameter, containing the *beneficiary address* and the *amount in atomic units*, respectively. For example, +Requesting payments in [ERC-20](./eip-20.md) tokens involves a request to call the `transfer` function of the token contract with an `address` and a `uint256` typed parameter, containing the *beneficiary address* and the *amount in atomic units*, respectively. For example, requesting a Unicorn to address `0x8e23ee67d1332ad560396262c48ffbb01f93d052` looks as follows: [ethereum:0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7/transfer?address=0x8e23ee67d1332ad560396262c48ffbb01f93d052&uint256=1](ethereum:0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7/transfer?address=0x8e23ee67d1332ad560396262c48ffbb01f93d052&uint256=1) -If using ENS names instead of hexadecimal addresses, the resolution is up to the payer, at any time between receiving the URL and sending the transaction. Hexadecimal addresses always take precedence over ENS names, i. e. even if there exists a matching ENS name consisting of 40 hexadecimal digits, it should never be resolved. Instead, the hexadecimal address should be used directly. - -If the payer client has access to the blockchain, the interface should display the amount in the units as specified in the token contract. Otherwise, it should be displayed as expressed in the URL. +If using ENS names instead of hexadecimal addresses, the resolution is up to the payer, at any time between receiving the URL and sending the transaction. Hexadecimal addresses always take precedence over ENS names, i. e. even if there exists a matching ENS name consisting of `0x` followed by 40 hexadecimal digits, it should never be resolved. Instead, the hexadecimal address should be used directly. Note that the indicated amount is only a suggestion (as are all the supplied arguments) which the user is free to change. With no indicated amount, the user should be prompted to enter the amount to be paid. Similarly `gasLimit` and `gasPrice` are suggested user-editable values for *gas limit* and *gas price*, respectively, for the requested transaction. It is acceptable to abbreviate `gasLimit` as `gas`, the two are treated synonymously. ## Rationale -The proposed format is chosen to resemble `bitcoin:` URLs as closely as possible, as both users and application programmers are already familiar with that format. In particular, this motivated the omission of the unit, which is often used in Ethereum ecosystem. Handling different orders of magnitude is delegated to the application, just like in the case of `bitcoin:`, but lacking access to the block chain, the application can take a hint from the exponent in the URL. Additional parameters may be added, if popular use cases requiring them emerge in practice. +The proposed format is chosen to resemble `bitcoin:` URLs as closely as possible, as both users and application programmers are already familiar with that format. In particular, this motivated the omission of the unit, which is often used in Ethereum ecosystem. Handling different orders of magnitude is facilitated by the exponent so that amount values can be expressed in their nominal units, just like in the case of `bitcoin:`. The use of scientific notation is strongly encouraged when expressing monetary value in ether or [ERC-20](./eip-20.md) tokens. For better human readability, the exponent should be the decimal value of the nominal unit: 18 for ether or the value returned by `decimals()` of the token contract for [ERC-20](./eip-20.md) tokens. Additional parameters may be added, if popular use cases requiring them emerge in practice. + +The `0x` prefix before ethereum addresses specified as hexadecimal numbers is following established practice and also unambiguously distinguishes hexadecimal addresses from ENS names consisting of 40 alphanumeric characters. + +Future upgrades that are partially or fully incompatible with this proposal must use a prefix other than `pay-` that is separated by a dash (`-`) character from whatever follows it. + +## Backwards Compatibility + +In the fairly common case of only indicating the recipient address in a request for payment in ether, this specification is compatible with the superseded ERC-67. + +## Security Considerations + +Since irreversible transactions can be initiated with parameters from such URLs, the integrity and authenticity of these URLs are of great importance. +In particular, changing either the recipient address or the amount transferred can be a profitable attack. Users should only use URLs received from authenticated sources with adequate integrity protection. + +To prevent malicious redirection of payments using ENS, hexadecimal interpretation of Ethereum addresses must have precedence over ENS lookups. Client software may alert the user if an ENS address is visually similar to a hexadecimal address or even outright reject such addresses as likely phishing attacks. -## Compatibility and Versioning -Future upgrades that are partially or fully incompatible with this proposal must use a prefix other than `pay-` that is separated by a dash (`-`) character from whatever follows it, as specified by ERC #831. +In order to make sure that the amount transacted is the same as the amount intended, the amount communicated to the human user should be easily verifiable by inspection, including the order of magnitude. In case of [ERC-20](./eip-20.md) token payments, if the payer client has access to the blockchain or some other trusted source of information about the token contract, the interface should display the amount in the units specified in the token contract. Otherwise, it should be displayed as expressed in the URL, possibly alerting the user to the uncertainty of the nominal unit. To facilitate human inspection of the amount, the use of scientific notation with an exponent corresponding to the nominal unit of the transacted token (e.g. 18 in case of ether) is advisable. ## Copyright -Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0) diff --git a/EIPS/eip-689.md b/EIPS/eip-689.md index 5b6935e93c238a..a5859cd02e0f56 100644 --- a/EIPS/eip-689.md +++ b/EIPS/eip-689.md @@ -20,7 +20,7 @@ Some test cases in the consensus test suite try to deploy a contract at an addre This EIP has no practical relevance to the main net history, but simplifies testing and reasoning. -This EIP has no effects after Constantinople fork because [EIP-86](https://github.com/ethereum/EIPs/pull/208) contains the changes proposed in this EIP. Even before the Constantinople fork, this EIP has no practical relevance because the change is visible only in case of a hash collision of keccak256. +This EIP has no effects after Constantinople fork because [EIP-86](./eip-86.md) contains the changes proposed in this EIP. Even before the Constantinople fork, this EIP has no practical relevance because the change is visible only in case of a hash collision of keccak256. Regarding testing, this EIP relieves clients from supporting reversion of code overwriting. diff --git a/EIPS/eip-695.md b/EIPS/eip-695.md index 937126b865eb56..16431b6288bde5 100644 --- a/EIPS/eip-695.md +++ b/EIPS/eip-695.md @@ -19,7 +19,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 by [EIP-155](https://eips.ethereum.org/EIPS/eip-155). +introduced by [EIP-155](./eip-155.md). ## Motivation @@ -33,7 +33,7 @@ the RPC. ### `eth_chainId` Returns the currently configured chain ID, a value used in replay-protected transaction -signing as introduced by [EIP-155](https://eips.ethereum.org/EIPS/eip-155). +signing as introduced by [EIP-155](./eip-155.md). 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 @@ -54,7 +54,7 @@ None. #### Example ```js -curl -X POST --data '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}' +curl -X POST --data '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":83}' // Result { @@ -80,7 +80,7 @@ Not relevant. 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. +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](./eip-155.md), and consumers will rely on it to identify the chain they are communicating with. ## Implementation diff --git a/EIPS/eip-7.md b/EIPS/eip-7.md index 31baa64384ff9f..b75de110b65b33 100644 --- a/EIPS/eip-7.md +++ b/EIPS/eip-7.md @@ -9,7 +9,7 @@ created: 2015-11-15 --- ### Hard Fork -[Homestead](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-606.md) +[Homestead](./eip-606.md) ### Parameters - Activation: diff --git a/EIPS/eip-712.md b/EIPS/eip-712.md index 282c8a39ff1aa2..975852e4d1af3c 100644 --- a/EIPS/eip-712.md +++ b/EIPS/eip-712.md @@ -1,7 +1,7 @@ --- eip: 712 title: Ethereum typed structured data hashing and signing -author: Remco Bloemen , Leonid Logvinov , Jacob Evans +author: Remco Bloemen (@Recmo), Leonid Logvinov (@LogvinovLeon), Jacob Evans (@dekz) discussions-to: https://ethereum-magicians.org/t/eip-712-eth-signtypeddata-as-a-standard-for-machine-verifiable-and-human-readable-typed-data-signing/397 status: Draft type: Standards Track @@ -95,9 +95,9 @@ The set of signable messages is extended from transactions and bytestrings `𝕋 This encoding is deterministic because the individual components are. The encoding is injective because the three cases always differ in first byte. (`RLP_encode(transaction)` does not start with `\x19`.) -The encoding is compliant with [EIP-191][eip191]. The 'version byte' is fixed to `0x01`, the 'version specific data' is the 32-byte domain separator `domainSeparator` and the 'data to sign' is the 32-byte `hashStruct(message)`. +The encoding is compliant with [EIP-191][EIP-191]. The 'version byte' is fixed to `0x01`, the 'version specific data' is the 32-byte domain separator `domainSeparator` and the 'data to sign' is the 32-byte `hashStruct(message)`. -[eip191]: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-191.md +[EIP-191]: ./eip-191.md ### Definition of typed structured data `𝕊` @@ -160,13 +160,15 @@ where the type of `eip712Domain` is a struct named `EIP712Domain` with one or mo * `string name` the user readable name of signing domain, i.e. the name of the DApp or the protocol. * `string version` the current major version of the signing domain. Signatures from different versions are not compatible. -* `uint256 chainId` the [EIP-155][eip155] chain id. The user-agent *should* refuse signing if it does not match the currently active chain. +* `uint256 chainId` the [EIP-155][EIP-155] chain id. The user-agent *should* refuse signing if it does not match the currently active chain. * `address verifyingContract` the address of the contract that will verify the signature. The user-agent *may* do contract specific phishing prevention. * `bytes32 salt` an disambiguating salt for the protocol. This can be used as a domain separator of last resort. -[eip155]: https://eips.ethereum.org/EIPS/eip-155 +[EIP-155]: ./eip-155.md -Future extensions to this standard can add new fields with new user-agent behaviour constraints. User-agents are free to use the provided information to inform/warn users or refuse signing. +Future extensions to this standard can add new fields with new user-agent behaviour constraints. User-agents are free to use the provided information to inform/warn users or refuse signing. Dapp implementers should not add private fields, new fields should be proposed through the EIP process. + +The `EIP712Domain` fields should be the order as above, skipping any absent fields. Future field additions must be in alphabetical order and come after the above fields. User-agents should accept fields in any order as specified by the `EIPT712Domain` type. ### Specification of the `eth_signTypedData` JSON RPC @@ -226,7 +228,7 @@ Typed data is a JSON object containing type information, domain separator parame `DATA`: Signature. As in `eth_sign` it is a hex encoded 129 byte array starting with `0x`. It encodes the `r`, `s` and `v` parameters from appendix F of the [yellow paper][yellow] in big-endian format. Bytes 0...64 contain the `r` parameter, bytes 64...128 the `s` parameter and the last byte the `v` parameter. Note that the `v` parameter includes the chain id as specified in [EIP-155][eip-155]. [yellow]: https://ethereum.github.io/yellowpaper/paper.pdf -[eip-155]: https://eips.ethereum.org/EIPS/eip-155 +[eip-155]: ./eip-155.md ##### Example @@ -388,9 +390,9 @@ Similarly, a straightforward implementation is sub-optimal for directed acyclic Since different domains have different needs, an extensible scheme is used where the DApp specifies a `EIP712Domain` struct type and an instance `eip712Domain` which it passes to the user-agent. The user-agent can then apply different verification measures depending on the fields that are there. -A field `string eip719dsl` can be added and be rejected if the value does not match the hash of the [EIP-719][eip719] DSL interface string. +A field `string eip719dsl` can be added and be rejected if the value does not match the hash of the [EIP-719][EIP-719] DSL interface string. -[eip719]: https://github.com/ethereum/EIPs/issues/719 +[EIP-719]: https://github.com/ethereum/EIPs/issues/719 ## Backwards Compatibility diff --git a/EIPS/eip-721.md b/EIPS/eip-721.md index ae2ef6633d79df..b89e9ea096b85a 100644 --- a/EIPS/eip-721.md +++ b/EIPS/eip-721.md @@ -391,12 +391,12 @@ XXXXERC721, by William Entriken -- a scalable example implementation **Standards** -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://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. [ERC-20](./eip-20.md) Token Standard. +1. [ERC-165](./eip-165.md) Standard Interface Detection. +1. [ERC-173](./eip-173.md) Owned Standard. +1. [ERC-223](https://github.com/ethereum/EIPs/issues/223) Token Standard. +1. [ERC-677](https://github.com/ethereum/EIPs/issues/677) `transferAndCall` Token Standard. +1. [ERC-827](https://github.com/ethereum/EIPs/issues/827) Token Standard. 1. Ethereum Name Service (ENS). https://ens.domains 1. Instagram -- What's the Image Resolution? https://help.instagram.com/1631821640426723 1. JSON Schema. https://json-schema.org/ diff --git a/EIPS/eip-725.md b/EIPS/eip-725.md index 8688e9cc86975f..8755537fd6cd58 100644 --- a/EIPS/eip-725.md +++ b/EIPS/eip-725.md @@ -1,55 +1,90 @@ --- eip: 725 -title: Proxy Account +title: ERC-725 Smart Contract Based Account author: Fabian Vogelsteller (@frozeman), Tyler Yasaka (@tyleryasaka) discussions-to: https://github.com/ethereum/EIPs/issues/725 status: Draft type: Standards Track category: ERC +requires: 165, 173 created: 2017-10-02 --- + ## Simple Summary -A standard interface for a simple proxy account. +A standard interface for a smart contract based account with attachable key value store. ## Abstract -The following describes standard functions for a unique identifiable proxy account to be used by humans, groups, organisations, objects and machines. The proxy has 2 abilities: (1) it can execute arbitrary contract calls, and (2) it can hold arbitrary data through a generic key/value store. One of these keys should hold the owner of the contract. The owner may be an address or a key manager contract for more complex management logic. Most importantly, this contract should be the reference point for a long-lasting identifiable profiles. +The following describes standard functions for a unique smart contract based account that can be used by humans, +groups, organisations, objects and machines. + +The standard is divided into two sub standards: + +`ERC725X`: +Can execute arbitrary smart contracts using and deploy other smart contracts. + +`ERC725Y`: +Can hold arbitrary data through a generic key/value store. ## Motivation -Standardizing a minimal interface for an proxy account allows third parties to interact with various proxy accounts contracts in a consistent manner. -the benefit is a persistent account that is independent from single keys and can attach an arbitrary amount of information to verifiy, or enhance the accounts purpose. +Standardizing a minimal interface for a smart contract based account allows any interface to operate through these account types. +Smart contact based accounts following this standard have the following advantages: + +- can hold any asset (native token, e.g. ERC20 like tokens) +- can execute any smart contract and deploy smart contracts +- have upgradeable security (through owner change, e.g. to a gnosis safe) +- are basic enough to work for for a long time +- are extensible though additional standardisation of the key/value data. +- can function as an owner/controller or proxy of other smart contracts + ## Specification +### ERC725X -### Methods +ERC165 identifier: `0x44c028fe` -#### owner +#### execute -Returns the current owner +Executes a call on any other smart contracts, transfers the blockchains native token, or deploys a new smart contract. +MUST only be called by the current owner of the contract. ```js -address public owner; +function execute(uint256 operationType, address to, uint256 value, bytes data) ``` -#### changeOwner +The `operationType` can execute the following operations: +- `0` for `call` +- `1` for `delegatecall` +- `2` for `create2` +- `3` for `create` + +Others may be added in the future. + +**Triggers Event:** [ContractCreated](#contractcreated) if a contract was created + +### Events + +#### ContractCreated -Changes the current owner. MUST only be called by the current owner of the contract. +MUST be triggered when `execute` creates a new contract using the `_operationType` `1`. ```js -function changeOwner(address _owner); +event ContractCreated(address indexed contractAddress) ``` -**Triggers Event:** [OwnerChanged](#ownerchanged) +### ERC725Y + +ERC165 identifier: `0x2bd57b73` #### getData Returns the data at the specified key. ```js -function getData(bytes32 _key) external view returns (bytes _value); +function getData(bytes32 key) external view returns(bytes value) ``` #### setData @@ -59,112 +94,109 @@ Sets the data at a specific key. MUST only be called by the current owner of the **Triggers Event:** [DataChanged](#datachanged) ```js -function setData(bytes32 _key, bytes _value) external; -``` - -#### execute - -Executes an action on other contracts or a transfer of the blockchains native cryptocurrency. MUST only be called by the current owner of the contract. - -```js -function execute(uint256 _operationType, address _to, uint256 _value, bytes _data) external; +function setData(bytes32 _key, bytes memory _value) external ``` -The `operationType` should represent the assembly operation as follows: -- `0` for `call` -- `1` for `create` - -Others may be added in the future. Inspired by [ERC1077](https://eips.ethereum.org/EIPS/eip-1077) and [Gnosis](https://github.com/gnosis/safe-contracts/blob/master/contracts/Enum.sol#L7) - ### Events - #### DataChanged MUST be triggered when `setData` was successfully called. ```js -event DataChanged(bytes32 indexed key, bytes value); -``` - -#### ContractCreated - -MUST be triggered when `execute` creates a new contract using the `_operationType` `1`. - -```js -event ContractCreated(address indexed contractAddress); -``` - -#### OwnerChanged - -MUST be triggered when `changeOwner` was successfully called. - -```js -event OwnerChanged(address indexed ownerAddress); +event DataChanged(bytes32 indexed key, bytes value) ``` ### Ownership -This contract is controlled by the owner. The owner can be a smart contract or an address, or itself. +This contract is controlled by an owner. The owner can be a smart contract or an external account. +This standard requires [ERC173](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-173.md) and should implement the functions: + +- `owner() view` +- `transferOwnership(address newOwner)` +- and the Event `event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)` ### Data keys Data keys, should be the keccak256 hash of a type name. -e.g. `myNewKeyType` is `0xa94996022594f93c34a730df0ae89d1ecd69dff98c17d0387e69ce58346323a4` +e.g. `keccak256('ERCXXXMyNewKeyType')` is `0x6935a24ea384927f250ee0b954ed498cd9203fc5d2bf95c735e52e6ca675e047` -#### Multiple keys of the same type +The [ERC725JSONSchema standard](https://github.com/lukso-network/LIPs/blob/master/LSPs/LSP-2-ERC725YJSONSchema.md) defines how keys should be named and generated. +This JSON schema can be used to auto decode ERC725Y values from smart contracts for application and smart contract interactions. -Multiple keys for the same key type must add a `keyTypeName-1` at the end of the key type. +#### Default key values -This would looks as follows for `myNewKeyType`: -version 0 `myNewKeyType`: `0xa94996022594f93c34a730df0ae89d1ecd69dff98c17d0387e69ce58346323a4` -version 1 `myNewKeyType-1`: `0xb6dace1ed14874742c4d1b8cd9b270305176f769e0ae22118a02c2db4e620f29` -version 2 `myNewKeyType-2`: `0x6cc96a01de588f4550e8c3a821aed065ae7897f8dfb61836c78c0389e499d9ed` -... +ERC725 key standards need to be defined within new standards, we suggest the following defaults: + +| Name | Description | Key | value | +| --- | --- | --- | --- | +| SupportedStandards:XYZ | Allows to determine standards supported by this contract | `0xeafec4d89fa9619884b6b89135626455000000000000000000000000xxxxxxxx`, where `xxxxxxxx` is the 4 bytes identifier of the standard supported | Value can be defined by the standard, by default it should be the 4 bytes identifier e.g. `0x7a30e6fc` | +| SupportedStandards:ERC725Account | Allows to determine standards supported by this contract | `0xeafec4d89fa9619884b6b89135626455000000000000000000000000afdeb5d6`, where `afdeb5d6` is the 4 bytes part of the hash of `keccak256('ERC725Account')` | Value is the 4 bytes identifier `0xafdeb5d6` | -Anyone that would like to standardize a new data key should make a pull request to update the table below. + +Other key examples COULD be: | Name | Description | Key | value | | --- | --- | --- | --- | -| owner | The owner of the proxy account | 0x0000000000000000000000000000000000000000000000000000000000000000 | left padded owner address, e.g. `0x000000000000000000000000de0B295669a9FD93d5F28D9Ec85E40f4cb697BAe` | -| 735 | The proxy accounts claim holder contract (per [ERC735](https://github.com/ethereum/EIPs/issues/735)) | 0xb0f23aea7d77ce19f9393243a7b50a3bcaac893c7d68a5a309dea7cacf035fd0 | left padded address of the claim holder contract, e.g. `0x000000000000000000000000de0B295669a9FD93d5F28D9Ec85E40f4cb697BAe` | -| 780 | The proxy accounts claim holder contract (per [ERC735](https://github.com/ethereum/EIPs/issues/735)) | 0xdaf52dba5981246bcf8fd7c6b00dce587fdcf5e2a95b281eea95dcd1376afdcd | left padded address of the claim registry contract, e.g. `0x000000000000000000000000de0B295669a9FD93d5F28D9Ec85E40f4cb697BAe` | +| ERC735 | A personal claim holder contract (per [ERC735](https://github.com/ethereum/EIPs/issues/735)) | `0x33f5765e0b3f726091f5ab06cd801c2bcd9bf89228534161c70fd7e257b8bfa3` | 20 bytes value `0xcafecafe69a9FD93d5F28D9Ec85E40f4cb69cafe` | +| ERC780 | A registry claim holder contract (per [ERC780](https://github.com/ethereum/EIPs/issues/780)) | `0x62db7b9279d03518c54464b4946aade7cafabff066a90c55b054d5c5ee04c371` | 20 bytes value `0xcafecafe69a9FD93d5F28D9Ec85E40f4cb69cafe` | -## Rationale +##### ERC725Account -The purpose of an identity proxy is to allow an entity to exist as a first-class citizen in Ethereum, with the ability to execute arbitrary contract calls. At that same time the proxy account should be managed by an arbitrary simple or complex logic. +An `SupportedStandards` > `ERC725Account` (See key > value above) is an ERC725 smart contract based account/profile for storing of assets and execution of other smart contracts. -It also opens up the possibility of [meta transactions](https://medium.com/@austin_48503/ethereum-meta-transactions-90ccf0859e84), where a third party can send a transaction to the owner contract, that then verifies the execution permission based on a signed message. +- `ERC173` to be controllable by an owner, that could be am external account, or smart contract +- `ERC725X` to interact with other smart contracts +- `ERC725Y` to attach data to the account for future extensibility +- COULD have [ERC1271](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1271.md) to be able to verify signatures by the owner (or owner contracts keys). +- Should fire the `event ValueReceived(address indexed sender, uint256 indexed value)` if ETH is received. -It further allows any information to be attached to that proxy accounts which can be in the forms of claims via [ERC735](https://github.com/ethereum/EIPs/issues/735) or [ERC780](https://github.com/ethereum/EIPs/issues/780), or any arbitrary new systems and protocols. +A full implementation of an `ERC725Account` can be found [found here](https://github.com/ERC725Alliance/ERC725/tree/master/implementations/contracts). -This specification was chosen to allow the most flexibility and experimentation around verifiable manageable accounts. +## Rationale +The purpose of an smart contract account is to allow an entity to exist as a first-class citizen with the ability to execute arbitrary contract calls. ## Implementation -- [Implementation by ERC725Alliance](https://github.com/ERC725Alliance/erc725/tree/master/contracts/contracts) +- [Latest implementation](https://github.com/ERC725Alliance/ERC725/tree/master/implementations/contracts) -### Solidity Interface -```js -pragma solidity ^0.5.4; +### Solidity Interfaces +```solidity +// SPDX-License-Identifier: CC0-1.0 +pragma solidity >=0.5.0 <0.7.0; -interface ERC725 { - event DataChanged(bytes32 indexed key, bytes32 indexed value); - event OwnerChanged(address indexed ownerAddress); +//ERC165 identifier: `0x44c028fe` +interface IERC725X /* is ERC165, ERC173 */ { event ContractCreated(address indexed contractAddress); + event Executed(uint256 indexed operation, address indexed to, uint256 indexed value, bytes data); - // address public owner; + function execute(uint256 operationType, address to, uint256 value, bytes memory data) external; +} + +//ERC165 identifier: `0x2bd57b73` +interface IERC725Y /* is ERC165, ERC173 */ { + event DataChanged(bytes32 indexed key, bytes value); - function changeOwner(address _owner) external; - function getData(bytes32 _key) external view returns (bytes32 _value); - function setData(bytes32 _key, bytes32 _value) external; - function execute(uint256 _operationType, address _to, uint256 _value, bytes calldata _data) external; + function getData(bytes32 key) external view returns (bytes memory value); + function setData(bytes32 key, bytes memory value) external; +} + +interface IERC725 /* is IERC725X, IERC725Y */ { + +} + +interface IERC725Account /* is IERC725, IERC725Y, IERC1271 */ { + event ValueReceived(address indexed sender, uint256 indexed value); } ``` +## Flow chart + +![ERC725v2-flow](https://user-images.githubusercontent.com/232662/57334038-996a8b00-70ec-11e9-9179-4dda3f30e09d.PNG) + ## Additional References - [Slides of the ERC Identity presentation](https://www.slideshare.net/FabianVogelsteller/erc-725-identity) diff --git a/EIPS/eip-747.md b/EIPS/eip-747.md index 252d0409dfe823..75f90bf28e59a4 100644 --- a/EIPS/eip-747.md +++ b/EIPS/eip-747.md @@ -7,17 +7,21 @@ status: Draft type: Standards Track category: Interface created: 2018-08-13 -requires: 1474 +requires: 1193 --- ## Simple Summary -A method for allowing users to easily track new assets with a suggestion from sites they are visiting. + +An RPC method for allowing users to easily track new assets with a suggestion from sites they are visiting. ## Abstract -Web3 JavaScript wallet browsers may implement `wallet_watchAsset()` to allow any website to suggest a token for the user's wallet to track. + +Web3 JavaScript wallet browsers may implement the `wallet_watchAsset` RPC method to allow any website to suggest a token for the user's wallet to track. ## Motivation -Today, one of the major uses of ethereum wallets is to acquire and track assets. Currently, each wallet either needs to pre-load a list of approved assets, or users need to be stepped through a tedious process of adding an asset for their given wallet. + +Today, one of the major uses of Ethereum wallets is to acquire and track assets. +Currently, each wallet either needs to pre-load a list of approved assets, or users need to be stepped through a tedious process of adding an asset for their given wallet. In the first case, wallets are burdened with both the security of managing this list, as well as the bandwidth of mass polling for known assets on their wallet. @@ -26,49 +30,81 @@ In the second case, the user experience is terrible. By leveraging a user's existing trust with websites they are learning about assets on, we are able to decentralize the responsibility of managing a user's list of known assets. ## Specification -A new method is added to web3 browsers' ethereum providers: -```javascript +We introduce the `wallet_watchAsset` RPC method: -/** -* @param {Object} opts - The options specifying the asset `type` and `options` specific for each of asset. -* @returns {Promise} success - Whether the user added the asset to their wallet. -*/ -async function wallet_watchAsset ( - opts -) { -/* Implementation would go here */ -} +### wallet_watchAsset -// Sample usage: -web3.wallet.watchAsset({ type, options }) -``` -As there are several types of different assets, this method has to provide support for each of them in a separate way. If it doesn't, it should give a response according to that. +Requests that a specified asset be added to the user's wallet, and returns `true` if the asset was successfully added, or an error if it was not. -In the case of assets of type `ERC20`, this method works as follows. +The meaning of "added to the user's wallet" is dependent on the wallet implementation. +A successful call to `wallet_watchAsset` should indicate that the specified asset became (or already was) included in some list of assets in the user's wallet, that the user can view and possibly interact with in the wallet UI. -```javascript -web3.wallet.watchAsset({ - type: 'ERC20', - options: { address, symbol, decimals [, image] } -}) +#### Parameters + +A single, `WatchAssetParameters` object. + +```typescript +interface WatchAssetParameters { + type: string; // The asset's interface, e.g. 'ERC20' + options: { + address: string; // The hexadecimal Ethereum address of the token contract + symbol?: string; // A ticker symbol or shorthand, up to 5 alphanumerical characters + decimals?: number; // The number of asset decimals + image?: string; // A string url of the token logo + }; +} ``` -The `image` parameter should link to a web-standard image format (png, jpg) of a reasonable size or a `Base64` image. To establish a baseline, let's say no greater than 512x512 pixels, and no greater than 256kb. However, this can be a client-defined setting. +The only strictly required fields are `type`, `options`, and `options.address`. +This interface can and should be extended depending on the asset `type`. + +##### type + +The `type` string should be the commonly accepted name of the interface implemented by the asset's contract, e.g. `ERC20`. + +Defining the global identifiers for different asset types is beyond the scope of this EIP. + +##### options.image -An example of use in the first case would be. +The `image` string should be a URL to a common image format (e.g. png, jpg, or svg) or a `Base64` image. +The image itself should be no larger than 512x512 pixels, and no larger than 256kb. +Implementers may edit these limits as necessary. + +#### Returns + +`boolean` - `true` if the the asset was added successfully, and an error otherwise. + +#### Example + +As there are several types of different assets, this method has to provide support for each of them in a separate way. +If it doesn't, it should give a response according to that. + +In the case of assets of type `ERC20`, this method works as follows. ```javascript -web3.wallet.watchAsset({ - type: 'ERC20', - options: { - address, - symbol, - decimals, - image: 'linktoimage.jpg' - } -}) +ethereum.request({ + method: 'wallet_watchAsset', + params: { + type: 'ERC20', + options: { + address: '0xb60e8dd61c5d32be8058bb8eb970870f07233155', + symbol: 'FOO', + decimals: 18, + image: 'https://foo.io/token-image.svg', + }, + }, +}); + .then((success) => { + if (success) { + console.log('FOO successfully added to wallet!') + } else { + throw new Error('Something went wrong.') + } + }) + .catch(console.error) ``` + Upon calling this request, the user should be prompted with the opportunity to add this token to their wallet: ![add-token-prompt 1](../assets/eip-747/add-token-prompt.gif) @@ -76,17 +112,21 @@ Upon calling this request, the user should be prompted with the opportunity to a For `Base64` images, the user just have to add it as `image` parameter. ```javascript -const base64image = 'data:image/png;base64, ... ' -web3.wallet.watchAsset({ - type: 'ERC20', - options: { - address, - symbol, - decimals, - image: base64image - } -}) +const base64image = 'data:image/png;base64, ... '; +ethereum.request({ + method: 'wallet_watchAsset', + params: { + type: 'ERC20', + options: { + address, + symbol, + decimals, + image: base64image, + }, + }, +}); ``` + Upon calling this request, the user should be prompted with the opportunity to add this token to their wallet: ![add-token-prompt 2](../assets/eip-747/add-token-prompt2.gif) @@ -95,13 +135,14 @@ If the user adds this token, it should appear somewhere in their wallet's UI, wi As a result of the addition or not of the asset a `Promise` should be returned, indicating if the user added the asset or an error if some parameter is not valid. -In the case of an asset type that is not supported by the wallet, an error should appear indicating at least. +If the wallet does not support the specified asset type, the error should indicate this with the message: -``` -Asset of type (type) not supported +```javascript +`Asset of type '${type}' not supported`; ``` ## Rationale + Displaying a user's assets is a basic feature that every modern dapp user expects. However, keeping this list, and polling for it from the network can be costly, especially on bandwidth constrained devices. Most wallets today either manage their own assets list, which they store client side, or they query a centralized API for balances, which reduces decentralization, letting that API's owner easily correlate account holders with their IP addresses. @@ -117,8 +158,9 @@ While some people might suggest we begin a TCR of trusted tokens to watch, this Most of the time a user is adding a asset, they learned about it on a website. At that moment, there is a natural alignment of interests, where the website wants the user to track their asset, and the user wants to track it. This is a natural point to introduce an API to easily allow these parties to collaborate, without involving the politics of the wallet's developers. ## Implementation + One implementation in progress can be viewed [on the MetaMask GitHub repository](https://github.com/MetaMask/metamask-extension/pull/4606). ## Copyright -Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/EIPS/eip-758.md b/EIPS/eip-758.md index eb71ae5febc725..30a6f3481e70dc 100644 --- a/EIPS/eip-758.md +++ b/EIPS/eip-758.md @@ -111,7 +111,7 @@ All transactions that were sealed _after_ the initial `eth_newCompletedTransacti ## Rationale -[EIP 658](./eip-658.md) originally proposed adding return data to transaction receipts. However, return data is not charged for (as it is not stored on the blockchain), so adding it to transaction receipts could result in DoS and spam opportunities. Instead, a simple Boolean `status` field was added to transaction receipts. This modified version of EIP 658 was included in the Byzantium hard fork. While the `status` field is useful, applications often need the return data as well. +[EIP-658](./eip-658.md) originally proposed adding return data to transaction receipts. However, return data is not charged for (as it is not stored on the blockchain), so adding it to transaction receipts could result in DoS and spam opportunities. Instead, a simple Boolean `status` field was added to transaction receipts. This modified version of EIP 658 was included in the Byzantium hard fork. While the `status` field is useful, applications often need the return data as well. The primary advantage of using the strategy outlined here is efficiency: no extra data needs to be stored on the blockchain, and minimal extra computational load is imposed on nodes. Although after-the-fact lookups of the return value would not be supported, this is consistent with the conventional use of return data, which are only accessible to the caller when the function returns, and are not stored for later use. diff --git a/EIPS/eip-777.md b/EIPS/eip-777.md index daf15ba2248e50..cde8e3adb6f56b 100644 --- a/EIPS/eip-777.md +++ b/EIPS/eip-777.md @@ -16,18 +16,18 @@ This EIP defines standard interfaces and behaviors for token contracts. ## Abstract -This standard defines a new way to interact with a token contract while remaining backward compatible with [ERC20]. +This standard defines a new way to interact with a token contract while remaining backward compatible with [ERC-20]. It defines advanced features to interact with tokens. Namely, *operators* to send tokens on behalf of another address—contract or regular account—and send/receive *hooks* to offer token holders more control over their tokens. -It takes advantage of [ERC1820] to find out whether and where to notify contracts and regular addresses +It takes advantage of [ERC-1820] to find out whether and where to notify contracts and regular addresses when they receive tokens as well as to allow compatibility with already-deployed contracts. ## Motivation -This standard tries to improve upon the widely used [ERC20] token standard. +This standard tries to improve upon the widely used [ERC-20] token standard. The main advantages of this standard are: 1. Uses the same philosophy as Ether in that tokens are sent with `send(dest, value, data)`. @@ -41,7 +41,7 @@ The main advantages of this standard are: (Rejection is done by `revert`ing in the hook function.) 4. The `tokensReceived` hook allows to send tokens to a contract and notify it in a single transaction, - unlike [ERC20] which requires a double call (`approve`/`transferFrom`) to achieve this. + unlike [ERC-20] which requires a double call (`approve`/`transferFrom`) to achieve this. 5. The holder can "authorize" and "revoke" operators which can send tokens on their behalf. These operators are intended to be verified contracts @@ -122,9 +122,9 @@ interface ERC777Token { The token contract MUST implement the above interface. The implementation MUST follow the specifications described below. -The token contract MUST register the `ERC777Token` interface with its own address via [ERC1820]. +The token contract MUST register the `ERC777Token` interface with its own address via [ERC-1820]. -> This is done by calling the `setInterfaceImplementer` function on the [ERC1820] registry +> This is done by calling the `setInterfaceImplementer` function on the [ERC-1820] registry > with the token contract address as both the address and the implementer > and the `keccak256` hash of `ERC777Token` (`0xac7fbab5f54a3ca8194167523c6753bfeb96a445279294b6125b68cce2177054`) > as the interface hash. @@ -133,7 +133,7 @@ If the contract has a switch to enable or disable ERC777 functions, every time t the token MUST register or unregister the `ERC777Token` interface for its own address accordingly via ERC1820. Unregistering implies calling the `setInterfaceImplementer` with the token contract address as the address, the `keccak256` hash of `ERC777Token` as the interface hash and `0x0` as the implementer. -(See [Set An Interface For An Address][erc1820-set] in [ERC1820] for more details.) +(See [Set An Interface For An Address][erc1820-set] in [ERC-1820] for more details.) When interacting with the token contract, all amounts and balances MUST be unsigned integers. I.e. internally, all values are stored as a denomination of 1E-18 of a token. @@ -142,7 +142,7 @@ be 1018 of the internal denomination. In other words, the internal denomination is similar to a wei and the display denomination is similar to an ether. -It is equivalent to an [ERC20]'s `decimals` function returning `18`. +It is equivalent to an [ERC-20]'s `decimals` function returning `18`. E.g. if a token contract returns a balance of `500,000,000,000,000,000` (0.5×1018) for a user, the user interface MUST show `0.5` tokens to the user. If the user wishes to send `0.3` tokens, @@ -247,15 +247,15 @@ I.e., this function SHOULD return `1` unless there is a good reason for not allo *NOTE*: [`defaultOperators`][defaultOperators] and [`isOperatorFor`][isOperatorFor] are also `view` functions, defined under the [operators] for consistency. -*[ERC20] compatibility requirement*: +*[ERC-20] compatibility requirement*: The decimals of the token MUST always be `18`. -For a *pure* ERC777 token the [ERC20] `decimals` function is OPTIONAL, +For a *pure* ERC777 token the [ERC-20] `decimals` function is OPTIONAL, and its existence SHALL NOT be relied upon when interacting with the token contract. (The decimal value of `18` is implied.) -For an [ERC20] compatible token, the `decimals` function is REQUIRED and MUST return `18`. -(In [ERC20], the `decimals` function is OPTIONAL. +For an [ERC-20] compatible token, the `decimals` function is REQUIRED and MUST return `18`. +(In [ERC-20], the `decimals` function is OPTIONAL. If the function is not present, the `decimals` value is not clearly defined and may be assumed to be `0`. -Hence for compatibility reasons, `decimals` MUST be implemented for [ERC20] compatible tokens.) +Hence for compatibility reasons, `decimals` MUST be implemented for [ERC-20] compatible tokens.) #### **Operators** @@ -433,10 +433,10 @@ with the associated `data` and `operatorData`, the token contract MUST apply the - The *operator* MAY include information in the `operatorData`. - The token contract MUST call the `tokensToSend` hook of the *holder* - if the *holder* registers an `ERC777TokensSender` implementation via [ERC1820]. + if the *holder* registers an `ERC777TokensSender` implementation via [ERC-1820]. - The token contract MUST call the `tokensReceived` hook of the *recipient* - if the *recipient* registers an `ERC777TokensRecipient` implementation via [ERC1820]. + if the *recipient* registers an `ERC777TokensRecipient` implementation via [ERC-1820]. - The `data` and `operatorData` MUST be immutable during the entire send process—hence the same `data` and `operatorData` MUST be used to call both hooks and emit the `Sent` event. @@ -448,7 +448,7 @@ The token contract MUST `revert` when sending in any of the following cases: - The resulting *holder* balance or *recipient* balance after the send is not a multiple of the *granularity* defined by the token contract. -- The *recipient* is a contract, and it does not implement the `ERC777TokensRecipient` interface via [ERC1820]. +- The *recipient* is a contract, and it does not implement the `ERC777TokensRecipient` interface via [ERC-1820]. - The address of the *holder* or the *recipient* is `0x0`. @@ -511,7 +511,7 @@ event Sent( Indicate a send of `amount` of tokens from the `from` address to the `to` address by the `operator` address. -*NOTE*: This event MUST NOT be emitted outside of a send or an [ERC20] transfer process. +*NOTE*: This event MUST NOT be emitted outside of a send or an [ERC-20] transfer process. > **parameters** > `operator`: Address which triggered the send. @@ -574,8 +574,8 @@ that the *operator* MAY specify an explicit value for `operatorData` #### **Minting Tokens** Minting tokens is the act of producing new tokens. -[ERC777] intentionally does not define specific functions to mint tokens. -This intent comes from the wish not to limit the use of the [ERC777] standard +[ERC-777] intentionally does not define specific functions to mint tokens. +This intent comes from the wish not to limit the use of the [ERC-777] standard as the minting process is generally specific for every token. Nonetheless, the rules below MUST be respected when minting for a *recipient*: @@ -591,7 +591,7 @@ Nonetheless, the rules below MUST be respected when minting for a *recipient*: - The token contract MUST emit a `Minted` event with the correct values as defined in the [`Minted` Event][minted]. - The token contract MUST call the `tokensReceived` hook of the *recipient* - if the *recipient* registers an `ERC777TokensRecipient` implementation via [ERC1820]. + if the *recipient* registers an `ERC777TokensRecipient` implementation via [ERC-1820]. - The `data` and `operatorData` MUST be immutable during the entire mint process—hence the same `data` and `operatorData` MUST be used to call the `tokensReceived` hook and emit the `Minted` event. @@ -599,7 +599,7 @@ Nonetheless, the rules below MUST be respected when minting for a *recipient*: The token contract MUST `revert` when minting in any of the following cases: - The resulting *recipient* balance after the mint is not a multiple of the *granularity* defined by the token contract. -- The *recipient* is a contract, and it does not implement the `ERC777TokensRecipient` interface via [ERC1820]. +- The *recipient* is a contract, and it does not implement the `ERC777TokensRecipient` interface via [ERC-1820]. - The address of the *recipient* is `0x0`. - The `tokensReceived` hook of the *recipient* `revert`s. @@ -608,10 +608,10 @@ for the amount of the initial supply to the address(es) receiving the initial su This means one or more `Minted` events must be emitted and the `tokensReceived` hook of the recipient(s) MUST be called. -*[ERC20] compatibility requirement*: +*[ERC-20] compatibility requirement*: While a `Sent` event MUST NOT be emitted when minting, -if the token contract is [ERC20] backward compatible, -a `Transfer` event with the `from` parameter set to `0x0` SHOULD be emitted as defined in the [ERC20] standard. +if the token contract is [ERC-20] backward compatible, +a `Transfer` event with the `from` parameter set to `0x0` SHOULD be emitted as defined in the [ERC-20] standard. The token contract MAY mint tokens for multiple *recipients* at once. In this case: @@ -656,7 +656,7 @@ Indicate the minting of `amount` of tokens to the `to` address by the `operator` #### **Burning Tokens** Burning tokens is the act of destroying existing tokens. -[ERC777] explicitly defines two functions to burn tokens (`burn` and `operatorBurn`). +[ERC-777] explicitly defines two functions to burn tokens (`burn` and `operatorBurn`). These functions facilitate the integration of the burning process in wallets and dapps. However, the token contract MAY prevent some or all *holders* from burning tokens for any reason. The token contract MAY also define other functions to burn tokens. @@ -674,7 +674,7 @@ The rules below MUST be respected when burning the tokens of a *holder*: - The token contract MUST emit a `Burned` event with the correct values as defined in the [`Burned` Event][burned]. - The token contract MUST call the `tokensToSend` hook of the *holder* - if the *holder* registers an `ERC777TokensSender` implementation via [ERC1820]. + if the *holder* registers an `ERC777TokensSender` implementation via [ERC-1820]. - The `operatorData` MUST be immutable during the entire burn process—hence the same `operatorData` MUST be used to call the `tokensToSend` hook and emit the `Burned` event. @@ -693,10 +693,10 @@ The token contract MUST `revert` when burning in any of the following cases: - The `tokensToSend` hook of the *holder* `revert`s. -*[ERC20] compatibility requirement*: +*[ERC-20] compatibility requirement*: While a `Sent` event MUST NOT be emitted when burning; -if the token contract is [ERC20] enabled, a `Transfer` event with the `to` parameter set to `0x0` SHOULD be emitted. -The [ERC20] standard does not define the concept of burning tokens, but this is a commonly accepted practice. +if the token contract is [ERC-20] enabled, a `Transfer` event with the `to` parameter set to `0x0` SHOULD be emitted. +The [ERC-20] standard does not define the concept of burning tokens, but this is a commonly accepted practice. The token contract MAY burn tokens for multiple *holders* at once. In this case: @@ -791,9 +791,9 @@ with the addition that the *operator* MAY specify an explicit value for `operato The `tokensToSend` hook notifies of any request to decrement the balance (send and burn) for a given *holder*. Any address (regular or contract) wishing to be notified of token debits from 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 `ERC777TokensSender` interface described below via [ERC-1820]. -> This is done by calling the `setInterfaceImplementer` function on the [ERC1820] registry +> This is done by calling the `setInterfaceImplementer` function on the [ERC-1820] registry > with the *holder* address as the address, > the `keccak256` hash of `ERC777TokensSender` > (`0x29ddb589b1fb5fc7cf394961c1adf5f8c6454761adf795e67fe149f658abe895`) as the interface hash, @@ -833,7 +833,7 @@ function tokensToSend( Notify a request to send or burn (if `to` is `0x0`) an `amount` tokens from the `from` address to the `to` address by the `operator` address. -*NOTE*: This function MUST NOT be called outside of a burn, send or [ERC20] transfer process. +*NOTE*: This function MUST NOT be called outside of a burn, send or [ERC-20] transfer process. > **identifier:** `75ab9782` > **parameters** @@ -870,13 +870,13 @@ The following rules apply when calling the `tokensToSend` hook: *NOTE*: Multiple *holders* MAY use the same implementation of `ERC777TokensSender`. -*NOTE*: An address can register at most one implementation at any given time for all [ERC777] tokens. +*NOTE*: An address can register at most one implementation at any given time for all [ERC-777] tokens. Hence the `ERC777TokensSender` MUST expect to be called by different token contracts. The `msg.sender` of the `tokensToSend` call is expected to be the address of the token contract. -*[ERC20] compatibility requirement*: -This hook takes precedence over [ERC20] and MUST be called (if registered) -when calling [ERC20]'s `transfer` and `transferFrom` event. +*[ERC-20] compatibility requirement*: +This hook takes precedence over [ERC-20] and MUST be called (if registered) +when calling [ERC-20]'s `transfer` and `transferFrom` event. When called from a `transfer`, `operator` MUST be the same value as the `from`. When called from a `transferFrom`, `operator` MUST be the address which issued the `transferFrom` call. @@ -884,9 +884,9 @@ 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 `ERC777TokensRecipient` interface described below via [ERC1820]. +MAY register the address of a contract implementing the `ERC777TokensRecipient` interface described below via [ERC-1820]. -> This is done by calling the `setInterfaceImplementer` function on the [ERC1820] registry +> This is done by calling the `setInterfaceImplementer` function on the [ERC-1820] registry > with the *recipient* address as the address, > the `keccak256` hash of `ERC777TokensRecipient` > (`0xb281fc8c12954d22544db45de3159a39272895b169a852b314f9cc762e44c53b`) as the interface hash, @@ -934,7 +934,7 @@ function tokensReceived( Notify a send or mint (if `from` is `0x0`) of `amount` tokens from the `from` address to the `to` address by the `operator` address. -*NOTE*: This function MUST NOT be called outside of a mint, send or [ERC20] transfer process. +*NOTE*: This function MUST NOT be called outside of a mint, send or [ERC-20] transfer process. > **identifier:** `0023de29` > **parameters** @@ -971,13 +971,13 @@ The following rules apply when calling the `tokensReceived` hook: *NOTE*: Multiple *holders* MAY use the same implementation of `ERC777TokensRecipient`. -*NOTE*: An address can register at most one implementation at any given time for all [ERC777] tokens. +*NOTE*: An address can register at most one implementation at any given time for all [ERC-777] tokens. Hence the `ERC777TokensRecipient` MUST expect to be called by different token contracts. The `msg.sender` of the `tokensReceived` call is expected to be the address of the token contract. -*[ERC20] compatibility requirement*: -This hook takes precedence over [ERC20] and MUST be called (if registered) -when calling [ERC20]'s `transfer` and `transferFrom` event. +*[ERC-20] compatibility requirement*: +This hook takes precedence over [ERC-20] and MUST be called (if registered) +when calling [ERC-20]'s `transfer` and `transferFrom` event. When called from a `transfer`, `operator` MUST be the same value as the `from`. When called from a `transferFrom`, `operator` MUST be the address which issued the `transferFrom` call. @@ -993,13 +993,13 @@ Dapps and wallets SHOULD first estimate the gas required when sending, minting, | **Color** | beige | white | light grey | dark grey | black | | **Hex** | `#C99D66` | `#FFFFFF` | `#EBEFF0` | `#3C3C3D` | `#000000` | -The logo MAY be used, modified and adapted to promote valid [ERC777] token implementations -and [ERC777] compliant technologies such as wallets and dapps. +The logo MAY be used, modified and adapted to promote valid [ERC-777] token implementations +and [ERC-777] compliant technologies such as wallets and dapps. -[ERC777] token contract authors MAY create a specific logo for their token based on this logo. +[ERC-777] token contract authors MAY create a specific logo for their token based on this logo. The logo MUST NOT be used to advertise, promote or associate in any way technology—such -as tokens—which is not [ERC777] compliant. +as tokens—which is not [ERC-777] compliant. The logo for the standard can be found in the [`/assets/eip-777/logo`][logos] folder in `SVG` and `PNG` formats. The `PNG` version of the logo offers a few sizes in pixels. @@ -1008,8 +1008,8 @@ If needed, other sizes MAY be created by converting from `SVG` into `PNG`. ## Rationale The principal intent for this standard is -to solve some of the shortcomings of [ERC20] while maintaining backward compatibility with [ERC20], -and avoiding the problems and vulnerabilities of [EIP223]. +to solve some of the shortcomings of [ERC-20] while maintaining backward compatibility with [ERC-20], +and avoiding the problems and vulnerabilities of [EIP-223]. Below are the rationales for the decisions regarding the main aspects of the standards. @@ -1020,12 +1020,12 @@ and can provide further clarifications regarding certain aspects or decisions. ### Lifecycle -More than just sending tokens, [ERC777] defines the entire lifecycle of a token, +More than just sending tokens, [ERC-777] defines the entire lifecycle of a token, starting with the minting process, followed by the sending process and terminating with the burn process. Having a lifecycle clearly defined is important for consistency and accuracy, especially when value is derived from scarcity. -In contrast when looking at some [ERC20] tokens, a discrepancy can be observed +In contrast when looking at some [ERC-20] tokens, a discrepancy can be observed between the value returned by the `totalSupply` and the actual circulating supply, as the standard does not clearly define a process to create and destroy tokens. @@ -1037,12 +1037,12 @@ Those fields may be empty for simple use cases, or they may contain valuable information related to the movement of tokens, similar to information attached to a bank transfer by the sender or the bank itself. -The use of a `data` field is equally present in other standard proposals such as [EIP223], +The use of a `data` field is equally present in other standard proposals such as [EIP-223], and was requested by multiple members of the community who reviewed this standard. ### Hooks -In most cases, [ERC20] requires two calls to safely transfer tokens to a contract without locking them. +In most cases, [ERC-20] requires two calls to safely transfer tokens to a contract without locking them. A call from the sender, using the `approve` function and a call from the recipient using `transferFrom`. Furthermore, this requires extra communication between the parties which is not clearly defined. @@ -1061,15 +1061,15 @@ for example located in the `data` or `operatorData` fields. Following the same intentions and based on suggestions from the community, the `tokensToSend` hook was added to give control over and prevent the movement of outgoing tokens. -#### **[ERC1820] Registry** +#### **[ERC-1820] Registry** -The [ERC1820] Registry allows holders to register their hooks. +The [ERC-1820] Registry allows holders to register their hooks. Other alternatives were examined beforehand to link hooks and holders. The first was for hooks to be defined at the sender's or recipient's address. -This approach is similar to [EIP223] which proposes a `tokenFallback` function on recipient contracts +This approach is similar to [EIP-223] which proposes a `tokenFallback` function on recipient contracts to be called when receiving tokens, -but improves on it by relying on [ERC165] for interface detection. +but improves on it by relying on [ERC-165] for interface detection. While straightforward to implement, this approach imposes several limitations. In particular, the sender and recipient must be contracts in order to provide their implementation of the hooks. Preventing externally owned addresses to benefit from hooks. @@ -1078,7 +1078,7 @@ as they undoubtedly were unaware and do not define the new hooks. Consequently existing smart contract infrastructure such as multisig wallets which potentially hold large amounts of ether and tokens would need to be migrated to new updated contracts. -The second approach considered was to use [ERC672] which offered pseudo-introspection for addresses using reverse-ENS. +The second approach considered was to use [ERC-672] which offered pseudo-introspection for addresses using reverse-ENS. However, this approach relied heavily on ENS, on top of which reverse lookup would need to be implemented. Analysis of this approach promptly revealed a certain degree of complexity and security concerns which would transcend the benefits of approach. @@ -1092,14 +1092,14 @@ The decision was made to keep this registry in a separate EIP, as to not over complicate this standard. More importantly, the registry is designed in a flexible fashion, such that other EIPs and smart contract infrastructures can benefit from it -for their own use cases, outside the realm of [ERC777] and tokens. -The first proposal for this registry was [ERC820]. +for their own use cases, outside the realm of [ERC-777] and tokens. +The first proposal for this registry was [ERC-820]. Unfortunately, issues emanating from upgrades in the Solidity language to versions 0.5 and above resulted in a bug in a separated part of the registry, which required changes. This was discovered right after the last call period. Attempts made to avoid creating a separate EIP, such as [ERC820a], were rejected. -Hence the standard for the registry used for [ERC777] became [ERC1820]. -[ERC1820] and [ERC820] are functionally equivalent. [ERC1820] simply contains the fix for newer versions of Solidity. +Hence the standard for the registry used for [ERC-777] became [ERC-1820]. +[ERC-1820] and [ERC-820] are functionally equivalent. [ERC-1820] simply contains the fix for newer versions of Solidity. ### Operators @@ -1108,8 +1108,8 @@ While intuitively every address moves its own tokens, separating the concepts of holder and operator allows for greater flexibility. Primarily, this originates from the fact that the standard defines a mechanism for holders to let other addresses become their operators. -Moreover, unlike the approve calls in [ERC20] where the role of an approved address is not clearly defined, -[ERC777] details the intent of and interactions with operators, +Moreover, unlike the approve calls in [ERC-20] where the role of an approved address is not clearly defined, +[ERC-777] details the intent of and interactions with operators, including an obligation for operators to be approved, and an irrevocable right for any holder to revoke operators. @@ -1127,29 +1127,29 @@ and to reduce the complexity for holders to use features provided through operat ## Backward Compatibility -This EIP does not introduce backward incompatibilities and is backward compatible with the older [ERC20] token standard. +This EIP does not introduce backward incompatibilities and is backward compatible with the older [ERC-20] token standard. This EIP does not use `transfer` and `transferFrom` and uses `send` and `operatorSend` to avoid confusion and mistakes when deciphering which token standard is being used. -This standard allows the implementation of [ERC20] functions `transfer`, `transferFrom`, `approve` and `allowance` -alongside to make a token fully compatible with [ERC20]. +This standard allows the implementation of [ERC-20] functions `transfer`, `transferFrom`, `approve` and `allowance` +alongside to make a token fully compatible with [ERC-20]. -The token MAY implement `decimals()` for backward compatibility with [ERC20]. +The token MAY implement `decimals()` for backward compatibility with [ERC-20]. If implemented, it MUST always return `18`. -Therefore a token contract MAY implement both [ERC20] and [ERC777] in parallel. +Therefore a token contract MAY implement both [ERC-20] and [ERC-777] in parallel. The specification of the `view` functions (such as `name`, `symbol`, `balanceOf`, `totalSupply`) and internal data (such as the mapping of balances) overlap without problems. -Note however that the following functions are mandatory in [ERC777] and MUST be implemented: +Note however that the following functions are mandatory in [ERC-777] and MUST be implemented: `name`, `symbol` `balanceOf` and `totalSupply` -(`decimals` is not part of the [ERC777] standard). +(`decimals` is not part of the [ERC-777] standard). The state-modifying functions from both standards are decoupled and can operate independently from each other. -Note that [ERC20] functions SHOULD be limited to only being called from old contracts. +Note that [ERC-20] functions SHOULD be limited to only being called from old contracts. -If the token implements [ERC20], -it MUST register the `ERC20Token` interface with its own address via [ERC1820]. +If the token implements [ERC-20], +it MUST register the `ERC20Token` interface with its own address via [ERC-1820]. This is done by calling the `setInterfaceImplementer` function on the ERC1820 registry with the token contract address as both the address and the implementer and the `keccak256` hash of `ERC20Token` (`0xaea199e31a596269b42cdafd93407f14436db6e4cad65417994c2eb37381e05a`) @@ -1159,18 +1159,18 @@ If the contract has a switch to enable or disable ERC20 functions, every time th the token MUST register or unregister the `ERC20Token` interface for its own address accordingly via ERC1820. Unregistering implies calling the `setInterfaceImplementer` with the token contract address as the address, the `keccak256` hash of `ERC20Token` as the interface hash and `0x0` as the implementer. -(See [Set An Interface For An Address][erc1820-set] in [ERC1820] for more details.) +(See [Set An Interface For An Address][erc1820-set] in [ERC-1820] for more details.) -The difference for new contracts implementing [ERC20] is that -`tokensToSend` and `tokensReceived` hooks take precedence over [ERC20]. -Even with an [ERC20] `transfer` and `transferFrom` call, the token contract MUST check via [ERC1820] +The difference for new contracts implementing [ERC-20] is that +`tokensToSend` and `tokensReceived` hooks take precedence over [ERC-20]. +Even with an [ERC-20] `transfer` and `transferFrom` call, the token contract MUST check via [ERC-1820] if the `from` and the `to` address implement `tokensToSend` and `tokensReceived` hook respectively. If any hook is implemented, it MUST be called. -Note that when calling [ERC20] `transfer` on a contract, if the contract does not implement `tokensReceived`, +Note that when calling [ERC-20] `transfer` on a contract, if the contract does not implement `tokensReceived`, the `transfer` call SHOULD still be accepted even if this means the tokens will probably be locked. The table below summarizes the different actions the token contract MUST take -when sending, minting and transferring token via [ERC777] and [ERC20]: +when sending, minting and transferring token via [ERC-777] and [ERC-20]: @@ -1216,13 +1216,13 @@ The movement MUST proceed and only be canceled if another condition is not respe such as lack of funds or a `revert` in `tokensReceived` (if present). During a send, mint and burn, the respective `Sent`, `Minted` and `Burned` events MUST be emitted. -Furthermore, if the token contract declares that it implements `ERC20Token` via [ERC1820], +Furthermore, if the token contract declares that it implements `ERC20Token` via [ERC-1820], the token contract SHOULD emit a `Transfer` event for minting and burning -and MUST emit a `Transfer` event for sending (as specified in the [ERC20] standard). -During an [ERC20]'s `transfer` or `transferFrom` functions, a valid `Sent` event MUST be emitted. +and MUST emit a `Transfer` event for sending (as specified in the [ERC-20] standard). +During an [ERC-20]'s `transfer` or `transferFrom` functions, a valid `Sent` event MUST be emitted. Hence for any movement of tokens, two events MAY be emitted: -an [ERC20] `Transfer` and an [ERC777] `Sent`, `Minted` or `Burned` (depending on the type of movement). +an [ERC-20] `Transfer` and an [ERC-777] `Sent`, `Minted` or `Burned` (depending on the type of movement). Third-party developers MUST be careful not to consider both events as separate movements. As a general rule, if an application considers the token as an ERC20 token, then only the `Transfer` event MUST be taken into account. @@ -1244,21 +1244,21 @@ Copyright and related rights waived via [CC0]. [operators]: #operators -[ERC20]: https://eips.ethereum.org/EIPS/eip-20 -[ERC165]: https://eips.ethereum.org/EIPS/eip-165 -[ERC672]: https://github.com/ethereum/EIPs/issues/672 -[ERC777]: https://eips.ethereum.org/EIPS/eip-777 -[ERC820]: https://eips.ethereum.org/EIPS/eip-820 +[ERC-20]: ./eip-20.md +[ERC-165]: ./eip-165.md +[ERC-672]: https://github.com/ethereum/EIPs/issues/672 +[ERC-777]: ./eip-777.md +[ERC-820]: ./eip-820.md [ERC820a]: https://github.com/ethereum/EIPs/pull/1758 -[ERC1820]: https://eips.ethereum.org/EIPS/eip-1820 -[erc1820-set]: https://eips.ethereum.org/EIPS/eip-1820#set-an-interface-for-an-address +[ERC-1820]: ./eip-1820.md +[erc1820-set]: ./eip-1820.md#set-an-interface-for-an-address [0xjac]: https://github.com/0xjac [0xjac/ERC777]: https://github.com/0xjac/ERC777 [master thesis]: https://github.com/0xjac/master-thesis [npm/erc777]: https://www.npmjs.com/package/erc777 [ref tests]: https://github.com/0xjac/ERC777/blob/master/test/ReferenceToken.test.js [reference implementation]: https://github.com/0xjac/ERC777/blob/master/contracts/examples/ReferenceToken.sol -[EIP223]: https://github.com/ethereum/EIPs/issues/223 +[EIP-223]: https://github.com/ethereum/EIPs/issues/223 [eth_estimateGas]: https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_estimategas [authorizedoperator]: #authorizedoperator diff --git a/EIPS/eip-820.md b/EIPS/eip-820.md index 0e0efd1d1671e1..15c0c5a3895c8a 100644 --- a/EIPS/eip-820.md +++ b/EIPS/eip-820.md @@ -3,7 +3,7 @@ eip: 820 title: Pseudo-introspection Registry Contract author: Jordi Baylina , Jacques Dafflon discussions-to: https://github.com/ethereum/EIPs/issues/820 -status: Superseded +status: Final type: Standards Track category: ERC requires: 165, 214 @@ -11,19 +11,19 @@ created: 2018-01-05 superseded-by: 1820 --- -> :information_source: **[ERC1820] has superseded [ERC820].** :information_source: -> [ERC1820] fixes the incompatibility in the [ERC165] logic which was introduced by the Solidty 0.5 update. +> :information_source: **[ERC-1820] has superseded [ERC-820].** :information_source: +> [ERC-1820] fixes the incompatibility in the [ERC-165] logic which was introduced by the Solidty 0.5 update. > Have a look at the [official announcement][erc1820-annoucement], and the comments about the [bug][erc820-bug] and the [fix][erc820-fix]. -> Apart from this fix, [ERC1820] is functionally equivalent to [ERC820]. +> Apart from this fix, [ERC-1820] is functionally equivalent to [ERC-820]. > -> :warning: [ERC1820] MUST be used in lieu of [ERC820]. :warning: +> :warning: [ERC-1820] MUST be used in lieu of [ERC-820]. :warning: ## Simple Summary This standard defines a universal registry smart contract where any address (contract or regular account) can register which interface it supports and which smart contract is responsible for its implementation. -This standard keeps backward compatibility with [ERC165]. +This standard keeps backward compatibility with [ERC-165]. ## Abstract @@ -33,21 +33,21 @@ Anyone can query this registry to ask if a specific address implements a given i This registry MAY be deployed on any chain and shares the same address on all chains. -Interfaces with zeroes (`0`) as the last 28 bytes are considered [ERC165] interfaces, and this registry SHALL forward the call to the contract to see if it implements the interface. +Interfaces with zeroes (`0`) as the last 28 bytes are considered [ERC-165] interfaces, and this registry SHALL forward the call to the contract to see if it implements the interface. -This contract also acts as an [ERC165] cache to reduce gas consumption. +This contract also acts as an [ERC-165] cache to reduce gas consumption. ## Motivation -There have been different approaches to define pseudo-introspection in Ethereum. The first is [ERC165] which has the limitation that it cannot be used by regular accounts. The second attempt is [ERC672] which uses reverse [ENS]. Using reverse [ENS] has two issues. First, it is unnecessarily complicated, and second, [ENS] is still a centralized contract controlled by a multisig. This multisig theoretically would be able to modify the system. +There have been different approaches to define pseudo-introspection in Ethereum. The first is [ERC-165] which has the limitation that it cannot be used by regular accounts. The second attempt is [ERC-672] which uses reverse [ENS]. Using reverse [ENS] has two issues. First, it is unnecessarily complicated, and second, [ENS] is still a centralized contract controlled by a multisig. This multisig theoretically would be able to modify the system. -This standard is much simpler than [ERC672], and it is *fully* decentralized. +This standard is much simpler than [ERC-672], and it is *fully* decentralized. This standard also provides a *unique* address for all chains. Thus solving the problem of resolving the correct registry address for different chains. ## Specification -### [ERC820] Registry Smart Contract +### [ERC-820] Registry Smart Contract > This is an exact copy of the code of the [ERC820 registry smart contract]. @@ -283,7 +283,7 @@ The strings of `820`'s at the end of the transaction are the `r` and `s` of the This contract is going to be deployed using the keyless deployment method---also known as [Nick]'s method---which relies on a single-use address. (See [Nick's article] for more details). This method works as follows: 1. Generate a transaction which deploys the contract from a new random account. - - This transaction MUST NOT use [EIP155] in order to work on any chain. + - 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. Set the `v`, `r`, `s` of the transaction signature to the following values: @@ -658,7 +658,7 @@ The contract has the address above for every chain on which it is deployed. Any interface name is hashed using `keccak256` and sent to `getInterfaceImplementer()`. -If the interface is part of a standard, it is best practice to explicitly state the interface name and link to this published [ERC820] such that other people don't have to come here to look up these rules. +If the interface is part of a standard, it is best practice to explicitly state the interface name and link to this published [ERC-820] such that other people don't have to come here to look up these rules. For convenience, the registry provides a function to compute the hash on-chain: @@ -684,47 +684,47 @@ Examples: - `keccak256("ERC777TokensSender")` - `keccak256("ERC777TokensRecipient")` -#### **[ERC165] Compatible Interfaces** +#### **[ERC-165] Compatible Interfaces** -> The compatibility with [ERC165], including the [ERC165 Cache], has been designed and developed with [William Entriken]. +> The compatibility with [ERC-165], including the [ERC165 Cache], has been designed and developed with [William Entriken]. -Any interface where the last 28 bytes are zeroes (`0`) SHALL be considered an [ERC165] interface. +Any interface where the last 28 bytes are zeroes (`0`) SHALL be considered an [ERC-165] interface. -**[ERC165] Lookup** +**[ERC-165] Lookup** -Anyone can explicitly check if a contract implements an [ERC165] interface using the registry by calling one of the two functions below: +Anyone can explicitly check if a contract implements an [ERC-165] interface using the registry by calling one of the two functions below: ``` solidity function implementsERC165Interface(address _contract, bytes4 _interfaceId) public view returns (bool) ``` -Checks whether a contract implements an [ERC165] interface or not. +Checks whether a contract implements an [ERC-165] interface or not. *NOTE*: The result is cached. If the cache is out of date, it MUST be updated by calling `updateERC165Cache`. (See [ERC165 Cache] for more details.) > **identifier:** `f712f3e8` > **parameters** > `_contract`: Address of the contract to check. -> `_interfaceId`: [ERC165] interface to check. +> `_interfaceId`: [ERC-165] interface to check. > **returns:** `true` if `_contract` implements `_interfaceId`, false otherwise. ``` solidity function implementsERC165InterfaceNoCache(address _contract, bytes4 _interfaceId) public view returns (bool) ``` -Checks whether a contract implements an [ERC165] interface or not without using nor updating the cache. +Checks whether a contract implements an [ERC-165] interface or not without using nor updating the cache. > **identifier:** `b7056765` > **parameters** > `_contract`: Address of the contract to check. -> `_interfaceId`: [ERC165] interface to check. +> `_interfaceId`: [ERC-165] interface to check. > **returns:** `true` if `_contract` implements `_interfaceId`, false otherwise. -**[ERC165] Cache** +**[ERC-165] Cache** -Whether a contract implements an [ERC165] interface or not can be cached manually to save gas. +Whether a contract implements an [ERC-165] interface or not can be cached manually to save gas. -If a contract dynamically changes its interface and relies on the [ERC165] cache of the [ERC820] registry, the cache MUST be updated manually---there is no automatic cache invalidation or cache update. Ideally the contract SHOULD automatically update the cache when changing its interface. However anyone MAY update the cache on the contract's behalf. +If a contract dynamically changes its interface and relies on the [ERC-165] cache of the [ERC-820] registry, the cache MUST be updated manually---there is no automatic cache invalidation or cache update. Ideally the contract SHOULD automatically update the cache when changing its interface. However anyone MAY update the cache on the contract's behalf. The cache update MUST be done using the `updateERC165Cache` function: @@ -735,7 +735,7 @@ function updateERC165Cache(address _contract, bytes4 _interfaceId) public > **identifier:** `a41e7d51` > **parameters** > `_contract`: Address of the contract for which to update the cache. -> `_interfaceId`: [ERC165] interface for which to update the cache. +> `_interfaceId`: [ERC-165] interface for which to update the cache. #### **Private User-defined Interfaces** @@ -743,7 +743,7 @@ This scheme is extensible. You MAY make up your own interface name and raise awa ### Set An Interface For An Address -For any address to set a contract as the interface implementation, it must call the following function of the [ERC820] registry: +For any address to set a contract as the interface implementation, it must call the following function of the [ERC-820] registry: ``` solidity function setInterfaceImplementer(address _addr, bytes32 _interfaceHash, address _implementer) public @@ -758,7 +758,7 @@ Only the `manager` defined for that address can set it. (Each address is the man - The `_implementer` MUST implement the `ERC820ImplementerInterface` (detailed below). - Calling `canImplementInterfaceForAddress` on `_implementer` with the given `_addr` and `_interfaceHash` MUST return the `ERC820_ACCEPT_MAGIC` value. -*NOTE*: The `_interfaceHash` MUST NOT be an [ERC165] interface---it MUST NOT end with 28 zeroes (`0`). +*NOTE*: The `_interfaceHash` MUST NOT be an [ERC-165] interface---it MUST NOT end with 28 zeroes (`0`). *NOTE*: The `_addr` MAY be `0`, then `msg.sender` is assumed. This default value simplifies interactions via multisigs where the data of the transaction to sign is constant regardless of the address of the multisig instance. @@ -770,7 +770,7 @@ Only the `manager` defined for that address can set it. (Each address is the man ### Get An Implementation Of An Interface For An Address -Anyone MAY query the [ERC820] Registry to obtain the address of a contract implementing an interface on behalf of some address using the `getInterfaceImplementer` function. +Anyone MAY query the [ERC-820] Registry to obtain the address of a contract implementing an interface on behalf of some address using the `getInterfaceImplementer` function. ``` solidity function getInterfaceImplementer(address _addr, bytes32 _interfaceHash) public view returns (address) @@ -778,7 +778,7 @@ function getInterfaceImplementer(address _addr, bytes32 _interfaceHash) public v Query if an address implements an interface and through which contract. -*NOTE*: If the last 28 bytes of the `_interfaceHash` are zeroes (`0`), then the first 4 bytes are considered an [ERC165] interface and the registry SHALL forward the call to the contract at `_addr` to see if it implements the [ERC165] interface (the first 4 bytes of `_interfaceHash`). The registry SHALL also cache [ERC165] queries to reduce gas consumption. Anyone MAY call the `erc165UpdateCache` function to update whether a contract implements an interface or not. +*NOTE*: If the last 28 bytes of the `_interfaceHash` are zeroes (`0`), then the first 4 bytes are considered an [ERC-165] interface and the registry SHALL forward the call to the contract at `_addr` to see if it implements the [ERC-165] interface (the first 4 bytes of `_interfaceHash`). The registry SHALL also cache [ERC-165] queries to reduce gas consumption. Anyone MAY call the `erc165UpdateCache` function to update whether a contract implements an interface or not. *NOTE*: The `_addr` MAY be `0`, then `msg.sender` is assumed. This default value is consistent with the behavior of the `setInterfaceImplementer` function and simplifies interactions via multisigs where the data of the transaction to sign is constant regardless of the address of the multisig instance. @@ -865,13 +865,13 @@ Get the manager of an address. This standards offers a way for any type of address (externally owned and contracts) to implement an interface and potentially delegate the implementation of the interface to a proxy contract. This delegation to a proxy contract is necessary for externally owned accounts and useful to avoid redeploying existing contracts such as multisigs and DAOs. -The registry can also act as a [ERC165] cache in order to save gas when looking up if a contract implements a specific [ERC165] interface. This cache is intentionally kept simple, without automatic cache update or invalidation. Anyone can easily and safely update the cache for any interface and any contract by calling the `updateERC165Cache` function. +The registry can also act as a [ERC-165] cache in order to save gas when looking up if a contract implements a specific [ERC-165] interface. This cache is intentionally kept simple, without automatic cache update or invalidation. Anyone can easily and safely update the cache for any interface and any contract by calling the `updateERC165Cache` function. The registry is deployed using a keyless deployment method relying on a single-use deployment address to ensure no one controls the registry, thereby ensuring trust. ## Backward Compatibility -This standard is backward compatible with [ERC165], as both methods MAY be implemented without conflicting with each other. +This standard is backward compatible with [ERC-165], as both methods MAY be implemented without conflicting with each other. ## Test Cases @@ -884,10 +884,10 @@ The implementation is available in the repo: [jbaylina/ERC820]. ## Copyright Copyright and related rights waived via [CC0]. -[EIP155]: https://eips.ethereum.org/EIPS/eip-155 -[ERC165]: https://eips.ethereum.org/EIPS/eip-165 -[ERC672]: https://github.com/ethereum/EIPs/issues/672 -[ERC820]: https://eips.ethereum.org/EIPS/eip-820 +[EIP-155]: ./eip-155.md +[ERC-165]: ./eip-165.md +[ERC-672]: https://github.com/ethereum/EIPs/issues/672 +[ERC-820]: ./eip-820.md [ERC820 registry smart contract]: https://github.com/jbaylina/ERC820/blob/master/contracts/ERC820Registry.sol [manager]: #manager [lookup]: #get-an-implementation-of-an-interface-for-an-address @@ -898,7 +898,7 @@ Copyright and related rights waived via [CC0]. [Nick]: https://github.com/Arachnid/ [William Entriken]: https://github.com/fulldecent [ENS]: https://ens.domains/ -[ERC1820]: https://eips.ethereum.org/EIPS/eip-1820 +[ERC-1820]: ./eip-1820.md [erc1820-annoucement]: https://github.com/ethereum/EIPs/issues/820#issuecomment-464109166 [erc820-bug]: https://github.com/ethereum/EIPs/issues/820#issuecomment-452465748 [erc820-fix]: https://github.com/ethereum/EIPs/issues/820#issuecomment-454021564 diff --git a/EIPS/eip-831.md b/EIPS/eip-831.md index 59d0741c15604a..12f00ef58df4b7 100644 --- a/EIPS/eip-831.md +++ b/EIPS/eip-831.md @@ -39,8 +39,8 @@ The need for this ERC emerged when refining ERC-681. We need a container that do ## References -1. ERC-681, https://eips.ethereum.org/EIPS/eip-681 -2. ERC-67, https://github.com/ethereum/EIPs/issues/67 +1. ERC-681, ./eip-681.md +2. ERC-67, ./eip-67.md ## Copyright diff --git a/EIPS/eip-868.md b/EIPS/eip-868.md index 9f71c55c7a9077..921cb420b39595 100644 --- a/EIPS/eip-868.md +++ b/EIPS/eip-868.md @@ -14,7 +14,7 @@ discussions-to: https://github.com/ethereum/devp2p/issues/44 # Abstract This EIP defines an extension to Node Discovery Protocol v4 to enable authoritative -resolution of [Ethereum Node Records (ENR)](https://eips.ethereum.org/EIPS/eip-778). +resolution of [Ethereum Node Records (ENR)](./eip-778.md). # Motivation diff --git a/EIPS/eip-875.md b/EIPS/eip-875.md index 2bef286af33e64..4673c5584607df 100644 --- a/EIPS/eip-875.md +++ b/EIPS/eip-875.md @@ -3,7 +3,7 @@ eip: 875 title: Simpler NFT standard with batching and native atomic swaps author: Weiwu Zhang , James Sangalli discussions-to: https://github.com/ethereum/EIPs/issues/875 -status: Abandoned +status: Withdrawn review-period-end: 2019-07-29 type: Standards Track category: ERC diff --git a/EIPS/eip-908.md b/EIPS/eip-908.md index f2a649d372c515..3f53cff6a08835 100644 --- a/EIPS/eip-908.md +++ b/EIPS/eip-908.md @@ -3,7 +3,7 @@ eip: 908 title: Reward clients for a sustainable network author: James Ray (@jamesray1), Micah Zoltu (@MicahZoltu) discussions-to: https://ethereum-magicians.org/t/eip-908-reward-full-nodes-and-clients/241 -status: Abandoned +status: Withdrawn type: Standards Track category: Core created: 2018-03-01 @@ -22,7 +22,7 @@ The tragedy of the commons is a phenomenon that is well known in many sectors, m Reward mechanisms that are external to being built in to the protocol are beyond the scope of this EIP. Such extra-protocol reward methods include state channel payments for extra services such as light client servers providing faster information such as receipts; state channel payments for buying state reads from full nodes; archival services (which is only applicable to future proposed versions of Ethereum with stateless clients); and tokens for the client and running full nodes. ## Motivation -Currently there is a lack of incentives for anyone to run a full node, while joining a mining pool is not really economical if one has to purchase a mining rig (several GPUs) now, since there is unlikely to be a return on investment by the time that Ethereum transitions to hybrid Proof-of-Work/Proof-of-Stake with [Casper FFG](https://eips.ethereum.org/EIPS/eip-1011), then full PoS with [CBC Casper](https://github.com/ethereum/research/blob/master/papers/CasperTFG/CasperTFG.pdf). +Currently there is a lack of incentives for anyone to run a full node, while joining a mining pool is not really economical if one has to purchase a mining rig (several GPUs) now, since there is unlikely to be a return on investment by the time that Ethereum transitions to hybrid Proof-of-Work/Proof-of-Stake with [Casper FFG](./eip-1011.md), then full PoS with [CBC Casper](https://github.com/ethereum/research/blob/master/papers/CasperTFG/CasperTFG.pdf). Additionally, providing a reward for clients gives a revenue stream that is independent of state channels or other layer 2 mechanisms, which are less secure, although this insecurity can be offset by mechanisms such as insurance, bonded payments and time locks. Rationalising that investors may invest in a client because it is an enabler for the Ethereum ecosystem (and thus opening up investment opportunities) may not scale very well, and it seems that it is more sustainable to monetize the client as part of the service(s) that it provides. @@ -40,7 +40,7 @@ Implementing this as a layer 2 solution may not ensure the sustainability of the Not providing incentives for clients is an issue now as there is less incentive to build a client that aligns with the needs of users, funds need to be raised externally to the protocol to fund client development, which is not as decentralized. If only a smaller subset is able to fund client development, such as VCs, angel investors and institutional investors, that may not align well with the interests of all current and potential stakeholders of Ethereum (which includes future stakeholders). Ostensibly, one of the goals of Ethereum is to decentralize everything, including wealth, or in other words, to improve wealth equality. Not providing incentives for full nodes validating transactions may not seem like as much of an issue now, but not doing so could hinder the growth of the protocol. Of course, incentives aren't enough, it also needs to be technically decentralized so that it is ideally possible for a low-end mainstream computer or perhaps even a mobile or embedded IoT device to be a verifying full node, or at least to be able to help with securing the network if it is deemed impractical for them to be a full node. -Note that with a supply cap (as in [EIP 960](https://github.com/ethereum/EIPs/issues/960), the issuance can be prevented from increasing indefinitely. Alternatively, it could at least be reduced (still potentially but not necessarily to zero, or to the same rate at which Ether is burnt when slashing participants, such as validators under a Casper PoS scheme or notaries under a sharding scheme), e.g. by hard forks, or as per [EIP 1015](https://eips.ethereum.org/EIPS/eip-1015), an on-chain contract governed by a decision assembly that gets signalling from other contracts that represent some set of stakeholders. +Note that with a supply cap (as in [EIP-960](https://github.com/ethereum/EIPs/issues/960), the issuance can be prevented from increasing indefinitely. Alternatively, it could at least be reduced (still potentially but not necessarily to zero, or to the same rate at which Ether is burnt when slashing participants, such as validators under a Casper PoS scheme or notaries under a sharding scheme), e.g. by hard forks, or as per [EIP-1015](./eip-1015.md), an on-chain contract governed by a decision assembly that gets signalling from other contracts that represent some set of stakeholders. ## Specification Add a new field to each block called `PrevBlockVerifications`, which is an arbitrary, unlimited size byte array. When a client verifies that a previous block is [valid](https://ethereum.github.io/yellowpaper/paper.pdf#subsubsection.4.3.2), the client appends a user agent to PrevBlockVerifications via an opcode in a transaction, PREV_BLOCK_VERIF. The user agent is a vector with the immutable fields: the blockhash of the block that is validated, and the index of a client address in an access list (details are below). A miner validates a transaction before including it in a block, however they are not able to change these fields of the vector because they're immutable. @@ -55,7 +55,7 @@ A miner could create a client and fill their block with transactions that only c ### More details on the access list -The access list prevents anyone inserting any address to the first element of the vector, where there may be a way to prevent censorship and centralization of authority of who decides to register new addresses in the list, e.g. on-chain governance with signalling (possibly similar to [EIP 1015](https://eips.ethereum.org/EIPS/eip-1015), which also specifies an alternative way of sending funds) or a layer 2 proof of authority network where new addresses can be added via a smart contract. Note that there may be serious drawbacks to implementing either of these listed examples. There is a refutation of [on-chain governance](https://medium.com/@Vlad_Zamfir/against-on-chain-governance-a4ceacd040ca) as well as of [plutocracy](https://vitalik.ca/general/2018/03/28/plutocracy.html). [Proof of Authority](https://en.wikipedia.org/wiki/Proof-of-authority) isn't suitable for a public network since it doesn't distribute trust well. However, using signalling in layer 2 contracts is more acceptable, but Vlad Zamfir argues that using that to influence outcomes in the protocol can disenfranchise miners from being necessary participants in the governance process. Thus, in light of these counterpoints, having an access list may not be suitable until a decentralized, trustless way of maintaining it is implemented and ideally accepted by the majority of a random sample that represents the population of Ethereum users. +The access list prevents anyone inserting any address to the first element of the vector, where there may be a way to prevent censorship and centralization of authority of who decides to register new addresses in the list, e.g. on-chain governance with signalling (possibly similar to [EIP-1015](./eip-1015.md), which also specifies an alternative way of sending funds) or a layer 2 proof of authority network where new addresses can be added via a smart contract. Note that there may be serious drawbacks to implementing either of these listed examples. There is a refutation of [on-chain governance](https://medium.com/@Vlad_Zamfir/against-on-chain-governance-a4ceacd040ca) as well as of [plutocracy](https://vitalik.ca/general/2018/03/28/plutocracy.html). [Proof of Authority](https://en.wikipedia.org/wiki/Proof-of-authority) isn't suitable for a public network since it doesn't distribute trust well. However, using signalling in layer 2 contracts is more acceptable, but Vlad Zamfir argues that using that to influence outcomes in the protocol can disenfranchise miners from being necessary participants in the governance process. Thus, in light of these counterpoints, having an access list may not be suitable until a decentralized, trustless way of maintaining it is implemented and ideally accepted by the majority of a random sample that represents the population of Ethereum users. However, another alternative to managing the access list would be to have decentralized verification that the address produced from querying an index in the access list does correspond to that of a "legitimate" client. Part of this verification would involve checking that there is a client that claims that this address is owned by them, that they are happy to receive funds in this manner and agree or arranged to putting the address in the access list, and that the client passes all tests in the [Ethereum test suite](https://github.com/ethereum/tests). However, this last proviso would then preclude new clients being funded from the start of development, although such would-be clients would not be able to receive funds in-protocol until they implement the client anyway (as an aside, they could raise funds in various ways—a DAII, pronounced die-yee, is recommended, while a platform for DAIIs is under development by [Dogezer](https://dogezer.com/)). All of this could be done off-chain, and if anyone found that some address in the access list was not legitimate, then they could challenge that address with a proof of illegitimacy, and the participant that submitted the address to the access list could be slashed (while they must hold a deposit in order to register and keep an address in the access list). diff --git a/EIPS/eip-926.md b/EIPS/eip-926.md index 1fe66569af2884..172f11d8452101 100644 --- a/EIPS/eip-926.md +++ b/EIPS/eip-926.md @@ -38,7 +38,7 @@ Providers have one mandatory function: function supportsInterface(bytes4 interfaceID) constant returns (bool) ``` -The `supportsInterface` function is documented in [EIP 165](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md), and returns true if the provider implements the interface specified by the provided 4 byte identifier. An interface identifier consists of the XOR of the function signature hashes of the functions provided by that interface; in the degenerate case of single-function interfaces, it is simply equal to the signature hash of that function. If a provider returns `true` for `supportsInterface()`, it must implement the functions specified in that interface. +The `supportsInterface` function is documented in [EIP-165](./eip-165.md), and returns true if the provider implements the interface specified by the provided 4 byte identifier. An interface identifier consists of the XOR of the function signature hashes of the functions provided by that interface; in the degenerate case of single-function interfaces, it is simply equal to the signature hash of that function. If a provider returns `true` for `supportsInterface()`, it must implement the functions specified in that interface. `supportsInterface` must always return true for `0x01ffc9a7`, which is the interface ID of `supportsInterface` itself. diff --git a/EIPS/eip-998.md b/EIPS/eip-998.md index 6eaf40ffb53018..c4cd113c9264e3 100644 --- a/EIPS/eip-998.md +++ b/EIPS/eip-998.md @@ -11,9 +11,9 @@ requires: 165, 721 --- ## Simple Summary -An extension of the [ERC721 standard](https://eips.ethereum.org/EIPS/eip-721) to enable ERC721 tokens to own other ERC721 tokens and ERC20 tokens. +An extension of the [ERC-721 standard](./eip-721.md) to enable ERC721 tokens to own other ERC721 tokens and ERC20 tokens. -An extension of the [ERC20](https://eips.ethereum.org/EIPS/eip-20) and [ERC223](https://github.com/ethereum/EIPs/issues/223) standards to enable ERC20 and ERC223 tokens to be owned by ERC721 tokens. +An extension of the [ERC-20](./eip-20.md) and [ERC-223](https://github.com/ethereum/EIPs/issues/223) standards to enable ERC20 and ERC223 tokens to be owned by ERC721 tokens. This specification covers four different kinds of composable tokens: @@ -48,15 +48,15 @@ A non-fungible token is ERC998 compliant and is an ERC998 Composable if it imple ### ERC721 -ERC998ERC721 top-down, ERC998ERC20 top-down, and ERC998ERC721 bottom-up composable contracts must implement the [ERC721 interface](https://eips.ethereum.org/EIPS/eip-721). +ERC998ERC721 top-down, ERC998ERC20 top-down, and ERC998ERC721 bottom-up composable contracts must implement the [ERC-721 interface](./eip-721.md). ### ERC20 -ERC998ERC20 bottom-up composable contracts must implement the [ERC20 interface](https://eips.ethereum.org/EIPS/eip-20). +ERC998ERC20 bottom-up composable contracts must implement the [ERC-20 interface](./eip-20.md). ### ERC165 -The [ERC165 standard](https://eips.ethereum.org/EIPS/eip-165) must be applied to each ERC998 interface that is used. +The [ERC-165 standard](./eip-165.md) must be applied to each ERC998 interface that is used. ### Authentication diff --git a/EIPS/eip-999.md b/EIPS/eip-999.md index 946cc8b5fbae42..5300e8969b4dc1 100644 --- a/EIPS/eip-999.md +++ b/EIPS/eip-999.md @@ -3,7 +3,7 @@ eip: 999 title: Restore Contract Code at 0x863DF6BFa4469f3ead0bE8f9F2AAE51c91A907b4 author: Afri Schoedon (@5chdn) discussions-to: https://ethereum-magicians.org/t/eip-999-restore-contract-code-at-0x863df6bfa4/130 -status: Abandoned +status: Withdrawn type: Standards Track category: Core created: 2018-04-04 diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md index f18eb4fd1e988e..61f357858bf11c 100644 --- a/ISSUE_TEMPLATE.md +++ b/ISSUE_TEMPLATE.md @@ -3,7 +3,7 @@ ATTENTION! If you would like to submit an EIP and it has already been written as If you are considering a proposal but would like to get some feedback on the idea before submitting a draft, then continue opening an Issue as a thread for discussion. Note that the more clearly and completely you state your idea the higher the quality of the feedback you are likely to receive. -Keep in mind the following guidelines from [EIP-1](https://eips.ethereum.org/EIPS/eip-1): +Keep in mind the following guidelines from [EIP-1](./eip-1.md): > Each EIP must have a champion - someone who writes the EIP using the style and format described below, shepherds the discussions in the appropriate forums, and attempts to build community consensus around the idea. The EIP champion (a.k.a. Author) should first attempt to ascertain whether the idea is EIP-able. Posting to the the Protocol Discussion forum or opening an Issue is the best way to go about this. diff --git a/README.md b/README.md index 9fb968b9b0c519..8532e6c1f83e37 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ This repository tracks the ongoing status of EIPs. It contains: - [Last Call](https://eips.ethereum.org/all#last-call) for proposals that may become final (see also [RSS feed](https://eips.ethereum.org/last-call.xml)). - [Accepted](https://eips.ethereum.org/all#accepted) proposals which are awaiting implementation or deployment by Ethereum client developers. - [Final](https://eips.ethereum.org/all#final) and [Active](https://eips.ethereum.org/all#active) proposals that are recorded. -- The [EIP process](EIPS/eip-1.md#eip-work-flow) that governs the EIP repository. +- The [EIP process](./EIPS/eip-1.md#eip-work-flow) that governs the EIP repository. Achieving "Final" status in this repository only represents that a proposal has been reviewed for technical accuracy. It is solely the responsibility of the reader to decide whether a proposal will be useful to them. @@ -28,6 +28,10 @@ The Ethereum Improvement Proposals repository exists as a place to share concret The canonical URL for a EIP that has achieved draft status at any point is at https://eips.ethereum.org/. For example, the canonical URL for EIP-1 is https://eips.ethereum.org/EIPS/eip-1. +Please consider anything which is not published on https://eips.ethereum.org/ as a working paper. + +And please consider anything published at https://eips.ethereum.org/ with a status of "draft" as an incomplete draft. + # Validation EIPs must pass some validation tests. The EIP repository ensures this by running tests using [html-proofer](https://rubygems.org/gems/html-proofer) and [eip_validator](https://rubygems.org/gems/eip_validator). diff --git a/_data/statuses.yaml b/_data/statuses.yaml index 78c8d10f4cb854..7d499fae8e6f87 100644 --- a/_data/statuses.yaml +++ b/_data/statuses.yaml @@ -1,8 +1,7 @@ +- Living +- Final - Last Call +- Review - Draft -- Accepted -- Final -- Active -- Abandoned -- Rejected -- Superseded +- Stagnant +- Withdrawn diff --git a/_includes/anchor_headings.html b/_includes/anchor_headings.html new file mode 100644 index 00000000000000..8126b2515b0363 --- /dev/null +++ b/_includes/anchor_headings.html @@ -0,0 +1,109 @@ +{% capture headingsWorkspace %} +{% comment %} + Version 1.0.5 + https://github.com/allejo/jekyll-anchor-headings + + "Be the pull request you wish to see in the world." ~Ben Balter + + Usage: + {% include anchor_headings.html html=content %} + + Parameters: + * html (string) - the HTML of compiled markdown generated by kramdown in Jekyll + + Optional Parameters: + * beforeHeading (bool) : false - Set to true if the anchor should be placed _before_ the heading's content + * anchorAttrs (string) : '' - Any custom HTML attributes that will be added to the `` tag; you may NOT use `href`, `class` or `title` + * anchorBody (string) : '' - The content that will be placed inside the anchor; the `%heading%` placeholder is available + * anchorClass (string) : '' - The class(es) that will be used for each anchor. Separate multiple classes with a space + * anchorTitle (string) : '' - The `title` attribute that will be used for anchors + * h_min (int) : 1 - The minimum header level to build an anchor for; any header lower than this value will be ignored + * h_max (int) : 6 - The maximum header level to build an anchor for; any header greater than this value will be ignored + * bodyPrefix (string) : '' - Anything that should be inserted inside of the heading tag _before_ its anchor and content + * bodySuffix (string) : '' - Anything that should be inserted inside of the heading tag _after_ its anchor and content + + Output: + The original HTML with the addition of anchors inside of all of the h1-h6 headings. +{% endcomment %} + +{% assign minHeader = include.h_min | default: 1 %} +{% assign maxHeader = include.h_max | default: 6 %} +{% assign beforeHeading = include.beforeHeading %} +{% assign nodes = include.html | split: ' + {% if headerLevel == 0 %} + + {% assign firstChunk = node | split: '>' | first %} + + + {% unless firstChunk contains '<' %} + {% capture node %}' | first }}>{% endcapture %} + {% assign header = _workspace[0] | replace: _hAttrToStrip, '' %} + + + {% capture anchor %}{% endcapture %} + + {% if html_id and headerLevel >= minHeader and headerLevel <= maxHeader %} + {% capture anchor %}href="#{{ html_id }}"{% endcapture %} + + {% if include.anchorClass %} + {% capture anchor %}{{ anchor }} class="{{ include.anchorClass }}"{% endcapture %} + {% endif %} + + {% if include.anchorTitle %} + {% capture anchor %}{{ anchor }} title="{{ include.anchorTitle | replace: '%heading%', header }}"{% endcapture %} + {% endif %} + + {% if include.anchorAttrs %} + {% capture anchor %}{{ anchor }} {{ include.anchorAttrs }}{% endcapture %} + {% endif %} + + {% capture anchor %}{{ include.anchorBody | replace: '%heading%', header | default: '' }}{% endcapture %} + + + {% if beforeHeading %} + {% capture anchor %}{{ anchor }} {% endcapture %} + {% else %} + {% capture anchor %} {{ anchor }}{% endcapture %} + {% endif %} + {% endif %} + + {% capture new_heading %} + maxHeader %} + {% continue %} + {% endif %} + + {% if firstHeader %} + {% assign firstHeader = false %} + {% assign minHeader = headerLevel %} + {% endif %} + + {% assign indentAmount = headerLevel | minus: minHeader %} + {% assign _workspace = node | split: '' | first }}>{% endcapture %} + {% assign header = _workspace[0] | replace: _hAttrToStrip, '' %} + + {% assign space = '' %} + {% for i in (1..indentAmount) %} + {% assign space = space | prepend: ' ' %} + {% endfor %} + + {% if include.item_class and include.item_class != blank %} + {% capture listItemClass %}{:.{{ include.item_class | replace: '%level%', headerLevel }}}{% endcapture %} + {% endif %} + + {% capture heading_body %}{% if include.sanitize %}{{ header | strip_html }}{% else %}{{ header }}{% endif %}{% endcapture %} + {% capture my_toc %}{{ my_toc }} +{{ space }}{{ listModifier }} {{ listItemClass }} [{{ heading_body | replace: "|", "\|" }}]({% if include.baseurl %}{{ include.baseurl }}{% endif %}#{{ html_id }}){% if include.anchor_class %}{:.{{ include.anchor_class }}}{% endif %}{% endcapture %} +{% endfor %} + +{% if include.class and include.class != blank %} + {% capture my_toc %}{:.{{ include.class }}} +{{ my_toc | lstrip }}{% endcapture %} +{% endif %} + +{% if include.id %} + {% capture my_toc %}{: #{{ include.id }}} +{{ my_toc | lstrip }}{% endcapture %} +{% endif %} +{% endcapture %}{% assign tocWorkspace = '' %}{{ my_toc | markdownify | strip }} diff --git a/_layouts/eip.html b/_layouts/eip.html index 5f827a8c5ef4a4..1a7bdd661e9d92 100644 --- a/_layouts/eip.html +++ b/_layouts/eip.html @@ -39,7 +39,12 @@

{% endif %}

- {{ content }} +
+

Table of Contents

+ {% include toc.html html=content sanitize=true h_max=3 %} +
+ + {% include anchor_headings.html html=content anchorClass="anchor-link" beforeHeading=true %}

Citation

Please cite this document as:

diff --git a/assets/css/style.scss b/assets/css/style.scss index 5654c2bbb956ee..832a320b41d59c 100644 --- a/assets/css/style.scss +++ b/assets/css/style.scss @@ -2,4 +2,22 @@ # Only the main Sass file needs front matter (the dashes are enough) --- -@import "minima"; \ No newline at end of file +@import 'minima'; + +.page-content { + a.anchor-link { + width: 16px; + height: 16px; + display: inline-block; + margin-left: -22px; + &:hover { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' class='anchor-link-icon' viewBox='0 0 16 16' version='1.1' width='16' height='16' aria-hidden='true'%3E%3Cpath fill-rule='evenodd' d='M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z'%3E%3C/path%3E%3C/svg%3E"); + } + } +} + +main.page-content { + div.wrapper { + max-width: calc(1280px - (30px * 2)); + } +} diff --git a/assets/eip-1/EIP-process.png b/assets/eip-1/EIP-process.png new file mode 100644 index 00000000000000..e3d7a60d57458d Binary files /dev/null and b/assets/eip-1/EIP-process.png differ diff --git a/assets/eip-2565/Complexity_Regression.png b/assets/eip-2565/Complexity_Regression.png index 236f9dc35d31f6..059671bbecf6fe 100644 Binary files a/assets/eip-2565/Complexity_Regression.png 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 index 92914f002e369b..53bb641124b985 100644 Binary files a/assets/eip-2565/GQuad_Change.png 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 deleted file mode 100644 index fa9c9235546c6c..00000000000000 Binary files a/assets/eip-2565/Library_Benchmarks.png and /dev/null differ diff --git a/assets/eip-2678/package.spec.json b/assets/eip-2678/package.spec.json new file mode 100644 index 00000000000000..f78790e505751c --- /dev/null +++ b/assets/eip-2678/package.spec.json @@ -0,0 +1,483 @@ +{ + "title": "Package Manifest", + "description": "EthPM Manifest Specification", + "type": "object", + "required": [ + "manifest" + ], + "version": "3", + "not": { + "required": ["manifest_version"] + }, + "properties": { + "manifest": { + "type": "string", + "title": "Manifest", + "description": "EthPM Manifest Version", + "default": "ethpm/3", + "enum": ["ethpm/3"] + }, + "name": { + "$ref": "#/definitions/PackageName" + }, + "version": { + "title": "Package Version", + "description": "The version of the package that this release is for", + "type": "string" + }, + "meta": { + "$ref": "#/definitions/PackageMeta" + }, + "sources": { + "title": "Sources", + "description": "The source files included in this release", + "type": "object", + "patternProperties": { + ".*": { + "$ref": "#/definitions/Source" + } + } + }, + "compilers": { + "title": "Compilers", + "description": "The compiler versions used in this release", + "type": "array", + "items": { + "$ref": "#/definitions/CompilerInformation" + } + }, + "contractTypes": { + "title": "Contract Types", + "description": "The contract types included in this release", + "type": "object", + "propertyNames": { + "$ref": "#/definitions/ContractTypeName" + }, + "patternProperties": { + "": { + "$ref": "#/definitions/ContractType" + } + } + }, + "deployments": { + "title": "Deployments", + "description": "The deployed contract instances in this release", + "type": "object", + "propertyNames": { + "$ref": "#/definitions/BlockchainURI" + }, + "patternProperties": { + "": { + "$ref": "#/definitions/Deployment" + } + } + }, + "buildDependencies": { + "title": "Build Dependencies", + "type": "object", + "propertyNames": { + "$ref": "#/definitions/PackageName" + }, + "patternProperties": { + "": { + "$ref": "#/definitions/ContentURI" + } + } + } + }, + "definitions": { + "Source": { + "title": "Source", + "description": "Information about a source file included in this package", + "type": "object", + "anyOf": [ + {"required": ["content"]}, + {"required": ["urls"]} + ], + "properties": { + "checksum": { + "$ref": "#/definitions/ChecksumObject" + }, + "urls": { + "title": "URLs", + "description": "Array of urls that resolve to the source file", + "type": "array", + "items": { + "$ref": "#/definitions/ContentURI" + } + }, + "content": { + "title": "Inlined source code", + "type": "string" + }, + "installPath": { + "title": "Target file path to install source file", + "type": "string", + "pattern": "^\\.\\/.*$" + }, + "type": { + "title": "Type", + "description": "File type of this source", + "type": "string" + }, + "license": { + "title": "License", + "description": "The license associated with the source file", + "type": "string" + } + } + }, + "PackageMeta": { + "title": "Package Meta", + "description": "Metadata about the package", + "type": "object", + "properties": { + "authors": { + "title": "Authors", + "description": "Authors of this package", + "type": "array", + "items": { + "type": "string" + } + }, + "license": { + "title": "License", + "description": "The license that this package and its source are released under", + "type": "string" + }, + "description": { + "title": "Description", + "description": "Description of this package", + "type": "string" + }, + "keywords": { + "title": "Keywords", + "description": "Keywords that apply to this package", + "type": "array", + "items": { + "type": "string" + } + }, + "links": { + "title": "Links", + "descriptions": "URIs for resources related to this package", + "type": "object", + "additionalProperties": { + "type": "string", + "format": "uri" + } + } + } + }, + "PackageName": { + "title": "Package Name", + "description": "The name of the package that this release is for", + "type": "string", + "pattern": "^[a-z][-a-z0-9]{0,255}$" + }, + "ContractType": { + "title": "Contract Type", + "description": "Data for a contract type included in this package", + "type": "object", + "properties":{ + "contractName": { + "$ref": "#/definitions/ContractTypeName" + }, + "sourceId": { + "title": "Source ID", + "description": "The source ID that corresponds to this contract type", + "type": "string" + }, + "deploymentBytecode": { + "$ref": "#/definitions/BytecodeObject" + }, + "runtimeBytecode": { + "$ref": "#/definitions/BytecodeObject" + }, + "abi": { + "title": "ABI", + "description": "The ABI for this contract type", + "type": "array" + }, + "devdoc": { + "title": "Devdoc", + "description": "The dev-doc for this contract", + "type": "object" + }, + "userdoc": { + "title": "Userdoc", + "description": "The user-doc for this contract", + "type": "object" + } + } + }, + "ContractInstance": { + "title": "Contract Instance", + "description": "Data for a deployed instance of a contract", + "type": "object", + "required": [ + "contractType", + "address" + ], + "properties": { + "contractType": { + "anyOf": [ + {"$ref": "#/definitions/ContractTypeName"}, + {"$ref": "#/definitions/NestedContractTypeName"} + ] + }, + "address": { + "$ref": "#/definitions/Address" + }, + "transaction": { + "$ref": "#/definitions/TransactionHash" + }, + "block": { + "$ref": "#/definitions/BlockHash" + }, + "runtimeBytecode": { + "$ref": "#/definitions/BytecodeObject" + }, + "linkDependencies": { + "title": "Link Dependencies", + "description": "The values for the link references found within this contract instances runtime bytecode", + "type": "array", + "items": { + "$ref": "#/definitions/LinkValue" + } + } + } + }, + "ContractTypeName": { + "title": "Contract Type Name", + "description": "The name of the contract type", + "type": "string", + "pattern": "^(?:[a-z][-a-z0-9]{0,255}\\:)?[a-zA-Z_$][-a-zA-Z0-9_$]{0,255}(?:[-a-zA-Z0-9]{1,256}])?$" + }, + "ByteString": { + "title": "Byte String", + "description": "0x-prefixed hexadecimal string representing bytes", + "type": "string", + "pattern": "^0x([0-9a-fA-F]{2})*$" + }, + "BytecodeObject": { + "title": "Bytecode Object", + "type": "object", + "anyOf": [ + {"required": ["bytecode"]}, + {"required": ["linkDependencies"]} + ], + "properties": { + "bytecode": { + "$ref": "#/definitions/ByteString" + }, + "linkReferences": { + "type": "array", + "items": { + "$ref": "#/definitions/LinkReference" + } + }, + "linkDependencies": { + "type": "array", + "items": { + "$ref": "#/definitions/LinkValue" + } + } + } + }, + "ChecksumObject": { + "title": "Checksum Object", + "description": "Checksum information about the contents of a source file", + "type": "object", + "required": [ + "hash", + "algorithm" + ], + "properties": { + "hash": { + "type": "string" + }, + "algorithm": { + "type": "string" + } + } + }, + "LinkReference": { + "title": "Link Reference", + "description": "A defined location in some bytecode which requires linking", + "type": "object", + "required": [ + "offsets", + "length", + "name" + ], + "properties": { + "offsets": { + "type": "array", + "items": { + "type": "integer", + "minimum": 0 + } + }, + "length": { + "type": "integer", + "minimum": 1 + }, + "name": { + "anyOf": [ + {"$ref": "#/definitions/ContractTypeName"}, + {"$ref": "#/definitions/NestedContractTypeName"} + ] + } + } + }, + "LinkValue": { + "title": "Link Value", + "description": "A value for an individual link reference in a contract's bytecode", + "type": "object", + "required": [ + "offsets", + "type", + "value" + ], + "properties": { + "offsets": { + "type": "array", + "items": { + "type": "integer", + "minimum": 0 + } + }, + "type": { + "description": "The type of link value", + "type": "string" + }, + "value": { + "description": "The value for the link reference" + } + }, + "oneOf": [{ + "properties": { + "type": { + "enum": ["literal"] + }, + "value": { + "$ref": "#/definitions/ByteString" + } + } + }, { + "properties": { + "type": { + "enum": ["reference"] + }, + "value": { + "anyOf": [ + {"$ref": "#/definitions/ContractInstanceName"}, + {"$ref": "#/definitions/NestedContractInstanceName"} + ] + } + } + }] + }, + "ContractInstanceName": { + "title": "Contract Instance Name", + "description": "The name of the deployed contract instance", + "type": "string", + "pattern": "^[a-zA-Z_$][-a-zA-Z0-9_$]{0,255}(?:[-a-zA-Z0-9]{1,256})?$" + }, + "Deployment": { + "title": "Deployment", + "type": "object", + "propertyNames": { + "$ref": "#/definitions/ContractInstanceName" + }, + "patternProperties": { + "": { + "$ref": "#/definitions/ContractInstance" + } + } + }, + "NestedContractTypeName": { + "title": "Nested Contract Type Name", + "description": "Name of a nested contract type from somewhere down the dependency tree", + "type": "string", + "pattern": "^(?:[a-z][-a-z0-9]{0,255}\\:)+[a-zA-Z_$][-a-zA-Z0-9_$]{0,255}(?:[-a-zA-Z0-9]{1,256})?$" + }, + "NestedContractInstanceName": { + "title": "Nested Contract Instance Name", + "description": "Name of a nested contract instance from somewhere down the dependency tree", + "type": "string", + "pattern": "^(?:[a-z][-a-z0-9]{0,255}\\:)+[a-zA-Z_$][-a-zA-Z0-9_$]{0,255}(?:[-a-zA-Z0-9]{1,256})?$" + }, + "CompilerInformation": { + "title": "Compiler Information", + "description": "Information about the software that was used to compile a contract type or deployment", + "type": "object", + "required": [ + "name", + "version" + ], + "properties": { + "name": { + "description": "The name of the compiler", + "type": "string" + }, + "version": { + "description": "The version string for the compiler", + "type": "string" + }, + "settings": { + "description": "The settings used for compilation", + "type": "object" + }, + "contractTypes": { + "description": "The contract types that targeted this compiler.", + "type": "array", + "items": { + "$ref": "#/definitions/ContractTypeName" + } + } + } + }, + "Address": { + "title": "Address", + "description": "A 0x-prefixed Ethereum address", + "allOf": [ + { "$ref": "#/definitions/ByteString" }, + { "minLength": 42, "maxLength": 42 } + ] + }, + "TransactionHash": { + "title": "Transaction Hash", + "description": "A 0x-prefixed Ethereum transaction hash", + "allOf": [ + { "$ref": "#/definitions/ByteString" }, + { "minLength": 66, "maxLength": 66 } + ] + }, + "BlockHash": { + "title": "Block Hash", + "description": "An Ethereum block hash", + "allOf": [ + { "$ref": "#/definitions/ByteString" }, + { "minLength": 66, "maxLength": 66 } + ] + }, + "ContentURI": { + "title": "Content URI", + "description": "An content addressable URI", + "type": "string", + "format": "uri" + }, + "BlockchainURI": { + "title": "Blockchain URI", + "description": "An BIP122 URI", + "type": "string", + "pattern": "^blockchain\\://[0-9a-fA-F]{64}\\/block\\/[0-9a-fA-F]{64}$" + } + }, + "dependencies": { + "name": ["version"], + "version": ["name"] + } +} diff --git a/assets/eip-2680/sha256-384-512.pdf b/assets/eip-2680/sha256-384-512.pdf new file mode 100644 index 00000000000000..0524e81837999e Binary files /dev/null and b/assets/eip-2680/sha256-384-512.pdf differ diff --git a/assets/eip-2980/Finma-ICO-Guidelines.pdf b/assets/eip-2980/Finma-ICO-Guidelines.pdf new file mode 100644 index 00000000000000..2c8ba8deb21737 Binary files /dev/null and b/assets/eip-2980/Finma-ICO-Guidelines.pdf differ diff --git a/assets/eip-2980/Swiss-Confederation-AMLA.pdf b/assets/eip-2980/Swiss-Confederation-AMLA.pdf new file mode 100644 index 00000000000000..831c89cd56fbd2 Binary files /dev/null and b/assets/eip-2980/Swiss-Confederation-AMLA.pdf differ diff --git a/assets/eip-2980/Swiss-Confederation-BA.pdf b/assets/eip-2980/Swiss-Confederation-BA.pdf new file mode 100644 index 00000000000000..231a55142294d4 Binary files /dev/null and b/assets/eip-2980/Swiss-Confederation-BA.pdf differ diff --git a/assets/eip-2980/Swiss-Confederation-CISA.pdf b/assets/eip-2980/Swiss-Confederation-CISA.pdf new file mode 100644 index 00000000000000..3f870033977d53 Binary files /dev/null and b/assets/eip-2980/Swiss-Confederation-CISA.pdf differ diff --git a/assets/eip-2980/Swiss-Confederation-FINIA.pdf b/assets/eip-2980/Swiss-Confederation-FINIA.pdf new file mode 100644 index 00000000000000..e070984443c663 Binary files /dev/null and b/assets/eip-2980/Swiss-Confederation-FINIA.pdf differ diff --git a/assets/eip-2980/Swiss-Confederation-FINSA.pdf b/assets/eip-2980/Swiss-Confederation-FINSA.pdf new file mode 100644 index 00000000000000..154aec36be4883 Binary files /dev/null and b/assets/eip-2980/Swiss-Confederation-FINSA.pdf differ diff --git a/assets/eip-2980/Swiss-Confederation-FMIA.pdf b/assets/eip-2980/Swiss-Confederation-FMIA.pdf new file mode 100644 index 00000000000000..959c239d590714 Binary files /dev/null and b/assets/eip-2980/Swiss-Confederation-FMIA.pdf differ diff --git a/assets/eip-2980/Swiss-Confederation-SESTA.pdf b/assets/eip-2980/Swiss-Confederation-SESTA.pdf new file mode 100644 index 00000000000000..b83062d57211f6 Binary files /dev/null and b/assets/eip-2980/Swiss-Confederation-SESTA.pdf differ diff --git a/assets/eip-3005/meta-txs-directly-to-token-smart-contract.png b/assets/eip-3005/meta-txs-directly-to-token-smart-contract.png new file mode 100644 index 00000000000000..2c792f1429aa58 Binary files /dev/null and b/assets/eip-3005/meta-txs-directly-to-token-smart-contract.png differ diff --git a/assets/eip-3068/2012-685_Square_Root_Even_Ext.pdf b/assets/eip-3068/2012-685_Square_Root_Even_Ext.pdf new file mode 100644 index 00000000000000..077e093b4927dc Binary files /dev/null and b/assets/eip-3068/2012-685_Square_Root_Even_Ext.pdf differ diff --git a/assets/eip-3068/2015-1027_exTNFS.pdf b/assets/eip-3068/2015-1027_exTNFS.pdf new file mode 100644 index 00000000000000..a121ddb3afcaff Binary files /dev/null and b/assets/eip-3068/2015-1027_exTNFS.pdf differ diff --git a/assets/eip-3068/2016-1102_Assessing_NFS_Advances.pdf b/assets/eip-3068/2016-1102_Assessing_NFS_Advances.pdf new file mode 100644 index 00000000000000..2b429691d1fdcd Binary files /dev/null and b/assets/eip-3068/2016-1102_Assessing_NFS_Advances.pdf differ diff --git a/assets/eip-3068/2017-334.pdf b/assets/eip-3068/2017-334.pdf new file mode 100644 index 00000000000000..297ded43d2c425 Binary files /dev/null and b/assets/eip-3068/2017-334.pdf differ diff --git a/assets/eip-3068/2019-403_BLS12_H2C.pdf b/assets/eip-3068/2019-403_BLS12_H2C.pdf new file mode 100644 index 00000000000000..99a6ace575d242 Binary files /dev/null and b/assets/eip-3068/2019-403_BLS12_H2C.pdf differ diff --git a/assets/eip-3068/latincrypt12.pdf b/assets/eip-3068/latincrypt12.pdf new file mode 100644 index 00000000000000..11ebc47d61f47a Binary files /dev/null and b/assets/eip-3068/latincrypt12.pdf differ diff --git a/assets/eip-3068/madnet.pdf b/assets/eip-3068/madnet.pdf new file mode 100644 index 00000000000000..5185154e590d94 Binary files /dev/null and b/assets/eip-3068/madnet.pdf differ diff --git a/assets/eip-3068/weilsigs.pdf b/assets/eip-3068/weilsigs.pdf new file mode 100644 index 00000000000000..125c14f6084270 Binary files /dev/null and b/assets/eip-3068/weilsigs.pdf differ diff --git a/assets/eip-3102/sibling.svg b/assets/eip-3102/sibling.svg new file mode 100644 index 00000000000000..f670dc17b084b1 --- /dev/null +++ b/assets/eip-3102/sibling.svg @@ -0,0 +1,3 @@ + + +
root
root
...
...
4
4
2
2
2
2
root
root
...
...
5
5
8
8
8
8
root
root
...
...
8
8
Delete 10000100
Delete 100...
root
root
...
...
7
7
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/assets/eip-3267/contracts/BaseBidOnAddresses.sol b/assets/eip-3267/contracts/BaseBidOnAddresses.sol new file mode 100644 index 00000000000000..f39deebf7c8567 --- /dev/null +++ b/assets/eip-3267/contracts/BaseBidOnAddresses.sol @@ -0,0 +1,131 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +pragma solidity ^0.7.1; +import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol"; +import { ABDKMath64x64 } from "abdk-libraries-solidity/ABDKMath64x64.sol"; +import { BaseLock } from "./BaseLock.sol"; + +/// @title Bidding on Ethereum addresses +/// @author Victor Porton +/// @notice Not audited, not enough tested. +/// This allows anyone claim conditional tokens in order for him to transfer money from the future. +/// See `docs/future-money.rst`. +abstract contract BaseBidOnAddresses is BaseLock { + using ABDKMath64x64 for int128; + using SafeMath for uint256; + + /// A condition score was stored in the chain by an oracle. + /// @param oracleId The oracle ID. + /// @param condition The conditional (customer addresses). + /// @param numerator The relative score provided by the oracle. + event ReportedNumerator( + uint64 indexed oracleId, + uint256 indexed condition, + uint256 numerator + ); + + /// Some condition scores were stored in the chain by an oracle. + /// @param oracleId The oracle ID. + /// @param conditions The conditionals (customer addresses). + /// @param numerators The relative scores provided by the oracle. + event ReportedNumeratorsBatch( + uint64 indexed oracleId, + uint64[] indexed conditions, + uint256[] numerators + ); + + // Whether an oracle finished its work. + mapping(uint64 => bool) private oracleFinishedMap; + // Mapping (oracleId => (condition => numerator)) for payout numerators. + mapping(uint64 => mapping(uint256 => uint256)) private payoutNumeratorsMap; + // Mapping (oracleId => denominator) for payout denominators. + mapping(uint256 => uint) private payoutDenominatorMap; + + /// Constructor. + /// @param _uri Our ERC-1155 tokens description URI. + constructor(string memory _uri) BaseLock(_uri) { } + + /// Retrieve the last stored payout numerator (relative score of a condition). + /// @param _oracleId The oracle ID. + /// @param _condition The condition (the original receiver of a conditional token). + /// The result can't change if the oracle has finished. + function payoutNumerator(uint64 _oracleId, uint256 _condition) public view returns (uint256) { + return payoutNumeratorsMap[_oracleId][_condition]; + } + + /// Retrieve the last stored payout denominator (the sum of all numerators of the oracle). + /// @param _oracleId The oracle ID. + /// The result can't change if the oracle has finished. + function payoutDenominator(uint64 _oracleId) public view returns (uint256) { + return payoutDenominatorMap[_oracleId]; + } + + /// Called by the oracle owner for reporting results of conditions. + /// @param _oracleId The oracle ID. + /// @param _condition The condition. + /// @param _numerator The relative score of the condition. + /// Note: We could make oracles easily verificable by a hash of all the data, but + /// - It may need allowing to set a numerator only once. + /// - It may be not necessary because future technology will allow to aggregate blockchains. + function reportNumerator(uint64 _oracleId, uint256 _condition, uint256 _numerator) external + _isOracle(_oracleId) + _oracleNotFinished(_oracleId) // otherwise an oracle can break data consistency + { + _updateNumerator(_oracleId, _numerator, _condition); + emit ReportedNumerator(_oracleId, _condition, _numerator); + } + + /// Called by the oracle owner for reporting results of several conditions. + /// @param _oracleId The oracle ID. + /// @param _conditions The conditions. + /// @param _numerators The relative scores of the condition. + function reportNumeratorsBatch(uint64 _oracleId, uint64[] calldata _conditions, uint256[] calldata _numerators) external + _isOracle(_oracleId) + _oracleNotFinished(_oracleId) // otherwise an oracle can break data consistency + { + require(_conditions.length == _numerators.length, "Length mismatch."); + for (uint _i = 0; _i < _conditions.length; ++_i) { + _updateNumerator(_oracleId, _numerators[_i], _conditions[_i]); + } + emit ReportedNumeratorsBatch(_oracleId, _conditions, _numerators); + } + + /// Need to be called after all numerators were reported. + /// @param _oracleId The oracle ID. + /// + /// You should set grace period end time before calling this method. + /// + /// TODO: Maybe it makes sense to allow to set finish time in a point of the future? + function finishOracle(uint64 _oracleId) external + _isOracle(_oracleId) + { + oracleFinishedMap[_oracleId] = true; + emit OracleFinished(_oracleId); + } + + /// Check if an oracle has finished. + /// @param _oracleId The oracle ID. + /// @return `true` if it has finished. + function isOracleFinished(uint64 _oracleId) public view override returns (bool) { + return oracleFinishedMap[_oracleId]; + } + + function _updateNumerator(uint64 _oracleId, uint256 _numerator, uint256 _condition) private { + payoutDenominatorMap[_oracleId] = payoutDenominatorMap[_oracleId].add(_numerator).sub(payoutNumeratorsMap[_oracleId][_condition]); + payoutNumeratorsMap[_oracleId][_condition] = _numerator; + } + + // Virtuals // + + function _calcRewardShare(uint64 _oracleId, uint256 _condition) internal virtual override view returns (int128) { + uint256 _numerator = payoutNumeratorsMap[_oracleId][_condition]; + uint256 _denominator = payoutDenominatorMap[_oracleId]; + return ABDKMath64x64.divu(_numerator, _denominator); + } + + // Modifiers // + + modifier _oracleNotFinished(uint64 _oracleId) { + require(!isOracleFinished(_oracleId), "Oracle is finished."); + _; + } +} diff --git a/assets/eip-3267/contracts/BaseLock.sol b/assets/eip-3267/contracts/BaseLock.sol new file mode 100644 index 00000000000000..ca661791fab447 --- /dev/null +++ b/assets/eip-3267/contracts/BaseLock.sol @@ -0,0 +1,510 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +pragma solidity ^0.7.1; +import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol"; +import { ABDKMath64x64 } from "abdk-libraries-solidity/ABDKMath64x64.sol"; +import { ERC1155WithTotals } from "./ERC1155/ERC1155WithTotals.sol"; +import { ERC1155Holder } from "@openzeppelin/contracts/token/ERC1155/ERC1155Holder.sol"; +import { IERC1155 } from "@openzeppelin/contracts/token/ERC1155/IERC1155.sol"; +import { ERC721Holder } from "@openzeppelin/contracts/token/ERC721/ERC721Holder.sol"; + +/// @title A base class to lock collaterals and distribute them proportional to an oracle result. +/// @author Victor Porton +/// @notice Not audited, not enough tested. +/// +/// One can also donate/bequest a smart wallet (explain how). +/// +/// We have two kinds of ERC-1155 token IDs: +/// - conditional tokens: numbers < 2**64 +/// - a combination of a collateral contract address and collateral token ID +/// (a counter of donated amount of collateral tokens, don't confuse with collateral tokens themselves) +/// +/// Inheriting from here don't forget to create `createOracle()` external method. +abstract contract BaseLock is + ERC1155WithTotals, + ERC1155Holder, // You are recommended to use `donate()` function instead. + ERC721Holder // It can be used through an ERC-1155 wrapper. +{ + using ABDKMath64x64 for int128; + using SafeMath for uint256; + + /// Emitted when an oracle is created. + /// @param oracleId The ID of the created oracle. + event OracleCreated(uint64 oracleId); + + /// Emitted when an oracle owner is set. + /// @param oracleOwner Who created an oracle + /// @param oracleId The ID of the oracle. + event OracleOwnerChanged(address indexed oracleOwner, uint64 indexed oracleId); + + /// Emitted when an oracle owner is set. + /// @param sender Who created the condition + /// @param customer The owner of the condition. + /// @param condition The created condition ID. + event ConditionCreated(address indexed sender, address indexed customer, uint256 indexed condition); + + /// Emitted when a collateral is donated. + /// @param collateralContractAddress The ERC-1155 contract of the donated token. + /// @param collateralTokenId The ERC-1155 ID of the donated token. + /// @param sender Who donated. + /// @param amount The amount donated. + /// @param to Whose account the donation is assigned to. + /// @param data Additional transaction data. + event DonateCollateral( + IERC1155 indexed collateralContractAddress, + uint256 indexed collateralTokenId, + address indexed sender, + uint256 amount, + address to, + bytes data + ); + + /// Emitted when an oracle is marked as having finished its work. + /// @param oracleId The oracle ID. + event OracleFinished(uint64 indexed oracleId); + + /// Emitted when collateral is withdrawn. + /// @param contractAddress The ERC-1155 contract of the collateral token. + /// @param collateralTokenId The ERC-1155 token ID of the collateral. + /// @param oracleId The oracle ID for which withdrawal is done. + /// @param user Who has withdrawn. + /// @param amount The amount withdrawn. + event CollateralWithdrawn( + IERC1155 indexed contractAddress, + uint256 indexed collateralTokenId, + uint64 indexed oracleId, + address user, + uint256 amount + ); + + // Next ID. + uint64 public maxOracleId; // It doesn't really need to be public. + uint64 public maxConditionId; // It doesn't really need to be public. + + // Mapping (oracleId => oracle owner). + mapping(uint64 => address) private oracleOwnersMap; + // Mapping (oracleId => time) the max time for first withdrawal. + mapping(uint64 => uint) private gracePeriodEnds; + // The user lost the right to transfer conditional tokens: (user => (conditionalToken => bool)). + mapping(address => mapping(uint256 => bool)) private userUsedRedeemMap; + // Mapping (token => (original user => amount)) used to calculate withdrawal of collateral amounts. + mapping(uint256 => mapping(address => uint256)) public lastCollateralBalanceFirstRoundMap; + // Mapping (token => (original user => amount)) used to calculate withdrawal of collateral amounts. + mapping(uint256 => mapping(address => uint256)) public lastCollateralBalanceSecondRoundMap; + /// Mapping (oracleId => amount user withdrew in first round) (see `docs/Calculations.md`). + mapping(uint64 => uint256) public usersWithdrewInFirstRound; + + // Mapping (condition ID => original account) + mapping(uint256 => address) public conditionOwners; + + /// Constructor. + /// @param _uri Our ERC-1155 tokens description URI. + constructor(string memory _uri) ERC1155WithTotals(_uri) { + _registerInterface( + BaseLock(0).onERC1155Received.selector ^ + BaseLock(0).onERC1155BatchReceived.selector ^ + BaseLock(0).onERC721Received.selector + ); + } + + /// This function makes no sense, because it would produce a condition with zero tokens. + // function createCondition() public returns (uint64) { + // return _createCondition(); + // } + + /// Modify the owner of an oracle. + /// @param _newOracleOwner New owner. + /// @param _oracleId The oracle whose owner to change. + function changeOracleOwner(address _newOracleOwner, uint64 _oracleId) public _isOracle(_oracleId) { + oracleOwnersMap[_oracleId] = _newOracleOwner; + emit OracleOwnerChanged(_newOracleOwner, _oracleId); + } + + /// Set the end time of the grace period. + /// + /// The first withdrawal can be done *only* during the grace period. + /// The second withdrawal can be done after the end of the grace period and only if the first withdrawal was done. + /// + /// The intention of the grace period is to check which of users are active ("alive"). + function updateGracePeriodEnds(uint64 _oracleId, uint _time) public _isOracle(_oracleId) { + gracePeriodEnds[_oracleId] = _time; + } + + /// Donate funds in an ERC-1155 token. + /// + /// First, the collateral token need to be approved to be spent by this contract from the address `_from`. + /// + /// It also mints a token (with a different ID), that counts donations in that token. + /// + /// @param _collateralContractAddress The collateral ERC-1155 contract address. + /// @param _collateralTokenId The collateral ERC-1155 token ID. + /// @param _oracleId The oracle ID to whose ecosystem to donate to. + /// @param _amount The amount to donate. + /// @param _from From whom to take the donation. + /// @param _to On whose account the donation amount is assigned. + /// @param _data Additional transaction data. + function donate( + IERC1155 _collateralContractAddress, + uint256 _collateralTokenId, + uint64 _oracleId, + uint256 _amount, + address _from, + address _to, + bytes calldata _data) public + { + uint _donatedPerOracleCollateralTokenId = _collateralDonatedPerOracleTokenId(_collateralContractAddress, _collateralTokenId, _oracleId); + _mint(_to, _donatedPerOracleCollateralTokenId, _amount, _data); + uint _donatedCollateralTokenId = _collateralDonatedTokenId(_collateralContractAddress, _collateralTokenId); + _mint(_to, _donatedCollateralTokenId, _amount, _data); + emit DonateCollateral(_collateralContractAddress, _collateralTokenId, _from, _amount, _to, _data); + _collateralContractAddress.safeTransferFrom(_from, address(this), _collateralTokenId, _amount, _data); // last against reentrancy attack + } + + /// Gather a DeFi profit of a token previous donated to this contact. + /// @param _collateralContractAddress The collateral ERC-1155 contract address. + /// @param _collateralTokenId The collateral ERC-1155 token ID. + /// @param _oracleId The oracle ID to whose ecosystem to donate to. + /// @param _data Additional transaction data. + /// TODO: Batch calls in several tokens and/or to several oracles for less gas usage? + function gatherDeFiProfit( + IERC1155 _collateralContractAddress, + uint256 _collateralTokenId, + uint64 _oracleId, + bytes calldata _data) external + { + uint _donatedPerOracleCollateralTokenId = _collateralDonatedPerOracleTokenId(_collateralContractAddress, _collateralTokenId, _oracleId); + uint _donatedCollateralTokenId = _collateralDonatedTokenId(_collateralContractAddress, _collateralTokenId); + + // We consider an overflow an error and just revert: + // FIXME: Impossible due to reentrancy vulnerability? (Really? It's a view!) + uint256 _difference = + _collateralContractAddress.balanceOf(address(this), _collateralTokenId).sub( + balanceOf(address(this), _donatedCollateralTokenId)); + uint256 _amount = // rounding down to prevent overflows + _difference * + balanceOf(address(this), _donatedPerOracleCollateralTokenId) / + balanceOf(address(this), _donatedCollateralTokenId); + + // Last to avoid reentrancy vulnerability. + donate( + _collateralContractAddress, + _collateralTokenId, + _oracleId, + _amount, + address(this), + address(this), + _data); + } + + /// Calculate how much collateral is owed to a user. + /// @param _collateralContractAddress The ERC-1155 collateral token contract. + /// @param _collateralTokenId The ERC-1155 collateral token ID. + /// @param _oracleId From which oracle's "account" to withdraw. + /// @param _condition The condition (the original receiver of a conditional token). + /// @param _user The user to which we may owe. + function collateralOwing( + IERC1155 _collateralContractAddress, + uint256 _collateralTokenId, + uint64 _oracleId, + uint256 _condition, + address _user + ) external view returns(uint256) { + bool _inFirstRound = _isInFirstRound(_oracleId); + (, uint256 _donated) = + _collateralOwingBase(_collateralContractAddress, _collateralTokenId, _oracleId, _condition, _user, _inFirstRound); + return _donated; + } + + /// Transfer to `msg.sender` the collateral ERC-1155 token. + /// + /// The amount transferred is proportional to the score of `_condition` by the oracle. + /// @param _collateralContractAddress The ERC-1155 collateral token contract. + /// @param _collateralTokenId The ERC-1155 collateral token ID. + /// @param _oracleId From which oracle's "account" to withdraw. + /// @param _condition The condition. + /// @param _data Additional data. + /// + /// Notes: + /// - It is made impossible to withdraw somebody's other collateral, as otherwise we can't mark non-active + /// accounts in grace period. + /// - We can't transfer to somebody other than `msg.sender` because anybody can transfer + /// (needed for multi-level transfers). + /// - After this function is called, it becomes impossible to transfer the corresponding conditional token + /// of `msg.sender` (to prevent its repeated withdrawal). + function withdrawCollateral( + IERC1155 _collateralContractAddress, + uint256 _collateralTokenId, + uint64 _oracleId, + uint256 _condition, + bytes calldata _data) external + { + require(isOracleFinished(_oracleId), "too early"); // to prevent the denominator or the numerators change meantime + bool _inFirstRound = _isInFirstRound(_oracleId); + userUsedRedeemMap[msg.sender][_condition] = true; + // _burn(msg.sender, _condition, conditionalBalance); // Burning it would break using the same token for multiple markets. + (uint _donatedPerOracleCollateralTokenId, uint256 _owingDonated) = + _collateralOwingBase(_collateralContractAddress, _collateralTokenId, _oracleId, _condition, msg.sender, _inFirstRound); + + // Against rounding errors. Not necessary because of rounding down. + // if(_owing > balanceOf(address(this), _collateralTokenId)) _owing = balanceOf(address(this), _collateralTokenId); + + if (_owingDonated != 0) { + uint256 _newTotal = totalSupply(_donatedPerOracleCollateralTokenId); + if (_inFirstRound) { + lastCollateralBalanceFirstRoundMap[_donatedPerOracleCollateralTokenId][msg.sender] = _newTotal; + } else { + lastCollateralBalanceSecondRoundMap[_donatedPerOracleCollateralTokenId][msg.sender] = _newTotal; + } + } + if (!_inFirstRound) { + usersWithdrewInFirstRound[_oracleId] = usersWithdrewInFirstRound[_oracleId].add(_owingDonated); + } + // Last to prevent reentrancy attack: + _collateralContractAddress.safeTransferFrom(address(this), msg.sender, _collateralTokenId, _owingDonated, _data); + emit CollateralWithdrawn( + _collateralContractAddress, + _collateralTokenId, + _oracleId, + msg.sender, + _owingDonated + ); + } + + /// An ERC-1155 function. + /// + /// We disallow transfers of conditional tokens after redeem `_to` prevent "gathering" them before redeeming + /// each oracle. + function safeTransferFrom( + address _from, + address _to, + uint256 _id, + uint256 _value, + bytes calldata _data + ) + public override + { + _checkTransferAllowed(_id, _from); + _baseSafeTransferFrom(_from, _to, _id, _value, _data); + } + + /// An ERC-1155 function. + /// + /// We disallow transfers of conditional tokens after redeem `_to` prevent "gathering" them before redeeming + /// each oracle. + function safeBatchTransferFrom( + address _from, + address _to, + uint256[] calldata _ids, + uint256[] calldata _values, + bytes calldata _data + ) + public override + { + for(uint _i = 0; _i < _ids.length; ++_i) { + _checkTransferAllowed(_ids[_i], _from); + } + _baseSafeBatchTransferFrom(_from, _to, _ids, _values, _data); + } + + // Getters // + + /// Get the oracle owner. + /// @param _oracleId The oracle ID. + function oracleOwner(uint64 _oracleId) public view returns (address) { + return oracleOwnersMap[_oracleId]; + } + + /// Is the oracle marked as having finished its work? + /// + /// `oracleId` is the oracle ID. + function isOracleFinished(uint64 /*oracleId*/) public virtual view returns (bool) { + return true; + } + + /// Are transfers of a conditinal token locked? + /// + /// This is used to prevent its repeated withdrawal. + /// @param _user Querying if locked for this user. + /// @param _condition The condition (the original receiver of a conditional token). + function isConditionalLocked(address _user, uint256 _condition) public view returns (bool) { + return userUsedRedeemMap[_user][_condition]; + } + + /// Retrieve the end of the grace period. + /// @param _oracleId For which oracle. + function gracePeriodEnd(uint64 _oracleId) public view returns (uint) { + return gracePeriodEnds[_oracleId]; + } + + // Virtual functions // + + /// Current address of a user. + /// @param _originalAddress The original address of the user. + function originalToCurrentAddress(address _originalAddress) internal virtual returns (address) { + return _originalAddress; + } + + /// Mint a conditional to a customer. + function _mintToCustomer(address _customer, uint256 _condition, uint256 _amount, bytes calldata _data) + internal virtual + { + require(conditionOwners[_condition] == _customer, "Other's salary get attempt."); + _mint(originalToCurrentAddress(_customer), _condition, _amount, _data); + } + + /// Calculate the share of a condition in an oracle's market. + /// @param _oracleId The oracle ID. + /// @return Uses `ABDKMath64x64` number ID. + function _calcRewardShare(uint64 _oracleId, uint256 _condition) internal virtual view returns (int128); + + function _calcMultiplier(uint64 _oracleId, uint256 _condition, int128 _oracleShare) internal virtual view returns (int128) { + int128 _rewardShare = _calcRewardShare(_oracleId, _condition); + return _oracleShare.mul(_rewardShare); + } + + function _doTransfer(uint256 _id, address _from, address _to, uint256 _value) internal virtual { + _balances[_id][_from] = _balances[_id][_from].sub(_value); + _balances[_id][_to] = _value.add(_balances[_id][_to]); + } + + // Internal // + + /// Generate the ERC-1155 token ID that counts amount of donations per oracle for a ERC-1155 collateral token. + /// @param _collateralContractAddress The ERC-1155 contract of the collateral token. + /// @param _collateralTokenId The ERC-1155 ID of the collateral token. + /// @param _oracleId The oracle ID. + /// Note: It does not conflict with other tokens kinds, because the only other one is the uint64 conditional. + function _collateralDonatedPerOracleTokenId(IERC1155 _collateralContractAddress, uint256 _collateralTokenId, uint64 _oracleId) + internal pure returns (uint256) + { + return uint256(keccak256(abi.encodePacked(_collateralContractAddress, _collateralTokenId, _oracleId))); + } + + /// Generate the ERC-1155 token ID that counts amount of donations for a ERC-1155 collateral token. + /// @param _collateralContractAddress The ERC-1155 contract of the collateral token. + /// @param _collateralTokenId The ERC-1155 ID of the collateral token. + /// Note: It does not conflict with other tokens kinds, because the only other one is the uint64 conditional. + function _collateralDonatedTokenId(IERC1155 _collateralContractAddress, uint256 _collateralTokenId) + internal pure returns (uint256) + { + return uint256(keccak256(abi.encodePacked(_collateralContractAddress, _collateralTokenId))); + } + + function _checkTransferAllowed(uint256 _id, address _from) internal view { + require(!userUsedRedeemMap[_from][_id], "You can't trade conditional tokens after redeem."); + } + + function _baseSafeTransferFrom(address _from, address _to, uint256 _id, uint256 _value, bytes memory _data) private { + require(_to != address(0), "ERC1155: target address must be non-zero"); + require( + _from == msg.sender || _operatorApprovals[_from][msg.sender] == true, + "ERC1155: need operator approval for 3rd party transfers." + ); + + _doTransfer(_id, _from, _to, _value); + + emit TransferSingle(msg.sender, _from, _to, _id, _value); + + _doSafeTransferAcceptanceCheck(msg.sender, _from, _to, _id, _value, _data); + } + + function _baseSafeBatchTransferFrom( + address _from, + address _to, + uint256[] memory _ids, + uint256[] memory _values, + bytes memory _data + ) + private + { + require(_ids.length == _values.length, "ERC1155: IDs and _values must have same lengths"); + require(_to != address(0), "ERC1155: target address must be non-zero"); + require( + _from == msg.sender || _operatorApprovals[_from][msg.sender] == true, + "ERC1155: need operator approval for 3rd party transfers." + ); + + for (uint256 _i = 0; _i < _ids.length; ++_i) { + uint256 _id = _ids[_i]; + uint256 _value = _values[_i]; + + _doTransfer(_id, _from, _to, _value); + } + + emit TransferBatch(msg.sender, _from, _to, _ids, _values); + + _doSafeBatchTransferAcceptanceCheck(msg.sender, _from, _to, _ids, _values, _data); + } + + function _createOracle() internal returns (uint64) { + uint64 _oracleId = ++maxOracleId; + oracleOwnersMap[_oracleId] = msg.sender; + emit OracleCreated(_oracleId); + emit OracleOwnerChanged(msg.sender, _oracleId); + return _oracleId; + } + + /// Start with 1, not 0, to avoid glitch with `conditionalTokens` variable. + /// + /// TODO: Use uint64 variables instead? + function _createCondition(address _customer) internal returns (uint256) { + return _doCreateCondition(_customer); + } + + /// Start with 1, not 0, to avoid glitch with `conditionalTokens` variable. + /// + /// TODO: Use uint64 variables instead? + function _doCreateCondition(address _customer) internal virtual returns (uint256) { + uint64 _condition = ++maxConditionId; + + conditionOwners[_condition] = _customer; + + emit ConditionCreated(msg.sender, _customer, _condition); + + return _condition; + } + + function _collateralOwingBase( + IERC1155 _collateralContractAddress, + uint256 _collateralTokenId, + uint64 _oracleId, + uint256 _condition, + address _user, + bool _inFirstRound + ) + private view returns (uint _donatedPerOracleCollateralTokenId, uint256 _donated) + { + uint256 _conditionalBalance = balanceOf(_user, _condition); + uint256 _totalConditionalBalance = + _inFirstRound ? totalSupply(_condition) : usersWithdrewInFirstRound[_oracleId]; + _donatedPerOracleCollateralTokenId = _collateralDonatedPerOracleTokenId(_collateralContractAddress, _collateralTokenId, _oracleId); + // Rounded to below for no out-of-funds: + int128 _oracleShare = ABDKMath64x64.divu(_conditionalBalance, _totalConditionalBalance); + uint256 _newDividendsDonated = + totalSupply(_donatedPerOracleCollateralTokenId) - + (_inFirstRound + ? lastCollateralBalanceFirstRoundMap[_donatedPerOracleCollateralTokenId][_user] + : lastCollateralBalanceSecondRoundMap[_donatedPerOracleCollateralTokenId][_user]); + int128 _multiplier = _calcMultiplier(_oracleId, _condition, _oracleShare); + _donated = _multiplier.mulu(_newDividendsDonated); + } + + function _isInFirstRound(uint64 _oracleId) internal view returns (bool) { + return block.timestamp <= gracePeriodEnds[_oracleId]; + } + + function _isConditional(uint256 _tokenId) internal pure returns (bool) { + // Zero 2**-192 probability that tokenId < (1<<64) if it's not a conditional. + // Note to auditor: It's a hack, check for no errors carefully. + return _tokenId < (1<<64); + } + + modifier _isOracle(uint64 _oracleId) { + require(oracleOwnersMap[_oracleId] == msg.sender, "Not the oracle owner."); + _; + } + + modifier checkIsConditional(uint256 _tokenId) { + require(_isConditional(_tokenId), "It's not your conditional."); + _; + } +} diff --git a/assets/eip-3267/contracts/BaseRestorableSalary.sol b/assets/eip-3267/contracts/BaseRestorableSalary.sol new file mode 100644 index 00000000000000..2916b6c8705740 --- /dev/null +++ b/assets/eip-3267/contracts/BaseRestorableSalary.sol @@ -0,0 +1,174 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +pragma solidity ^0.7.1; +import "./Salary.sol"; + +/// @author Victor Porton +/// @notice Not audited, not enough tested. +/// A base class for salary with receiver accounts that can be restored by an "attorney". +abstract contract BaseRestorableSalary is BaseSalary { + // INVARIANT: `_originalAddress(newToOldAccount[newAccount]) == _originalAddress(newAccount)` + // if `newToOldAccount[newAccount] != address(0)` for every `newAccount` + // INVARIANT: originalAddresses and originalToCurrentAddresses are mutually inverse. + // That is: + // - `originalAddresses[originalToCurrentAddresses[x]] == x` if `originalToCurrentAddresses[x] != address(0)` + // - `originalToCurrentAddresses[originalAddresses[x]] == x` if `originalAddresses[x] != address(0)` + + /// Mapping (current address => very first address an account had). + mapping(address => address) public originalAddresses; + + /// Mapping (very first address an account had => current address). + mapping(address => address) public originalToCurrentAddresses; + + // Mapping from old to new account addresses (created after every change of an address). + mapping(address => address) public newToOldAccount; + + /// Constructor. + /// @param _uri Our ERC-1155 tokens description URI. + constructor (string memory _uri) BaseSalary(_uri) { } + + /// Below copied from https://github.com/vporton/restorable-funds/blob/f6192fd23cad529b84155d52ae202430cd97db23/contracts/RestorableERC1155.sol + + /// Give the user the "permission" to move funds from `_oldAccount` to `_newAccount`. + /// + /// This function is intended to be called by an attorney or the user to move to a new account. + /// @param _oldAccount is a current address. + /// @param _newAccount is a new address. + function permitRestoreAccount(address _oldAccount, address _newAccount) public { + if (msg.sender != _oldAccount) { + checkAllowedRestoreAccount(_oldAccount, _newAccount); // only authorized "attorneys" or attorney DAOs + } + _avoidZeroAddressManipulatins(_oldAccount, _newAccount); + address _orig = _originalAddress(_oldAccount); + + // We don't disallow joining several accounts together to consolidate salaries for different projects. + // require(originalAddresses[_newAccount] == 0, "Account is taken.") + + newToOldAccount[_newAccount] = _oldAccount; + originalAddresses[_newAccount] = _orig; + originalToCurrentAddresses[_orig] = _newAccount; + // Auditor: Check that the above invariant hold. + emit AccountRestored(_oldAccount, _newAccount); + } + + /// Retire the user's "permission" to move funds from `_oldAccount` to `_newAccount`. + /// + /// This function is intended to be called by an attorney. + /// @param _oldAccount is an old current address. + /// @param _newAccount is a new address. + /// (In general) it isn't allowed to be called by `msg.sender == _oldAccount`, + /// because it would allow to keep stealing the salary by hijacked old account. + function dispermitRestoreAccount(address _oldAccount, address _newAccount) public { + checkAllowedUnrestoreAccount(_oldAccount, _newAccount); // only authorized "attorneys" or attorney DAOs + _avoidZeroAddressManipulatins(_oldAccount, _newAccount); + newToOldAccount[_newAccount] = address(0); + originalToCurrentAddresses[_oldAccount] = address(0); + originalAddresses[_newAccount] = address(0); + // Auditor: Check that the above invariants hold. + emit AccountUnrestored(_oldAccount, _newAccount); + } + + /// Move the entire balance of a token from an old account to a new account of the same user. + /// @param _oldAccount Old account. + /// @param _newAccount New account. + /// @param _token The ERC-1155 token ID. + /// This function can be called by the affected user. + /// + /// Remark: We don't need to create new tokens like as on a regular transfer, + /// because it isn't a transfer to a trader. + function restoreFunds(address _oldAccount, address _newAccount, uint256 _token) public + checkMovedOwner(_oldAccount, _newAccount) + { + uint256 _amount = _balances[_token][_oldAccount]; + + _balances[_token][_newAccount] = _balances[_token][_oldAccount]; + _balances[_token][_oldAccount] = 0; + + emit TransferSingle(_msgSender(), _oldAccount, _newAccount, _token, _amount); + } + + /// Move the entire balance of tokens from an old account to a new account of the same user. + /// @param _oldAccount Old account. + /// @param _newAccount New account. + /// @param _tokens The ERC-1155 token IDs. + /// This function can be called by the affected user. + /// + /// Remark: We don't need to create new tokens like as on a regular transfer, + /// because it isn't a transfer to a trader. + function restoreFundsBatch(address _oldAccount, address _newAccount, uint256[] calldata _tokens) public + checkMovedOwner(_oldAccount, _newAccount) + { + uint256[] memory _amounts = new uint256[](_tokens.length); + for (uint _i = 0; _i < _tokens.length; ++_i) { + uint256 _token = _tokens[_i]; + uint256 _amount = _balances[_token][_oldAccount]; + _amounts[_i] = _amount; + + _balances[_token][_newAccount] = _balances[_token][_oldAccount]; + _balances[_token][_oldAccount] = 0; + } + + emit TransferBatch(_msgSender(), _oldAccount, _newAccount, _tokens, _amounts); + } + + // Internal functions // + + function _avoidZeroAddressManipulatins(address _oldAccount, address _newAccount) internal view { + // To avoid make-rich-quick manipulations with lost funds: + require(_oldAccount != address(0) && _newAccount != address(0) && + originalAddresses[_newAccount] != address(0) && newToOldAccount[_newAccount] != address(0), + "Trying to get nobody's funds."); + } + + // Virtual functions // + + /// Check if `msg.sender` is an attorney allowed to restore a user's account. + function checkAllowedRestoreAccount(address /*_oldAccount*/, address /*_newAccount*/) public virtual; + + /// Check if `msg.sender` is an attorney allowed to unrestore a user's account. + function checkAllowedUnrestoreAccount(address /*_oldAccount*/, address /*_newAccount*/) public virtual; + + /// Find the original address of a given account. + /// This function is internal, because it can be calculated off-chain. + /// @param _account The current address. + function _originalAddress(address _account) internal view virtual returns (address) { + address _newAddress = originalAddresses[_account]; + return _newAddress != address(0) ? _newAddress : _account; + } + + // Find the current address for an original address. + // @param _conditional The original address. + function originalToCurrentAddress(address _customer) internal virtual override returns (address) { + address current = originalToCurrentAddresses[_customer]; + return current != address(0) ? current : _customer; + } + + // TODO: Is the following function useful to save gas in other contracts? + // function getCurrent(address _account) public returns (uint256) { + // address _original = originalAddresses[_account]; + // return _original == 0 ? 0 : originalToCurrentAddress(_original); + // } + + // Modifiers // + + /// Check that `_newAccount` is the user that has the right to restore funds from `_oldAccount`. + /// + /// We also allow funds restoration by attorneys for convenience of users. + /// This is not an increased security risk, because a dishonest attorney can anyway transfer money to himself. + modifier checkMovedOwner(address _oldAccount, address _newAccount) virtual { + if (_msgSender() != _newAccount) { + checkAllowedRestoreAccount(_oldAccount, _newAccount); // only authorized "attorneys" or attorney DAOs + } + + for (address _account = _oldAccount; _account != _newAccount; _account = newToOldAccount[_account]) { + require(_account != address(0), "Not a moved owner"); + } + + _; + } + + // Events // + + event AccountRestored(address indexed oldAccount, address indexed newAccount); + + event AccountUnrestored(address indexed oldAccount, address indexed newAccount); +} diff --git a/assets/eip-3267/contracts/BaseSalary.sol b/assets/eip-3267/contracts/BaseSalary.sol new file mode 100644 index 00000000000000..276b97369f2de3 --- /dev/null +++ b/assets/eip-3267/contracts/BaseSalary.sol @@ -0,0 +1,239 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +pragma solidity ^0.7.1; +import "./BaseBidOnAddresses.sol"; + +/// @title Base class for a "salary" that is paid one token per second using minted conditionals. +/// @author Victor Porton +/// @notice Not audited, not enough tested. +/// It was considered to allow the DAO to adjust registration date to pay salary retrospectively, +/// but this seems giving too much rights to the DAO similarly as if it had the right to declare anyone dead. +/// +/// It would cause this effect: A scientist who is already great may register then his date is moved back +/// in time and instantly he or she receives a very big sum of money to his account. +/// If it is done erroneously, there may be no way to move the registration date again forward in time, +/// because the tokens may be already withdrawn. And it cannot be done in a fully decentralized way because +/// it needs oracles. So errors are seem inevitable. +/// On the other hand, somebody malicious may create and register in my system a pool of Ethereum addresses that +/// individuals can receive from them as if they themselves registered in the past. +/// So it in some cases (if the registration date is past the contract deployment) this issue is impossible to +/// mitigate. +/// +/// The salary is paid in minted tokens groups into "chains": +/// the original salary token and anyone can replace it by another token, next in the chain. +contract BaseSalary is BaseBidOnAddresses { + /// Salary receiver registered. + /// @param customer The customer address. + /// @param oracleId The oracle ID for which he registers. + /// @param data Additional data. + event CustomerRegistered( + address indexed customer, + uint64 indexed oracleId, + uint256 indexed condition, + bytes data + ); + + /// Salary tokens minted. + /// @param customer The customer address. + /// @param oracleId The oracle ID. + /// @param amount The minted amount. + /// @param data Additional data. + event SalaryMinted( + address indexed customer, + uint64 indexed oracleId, + uint256 indexed condition, + uint256 amount, + bytes data + ); + + /// Salary token recreated (salary recalculation request). + /// @param customer The customer address. + /// @param originalCondition The original token ID. + /// @param newCondition The new token ID. + event ConditionReCreate( + address indexed customer, + uint256 indexed originalCondition, + uint256 indexed newCondition + ); + + // Mapping (condition ID => registration time). + mapping(uint256 => uint) public conditionCreationDates; + // Mapping (condition ID => salary block time). + mapping(uint256 => uint) public lastSalaryDates; + /// Mapping (condition ID => account) - salary recipients. + mapping(uint256 => address) public salaryReceivers; + + /// Mapping (condition ID => first condition ID in the chain) + /// + /// I call _chain_ of conditions the list of conditions resulting from creating and recreating conditions. + mapping(uint256 => uint256) public firstConditionInChain; + /// Mapping (first condition ID in the chain => last condition ID in the chain) + /// + /// I call _chain_ of conditions the list of conditions resulting from creating and recreating conditions. + mapping(uint256 => uint256) public firstToLastConditionInChain; + + /// Constructor. + /// @param _uri The ERC-1155 token URI. + constructor(string memory _uri) BaseBidOnAddresses(_uri) { } + + /// Mint a salary token. + /// @param _oracleId The oracle ID. + /// @param _condition The condition ID. + /// @param _data Additional data. + /// This method can be called only by the salary receiver. + function mintSalary(uint64 _oracleId, uint256 _condition, bytes calldata _data) + ensureLastConditionInChain(_condition) external + { + uint _lastSalaryDate = lastSalaryDates[_condition]; + require(_lastSalaryDate != 0, "You are not registered."); + // Note: Even if you withdraw once per 20 years, you will get only 630,720,000 tokens. + // This number is probably not to big to be displayed well in UIs. + uint256 _amount = (block.timestamp - _lastSalaryDate) * 10**18; // one token per second + _mintToCustomer(msg.sender, firstToLastConditionInChain[_condition], _amount, _data); + lastSalaryDates[_condition] = block.timestamp; + emit SalaryMinted(msg.sender, _oracleId, _condition, _amount, _data); + } + + /// Make a new condition that replaces the old one. + /// + /// In other words, it is a request to recalculate somebody's salary. + /// + /// Anyone can request to recalculate anyone's salary. + /// + /// It's also useful to punish someone for decreasing his work performance or an evil act. + /// This is to be called among other when a person dies. + /// + /// Recalculation is also forced when a salary receiver transfers away his current salary token. + /// It is useful to remove a trader's incentive to kill the issuer to reduce the circulating supply. + /// + /// Issue to solve later: Should we recommend: + /// - calling this function on each new project milestone? + /// - calling this function regularly (e.g. every week)? + /// + /// This function also withdraws the old token. + function recreateCondition(uint256 _condition) public returns (uint256) { + return _recreateCondition(_condition); + } + + function _doCreateCondition(address _customer) internal virtual override returns (uint256) { + uint256 _condition = super._doCreateCondition(_customer); + salaryReceivers[_condition] = _customer; + conditionCreationDates[_condition] = block.timestamp; + firstConditionInChain[_condition] = _condition; + firstToLastConditionInChain[_condition] = _condition; + return _condition; + } + + /// Make a new condition that replaces the old one. + /// The same can be done by transferring to yourself 0 tokens, but this method uses less gas. + /// + /// We need to create a new condition every time when an outgoimg transfer of a conditional token happens. + /// Otherwise an investor would gain if he kills a scientist to reduce the circulating supply of his token to increase the price. + /// Allowing old tokens to be exchangeable for new ones? (Allowing the reverse swap would create killer's gain.) + /// Additional benefit of this solution: We can have different rewards at different stages of project, + /// what may be beneficial for early startups funding. + /// + /// Problem to be solved later: There should be an advice to switch to a new token at each milestone of a project? + /// + /// Anyone can create a ERC-1155 contract that allows to use any of the tokens in the list + /// by locking any of the tokens in the list as a new "general" token. We should recommend customers not to + /// use such contracts, because it creates for them the killer exploit. + /// + /// If we would exchange the old and new tokens for the same amounts of collaterals, then it would be + /// effectively the same token and therefore minting more new token would possibly devalue the old one, + /// thus triggering the killer's exploit again. So we make old and new completely independent. + /// + /// Old token is 1:1 converted to the new token. + /// + /// Remark: To make easy to exchange the token even if it is recreated, we can make a wrapper or locker + /// token that uses `firstConditionInChain[]` to aggregate several tokens together. + /// A similar wrapper (the customer need to `setApprovalForAll()` on it) that uses + /// `firstToLastConditionInChain[]` can be used to transfer away recreated tokens + /// even if an evil DAO tries to frontrun the customer by recreating his tokens very often. + /// TODO: Test that it's possible to create such a locker. + /// + /// Note: That wrapper could be carelessly used to create the investor's killing customer incentive + /// by the customer using it to transfer to an investor. Even if the customer uses it only for + /// exchanges, an investor can buy at an exchange and be a killer. + /// To make it safe, it must stop accepting any new tokens after a transfer. + /// It can determine if a token is new just comparing by `<` operator. + /// It's strongly recommended that an app that uses this contract provides its own swap/exchange UI + /// and warns the user not to use arbitrary exchanges as being an incentive to kill the user. + /// + /// We allow anybody (not just the account owner or DAO) to recreate a condition, because: + /// - Exchanges can create a "composite" token that allows to withdraw any of the tokens in the chain + /// up to a certain period of time (using on-chain `conditionCreationDates`). + /// - Therefore somebody's token can be withdrawn even if its ID changes arbitrarily often. + /// + /// @param _condition The condition ID. + function _recreateCondition(uint256 _condition) + internal ensureFirstConditionInChain(_condition) returns (uint256) + { + address _customer = salaryReceivers[_condition]; + uint256 _oldCondition = firstToLastConditionInChain[_condition]; + uint256 _newCondition = _doCreateCondition(_customer); + firstConditionInChain[_newCondition] = _condition; + + uint256 _amount = _balances[_oldCondition][_customer]; + _balances[_newCondition][_customer] = _amount; + _balances[_oldCondition][_customer] = 0; + + // TODO: Should we swap two following lines? + emit TransferSingle(msg.sender, _customer, address(0), _condition, _amount); + emit TransferSingle(msg.sender, address(0), _customer, _newCondition, _amount); + + lastSalaryDates[_newCondition] = lastSalaryDates[_condition]; + // TODO: Should we here set `lastSalaryDates[_condition] = 0` to save storage space? // TODO: It would also eliminate the need to check in mint function. + + emit ConditionReCreate(_customer, _condition, _newCondition); + return _newCondition; + } + + /// Check if it is the first condition in a chain of conditions. + /// @param _id The condition ID. + /// + /// Must be called with `_id != 0`. + function isFirstConditionInChain(uint256 _id) internal view returns (bool) { + return firstConditionInChain[_id] == _id; + } + + /// Check if it is the last condition in a chain of conditions. + /// @param _id The condition ID. + /// + /// Must be called with `_id != 0`. + /// + /// TODO: Should make this function public? + function isLastConditionInChain(uint256 _id) internal view returns (bool) { + return firstToLastConditionInChain[firstConditionInChain[_id]] == _id; + } + + function _doTransfer(uint256 _id, address _from, address _to, uint256 _value) internal virtual override { + super._doTransfer(_id, _from, _to, _value); + + if (_id != 0 && salaryReceivers[_id] == msg.sender) { + if (isLastConditionInChain(_id)) { // correct because `_id != 0` + _recreateCondition(_id); + } + } + } + + function _registerCustomer(address _customer, uint64 _oracleId, bytes calldata _data) + virtual internal returns (uint256) + { + uint256 _condition = _doCreateCondition(_customer); + lastSalaryDates[_condition] = block.timestamp; + emit CustomerRegistered(msg.sender, _oracleId, _condition, _data); + return _condition; + } + + modifier ensureFirstConditionInChain(uint256 _id) { + // TODO: Is `_id != 0` check needed? + require(_isConditional(_id) && _id != 0 && isFirstConditionInChain(_id), "Only for the last salary token."); + _; + } + + modifier ensureLastConditionInChain(uint256 _id) { + // TODO: Is `_id != 0` check needed? + require(_isConditional(_id) && _id != 0 && isLastConditionInChain(_id), "Only for the last salary token."); + _; + } +} diff --git a/assets/eip-3267/contracts/BidOnAddresses.sol b/assets/eip-3267/contracts/BidOnAddresses.sol new file mode 100644 index 00000000000000..baeb637c45cb09 --- /dev/null +++ b/assets/eip-3267/contracts/BidOnAddresses.sol @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +pragma solidity ^0.7.1; +import "./BaseBidOnAddresses.sol"; + +/// @title Bidding on Ethereum addresses +/// @author Victor Porton +/// @notice Not audited, not enough tested. +/// This allows anyone to claim 1000 conditional tokens in order for him to transfer money from the future. +/// See `docs/future-money.rst` and anyone to donate. +/// +/// We have two kinds of ERC-1155 token IDs: +/// - conditional tokens: numbers < 2**64 +/// - a combination of a collateral contract address and collateral token ID +/// (a counter of donated amount of collateral tokens, don't confuse with collateral tokens themselves) +/// +/// In functions of this contact `condition` is always a customer's original address. +/// +/// We receive funds in ERC-1155, see also https://github.com/vporton/wrap-tokens +contract BidOnAddresses is BaseBidOnAddresses { + uint constant INITIAL_CUSTOMER_BALANCE = 1000 * 10**18; // an arbitrarily chosen value + + /// Customer registered. + /// @param sender `msg.sender`. + /// @param customer The customer address. + /// @param data Additional data. + event CustomerRegistered( + address indexed sender, + address indexed customer, + uint256 indexed condition, + bytes data + ); + + /// @param _uri The ERC-1155 token URI. + constructor(string memory _uri) BaseBidOnAddresses(_uri) { + _registerInterface( + BidOnAddresses(0).onERC1155Received.selector ^ + BidOnAddresses(0).onERC1155BatchReceived.selector + ); + } + + /// Anyone can register anyone. + /// + /// This can be called both before or after the oracle finish. However registering after the finish is useless. + /// + /// We check that `oracleId` exists (we don't want "spammers" to register themselves for a million oracles). + /// + /// We allow anyone to register anyone. This is useful for being registered by robots. + /// At first it seems to be harmful to make somebody a millionaire unwillingly (he then needs a fortress and bodyguards), + /// but: Salary tokens will be worth real money, only if the registered person publishes his works together + /// with his Ethereum address. So, he can be made rich against his will only by impersonating him. But if somebody + /// impersonates him, then they are able to present him richer than he is anyway, so making him vulnerable to + /// kidnappers anyway. So having somebody registered against his will seems not to be a problem at all + /// (except that he will see superfluous worthless tokens in Etherscan data of his account.) + /// + /// An alternative way would be to make registration gasless but requiring a registrant signature. + /// This is not very good, probably: + /// - It requires to install MetaMask. + /// - It bothers the person to sign something, when he could just be hesitant to get what he needs. + /// - It somehow complicates this contract. + /// @param _customer The address of the customer. // TODO: current or original + /// @param _oracleId The oracle ID. + /// @param _data Additional data. + function registerCustomer(address _customer, uint64 _oracleId, bytes calldata _data) external { + require(_oracleId <= maxOracleId, "Oracle doesn't exist."); + uint256 _condition = _createCondition(_customer); + _mintToCustomer(_customer, _condition, INITIAL_CUSTOMER_BALANCE, _data); + emit CustomerRegistered(msg.sender, _customer, _condition, _data); + } +} diff --git a/assets/eip-3267/contracts/DAOInterface.sol b/assets/eip-3267/contracts/DAOInterface.sol new file mode 100644 index 00000000000000..86417857ced575 --- /dev/null +++ b/assets/eip-3267/contracts/DAOInterface.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +pragma solidity ^0.7.1; + +/// @notice The "DAO plugin" interface. +/// @author Victor Porton +/// @notice Not audited, not enough tested. +interface DAOInterface { + /// Check if `msg.sender` is an attorney allowed to restore a given account. + function checkAllowedRestoreAccount(address _oldAccount, address _newAccount) external; + + /// Check if `msg.sender` is an attorney allowed to unrestore a given account. + function checkAllowedUnrestoreAccount(address _oldAccount, address _newAccount) external; +} diff --git a/assets/eip-3267/contracts/DefaultDAOInterface.sol b/assets/eip-3267/contracts/DefaultDAOInterface.sol new file mode 100644 index 00000000000000..79cf6838de89b8 --- /dev/null +++ b/assets/eip-3267/contracts/DefaultDAOInterface.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +pragma solidity ^0.7.1; +import "./DAOInterface.sol"; + +/// @notice "Default" contract for `DAOInterface`. +/// @author Victor Porton +/// @notice Not audited, not enough tested. +contract DefaultDAOInterface is DAOInterface { + function checkAllowedRestoreAccount(address /*_oldAccount*/, address /*_newAccount*/) external pure override { + revert("unimplemented"); + } + + function checkAllowedUnrestoreAccount(address /*_oldAccount*/, address /*_newAccount*/) external pure override { + revert("unimplemented"); + } +} diff --git a/assets/eip-3267/contracts/ERC1155/ERC1155.sol b/assets/eip-3267/contracts/ERC1155/ERC1155.sol new file mode 100644 index 00000000000000..de4637f9b78fa1 --- /dev/null +++ b/assets/eip-3267/contracts/ERC1155/ERC1155.sol @@ -0,0 +1,414 @@ +// SPDX-License-Identifier: MIT + +pragma solidity >=0.6.0 <0.8.0; + +import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol"; +import "@openzeppelin/contracts/token/ERC1155/IERC1155MetadataURI.sol"; +import "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol"; +import "@openzeppelin/contracts/GSN/Context.sol"; +import "@openzeppelin/contracts/introspection/ERC165.sol"; +import "@openzeppelin/contracts/math/SafeMath.sol"; +import "@openzeppelin/contracts/utils/Address.sol"; + +/** + * + * @dev Implementation of the basic standard multi-token. + * See https://eips.ethereum.org/EIPS/eip-1155 + * Originally based on code by Enjin: https://github.com/enjin/erc-1155 + * + * _Available since v3.1._ + */ +contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI { + using SafeMath for uint256; + using Address for address; + + // Mapping from token ID to account balances + mapping (uint256 => mapping(address => uint256)) internal _balances; + + // Mapping from account to operator approvals + mapping (address => mapping(address => bool)) internal _operatorApprovals; + + // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json + string private _uri; + + /* + * bytes4(keccak256('balanceOf(address,uint256)')) == 0x00fdd58e + * bytes4(keccak256('balanceOfBatch(address[],uint256[])')) == 0x4e1273f4 + * bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465 + * bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5 + * bytes4(keccak256('safeTransferFrom(address,address,uint256,uint256,bytes)')) == 0xf242432a + * bytes4(keccak256('safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)')) == 0x2eb2c2d6 + * + * => 0x00fdd58e ^ 0x4e1273f4 ^ 0xa22cb465 ^ + * 0xe985e9c5 ^ 0xf242432a ^ 0x2eb2c2d6 == 0xd9b67a26 + */ + bytes4 private constant _INTERFACE_ID_ERC1155 = 0xd9b67a26; + + /* + * bytes4(keccak256('uri(uint256)')) == 0x0e89341c + */ + bytes4 private constant _INTERFACE_ID_ERC1155_METADATA_URI = 0x0e89341c; + + /** + * @dev See {_setURI}. + */ + constructor (string memory uri_) { + _setURI(uri_); + + // register the supported interfaces to conform to ERC1155 via ERC165 + _registerInterface(_INTERFACE_ID_ERC1155); + + // register the supported interfaces to conform to ERC1155MetadataURI via ERC165 + _registerInterface(_INTERFACE_ID_ERC1155_METADATA_URI); + } + + /** + * @dev See {IERC1155MetadataURI-uri}. + * + * This implementation returns the same URI for *all* token types. It relies + * on the token type ID substitution mechanism + * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP]. + * + * Clients calling this function must replace the `\{id\}` substring with the + * actual token type ID. + */ + function uri(uint256) external view override returns (string memory) { + return _uri; + } + + /** + * @dev See {IERC1155-balanceOf}. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function balanceOf(address account, uint256 id) public view virtual override returns (uint256) { + require(account != address(0), "ERC1155: balance query for the zero address"); + return _balances[id][account]; + } + + /** + * @dev See {IERC1155-balanceOfBatch}. + * + * Requirements: + * + * - `accounts` and `ids` must have the same length. + */ + function balanceOfBatch( + address[] memory accounts, + uint256[] memory ids + ) + public + view + virtual + override + returns (uint256[] memory) + { + require(accounts.length == ids.length, "ERC1155: accounts and ids length mismatch"); + + uint256[] memory batchBalances = new uint256[](accounts.length); + + for (uint256 i = 0; i < accounts.length; ++i) { + require(accounts[i] != address(0), "ERC1155: batch balance query for the zero address"); + batchBalances[i] = _balances[ids[i]][accounts[i]]; + } + + return batchBalances; + } + + /** + * @dev See {IERC1155-setApprovalForAll}. + */ + function setApprovalForAll(address operator, bool approved) public virtual override { + require(_msgSender() != operator, "ERC1155: setting approval status for self"); + + _operatorApprovals[_msgSender()][operator] = approved; + emit ApprovalForAll(_msgSender(), operator, approved); + } + + /** + * @dev See {IERC1155-isApprovedForAll}. + */ + function isApprovedForAll(address account, address operator) public view virtual override returns (bool) { + return _operatorApprovals[account][operator]; + } + + /** + * @dev See {IERC1155-safeTransferFrom}. + */ + function safeTransferFrom( + address from, + address to, + uint256 id, + uint256 amount, + bytes memory data + ) + public + virtual + override + { + require(to != address(0), "ERC1155: transfer to the zero address"); + require( + from == _msgSender() || isApprovedForAll(from, _msgSender()), + "ERC1155: caller is not owner nor approved" + ); + + address operator = _msgSender(); + + _beforeTokenTransfer(operator, from, to, _asSingletonArray(id), _asSingletonArray(amount), data); + + _balances[id][from] = _balances[id][from].sub(amount, "ERC1155: insufficient balance for transfer"); + _balances[id][to] = _balances[id][to].add(amount); + + emit TransferSingle(operator, from, to, id, amount); + + _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data); + } + + /** + * @dev See {IERC1155-safeBatchTransferFrom}. + */ + function safeBatchTransferFrom( + address from, + address to, + uint256[] memory ids, + uint256[] memory amounts, + bytes memory data + ) + public + virtual + override + { + require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch"); + require(to != address(0), "ERC1155: transfer to the zero address"); + require( + from == _msgSender() || isApprovedForAll(from, _msgSender()), + "ERC1155: transfer caller is not owner nor approved" + ); + + address operator = _msgSender(); + + _beforeTokenTransfer(operator, from, to, ids, amounts, data); + + for (uint256 i = 0; i < ids.length; ++i) { + uint256 id = ids[i]; + uint256 amount = amounts[i]; + + _balances[id][from] = _balances[id][from].sub( + amount, + "ERC1155: insufficient balance for transfer" + ); + _balances[id][to] = _balances[id][to].add(amount); + } + + emit TransferBatch(operator, from, to, ids, amounts); + + _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data); + } + + /** + * @dev Sets a new URI for all token types, by relying on the token type ID + * substitution mechanism + * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP]. + * + * By this mechanism, any occurrence of the `\{id\}` substring in either the + * URI or any of the amounts in the JSON file at said URI will be replaced by + * clients with the token type ID. + * + * For example, the `https://token-cdn-domain/\{id\}.json` URI would be + * interpreted by clients as + * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json` + * for token type ID 0x4cce0. + * + * See {uri}. + * + * Because these URIs cannot be meaningfully represented by the {URI} event, + * this function emits no events. + */ + function _setURI(string memory newuri) internal virtual { + _uri = newuri; + } + + /** + * @dev Creates `amount` tokens of token type `id`, and assigns them to `account`. + * + * Emits a {TransferSingle} event. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the + * acceptance magic value. + */ + function _mint(address account, uint256 id, uint256 amount, bytes memory data) internal virtual { + require(account != address(0), "ERC1155: mint to the zero address"); + + address operator = _msgSender(); + + _beforeTokenTransfer(operator, address(0), account, _asSingletonArray(id), _asSingletonArray(amount), data); + + _balances[id][account] = _balances[id][account].add(amount); + emit TransferSingle(operator, address(0), account, id, amount); + + _doSafeTransferAcceptanceCheck(operator, address(0), account, id, amount, data); + } + + /** + * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}. + * + * Requirements: + * + * - `ids` and `amounts` must have the same length. + * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the + * acceptance magic value. + */ + function _mintBatch(address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data) internal virtual { + require(to != address(0), "ERC1155: mint to the zero address"); + require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch"); + + address operator = _msgSender(); + + _beforeTokenTransfer(operator, address(0), to, ids, amounts, data); + + for (uint i = 0; i < ids.length; i++) { + _balances[ids[i]][to] = amounts[i].add(_balances[ids[i]][to]); + } + + emit TransferBatch(operator, address(0), to, ids, amounts); + + _doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data); + } + + /** + * @dev Destroys `amount` tokens of token type `id` from `account` + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens of token type `id`. + */ + function _burn(address account, uint256 id, uint256 amount) internal virtual { + require(account != address(0), "ERC1155: burn from the zero address"); + + address operator = _msgSender(); + + _beforeTokenTransfer(operator, account, address(0), _asSingletonArray(id), _asSingletonArray(amount), ""); + + _balances[id][account] = _balances[id][account].sub( + amount, + "ERC1155: burn amount exceeds balance" + ); + + emit TransferSingle(operator, account, address(0), id, amount); + } + + /** + * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}. + * + * Requirements: + * + * - `ids` and `amounts` must have the same length. + */ + function _burnBatch(address account, uint256[] memory ids, uint256[] memory amounts) internal virtual { + require(account != address(0), "ERC1155: burn from the zero address"); + require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch"); + + address operator = _msgSender(); + + _beforeTokenTransfer(operator, account, address(0), ids, amounts, ""); + + for (uint i = 0; i < ids.length; i++) { + _balances[ids[i]][account] = _balances[ids[i]][account].sub( + amounts[i], + "ERC1155: burn amount exceeds balance" + ); + } + + emit TransferBatch(operator, account, address(0), ids, amounts); + } + + /** + * @dev Hook that is called before any token transfer. This includes minting + * and burning, as well as batched variants. + * + * The same hook is called on both single and batched variants. For single + * transfers, the length of the `id` and `amount` arrays will be 1. + * + * Calling conditions (for each `id` and `amount` pair): + * + * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * of token type `id` will be transferred to `to`. + * - When `from` is zero, `amount` tokens of token type `id` will be minted + * for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens of token type `id` + * will be burned. + * - `from` and `to` are never both zero. + * - `ids` and `amounts` have the same, non-zero length. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address operator, + address from, + address to, + uint256[] memory ids, + uint256[] memory amounts, + bytes memory data + ) + internal virtual + { } + + function _doSafeTransferAcceptanceCheck( + address operator, + address from, + address to, + uint256 id, + uint256 amount, + bytes memory data + ) + internal + { + if (to.isContract()) { + try IERC1155Receiver(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) { + if (response != IERC1155Receiver(to).onERC1155Received.selector) { + revert("ERC1155: ERC1155Receiver rejected tokens"); + } + } catch Error(string memory reason) { + revert(reason); + } catch { + revert("ERC1155: transfer to non ERC1155Receiver implementer"); + } + } + } + + function _doSafeBatchTransferAcceptanceCheck( + address operator, + address from, + address to, + uint256[] memory ids, + uint256[] memory amounts, + bytes memory data + ) + internal + { + if (to.isContract()) { + try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns (bytes4 response) { + if (response != IERC1155Receiver(to).onERC1155BatchReceived.selector) { + revert("ERC1155: ERC1155Receiver rejected tokens"); + } + } catch Error(string memory reason) { + revert(reason); + } catch { + revert("ERC1155: transfer to non ERC1155Receiver implementer"); + } + } + } + + function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) { + uint256[] memory array = new uint256[](1); + array[0] = element; + + return array; + } +} diff --git a/assets/eip-3267/contracts/ERC1155/ERC1155TokenReceiver.sol b/assets/eip-3267/contracts/ERC1155/ERC1155TokenReceiver.sol new file mode 100644 index 00000000000000..7e888ba6599b6d --- /dev/null +++ b/assets/eip-3267/contracts/ERC1155/ERC1155TokenReceiver.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +pragma solidity ^0.7.1; + +import "./IERC1155TokenReceiver.sol"; +import "@openzeppelin/contracts/introspection/ERC165.sol"; + +abstract contract ERC1155TokenReceiver is ERC165, IERC1155TokenReceiver { + constructor() { + _registerInterface( + ERC1155TokenReceiver(0).onERC1155Received.selector ^ + ERC1155TokenReceiver(0).onERC1155BatchReceived.selector + ); + } +} diff --git a/assets/eip-3267/contracts/ERC1155/ERC1155WithTotals.sol b/assets/eip-3267/contracts/ERC1155/ERC1155WithTotals.sol new file mode 100644 index 00000000000000..95bf2285ced6a5 --- /dev/null +++ b/assets/eip-3267/contracts/ERC1155/ERC1155WithTotals.sol @@ -0,0 +1,100 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +pragma solidity ^0.7.1; +import "@openzeppelin/contracts/math/SafeMath.sol"; +import { ERC1155 } from "./ERC1155.sol"; + +/// @title A base contract for an ERC-1155 contract with calculation of totals. +abstract contract ERC1155WithTotals is ERC1155 { + using SafeMath for uint256; + + // Mapping (token => total). + mapping(uint256 => uint256) private totalBalances; + + /// Construct a token contract with given description URI. + /// @param uri_ Description URI. + constructor (string memory uri_) ERC1155(uri_) { } + + // Overrides // + + // Need also update totals - commented out + // function _mintBatch(address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data) internal virtual override { + // return super._mintBatch(_originalAddress(to), ids, amounts, data); + // } + + // Need also update totals - commented out + // function _burnBatch(address account, uint256[] memory ids, uint256[] memory amounts) internal virtual override { + // return super._burnBatch(_originalAddress(account), ids, amounts); + // } + + /// Total supply of a token (conforms to `IERC1155Views`). + /// @param id Token ID. + /// @return Total supply. + function totalSupply(uint256 id) public view returns (uint256) { + return totalBalances[id]; + } + + /// Mint a token. + /// @param to Whom to mint to. + /// @param id Token ID. + /// @param value Amount to mint. + /// @param data Additional data. + function _mint(address to, uint256 id, uint256 value, bytes memory data) internal override { + require(to != address(0), "ERC1155: mint to the zero address"); + + _doMint(to, id, value); + emit TransferSingle(msg.sender, address(0), to, id, value); + + _doSafeTransferAcceptanceCheck(msg.sender, address(0), to, id, value, data); + } + + /// Mint zero or more tokens. + /// @param to Whom to mint to. + /// @param ids Token IDs. + /// @param values Amounts to mint. + /// @param data Additional data. + function _batchMint(address to, uint256[] memory ids, uint256[] memory values, bytes memory data) internal { + require(to != address(0), "ERC1155: batch mint to the zero address"); + require(ids.length == values.length, "ERC1155: IDs and values must have same lengths"); + + for(uint i = 0; i < ids.length; i++) { + _doMint(to, ids[i], values[i]); + } + + emit TransferBatch(msg.sender, address(0), to, ids, values); + + _doSafeBatchTransferAcceptanceCheck(msg.sender, address(0), to, ids, values, data); + } + + /// Burn a token. + /// @param owner Whose tokens to burn. + /// @param id Token ID. + /// @param value Amount to mint. + function _burn(address owner, uint256 id, uint256 value) internal override { + _doBurn(owner, id, value); + emit TransferSingle(msg.sender, owner, address(0), id, value); + } + + /// Burn zero or more tokens. + /// @param owner Whose tokens to burn. + /// @param ids Token IDs. + /// @param values Amounts to mint. + function _batchBurn(address owner, uint256[] memory ids, uint256[] memory values) internal { + require(ids.length == values.length, "ERC1155: IDs and values must have same lengths"); + + for(uint i = 0; i < ids.length; i++) { + _doBurn(owner, ids[i], values[i]); + } + + emit TransferBatch(msg.sender, owner, address(0), ids, values); + } + + function _doMint(address to, uint256 id, uint256 value) private { + totalBalances[id] = totalBalances[id].add(value); + _balances[id][to] = _balances[id][to] + value; // The previous didn't overflow, therefore this doesn't overflow. + } + + function _doBurn(address from, uint256 id, uint256 value) private { + _balances[id][from] = _balances[id][from].sub(value); + totalBalances[id] = totalBalances[id] - value; // The previous didn't overflow, therefore this doesn't overflow. + } +} \ No newline at end of file diff --git a/assets/eip-3267/contracts/ERC1155/IERC1155.sol b/assets/eip-3267/contracts/ERC1155/IERC1155.sol new file mode 100644 index 00000000000000..2ecf0f1821e23d --- /dev/null +++ b/assets/eip-3267/contracts/ERC1155/IERC1155.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +pragma solidity ^0.7.1; + +import "@openzeppelin/contracts/introspection/IERC165.sol"; + +/** + @title ERC-1155 Multi Token Standard basic interface + @dev See https://eips.ethereum.org/EIPS/eip-1155 + */ +abstract contract IERC1155 is IERC165 { + event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value); + + event TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values); + + event ApprovalForAll(address indexed owner, address indexed operator, bool approved); + + event URI(string value, uint256 indexed id); + + function balanceOf(address owner, uint256 id) public view virtual returns (uint256); + + function balanceOfBatch(address[] memory owners, uint256[] memory ids) public view virtual returns (uint256[] memory); + + function setApprovalForAll(address operator, bool approved) external virtual; + + function isApprovedForAll(address owner, address operator) external view virtual returns (bool); + + function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external virtual; + + function safeBatchTransferFrom(address from, address to, uint256[] calldata ids, uint256[] calldata values, bytes calldata data) external virtual; +} diff --git a/assets/eip-3267/contracts/ERC1155/IERC1155TokenReceiver.sol b/assets/eip-3267/contracts/ERC1155/IERC1155TokenReceiver.sol new file mode 100644 index 00000000000000..f737f41c7104a6 --- /dev/null +++ b/assets/eip-3267/contracts/ERC1155/IERC1155TokenReceiver.sol @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +pragma solidity ^0.7.1; + +import "@openzeppelin/contracts/introspection/IERC165.sol"; + +/** + @title ERC-1155 Multi Token Receiver Interface + @dev See https://eips.ethereum.org/EIPS/eip-1155 +*/ +abstract contract IERC1155TokenReceiver is IERC165 { + + /** + @dev Handles the receipt of a single ERC1155 token type. This function is + called at the end of a `safeTransferFrom` after the balance has been updated. + To accept the transfer, this must return + `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` + (i.e. 0xf23a6e61, or its own function selector). + @param operator The address which initiated the transfer (i.e. msg.sender) + @param from The address which previously owned the token + @param id The ID of the token being transferred + @param value The amount of tokens being transferred + @param data Additional data with no specified format + @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed + */ + function onERC1155Received( + address operator, + address from, + uint256 id, + uint256 value, + bytes calldata data + ) + external virtual + returns(bytes4); + + /** + @dev Handles the receipt of a multiple ERC1155 token types. This function + is called at the end of a `safeBatchTransferFrom` after the balances have + been updated. To accept the transfer(s), this must return + `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` + (i.e. 0xbc197c81, or its own function selector). + @param operator The address which initiated the batch transfer (i.e. msg.sender) + @param from The address which previously owned the token + @param ids An array containing ids of each token being transferred (order and length must match values array) + @param values An array containing amounts of each token being transferred (order and length must match ids array) + @param data Additional data with no specified format + @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed + */ + function onERC1155BatchReceived( + address operator, + address from, + uint256[] calldata ids, + uint256[] calldata values, + bytes calldata data + ) + external virtual + returns(bytes4); +} diff --git a/assets/eip-3267/contracts/ERC1155/README.md b/assets/eip-3267/contracts/ERC1155/README.md new file mode 100644 index 00000000000000..8f69c423feb210 --- /dev/null +++ b/assets/eip-3267/contracts/ERC1155/README.md @@ -0,0 +1,12 @@ +--- +sections: + - title: Core + contracts: + - IERC1155 + - ERC1155 + - IERC1155TokenReceiver +--- + +This set of interfaces and contracts are all related to the [ERC1155 Multi Token Standard](https://eips.ethereum.org/EIPS/eip-1155). + +The EIP consists of two interfaces which fulfill different roles, found here as `IERC1155` and `IERC1155TokenReceiver`. Only `IERC1155` is required for a contract to be ERC1155 compliant. The basic functionality is implemented in `ERC1155`. diff --git a/assets/eip-3267/contracts/README.md b/assets/eip-3267/contracts/README.md new file mode 100644 index 00000000000000..47e04b2250cb77 --- /dev/null +++ b/assets/eip-3267/contracts/README.md @@ -0,0 +1,31 @@ +This directory contains contract sources for EIP 3267 draft. + +The audit of the contracts was paid for, now it is in progress. +(There are some FIXME/TODO comments for the auditors.) + +The contracts are to be compiled with Solidity 0.7.6. + +Dependencies (Node.js packages): + +- @openzeppelin/contracts 3.3.0 +- abdk-libraries-solidity 2.4.0 + +The contracts to be deployed are: +- SalaryWithDAO +- DefaultDAOInterface + +The sources: +- [ERC1155/ERC1155.sol](./ERC1155/ERC1155.sol) +- [ERC1155/ERC1155TokenReceiver.sol](./ERC1155/ERC1155TokenReceiver.sol) +- [ERC1155/ERC1155WithTotals.sol](./ERC1155/ERC1155WithTotals.sol) +- [ERC1155/IERC1155.sol](./ERC1155/IERC1155.sol) +- [ERC1155/IERC1155TokenReceiver.sol](./ERC1155/IERC1155TokenReceiver.sol) +- [BaseBidOnAddresses.sol](./BaseBidOnAddresses.sol) +- [BaseLock.sol](./BaseLock.sol) +- [BaseRestorableSalary.sol](./BaseRestorableSalary.sol) +- [BaseSalary.sol](./BaseSalary.sol) +- [BidOnAddresses.sol](./BidOnAddresses.sol) +- [DAOInterface.sol](./DAOInterface.sol) +- [DefaultDAOInterface.sol](./DefaultDAOInterface.sol) +- [Salary.sol](./Salary.sol) +- [SalaryWithDAO.sol](./SalaryWithDAO.sol) diff --git a/assets/eip-3267/contracts/Salary.sol b/assets/eip-3267/contracts/Salary.sol new file mode 100644 index 00000000000000..5cbc23d57d4389 --- /dev/null +++ b/assets/eip-3267/contracts/Salary.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +pragma solidity ^0.7.1; +import "./BaseSalary.sol"; + +/// @title "Salary" that is paid one token per second using minted conditionals. +/// @author Victor Porton +/// @notice Not audited, not enough tested. +contract Salary is BaseSalary { + /// @param _uri The ERC-1155 token URI. + constructor(string memory _uri) BaseSalary(_uri) { } + + /// Register a salary recipient. + /// + /// Can be called both before or after the oracle finish. However registering after the finish is useless. + /// + /// Anyone can register anyone (useful for robots registering a person). + /// + /// Registering another person is giving him money against his will (forcing to hire bodyguards, etc.), + /// but if one does not want, he can just not associate this address with his identity in his publications. + /// @param _customer The original address. + /// @param _oracleId The oracle ID. + /// @param _data The current data. + function registerCustomer(address _customer, uint64 _oracleId, bytes calldata _data) + virtual public returns (uint256) + { + return _registerCustomer(_customer, _oracleId, _data); + } +} \ No newline at end of file diff --git a/assets/eip-3267/contracts/SalaryWithDAO.sol b/assets/eip-3267/contracts/SalaryWithDAO.sol new file mode 100644 index 00000000000000..6b6fc23172669c --- /dev/null +++ b/assets/eip-3267/contracts/SalaryWithDAO.sol @@ -0,0 +1,126 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +pragma solidity ^0.7.1; +import { ABDKMath64x64 } from "abdk-libraries-solidity/ABDKMath64x64.sol"; +import "./BaseRestorableSalary.sol"; +import "./DAOInterface.sol"; + +/// Salary system with a "DAO" that can assign attorneys to restore lost Ethereum accounts. +/// @author Victor Porton +/// @notice Not audited, not enough tested. +contract SalaryWithDAO is BaseRestorableSalary { + using ABDKMath64x64 for int128; + + /// The DAO interface. + DAOInterface public daoPlugin; + + /// When set to true, your account can't be moved to new address (by the DAO). + /// + /// By default new users are not under DAO control to avoid front-running of resigning control + /// by an evil DAO. + /// + /// Mapping (current address => under control) + mapping (address => bool) public underDAOControl; + + /// Mapping (current address => account has at least one salary). + mapping (address => bool) public accountHasSalary; + + // DAO share will be zero to prevent theft by voters and because it can be done instead by future voting. + // int128 public daoShare = int128(0).div(1); // zero by default + + /// Constructor. + /// @param _daoPlugin The DAO interface. + /// @param _uri The ERC-1155 token URI. + constructor(DAOInterface _daoPlugin, string memory _uri) + BaseRestorableSalary(_uri) + { + daoPlugin = _daoPlugin; + } + + /// Create an oracle for caclcualting salary amounts. + function createOracle() external returns (uint64) { + return _createOracle(); + } + + /// Register a salary recipient. + /// + /// Can be called both before or after the oracle finish. However registering after the finish is useless. + /// + /// Anyone can register anyone (useful for robots registering a person). + /// + /// Registering another person is giving him money against his will (forcing to hire bodyguards, etc.), + /// but if one does not want, he can just not associate this address with his identity in his publications. + /// @param _customer The original address. + /// @param _oracleId The oracle ID. + /// @param _underDAOControl If the registered address will be under DAO control. + /// @param _data The current data. + function registerCustomer(address _customer, uint64 _oracleId, bool _underDAOControl, bytes calldata _data) + virtual public returns (uint256) + { + address _orig = _originalAddress(_customer); + // Auditor: Check that this value is set to false, when (and if) necessary. + accountHasSalary[_customer] = true; + underDAOControl[_customer] = _underDAOControl; // We don't trigger and event to reduce gas usage. + return super._registerCustomer(_orig, _oracleId, _data); + } + + /// A user can agree for DAO control. Then his account can be restored by DAO for the expense + /// of the DAO assigned personnel or software being able to steal his funds. + /// + /// Be exteremely careful calling this method: If you refuse and lose your key, your funds are lost! + /// + /// Fishers may trick one to resign mistakenly. However, it's no much worse than just fishing for + /// withdrawing the salary token, because a user could just register anew and notify traders/oracles + /// that it's the same person. + function setDAOControl(bool _underControl) public { + address _orig = _originalAddress(msg.sender); + require(accountHasSalary[_orig], "Cannot resign account receiving a salary."); + underDAOControl[_orig] = _underControl; // We don't trigger and event to reduce gas usage. + } + + /// The DAO can replace itself. + function setDAO(DAOInterface _daoPlugin) public onlyDAO { + daoPlugin = _daoPlugin; + } + + /// Set the token URI. + function setURI(string memory _newuri) public onlyDAO { + _setURI(_newuri); + } + + // Overrides /// + + function checkAllowedRestoreAccount(address _oldAccount, address _newAccount) + public virtual override isUnderDAOControl(_oldAccount) + { + daoPlugin.checkAllowedRestoreAccount(_oldAccount, _newAccount); + } + + /// Allow the user to unrestore by himself? + /// We won't not allow it to `_oldAccount` because it may be a stolen private key. + /// We could allow it to `_newAccount`, but this makes no much sense, because + /// it would only prevent the user to do a theft by himself, let only DAO could be allowed to do. + function checkAllowedUnrestoreAccount(address _oldAccount, address _newAccount) + public virtual override isUnderDAOControl(_oldAccount) + { + daoPlugin.checkAllowedUnrestoreAccount(_oldAccount, _newAccount); + } + + // Internal // + + function _isDAO() internal view returns (bool) { + return msg.sender == address(daoPlugin); + } + + // Modifiers // + + modifier onlyDAO() { + require(_isDAO(), "Only DAO can do."); + _; + } + + /// @param _customer The current address. + modifier isUnderDAOControl(address _customer) { + require(underDAOControl[_customer], "Not under DAO control."); + _; + } +} diff --git a/assets/eip-3267/science-salaries.pdf b/assets/eip-3267/science-salaries.pdf new file mode 100644 index 00000000000000..a6a243c68ce9d1 Binary files /dev/null and b/assets/eip-3267/science-salaries.pdf differ diff --git a/eip-template.md b/eip-template.md index dbf2518f213e03..112192e1606357 100644 --- a/eip-template.md +++ b/eip-template.md @@ -18,19 +18,19 @@ Note that an EIP number will be assigned by an editor. When opening a pull reque The title should be 44 characters or less. ## Simple Summary -If you can't explain it simply, you don't understand it well enough." Provide a simplified and layman-accessible explanation of the EIP. +If you can't explain it simply, you don't understand it well enough." Provide a simplified and layman-accessible explanation of the EIP. Imagine an email subject line, GitHub PR title, or forum post title. ## Abstract -A short (~200 word) description of the technical issue being addressed. +A short (~200 word) description of the technical issue being addressed. This should be a very terse and human-readable version of the specification section. Someone should be able to read only the abstract to get the gist of what this specification does. ## Motivation -The motivation is critical for EIPs that want to change the Ethereum protocol. It should clearly explain why the existing protocol specification is inadequate to address the problem that the EIP solves. EIP submissions without sufficient motivation may be rejected outright. +The motivation section should describe the "why" of this EIP. What problem does it solve? Why should someone want to implement this standard? What benefit does it provide to the Ethereum ecosystem? What use cases does this EIP address? ## Specification The technical specification should describe the syntax and semantics of any new feature. The specification should be detailed enough to allow competing, interoperable implementations for any of the current Ethereum platforms (go-ethereum, parity, cpp-ethereum, ethereumj, ethereumjs, and [others](https://github.com/ethereum/wiki/wiki/Clients)). ## Rationale -The rationale fleshes out the specification by describing what motivated the design and why particular design decisions were made. It should describe alternate designs that were considered and related work, e.g. how the feature is supported in other languages. The rationale may also provide evidence of consensus within the community, and should discuss important objections or concerns raised during discussion. +The rationale fleshes out the specification by describing what motivated the design and why particular design decisions were made. It should describe alternate designs that were considered and related work, e.g. how the feature is supported in other languages. ## Backwards Compatibility All EIPs that introduce backwards incompatibilities must include a section describing these incompatibilities and their severity. The EIP must explain how the author proposes to deal with these incompatibilities. EIP submissions without a sufficient backwards compatibility treatise may be rejected outright. @@ -38,8 +38,8 @@ All EIPs that introduce backwards incompatibilities must include a section descr ## Test Cases Test cases for an implementation are mandatory for EIPs that are affecting consensus changes. Other EIPs can choose to include links to test cases if applicable. -## 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. +## Reference Implementation +An optional section that contains a reference/example implementation that people can use to assist in understanding or implementing this specification. If the implementation is too large to reasonably be included inline, then consider adding it as one or more files in `../assets/eip-####/`. ## Security Considerations All EIPs must contain a section that discusses the security implications/considerations relevant to the proposed change. Include information that might be important for security discussions, surfaces risks and can be used throughout the life cycle of the proposal. E.g. include security-relevant design decisions, concerns, important discussions, implementation-specific guidance and pitfalls, an outline of threats and risks and how they are being addressed. EIP submissions missing the "Security Considerations" section will be rejected. An EIP cannot proceed to status "Final" without a Security Considerations discussion deemed sufficient by the reviewers.