mirror of https://github.com/status-im/EIPs.git
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
0a98e9442c
|
@ -0,0 +1,7 @@
|
|||
uint
|
||||
ith
|
||||
mitre
|
||||
readded
|
||||
crate
|
||||
developper
|
||||
ist
|
|
@ -1,3 +1,4 @@
|
|||
_site
|
||||
.sass-cache
|
||||
.jekyll-metadata
|
||||
vendor
|
||||
|
|
|
@ -24,4 +24,6 @@ elif [[ $TASK = 'eip-validator' ]]; then
|
|||
|
||||
FILES="$(ls EIPS/*.md | egrep "eip-[0-9]+.md")"
|
||||
bundle exec eip_validator $FILES
|
||||
elif [[ $TASK = 'codespell' ]]; then
|
||||
codespell -q4 -I .codespell-whitelist eip-X.md EIPS/
|
||||
fi
|
||||
|
|
13
.travis.yml
13
.travis.yml
|
@ -10,7 +10,7 @@ cache:
|
|||
- bundler
|
||||
- directories:
|
||||
- $TRAVIS_BUILD_DIR/tmp/.htmlproofer #https://github.com/gjtorikian/html-proofer/issues/381
|
||||
|
||||
- /usr/local/lib/python3.3/dist-packages/pip/
|
||||
|
||||
# Assume bundler is being used, therefore
|
||||
# the `install` step will run `bundle install` by default.
|
||||
|
@ -23,14 +23,17 @@ env:
|
|||
matrix:
|
||||
fast_finish: true
|
||||
include:
|
||||
- rvm: 2.2.5
|
||||
- rvm: 2.3.0
|
||||
env: TASK='htmlproofer'
|
||||
- rvm: 2.2.5
|
||||
- rvm: 2.3.0
|
||||
env: TASK='htmlproofer-external'
|
||||
- rvm: 2.2.5
|
||||
- rvm: 2.3.0
|
||||
env: TASK='eip-validator'
|
||||
- python: 3.3
|
||||
env: TASK='codespell'
|
||||
before_script: "sudo pip install urllib3[secure] && sudo pip install codespell"
|
||||
allow_failures:
|
||||
- rvm: 2.2.5
|
||||
- rvm: 2.3.0
|
||||
env: TASK='htmlproofer-external'
|
||||
|
||||
notifications:
|
||||
|
|
124
EIPS/eip-1.md
124
EIPS/eip-1.md
|
@ -5,7 +5,8 @@ status: Active
|
|||
type: Meta
|
||||
author: Martin Becze <mb@ethereum.org>, Hudson Jameson <hudson@ethereum.org>, and others
|
||||
https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1.md
|
||||
created: 2015-10-27, 2017-02-01
|
||||
created: 2015-10-27
|
||||
updated: 2015-12-07, 2016-02-01, 2018-03-21, 2018-05-29, 2018-10-17, 2019-05-19
|
||||
---
|
||||
|
||||
## What is an EIP?
|
||||
|
@ -22,61 +23,95 @@ For Ethereum implementers, EIPs are a convenient way to track the progress of th
|
|||
|
||||
There are three types of EIP:
|
||||
|
||||
- A **Standard Track EIP** describes any change that affects most or all Ethereum implementations, such as a change to the 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].
|
||||
- A **Standard 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. [EIP5], [EIP101]), 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, [EIP90], and the miner/node strategy changes 2, 3, and 4 of [EIP86]).
|
||||
- **Networking** - includes improvements around [devp2p] ([EIP8]) 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 ([EIP59], [EIP6]) 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.
|
||||
- **Interface** - includes improvements around client [API/RPC] specifications and standards, and also certain language-level standards like method names ([EIP6]) 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 ([EIP82]), and wallet formats ([EIP75], [EIP85]).
|
||||
- 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.
|
||||
- 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.
|
||||
|
||||
An EIP must meet certain minimum criteria. It must be a clear and complete description of the proposed enhancement. The enhancement must represent a net improvement. The proposed implementation, if applicable, must be solid and must not complicate the protocol unduly.
|
||||
|
||||
### Special requirements for Core EIPs
|
||||
|
||||
If a **Core** EIP mentions or proposes changes to the EVM (Ethereum Virtual Machine), it should refer to the instructions by their mnemonics and define the opcodes of those mnemonics at least once. A preferred way is the following:
|
||||
```
|
||||
REVERT (0xfe)
|
||||
```
|
||||
|
||||
## EIP Work Flow
|
||||
|
||||
### Shepherding an EIP
|
||||
|
||||
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).
|
||||
|
||||
:warning: Before you begin, vet your idea, this will save you time. 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 (searching the Internet does not always do the trick). It also helps to make sure the idea is applicable to the entire community and not just the author. Just because an idea sounds good to the author does not mean it will work for most people in most areas where Ethereum is used. Examples of appropriate public forums to gauge interest around your EIP include [the Ethereum subreddit], [the Issues section of this repository], and [one of the Ethereum Gitter chat rooms]. In particular, [the Issues section of this repository] is an excellent place to discuss your proposal with the community and start creating more formalized language around your EIP.
|
||||
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].
|
||||
|
||||
Your role as the champion is to write the EIP using the style and format described below, shepherd the discussions in the appropriate forums, and build community consensus around the idea. Following is the process that a successful EIP will move along:
|
||||
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.
|
||||
|
||||
### Core EIPs
|
||||
|
||||
For Core EIPs, given that they require client implementations to be considered **Final** (see "EIPs Process" below), you will need to either provide an implementation for clients or convince clients to implement your EIP.
|
||||
|
||||
The best way to get client implementers to review your EIP is to present it on an AllCoreDevs call. You can request to do so by posting a comment linking your EIP on an [AllCoreDevs agenda GitHub Issue].
|
||||
|
||||
The AllCoreDevs call serve as a way for client implementers to do three things. First, to discuss the technical merits of EIPs. Second, to gauge what other clients will be implementing. Third, to coordinate EIP implementation for network upgrades.
|
||||
|
||||
These calls generally result in a "rough consensus" around what EIPs should be implemented. This "rough consensus" rests on the assumptions that EIPs are not contentious enough to cause a network split and that they are technically sound.
|
||||
|
||||
:warning: The EIPs process and AllCoreDevs call were not designed to address contentious non-technical issues, but, due to the lack of other ways to address these, often end up entangled in them. This puts the burden on client implementers to try and gauge community sentiment, which hinders the technical coordination function of EIPs and AllCoreDevs calls. If you are shepherding an EIP, you can make the process of building community consensus easier by making sure that [the Ethereum Magicians forum] thread for your EIP includes or links to as much of the community discussion as possible and that various stakeholders are well-represented.
|
||||
|
||||
*In short, your role as the champion is to write the EIP using the style and format described below, shepherd the discussions in the appropriate forums, and build community consensus around the idea.*
|
||||
|
||||
### EIP Process
|
||||
|
||||
Following is the process that a successful non-Core EIP will move along:
|
||||
|
||||
```
|
||||
[ WIP ] -> [ DRAFT ] -> [ LAST CALL ] -> [ ACCEPTED ] -> [ FINAL ]
|
||||
[ WIP ] -> [ DRAFT ] -> [ LAST CALL ] -> [ FINAL ]
|
||||
```
|
||||
|
||||
Following is the process that a successful Core EIP will move along:
|
||||
|
||||
```
|
||||
[ IDEA ] -> [ DRAFT ] -> [ LAST CALL ] -> [ ACCEPTED ] -> [ FINAL ]
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
* **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).
|
||||
* **Work in progress (WIP)** -- 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.
|
||||
* **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 http://eips.ethereum.org/ website (subscribe via RSS at [last-call.xml](/last-call.xml)).
|
||||
* **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 (Not core EIPs) -- A successful Last Call without material changes or unaddressed technical complaints will become Final.
|
||||
* **Accepted (Core EIPs only)** -- This EIP is in the hands of the Ethereum client developers. 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: 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:
|
||||
|
||||
* **Deferred** -- This is for core EIPs that have been put off for a future hard fork.
|
||||
* **Rejected** -- An EIP that is fundamentally broken or a Core EIP that was rejected by the Core Devs and will not be implemented.
|
||||
* **Active** -- This is similar to Final, but denotes an EIP which which may be updated without changing its EIP number.
|
||||
* **Superseded** -- An EIP which was previously final but is no longer considered state-of-the-art. Another EIP will be in Final status and reference the Superseded EIP.
|
||||
* **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.
|
||||
|
||||
## 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.
|
||||
- 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.
|
||||
- Abstract - a short (~200 word) description of the technical issue being addressed.
|
||||
- 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.
|
||||
- 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.
|
||||
|
@ -88,37 +123,39 @@ Each EIP should have the following parts:
|
|||
## EIP Formats and Templates
|
||||
|
||||
EIPs should be written in [markdown] format.
|
||||
Image files should be included in a subdirectory of the `assets` folder for that EIP as follow: `assets/eip-X` (for eip **X**). When linking to an image in the EIP, use relative links such as `../assets/eip-X/image.png`.
|
||||
Image 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`.
|
||||
|
||||
## EIP Header Preamble
|
||||
|
||||
Each EIP must begin with an RFC 822 style header preamble, preceded and followed by three hyphens (`---`). The headers must appear in the following order. Headers marked with "*" are optional and are described below. All other headers are required.
|
||||
Each EIP must begin with an [RFC 822](https://www.ietf.org/rfc/rfc822.txt) style header preamble, preceded and followed by three hyphens (`---`). This header is also termed ["front matter" by Jekyll](https://jekyllrb.com/docs/front-matter/). The headers must appear in the following order. Headers marked with "*" are optional and are described below. All other headers are required.
|
||||
|
||||
` eip:` <EIP number> (this is determined by the EIP editor)
|
||||
` eip:` *EIP number* (this is determined by the EIP editor)
|
||||
|
||||
` title:` <EIP title>
|
||||
` title:` *EIP title*
|
||||
|
||||
` author:` <a list of the author's or authors' name(s) and/or username(s), or name(s) and email(s). Details are below.>
|
||||
` author:` *a list of the author's or authors' name(s) and/or username(s), or name(s) and email(s). Details are below.*
|
||||
|
||||
` * discussions-to:` \<a url pointing to the official discussion thread\>
|
||||
` * discussions-to:` *a url pointing to the official discussion thread*
|
||||
|
||||
` status:` <Draft | Last Call | Accepted | Final | Active | Deferred | Rejected | Superseded>
|
||||
` status:` *Draft | Last Call | Accepted | Final | Active | Abandoned | Rejected | Superseded*
|
||||
|
||||
`* review-period-end:` <date review period ends>
|
||||
`* review-period-end:` *date review period ends*
|
||||
|
||||
` type:` <Standards Track (Core, Networking, Interface, ERC) | Informational | Meta>
|
||||
` type:` *Standards Track | Informational | Meta*
|
||||
|
||||
` * category:` <Core | Networking | Interface | ERC>
|
||||
` * category:` *Core | Networking | Interface | ERC* (Standards Track EIPs only)
|
||||
|
||||
` created:` <date created on>
|
||||
` created:` *date created on*
|
||||
|
||||
` * requires:` <EIP number(s)>
|
||||
` * updated:` *comma separated list of dates*
|
||||
|
||||
` * replaces:` <EIP number(s)>
|
||||
` * requires:` *EIP number(s)*
|
||||
|
||||
` * superseded-by:` <EIP number(s)>
|
||||
` * replaces:` *EIP number(s)*
|
||||
|
||||
` * resolution:` \<a url pointing to the resolution of this EIP\>
|
||||
` * superseded-by:` *EIP number(s)*
|
||||
|
||||
` * resolution:` *a url pointing to the resolution of this EIP*
|
||||
|
||||
Headers that permit lists must separate elements with commas.
|
||||
|
||||
|
@ -164,6 +201,10 @@ The `category` header specifies the EIP's category. This is required for standar
|
|||
|
||||
The `created` header records the date that the EIP was assigned a number. Both headers should be in yyyy-mm-dd format, e.g. 2001-08-14.
|
||||
|
||||
#### `updated` header
|
||||
|
||||
The `updated` header records the date(s) when the EIP was updated with "substantial" changes. This header is only valid for EIPs of Draft and Active status.
|
||||
|
||||
#### `requires` header
|
||||
|
||||
EIPs may have a `requires` header, indicating the EIP numbers that this EIP depends on.
|
||||
|
@ -198,13 +239,17 @@ The current EIP editors are
|
|||
|
||||
` * Martin Becze (@wanderer)`
|
||||
|
||||
` * Greg Colvin (@gcolvin)`
|
||||
|
||||
` * Alex Beregszaszi (@axic)`
|
||||
|
||||
## EIP Editor Responsibilities
|
||||
|
||||
For each new EIP that comes in, an editor does the following:
|
||||
|
||||
- Read the EIP to check if it is ready: sound and complete. The ideas must make technical sense, even if they don't seem likely to get to final status.
|
||||
- The title should accurately describe the content.
|
||||
- Check the EIP for language (spelling, grammar, sentence structure, etc.), markup (Github flavored Markdown), code style
|
||||
- Check the EIP for language (spelling, grammar, sentence structure, etc.), markup (GitHub flavored Markdown), code style
|
||||
|
||||
If the EIP isn't ready, the editor will send it back to the author for revision, with specific instructions.
|
||||
|
||||
|
@ -224,14 +269,18 @@ The editors don't pass judgment on EIPs. We merely do the administrative & edito
|
|||
|
||||
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, 2016: EIP 1 has been improved and will be placed as a PR.
|
||||
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](http://eips.ethereum.org/).
|
||||
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.
|
||||
|
||||
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
|
||||
|
@ -246,7 +295,6 @@ See [the revision history for further details](https://github.com/ethereum/EIPs/
|
|||
[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
|
||||
[EIP59]: https://github.com/ethereum/EIPs/issues/59
|
||||
[EIP6]: 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
|
||||
|
@ -265,6 +313,8 @@ See [the revision history for further details](https://github.com/ethereum/EIPs/
|
|||
[markdown]: https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet
|
||||
[Bitcoin's BIP-0001]: https://github.com/bitcoin/bips
|
||||
[Python's PEP-0001]: https://www.python.org/dev/peps/
|
||||
[the Ethereum Magicians forum]: https://ethereum-magicians.org/
|
||||
[AllCoreDevs agenda GitHub Issue]: https://github.com/ethereum/pm/issues
|
||||
|
||||
## Copyright
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
eip: 100
|
||||
title: Change difficulty adjustment to target mean block time including uncles
|
||||
author: Vitalik Buterin
|
||||
author: Vitalik Buterin (@vbuterin)
|
||||
type: Standards Track
|
||||
category: Core
|
||||
status: Final
|
||||
|
|
|
@ -183,7 +183,7 @@ def check_and_finalize_new_checkpoint(new_block):
|
|||
db.last_finalized_block = finalized_hash
|
||||
```
|
||||
|
||||
The new chain scoring rule queries the casper contract to find the highest justified epoch that meets the client's minimum deposit requirement (`NON_REVERT_MIN_DEPOSITS`). The `10**40` multiplier ensures that the justified epoch takes precendence over block mining difficulty. `total_difficulty` only serves as a tie breaker if the two blocks in question have an equivalent `highest_justified_epoch`.
|
||||
The new chain scoring rule queries the casper contract to find the highest justified epoch that meets the client's minimum deposit requirement (`NON_REVERT_MIN_DEPOSITS`). The `10**40` multiplier ensures that the justified epoch takes precedence over block mining difficulty. `total_difficulty` only serves as a tie breaker if the two blocks in question have an equivalent `highest_justified_epoch`.
|
||||
|
||||
_Note_: If the client has no justified checkpoints, the contract returns `highest_justified_epoch` as `0` essentially reverting the fork choice rule to pure PoW.
|
||||
|
||||
|
@ -379,7 +379,7 @@ Any call to this method fails prior to the end of the `WARM_UP_PERIOD`. Thus the
|
|||
#### Issuance
|
||||
A fixed amount of 1.25M ETH was chosen as `CASPER_BALANCE` to fund the casper contract. This gives the contract enough runway to operate for approximately 2 years (assuming ~10M ETH in validator deposits). Acting similarly to the "difficulty bomb", this "funding crunch" forces the network to hardfork in the relative near future to further fund the contract. This future hardfork is an opportunity to upgrade the contract and transition to full PoS.
|
||||
|
||||
The PoW block reward is reduced from 3.0 to 0.6 ETH/block over the course of approximately one year because the security of the chain is greatly shifted from PoW difficulty to PoS finality and because rewards are now issued to both validators and miners. Rewards are stepped down by 0.6 ETH/block every 3 months (`REWARD_STEPDOWN_BLOCK_COUNT`) to provide for a conservative transition period from full PoW to hybrid PoS/PoW. This gives validators time to become familiar with the new technology and begin logging on and also provides the network with more leeway in case of any unforseen issues. If any major issues do arise, the Ethereum network will still have substantial PoW security to rely upon while decisions are made and/or patches are deployed. See [here](https://gist.github.com/djrtwo/bc864c0d0a275170183803814b207b9a) for further analysis of the current PoW security and of the effect of PoW block reward reduction in the context of Hybrid Casper FFG.
|
||||
The PoW block reward is reduced from 3.0 to 0.6 ETH/block over the course of approximately one year because the security of the chain is greatly shifted from PoW difficulty to PoS finality and because rewards are now issued to both validators and miners. Rewards are stepped down by 0.6 ETH/block every 3 months (`REWARD_STEPDOWN_BLOCK_COUNT`) to provide for a conservative transition period from full PoW to hybrid PoS/PoW. This gives validators time to become familiar with the new technology and begin logging on and also provides the network with more leeway in case of any unforeseen issues. If any major issues do arise, the Ethereum network will still have substantial PoW security to rely upon while decisions are made and/or patches are deployed. See [here](https://gist.github.com/djrtwo/bc864c0d0a275170183803814b207b9a) for further analysis of the current PoW security and of the effect of PoW block reward reduction in the context of Hybrid Casper FFG.
|
||||
|
||||
In addition to block rewards, miners now receive an issuance reward for including successful `vote` transactions into the block on time. This reward is equal to 1/8th that of the reward the validator receives for a successful `vote` transaction. Under optimal FFG conditions after group validator reward adjustments are made, miners receive approximately 1/5th of the total ETH issued by the Casper contract.
|
||||
|
||||
|
|
|
@ -3,9 +3,9 @@ eip: 1013
|
|||
title: "Hardfork Meta: Constantinople"
|
||||
author: Nick Savers (@nicksavers)
|
||||
type: Meta
|
||||
status: Draft
|
||||
status: Final
|
||||
created: 2018-04-20
|
||||
requires: 145, 1014, 1052, 1234, 1283
|
||||
requires: 145, 609, 1014, 1052, 1234, 1283
|
||||
---
|
||||
|
||||
## Abstract
|
||||
|
@ -17,18 +17,21 @@ This meta-EIP specifies the changes included in the Ethereum hardfork named Cons
|
|||
- Codename: Constantinople
|
||||
- Aliases: Metropolis/Constantinople, Metropolis part 2
|
||||
- Activation:
|
||||
- Block >= TBD on the Ethereum mainnet
|
||||
- Block >= 4,230,000 on the Ropsten testnet
|
||||
- `Block >= 7_280_000` on the Ethereum mainnet
|
||||
- `Block >= 4,230,000` on the Ropsten testnet
|
||||
- `Block >= 9_200_000` on the Kovan testnet
|
||||
- `Block >= 3_660_663` on the Rinkeby testnet
|
||||
- Included EIPs:
|
||||
- [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
|
||||
- [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
|
||||
|
||||
## References
|
||||
|
||||
The list above includes the EIPs discussed as candidates for Constantinople at the All Core Dev [Constantinople Session #1](https://github.com/ethereum/pm/issues/55). See also [Constantinople Progress Tracker](https://github.com/ethereum/pm/wiki/Constantinople-Progress-Tracker).
|
||||
1. The list above includes the EIPs discussed as candidates for Constantinople at the All Core Dev [Constantinople Session #1](https://github.com/ethereum/pm/issues/55). See also [Constantinople Progress Tracker](https://github.com/ethereum/pm/wiki/Constantinople-Progress-Tracker).
|
||||
2. https://blog.ethereum.org/2019/02/22/ethereum-constantinople-st-petersburg-upgrade-announcement/
|
||||
|
||||
## Copyright
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ title: Skinny CREATE2
|
|||
author: Vitalik Buterin (@vbuterin)
|
||||
category: Core
|
||||
type: Standards Track
|
||||
status: Accepted
|
||||
status: Final
|
||||
created: 2018-04-20
|
||||
---
|
||||
|
||||
|
@ -52,7 +52,7 @@ With [EIP 161](https://eips.ethereum.org/EIPS/eip-161)
|
|||
|
||||
> 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
|
||||
|
||||
This means that if a contract is created in a transaction, the `nonce` is immediately non-zero, with the side-effect that a collision within the same transaction will always fail -- even if it's carried out from the `init_code` itself/
|
||||
This means that if a contract is created in a transaction, the `nonce` is immediately non-zero, with the side-effect that a collision within the same transaction will always fail -- even if it's carried out from the `init_code` itself.
|
||||
|
||||
It should also be noted that `SELFDESTRUCT` has no immediate effect on `nonce` or `code`, thus a contract cannot be destroyed and recreated within one transaction.
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ created: 2018-04-20
|
|||
|
||||
## Simple Summary
|
||||
|
||||
This EIP changes the block reward step by instead of setting it to be hard coded on the clients and to be given to the miner/validator etherbase, it should instead go to an address decided by an on-chain contract, with hard limits on how it would be issued (six month lock-in; issuance can only decrease or be mantained, but not increase;). A decision method is suggested but not essential to the notion of this EIP. This would **not be a generic governance solution**, which is a much broader and harder topic, would **not** affect technical upgrade decisions or other hard forks, but seen as *a forum to attempt to prevent contentious hard forks* that can be solved with the issuance.
|
||||
This EIP changes the block reward step by instead of setting it to be hard coded on the clients and to be given to the miner/validator etherbase, it should instead go to an address decided by an on-chain contract, with hard limits on how it would be issued (six month lock-in; issuance can only decrease or be maintained, but not increase;). A decision method is suggested but not essential to the notion of this EIP. This would **not be a generic governance solution**, which is a much broader and harder topic, would **not** affect technical upgrade decisions or other hard forks, but seen as *a forum to attempt to prevent contentious hard forks* that can be solved with the issuance.
|
||||
|
||||
## Summary
|
||||
### Thesis: many controversial issues boil down to resources
|
||||
|
@ -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 outweight 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](http://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](http://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](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.
|
||||
|
||||
|
||||
#### 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](http://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](https://eips.ethereum.org/EIPS/eip-908), fair distribution of tokens etc.
|
||||
|
||||
## Proposed Solution
|
||||
### Issuance Contract
|
||||
|
@ -52,7 +52,7 @@ It's not meant to be a general governance contract. The contract **should NOT be
|
|||
|
||||
##### It cannot only decrease issuance, and once decreased it cannot be increased again
|
||||
|
||||
In order to reduce future abuse and uncertainity, **once issuance is reduced, it cannot be increased**. To prevent a single action reducing it to 0, the reduction is limited up to a percentage per time, so if the **decision assembly** is agressively to reduce issuance to zero, it would take a known number of years.
|
||||
In order to reduce future abuse and uncertainty, **once issuance is reduced, it cannot be increased**. To prevent a single action reducing it to 0, the reduction is limited up to a percentage per time, so if the **decision assembly** is aggressively to reduce issuance to zero, it would take a known number of years.
|
||||
|
||||
##### Results are locked for six months
|
||||
|
||||
|
@ -109,7 +109,7 @@ A lot of things are suggested in this EIP, so I would like to propose these ques
|
|||
|
||||
1. Do we want to have dynamically changing block rewards, instead of having them be hard coded in the protocol?
|
||||
2. If the answer above is yes, then what would be the best governance process to decide it, and what sorts of limits would we want that governance contract to have?
|
||||
3. If the answer is a multi-signalling contract, then what sorts of signals would we want, what sort of relative weight should they have and what would be the proccess to add and remove them?
|
||||
3. If the answer is a multi-signalling contract, then what sorts of signals would we want, what sort of relative weight should they have and what would be the process to add and remove them?
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -3,10 +3,11 @@ eip: 1052
|
|||
title: EXTCODEHASH opcode
|
||||
author: Nick Johnson <arachnid@notdot.net>, Paweł Bylica <pawel@ethereum.org>
|
||||
discussions-to: https://ethereum-magicians.org/t/extcodehash-opcode/262
|
||||
status: Accepted
|
||||
status: Final
|
||||
type: Standards Track
|
||||
category: Core
|
||||
created: 2018-05-02
|
||||
requires: 161
|
||||
---
|
||||
|
||||
## Abstract
|
||||
|
@ -24,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 `0` is pushed to the stack.
|
||||
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 have code the keccak256 hash of empty data
|
||||
(i.e. `c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470`)
|
||||
|
|
|
@ -0,0 +1,286 @@
|
|||
---
|
||||
eip: 1056
|
||||
title: Ethereum Lightweight Identity
|
||||
author: Pelle Braendgaard <pelle.braendgaard@consensys.net>, Joel Torstensson <oed@consensys.net>
|
||||
type: Standards Track
|
||||
category: ERC
|
||||
discussions-to: https://github.com/ethereum/EIPs/issues/1056
|
||||
status: Draft
|
||||
created: 2018-05-03
|
||||
---
|
||||
|
||||
## Simple Summary
|
||||
|
||||
A registry for key and attribute management of lightweight blockchain identities.
|
||||
|
||||
## Abstract
|
||||
|
||||
This ERC describes a standard for creating and updating identities with a limited use of blockchain resources. An identity can have an unlimited number of `delegates` and `attributes` associated with it. Identity creation is as simple as creating a regular key pair ethereum account, which means that it's free (no gas costs) and all ethereum accounts are valid identities. Furthermore this ERC is fully [DID compliant](https://w3c-ccg.github.io/did-spec/).
|
||||
|
||||
## 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://github.com/ethereum/EIPs/issues/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.
|
||||
|
||||
## Definitions
|
||||
|
||||
* `Identifier`: a piece of data that uniquely identifies the identity, an ethereum address
|
||||
|
||||
* `delegate`: an address that is delegated for a specific time to perform some sort of function on behalf of an identity
|
||||
|
||||
* `delegateType`: the type of a delegate, is determined by a protocol or application higher up
|
||||
Examples:
|
||||
|
||||
* `did-jwt`
|
||||
* `raiden`
|
||||
|
||||
* `attribute`: a piece of data associated with the identity
|
||||
|
||||
## Specification
|
||||
|
||||
This ERC specifies a contract called `EthereumDIDRegistry` that is deployed once and can then be commonly used by everyone.
|
||||
|
||||
### Identity ownership
|
||||
|
||||
By default an identity is owned by itself, meaning whoever controls the ethereum account with that address. The owner can be updated to a new key pair account or to a multisig account etc.
|
||||
|
||||
#### identityOwner
|
||||
|
||||
Returns the owner of the given identity.
|
||||
|
||||
```js
|
||||
function identityOwner(address identity) public view returns(address);
|
||||
```
|
||||
|
||||
#### changeOwner
|
||||
|
||||
Sets the owner of the given identity to another ethereum account.
|
||||
|
||||
```js
|
||||
function changeOwner(address identity, address newOwner) public;
|
||||
```
|
||||
|
||||
#### changeOwnerSigned
|
||||
|
||||
Same as above but with raw signature.
|
||||
|
||||
|
||||
```js
|
||||
function changeOwnerSigned(address identity, uint8 sigV, bytes32 sigR, bytes32 sigS, address newOwner) public;
|
||||
```
|
||||
|
||||
### Delegate management
|
||||
|
||||
Delegates can be used both on- and off-chain. They all have a `delegateType` which can be used to specify the purpose of the delegate.
|
||||
|
||||
#### validDelegate
|
||||
|
||||
Returns true if the given `delegate` is a delegate with type `delegateType` of `identity`.
|
||||
|
||||
```js
|
||||
function validDelegate(address identity, bytes32 delegateType, address delegate) public view returns(bool);
|
||||
```
|
||||
|
||||
#### addDelegate
|
||||
|
||||
Adds a new delegate with the given type. `validity` indicates the number of seconds that the delegate will be valid for, after which it will no longer be a delegate of `identity`.
|
||||
|
||||
```js
|
||||
function addDelegate(address identity, bytes32 delegateType, address delegate, uint validity) public;
|
||||
```
|
||||
|
||||
|
||||
#### addDelegateSigned
|
||||
|
||||
Same as above but with raw signature.
|
||||
|
||||
|
||||
```js
|
||||
function addDelegateSigned(address identity, uint8 sigV, bytes32 sigR, bytes32 sigS, bytes32 delegateType, address delegate, uint validity) public;
|
||||
```
|
||||
|
||||
|
||||
#### revokeDelegate
|
||||
|
||||
Revokes the given `delegate` for the given `identity`.
|
||||
|
||||
|
||||
```js
|
||||
function revokeDelegate(address identity, bytes32 delegateType, address delegate) public;
|
||||
```
|
||||
|
||||
|
||||
#### revokeDelegateSigned
|
||||
|
||||
Same as above but with raw signature.
|
||||
|
||||
|
||||
```js
|
||||
function revokeDelegateSigned(address identity, uint8 sigV, bytes32 sigR, bytes32 sigS, bytes32 delegateType, address delegate) public;
|
||||
```
|
||||
|
||||
|
||||
### Attribute management
|
||||
|
||||
Attributes contain simple data about the identity. They can be managed only by the owner of the identity.
|
||||
|
||||
|
||||
#### setAttribute
|
||||
|
||||
Sets an attribute with the given `name` and `value`, valid for `validity` seconds.
|
||||
|
||||
|
||||
```js
|
||||
function setAttribute(address identity, bytes32 name, bytes value, uint validity) public;
|
||||
```
|
||||
|
||||
|
||||
#### setAttributeSigned
|
||||
|
||||
Same as above but with raw signature.
|
||||
|
||||
|
||||
```js
|
||||
function setAttributeSigned(address identity, uint8 sigV, bytes32 sigR, bytes32 sigS, bytes32 name, bytes value, uint validity) public;
|
||||
```
|
||||
|
||||
|
||||
#### revokeAttrubte
|
||||
|
||||
Revokes an attribute.
|
||||
|
||||
|
||||
```js
|
||||
function revokeAttribute(address identity, bytes32 name, bytes value) public;
|
||||
```
|
||||
|
||||
|
||||
#### revokeAttributeSigned
|
||||
|
||||
Same as above but with raw signature.
|
||||
|
||||
|
||||
```js
|
||||
function revokeAttributeSigned(address identity, uint8 sigV, bytes32 sigR, bytes32 sigS, bytes32 name, bytes value) public;
|
||||
```
|
||||
|
||||
|
||||
### Events
|
||||
|
||||
#### DIDOwnerChanged
|
||||
|
||||
MUST be triggered when `changeOwner` or `changeOwnerSigned` was successfully called.
|
||||
|
||||
|
||||
```js
|
||||
event DIDOwnerChanged(
|
||||
address indexed identity,
|
||||
address owner,
|
||||
uint previousChange
|
||||
);
|
||||
```
|
||||
|
||||
|
||||
#### DIDDelegateChanged
|
||||
|
||||
MUST be triggered when a change to a delegate was successfully made.
|
||||
|
||||
|
||||
```js
|
||||
event DIDDelegateChanged(
|
||||
address indexed identity,
|
||||
bytes32 delegateType,
|
||||
address delegate,
|
||||
uint validTo,
|
||||
uint previousChange
|
||||
);
|
||||
```
|
||||
|
||||
|
||||
#### DIDAttritueChanged
|
||||
|
||||
MUST be triggered when a change to an attribute was successfully made.
|
||||
|
||||
|
||||
```js
|
||||
event DIDAttributeChanged(
|
||||
address indexed identity,
|
||||
bytes32 name,
|
||||
bytes value,
|
||||
uint validTo,
|
||||
uint previousChange
|
||||
);
|
||||
```
|
||||
|
||||
|
||||
### Efficient lookup of events through linked identity events
|
||||
|
||||
Contract Events are a useful feature for storing data from smart contracts exclusively for off-chain use. Unfortunately current ethereum implementations provide a very inefficient lookup mechanism. By using linked events that always link to the previous block with a change for the identity, we can solve this problem with much improved performance. Each identity has its previously changed block stored in the `changed` mapping.
|
||||
|
||||
|
||||
|
||||
1. Lookup `previousChange` block for identity
|
||||
|
||||
2. Lookup all events for given identity address using web3, but only for the `previousChange` block
|
||||
|
||||
3. Do something with event
|
||||
|
||||
4. Find `previousChange` from the event and repeat
|
||||
|
||||
|
||||
|
||||
Example code:
|
||||
|
||||
|
||||
```js
|
||||
const history = []
|
||||
previousChange = await didReg.changed(identity)
|
||||
while (previousChange) {
|
||||
const filter = await didReg.allEvents({topics: [identity], fromBlock: previousChange, toBlock: previousChange})
|
||||
const events = await getLogs(filter)
|
||||
previousChange = undefined
|
||||
for (let event of events) {
|
||||
history.unshift(event)
|
||||
previousChange = event.args.previousChange
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Building a DID document for an identity
|
||||
|
||||
The primary owner key should be looked up using `identityOwner(identity)`. This should be the first of the publicKeys listed. Iterate through the `DIDDelegateChanged` events to build a list of additional keys and authentication sections as needed. The list of delegateTypes to include is still to be determined. Iterate through `DIDAttributeChanged` events for service entries, encryption public keys and other public names. The attribute names are still to be determined.
|
||||
|
||||
|
||||
## Rationale
|
||||
|
||||
For on-chain interactions Ethereum has a built in account abstraction that can be used regardless of whether the account is a smart contract or a key pair. Any transaction has a `msg.sender` as the verified send of the transaction.
|
||||
|
||||
|
||||
Since each Ethereum transaction has to be funded, there is a growing trend of on-chain transactions that are authenticated via an externally created signature and not by the actual transaction originator. This allows 3rd party funding services or receiver pays without any fundamental changes to the underlying Ethereum architecture. These kinds of transactions have to be signed by an actual key pair and thus can not be used to represent smart contract based Ethereum accounts.
|
||||
|
||||
|
||||
We propose a way of a Smart Contract or regular key pair delegating signing for various purposes to externally managed key pairs. This allows a smart contract to be represented both on-chain as well as off-chain or in payment channels through temporary or permanent delegates.
|
||||
|
||||
|
||||
## Backwards Compatibility
|
||||
|
||||
All ethereum accounts are valid identities (and DID compatible) using this standard. This means that any wallet provider that uses key pair accounts already supports the bare minimum of this standard, and can implement `delegate` and `attribute` functionality by simply using the `ethr-did` referenced below. As the **DID Auth** standard solidifies it also means that all of these wallets will be compatible with the [DID decentralized login system](https://github.com/decentralized-identity).
|
||||
|
||||
|
||||
## Implementation
|
||||
|
||||
[ethr-did-registry](https://github.com/uport-project/ethr-did-registry/blob/develop/contracts/EthereumDIDRegistry.sol) (`EthereumDIDRegistry` contract implementation)
|
||||
|
||||
[ethr-did-resolver](https://github.com/uport-project/ethr-did-resolver) (DID compatible resolver)
|
||||
|
||||
[ethr-did](https://github.com/uport-project/ethr-did) (javascript library for using the identity)
|
||||
|
||||
|
||||
### Deployment
|
||||
|
||||
The address for the `EthereumDIDRegistry` is `0xdca7ef03e98e0dc2b855be647c39abe984fcf21b` on Mainnet, Ropsten, Rinkeby and Kovan.
|
||||
|
||||
## Copyright
|
||||
|
||||
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
|
||||
|
566
EIPS/eip-1057.md
566
EIPS/eip-1057.md
|
@ -11,80 +11,150 @@ created: 2018-05-02
|
|||
|
||||
## Simple Summary
|
||||
|
||||
The following is a proposal for an alternate proof-of-work algorithm - **“ProgPoW”** - tuned for commodity hardware in order to close the efficiency gap available to specialized ASICs.
|
||||
A new Proof-of-Work algorithm to replace Ethash that utilizes almost all parts of commodity GPUs.
|
||||
|
||||
## Abstract
|
||||
|
||||
The security of proof-of-work is built on a fair, randomized lottery where miners with similar resources have a similar chance of generating the next block.
|
||||
|
||||
For Ethereum - a community based on widely distributed commodity hardware - specialized ASICs enable certain participants to gain a much greater chance of generating the next block, and undermine the distributed security.
|
||||
|
||||
ASIC-resistance is a misunderstood problem. FPGAs, GPUs and CPUs can themselves be considered ASICs. Any algorithm that executes on a commodity ASIC can have a specialized ASIC made for it; most existing algorithms provide opportunities that reduce power usage and cost. Thus, the proper question to ask when solving ASIC-resistance is “how much more efficient will a specialized ASIC be, in comparison with commodity hardware?”
|
||||
|
||||
EIP<NaN> presents an algorithm that is tuned for commodity GPUs where there is minimal opportunity for ASIC specialization. This prevents specialized ASICs without resorting to a game of whack-a-mole where the network changes algorithms every few months.
|
||||
ProgPoW is a proof-of-work algorithm designed to close the efficiency gap available to specialized ASICs. It utilizes almost all parts of commodity hardware (GPUs), and comes pre-tuned for the most common hardware utilized in the Ethereum network.
|
||||
|
||||
## Motivation
|
||||
|
||||
Until Ethereum transitions to a pure proof-of-stake model, proof-of-work will continue to be a part of the security of the network - whether it’s adapted into a hybrid model (as is the case of Casper FFG), or adopted by a hard fork.
|
||||
Ever since the first bitcoin mining ASIC was released, many new Proof of Work algorithms have been created with the intention of being “ASIC-resistant”. The goal of “ASIC-resistance” is to resist the centralization of PoW mining power such that these coins couldn’t be so easily manipulated by a few players.
|
||||
|
||||
Ethash allows for the creation of an ASIC that is roughly twice as efficient as a commodity GPU. Ethash’s memory accesses are paired with a very small amount of fixed compute. Most of a GPU’s capacity and complexity sits idle, wasting power, while waiting for DRAM accesses. A specialized ASIC can implement a much smaller (and cheaper) compute engine that burns much less power.
|
||||
This document presents an overview of the algorithm and examines what it means to be “ASIC-resistant.” Next, we compare existing PoW designs by analyzing how each algorithm executes in hardware. Finally, we present the detailed implementation by walking through the code.
|
||||
|
||||
As miner rewards are reduced with Casper FFG, it will remain profitable to mine on a specialized ASIC long after GPUs have exited the network. This will make it easier for an entity that has access to private ASICs to stage a 51% attack on the Ethereum network.
|
||||
### ProgPoW Overview
|
||||
The design goal of ProgPoW is to have the algorithm’s requirements match what is available on commodity GPUs: If the algorithm were to be implemented on a custom ASIC there should be little opportunity for efficiency gains compared to a commodity GPU.
|
||||
|
||||
The main elements of the algorithm are:
|
||||
* Changes keccak_f1600 (with 64-bit words) to keccak_f800 (with 32-bit words) to reduce impact on total power
|
||||
* Increases mix state.
|
||||
* Adds a random sequence of math in the main loop.
|
||||
* Adds reads from a small, low-latency cache that supports random addresses.
|
||||
* Increases the DRAM read from 128 bytes to 256 bytes.
|
||||
|
||||
The random sequence changes every `PROGPOW_PERIOD` (about 2 to 12 minutes depending on the configured value). When mining source code is generated for the random sequence and compiled on the host CPU. The GPU will execute the compiled code where what math to perform and what mix state to use are already resolved.
|
||||
|
||||
While a custom ASIC to implement this algorithm is still possible, the efficiency gains available are minimal. The majority of a commodity GPU is required to support the above elements. The only optimizations available are:
|
||||
* Remove the graphics pipeline (displays, geometry engines, texturing, etc)
|
||||
* Remove floating point math
|
||||
* A few ISA tweaks, like instructions that exactly match the merge() function
|
||||
|
||||
These would result in minimal, roughly 1.1-1.2x, efficiency gains. This is much less than the 2x for Ethash or 50x for Cryptonight.
|
||||
|
||||
### Rationale for PoW on Commodity Hardware
|
||||
With the growth of large mining pools, the control of hashing power has been delegated to the top few pools to provide a steadier economic return for small miners. While some have made the argument that large centralized pools defeats the purpose of “ASIC resistance,” it’s important to note that ASIC based coins are even more centralized for several reasons.
|
||||
|
||||
1. No natural distribution: There isn’t an economic purpose for ultra-specialized hardware outside of mining and thus no reason for most people to have it.
|
||||
2. No reserve group: Thus, there’s no reserve pool of hardware or reserve pool of interested parties to jump in when coin price is volatile and attractive for manipulation.
|
||||
3. High barrier to entry: Initial miners are those rich enough to invest capital and ecological resources on the unknown experiment a new coin may be. Thus, initial coin distribution through mining will be very limited causing centralized economic bias.
|
||||
4. Delegated centralization vs implementation centralization: While pool centralization is delegated, hardware monoculture is not: only the limiter buyers of this hardware can participate so there isn’t even the possibility of divesting control on short notice.
|
||||
5. No obvious decentralization of control even with decentralized mining: Once large custom ASIC makers get into the game, designing back-doored hardware is trivial. ASIC makers have no incentive to be transparent or fair in market participation.
|
||||
|
||||
While the goal of “ASIC resistance” is valuable, the entire concept of “ASIC resistance” is a bit of a fallacy. CPUs and GPUs are themselves ASICs. Any algorithm that can run on a commodity ASIC (a CPU or GPU) by definition can have a customized ASIC created for it with slightly less functionality. Some algorithms are intentionally made to be “ASIC friendly” - where an ASIC implementation is drastically more efficient than the same algorithm running on general purpose hardware. The protection that this offers when the coin is unknown also makes it an attractive target for a dedicate mining ASIC company as soon as it becomes useful.
|
||||
|
||||
Therefore, ASIC resistance is: the efficiency difference of specialized hardware versus hardware that has a wider adoption and applicability. A smaller efficiency difference between custom vs general hardware mean higher resistance and a better algorithm. This efficiency difference is the proper metric to use when comparing the quality of PoW algorithms. Efficiency could mean absolute performance, performance per watt, or performance per dollar - they are all highly correlated. If a single entity creates and controls an ASIC that is drastically more efficient, they can gain 51% of the network hashrate and possibly stage an attack.
|
||||
|
||||
### Review of Existing PoW Algorithms
|
||||
|
||||
#### SHA256
|
||||
* Potential ASIC efficiency gain ~ 1000X
|
||||
|
||||
The SHA algorithm is a sequence of simple math operations - additions, logical ops, and rotates.
|
||||
|
||||
To process a single op on a CPU or GPU requires fetching and decoding an instruction, reading data from a register file, executing the instruction, and then writing the result back to a register file. This takes significant time and power.
|
||||
|
||||
A single op implemented in an ASIC takes a handful of transistors and wires. This means every individual op takes negligible power, area, or time. A hashing core is built by laying out the sequence of required ops.
|
||||
|
||||
The hashing core can execute the required sequence of ops in much less time, and using less power or area, than doing the same sequence on a CPU or GPU. A bitcoin ASIC consists of a number of identical hashing cores and some minimal off-chip communication.
|
||||
|
||||
#### Scrypt and NeoScrypt
|
||||
* Potential ASIC efficiency gain ~ 1000X
|
||||
|
||||
Scrypt and NeoScrypt are similar to SHA in the arithmetic and bitwise operations used. Unfortunately, popular coins such as Litecoin only use a scratchpad size between 32kb and 128kb for their PoW mining algorithm. This scratch pad is small enough to trivially fit on an ASIC next to the math core. The implementation of the math core would be very similar to SHA, with similar efficiency gains.
|
||||
|
||||
#### X11 and X16R
|
||||
* Potential ASIC efficiency gain ~ 1000X
|
||||
|
||||
X11 (and similar X##) require an ASIC that has 11 unique hashing cores pipelined in a fixed sequence. Each individual hashing core would have similar efficiency to an individual SHA core, so the overall design will have the same efficiency gains.
|
||||
|
||||
X16R requires the multiple hashing cores to interact through a simple sequencing state machine. Each individual core will have similar efficiency gains and the sequencing logic will take minimal power, area, or time.
|
||||
|
||||
The Baikal BK-X is an existing ASIC with multiple hashing cores and a programmable sequencer. It has been upgraded to enable new algorithms that sequence the hashes in different orders.
|
||||
|
||||
#### Equihash
|
||||
* Potential ASIC efficiency gain ~ 100X
|
||||
|
||||
The ~150mb of state is large but possible on an ASIC. The binning, sorting, and comparing of bit strings could be implemented on an ASIC at extremely high speed.
|
||||
|
||||
#### Cuckoo Cycle
|
||||
* Potential ASIC efficiency gain ~ 100X
|
||||
|
||||
The amount of state required on-chip is not clear as there are Time/Memory Tradeoff attacks. A specialized graph traversal core would have similar efficiency gains to a SHA compute core.
|
||||
|
||||
#### CryptoNight
|
||||
* Potential ASIC efficiency gain ~ 50X
|
||||
|
||||
Compared to Scrypt, CryptoNight does much less compute and requires a full 2mb of scratch pad (there is no known Time/Memory Tradeoff attack). The large scratch pad will dominate the ASIC implementation and limit the number of hashing cores, limiting the absolute performance of the ASIC. An ASIC will consist almost entirely of just on-die SRAM.
|
||||
|
||||
#### Ethash
|
||||
* Potential ASIC efficiency gain ~ 2X
|
||||
|
||||
Ethash requires external memory due to the large size of the DAG. However that is all that it requires - there is minimal compute that is done on the result loaded from memory. As a result a custom ASIC could remove most of the complexity, and power, of a GPU and be just a memory interface connected to a small compute engine.
|
||||
|
||||
## Specification
|
||||
|
||||
ProgPoW is based on Ethash and follows the same general structure. The algorithm has five main changes from Ethash, each tuned for commodity GPUs while minimizing the possible advantage of a specialized ASIC.
|
||||
|
||||
The name of the algorithm comes from the fact that the inner loop between global memory accesses is a randomly generated program based on the block number. The random program is designed to both run efficiently on commodity GPUs and also cover most of the GPU's functionality. The random program sequence prevents the creation of a fixed pipeline implementation as seen in a specialized ASIC. The access size has also been tweaked to match contemporary GPUs.
|
||||
|
||||
In contrast to Ethash, the changes detailed below make ProgPoW dependent on the core compute capabilities in addition to memory bandwidth and size.
|
||||
|
||||
**Changes keccak_f1600 (with 64-bit words) to keccak_f800 (with 32-bit words).**
|
||||
|
||||
*On 64-bit architectures f1600 processes twice as many bits as f800 in roughly the same time. As GPUs are natively 32-bit architectures, f1600 takes twice as long as f800. ProgPow doesn’t require all the bits f1600 can consume, thus reducing the size reduces the optimization opportunity for a specialized ASIC.*
|
||||
|
||||
**Increases mix state.**
|
||||
|
||||
*A significant part of a GPU’s area, power, and complexity is the large register file. A large mix state ensures that a specialized ASIC would need to implement similar state storage, limiting any advantage.*
|
||||
|
||||
**Adds a random sequence of math in the main loop.**
|
||||
|
||||
*The random math changes every 50 blocks to amortize compilation overhead. Having a random sequence of math that reads and writes random locations within the state ensures that the ASIC executing the algorithm is fully programmable. There is no possibility to create an ASIC with a fixed pipeline that is much faster or lower power.*
|
||||
|
||||
**Adds reads from a small, low-latency cache that supports random addresses.**
|
||||
|
||||
*Another significant part of a GPU’s area, power, and complexity is the memory hierarchy. Adding cached reads makes use of this hierarchy and ensures that a specialized ASIC also implements a similar hierarchy, preventing power or area savings.*
|
||||
|
||||
**Increases the DRAM read from 128 bytes to 256 bytes.**
|
||||
|
||||
*The DRAM read from the DAG is the same as Ethash’s, but with the size increased to `256 bytes`. This better matches the workloads seen on commodity GPUs, preventing a specialized ASIC from being able to gain performance by optimizing the memory controller for abnormally small accesses.*
|
||||
|
||||
The DAG file is generated according to traditional Ethash specifications.
|
||||
The DAG is generated exactly as in Ethash. All the parameters (ephoch length, DAG size, etc) are unchanged. See the original [Ethash](https://github.com/ethereum/wiki/wiki/Ethash) spec for details on generating the DAG.
|
||||
|
||||
ProgPoW can be tuned using the following parameters. The proposed settings have been tuned for a range of existing, commodity GPUs:
|
||||
* `PROGPOW_PERIOD`: Number of blocks before changing the random program
|
||||
* `PROGPOW_LANES`: The number of parallel lanes that coordinate to calculate a single hash instance
|
||||
* `PROGPOW_REGS`: The register file usage size
|
||||
* `PROGPOW_DAG_LOADS`: Number of uint32 loads from the DAG per lane
|
||||
* `PROGPOW_CACHE_BYTES`: The size of the cache
|
||||
* `PROGPOW_CNT_DAG`: The number of DAG accesses, defined as the outer loop of the algorithm (64 is the same as ethash)
|
||||
* `PROGPOW_CNT_CACHE`: The number of cache accesses per loop
|
||||
* `PROGPOW_CNT_MATH`: The number of math operations per loop
|
||||
|
||||
* `PROGPOW_PERIOD`: Number of blocks before changing the random program; default is `50`.
|
||||
* `PROGPOW_LANES`: The number of parallel lanes that coordinate to calculate a single hash instance; default is `16`.
|
||||
* `PROGPOW_REGS`: The register file usage size; default is `32`.
|
||||
* `PROGPOW_DAG_LOADS`: Number of uint32 loads from the DAG per lane; default is `4`;
|
||||
* `PROGPOW_CACHE_BYTES`: The size of the cache; default is `16 x 1024`.
|
||||
* `PROGPOW_CNT_DAG`: The number of DAG accesses, defined as the outer loop of the algorithm; default is `64` (same as Ethash).
|
||||
* `PROGPOW_CNT_CACHE`: The number of cache accesses per loop; default is `12`.
|
||||
* `PROGPOW_CNT_MATH`: The number of math operations per loop; default is `20`.
|
||||
The value of these parameters has been tweaked between version 0.9.2 (live on the gangnum testnet) and 0.9.3 (proposed for Ethereum adoption). See [this medium post](https://medium.com/@ifdefelse/progpow-progress-da5bb31a651b) for details.
|
||||
|
||||
The random program changes every `PROGPOW_PERIOD` blocks (default `50`, roughly 12.5 minutes) to ensure the hardware executing the algorithm is fully programmable. If the program only changed every DAG epoch (roughly 5 days) certain miners could have time to develop hand-optimized versions of the random sequence, giving them an undue advantage.
|
||||
| Parameter | 0.9.2 | 0.9.3 |
|
||||
|-----------------------|-----------|-----------|
|
||||
| `PROGPOW_PERIOD` | `50` | `10` |
|
||||
| `PROGPOW_LANES` | `16` | `16` |
|
||||
| `PROGPOW_REGS` | `32` | `32` |
|
||||
| `PROGPOW_DAG_LOADS` | `4` | `4` |
|
||||
| `PROGPOW_CACHE_BYTES` | `16x1024` | `16x1024` |
|
||||
| `PROGPOW_CNT_DAG` | `64` | `64` |
|
||||
| `PROGPOW_CNT_CACHE` | `12` | `11` |
|
||||
| `PROGPOW_CNT_MATH` | `20` | `18` |
|
||||
|
||||
ProgPoW uses **FNV1a** for merging data. The existing Ethash uses FNV1 for merging, but FNV1a provides better distribution properties.
|
||||
|
||||
The random program changes every `PROGPOW_PERIOD` blocks to ensure the hardware executing the algorithm is fully programmable. If the program only changed every DAG epoch (roughly 5 days) certain miners could have time to develop hand-optimized versions of the random sequence, giving them an undue advantage.
|
||||
|
||||
Sample code is written in C++, this should be kept in mind when evaluating the code in the specification.
|
||||
|
||||
All numerics are computed using unsigned 32 bit integers. Any overflows are trimmed off before proceeding to the next computation. Languages that use numerics not fixed to bit lengths (such as Python and JavaScript) or that only use signed integers (such as Java) will need to keep their languages' quirks in mind. The extensive use of 32 bit data values aligns with modern GPUs internal data architectures.
|
||||
|
||||
ProgPoW uses a 32-bit variant of **FNV1a** for merging data. The existing Ethash uses a similar variant of FNV1 for merging, but FNV1a provides better distribution properties.
|
||||
|
||||
Test vectors can be found [in the test vectors file](../assets/eip-1057/test-vectors.md#fnv1a).
|
||||
|
||||
```cpp
|
||||
const uint32_t FNV_PRIME = 0x1000193;
|
||||
const uint32_t FNV_OFFSET_BASIS = 0x811c9dc5;
|
||||
|
||||
uint32_t fnv1a(uint32_t h, uint32_t d)
|
||||
{
|
||||
return (h ^ d) * FNV_PRIME;
|
||||
}
|
||||
```
|
||||
|
||||
ProgPow uses [KISS99](https://en.wikipedia.org/wiki/KISS_(algorithm)) for random number generation. This is the simplest (fewest instruction) random generator that passes the TestU01 statistical test suite. A more complex random number generator like Mersenne Twister can be efficiently implemented on a specialized ASIC, providing an opportunity for efficiency gains.
|
||||
|
||||
Test vectors can be found [in the test vectors file](../assets/eip-1057/test-vectors.md#kiss99).
|
||||
|
||||
```cpp
|
||||
|
||||
uint32_t fnv1a(uint32_t &h, uint32_t d)
|
||||
{
|
||||
return h = (h ^ d) * 0x1000193;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
uint32_t z, w, jsr, jcong;
|
||||
} kiss99_t;
|
||||
|
@ -105,7 +175,9 @@ uint32_t kiss99(kiss99_t &st)
|
|||
}
|
||||
```
|
||||
|
||||
The `LANES*REGS` of mix data is initialized from the hash’s seed.
|
||||
The `fill_mix` function populates an array of `int32` values used by each lane in the hash calculations.
|
||||
|
||||
Test vectors can be found [in the test vectors file](../assets/eip-1057/test-vectors.md#fill_mix).
|
||||
|
||||
```cpp
|
||||
void fill_mix(
|
||||
|
@ -116,26 +188,32 @@ void fill_mix(
|
|||
{
|
||||
// Use FNV to expand the per-warp seed to per-lane
|
||||
// Use KISS to expand the per-lane seed to fill mix
|
||||
uint32_t fnv_hash = 0x811c9dc5;
|
||||
kiss99_t st;
|
||||
st.z = fnv1a(fnv_hash, seed);
|
||||
st.w = fnv1a(fnv_hash, seed >> 32);
|
||||
st.jsr = fnv1a(fnv_hash, lane_id);
|
||||
st.jcong = fnv1a(fnv_hash, lane_id);
|
||||
st.z = fnv1a(FNV_OFFSET_BASIS, seed);
|
||||
st.w = fnv1a(st.z, seed >> 32);
|
||||
st.jsr = fnv1a(st.w, lane_id);
|
||||
st.jcong = fnv1a(st.jsr, lane_id);
|
||||
for (int i = 0; i < PROGPOW_REGS; i++)
|
||||
mix[i] = kiss99(st);
|
||||
}
|
||||
```
|
||||
|
||||
Like ethash Keccak is used to seed the sequence per-nonce and to produce the final result. The keccak-f800 variant is used as the 32-bit word size matches the native word size of modern GPUs. The implementation is a variant of SHAKE with width=800, bitrate=576, capacity=224, output=256, and no padding. The result of keccak is treated as a 256-bit big-endian number - that is result byte 0 is the MSB of the value.
|
||||
Like Ethash Keccak is used to seed the sequence per-nonce and to produce the final result. The keccak-f800 variant is used as the 32-bit word size matches the native word size of modern GPUs. The implementation is a variant of SHAKE with width=800, bitrate=576, capacity=224, output=256, and no padding. The result of keccak is treated as a 256-bit big-endian number - that is result byte 0 is the MSB of the value.
|
||||
|
||||
As with Ethash the input and output of the keccak function are fixed and relatively small. This means only a single "absorb" and "squeeze" phase are required. For a pseudo-code imenentation of the `keccak_f800_round` function see the `Round[b](A,RC)` function in the "Pseudo-code description of the permutations" section of the [official Keccak specs](https://keccak.team/keccak_specs_summary.html).
|
||||
|
||||
Test vectors can be found [in the test vectors file](../assets/eip-1057/test-vectors.md#keccak_f800_progpow).
|
||||
|
||||
```cpp
|
||||
hash32_t keccak_f800_progpow(hash32_t header, uint64_t seed, hash32_t digest)
|
||||
{
|
||||
uint32_t st[25];
|
||||
|
||||
// Initialization
|
||||
for (int i = 0; i < 25; i++)
|
||||
st[i] = 0;
|
||||
|
||||
// Absorb phase for fixed 18 words of input
|
||||
for (int i = 0; i < 8; i++)
|
||||
st[i] = header.uint32s[i];
|
||||
st[8] = seed;
|
||||
|
@ -143,29 +221,206 @@ hash32_t keccak_f800_progpow(hash32_t header, uint64_t seed, hash32_t digest)
|
|||
for (int i = 0; i < 8; i++)
|
||||
st[10+i] = digest.uint32s[i];
|
||||
|
||||
// keccak_f800 call for the single absorb pass
|
||||
for (int r = 0; r < 22; r++)
|
||||
keccak_f800_round(st, r);
|
||||
|
||||
// Squeeze phase for fixed 8 words of output
|
||||
hash32_t ret;
|
||||
for (int i=0; i<8; i++)
|
||||
ret.uint32s[i] = st[i];
|
||||
|
||||
return ret;
|
||||
}
|
||||
```
|
||||
|
||||
The inner loop uses FNV and KISS99 to generate a random sequence from the `prog_seed`. This random sequence determines which mix state is accessed and what random math is performed.
|
||||
|
||||
Since the `prog_seed` changes only once per `PROGPOW_PERIOD` it is expected that while mining `progPowLoop` will be evaluated on the CPU to generate source code for that period's sequence. The source code will be compiled on the CPU before running on the GPU.
|
||||
|
||||
Test vectors can be found [in the test vectors file](../assets/eip-1057/test-vectors.md#progpowinit).
|
||||
|
||||
```cpp
|
||||
kiss99_t progPowInit(uint64_t prog_seed, int mix_seq_dst[PROGPOW_REGS], int mix_seq_src[PROGPOW_REGS])
|
||||
{
|
||||
kiss99_t prog_rnd;
|
||||
prog_rnd.z = fnv1a(FNV_OFFSET_BASIS, prog_seed);
|
||||
prog_rnd.w = fnv1a(prog_rnd.z, prog_seed >> 32);
|
||||
prog_rnd.jsr = fnv1a(prog_rnd.w, prog_seed);
|
||||
prog_rnd.jcong = fnv1a(prog_rnd.jsr, prog_seed >> 32);
|
||||
// Create a random sequence of mix destinations for merge() and mix sources for cache reads
|
||||
// guarantees every destination merged once
|
||||
// guarantees no duplicate cache reads, which could be optimized away
|
||||
// Uses Fisher-Yates shuffle
|
||||
for (int i = 0; i < PROGPOW_REGS; i++)
|
||||
{
|
||||
mix_seq_dst[i] = i;
|
||||
mix_seq_src[i] = i;
|
||||
}
|
||||
for (int i = PROGPOW_REGS - 1; i > 0; i--)
|
||||
{
|
||||
int j;
|
||||
j = kiss99(prog_rnd) % (i + 1);
|
||||
swap(mix_seq_dst[i], mix_seq_dst[j]);
|
||||
j = kiss99(prog_rnd) % (i + 1);
|
||||
swap(mix_seq_src[i], mix_seq_src[j]);
|
||||
}
|
||||
return prog_rnd;
|
||||
}
|
||||
```
|
||||
|
||||
The math operations that merges values into the mix data are ones chosen to maintain entropy.
|
||||
|
||||
Test vectors can be found [in the test vectors file](../assets/eip-1057/test-vectors.md#math).
|
||||
|
||||
```cpp
|
||||
// Merge new data from b into the value in a
|
||||
// Assuming A has high entropy only do ops that retain entropy
|
||||
// even if B is low entropy
|
||||
// (IE don't do A&B)
|
||||
uint32_t merge(uint32_t a, uint32_t b, uint32_t r)
|
||||
{
|
||||
switch (r % 4)
|
||||
{
|
||||
case 0: return (a * 33) + b;
|
||||
case 1: return (a ^ b) * 33;
|
||||
// prevent rotate by 0 which is a NOP
|
||||
case 2: return ROTL32(a, ((r >> 16) % 31) + 1) ^ b;
|
||||
case 3: return ROTR32(a, ((r >> 16) % 31) + 1) ^ b;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The math operations chosen for the random math are ones that are easy to implement in CUDA and OpenCL, the two main programming languages for commodity GPUs. The [mul_hi](https://www.khronos.org/registry/OpenCL/sdk/1.1/docs/man/xhtml/mul_hi.html), [min](https://www.khronos.org/registry/OpenCL/sdk/2.0/docs/man/xhtml/integerMax.html), [clz](https://www.khronos.org/registry/OpenCL/sdk/1.1/docs/man/xhtml/clz.html), and [popcount](https://www.khronos.org/registry/OpenCL/sdk/2.0/docs/man/xhtml/popcount.html) functions match the corresponding OpenCL functions. ROTL32 matches the OpenCL [rotate](https://www.khronos.org/registry/OpenCL/sdk/1.0/docs/man/xhtml/rotate.html) function. ROTR32 is rotate right, which is equivalent to `rotate(i, 32-v)`.
|
||||
|
||||
Test vectors can be found [in the test vectors file](../assets/eip-1057/test-vectors.md#math).
|
||||
|
||||
```cpp
|
||||
// Random math between two input values
|
||||
uint32_t math(uint32_t a, uint32_t b, uint32_t r)
|
||||
{
|
||||
switch (r % 11)
|
||||
{
|
||||
case 0: return a + b;
|
||||
case 1: return a * b;
|
||||
case 2: return mul_hi(a, b);
|
||||
case 3: return min(a, b);
|
||||
case 4: return ROTL32(a, b);
|
||||
case 5: return ROTR32(a, b);
|
||||
case 6: return a & b;
|
||||
case 7: return a | b;
|
||||
case 8: return a ^ b;
|
||||
case 9: return clz(a) + clz(b);
|
||||
case 10: return popcount(a) + popcount(b);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
The flow of the inner loop is:
|
||||
* Lane `(loop % LANES)` is chosen as the leader for that loop iteration
|
||||
* The leader's `mix[0]` value modulo the number of 256-byte DAG entries is is used to select where to read from the full DAG
|
||||
* Each lane reads `DAG_LOADS` sequential words, using `(lane ^ loop) % LANES` as the starting offset within the entry.
|
||||
* The random sequence of math and cache accesses is performed
|
||||
* The DAG data read at the start of the loop is merged at the end of the loop
|
||||
|
||||
`prog_seed` and `loop` come from the outer loop, corresponding to the current program seed (which is block_number/PROGPOW_PERIOD) and the loop iteration number. `mix` is the state array, initially filled by `fill_mix`. `dag` is the bytes of the Ethash DAG grouped into 32 bit unsigned ints in litte-endian format. On little-endian architectures this is just a normal int32 pointer to the existing DAG.
|
||||
|
||||
`DAG_BYTES` is set to the number of bytes in the current DAG, which is generated identically to the existing Ethash algorithm.
|
||||
|
||||
Test vectors can be found [in the test vectors file](../assets/eip-1057/test-vectors.md#progpowloop).
|
||||
|
||||
```cpp
|
||||
void progPowLoop(
|
||||
const uint64_t prog_seed,
|
||||
const uint32_t loop,
|
||||
uint32_t mix[PROGPOW_LANES][PROGPOW_REGS],
|
||||
const uint32_t *dag)
|
||||
{
|
||||
// dag_entry holds the 256 bytes of data loaded from the DAG
|
||||
uint32_t dag_entry[PROGPOW_LANES][PROGPOW_DAG_LOADS];
|
||||
// On each loop iteration rotate which lane is the source of the DAG address.
|
||||
// The source lane's mix[0] value is used to ensure the last loop's DAG data feeds into this loop's address.
|
||||
// dag_addr_base is which 256-byte entry within the DAG will be accessed
|
||||
uint32_t dag_addr_base = mix[loop%PROGPOW_LANES][0] %
|
||||
(DAG_BYTES / (PROGPOW_LANES*PROGPOW_DAG_LOADS*sizeof(uint32_t)));
|
||||
for (int l = 0; l < PROGPOW_LANES; l++)
|
||||
{
|
||||
// Lanes access DAG_LOADS sequential words from the dag entry
|
||||
// Shuffle which portion of the entry each lane accesses each iteration by XORing lane and loop.
|
||||
// This prevents multi-chip ASICs from each storing just a portion of the DAG
|
||||
size_t dag_addr_lane = dag_addr_base * PROGPOW_LANES + (l ^ loop) % PROGPOW_LANES;
|
||||
for (int i = 0; i < PROGPOW_DAG_LOADS; i++)
|
||||
dag_entry[l][i] = dag[dag_addr_lane * PROGPOW_DAG_LOADS + i];
|
||||
}
|
||||
|
||||
// Initialize the program seed and sequences
|
||||
// When mining these are evaluated on the CPU and compiled away
|
||||
int mix_seq_dst[PROGPOW_REGS];
|
||||
int mix_seq_src[PROGPOW_REGS];
|
||||
int mix_seq_dst_cnt = 0;
|
||||
int mix_seq_src_cnt = 0;
|
||||
kiss99_t prog_rnd = progPowInit(prog_seed, mix_seq_dst, mix_seq_src);
|
||||
|
||||
int max_i = max(PROGPOW_CNT_CACHE, PROGPOW_CNT_MATH);
|
||||
for (int i = 0; i < max_i; i++)
|
||||
{
|
||||
if (i < PROGPOW_CNT_CACHE)
|
||||
{
|
||||
// Cached memory access
|
||||
// lanes access random 32-bit locations within the first portion of the DAG
|
||||
int src = mix_seq_src[(mix_seq_src_cnt++)%PROGPOW_REGS];
|
||||
int dst = mix_seq_dst[(mix_seq_dst_cnt++)%PROGPOW_REGS];
|
||||
int sel = kiss99(prog_rnd);
|
||||
for (int l = 0; l < PROGPOW_LANES; l++)
|
||||
{
|
||||
uint32_t offset = mix[l][src] % (PROGPOW_CACHE_BYTES/sizeof(uint32_t));
|
||||
mix[l][dst] = merge(mix[l][dst], dag[offset], sel);
|
||||
}
|
||||
}
|
||||
if (i < PROGPOW_CNT_MATH)
|
||||
{
|
||||
// Random Math
|
||||
// Generate 2 unique sources
|
||||
int src_rnd = kiss99(prog_rnd) % (PROGPOW_REGS * (PROGPOW_REGS-1));
|
||||
int src1 = src_rnd % PROGPOW_REGS; // 0 <= src1 < PROGPOW_REGS
|
||||
int src2 = src_rnd / PROGPOW_REGS; // 0 <= src2 < PROGPOW_REGS - 1
|
||||
if (src2 >= src1) ++src2; // src2 is now any reg other than src1
|
||||
int sel1 = kiss99(prog_rnd);
|
||||
int dst = mix_seq_dst[(mix_seq_dst_cnt++)%PROGPOW_REGS];
|
||||
int sel2 = kiss99(prog_rnd);
|
||||
for (int l = 0; l < PROGPOW_LANES; l++)
|
||||
{
|
||||
uint32_t data = math(mix[l][src1], mix[l][src2], sel1);
|
||||
mix[l][dst] = merge(mix[l][dst], data, sel2);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Consume the global load data at the very end of the loop to allow full latency hiding
|
||||
// Always merge into mix[0] to feed the offset calculation
|
||||
for (int i = 0; i < PROGPOW_DAG_LOADS; i++)
|
||||
{
|
||||
int dst = (i==0) ? 0 : mix_seq_dst[(mix_seq_dst_cnt++)%PROGPOW_REGS];
|
||||
int sel = kiss99(prog_rnd);
|
||||
for (int l = 0; l < PROGPOW_LANES; l++)
|
||||
mix[l][dst] = merge(mix[l][dst], dag_entry[l][i], sel);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The flow of the overall algorithm is:
|
||||
* A keccak hash of the header + nonce to create a seed
|
||||
* Use the seed to generate initial mix data
|
||||
* Loop multiple times, each time hashing random loads and random math into the mix data
|
||||
* Hash all the mix data into a single 256-bit value
|
||||
* A final keccak hash that is compared against the target
|
||||
* A final keccak hash is computed
|
||||
* When mining this final value is compared against a `hash32_t` target
|
||||
|
||||
```cpp
|
||||
bool progpow_search(
|
||||
hash32_t progPowHash(
|
||||
const uint64_t prog_seed, // value is (block_number/PROGPOW_PERIOD)
|
||||
const uint64_t nonce,
|
||||
const hash32_t header,
|
||||
const hash32_t target, // miner can use a uint64_t target, doesn't need the full 256 bit target
|
||||
const uint32_t *dag // gigabyte DAG located in framebuffer - the first portion gets cached
|
||||
)
|
||||
{
|
||||
|
@ -191,171 +446,21 @@ bool progpow_search(
|
|||
uint32_t digest_lane[PROGPOW_LANES];
|
||||
for (int l = 0; l < PROGPOW_LANES; l++)
|
||||
{
|
||||
digest_lane[l] = 0x811c9dc5
|
||||
digest_lane[l] = FNV_OFFSET_BASIS
|
||||
for (int i = 0; i < PROGPOW_REGS; i++)
|
||||
fnv1a(digest_lane[l], mix[l][i]);
|
||||
digest_lane[l] = fnv1a(digest_lane[l], mix[l][i]);
|
||||
}
|
||||
// Reduce all lanes to a single 256-bit digest
|
||||
for (int i = 0; i < 8; i++)
|
||||
digest.uint32s[i] = 0x811c9dc5;
|
||||
digest.uint32s[i] = FNV_OFFSET_BASIS;
|
||||
for (int l = 0; l < PROGPOW_LANES; l++)
|
||||
fnv1a(digest.uint32s[l%8], digest_lane[l])
|
||||
digest.uint32s[l%8] = fnv1a(digest.uint32s[l%8], digest_lane[l])
|
||||
|
||||
// keccak(header .. keccak(header..nonce) .. digest);
|
||||
return (keccak_f800_progpow(header, seed, digest) <= target);
|
||||
keccak_f800_progpow(header, seed, digest);
|
||||
}
|
||||
```
|
||||
|
||||
The inner loop uses FNV and KISS99 to generate a random sequence from the `prog_seed`. This random sequence determines which mix state is accessed and what random math is performed. Since the `prog_seed` changes relatively infrequently it is expected that `progPowLoop` will be compiled while mining instead of interpreted on the fly.
|
||||
|
||||
```cpp
|
||||
kiss99_t progPowInit(uint64_t prog_seed, int mix_seq_dst[PROGPOW_REGS], int mix_seq_cache[PROGPOW_REGS])
|
||||
{
|
||||
kiss99_t prog_rnd;
|
||||
uint32_t fnv_hash = 0x811c9dc5;
|
||||
prog_rnd.z = fnv1a(fnv_hash, prog_seed);
|
||||
prog_rnd.w = fnv1a(fnv_hash, prog_seed >> 32);
|
||||
prog_rnd.jsr = fnv1a(fnv_hash, prog_seed);
|
||||
prog_rnd.jcong = fnv1a(fnv_hash, prog_seed >> 32);
|
||||
// Create a random sequence of mix destinations for merge() and mix sources for cache reads
|
||||
// guarantees every destination merged once
|
||||
// guarantees no duplicate cache reads, which could be optimized away
|
||||
// Uses Fisher-Yates shuffle
|
||||
for (int i = 0; i < PROGPOW_REGS; i++)
|
||||
{
|
||||
mix_seq_dst[i] = i;
|
||||
mix_seq_cache[i] = i;
|
||||
}
|
||||
for (int i = PROGPOW_REGS - 1; i > 0; i--)
|
||||
{
|
||||
int j;
|
||||
j = kiss99(prog_rnd) % (i + 1);
|
||||
swap(mix_seq_dst[i], mix_seq_dst[j]);
|
||||
j = kiss99(prog_rnd) % (i + 1);
|
||||
swap(mix_seq_cache[i], mix_seq_cache[j]);
|
||||
}
|
||||
return prog_rnd;
|
||||
}
|
||||
```
|
||||
|
||||
The math operations that merge values into the mix data are ones chosen to maintain entropy.
|
||||
|
||||
```cpp
|
||||
// Merge new data from b into the value in a
|
||||
// Assuming A has high entropy only do ops that retain entropy
|
||||
// even if B is low entropy
|
||||
// (IE don't do A&B)
|
||||
void merge(uint32_t &a, uint32_t b, uint32_t r)
|
||||
{
|
||||
switch (r % 4)
|
||||
{
|
||||
case 0: a = (a * 33) + b; break;
|
||||
case 1: a = (a ^ b) * 33; break;
|
||||
// prevent rotate by 0 which is a NOP
|
||||
case 2: a = ROTL32(a, ((r >> 16) % 31) + 1) ^ b; break;
|
||||
case 3: a = ROTR32(a, ((r >> 16) % 31) + 1) ^ b; break;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The math operations chosen for the random math are ones that are easy to implement in CUDA and OpenCL, the two main programming languages for commodity GPUs.
|
||||
|
||||
```cpp
|
||||
// Random math between two input values
|
||||
uint32_t math(uint32_t a, uint32_t b, uint32_t r)
|
||||
{
|
||||
switch (r % 11)
|
||||
{
|
||||
case 0: return a + b;
|
||||
case 1: return a * b;
|
||||
case 2: return mul_hi(a, b);
|
||||
case 3: return min(a, b);
|
||||
case 4: return ROTL32(a, b);
|
||||
case 5: return ROTR32(a, b);
|
||||
case 6: return a & b;
|
||||
case 7: return a | b;
|
||||
case 8: return a ^ b;
|
||||
case 9: return clz(a) + clz(b);
|
||||
case 10: return popcount(a) + popcount(b);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The main loop:
|
||||
|
||||
```cpp
|
||||
void progPowLoop(
|
||||
const uint64_t prog_seed,
|
||||
const uint32_t loop,
|
||||
uint32_t mix[PROGPOW_LANES][PROGPOW_REGS],
|
||||
const uint32_t *dag)
|
||||
{
|
||||
// All lanes share a base address for the global load
|
||||
// Global offset uses mix[0] to guarantee it depends on the load result
|
||||
uint32_t data_g[PROGPOW_LANES][PROGPOW_DAG_LOADS];
|
||||
uint32_t offset_g = mix[loop%PROGPOW_LANES][0] % (DAG_BYTES / (PROGPOW_LANES*PROGPOW_DAG_LOADS*sizeof(uint32_t)));
|
||||
for (int l = 0; l < PROGPOW_LANES; l++)
|
||||
{
|
||||
// global load to the 256 byte DAG entry
|
||||
// every lane can access every part of the entry
|
||||
uint32_t offset_l = offset_g * PROGPOW_LANES + (l ^ loop) % PROGPOW_LANES;
|
||||
for (int i = 0; i < PROGPOW_DAG_LOADS; i++)
|
||||
data_g[l][i] = dag[offset_l * PROGPOW_DAG_LOADS + i];
|
||||
}
|
||||
|
||||
// Initialize the program seed and sequences
|
||||
// When mining these are evaluated on the CPU and compiled away
|
||||
int mix_seq_dst[PROGPOW_REGS];
|
||||
int mix_seq_src[PROGPOW_REGS];
|
||||
int mix_seq_dst_cnt = 0;
|
||||
int mix_seq_src_cnt = 0;
|
||||
kiss99_t prog_rnd = progPowInit(prog_seed, mix_seq_dst, mix_seq_src);
|
||||
|
||||
int max_i = max(PROGPOW_CNT_CACHE, PROGPOW_CNT_MATH);
|
||||
for (int i = 0; i < max_i; i++)
|
||||
{
|
||||
if (i < PROGPOW_CNT_CACHE)
|
||||
{
|
||||
// Cached memory access
|
||||
// lanes access random 32-bit locations within the first portion of the DAG
|
||||
int src = mix_seq_src[(mix_seq_src_cnt++)%PROGPOW_REGS];
|
||||
int dst = mix_seq_dst[(mix_seq_dst_cnt++)%PROGPOW_REGS];
|
||||
int sel = kiss99(prog_rnd);
|
||||
for (int l = 0; l < PROGPOW_LANES; l++)
|
||||
{
|
||||
uint32_t offset = mix[l][src] % (PROGPOW_CACHE_BYTES/sizeof(uint32_t));
|
||||
merge(mix[l][dst], dag[offset], sel);
|
||||
}
|
||||
}
|
||||
if (i < PROGPOW_CNT_MATH)
|
||||
{
|
||||
// Random Math
|
||||
// Generate 2 unique sources
|
||||
int src_rnd = kiss99(prog_rnd) % (PROGPOW_REGS * (PROGPOW_REGS-1));
|
||||
int src1 = src_rnd % PROGPOW_REGS; // 0 <= src1 < PROGPOW_REGS
|
||||
int src2 = src_rnd / PROGPOW_REGS; // 0 <= src2 < PROGPOW_REGS - 1
|
||||
if (src2 >= src1) ++src2; // src2 is now any reg other than src
|
||||
int sel1 = kiss99(prog_rnd);
|
||||
int dst = mix_seq_dst[(mix_seq_dst_cnt++)%PROGPOW_REGS];
|
||||
int sel2 = kiss99(prog_rnd);
|
||||
for (int l = 0; l < PROGPOW_LANES; l++)
|
||||
{
|
||||
uint32_t data = math(mix[l][src1], mix[l][src2], sel1);
|
||||
merge(mix[l][dst], data, sel2);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Consume the global load data at the very end of the loop to allow full latency hiding
|
||||
// Always merge into mix[0] to feed the offset calculation
|
||||
for (int i = 0; i < PROGPOW_DAG_LOADS; i++)
|
||||
{
|
||||
int dst = (i==0) ? 0 : mix_seq_dst[(mix_seq_dst_cnt++)%PROGPOW_REGS];
|
||||
int sel = kiss99(prog_rnd);
|
||||
for (int l = 0; l < PROGPOW_LANES; l++)
|
||||
merge(mix[l][dst], data_g[l][i], sel);
|
||||
}
|
||||
}
|
||||
```
|
||||
## Rationale
|
||||
|
||||
ProgPoW utilizes almost all parts of a commodity GPU, excluding:
|
||||
|
@ -371,10 +476,27 @@ Since the GPU is almost fully utilized, there’s little opportunity for specia
|
|||
|
||||
This algorithm is not backwards compatible with the existing Ethash, and will require a fork for adoption. Furthermore, the network hashrate will halve since twice as much memory is loaded per hash.
|
||||
|
||||
## Test Cases
|
||||
|
||||
### progpow 0.9.2
|
||||
The algorithm run on block 30,000 produces the following digest and result:
|
||||
```
|
||||
header ffeeddccbbaa9988776655443322110000112233445566778899aabbccddeeff
|
||||
nonce 123456789abcdef0
|
||||
|
||||
digest: 11f19805c58ab46610ff9c719dcf0a5f18fa2f1605798eef770c47219274767d
|
||||
result: 5b7ccd472dbefdd95b895cac8ece67ff0deb5a6bd2ecc6e162383d00c3728ece
|
||||
```
|
||||
|
||||
Additional test vectors can be found [in the test vectors file](../assets/eip-1057/test-vectors.md#progpowhash).
|
||||
### progpow 0.9.3
|
||||
[Machine-readable test vectors](https://github.com/ethereum/EIPs/blob/ad4e73f239d53d72a21cfd8fdc89dc81eb9d2688/assets/eip-1057/test-vectors-0.9.3.json)
|
||||
|
||||
## Implementation
|
||||
|
||||
Please refer to the official code located at [ProgPOW](https://github.com/ifdefelse/ProgPOW) for the full code, implemented in the standard ethminer.
|
||||
The reference ProgPoW mining implementation located at [ProgPOW](https://github.com/ifdefelse/ProgPOW) is a derivative of ethminer so retains the GPL license.
|
||||
## License and Copyright
|
||||
|
||||
## Copyright
|
||||
The ProgPoW algorithm and this specification are a new work. Copyright and related rights are waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
|
||||
|
||||
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
|
||||
The reference ProgPoW mining implementation located at [ProgPOW](https://github.com/ifdefelse/ProgPOW) is a derivative of ethminer so retains the GPL license.
|
||||
|
|
|
@ -36,13 +36,13 @@ When mapping the IPFS base58 string to ENS resolver, first we convert the Base58
|
|||
## Rationale
|
||||
To implement the specification, need two methods from ENS public resolver contract, when we want to store IPFS file fingerprint to contract, convert the Base58 string identifier to the hex format and invoke the `setMultihash` method below :
|
||||
|
||||
```
|
||||
```solidity
|
||||
function setMultihash(bytes32 node, bytes hash) public only_owner(node);
|
||||
```
|
||||
|
||||
Whenever users need to visit the ENS content, we call the `multihash` method to get the IPFS hex data, transfer to the Base58 format, and return the IPFS resources to use.
|
||||
|
||||
```
|
||||
```solidity
|
||||
function multihash(bytes32 node) public view returns (bytes);
|
||||
```
|
||||
|
||||
|
@ -52,7 +52,7 @@ To implement the way to transfer from base58 to hex format and the reverse one,
|
|||
The library link : [https://www.npmjs.com/package/multihashes](https://www.npmjs.com/package/multihashes)
|
||||
To implement the method transfer from IPFS(Base58) to hex format :
|
||||
|
||||
```
|
||||
```javascript
|
||||
import multihash from 'multihashes'
|
||||
|
||||
export const toHex = function(ipfsHash) {
|
||||
|
@ -63,7 +63,7 @@ export const toHex = function(ipfsHash) {
|
|||
|
||||
To implement the method transfer from hex format to IPFS(Base58) :
|
||||
|
||||
```
|
||||
```javascript
|
||||
import multihash from 'multihashes'
|
||||
|
||||
export const toBase58 = function(contentHash) {
|
||||
|
|
|
@ -7,7 +7,6 @@ status: Draft
|
|||
type: Standards Track
|
||||
category: ERC
|
||||
created: 2018-05-05
|
||||
version: 1.0.0
|
||||
---
|
||||
|
||||
## Simple Summary
|
||||
|
@ -46,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](http://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](https://eips.ethereum.org/EIPS/eip-658), and there's no reason that these status codes couldn't be used by the EVM itself.
|
||||
|
||||
### Smart Contract Autonomy
|
||||
|
||||
|
@ -104,10 +103,10 @@ General codes. These double as bare "reasons", since `0x01 == 1`.
|
|||
| `0x02` | Awaiting Others |
|
||||
| `0x03` | Accepted |
|
||||
| `0x04` | Lower Limit or Insufficient |
|
||||
| `0x05` | Reciever Action Requested |
|
||||
| `0x05` | Receiver Action Requested |
|
||||
| `0x06` | Upper Limit |
|
||||
| `0x07` | [reserved] |
|
||||
| `0x08` | Duplicate, Unnessesary, or Inapplicable |
|
||||
| `0x08` | Duplicate, Unnecessary, or Inapplicable |
|
||||
| `0x09` | [reserved] |
|
||||
| `0x0A` | [reserved] |
|
||||
| `0x0B` | [reserved] |
|
||||
|
@ -130,7 +129,7 @@ Also used for common state machine actions (ex. "stoplight" actions).
|
|||
| `0x15` | Needs Your Permission or Request for Continuation |
|
||||
| `0x16` | Revoked or Banned |
|
||||
| `0x17` | [reserved] |
|
||||
| `0x18` | Not Applicatable to Current State |
|
||||
| `0x18` | Not Applicable to Current State |
|
||||
| `0x19` | [reserved] |
|
||||
| `0x1A` | [reserved] |
|
||||
| `0x1B` | [reserved] |
|
||||
|
@ -229,7 +228,7 @@ Special token and financial concepts. Many related concepts are included in othe
|
|||
| `0x5C` | [reserved] |
|
||||
| `0x5D` | [reserved] |
|
||||
| `0x5E` | [reserved] |
|
||||
| `0x5F` | Token or Fiunancial Information |
|
||||
| `0x5F` | Token or Financial Information |
|
||||
|
||||
#### `0x6*` TBD
|
||||
|
||||
|
@ -286,7 +285,7 @@ Currently unspecified. (Full range reserved)
|
|||
|
||||
Actions around signatures, cryptography, signing, and application-level authentication.
|
||||
|
||||
The meta code `0xEF` is often used to signal a payload descibing the algorithm or process used.
|
||||
The meta code `0xEF` is often used to signal a payload describing the algorithm or process used.
|
||||
|
||||
| Code | Description |
|
||||
|--------|-------------------------------------|
|
||||
|
@ -344,14 +343,14 @@ Among other things, the meta code `0xFF` may be used to describe what the off-ch
|
|||
| `0x*5` | `0x05` Receiver Action Required | `0x15` Needs Your Permission or Request for Continuation | `0x25` Request for Match | `0x35` Receiver's Ratification Requested | `0x45` Awaiting Your Availability | `0x55` Funds Requested | `0x65` [reserved] | `0x75` [reserved] | `0x85` [reserved] | `0x95` [reserved] | `0xA5` App-Specific Receiver Action Requested | `0xB5` [reserved] | `0xC5` [reserved] | `0xD5` [reserved] | `0xE5` Signature Required | `0xF5` Off-Chain Action Required |
|
||||
| `0x*6` | `0x06` Upper Limit | `0x16` Revoked or Banned | `0x26` Above Range or Overflow | `0x36` Offer or Vote Limit Reached | `0x46` Expired | `0x56` Transfer Volume Exceeded | `0x66` [reserved] | `0x76` [reserved] | `0x86` [reserved] | `0x96` [reserved] | `0xA6` App-Specific Expiry or Limit | `0xB6` [reserved] | `0xC6` [reserved] | `0xD6` [reserved] | `0xE6` Known to be Compromised | `0xF6` Off-Chain Expiry or Limit Reached |
|
||||
| `0x*7` | `0x07` [reserved] | `0x17` [reserved] | `0x27` [reserved] | `0x37` [reserved] | `0x47` [reserved] | `0x57` [reserved] | `0x67` [reserved] | `0x77` [reserved] | `0x87` [reserved] | `0x97` [reserved] | `0xA7` [reserved] | `0xB7` [reserved] | `0xC7` [reserved] | `0xD7` [reserved] | `0xE7` [reserved] | `0xF7` [reserved] |
|
||||
| `0x*8` | `0x08` Duplicate, Unnessesary, or Inapplicable | `0x18` Not Applicatable to Current State | `0x28` Duplicate, Conflict, or Collision | `0x38` Already Voted | `0x48` Already Done | `0x58` Funds Not Required | `0x68` [reserved] | `0x78` [reserved] | `0x88` [reserved] | `0x98` [reserved] | `0xA8` App-Specific Inapplicable Condition | `0xB8` [reserved] | `0xC8` [reserved] | `0xD8` [reserved] | `0xE8` Already Signed or Not Encrypted | `0xF8` Duplicate Off-Chain Request |
|
||||
| `0x*8` | `0x08` Duplicate, Unnecessary, or Inapplicable | `0x18` Not Applicable to Current State | `0x28` Duplicate, Conflict, or Collision | `0x38` Already Voted | `0x48` Already Done | `0x58` Funds Not Required | `0x68` [reserved] | `0x78` [reserved] | `0x88` [reserved] | `0x98` [reserved] | `0xA8` App-Specific Inapplicable Condition | `0xB8` [reserved] | `0xC8` [reserved] | `0xD8` [reserved] | `0xE8` Already Signed or Not Encrypted | `0xF8` Duplicate Off-Chain Request |
|
||||
| `0x*9` | `0x09` [reserved] | `0x19` [reserved] | `0x29` [reserved] | `0x39` [reserved] | `0x49` [reserved] | `0x59` [reserved] | `0x69` [reserved] | `0x79` [reserved] | `0x89` [reserved] | `0x99` [reserved] | `0xA9` [reserved] | `0xB9` [reserved] | `0xC9` [reserved] | `0xD9` [reserved] | `0xE9` [reserved] | `0xF9` [reserved] |
|
||||
| `0x*A` | `0x0A` [reserved] | `0x1A` [reserved] | `0x2A` [reserved] | `0x3A` [reserved] | `0x4A` [reserved] | `0x5A` [reserved] | `0x6A` [reserved] | `0x7A` [reserved] | `0x8A` [reserved] | `0x9A` [reserved] | `0xAA` [reserved] | `0xBA` [reserved] | `0xCA` [reserved] | `0xDA` [reserved] | `0xEA` [reserved] | `0xFA` [reserved] |
|
||||
| `0x*B` | `0x0B` [reserved] | `0x1B` [reserved] | `0x2B` [reserved] | `0x3B` [reserved] | `0x4B` [reserved] | `0x5B` [reserved] | `0x6B` [reserved] | `0x7B` [reserved] | `0x8B` [reserved] | `0x9B` [reserved] | `0xAB` [reserved] | `0xBB` [reserved] | `0xCB` [reserved] | `0xDB` [reserved] | `0xEB` [reserved] | `0xFB` [reserved] |
|
||||
| `0x*C` | `0x0C` [reserved] | `0x1C` [reserved] | `0x2C` [reserved] | `0x3C` [reserved] | `0x4C` [reserved] | `0x5C` [reserved] | `0x6C` [reserved] | `0x7C` [reserved] | `0x8C` [reserved] | `0x9C` [reserved] | `0xAC` [reserved] | `0xBC` [reserved] | `0xCC` [reserved] | `0xDC` [reserved] | `0xEC` [reserved] | `0xFC` [reserved] |
|
||||
| `0x*D` | `0x0D` [reserved] | `0x1D` [reserved] | `0x2D` [reserved] | `0x3D` [reserved] | `0x4D` [reserved] | `0x5D` [reserved] | `0x6D` [reserved] | `0x7D` [reserved] | `0x8D` [reserved] | `0x9D` [reserved] | `0xAD` [reserved] | `0xBD` [reserved] | `0xCD` [reserved] | `0xDD` [reserved] | `0xED` [reserved] | `0xFD` [reserved] |
|
||||
| `0x*E` | `0x0E` [reserved] | `0x1E` [reserved] | `0x2E` [reserved] | `0x3E` [reserved] | `0x4E` [reserved] | `0x5E` [reserved] | `0x6E` [reserved] | `0x7E` [reserved] | `0x8E` [reserved] | `0x9E` [reserved] | `0xAE` [reserved] | `0xBE` [reserved] | `0xCE` [reserved] | `0xDE` [reserved] | `0xEE` [reserved] | `0xFE` [reserved] |
|
||||
| `0x*F` | `0x0F` Informational or Metadata | `0x1F` Permission Details or Control Conditions | `0x2F` Matching Meta or Info | `0x3F` Negotiation Rules or Participation Info | `0x4F` Availability Rules or Info (ex. time since or until) | `0x5F` Token or Fiunancial Information | `0x6F` [reserved] | `0x7F` [reserved] | `0x8F` [reserved] | `0x9F` [reserved] | `0xAF` App-Specific Meta or Info | `0xBF` [reserved] | `0xCF` [reserved] | `0xDF` [reserved] | `0xEF` Cryptography, ID, or Proof Metadata | `0xFF` Off-Chain Info or Meta |
|
||||
| `0x*F` | `0x0F` Informational or Metadata | `0x1F` Permission Details or Control Conditions | `0x2F` Matching Meta or Info | `0x3F` Negotiation Rules or Participation Info | `0x4F` Availability Rules or Info (ex. time since or until) | `0x5F` Token or Financial Information | `0x6F` [reserved] | `0x7F` [reserved] | `0x8F` [reserved] | `0x9F` [reserved] | `0xAF` App-Specific Meta or Info | `0xBF` [reserved] | `0xCF` [reserved] | `0xDF` [reserved] | `0xEF` Cryptography, ID, or Proof Metadata | `0xFF` Off-Chain Info or Meta |
|
||||
|
||||
### Example Function Change
|
||||
|
||||
|
@ -491,7 +490,7 @@ Alternate schemes include `bytes32` and `uint8`. While these work reasonably wel
|
|||
|
||||
`uint8` feels even more similar to HTTP status codes, and enums don't require as much casting. However does not break as evenly as a square table (256 doesn't look as nice in base 10).
|
||||
|
||||
Packing multiple codes into a single `bytes32` is nice in theory, but poses additional challenges. Unused space may be interpeted as `0x00 Failure`, you can only efficiently pack four codes at once, and there is a challenge in ensuring that code combinations are sensible. Forcing four codes into a packed representation encourages multiple status codes to be returned, which is often more information than strictly necessarily. This can lead to paradoxical results (ex `0x00` and `0x01` together), or greater resorces allocated to interpreting 256<sup>4</sup> (4.3 billion) permutations.
|
||||
Packing multiple codes into a single `bytes32` is nice in theory, but poses additional challenges. Unused space may be interpreted as `0x00 Failure`, you can only efficiently pack four codes at once, and there is a challenge in ensuring that code combinations are sensible. Forcing four codes into a packed representation encourages multiple status codes to be returned, which is often more information than strictly necessarily. This can lead to paradoxical results (ex `0x00` and `0x01` together), or greater resources allocated to interpreting 256<sup>4</sup> (4.3 billion) permutations.
|
||||
|
||||
### Multiple Returns
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
eip: 107
|
||||
title: safe "eth_sendTransaction" authorization via html popup
|
||||
author: Ronan Sandford <wighawag@gmail.com>
|
||||
author: Ronan Sandford (@wighawag)
|
||||
created: 2016-06-05
|
||||
status: Draft
|
||||
type: Standards Track
|
||||
|
@ -16,7 +16,7 @@ Every read only rpc call the dapp wants to perform is redirected to an invisible
|
|||
|
||||
Motivation
|
||||
==========
|
||||
Currently, if a user navigates to a dapp running on a website using her/his everyday browser, the dapp will by default have no access to the rpc api for security reasons. The user will have to enable CORS for the website's domain in order for the dapp to work. Unfortunately if the user does so, the dapp will be able to send transactions from any unlocked account without the need for any user consent. In other words, not only does the user need to change the node's default setting, but the user is also forced to trust the dapp in order to use it. This is of course not acceptable and forces existing dapps to rely on the use of workarrounds like:
|
||||
Currently, if a user navigates to a dapp running on a website using her/his everyday browser, the dapp will by default have no access to the rpc api for security reasons. The user will have to enable CORS for the website's domain in order for the dapp to work. Unfortunately if the user does so, the dapp will be able to send transactions from any unlocked account without the need for any user consent. In other words, not only does the user need to change the node's default setting, but the user is also forced to trust the dapp in order to use it. This is of course not acceptable and forces existing dapps to rely on the use of workarounds like:
|
||||
- if the transaction is a plain ether transfer, the user is asked to enter it in a dedicated trusted wallet like "Mist"
|
||||
- For more complex case, the user is asked to enter the transaction manually via the node command line interface.
|
||||
|
||||
|
@ -50,12 +50,12 @@ In order for the mechanism to work, the node needs to serve an html file via htt
|
|||
|
||||
This file will then be used by the dapp in 2 different modes (invisible iframe and popup window).
|
||||
|
||||
The invisible iframe will be embeded in the dapp to allow the dapp to send its read-only rpc call without having to enable CORS for the dapp's website domain. This is done by sending message to the iframe (via javascript ```window.postMessage```) which in turn execute the rpc call. This works since the iframe and the node share the same domain/port.
|
||||
The invisible iframe will be embedded in the dapp to allow the dapp to send its read-only rpc call without having to enable CORS for the dapp's website domain. This is done by sending message to the iframe (via javascript ```window.postMessage```) which in turn execute the rpc call. This works since the iframe and the node share the same domain/port.
|
||||
|
||||
In the iframe mode, the html file's javascript code will ensure that no call requiring an unlocked key can be made. This is to prevent dapps from embedding the invisible iframe and tricking the user into clicking the confirm button.
|
||||
If the dapp requires an ```eth_sendTransaction``` call, the dapp will instead open a new window using the same url.
|
||||
|
||||
In this popup window mode, the html file's javascript code will alow ```eth_sendTransaction``` (but not ```eth_sign```, as there is no way to display to the user the meaningful content of the transaction to sign in a safe way) to be called. But instead of sending the call to the node directly, a confirmation dialog will be presented showing the sender and recipient addresses, as well as the amount being transfered along with the potential gas cost. Upon the user approving, the request will be sent and the result returned to the dapp. An error will be returned in case the user cancel the request.
|
||||
In this popup window mode, the html file's javascript code will allow ```eth_sendTransaction``` (but not ```eth_sign```, as there is no way to display to the user the meaningful content of the transaction to sign in a safe way) to be called. But instead of sending the call to the node directly, a confirmation dialog will be presented showing the sender and recipient addresses, as well as the amount being transferred along with the potential gas cost. Upon the user approving, the request will be sent and the result returned to the dapp. An error will be returned in case the user cancel the request.
|
||||
|
||||
The html page also checks for the availability of the "personal" api and if so, will ask the user to unlock the account if necessary. The unlocking is temporary (3s) so the password will be asked again if a transaction is attempted before the end of this short time.
|
||||
|
||||
|
@ -75,7 +75,7 @@ Upon receiving such message, the iframe will perform the actual rpc call to the
|
|||
In all the cases, the iframe/window will send a message back to the dapp using the following object:
|
||||
```
|
||||
{
|
||||
id:<id matchign the request>,
|
||||
id:<id matching the request>,
|
||||
result:<rpc result as is>,
|
||||
error:<error object>
|
||||
}
|
||||
|
@ -612,3 +612,6 @@ That's it.
|
|||
</body>
|
||||
</html>
|
||||
```
|
||||
## Copyright
|
||||
|
||||
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
eip: 1077
|
||||
title: Executable Signed Messages refunded by the contract
|
||||
author: Alex Van de Sande <avsa@ethereum.org>, Ricardo Guilherme Schmidt
|
||||
author: Alex Van de Sande <avsa@ethereum.org>, Ricardo Guilherme Schmidt (@3esmit)
|
||||
discussions-to: https://ethereum-magicians.org/t/erc1077-and-1078-the-magic-of-executable-signed-messages-to-login-and-do-actions/351
|
||||
status: Draft
|
||||
type: Standards Track
|
||||
|
@ -51,7 +51,7 @@ In order to be compliant, the transaction **MUST** request to sign a messageHash
|
|||
|
||||
The fields **MUST** be concatenated in this order:
|
||||
|
||||
```
|
||||
```solidity
|
||||
keccak256(
|
||||
byte(0x19),
|
||||
byte(0),
|
||||
|
@ -84,7 +84,7 @@ Regardless of which fields you use, in your contract you **must** accept an extr
|
|||
|
||||
#### Multiple signatures
|
||||
|
||||
If multiple signatures are required, then all signed messageHashes should then be *ordered by account* and sent to the receiveing contract which then will execute the following actions:
|
||||
If multiple signatures are required, then all signed messageHashes should then be *ordered by account* and sent to the receiving contract which then will execute the following actions:
|
||||
|
||||
#### keep track of nonces:
|
||||
|
||||
|
@ -166,7 +166,7 @@ A function which returns the amount of signatures that are required for a given
|
|||
|
||||
`event ExecutedSigned(bytes32 signHash, uint nonce, bool success);`
|
||||
|
||||
Whenever a new transaction is executed it **must** emit an event with the signHash, nonce and either the transaction was sucessfully executed or not. Apps that are waiting for a transaction to be executed should subscribe to the identity and watch this event to see if their transaction was sucessful. If a different signHash is executed with an equal or higher nonce, it means that your transaction has been replaced.
|
||||
Whenever a new transaction is executed it **must** emit an event with the signHash, nonce and either the transaction was successfully executed or not. Apps that are waiting for a transaction to be executed should subscribe to the identity and watch this event to see if their transaction was successful. If a different signHash is executed with an equal or higher nonce, it means that your transaction has been replaced.
|
||||
|
||||
## Implementation
|
||||
One initial implementation of such a contract can be found at [the Identity Gas Relay at the Status repository](https://github.com/status-im/contracts/blob/73-economic-abstraction/contracts/identity/IdentityGasRelay.sol)
|
||||
|
|
|
@ -71,7 +71,7 @@ Here's an example of a EIP681 compatible address to add a public key generated l
|
|||
|
||||
`ethereum:bob.example.eth?function=addKey(address='0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef',uint=1)`
|
||||
|
||||
If adding the new key requires multiple signatures, or if the app receiving that request exclusiveky deals with executeable signed messages and has no ether on itself, then it should follow the steps in the next section on how to request transactions.
|
||||
If adding the new key requires multiple signatures, or if the app receiving that request exclusiveky deals with executable signed messages and has no ether on itself, then it should follow the steps in the next section on how to request transactions.
|
||||
|
||||
As before, the user shouldn’t be forced to wait for transaction confirmation times. Instead, have an indicator somewhere on the app the shows the progress and then allow the user to interact with your app normally.
|
||||
|
||||
|
|
|
@ -172,7 +172,7 @@ event AccountFrozen(address indexed reported)
|
|||
|
||||
## Rationale
|
||||
|
||||
* A recoverable token standard can provide configurable saftey for users or contracts who desire this saftey.
|
||||
* A recoverable token standard can provide configurable safety for users or contracts who desire this safety.
|
||||
* Implementations of this standard will give users the ability to select a dispute resolution process on an opt-in basis and benefit the community by decreasing the necessity of consideration of token recovery actions.
|
||||
|
||||
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
---
|
||||
eip: 1081
|
||||
Title: Standard Bounties
|
||||
Authors: Mark Beylin <mark.beylin@consensys.net>, Kevin Owocki <kevin.owocki@consensys.net>, Ricardo Guilherme Schmidt (@3esmit)
|
||||
Discussions-to: https://gitter.im/bounties-network/Lobby
|
||||
Status: Draft
|
||||
Type: Standards Track
|
||||
Category: ERC
|
||||
Created: 2018-05-14
|
||||
Requires: 20
|
||||
title: Standard Bounties
|
||||
author: Mark Beylin <mark.beylin@consensys.net>, Kevin Owocki <kevin.owocki@consensys.net>, Ricardo Guilherme Schmidt (@3esmit)
|
||||
discussions-to: https://gitter.im/bounties-network/Lobby
|
||||
status: Draft
|
||||
type: Standards Track
|
||||
category: ERC
|
||||
created: 2018-05-14
|
||||
requires: 20
|
||||
---
|
||||
|
||||
## Simple Summary
|
||||
|
@ -42,7 +42,7 @@ Optional Functions:
|
|||
- `acceptAndFulfill(address[] _fulfillers, uint[] _numerators, uint _denomenator, string _data, StandardToken[] _payoutTokens, uint[] _tokenAmounts)`: During the course of the development of this standard, we discovered the desire for fulfillers to avoid paying gas fees on their own, entrusting the bounty's `issuer` to make the submission for them, and at the same time accept it. This is useful since it still immutably stores the exchange of tokens for completed work, but avoids the need for new bounty fulfillers to have any ETH to pay for gas costs in advance of their earnings.
|
||||
- `changeMasterCopy(StandardBounty _masterCopy)`: For `issuer`s to be able to change the masterCopy which their proxy contract relies on, if the proxy design pattern is being employed.
|
||||
- `refundableContribute(uint[] _amounts, StandardToken[] _tokens)`: While non-refundable contributions may be sent to a bounty simply by transferring those tokens to the address where it resides, one may also desire to contribute to a bounty with the option to refund their contribution, should the bounty never receive a correct submission which is paid out.
|
||||
`refundContribution(uint _contributionId)`: If a bounty hasn't yet paid out to any correct submissions and is past it's deadline, those individuals who employed the `refundableContribute` function may retreive their funds from the contract.
|
||||
`refundContribution(uint _contributionId)`: If a bounty hasn't yet paid out to any correct submissions and is past it's deadline, those individuals who employed the `refundableContribute` function may retrieve their funds from the contract.
|
||||
|
||||
**Schemas**
|
||||
Persona Schema:
|
||||
|
|
|
@ -7,17 +7,18 @@ status: Draft
|
|||
type: Standards Track
|
||||
category: Interface
|
||||
created: 2018-05-04
|
||||
requires: 1474
|
||||
---
|
||||
|
||||
## Simple summary
|
||||
|
||||
This proposal describes a way for DOM environments to expose user accounts in a way that requires user approval.
|
||||
This proposal describes a communication protocol between dapps and Ethereum-enabled DOM environments that allows the Ethereum-enabled DOM environment to choose what information to supply the dapp with and when.
|
||||
|
||||
## Abstract
|
||||
|
||||
The previous generation of Ethereum-enabled DOM environments follows a pattern of injecting a provider populated with accounts without user consent. This puts users of such environments at risk because malicious websites can use these accounts to view detailed account information and to arbitrarily initiate unwanted transactions on a user's behalf.
|
||||
|
||||
This proposal outlines a protocol in which Ethereum-enabled DOM environments expose no accounts until the user approves account access.
|
||||
This proposal outlines a protocol in which Ethereum-enabled DOM environments can choose to expose no accounts until the user approves account access.
|
||||
|
||||
## Specification
|
||||
|
||||
|
@ -29,7 +30,7 @@ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "S
|
|||
|
||||
#### `eth_requestAccounts`
|
||||
|
||||
Providers exposed by Ethereum-enabled DOM environments define a new RPC method: `eth_requestAccounts`. Calling this method triggers a user interface that allows the user to approve or reject account access for a given dapp. This method returns a `Promise` that is resolved with an `Array` of accounts if the user approves access or rejected with an `Error` if the user rejects access.
|
||||
Providers exposed by Ethereum-enabled DOM environments define a new RPC method: `eth_requestAccounts`. Calling this method may trigger a user interface that allows the user to approve or reject account access for a given dapp. This method returns a `Promise` that is resolved with an `Array` of accounts or is rejected with an `Error` if accounts are not available.
|
||||
|
||||
```js
|
||||
ethereum.send('eth_requestAccounts'): Promise<string>
|
||||
|
@ -37,7 +38,7 @@ ethereum.send('eth_requestAccounts'): Promise<string>
|
|||
|
||||
#### Provider#enable (DEPRECATED)
|
||||
|
||||
**Note: This method is deprecated in favor of the RPC method [`eth_requestAccounts`](#eth_requestAccounts).**
|
||||
**Note: This method is deprecated in favor of the RPC method [`eth_requestAccounts`](#eth_requestaccounts).**
|
||||
|
||||
Providers exposed by Ethereum-enabled DOM environments define a new RPC method: `ethereum.enable()`. Calling this method triggers a user interface that allows the user to approve or reject account access for a given dapp. This method returns a `Promise` that is resolved with an `Array` of accounts if the user approves access or rejected with an `Error` if the user rejects access.
|
||||
|
||||
|
@ -75,15 +76,15 @@ IF provider is undefined
|
|||
|
||||
##### `[1] REQUEST`
|
||||
|
||||
Dapps **MUST** request account access by calling the `eth_requestAccounts` RPC method on the provider exposed at `window.ethereum`. Calling this method **MUST** trigger a user interface that allows the user to approve or reject account access for a given dapp. This method **MUST** return a `Promise` that is resolved with an array of user accounts if the user approves account access or rejected if the user rejects account access.
|
||||
Dapps **MUST** request accounts by calling the `eth_requestAccounts` RPC method on the provider exposed at `window.ethereum`. Calling this method **MAY** trigger a user interface that allows the user to approve or reject account access for a given dapp. This method **MUST** return a `Promise` that is resolved with an array of one or more user accounts or rejected if no accounts are available (e.g., the user rejected account access).
|
||||
|
||||
##### `[2] RESOLVE`
|
||||
|
||||
If a user approves account access, DOM environments **MUST** populate the provider exposed at `window.ethereum` with an `Array` of user accounts. The `Promise` returned when calling the `eth_requestAccounts` RPC method **MUST** be resolved with an `Array` of user accounts.
|
||||
The `Promise` returned when calling the `eth_requestAccounts` RPC method **MUST** be resolved with an `Array` of user accounts.
|
||||
|
||||
##### `[3] REJECT`
|
||||
|
||||
If a user rejects account access, the `Promise` returned when calling the `eth_requestAccounts` RPC method **MUST** be rejected with an informative `Error`.
|
||||
The `Promise` returned when calling the `eth_requestAccounts` RPC method **MUST** be rejected with an informative `Error` if no accounts are available for any reason.
|
||||
|
||||
### Example initialization
|
||||
|
||||
|
@ -101,19 +102,16 @@ try {
|
|||
### Constraints
|
||||
|
||||
* Browsers **MUST** expose a provider at `window.ethereum` .
|
||||
* Browsers **MUST NOT** populate the provider with user accounts by default.
|
||||
* Browsers **MUST** define an `eth_requestAccounts` RPC method.
|
||||
* Browsers **MUST** show an account access approval UI when `eth_requestAccounts` is called.
|
||||
* Browsers **MUST** populate the provider with accounts if account access is approved.
|
||||
* Browsers **MUST** resolve the `Promise` returned by `eth_requestAccounts` if account access is approved.
|
||||
* Browsers **MUST NOT** populate the provider with accounts if account access is rejected.
|
||||
* Browsers **MUST** reject the `Promise` returned by `eth_requestAccounts` with an `Error` if account access is rejected.
|
||||
* Browsers **MAY** wait for a user interaction before resolving/rejecting the `eth_requestAccounts` promise.
|
||||
* Browsers **MUST** include at least one account if the `eth_requestAccounts` promise is resolved.
|
||||
* Browsers **MUST** reject the promise with an informative error if no accounts are available.
|
||||
|
||||
## Rationale
|
||||
|
||||
The pattern of automatic account exposure followed by the previous generation of Ethereum-enabled DOM environments fails to protect user privacy and fails to maintain safe user experience: untrusted websites can both view detailed account information and arbitrarily initiate transactions on a user's behalf. Even though most users may reject unsolicited transactions on untrusted websites, a protocol for account access should make such unsolicited requests impossible.
|
||||
|
||||
This proposal establishes a new pattern wherein dapps must request access to user accounts. This protocol directly strengthens user privacy by hiding user accounts and preventing unsolicited transaction requests on untrusted sites.
|
||||
This proposal establishes a new pattern wherein dapps must request access to user accounts. This protocol directly strengthens user privacy by allowing the browser to hide user accounts and preventing unsolicited transaction requests on untrusted sites.
|
||||
|
||||
### Immediate value-add
|
||||
|
||||
|
|
|
@ -1,22 +1,27 @@
|
|||
---
|
||||
eip: 1108
|
||||
title: Reduce alt_bn128 precompile gas costs
|
||||
author: Antonio Salazar Cardozo (@shadowfiend)
|
||||
status: Draft
|
||||
author: Antonio Salazar Cardozo (@shadowfiend), Zachary Williamson (@zac-williamson)
|
||||
discussions-to: https://ethereum-magicians.org/t/eip-1108-reduce-alt-bn128-precompile-gas-costs/3206
|
||||
status: Final
|
||||
type: Standards Track
|
||||
category: Core
|
||||
created: 2018-05-21
|
||||
requires: 196, 197
|
||||
---
|
||||
|
||||
## Short Description
|
||||
## Simple Summary
|
||||
|
||||
Recent changes to the underlying library used by the official Go reference
|
||||
The elliptic curve arithmetic precompiles are currently overpriced. Re-pricing the precompiles would greatly assist a number of privacy solutions and scaling solutions on Ethereum.
|
||||
|
||||
## Abstract
|
||||
|
||||
Changes in 2018 to the underlying library used by the official Go reference
|
||||
implementation led to significant performance gains for the `ECADD`, `ECMUL`,
|
||||
and pairing check precompiled contracts on the `alt_bn128` elliptic curve.
|
||||
|
||||
What is more, the performance boost for those operations can be also observed
|
||||
for Parity client.
|
||||
In the Parity client, field operations used by the precompile algorithms were optimized in 2018,
|
||||
and recent changes to the pairing algorithm used by the `bn` crate have brought considerable speedups.
|
||||
|
||||
Faster operations on Ethereum clients should be reflected in reduced gas costs.
|
||||
|
||||
|
@ -33,12 +38,13 @@ note](https://github.com/ethereum/go-ethereum/pull/16301#issuecomment-372687543)
|
|||
the computational cost of `ECADD`, `ECMUL`, and pairing checks (excepting the
|
||||
constant) has dropped roughly an order of magnitude across the board.
|
||||
|
||||
Also, [optimisations in the bn library](https://github.com/paritytech/bn/pull/9)
|
||||
Also, optimizations in the bn library [in 2018](https://github.com/paritytech/bn/pull/9) and [2019](https://github.com/paritytech/bn/pull/14)
|
||||
used by the [Parity client](https://github.com/paritytech/parity-ethereum) led to a
|
||||
significant performance boost we
|
||||
[benchmarked](https://gist.github.com/pdyraga/4649b74436940a01e8221d85e80bfeef)
|
||||
[benchmarked](https://gist.github.com/zac-williamson/838410a3da179d47d31b25b586c15e53)
|
||||
and compared against the [previous
|
||||
results](https://github.com/ethereum/benchmarking/blob/master/constantinople/analysis2.md).
|
||||
results](https://gist.github.com/pdyraga/4649b74436940a01e8221d85e80bfeef).
|
||||
|
||||
|
||||
## Specification
|
||||
|
||||
|
@ -48,15 +54,86 @@ Following is a table with the current gas cost and new gas cost:
|
|||
| ------------- | --------- | ----------------------------- | ------------------- |
|
||||
| `ECADD` | `0x06` | 500<sup>[1]</sup> | 150 |
|
||||
| `ECMUL` | `0x07` | 40 000<sup>[1]</sup> | 6 000 |
|
||||
| Pairing check | `0x08` | 80 000 * k + 100 000<sup>[2]</sup>| 28 300 * k + 35 450 |
|
||||
| Pairing check | `0x08` | 80 000 * k + 100 000<sup>[2]</sup>| 34 000 * k + 45 000 |
|
||||
|
||||
The gas costs for `ECADD` and `ECMUL` are updates to the costs listed in
|
||||
EIP-196, while the gas costs for the pairing check are updates to the cost
|
||||
listed in EIP-197. Updated gas costs have been adjusted to the less performant
|
||||
client which is Parity, according to benchmarks<sup>[3]</sup>.
|
||||
|
||||
To come up with these updates gas costs, the performance of the `ecrecover` precompile
|
||||
was measured at 116 microseconds per `ecrecover` invocation. Assuming the `ecrecover`
|
||||
gas price is fair at 3,000 gas, we get a price of 25.86 gas per microsecond of a precompile
|
||||
algorithm's runtime. With this in mind, the pairing precompile took 3,037 microseconds to
|
||||
compute 1 pairing, and 14,663 microseconds to compute 10 pairings. From this, the pairing
|
||||
algorithm has a fixed 'base' run-time of 1,745 microseconds, plus 1,292 microseconds per
|
||||
pairing. We can split the run-time into 'fixed cost' and 'linear cost per pairing'
|
||||
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).
|
||||
|
||||
[2]- Per [EIP-197](https://github.com/ethereum/EIPs/blob/df132cd37efb3986f9cd3ef4922b15a767d2c54a/EIPS/eip-197.md#specification).
|
||||
|
||||
[3]- [Parity benchmarks.](https://gist.github.com/pdyraga/4649b74436940a01e8221d85e80bfeef)
|
||||
[3]- [Parity benchmarks.](https://gist.github.com/zac-williamson/838410a3da179d47d31b25b586c15e53)
|
||||
|
||||
[4]- [PR comment clarifying gas cost math](https://github.com/ethereum/EIPs/pull/1987#discussion_r280977066).
|
||||
|
||||
## Rationale
|
||||
|
||||
### Existing protocols would benefit immensely from cheaper elliptic curve cryptography
|
||||
|
||||
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.
|
||||
* [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
|
||||
|
||||
These are all technologies that have been, or are in the process of being, deployed to main-net. There protocols would all benefit from reducing the gas cost of the precompiles.
|
||||
|
||||
To give a concrete example, it currently costs `820,000` gas to validate the cryptography in a typical AZTEC confidential transaction. If the gas schedule for the precompiles correctly reflected their load on the Ethereum network, this cost would be `197,000` gas. This significantly increases the potential use cases for private assets on Ethereum. AZTEC is planning to deploy several cryptographic protocols Ethereum, but these are at the limits of what is practical given the current precompile costs:
|
||||
|
||||
* Confidential weighted voting
|
||||
* Partial-order filling over encrypted orders, for private decentralized exchanges
|
||||
* Anonymous identity sharing proofs (e.g. proving you are on a whitelist, without revealing who you are)
|
||||
* Many-to-one payments and one-to-many confidential payments, as encrypted communication channels between main-net and L2 applications
|
||||
|
||||
For zk-SNARK based protocols on Ethereum, EIP-1108 will not only reduce the gas costs of verifying zk-SNARKs substantially, but can also aid in [batching together multiple zk-SNARK proofs](https://github.com/matter-labs/Groth16BatchVerifier). This is also a technique that can be used to split up monolithic zk-SNARK circuits into a batch of zk-SNARKs with smaller individual circuit sizes, which makes zk-SNARKs both easier to construct and deploy.
|
||||
|
||||
ZEther transactions currently cost ~`6,000,000` gas. This EIP would reduce this to ~`1,000,000` gas, which makes the protocol more practical.
|
||||
|
||||
To summarise, there are several protocols that currently exist on main-net, that would benefit immensely from this EIP. Elliptic curve cryptography can provide valuable solutions for Ethereum, such as scaling and privacy, and the scope and scale of these solutions can be increased if the gas costs for the `bn128` precompiles accurately reflects their computational load on the network.
|
||||
|
||||
### Cheaper elliptic curve cryptography can be used to trade storage for computation
|
||||
|
||||
Solutions such as Rollup and Ignis can be used to batch groups of individual transactions into a zk-SNARK proof, with the on-chain state being represented by a small Merkle root, instead of multiple account balances.
|
||||
|
||||
If zk-SNARK verification costs are decreased, these solutions can be deployed for a wider range of use cases and more Rollup-style transactions can be processed per block.
|
||||
|
||||
### 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.
|
||||
|
||||
|
||||
## Test Cases
|
||||
|
||||
As no underlying algorithms are being changed, there are no additional test cases to specify.
|
||||
|
||||
## Implementation
|
||||
|
||||
Both the Parity and Geth clients have already implemented cryptographic libraries that are fast enough to justify reducing the precompile gas costs. As a reference, here are a list of elliptic curve libraries, in `C++`, `golang` and `rust`, that support the `bn128` curve, and have run-times that are equal to or faster than the Parity benchmarks.
|
||||
|
||||
* [Parity bn crate (rust)](https://github.com/paritytech/bn)
|
||||
* [Geth bn256 library (golang)](https://github.com/ethereum/go-ethereum/tree/master/crypto/bn256/cloudflare)
|
||||
* [MCL, a portable C++ pairing library](https://github.com/herumi/mcl)
|
||||
* [Libff, a C++ pairing library used in many zk-SNARK libraries](https://github.com/scipr-lab/libff)
|
||||
|
||||
## Additional References
|
||||
|
||||
@vbuterin independently proposed a similar reduction after this EIP was originally created, with similar rationale, as [ethereum/EIPs#1187](https://github.com/ethereum/EIPs/issues/1187).
|
||||
|
||||
## Copyright
|
||||
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
|
||||
|
|
|
@ -37,7 +37,7 @@ The input stack values are:
|
|||
|
||||
mu_s[0] = The address of the precompiled smart contract that is called.
|
||||
mu_s[1] = Pointer to memory for the input parameters.
|
||||
mu_s[2] = Length of the input parametes in bytes.
|
||||
mu_s[2] = Length of the input parameters in bytes.
|
||||
mu_s[3] = Pointer to memory where the output is stored
|
||||
mu_s[4] = Length of the output buffer.
|
||||
|
||||
|
@ -75,7 +75,7 @@ Old contracts that call precompiled smart contracts with the CALL method, will c
|
|||
- Call to a regular contract
|
||||
- Call to a regular account
|
||||
- Call to 0x0 smart contract (Does not exists).
|
||||
- Call with large values for the offste pointers and lenghts
|
||||
- Call with large values for the offste pointers and lengths
|
||||
- Call with the exact gas remaining needed to call smart contract.
|
||||
- Call with the exact gas remaining minus one needed to call smart contract.
|
||||
|
||||
|
|
|
@ -77,7 +77,7 @@ contracts.
|
|||
> **Note**
|
||||
>
|
||||
> A [hosted
|
||||
> version](http://ethpm.github.io/ethpm-spec) of this
|
||||
> version](https://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.
|
||||
|
@ -89,7 +89,7 @@ Guiding Principles
|
|||
This specification makes the following assumptions about the document
|
||||
lifecycle.
|
||||
|
||||
1. Package manifests are intended to be generated programatically by
|
||||
1. Package manifests are intended to be generated programmatically by
|
||||
package management software as part of the release process.
|
||||
|
||||
2. Package manifests will be consumed by package managers during tasks
|
||||
|
@ -174,7 +174,7 @@ name collisions with future versions of the specification.
|
|||
<tbody>
|
||||
<tr class="odd">
|
||||
<td><p>See Also</p></td>
|
||||
<td><p>Formalized (<a href="http://json-schema.org">JSON-Schema</a>) version of this specification: <a href="https://github.com/ethpm/ethpm-spec/tree/v2.0.0/spec/package.spec.json">package.spec.json</a></p></td>
|
||||
<td><p>Formalized (<a href="https://json-schema.org">JSON-Schema</a>) version of this specification: <a href="https://github.com/ethpm/ethpm-spec/tree/v2.0.0/spec/package.spec.json">package.spec.json</a></p></td>
|
||||
</tr>
|
||||
<tr class="even">
|
||||
<td><p>Jump To</p></td>
|
||||
|
@ -286,7 +286,7 @@ be included in all Packages.
|
|||
|
||||
The `version` field declares the version number of this release. This
|
||||
value **must** be included in all Packages. This value **should**
|
||||
conform to the [semver](http://semver.org/) version
|
||||
conform to the [semver](https://semver.org/) version
|
||||
numbering specification.
|
||||
|
||||
<table>
|
||||
|
@ -1208,8 +1208,6 @@ To reference a contract type from a dependency, use the format
|
|||
section.
|
||||
|
||||
|
||||
<div id="address"></div>
|
||||
|
||||
#### Address: `address`
|
||||
|
||||
The `address` field defines the [Address](#term-address) of the
|
||||
|
@ -1326,8 +1324,6 @@ Every entry in the `link_references` for this bytecode **must** have a
|
|||
corresponding entry in the `link_dependencies` section.
|
||||
|
||||
|
||||
<div id="compiler-compiler-1"></div>
|
||||
|
||||
#### Compiler: `compiler`
|
||||
|
||||
The `compiler` field defines the compiler information that was used
|
||||
|
@ -1397,14 +1393,12 @@ The `name` field defines which compiler was used in compilation.
|
|||
</table>
|
||||
|
||||
|
||||
<div id="version-version-1"></div>
|
||||
|
||||
#### Version: `version`
|
||||
|
||||
The `version` field defines the version of the compiler. The field
|
||||
**should** be OS agnostic (OS not included in the string) and take the
|
||||
form of either the stable version in
|
||||
[semver](http://semver.org/) format or if built on a
|
||||
[semver](https://semver.org/) format or if built on a
|
||||
nightly should be denoted in the form of `<semver>-<commit-hash>` ex:
|
||||
`0.4.8-commit.60cc1668`.
|
||||
|
||||
|
@ -1435,7 +1429,7 @@ nightly should be denoted in the form of `<semver>-<commit-hash>` ex:
|
|||
The `settings` field defines any settings or configuration that was used
|
||||
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).
|
||||
Description](https://solidity.readthedocs.io/en/latest/using-the-compiler.html#compiler-input-and-output-json-description).
|
||||
|
||||
<table>
|
||||
<colgroup>
|
||||
|
@ -1848,7 +1842,7 @@ a supporting implementation.
|
|||
|
||||
- [Truffle](http://trufflesuite.com/)
|
||||
|
||||
- [Populus](http://populus.readthedocs.io/en/latest/)
|
||||
- [Populus](https://populus.readthedocs.io/en/latest/)
|
||||
|
||||
- [Embark](https://embark.status.im/)
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ The intention with this proposal is to enhance the ERC20 standard with token-loc
|
|||
I’ve extended the ERC20 interface with the following enhancements:
|
||||
|
||||
### Locking of tokens
|
||||
```
|
||||
```solidity
|
||||
/**
|
||||
* @dev Locks a specified amount of tokens against an address,
|
||||
* for a specified reason and time
|
||||
|
@ -55,7 +55,7 @@ function lock(bytes32 _reason, uint256 _amount, uint256 _time) public returns (b
|
|||
```
|
||||
|
||||
### Fetching number of tokens locked under each utility
|
||||
```
|
||||
```solidity
|
||||
/**
|
||||
* @dev Returns tokens locked for a specified address for a
|
||||
* specified reason
|
||||
|
@ -67,7 +67,7 @@ function lock(bytes32 _reason, uint256 _amount, uint256 _time) public returns (b
|
|||
```
|
||||
|
||||
### Fetching number of tokens locked under each utility at a future timestamp
|
||||
```
|
||||
```solidity
|
||||
/**
|
||||
* @dev Returns tokens locked for a specified address for a
|
||||
* specified reason at a specific time
|
||||
|
@ -80,7 +80,7 @@ function lock(bytes32 _reason, uint256 _amount, uint256 _time) public returns (b
|
|||
```
|
||||
|
||||
### Fetching number of tokens held by an address
|
||||
```
|
||||
```solidity
|
||||
/**
|
||||
* @dev @dev Returns total tokens held by an address (locked + transferable)
|
||||
* @param _of The address to query the total balance of
|
||||
|
@ -89,7 +89,7 @@ function totalBalanceOf(address _of) view returns (uint256 amount)
|
|||
```
|
||||
|
||||
### Extending lock period
|
||||
```
|
||||
```solidity
|
||||
/**
|
||||
* @dev Extends lock for a specified reason and time
|
||||
* @param _reason The reason to lock tokens
|
||||
|
@ -99,7 +99,7 @@ function totalBalanceOf(address _of) view returns (uint256 amount)
|
|||
```
|
||||
|
||||
### Increasing number of tokens locked
|
||||
```
|
||||
```solidity
|
||||
/**
|
||||
* @dev Increase number of tokens locked for a specified reason
|
||||
* @param _reason The reason to lock tokens
|
||||
|
@ -108,7 +108,7 @@ function totalBalanceOf(address _of) view returns (uint256 amount)
|
|||
function increaseLockAmount(bytes32 _reason, uint256 _amount) public returns (bool)
|
||||
```
|
||||
### Fetching number of unlockable tokens under each utility
|
||||
```
|
||||
```solidity
|
||||
/**
|
||||
* @dev Returns unlockable tokens for a specified address for a specified reason
|
||||
* @param _of The address to query the the unlockable token count of
|
||||
|
@ -117,7 +117,7 @@ function totalBalanceOf(address _of) view returns (uint256 amount)
|
|||
function tokensUnlockable(address _of, bytes32 _reason) public view returns (uint256 amount)
|
||||
```
|
||||
### Fetching number of unlockable tokens
|
||||
```
|
||||
```solidity
|
||||
/**
|
||||
* @dev Gets the unlockable tokens of a specified address
|
||||
* @param _of The address to query the the unlockable token count of
|
||||
|
@ -125,7 +125,7 @@ function totalBalanceOf(address _of) view returns (uint256 amount)
|
|||
function getUnlockableTokens(address _of) public view returns (uint256 unlockableTokens)
|
||||
```
|
||||
### Unlocking tokens
|
||||
```
|
||||
```solidity
|
||||
/**
|
||||
* @dev Unlocks the unlockable tokens of a specified address
|
||||
* @param _of Address of user, claiming back unlockable tokens
|
||||
|
|
|
@ -3,7 +3,7 @@ eip: 1154
|
|||
title: Oracle Interface
|
||||
author: Alan Lu (@cag)
|
||||
discussions-to: https://github.com/ethereum/EIPs/issues/1161
|
||||
status: Draft
|
||||
status: Abandoned
|
||||
type: Standards Track
|
||||
category: ERC
|
||||
created: 2018-06-13
|
||||
|
@ -100,7 +100,7 @@ Transaction-wise, both systems are roughly equivalent in efficiency in this scen
|
|||
#### Result Immutability
|
||||
In both the proposed specification and the alternate specification, results are immutable once they are determined. This is due to the expectation that typical consumers will require results to be immutable in order to determine a resulting state consistently. With the proposed push-based system, the consumer enforces the result immutability requirement, whereas in the alternate pull-based system, either the oracle would have to be trusted to implement the spec correctly and enforce the immutability requirement, or the consumer would also have to handle result immutability.
|
||||
|
||||
For data which mutates over time, the `id` field may be structured to specify "what" and "when" for the data (using 128 bits to specify "when" is still safe for many millenia).
|
||||
For data which mutates over time, the `id` field may be structured to specify "what" and "when" for the data (using 128 bits to specify "when" is still safe for many millennia).
|
||||
|
||||
## Implementation
|
||||
|
||||
|
|
601
EIPS/eip-1155.md
601
EIPS/eip-1155.md
|
@ -1,10 +1,10 @@
|
|||
---
|
||||
eip: 1155
|
||||
title: ERC-1155 Multi Token Standard
|
||||
author: Witek Radomski <witek@enjin.com>, Andrew Cooke <andrew@enjin.com>, Philippe Castonguay <pc@horizongames.net>, James Therien <james@enjin.com>, Eric Binet <eric@enjin.com>
|
||||
author: Witek Radomski <witek@enjin.io>, Andrew Cooke <ac0dem0nk3y@gmail.com>, Philippe Castonguay <pc@horizongames.net>, James Therien <james@turing-complete.com>, Eric Binet <eric@enjin.io>, Ronan Sandford <wighawag@gmail.com>
|
||||
type: Standards Track
|
||||
category: ERC
|
||||
status: Draft
|
||||
status: Final
|
||||
created: 2018-06-17
|
||||
discussions-to: https://github.com/ethereum/EIPs/issues/1155
|
||||
requires: 165
|
||||
|
@ -12,114 +12,120 @@ requires: 165
|
|||
|
||||
## Simple Summary
|
||||
|
||||
A standard interface for contracts that manage multiple token types. A single deployed contract may include any combination of fungible tokens, non-fungible tokens, or other configurations (for example, semi-fungible tokens).
|
||||
A standard interface for contracts that manage multiple token types. A single deployed contract may include any combination of fungible tokens, non-fungible tokens or other configurations (e.g. semi-fungible tokens).
|
||||
|
||||
## Abstract
|
||||
|
||||
This standard outlines a smart contract interface where one can represent any number of Fungible and Non-Fungible token types in a single contract. Existing standards such as ERC-20 require deployment of separate contracts per token type. The ERC-721 standard's Token ID is a single non-fungible index and the group of these non-fungibles is deployed as a single contract with settings for the entire collection. In contrast, the ERC-1155 Multi Token Standard allows for each Token ID to represent a new configurable token type, which may have its own metadata, supply and other attributes.
|
||||
This standard outlines a smart contract interface that can represent any number of fungible and non-fungible token types. Existing standards such as ERC-20 require deployment of separate contracts per token type. The ERC-721 standard's token ID is a single non-fungible index and the group of these non-fungibles is deployed as a single contract with settings for the entire collection. In contrast, the ERC-1155 Multi Token Standard allows for each token ID to represent a new configurable token type, which may have its own metadata, supply and other attributes.
|
||||
|
||||
The `_id` parameter is contained in each function's parameters and indicates a specific token or token type in a transaction.
|
||||
The `_id` argument contained in each function's argument set indicates a specific token or token type in a transaction.
|
||||
|
||||
## Motivation
|
||||
|
||||
Tokens standards like ERC-20 and ERC-721 require a separate contract to be deployed for each token type or collection. This places a lot of redundant bytecode on the Ethereum blockchain and limits certain functionality by the nature of separating each token contract into its own permissioned address. With the rise of blockchain games and platforms like Enjin Coin, game developers may be creating thousands of token types, and a new type of token standard is needed to support them. However, ERC-1155 is not specific to games, and many other applications can benefit from this flexibility.
|
||||
Tokens standards like ERC-20 and ERC-721 require a separate contract to be deployed for each token type or collection. This places a lot of redundant bytecode on the Ethereum blockchain and limits certain functionality by the nature of separating each token contract into its own permissioned address. With the rise of blockchain games and platforms like Enjin Coin, game developers may be creating thousands of token types, and a new type of token standard is needed to support them. However, ERC-1155 is not specific to games and many other applications can benefit from this flexibility.
|
||||
|
||||
New functionality is possible with this design, such as transferring multiple token types at once, saving on transaction costs. Trading (escrow / atomic swaps) of multiple tokens can be built on top of this standard and it removes the need to "approve" individual token contracts separately. It is also easy to describe and mix multiple fungible or non-fungible token types in a single contract.
|
||||
New functionality is possible with this design such as transferring multiple token types at once, saving on transaction costs. Trading (escrow / atomic swaps) of multiple tokens can be built on top of this standard and it removes the need to "approve" individual token contracts separately. It is also easy to describe and mix multiple fungible or non-fungible token types in a single contract.
|
||||
|
||||
# Specification
|
||||
## Specification
|
||||
|
||||
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.
|
||||
|
||||
**Smart contracts implementing the ERC-1155 standard MUST implement the `ERC1155` and `ERC165` interfaces.**
|
||||
**Smart contracts implementing the ERC-1155 standard MUST implement all of the functions in the `ERC1155` interface.**
|
||||
|
||||
**Smart contracts implementing the ERC-1155 standard MUST implement the ERC-165 `supportsInterface` function and MUST return the constant value `true` if `0xd9b67a26` is passed through the `interfaceID` argument.**
|
||||
|
||||
```solidity
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.9;
|
||||
|
||||
/**
|
||||
@title ERC-1155 Multi Token Standard
|
||||
@dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1155.md
|
||||
@dev See https://eips.ethereum.org/EIPS/eip-1155
|
||||
Note: The ERC-165 identifier for this interface is 0xd9b67a26.
|
||||
*/
|
||||
interface ERC1155 /* is ERC165 */ {
|
||||
/**
|
||||
@dev Either TransferSingle or TransferBatch MUST emit when tokens are transferred, including zero value transfers as well as minting or burning.
|
||||
Operator will always be msg.sender.
|
||||
Either event from address `0x0` signifies a minting operation.
|
||||
An event to address `0x0` signifies a burning or melting operation.
|
||||
The total value transferred from address 0x0 minus the total value transferred to 0x0 may be used by clients and exchanges to be added to the "circulating supply" for a given token ID.
|
||||
To broadcast the existence of a token ID with no initial balance, the contract SHOULD emit the TransferSingle event from `0x0` to `0x0`, with the token creator as `_operator`, and a `_value` of 0.
|
||||
@dev Either `TransferSingle` or `TransferBatch` MUST emit when tokens are transferred, including zero value transfers as well as minting or burning (see "Safe Transfer Rules" section of the standard).
|
||||
The `_operator` argument MUST be the address of an account/contract that is approved to make the transfer (SHOULD be msg.sender).
|
||||
The `_from` argument MUST be the address of the holder whose balance is decreased.
|
||||
The `_to` argument MUST be the address of the recipient whose balance is increased.
|
||||
The `_id` argument MUST be the token type being transferred.
|
||||
The `_value` argument MUST be the number of tokens the holder balance is decreased by and match what the recipient balance is increased by.
|
||||
When minting/creating tokens, the `_from` argument MUST be set to `0x0` (i.e. zero address).
|
||||
When burning/destroying tokens, the `_to` argument MUST be set to `0x0` (i.e. zero address).
|
||||
*/
|
||||
event TransferSingle(address indexed _operator, address indexed _from, address indexed _to, uint256 _id, uint256 _value);
|
||||
|
||||
/**
|
||||
@dev Either TransferSingle or TransferBatch MUST emit when tokens are transferred, including zero value transfers as well as minting or burning.
|
||||
Operator will always be msg.sender.
|
||||
Either event from address `0x0` signifies a minting operation.
|
||||
An event to address `0x0` signifies a burning or melting operation.
|
||||
The total value transferred from address 0x0 minus the total value transferred to 0x0 may be used by clients and exchanges to be added to the "circulating supply" for a given token ID.
|
||||
To broadcast the existence of multiple token IDs with no initial balance, this SHOULD emit the TransferBatch event from `0x0` to `0x0`, with the token creator as `_operator`, and a `_value` of 0.
|
||||
@dev Either `TransferSingle` or `TransferBatch` MUST emit when tokens are transferred, including zero value transfers as well as minting or burning (see "Safe Transfer Rules" section of the standard).
|
||||
The `_operator` argument MUST be the address of an account/contract that is approved to make the transfer (SHOULD be msg.sender).
|
||||
The `_from` argument MUST be the address of the holder whose balance is decreased.
|
||||
The `_to` argument MUST be the address of the recipient whose balance is increased.
|
||||
The `_ids` argument MUST be the list of tokens being transferred.
|
||||
The `_values` argument MUST be the list of number of tokens (matching the list and order of tokens specified in _ids) the holder balance is decreased by and match what the recipient balance is increased by.
|
||||
When minting/creating tokens, the `_from` argument MUST be set to `0x0` (i.e. zero address).
|
||||
When burning/destroying tokens, the `_to` argument MUST be set to `0x0` (i.e. zero address).
|
||||
*/
|
||||
event TransferBatch(address indexed _operator, address indexed _from, address indexed _to, uint256[] _ids, uint256[] _values);
|
||||
|
||||
/**
|
||||
@dev MUST emit when an approval is updated.
|
||||
@dev MUST emit when approval for a second party/operator address to manage all tokens for an owner address is enabled or disabled (absence of an event assumes disabled).
|
||||
*/
|
||||
event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);
|
||||
|
||||
/**
|
||||
@dev MUST emit when the URI is updated for a token ID.
|
||||
URIs are defined in RFC 3986.
|
||||
The URI MUST point a JSON file that conforms to the "ERC-1155 Metadata JSON Schema".
|
||||
The URI MUST point to a JSON file that conforms to the "ERC-1155 Metadata URI JSON Schema".
|
||||
*/
|
||||
event URI(string _value, uint256 indexed _id);
|
||||
|
||||
/**
|
||||
@notice Transfers value amount of an _id from the _from address to the _to address specified.
|
||||
@dev MUST emit TransferSingle event on success.
|
||||
Caller must be approved to manage the _from account's tokens (see isApprovedForAll).
|
||||
MUST throw if `_to` is the zero address.
|
||||
MUST throw if balance of sender for token `_id` is lower than the `_value` sent.
|
||||
MUST throw on any other error.
|
||||
When transfer is complete, this function MUST check if `_to` is a smart contract (code size > 0). If so, it MUST call `onERC1155Received` on `_to` and revert if the return value is not `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`.
|
||||
@notice Transfers `_value` amount of an `_id` from the `_from` address to the `_to` address specified (with safety call).
|
||||
@dev Caller must be approved to manage the tokens being transferred out of the `_from` account (see "Approval" section of the standard).
|
||||
MUST revert if `_to` is the zero address.
|
||||
MUST revert if balance of holder for token `_id` is lower than the `_value` sent.
|
||||
MUST revert on any other error.
|
||||
MUST emit the `TransferSingle` event to reflect the balance change (see "Safe Transfer Rules" section of the standard).
|
||||
After the above conditions are met, this function MUST check if `_to` is a smart contract (e.g. code size > 0). If so, it MUST call `onERC1155Received` on `_to` and act appropriately (see "Safe Transfer Rules" section of the standard).
|
||||
@param _from Source address
|
||||
@param _to Target address
|
||||
@param _id ID of the token type
|
||||
@param _value Transfer amount
|
||||
@param _data Additional data with no specified format, sent in call to `_to`
|
||||
@param _data Additional data with no specified format, MUST be sent unaltered in call to `onERC1155Received` on `_to`
|
||||
*/
|
||||
function safeTransferFrom(address _from, address _to, uint256 _id, uint256 _value, bytes calldata _data) external;
|
||||
|
||||
/**
|
||||
@notice Send multiple types of Tokens from a 3rd party in one transfer (with safety call).
|
||||
@dev MUST emit TransferBatch event on success.
|
||||
Caller must be approved to manage the _from account's tokens (see isApprovedForAll).
|
||||
MUST throw if `_to` is the zero address.
|
||||
MUST throw if length of `_ids` is not the same as length of `_values`.
|
||||
MUST throw if any of the balance of sender for token `_ids` is lower than the respective `_values` sent.
|
||||
MUST throw on any other error.
|
||||
When transfer is complete, this function MUST check if `_to` is a smart contract (code size > 0). If so, it MUST call `onERC1155BatchReceived` on `_to` and revert if the return value is not `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`.
|
||||
Transfers and events MUST occur in the array order they were submitted (_ids[0] before _ids[1], etc).
|
||||
@param _from Source addresses
|
||||
@param _to Target addresses
|
||||
@param _ids IDs of each token type
|
||||
@param _values Transfer amounts per token type
|
||||
@param _data Additional data with no specified format, sent in call to `_to`
|
||||
@notice Transfers `_values` amount(s) of `_ids` from the `_from` address to the `_to` address specified (with safety call).
|
||||
@dev Caller must be approved to manage the tokens being transferred out of the `_from` account (see "Approval" section of the standard).
|
||||
MUST revert if `_to` is the zero address.
|
||||
MUST revert if length of `_ids` is not the same as length of `_values`.
|
||||
MUST revert if any of the balance(s) of the holder(s) for token(s) in `_ids` is lower than the respective amount(s) in `_values` sent to the recipient.
|
||||
MUST revert on any other error.
|
||||
MUST emit `TransferSingle` or `TransferBatch` event(s) such that all the balance changes are reflected (see "Safe Transfer Rules" section of the standard).
|
||||
Balance changes and events MUST follow the ordering of the arrays (_ids[0]/_values[0] before _ids[1]/_values[1], etc).
|
||||
After the above conditions for the transfer(s) in the batch are met, this function MUST check if `_to` is a smart contract (e.g. code size > 0). If so, it MUST call the relevant `ERC1155TokenReceiver` hook(s) on `_to` and act appropriately (see "Safe Transfer Rules" section of the standard).
|
||||
@param _from Source address
|
||||
@param _to Target address
|
||||
@param _ids IDs of each token type (order and length must match _values array)
|
||||
@param _values Transfer amounts per token type (order and length must match _ids array)
|
||||
@param _data Additional data with no specified format, MUST be sent unaltered in call to the `ERC1155TokenReceiver` hook(s) on `_to`
|
||||
*/
|
||||
function safeBatchTransferFrom(address _from, address _to, uint256[] calldata _ids, uint256[] calldata _values, bytes calldata _data) external;
|
||||
|
||||
/**
|
||||
@notice Get the balance of an account's Tokens.
|
||||
@notice Get the balance of an account's tokens.
|
||||
@param _owner The address of the token holder
|
||||
@param _id ID of the Token
|
||||
@return The _owner's balance of the Token type requested
|
||||
@param _id ID of the token
|
||||
@return The _owner's balance of the token type requested
|
||||
*/
|
||||
function balanceOf(address _owner, uint256 _id) external view returns (uint256);
|
||||
|
||||
/**
|
||||
@notice Get the balance of multiple account/token pairs
|
||||
@param _owners The addresses of the token holders
|
||||
@param _ids ID of the Tokens
|
||||
@return The _owner's balance of the Token types requested
|
||||
@param _ids ID of the tokens
|
||||
@return The _owner's balance of the token types requested (i.e. balance for each (owner, id) pair)
|
||||
*/
|
||||
function balanceOfBatch(address[] calldata _owners, uint256[] calldata _ids) external view returns (uint256[] memory);
|
||||
|
||||
|
@ -133,32 +139,36 @@ interface ERC1155 /* is ERC165 */ {
|
|||
|
||||
/**
|
||||
@notice Queries the approval status of an operator for a given owner.
|
||||
@param _owner The owner of the Tokens
|
||||
@param _owner The owner of the tokens
|
||||
@param _operator Address of authorized operator
|
||||
@return True if the operator is approved, false if not
|
||||
*/
|
||||
function isApprovedForAll(address _owner, address _operator) external view returns (bool);
|
||||
}
|
||||
```
|
||||
</details>
|
||||
|
||||
## ERC-1155 Token Receiver
|
||||
### ERC-1155 Token Receiver
|
||||
|
||||
Smart contracts **MUST** implement this interface to accept transfers.
|
||||
**Smart contracts MUST implement all of the functions in the `ERC1155TokenReceiver` interface to accept transfers. See "Safe Transfer Rules" for further detail.**
|
||||
|
||||
**Smart contracts MUST implement the ERC-165 `supportsInterface` function and signify support for the `ERC1155TokenReceiver` interface to accept transfers. See "ERC1155TokenReceiver ERC-165 rules" for further detail.**
|
||||
|
||||
```solidity
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.9;
|
||||
|
||||
/**
|
||||
Note: The ERC-165 identifier for this interface is 0x4e2312e0.
|
||||
*/
|
||||
interface ERC1155TokenReceiver {
|
||||
/**
|
||||
@notice Handle the receipt of a single ERC1155 token type.
|
||||
@dev An ERC1155-compliant smart contract MUST call this function on the token recipient contract, at the end of a `safeTransferFrom` after the balance has been updated.
|
||||
This function MAY throw to revert and reject the transfer.
|
||||
Return of other than the magic value MUST result in the transaction being reverted.
|
||||
Note: The contract address is always the message sender.
|
||||
@param _operator The address which called the `safeTransferFrom` function
|
||||
This function MUST return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` (i.e. 0xf23a6e61) if it accepts the transfer.
|
||||
This function MUST revert if it rejects the transfer.
|
||||
Return of any other value than the prescribed keccak256 generated value MUST result in the transaction being reverted by the caller.
|
||||
@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 _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)"))`
|
||||
|
@ -168,13 +178,13 @@ interface ERC1155TokenReceiver {
|
|||
/**
|
||||
@notice Handle the receipt of multiple ERC1155 token types.
|
||||
@dev An ERC1155-compliant smart contract MUST call this function on the token recipient contract, at the end of a `safeBatchTransferFrom` after the balances have been updated.
|
||||
This function MAY throw to revert and reject the transfer.
|
||||
Return of other than the magic value WILL result in the transaction being reverted.
|
||||
Note: The contract address is always the message sender.
|
||||
@param _operator The address which called the `safeBatchTransferFrom` function
|
||||
This function MUST return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` (i.e. 0xbc197c81) if it accepts the transfer(s).
|
||||
This function MUST revert if it rejects the transfer(s).
|
||||
Return of any other value than the prescribed keccak256 generated value MUST result in the transaction being reverted by the caller.
|
||||
@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
|
||||
@param _values An array containing amounts of each token being transferred
|
||||
@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)"))`
|
||||
*/
|
||||
|
@ -182,20 +192,241 @@ interface ERC1155TokenReceiver {
|
|||
}
|
||||
```
|
||||
|
||||
## Metadata
|
||||
### Safe Transfer Rules
|
||||
|
||||
The URI value allows for ID substitution by clients. If the string `%s` exists in any URI, clients MUST replace this with the actual token ID in hexadecimal form. This allows for large number of tokens to use the same on-chain string by defining a URI once, for a large collection of tokens. Example of such a URI: `https://token-cdn-domain/%s.json` would be replaced with `https://token-cdn-domain/780000000000001e000000000000000000000000000000000000000000000000.json` if the client is referring to token ID `780000000000001e000000000000000000000000000000000000000000000000`.
|
||||
To be more explicit about how the standard `safeTransferFrom` and `safeBatchTransferFrom` functions MUST operate with respect to the `ERC1155TokenReceiver` hook functions, a list of scenarios and rules follows.
|
||||
|
||||
The string format of the substituted hexadecimal ID MUST be lowercase alphanumeric: `[0-9a-f]` with no 0x prefix.
|
||||
#### Scenarios
|
||||
|
||||
### Metadata Extensions
|
||||
**_Scenario#1 :_** The recipient is not a contract.
|
||||
* `onERC1155Received` and `onERC1155BatchReceived` MUST NOT be called on an EOA (Externally Owned Account).
|
||||
|
||||
The following optional extensions can be identified with the (ERC-165 Standard Interface Detection)[https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md].
|
||||
**_Scenario#2 :_** The transaction is not a mint/transfer of a token.
|
||||
* `onERC1155Received` and `onERC1155BatchReceived` MUST NOT be called outside of a mint or transfer process.
|
||||
|
||||
Changes to the URI MUST emit the `URI` event if the change can be expressed with an event. If the optional ERC1155Metadata_URI extension is included, the value returned by this function SHOULD be used to retrieve values for which no event was emitted. The function MUST return the same value as the event if it was emitted.
|
||||
**_Scenario#3 :_** The receiver does not implement the necessary `ERC1155TokenReceiver` interface function(s).
|
||||
* The transfer MUST be reverted with the one caveat below.
|
||||
- If the token(s) being sent are part of a hybrid implementation of another standard, that particular standard's rules on sending to a contract MAY now be followed instead. See "Compatibility with other standards" section.
|
||||
|
||||
**_Scenario#4 :_** The receiver implements the necessary `ERC1155TokenReceiver` interface function(s) but returns an unknown value.
|
||||
* The transfer MUST be reverted.
|
||||
|
||||
**_Scenario#5 :_** The receiver implements the necessary `ERC1155TokenReceiver` interface function(s) but throws an error.
|
||||
* The transfer MUST be reverted.
|
||||
|
||||
**_Scenario#6 :_** The receiver implements the `ERC1155TokenReceiver` interface and is the recipient of one and only one balance change (e.g. `safeTransferFrom` called).
|
||||
* The balances for the transfer MUST have been updated before the `ERC1155TokenReceiver` hook is called on a recipient contract.
|
||||
* The transfer event MUST have been emitted to reflect the balance changes before the `ERC1155TokenReceiver` hook is called on the recipient contract.
|
||||
* One of `onERC1155Received` or `onERC1155BatchReceived` MUST be called on the recipient contract.
|
||||
* The `onERC1155Received` hook SHOULD be called on the recipient contract and its rules followed.
|
||||
- See "onERC1155Received rules" for further rules that MUST be followed.
|
||||
* The `onERC1155BatchReceived` hook MAY be called on the recipient contract and its rules followed.
|
||||
- See "onERC1155BatchReceived rules" for further rules that MUST be followed.
|
||||
|
||||
**_Scenario#7 :_** The receiver implements the `ERC1155TokenReceiver` interface and is the recipient of more than one balance change (e.g. `safeBatchTransferFrom` called).
|
||||
* All balance transfers that are referenced in a call to an `ERC1155TokenReceiver` hook MUST be updated before the `ERC1155TokenReceiver` hook is called on the recipient contract.
|
||||
* All transfer events MUST have been emitted to reflect current balance changes before an `ERC1155TokenReceiver` hook is called on the recipient contract.
|
||||
* `onERC1155Received` or `onERC1155BatchReceived` MUST be called on the recipient as many times as necessary such that every balance change for the recipient in the scenario is accounted for.
|
||||
- The return magic value for every hook call MUST be checked and acted upon as per "onERC1155Received rules" and "onERC1155BatchReceived rules".
|
||||
* The `onERC1155BatchReceived` hook SHOULD be called on the recipient contract and its rules followed.
|
||||
- See "onERC1155BatchReceived rules" for further rules that MUST be followed.
|
||||
* The `onERC1155Received` hook MAY be called on the recipient contract and its rules followed.
|
||||
- See "onERC1155Received rules" for further rules that MUST be followed.
|
||||
|
||||
**_Scenario#8 :_** You are the creator of a contract that implements the `ERC1155TokenReceiver` interface and you forward the token(s) onto another address in one or both of `onERC1155Received` and `onERC1155BatchReceived`.
|
||||
* Forwarding should be considered acceptance and then initiating a new `safeTransferFrom` or `safeBatchTransferFrom` in a new context.
|
||||
- The prescribed keccak256 acceptance value magic for the receiver hook being called MUST be returned after forwarding is successful.
|
||||
* The `_data` argument MAY be re-purposed for the new context.
|
||||
* If forwarding fails the transaction MAY be reverted.
|
||||
- If the contract logic wishes to keep the ownership of the token(s) itself in this case it MAY do so.
|
||||
|
||||
**_Scenario#9 :_** You are transferring tokens via a non-standard API call i.e. an implementation specific API and NOT `safeTransferFrom` or `safeBatchTransferFrom`.
|
||||
* In this scenario all balance updates and events output rules are the same as if a standard transfer function had been called.
|
||||
- i.e. an external viewer MUST still be able to query the balance via a standard function and it MUST be identical to the balance as determined by `TransferSingle` and `TransferBatch` events alone.
|
||||
* If the receiver is a contract the `ERC1155TokenReceiver` hooks still need to be called on it and the return values respected the same as if a standard transfer function had been called.
|
||||
- However while the `safeTransferFrom` or `safeBatchTransferFrom` functions MUST revert if a receiving contract does not implement the `ERC1155TokenReceiver` interface, a non-standard function MAY proceed with the transfer.
|
||||
- See "Implementation specific transfer API rules".
|
||||
|
||||
|
||||
#### Rules
|
||||
|
||||
**_safeTransferFrom rules:_**
|
||||
* Caller must be approved to manage the tokens being transferred out of the `_from` account (see "Approval" section).
|
||||
* MUST revert if `_to` is the zero address.
|
||||
* MUST revert if balance of holder for token `_id` is lower than the `_value` sent to the recipient.
|
||||
* MUST revert on any other error.
|
||||
* MUST emit the `TransferSingle` event to reflect the balance change (see "TransferSingle and TransferBatch event rules" section).
|
||||
* After the above conditions are met, this function MUST check if `_to` is a smart contract (e.g. code size > 0). If so, it MUST call `onERC1155Received` on `_to` and act appropriately (see "onERC1155Received rules" section).
|
||||
- The `_data` argument provided by the sender for the transfer MUST be passed with its contents unaltered to the `onERC1155Received` hook function via its `_data` argument.
|
||||
|
||||
**_safeBatchTransferFrom rules:_**
|
||||
* Caller must be approved to manage all the tokens being transferred out of the `_from` account (see "Approval" section).
|
||||
* MUST revert if `_to` is the zero address.
|
||||
* MUST revert if length of `_ids` is not the same as length of `_values`.
|
||||
* MUST revert if any of the balance(s) of the holder(s) for token(s) in `_ids` is lower than the respective amount(s) in `_values` sent to the recipient.
|
||||
* MUST revert on any other error.
|
||||
* MUST emit `TransferSingle` or `TransferBatch` event(s) such that all the balance changes are reflected (see "TransferSingle and TransferBatch event rules" section).
|
||||
* The balance changes and events MUST occur in the array order they were submitted (_ids[0]/_values[0] before _ids[1]/_values[1], etc).
|
||||
* After the above conditions are met, this function MUST check if `_to` is a smart contract (e.g. code size > 0). If so, it MUST call `onERC1155Received` or `onERC1155BatchReceived` on `_to` and act appropriately (see "onERC1155Received and onERC1155BatchReceived rules" section).
|
||||
- The `_data` argument provided by the sender for the transfer MUST be passed with its contents unaltered to the `ERC1155TokenReceiver` hook function(s) via their `_data` argument.
|
||||
|
||||
**_TransferSingle and TransferBatch event rules:_**
|
||||
* `TransferSingle` SHOULD be used to indicate a single balance transfer has occurred between a `_from` and `_to` pair.
|
||||
- It MAY be emitted multiple times to indicate multiple balance changes in the transaction, but note that `TransferBatch` is designed for this to reduce gas consumption.
|
||||
- The `_operator` argument MUST be the address of an account/contract that is approved to make the transfer (SHOULD be msg.sender).
|
||||
- The `_from` argument MUST be the address of the holder whose balance is decreased.
|
||||
- The `_to` argument MUST be the address of the recipient whose balance is increased.
|
||||
- The `_id` argument MUST be the token type being transferred.
|
||||
- The `_value` argument MUST be the number of tokens the holder balance is decreased by and match what the recipient balance is increased by.
|
||||
- When minting/creating tokens, the `_from` argument MUST be set to `0x0` (i.e. zero address). See "Minting/creating and burning/destroying rules".
|
||||
- When burning/destroying tokens, the `_to` argument MUST be set to `0x0` (i.e. zero address). See "Minting/creating and burning/destroying rules".
|
||||
* `TransferBatch` SHOULD be used to indicate multiple balance transfers have occurred between a `_from` and `_to` pair.
|
||||
- It MAY be emitted with a single element in the list to indicate a singular balance change in the transaction, but note that `TransferSingle` is designed for this to reduce gas consumption.
|
||||
- The `_operator` argument MUST be the address of an account/contract that is approved to make the transfer (SHOULD be msg.sender).
|
||||
- The `_from` argument MUST be the address of the holder whose balance is decreased for each entry pair in `_ids` and `_values`.
|
||||
- The `_to` argument MUST be the address of the recipient whose balance is increased for each entry pair in `_ids` and `_values`.
|
||||
- The `_ids` array argument MUST contain the ids of the tokens being transferred.
|
||||
- The `_values` array argument MUST contain the number of token to be transferred for each corresponding entry in `_ids`.
|
||||
- `_ids` and `_values` MUST have the same length.
|
||||
- When minting/creating tokens, the `_from` argument MUST be set to `0x0` (i.e. zero address). See "Minting/creating and burning/destroying rules".
|
||||
- When burning/destroying tokens, the `_to` argument MUST be set to `0x0` (i.e. zero address). See "Minting/creating and burning/destroying rules".
|
||||
* The total value transferred from address `0x0` minus the total value transferred to `0x0` observed via the `TransferSingle` and `TransferBatch` events MAY be used by clients and exchanges to determine the "circulating supply" for a given token ID.
|
||||
* To broadcast the existence of a token ID with no initial balance, the contract SHOULD emit the `TransferSingle` event from `0x0` to `0x0`, with the token creator as `_operator`, and a `_value` of 0.
|
||||
* All `TransferSingle` and `TransferBatch` events MUST be emitted to reflect all the balance changes that have occurred before any call(s) to `onERC1155Received` or `onERC1155BatchReceived`.
|
||||
- To make sure event order is correct in the case of valid re-entry (e.g. if a receiver contract forwards tokens on receipt) state balance and events balance MUST match before calling an external contract.
|
||||
|
||||
**_onERC1155Received rules:_**
|
||||
- The `_operator` argument MUST be the address of an account/contract that is approved to make the transfer (SHOULD be msg.sender).
|
||||
* The `_from` argument MUST be the address of the holder whose balance is decreased.
|
||||
- `_from` MUST be 0x0 for a mint.
|
||||
* The `_id` argument MUST be the token type being transferred.
|
||||
* The `_value` argument MUST be the number of tokens the holder balance is decreased by and match what the recipient balance is increased by.
|
||||
* The `_data` argument MUST contain the information provided by the sender for the transfer with its contents unaltered.
|
||||
- i.e. it MUST pass on the unaltered `_data` argument sent via the `safeTransferFrom` or `safeBatchTransferFrom` call for this transfer.
|
||||
* The recipient contract MAY accept an increase of its balance by returning the acceptance magic value `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
|
||||
- If the return value is `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` the transfer MUST be completed or MUST revert if any other conditions are not met for success.
|
||||
* The recipient contract MAY reject an increase of its balance by calling revert.
|
||||
- If the recipient contract throws/reverts the transaction MUST be reverted.
|
||||
* If the return value is anything other than `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` the transaction MUST be reverted.
|
||||
* `onERC1155Received` (and/or `onERC1155BatchReceived`) MAY be called multiple times in a single transaction and the following requirements must be met:
|
||||
- All callbacks represent mutually exclusive balance changes.
|
||||
- The set of all calls to `onERC1155Received` and `onERC1155BatchReceived` describes all balance changes that occurred during the transaction in the order submitted.
|
||||
* A contract MAY skip calling the `onERC1155Received` hook function if the transfer operation is transferring the token to itself.
|
||||
|
||||
**_onERC1155BatchReceived rules:_**
|
||||
- The `_operator` argument MUST be the address of an account/contract that is approved to make the transfer (SHOULD be msg.sender).
|
||||
* The `_from` argument MUST be the address of the holder whose balance is decreased.
|
||||
- `_from` MUST be 0x0 for a mint.
|
||||
* The `_ids` argument MUST be the list of tokens being transferred.
|
||||
* The `_values` argument MUST be the list of number of tokens (matching the list and order of tokens specified in `_ids`) the holder balance is decreased by and match what the recipient balance is increased by.
|
||||
* The `_data` argument MUST contain the information provided by the sender for the transfer with its contents unaltered.
|
||||
- i.e. it MUST pass on the unaltered `_data` argument sent via the `safeBatchTransferFrom` call for this transfer.
|
||||
* The recipient contract MAY accept an increase of its balance by returning the acceptance magic value `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
|
||||
- If the return value is `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` the transfer MUST be completed or MUST revert if any other conditions are not met for success.
|
||||
* The recipient contract MAY reject an increase of its balance by calling revert.
|
||||
- If the recipient contract throws/reverts the transaction MUST be reverted.
|
||||
* If the return value is anything other than `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` the transaction MUST be reverted.
|
||||
* `onERC1155BatchReceived` (and/or `onERC1155Received`) MAY be called multiple times in a single transaction and the following requirements must be met:
|
||||
- All callbacks represent mutually exclusive balance changes.
|
||||
- The set of all calls to `onERC1155Received` and `onERC1155BatchReceived` describes all balance changes that occurred during the transaction in the order submitted.
|
||||
* A contract MAY skip calling the `onERC1155BatchReceived` hook function if the transfer operation is transferring the token(s) to itself.
|
||||
|
||||
**_ERC1155TokenReceiver ERC-165 rules:_**
|
||||
* The implementation of the ERC-165 `supportsInterface` function SHOULD be as follows:
|
||||
```solidity
|
||||
function supportsInterface(bytes4 interfaceID) external view returns (bool) {
|
||||
return interfaceID == 0x01ffc9a7 || // ERC-165 support (i.e. `bytes4(keccak256('supportsInterface(bytes4)'))`).
|
||||
interfaceID == 0x4e2312e0; // ERC-1155 `ERC1155TokenReceiver` support (i.e. `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)")) ^ bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`).
|
||||
}
|
||||
```
|
||||
* The implementation MAY differ from the above but:
|
||||
- It MUST return the constant value `true` if `0x01ffc9a7` is passed through the `interfaceID` argument. This signifies ERC-165 support.
|
||||
- It MUST return the constant value `true` if `0x4e2312e0` is passed through the `interfaceID` argument. This signifies ERC-1155 `ERC1155TokenReceiver` support.
|
||||
- It MUST NOT consume more than 10,000 gas.
|
||||
- This keeps it below the ERC-165 requirement of 30,000 gas, reduces the gas reserve needs and minimises possible side-effects of gas exhaustion during the call.
|
||||
|
||||
**_Implementation specific transfer API rules:_**
|
||||
* If an implementation specific API function is used to transfer ERC-1155 token(s) to a contract, the `safeTransferFrom` or `safeBatchTransferFrom` (as appropriate) rules MUST still be followed if the receiver implements the `ERC1155TokenReceiver` interface. If it does not the non-standard implementation SHOULD revert but MAY proceed.
|
||||
* An example:
|
||||
1. An approved user calls a function such as `function myTransferFrom(address _from, address _to, uint256[] calldata _ids, uint256[] calldata _values);`.
|
||||
2. `myTransferFrom` updates the balances for `_from` and `_to` addresses for all `_ids` and `_values`.
|
||||
3. `myTransferFrom` emits `TransferBatch` with the details of what was transferred from address `_from` to address `_to`.
|
||||
4. `myTransferFrom` checks if `_to` is a contract address and determines that it is so (if not, then the transfer can be considered successful).
|
||||
5. `myTransferFrom` calls `onERC1155BatchReceived` on `_to` and it reverts or returns an unknown value (if it had returned `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` the transfer can be considered successful).
|
||||
6. At this point `myTransferFrom` SHOULD revert the transaction immediately as receipt of the token(s) was not explicitly accepted by the `onERC1155BatchReceived` function.
|
||||
7. If however `myTransferFrom` wishes to continue it MUST call `supportsInterface(0x4e2312e0)` on `_to` and if it returns the constant value `true` the transaction MUST be reverted, as it is now known to be a valid receiver and the previous acceptance step failed.
|
||||
- NOTE: You could have called `supportsInterface(0x4e2312e0)` at a previous step if you wanted to gather and act upon that information earlier, such as in a hybrid standards scenario.
|
||||
8. If the above call to `supportsInterface(0x4e2312e0)` on `_to` reverts or returns a value other than the constant value `true` the `myTransferFrom` function MAY consider this transfer successful.
|
||||
- __NOTE__: this MAY result in unrecoverable tokens if sent to an address that does not expect to receive ERC-1155 tokens.
|
||||
* The above example is not exhaustive but illustrates the major points (and shows that most are shared with `safeTransferFrom` and `safeBatchTransferFrom`):
|
||||
- Balances that are updated MUST have equivalent transfer events emitted.
|
||||
- A receiver address has to be checked if it is a contract and if so relevant `ERC1155TokenReceiver` hook function(s) have to be called on it.
|
||||
- Balances (and events associated) that are referenced in a call to an `ERC1155TokenReceiver` hook MUST be updated (and emitted) before the `ERC1155TokenReceiver` hook is called.
|
||||
- The return values of the `ERC1155TokenReceiver` hook functions that are called MUST be respected if they are implemented.
|
||||
- Only non-standard transfer functions MAY allow tokens to be sent to a recipient contract that does NOT implement the necessary `ERC1155TokenReceiver` hook functions. `safeTransferFrom` and `safeBatchTransferFrom` MUST revert in that case (unless it is a hybrid standards implementation see "Compatibility with other standards").
|
||||
|
||||
**_Minting/creating and burning/destroying rules:_**
|
||||
* A mint/create operation is essentially a specialized transfer and MUST follow these rules:
|
||||
- To broadcast the existence of a token ID with no initial balance, the contract SHOULD emit the `TransferSingle` event from `0x0` to `0x0`, with the token creator as `_operator`, and a `_value` of 0.
|
||||
- The "TransferSingle and TransferBatch event rules" MUST be followed as appropriate for the mint(s) (i.e. singles or batches) however the `_from` argument MUST be set to `0x0` (i.e. zero address) to flag the transfer as a mint to contract observers.
|
||||
- __NOTE:__ This includes tokens that are given an initial balance in the contract. The balance of the contract MUST also be able to be determined by events alone meaning initial contract balances (for eg. in construction) MUST emit events to reflect those balances too.
|
||||
* A burn/destroy operation is essentially a specialized transfer and MUST follow these rules:
|
||||
- The "TransferSingle and TransferBatch event rules" MUST be followed as appropriate for the burn(s) (i.e. singles or batches) however the `_to` argument MUST be set to `0x0` (i.e. zero address) to flag the transfer as a burn to contract observers.
|
||||
- When burning/destroying you do not have to actually transfer to `0x0` (that is impl specific), only the `_to` argument in the event MUST be set to `0x0` as above.
|
||||
* The total value transferred from address `0x0` minus the total value transferred to `0x0` observed via the `TransferSingle` and `TransferBatch` events MAY be used by clients and exchanges to determine the "circulating supply" for a given token ID.
|
||||
* As mentioned above mint/create and burn/destroy operations are specialized transfers and so will likely be accomplished with custom transfer functions rather than `safeTransferFrom` or `safeBatchTransferFrom`. If so the "Implementation specific transfer API rules" section would be appropriate.
|
||||
- Even in a non-safe API and/or hybrid standards case the above event rules MUST still be adhered to when minting/creating or burning/destroying.
|
||||
* A contract MAY skip calling the `ERC1155TokenReceiver` hook function(s) if the mint operation is transferring the token(s) to itself. In all other cases the `ERC1155TokenReceiver` rules MUST be followed as appropriate for the implementation (i.e. safe, custom and/or hybrid).
|
||||
|
||||
|
||||
##### A solidity example of the keccak256 generated constants for the various magic values (these MAY be used by implementation):
|
||||
|
||||
```solidity
|
||||
pragma solidity ^0.5.2;
|
||||
bytes4 constant public ERC1155_ERC165 = 0xd9b67a26; // ERC-165 identifier for the main token standard.
|
||||
bytes4 constant public ERC1155_ERC165_TOKENRECEIVER = 0x4e2312e0; // ERC-165 identifier for the `ERC1155TokenReceiver` support (i.e. `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)")) ^ bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`).
|
||||
bytes4 constant public ERC1155_ACCEPTED = 0xf23a6e61; // Return value from `onERC1155Received` call if a contract accepts receipt (i.e `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`).
|
||||
bytes4 constant public ERC1155_BATCH_ACCEPTED = 0xbc197c81; // Return value from `onERC1155BatchReceived` call if a contract accepts receipt (i.e `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`).
|
||||
```
|
||||
|
||||
#### Compatibility with other standards
|
||||
|
||||
There have been requirements during the design discussions to have this standard be compatible with existing standards when sending to contract addresses, specifically ERC-721 at time of writing.
|
||||
To cater for this scenario, there is some leeway with the revert logic should a contract not implement the `ERC1155TokenReceiver` as per "Safe Transfer Rules" section above, specifically "Scenario#3 : The receiver does not implement the necessary `ERC1155TokenReceiver` interface function(s)".
|
||||
|
||||
Hence in a hybrid ERC-1155 contract implementation an extra call MUST be made on the recipient contract and checked before any hook calls to `onERC1155Received` or `onERC1155BatchReceived` are made.
|
||||
Order of operation MUST therefore be:
|
||||
1. The implementation MUST call the function `supportsInterface(0x4e2312e0)` on the recipient contract, providing at least 10,000 gas.
|
||||
2. If the function call succeeds and the return value is the constant value `true` the implementation proceeds as a regular ERC-1155 implementation, with the call(s) to the `onERC1155Received` or `onERC1155BatchReceived` hooks and rules associated.
|
||||
3. If the function call fails or the return value is NOT the constant value `true` the implementation can assume the recipient contract is not an `ERC1155TokenReceiver` and follow its other standard's rules for transfers.
|
||||
|
||||
*__Note that a pure implementation of a single standard is recommended__* rather than a hybrid solution, but an example of a hybrid ERC-1155/ERC-721 contract is linked in the references section under implementations.
|
||||
|
||||
An important consideration is that even if the tokens are sent with another standard's rules the *__ERC-1155 transfer events MUST still be emitted.__* This is so the balances can still be determined via events alone as per ERC-1155 standard rules.
|
||||
|
||||
|
||||
### Metadata
|
||||
|
||||
The URI value allows for ID substitution by clients. If the string `{id}` exists in any URI, clients MUST replace this with the actual token ID in hexadecimal form. This allows for a large number of tokens to use the same on-chain string by defining a URI once, for that large number of tokens.
|
||||
|
||||
* The string format of the substituted hexadecimal ID MUST be lowercase alphanumeric: `[0-9a-f]` with no 0x prefix.
|
||||
* The string format of the substituted hexadecimal ID MUST be leading zero padded to 64 hex characters length if necessary.
|
||||
|
||||
Example of such a URI: `https://token-cdn-domain/{id}.json` would be replaced with `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json` if the client is referring to token ID 314592/0x4CCE0.
|
||||
|
||||
#### Metadata Extensions
|
||||
|
||||
The optional `ERC1155Metadata_URI` extension can be identified with the (ERC-165 Standard Interface Detection)[https://eips.ethereum.org/EIPS/eip-165].
|
||||
|
||||
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.
|
||||
* _Changes_ to the URI MUST emit the `URI` event if the change can be expressed with an event (i.e. it isn't dynamic/programmatic).
|
||||
- An implementation MAY emit the `URI` event during a mint operation but it is NOT mandatory. An observer MAY fetch the metadata uri at mint time from the `uri` function if it was not emitted.
|
||||
* The `uri` function SHOULD be used to retrieve values if no event was emitted.
|
||||
* The `uri` function MUST return the same value as the latest event for an `_id` if it was emitted.
|
||||
* The `uri` function MUST NOT be used to check for the existence of a token as it is possible for an implementation to return a valid string even if the token does not exist.
|
||||
|
||||
```solidity
|
||||
pragma solidity ^0.5.9;
|
||||
|
||||
/**
|
||||
Note: The ERC-165 identifier for this interface is 0x0e89341c.
|
||||
|
@ -204,18 +435,19 @@ interface ERC1155Metadata_URI {
|
|||
/**
|
||||
@notice A distinct Uniform Resource Identifier (URI) for a given token.
|
||||
@dev URIs are defined in RFC 3986.
|
||||
The URI may point to a JSON file that conforms to the "ERC-1155 Metadata JSON Schema".
|
||||
The URI MUST point to a JSON file that conforms to the "ERC-1155 Metadata URI JSON Schema".
|
||||
@return URI string
|
||||
*/
|
||||
function uri(uint256 _id) external view returns (string memory);
|
||||
}
|
||||
```
|
||||
|
||||
### ERC-1155 Metadata URI JSON Schema
|
||||
#### ERC-1155 Metadata URI JSON Schema
|
||||
|
||||
This JSON schema is loosely based on the "ERC721 Metadata JSON Schema", but includes optional formatting to allow for ID substitution by clients. If the string `%s` exists in any JSON value, it MUST be replaced with the actual token ID, by all client software that follows this standard.
|
||||
This JSON schema is loosely based on the "ERC721 Metadata JSON Schema", but includes optional formatting to allow for ID substitution by clients. If the string `{id}` exists in any JSON value, it MUST be replaced with the actual token ID, by all client software that follows this standard.
|
||||
|
||||
The string format of the substituted hexadecimal ID MUST be lowercase alphanumeric: `[0-9a-f]` with no 0x prefix.
|
||||
* The string format of the substituted hexadecimal ID MUST be lowercase alphanumeric: `[0-9a-f]` with no 0x prefix.
|
||||
* The string format of the substituted hexadecimal ID MUST be leading zero padded to 64 hex characters length if necessary.
|
||||
|
||||
```json
|
||||
{
|
||||
|
@ -252,7 +484,7 @@ An example of an ERC-1155 Metadata JSON file follows. The properties array propo
|
|||
{
|
||||
"name": "Asset Name",
|
||||
"description": "Lorem ipsum...",
|
||||
"image": "https:\/\/s3.amazonaws.com\/your-bucket\/images\/%s.png",
|
||||
"image": "https:\/\/s3.amazonaws.com\/your-bucket\/images\/{id}.png",
|
||||
"properties": {
|
||||
"simple_property": "example value",
|
||||
"rich_property": {
|
||||
|
@ -275,136 +507,205 @@ An example of an ERC-1155 Metadata JSON file follows. The properties array propo
|
|||
}
|
||||
```
|
||||
|
||||
##### Localization
|
||||
|
||||
Metadata localization should be standardized to increase presentation uniformity across all languages. As such, a simple overlay method is proposed to enable localization. If the metadata JSON file contains a `localization` attribute, its content MAY be used to provide localized values for fields that need it. The `localization` attribute should be a sub-object with three attributes: `uri`, `default` and `locales`. If the string `{locale}` exists in any URI, it MUST be replaced with the chosen locale by all client software.
|
||||
|
||||
##### JSON Schema
|
||||
|
||||
```json
|
||||
{
|
||||
"title": "Token Metadata",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"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": {
|
||||
"type": "string",
|
||||
"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.",
|
||||
},
|
||||
"properties": {
|
||||
"type": "object",
|
||||
"description": "Arbitrary properties. Values may be strings, numbers, object or arrays.",
|
||||
},
|
||||
"localization": {
|
||||
"type": "object",
|
||||
"required": ["uri", "default", "locales"],
|
||||
"properties": {
|
||||
"uri": {
|
||||
"type": "string",
|
||||
"description": "The URI pattern to fetch localized data from. This URI should contain the substring `{locale}` which will be replaced with the appropriate locale value before sending the request."
|
||||
},
|
||||
"default": {
|
||||
"type": "string",
|
||||
"description": "The locale of the default data within the base JSON"
|
||||
},
|
||||
"locales": {
|
||||
"type": "array",
|
||||
"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/)."
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
##### Localized Sample
|
||||
|
||||
Base URI:
|
||||
```json
|
||||
{
|
||||
"name": "Advertising Space",
|
||||
"description": "Each token represents a unique Ad space in the city.",
|
||||
"localization": {
|
||||
"uri": "ipfs://QmWS1VAdMD353A6SDk9wNyvkT14kyCiZrNDYAad4w1tKqT/{locale}.json",
|
||||
"default": "en",
|
||||
"locales": ["en", "es", "fr"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
es.json:
|
||||
```json
|
||||
{
|
||||
"name": "Espacio Publicitario",
|
||||
"description": "Cada token representa un espacio publicitario único en la ciudad."
|
||||
}
|
||||
```
|
||||
|
||||
fr.json:
|
||||
```json
|
||||
{
|
||||
"name": "Espace Publicitaire",
|
||||
"description": "Chaque jeton représente un espace publicitaire unique dans la ville."
|
||||
}
|
||||
```
|
||||
|
||||
### 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 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.
|
||||
|
||||
## Rationale
|
||||
|
||||
<details>
|
||||
<summary>
|
||||
Metadata Choices</summary>
|
||||
### Metadata Choices
|
||||
|
||||
The `symbol` function (found in the ERC-20 and ERC-721 standards) was not included as we do not believe this is a globally useful piece of data to identify a generic virtual item / asset and are also prone to collisions. Short-hand symbols are used in tickers and currency trading, but they aren't as useful outside of that space.
|
||||
|
||||
The `name` function (for human-readable asset names, on-chain) was removed from the standard to allow the Metadata JSON to be the definitive asset name and reduce duplication of data. This also allows localization for names, which would otherwise be prohibitively expensive if each language string was stored on-chain, not to mention bloating the standard interface. While this decision may add a small burden on implementers to host a JSON file containing metadata, we believe any serious implementation of ERC-1155 will already utilize JSON Metadata.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>
|
||||
Upgrades</summary>
|
||||
### 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 ERC-1538. This will also have the added benefit of providing a stable contract address for users.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>
|
||||
Design decision: Supporting non-batch</summary>
|
||||
### Design decision: Supporting non-batch
|
||||
|
||||
The standard supports `safeTransferFrom` and `onERC1155Received` functions because they are significantly cheaper for single token-type transfers, which is arguably a common use case.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>
|
||||
Design decision: Safe transfers only</summary>
|
||||
### Design decision: Safe transfers only
|
||||
|
||||
The standard only supports safe-style transfers, making it possible for receiver contracts to depend on `onERC1155Received` or `onERC1155BatchReceived` function to be always called at the end of a transfer.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>
|
||||
Guaranteed log trace</summary>
|
||||
### Guaranteed log trace
|
||||
|
||||
As the Ethereum ecosystem continues to grow, many dapps are relying on traditional databases and explorer API services to retrieve and categorize data. The ERC-1155 standard guarantees that event logs emitted by the smart contract will provide enough data to create an accurate record of all current token balances. A database or explorer may listen to events and be able to provide indexed and categorized searches of every ERC-1155 token in the contract.
|
||||
|
||||
</details>
|
||||
### Approval
|
||||
|
||||
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://github.com/ethereum/EIPs/issues/1761) which is compatible with ERC-1155.
|
||||
|
||||
## Usage
|
||||
|
||||
This standard can be used to represent multiple token types for an entire domain. Both Fungible and Non-Fungible tokens can be stored in the same smart-contract.
|
||||
|
||||
<details>
|
||||
<summary>
|
||||
Batch Operations</summary>
|
||||
This standard can be used to represent multiple token types for an entire domain. Both fungible and non-fungible tokens can be stored in the same smart-contract.
|
||||
|
||||
### Batch Transfers
|
||||
|
||||
The `safeBatchTransferFrom` function allows for batch transfers of multiple token ids and values. The design of ERC-1155 makes batch transfers possible without the need for a wrapper contract, as with existing token standards. This reduces gas costs when more than one token type is included in a batch transfer, as compared to single transfers with multiple transactions.
|
||||
The `safeBatchTransferFrom` function allows for batch transfers of multiple token IDs and values. The design of ERC-1155 makes batch transfers possible without the need for a wrapper contract, as with existing token standards. This reduces gas costs when more than one token type is included in a batch transfer, as compared to single transfers with multiple transactions.
|
||||
|
||||
Another advantage of standardized batch transfers is the ability for a smart contract to respond to the batch transfer in a single operation using `onERC1155BatchReceived`.
|
||||
|
||||
It is RECOMMENDED that clients and wallets sort the token IDs and associated values (in ascending order) when posting a batch transfer, as some ERC-1155 implementations offer significant gas cost savings when IDs are sorted. See [Horizon Games - Multi-Token Standard](https://github.com/horizon-games/multi-token-standard) "packed balance" implementation for an example of this.
|
||||
|
||||
### Batch Balance
|
||||
|
||||
The `balanceOfBatch` function allows clients to retrieve balances of multiple owners and token ids with a single call.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>
|
||||
Approval</summary>
|
||||
|
||||
### Approval
|
||||
|
||||
The function `setApprovalForAll` allows an operator to manage one's entire set of tokens on behalf of the approver. Single-token based approval of specific token values is not part of the standard. To scope an approval to a specific set or quantity of tokens, we recommend deploying a contract that contains the desired rules, and directing end-users to approve this contract to manage their set of tokens.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>
|
||||
Enumeration</summary>
|
||||
The `balanceOfBatch` function allows clients to retrieve balances of multiple owners and token IDs with a single call.
|
||||
|
||||
### Enumerating from events
|
||||
|
||||
In order to keep storage requirements light for contracts implementing ERC-1155, enumeration (discovering the IDs and values of tokens) must be done using event logs. It is RECOMMENDED that clients such as exchanges and blockchain explorers maintain a local database containing the Token ID, Supply, and URI at the minimum. This can be built from each TransferSingle, TransferBatch, and URI event, starting from the block the smart contract was deployed until the latest block.
|
||||
In order to keep storage requirements light for contracts implementing ERC-1155, enumeration (discovering the IDs and values of tokens) must be done using event logs. It is RECOMMENDED that clients such as exchanges and blockchain explorers maintain a local database containing the token ID, Supply, and URI at the minimum. This can be built from each TransferSingle, TransferBatch, and URI event, starting from the block the smart contract was deployed until the latest block.
|
||||
|
||||
ERC-1155 contracts must therefore carefully emit TransferSingle or TransferBatch events in any instance where tokens are created, minted, or destroyed.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>
|
||||
Non-Fungible Tokens</summary>
|
||||
ERC-1155 contracts must therefore carefully emit `TransferSingle` or `TransferBatch` events in any instance where tokens are created, minted, transferred or destroyed.
|
||||
|
||||
### Non-Fungible Tokens
|
||||
|
||||
The following strategy is an example of how to mix fungible and non-fungible tokens together in the same contract. The top 128 bits of the uint256 `_id` parameter in any ERC-1155 function could represent the base token ID, while the bottom 128 bits might be used for any extra data passed to the contract.
|
||||
The following strategies are examples of how you MAY mix fungible and non-fungible tokens together in the same contract. The standard does NOT mandate how an implementation must do this.
|
||||
|
||||
Non-Fungible tokens can be interacted with using an index based accessor into the contract/token data set. Therefore to access a particular token set within a mixed data contract and particular NFT within that set, `_id` could be passed as `<uint128: base token id><uint128: index of NFT>`.
|
||||
##### Split ID bits
|
||||
|
||||
Inside the contract code the two pieces of data needed to access the individual NFT can be extracted with uint128(~0) and the same mask shifted by 128.
|
||||
The top 128 bits of the uint256 `_id` parameter in any ERC-1155 function MAY represent the base token ID, while the bottom 128 bits MAY represent the index of the non-fungible to make it unique.
|
||||
|
||||
### Example of split ID bits
|
||||
Non-fungible tokens can be interacted with using an index based accessor into the contract/token data set. Therefore to access a particular token set within a mixed data contract and a particular non-fungible within that set, `_id` could be passed as `<uint128: base token id><uint128: index of non-fungible>`.
|
||||
|
||||
To identify a non-fungible set/category as a whole (or a fungible) you COULD just pass in the base id via the `_id` argument as `<uint128: base token id><uint128: zero>`. If your implementation uses this technique this naturally means the index of a non-fungible SHOULD be 1-based.
|
||||
|
||||
Inside the contract code the two pieces of data needed to access the individual non-fungible can be extracted with uint128(~0) and the same mask shifted by 128.
|
||||
|
||||
```solidity
|
||||
uint256 baseToken = 12345 << 128;
|
||||
uint128 index = 50;
|
||||
uint256 baseTokenNFT = 12345 << 128;
|
||||
uint128 indexNFT = 50;
|
||||
|
||||
balanceOf(baseToken, msg.sender); // Get balance of the base token
|
||||
balanceOf(baseToken + index, msg.sender); // Get balance of the Non-Fungible token index
|
||||
uint256 baseTokenFT = 54321 << 128;
|
||||
|
||||
balanceOf(baseTokenNFT, msg.sender); // Get balance of the base token for non-fungible set 12345 (this MAY be used to get balance of the user for all of this token set if the implementation wishes as a convenience).
|
||||
balanceOf(baseTokenNFT + indexNFT, msg.sender); // Get balance of the token at index 50 for non-fungible set 12345 (should be 1 if user owns the individual non-fungible token or 0 if they do not).
|
||||
balanceOf(baseTokenFT, msg.sender); // Get balance of the fungible base token 54321.
|
||||
```
|
||||
|
||||
</details>
|
||||
Note that 128 is an arbitrary number, an implementation MAY choose how they would like this split to occur as suitable for their use case. An observer of the contract would simply see events showing balance transfers and mints happening and MAY track the balances using that information alone.
|
||||
For an observer to be able to determine type (non-fungible or fungible) from an ID alone they would have to know the split ID bits format on a implementation by implementation basis.
|
||||
|
||||
The [ERC-1155 Reference Implementation](https://github.com/enjin/erc-1155) is an example of the split ID bits strategy.
|
||||
|
||||
##### Natural Non-Fungible tokens
|
||||
|
||||
Another simple way to represent non-fungibles is to allow a maximum value of 1 for each non-fungible token. This would naturally mirror the real world, where unique items have a quantity of 1 and fungible items have a quantity greater than 1.
|
||||
|
||||
## References
|
||||
|
||||
**Standards**
|
||||
- [ERC-721 Non-Fungible Token Standard](https://raw.githubusercontent.com/ethereum/EIPs/master/EIPS/eip-721.md)
|
||||
- [ERC-165 Standard Interface Detection](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md)
|
||||
- [ERC-1538 Transparent Contract Standard](https://github.com/ethereum/EIPs/issues/1538)
|
||||
- [JSON Schema](http://json-schema.org/)
|
||||
- [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)
|
||||
- [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)
|
||||
|
||||
**Implementations**
|
||||
- [ERC-1155 Reference Implementation](https://github.com/enjin/erc-1155)
|
||||
- [Horizon Games - Multi-Token Standard](https://github.com/horizon-games/multi-token-standard)
|
||||
- [Enjin Coin](https://enjincoin.io) ([github](https://github.com/enjin))
|
||||
- [Enjin Coin](https://enjincoin.io) ([GitHub](https://github.com/enjin))
|
||||
- [The Sandbox - Dual ERC-1155/721 Contract](https://github.com/pixowl/thesandbox-contracts/tree/master/src/Asset)
|
||||
|
||||
**Articles & Discussions**
|
||||
- [Github - Original Discussion Thread](https://github.com/ethereum/EIPs/issues/1155)
|
||||
- [GitHub - Original Discussion Thread](https://github.com/ethereum/EIPs/issues/1155)
|
||||
- [ERC-1155 - The Crypto Item Standard](https://blog.enjincoin.io/erc-1155-the-crypto-item-standard-ac9cf1c5a226)
|
||||
- [Here Be Dragons - Going Beyond ERC-20 and ERC-721 To Reduce Gas Cost by ~80%](https://medium.com/horizongames/going-beyond-erc20-and-erc721-9acebd4ff6ef)
|
||||
- [Blockonomi - Ethereum ERC-1155 Token Perfect for Online Games, Possibly More](https://blockonomi.com/erc1155-gaming-token/)
|
||||
- [Beyond Gaming - Exploring the Utility of ERC-1155 Token Standard!](https://blockgeeks.com/erc-1155-token/)
|
||||
- [ERC-1155: A new standard for The Sandbox](https://medium.com/sandbox-game/erc-1155-a-new-standard-for-the-sandbox-c95ee1e45072)
|
||||
|
||||
## Copyright
|
||||
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
|
||||
|
|
|
@ -7,6 +7,7 @@ status: Final
|
|||
type: Standards Track
|
||||
category: ERC
|
||||
created: 2018-06-22
|
||||
requires: 211
|
||||
---
|
||||
|
||||
<!--You can leave these HTML comments in your merged EIP and delete the visible duplicate text guides, they will not appear and may be helpful to refer to if you edit it again. This is the suggested template for new EIPs. Note that an EIP number will be assigned by an editor. When opening a pull request to submit your EIP, please use an abbreviated title in the filename, `eip-draft_title_abbrev.md`. The title should be 44 characters or less.-->
|
||||
|
@ -21,11 +22,11 @@ By standardizing on a known minimal bytecode redirect implementation, this stand
|
|||
|
||||
## 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.-->
|
||||
This standard supports use-cases wherein it is desireable to clone exact contract functionality with a minimum of side effects (e.g. memory slot stomping) and with low gas cost deployment of duplicate proxies.
|
||||
This standard supports use-cases wherein it is desirable to clone exact contract functionality with a minimum of side effects (e.g. memory slot stomping) and with low gas cost deployment of duplicate proxies.
|
||||
|
||||
## 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)).-->
|
||||
The exact bytecode of the standard clone contract is this: `363d3d373d3d3d363d73bebebebebebebebebebebebebebebebebebebebe5af43d82803e903d91602b57fd5bf3` wherein the bytes at idices 10 - 29 (inclusive) are replaced with the 20 byte address of the master functionality contract.
|
||||
The exact bytecode of the standard clone contract is this: `363d3d373d3d3d363d73bebebebebebebebebebebebebebebebebebebebe5af43d82803e903d91602b57fd5bf3` wherein the bytes at indices 10 - 29 (inclusive) are replaced with the 20 byte address of the master functionality contract.
|
||||
|
||||
A reference implementation of this can be found at the [optionality/clone-factory](https://github.com/optionality/clone-factory) github repo.
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ status: Draft
|
|||
type: Standards Track
|
||||
category: Interface
|
||||
created: 2018-06-24
|
||||
requires: 1474
|
||||
---
|
||||
|
||||
<!--You can leave these HTML comments in your merged EIP and delete the visible duplicate text guides, they will not appear and may be helpful to refer to if you edit it again. This is the suggested template for new EIPs. Note that an EIP number will be assigned by an editor. When opening a pull request to submit your EIP, please use an abbreviated title in the filename, `eip-draft_title_abbrev.md`. The title should be 44 characters or less.-->
|
||||
|
@ -124,7 +125,7 @@ This one Method actually returns 3 different important data points:
|
|||
|
||||
Combining these in one Method allows the client to work very efficient since the required data are already fetched from the db.
|
||||
|
||||
### Proofs for non existant values
|
||||
### Proofs for non existent values
|
||||
|
||||
In case an address or storage-value does not exist, the proof needs to provide enough data to verify this fact. This means the client needs to follow the path from the root node and deliver until the last matching node. If the last matching node is a branch, the proof value in the node must be an empty one. In case of leaf-type, it must be pointing to a different relative-path in order to proof that the requested path does not exist.
|
||||
|
||||
|
@ -141,7 +142,7 @@ Since this only adds a new Method there are no issues with Backwards Compatibili
|
|||
## 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.-->
|
||||
|
||||
<TODO>Tests still need to be implemented, but the core function creating the proof already exists inside the clients and are well tested.
|
||||
TODO: Tests still need to be implemented, but the core function creating the proof already exists inside the clients and are well tested.
|
||||
|
||||
## 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.-->
|
||||
|
|
104
EIPS/eip-1191.md
104
EIPS/eip-1191.md
|
@ -2,22 +2,31 @@
|
|||
eip: 1191
|
||||
title: Add chain id to mixed-case checksum address encoding
|
||||
author: Juliano Rizzo (@juli)
|
||||
status: Draft
|
||||
status: Last Call
|
||||
review-period-end: 2019-11-18
|
||||
type: Standards Track
|
||||
category: ERC
|
||||
created: 2018-03-18
|
||||
requires: 55, 155
|
||||
discussions-to: https://github.com/ethereum/EIPs/issues/1121
|
||||
---
|
||||
|
||||
## Simple Summary
|
||||
This EIP extends EIP-55 by optionally adding a chain id defined by EIP-155 to the checksum calculation.
|
||||
|
||||
## Abstract
|
||||
The EIP-55 was created to prevent users from losing funds by sending them to invalid addresses. This EIP extends EIP-55 to protect users from losing funds by sending them to addresses that are valid but that where obtained from a client of another network.For example, if this EIP is implemented, a wallet can alert the user that is trying to send funds to an Ethereum Testnet address from an Ethereum Mainnet wallet.
|
||||
|
||||
## Motivation
|
||||
The motivation of this proposal is to provide a mechanism to allow software to distinguish addresses from different Ethereum based networks. This proposal is necessary because Ethereum addresses are hashes of public keys and do not include any metadata. By extending the EIP-55 checksum algorithm it is possible to achieve this objective.
|
||||
|
||||
## Specification
|
||||
Convert the address using the same algorithm defined by EIP-55 but if a registered chain id is provided, add it to the input of the hash function. If the chain id passed to the function belongs to a network that opted for using this checksum variant, prefix the address with the chain id and the `0x` separator before calculating the hash. Then convert the address to hexadecimal, but if the ith digit is a letter (ie. it's one of `abcdef`) print it in uppercase if the 4*ith bit of the calculated hash is 1 otherwise print it in lowercase.
|
||||
|
||||
## Rationale
|
||||
Benefits:
|
||||
- By means of a minimal code change on existing libraries, users are protected from losing funds by mixing addresses of different Ethereum based networks.
|
||||
|
||||
## Backwards Compatibility
|
||||
This proposal is fully backward compatible. The checksum calculation is changed only for new networks that choose to adopt this EIP and add their chain numbers to the Adoption Table included in this document.
|
||||
|
||||
|
@ -37,43 +46,53 @@ def eth_checksum_encode(addr, chainid=1):
|
|||
out = addr[:2] + ''.join([c.upper() if int(a,16) >= 8 else c for c,a in aggregate])
|
||||
return out
|
||||
```
|
||||
|
||||
## Test Cases
|
||||
```python
|
||||
eth_mainnet = [
|
||||
'0x88021160C5C792225E4E5452585947470010289D',
|
||||
'0x27b1fdb04752bbc536007a920d24acb045561c26',
|
||||
'0x52908400098527886E0F7030069857D2E4169EE7',
|
||||
'0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed',
|
||||
'0x8617E340B3D01FA5F11F306F4090FD50E238070D',
|
||||
'0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb',
|
||||
'0xdbF03B407c01E7cD3CBea99509d93f8DDDC8C6FB',
|
||||
'0xde709f2102306220921060314715629080e2fb77',
|
||||
'0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359',
|
||||
"0x27b1fdb04752bbc536007a920d24acb045561c26",
|
||||
"0x3599689E6292b81B2d85451025146515070129Bb",
|
||||
"0x42712D45473476b98452f434e72461577D686318",
|
||||
"0x52908400098527886E0F7030069857D2E4169EE7",
|
||||
"0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed",
|
||||
"0x6549f4939460DE12611948b3f82b88C3C8975323",
|
||||
"0x66f9664f97F2b50F62D13eA064982f936dE76657",
|
||||
"0x8617E340B3D01FA5F11F306F4090FD50E238070D",
|
||||
"0x88021160C5C792225E4E5452585947470010289D",
|
||||
"0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb",
|
||||
"0xdbF03B407c01E7cD3CBea99509d93f8DDDC8C6FB",
|
||||
"0xde709f2102306220921060314715629080e2fb77",
|
||||
"0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359",
|
||||
]
|
||||
rsk_mainnet = [
|
||||
'0x6549F4939460DE12611948B3F82B88C3C8975323',
|
||||
'0x27b1FdB04752BBc536007A920D24ACB045561c26',
|
||||
'0x3599689E6292B81B2D85451025146515070129Bb',
|
||||
'0x52908400098527886E0F7030069857D2E4169ee7',
|
||||
'0x5aaEB6053f3e94c9b9a09f33669435E7ef1bEAeD',
|
||||
'0x8617E340b3D01Fa5f11f306f4090fd50E238070D',
|
||||
'0xD1220A0Cf47c7B9BE7a2e6ba89F429762E7B9adB',
|
||||
'0xDBF03B407c01E7CD3cBea99509D93F8Dddc8C6FB',
|
||||
'0xDe709F2102306220921060314715629080e2FB77',
|
||||
'0xFb6916095cA1Df60bb79ce92cE3EA74c37c5d359',
|
||||
"0x27b1FdB04752BBc536007A920D24ACB045561c26",
|
||||
"0x3599689E6292B81B2D85451025146515070129Bb",
|
||||
"0x42712D45473476B98452f434E72461577d686318",
|
||||
"0x52908400098527886E0F7030069857D2E4169ee7",
|
||||
"0x5aaEB6053f3e94c9b9a09f33669435E7ef1bEAeD",
|
||||
"0x6549F4939460DE12611948B3F82B88C3C8975323",
|
||||
"0x66F9664f97f2B50F62d13EA064982F936de76657",
|
||||
"0x8617E340b3D01Fa5f11f306f4090fd50E238070D",
|
||||
"0x88021160c5C792225E4E5452585947470010289d",
|
||||
"0xD1220A0Cf47c7B9BE7a2e6ba89F429762E7B9adB",
|
||||
"0xDBF03B407c01E7CD3cBea99509D93F8Dddc8C6FB",
|
||||
"0xDe709F2102306220921060314715629080e2FB77",
|
||||
"0xFb6916095cA1Df60bb79ce92cE3EA74c37c5d359",
|
||||
]
|
||||
rsk_testnet = [
|
||||
'0x42712D45473476B98452F434E72461577D686318',
|
||||
'0x27B1FdB04752BbC536007a920D24acB045561C26',
|
||||
'0x3599689e6292b81b2D85451025146515070129Bb',
|
||||
'0x52908400098527886E0F7030069857D2e4169EE7',
|
||||
'0x5aAeb6053F3e94c9b9A09F33669435E7EF1BEaEd',
|
||||
'0x66f9664F97F2b50f62d13eA064982F936DE76657',
|
||||
'0x8617e340b3D01fa5F11f306F4090Fd50e238070d',
|
||||
'0xDE709F2102306220921060314715629080e2Fb77',
|
||||
'0xFb6916095CA1dF60bb79CE92ce3Ea74C37c5D359',
|
||||
'0xd1220a0CF47c7B9Be7A2E6Ba89f429762E7b9adB',
|
||||
'0xdbF03B407C01E7cd3cbEa99509D93f8dDDc8C6fB',
|
||||
"0x27B1FdB04752BbC536007a920D24acB045561C26",
|
||||
"0x3599689e6292b81b2D85451025146515070129Bb",
|
||||
"0x42712D45473476B98452F434E72461577D686318",
|
||||
"0x52908400098527886E0F7030069857D2e4169EE7",
|
||||
"0x5aAeb6053F3e94c9b9A09F33669435E7EF1BEaEd",
|
||||
"0x6549f4939460dE12611948b3f82b88C3c8975323",
|
||||
"0x66f9664F97F2b50f62d13eA064982F936DE76657",
|
||||
"0x8617e340b3D01fa5F11f306F4090Fd50e238070d",
|
||||
"0x88021160c5C792225E4E5452585947470010289d",
|
||||
"0xd1220a0CF47c7B9Be7A2E6Ba89f429762E7b9adB",
|
||||
"0xdbF03B407C01E7cd3cbEa99509D93f8dDDc8C6fB",
|
||||
"0xDE709F2102306220921060314715629080e2Fb77",
|
||||
"0xFb6916095CA1dF60bb79CE92ce3Ea74C37c5D359",
|
||||
]
|
||||
test_cases = {30 : rsk_mainnet, 31 : rsk_testnet, 1 : eth_mainnet}
|
||||
|
||||
|
@ -82,16 +101,27 @@ for chainid, cases in test_cases.items():
|
|||
assert ( addr == eth_checksum_encode(addr,chainid) )
|
||||
```
|
||||
## Adoption
|
||||
|
||||
### Adoption Table
|
||||
|
||||
| Network | Chain id | Supports this EIP |
|
||||
|--------------|----------|-------------------|
|
||||
|-|-|-|
|
||||
| RSK Mainnet | 30 | Yes |
|
||||
| RSK Testnet | 31 | Yes |
|
||||
|
||||
### Implementation Table
|
||||
|
||||
| Wallet | Implements this EIP|
|
||||
|--------------|--------------------|
|
||||
| MyCrypto | In progress |
|
||||
| Ledger | In progress |
|
||||
| Trezor | In progress |
|
||||
| Project | Adopted this EIP | Implementation |
|
||||
|-|-|-|
|
||||
| MyCrypto | Yes | [JavaScript](https://github.com/MyCryptoHQ/MyCrypto/blob/develop/common/utils/formatters.ts#L126) |
|
||||
| MyEtherWallet | Yes | [JavaScript](https://github.com/MyEtherWallet/MyEtherWallet/blob/73c4a24f8f67c655749ac990c5b62efd92a2b11a/src/helpers/addressUtils.js#L22) |
|
||||
| Ledger | Yes | [C](https://github.com/LedgerHQ/ledger-app-eth/blob/master/src_common/ethUtils.c#L203) |
|
||||
| Trezor | Yes | [Python](https://github.com/trezor/trezor-core/blob/270bf732121d004a4cd1ab129adaccf7346ff1db/src/apps/ethereum/get_address.py#L32) and [C](https://github.com/trezor/trezor-crypto/blob/4153e662b60a0d83c1be15150f18483a37e9092c/address.c#L62) |
|
||||
| Web3.js | Yes | [JavaScript](https://github.com/ethereum/web3.js/blob/aaf26c8806bc9fb60cf6dcb6658104963c6c7fc7/packages/web3-utils/src/Utils.js#L140) |
|
||||
| EthereumJS-util | Yes | [JavaScript](https://github.com/ethereumjs/ethereumjs-util/pull/204/commits/cdf0b3c996b05ac5b1f758f17ea9f9ed1847c1eb) |
|
||||
| ENS address-encoder | Yes | [TypeScript](https://github.com/ensdomains/address-encoder/commit/5bf53b13fa014646ea28c9e5f937361dc9b40590) |
|
||||
|
||||
## Copyright
|
||||
|
||||
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
|
||||
|
||||
|
|
136
EIPS/eip-1193.md
136
EIPS/eip-1193.md
|
@ -1,22 +1,18 @@
|
|||
---
|
||||
eip: 1193
|
||||
title: Ethereum Provider JavaScript API
|
||||
author: Ryan Ghods (@ryanio), Marc Garreau (@marcgarreau), Fabian Vogelsteller (@frozeman), Victor Maia (@MaiaVictor)
|
||||
author: Fabian Vogelsteller (@frozeman), Ryan Ghods (@ryanio), Marc Garreau (@marcgarreau), Victor Maia (@MaiaVictor)
|
||||
discussions-to: https://ethereum-magicians.org/t/eip-1193-ethereum-provider-javascript-api/640
|
||||
status: Draft
|
||||
type: Standards Track
|
||||
category: Interface
|
||||
created: 2018-06-30
|
||||
requires: 1102
|
||||
requires: 155, 695, 1102, 1474
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
This EIP formalizes an Ethereum Provider JavaScript API for consistency across clients and applications.
|
||||
|
||||
The provider is designed to be minimal containing 2 methods: `send` and `on`. It emits 5 types of events: `notification`, `connect`, `close`, `networkChanged`, and `accountsChanged`.
|
||||
|
||||
It is intended to be available on `window.ethereum`.
|
||||
This EIP formalizes an Ethereum Provider JavaScript API for consistency across clients and applications. The provider is designed to be minimal and is intended to be available on `window.ethereum` for cross environment compatibility.
|
||||
|
||||
## API
|
||||
|
||||
|
@ -32,27 +28,19 @@ Promise resolves with `result` or rejects with `Error`.
|
|||
|
||||
See the [available methods](https://github.com/ethereum/wiki/wiki/JSON-RPC#json-rpc-methods).
|
||||
|
||||
#### eth_requestAccounts
|
||||
|
||||
By default, the provider supplied to a new dapp has is a "read-only" provider with no accounts authenticated.
|
||||
|
||||
To request accounts, call `ethereum.send('eth_requestAccounts')`. This will ask the user which account(s) they would like to authenticate to the dapp.
|
||||
|
||||
Promise resolves with an array of the account(s) addresses.
|
||||
|
||||
### Events
|
||||
|
||||
Events are emitted using [EventEmitter](https://nodejs.org/api/events.html).
|
||||
|
||||
#### notification
|
||||
|
||||
All subscriptions from the node emit on `notification`. Attach listeners with:
|
||||
All subscriptions from the node emit on notification. Attach listeners with:
|
||||
|
||||
```js
|
||||
ethereum.on('notification', listener: (result: any) => void): this;
|
||||
```
|
||||
|
||||
To create a subscription, call `ethereum.send('eth_subscribe')` or `ethereum.send('shh_subscribe')`. The subscription `result` object will emit through `notification`.
|
||||
To create a subscription, call `ethereum.send('eth_subscribe', [])` or `ethereum.send('shh_subscribe', [])`.
|
||||
|
||||
See the [eth subscription methods](https://github.com/ethereum/go-ethereum/wiki/RPC-PUB-SUB#supported-subscriptions) and [shh subscription methods](https://github.com/ethereum/go-ethereum/wiki/Whisper-v6-RPC-API#shh_subscribe).
|
||||
|
||||
|
@ -81,6 +69,16 @@ ethereum.on('close', listener: (code: Number, reason: String) => void): this;
|
|||
|
||||
The event emits with `code` and `reason`. The code follows the table of [`CloseEvent` status codes](https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent#Status_codes).
|
||||
|
||||
#### chainChanged
|
||||
|
||||
The provider emits `chainChanged` on connect to a new chain.
|
||||
|
||||
```js
|
||||
ethereum.on('chainChanged', listener: (chainId: String) => void): this;
|
||||
```
|
||||
|
||||
The event emits with `chainId`, the new chain returned from `eth_chainId`.
|
||||
|
||||
#### networkChanged
|
||||
|
||||
The provider emits `networkChanged` on connect to a new network.
|
||||
|
@ -101,22 +99,17 @@ ethereum.on('accountsChanged', listener: (accounts: Array<String>) => void): thi
|
|||
|
||||
The event emits with `accounts`, an array of the accounts' addresses.
|
||||
|
||||
### Constructor
|
||||
|
||||
```js
|
||||
ethereum.constructor.name;
|
||||
> 'EthereumProvider'
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
```js
|
||||
const ethereum = window.ethereum;
|
||||
|
||||
// A) Primary use case - set provider in web3.js
|
||||
web3.setProvider(ethereum);
|
||||
// A) Set provider in web3.js
|
||||
var web3 = new Web3(ethereum);
|
||||
// web3.eth.getBlock('latest', true).then(...)
|
||||
|
||||
// B) Secondary use case - use provider object directly
|
||||
|
||||
// B) Use provider object directly
|
||||
// Example 1: Log last block
|
||||
ethereum
|
||||
.send('eth_getBlockByNumber', ['latest', 'true'])
|
||||
|
@ -130,24 +123,7 @@ ethereum
|
|||
);
|
||||
});
|
||||
|
||||
// Example 2: Request accounts
|
||||
ethereum
|
||||
.send('eth_requestAccounts')
|
||||
.then(accounts => {
|
||||
if (accounts.length > 0) {
|
||||
console.log(`Accounts enabled:\n${accounts.join('\n')}`);
|
||||
} else {
|
||||
console.error(`No accounts enabled.`);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error(
|
||||
`Error requesting accounts: ${error.message}.
|
||||
Code: ${error.code}. Data: ${error.data}`
|
||||
);
|
||||
});
|
||||
|
||||
// Example 3: Log available accounts
|
||||
// Example 2: Log available accounts
|
||||
ethereum
|
||||
.send('eth_accounts')
|
||||
.then(accounts => {
|
||||
|
@ -160,7 +136,8 @@ ethereum
|
|||
);
|
||||
});
|
||||
|
||||
// Example 4: Log new blocks
|
||||
|
||||
// Example 3: Log new blocks
|
||||
let subId;
|
||||
ethereum
|
||||
.send('eth_subscribe', ['newHeads'])
|
||||
|
@ -187,20 +164,9 @@ ethereum
|
|||
Code: ${error.code}. Data: ${error.data}`
|
||||
);
|
||||
});
|
||||
// to unsubscribe
|
||||
ethereum
|
||||
.send('eth_unsubscribe', [subId])
|
||||
.then(result => {
|
||||
console.log(`Unsubscribed newHeads subscription ${subId}`);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error(
|
||||
`Error unsubscribing newHeads subscription: ${error.message}.
|
||||
Code: ${error.code}. Data: ${error.data}`
|
||||
);
|
||||
});
|
||||
|
||||
// Example 5: Log when accounts change
|
||||
|
||||
// Example 4: Log when accounts change
|
||||
const logAccounts = accounts => {
|
||||
console.log(`Accounts:\n${accounts.join('\n')}`);
|
||||
};
|
||||
|
@ -208,7 +174,7 @@ ethereum.on('accountsChanged', logAccounts);
|
|||
// to unsubscribe
|
||||
ethereum.removeListener('accountsChanged', logAccounts);
|
||||
|
||||
// Example 6: Log if connection ends
|
||||
// Example 5: Log if connection ends
|
||||
ethereum.on('close', (code, reason) => {
|
||||
console.log(`Ethereum provider connection closed: ${reason}. Code: ${code}`);
|
||||
});
|
||||
|
@ -216,35 +182,21 @@ ethereum.on('close', (code, reason) => {
|
|||
|
||||
## Specification
|
||||
|
||||
### Send
|
||||
### Errors
|
||||
|
||||
The `send` method **MUST** send a properly formatted [JSON-RPC request](https://www.jsonrpc.org/specification#request_object).
|
||||
|
||||
If the Ethereum JSON-RPC API returns a response object with no error, then the Promise **MUST** resolve with the `response.result` object untouched by the implementing Ethereum Provider.
|
||||
|
||||
If the Ethereum JSON-RPC API returns response object that contains an error property then the Promise **MUST** reject with an Error object containing the `response.error.message` as the Error message, `response.error.code` as a code property on the error and `response.error.data` as a data property on the error.
|
||||
If the Ethereum Provider request returns an error property then the Promise **MUST** reject with an Error object containing the `error.message` as the Error message, `error.code` as a code property on the error and `error.data` as a data property on the error.
|
||||
|
||||
If an error occurs during processing, such as an HTTP error or internal parsing error, then the Promise **MUST** reject with an `Error` object.
|
||||
|
||||
If the implementing Ethereum Provider is not talking to an external Ethereum JSON-RPC API provider then it **MUST** resolve with an object that matches the JSON-RPC API object as specified in the [Ethereum JSON-RPC documentation](https://github.com/ethereum/wiki/wiki/JSON-RPC).
|
||||
|
||||
If the JSON-RPC request requires an account that is not yet authenticated, the Promise **MUST** reject with Error code 4100.
|
||||
|
||||
#### eth_requestAccounts
|
||||
|
||||
The provider supplied to a new dapp **MUST** be a "read-only" provider: authenticating no accounts by default, returning a blank array for `eth_accounts`, and rejecting any methods that require an account with Error code `4100`.
|
||||
|
||||
If the dapp has been previously authenticated and remembered by the user, then the provider supplied on load **MAY** automatically be enabled with the previously authenticated accounts.
|
||||
|
||||
If no accounts are authenticated, the `eth_requestAccounts` method **MUST** ask the user which account(s) they would like to authenticate to the dapp. If the request has been previously granted and remembered, the `eth_requestAccounts` method **MAY** immediately return.
|
||||
|
||||
The `eth_requestAccounts` method **MUST** resolve with an array of the account(s) addresses or reject with an `Error`. If the account(s) enabled by the provider change, the `accountsChanged` event **MUST** also emit.
|
||||
If the request requires an account that is not yet authenticated, the Promise **MUST** reject with Error code 4100.
|
||||
|
||||
### Events
|
||||
|
||||
The provider **SHOULD** extend from `EventEmitter` to provide dapps flexibility in listening to events. In place of full `EventEmitter` functionality, the provider **MAY** provide as many methods as it can reasonably provide, but **MUST** provide at least `on`, `emit`, and `removeListener`.
|
||||
|
||||
#### notification
|
||||
|
||||
All subscriptions received from the node **MUST** emit the `message.params` to the eventName `notification` without modification.
|
||||
All subscriptions received from the node **MUST** emit the `subscription` property with the subscription ID and a `results` property.
|
||||
|
||||
#### connect
|
||||
|
||||
|
@ -254,6 +206,10 @@ If the network connects, the Ethereum Provider **MUST** emit an event named `con
|
|||
|
||||
If the network connection closes, the Ethereum Provider **MUST** emit an event named `close` with args `code: Number, reason: String` following the [status codes for `CloseEvent`](https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent#Status_codes).
|
||||
|
||||
#### chainChanged
|
||||
|
||||
If the chain the provider is connected to changes, the provider **MUST** emit an event named `chainChanged` with args `chainId: String` containing the ID of the new chain (using the Ethereum JSON-RPC call `eth_chainId`).
|
||||
|
||||
#### networkChanged
|
||||
|
||||
If the network the provider is connected to changes, the provider **MUST** emit an event named `networkChanged` with args `networkId: String` containing the ID of the new network (using the Ethereum JSON-RPC call `net_version`).
|
||||
|
@ -262,13 +218,9 @@ If the network the provider is connected to changes, the provider **MUST** emit
|
|||
|
||||
If the accounts connected to the Ethereum Provider change at any time, the Ethereum Provider **MUST** send an event with the name `accountsChanged` with args `accounts: Array<String>` containing the accounts' addresses.
|
||||
|
||||
### Class
|
||||
|
||||
The name of the constructor of the Ethereum Provider **MUST** be `EthereumProvider`.
|
||||
|
||||
### web3.js Backwards Compatibility
|
||||
|
||||
If the implementing Ethereum Provider would like to be compatible with `web3.js` prior to `1.0.0-beta38`, it **MUST** provide two methods: `sendAsync(payload: Object, callback: (error: any, result: any) => void): void` and `isConnected(): Boolean`.
|
||||
If the implementing Ethereum Provider would like to be compatible with `web3.js` prior to `1.0.0-beta38`, it **MUST** provide the method: `sendAsync(payload: Object, callback: (error: any, result: any) => void): void`.
|
||||
|
||||
### Error object and codes
|
||||
|
||||
|
@ -277,10 +229,9 @@ If an Error object is returned, it **MUST** contain a human readable string mess
|
|||
Appropriate error codes **SHOULD** follow the table of [`CloseEvent` status codes](https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent#Status_codes), along with the following table:
|
||||
|
||||
| Status code | Name | Description |
|
||||
| ----------- | ---------------------------- | --------------------------------------------------------------------- |
|
||||
| 4001 | User Denied Request Accounts | User denied authorizing any accounts for the dapp. |
|
||||
| 4010 | User Denied Create Account | User denied creating a new account. |
|
||||
| 4100 | Unauthorized | The requested account has not been authorized by the user. |
|
||||
| ----------- | ---------------------------- | ------------------------------------------------------------------------ |
|
||||
| 4001 | User Rejected Request | The user rejected the request. |
|
||||
| 4100 | Unauthorized | The requested method and/or account has not been authorized by the user. |
|
||||
| 4200 | Unsupported Method | The requested method is not supported by the given Ethereum Provider. |
|
||||
|
||||
## Sample Class Implementation
|
||||
|
@ -292,7 +243,6 @@ class EthereumProvider extends EventEmitter {
|
|||
super();
|
||||
|
||||
// Init storage
|
||||
this._isConnected = false;
|
||||
this._nextJsonrpcId = 0;
|
||||
this._promises = {};
|
||||
|
||||
|
@ -396,12 +346,10 @@ class EthereumProvider extends EventEmitter {
|
|||
}
|
||||
|
||||
_emitConnect() {
|
||||
this._isConnected = true;
|
||||
this.emit('connect');
|
||||
}
|
||||
|
||||
_emitClose(code, reason) {
|
||||
this._isConnected = false;
|
||||
this.emit('close', code, reason);
|
||||
}
|
||||
|
||||
|
@ -430,10 +378,6 @@ class EthereumProvider extends EventEmitter {
|
|||
);
|
||||
});
|
||||
}
|
||||
|
||||
isConnected() {
|
||||
return this._isConnected;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
|
108
EIPS/eip-1202.md
108
EIPS/eip-1202.md
|
@ -9,22 +9,6 @@ created: 2018-07-08
|
|||
discussions-to: https://github.com/ethereum/EIPs/issues/1202
|
||||
---
|
||||
|
||||
## Note to Readers
|
||||
|
||||
1. We are still open to have co-author to collaborate, in particular, we are looking for co-authors of the
|
||||
following category:
|
||||
- standard designers who are experienced in application-layer standard design, or
|
||||
- developers who have experience with blockchain-based voting system in practice
|
||||
- researchers with research interest in crypto/zero-knowledge-proof voting
|
||||
|
||||
|
||||
2. We have two discussion destinations:
|
||||
- [Github Ethereum EIP Issue #1202](https://github.com/ethereum/EIPs/issues/1202) for long and more mature thoughts
|
||||
- [Telegram Channel t.me/erc1202](https://t.me/erc1202) for real-time and related random chat.
|
||||
|
||||
3. We are actively working on updating this draft as many feedbacks have come in since it merged into official EIP repo.
|
||||
If you are viewing a snapshot of this draft, please be adviced the latest dev version of ERC 1202 can be found [here](https://github.com/xinbenlv/eip-1202-draft/blob/master/EIP-1202.md)
|
||||
|
||||
## Simple Summary
|
||||
Propose a standard interface for voting.
|
||||
|
||||
|
@ -136,18 +120,9 @@ We made the following design decisions and here are the rationales.
|
|||
|
||||
- **Weight**: We assume there are `weight` of votes and can be checked by calling `weightOf(address addr)`, and the weight distribution is either internally determined or determined by constructor. However we have not been considering updating the weight distribution. Please comment on this design decision as we want to learn how likely an implementor would want to be able to update the voting weight distributions.
|
||||
|
||||
### Security and Privacy of Voting
|
||||
// TODO
|
||||
|
||||
## Backward Compatibility
|
||||
There is no backward compatibility issue we are aware of.
|
||||
|
||||
|
||||
## Interactions with other ERCs
|
||||
// TODO add interaction discussion for the following ERCs
|
||||
ERC20, ERC721, ERC735, ERC780, ERC165
|
||||
|
||||
|
||||
## Simple Code Examples
|
||||
### Example 1: Simplest Version: Single Issue Yes/No Question Per Smart Contract Address Per Non-Weighted Vote
|
||||
|
||||
|
@ -162,57 +137,6 @@ ERC20, ERC721, ERC735, ERC780, ERC165
|
|||
- [Source Code](https://github.com/xinbenlv/eip-1202-draft/blob/master/contracts/advanced-version/AdvancedTokenVote1202.sol)
|
||||
- [Deployment (Ropsten)](https://ropsten.etherscan.io/address/0xfd8b3be5f9db4662d1c9269f948345b46e37fd26#code)
|
||||
|
||||
## Comprehensive Application Examples
|
||||
|
||||
### Example 1: Joint Wallet Account Spending Approval
|
||||
// TODO
|
||||
|
||||
### Example 2: Secret Vote
|
||||
// TODO
|
||||
|
||||
### Example 3: Token Re-issue
|
||||
// TODO
|
||||
|
||||
### Example 4: Multi-input Oracle
|
||||
// TODO
|
||||
|
||||
|
||||
## Case Study
|
||||
|
||||
### Existing Voting Systems in Blockchain World
|
||||
// TODO
|
||||
|
||||
#### Carbon Vote
|
||||
// TODO
|
||||
|
||||
#### PLACE Voting
|
||||
https://medium.com/@jameson.quinn/how-place-voting-works-617a5e8ac422
|
||||
|
||||
#### PLCR Voting
|
||||
[PLCR Voting: ](https://github.com/ConsenSys/PLCRVoting)
|
||||
https://medium.com/metax-publication/a-walkthrough-of-plcr-voting-in-solidity-92420bd5b87c
|
||||
|
||||
####
|
||||
|
||||
### Exiting Voting Systems in Real World
|
||||
// TODO
|
||||
|
||||
#### Simple Majority Vote Requiring Quorum (e.g. Company Board)
|
||||
// TODO, and a small variant: ZaiGeZaiGu function committee approval (1/2 as quorum, majority vote)
|
||||
|
||||
|
||||
#### Two-tiered Shareholder Vote (e.g. GOOG, FB)
|
||||
// TODO
|
||||
|
||||
#### Jury Decision of US Federal Criminal Court (All Ayle for Guity, 5/5 for Tie)
|
||||
// TODO
|
||||
|
||||
#### US Presidential Election: Different Vote Time, Multi-Reginal, Two-level (General and Editorial(delegate))
|
||||
// TODO
|
||||
|
||||
#### Super-Girl China 2005: Idol Ranking Vote, Multiple Votes Allowed
|
||||
// TODO
|
||||
|
||||
|
||||
## Summary of Discussions
|
||||
|
||||
|
@ -259,37 +183,11 @@ Here are a few early questions I'd like to ask people here.
|
|||
- [Paper: A Smart Contract for Boardroom Voting with Maximum Voter Privacy](https://eprint.iacr.org/2017/110.pdf) - *Suggested by @aodhgan*
|
||||
- [Private Voting for TCR](https://blog.enigma.co/private-voting-for-tcrs-with-enigma-b441b5d4fa7b)
|
||||
|
||||
### Worthnoting Academic Papers
|
||||
|
||||
|
||||
## Request for Comment
|
||||
We kindly request the community for comments, in particular, the following ERC and projects related authors:
|
||||
|
||||
- ERC-20: @frozeman, @vbuterin
|
||||
- ERC-721: @fulldecent, Dieter Shirley, Jacob Evans, Nastassia Sachs
|
||||
- Carbon Vote: @lgn21st, @Aaaaaashu
|
||||
- Alex Van de Sande (Mist) and Nick Johnson (ENS) * - suggested by Fabian (@frozeman)*
|
||||
- Will Warren, 0xProject a project who cares a lot about governance. * - nominated by Evan()@evanbots)*
|
||||
|
||||
Your comments and suggestions will be greatly appreciated.
|
||||
|
||||
## Acknowledgement
|
||||
The authors of EIP 1202 greatly appreciate the valuable input from distinguished community members including: @frozeman, @fulldecent, @bingen, @aodhgan.
|
||||
We appreciate Ansley, Andrew, Fred from Enigma, Fan and Raullen from IoTex for sharing us their use cases. we also appreciate the valuable input for designing an EIP from distinguished community members including: @frozeman, @fulldecent, @bingen, @aodhgan.
|
||||
|
||||
## EIP Work Logs
|
||||
|
||||
- 2018-07-08: (@xinbenlv) Created early feedback request. Asked around discussion channels suggested in [EIP-1](https://eips.ethereum.org/EIPS/eip-1), such as [Ethereum-Magicians](https://ethereum-magicians.org/t/eip-x-voting-standard-early-feedback-wanted/670/2), [Gitter](https://gitter.im/ethereum/EIPs), [Reddit](https://www.reddit.com/r/ethereum/comments/8x6k11/early_feedback_request_for_eipx_voting_standard/)
|
||||
- 2018-07-09: (@xinbenlv)Added examples outline. Request for co-author.
|
||||
- 2018-07-17: (@xinbenlv)Added co-author. @evbots, added two simple examples.
|
||||
- 2018-07-19: (@xinbenlv)Added interface-like specification. Moved content from [issue](https://github.com/ethereum/EIPs/issues/1202) to [xinbenlv's Github repo](https://github.com/xinbenlv/eip-1202-draft/blob/master/EIP-1202.md) . Added TokenVote example.
|
||||
- 2018-07-20: (@xinbenlv)Added advanced token vote example.
|
||||
- 2018-07-22: (@xinbenlv)Moved official discussion thread from [github issue](https://github.com/ethereum/EIPs/issues/1202) to [ethereum-magicians](https://ethereum-magicians.org/t/erc-1202-voting-standard-official-discussion-thread/670) - moved back as it's ok to use GitHub issue as official discussion thread.
|
||||
- 2018-07-23: (@xinbenlv)
|
||||
- added co-author Yin Xu (@yingogobot)
|
||||
- added outline for a few applications and case studies for further drafting.
|
||||
- added citation of ERC-735 and ERC-780
|
||||
- 2018-07-25: (@xinbenlv) Added input from @fulldecent, @bingen, @aodhgan to mention the privacy casting, PLCR etc, and
|
||||
added placeholders for related session.
|
||||
## Work Directory
|
||||
The drafting and revision of EIP-1202 is conducted at [GitHub/xinbenlv/eip-1202](https://github.com/xinbenlv/eip-1202)
|
||||
|
||||
## Copyright
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ author: Afri Schoedon (@5chdn)
|
|||
discussions-to: https://ethereum-magicians.org/t/eip-1234-constantinople-difficulty-bomb-delay-and-block-reward-adjustment/833
|
||||
type: Standards Track
|
||||
category: Core
|
||||
status: Accepted
|
||||
status: Final
|
||||
created: 2018-07-19
|
||||
---
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ We considered use cases of MVTs being assigned to individuals which are non-tran
|
|||
- Investor permissioning: Making regulatory compliance a simple on chain process. Tokenization of securities, that are streamlined to flow only to accredited addresses, tracing and certifying on chain addresses for AML purposes.
|
||||
- Software licencing: Software companies like game developers can use the protocol to authorize certain hardware units(consoles) to download and use specific software(games)
|
||||
|
||||
In general, an individual can have different memberships in his day to day life. The protocol allows for the creation of software that puts everything all at one place. His identity can be verified instantly. Imagine a world where you don't need to carry a wallet full of identity cards (Passport, gym membership, SSN, Company ID etc) and organizations can easily keep track of all its members. Organizations can easily identify and disallow fake identities.
|
||||
In general, an individual can have different memberships in their day to day life. The protocol allows for the creation of software that puts everything all at one place. Their identity can be verified instantly. Imagine a world where you don't need to carry a wallet full of identity cards (Passport, gym membership, SSN, Company ID etc) and organizations can easily keep track of all its members. Organizations can easily identify and disallow fake identities.
|
||||
|
||||
Attributes are a huge part of ERC-1261 which help to store identifiable information regarding its members. Polls can make use of attributes to calculate the voterbase.
|
||||
E.g: Users should belong to USA entity and not belong to Washington state attribute to be a part of a poll.
|
||||
|
@ -94,7 +94,7 @@ interface IERC1261 {/* is ERC173, ERC165 */
|
|||
/// Contract can set a max number of attributes and throw if limit is reached.
|
||||
/// @param _name Name of the attribute which is to be added.
|
||||
/// @param values List of values of the specified attribute.
|
||||
function addAttributeSet(bytes32 _name, bytes32[] values) external;
|
||||
function addAttributeSet(bytes32 _name, bytes32[] calldata values) external;
|
||||
|
||||
/// @notice Modifies the attribute value of a specific attribute for a given `_to` address.
|
||||
/// @dev Use appropriate checks for whether a user/admin can modify the data.
|
||||
|
@ -106,13 +106,13 @@ interface IERC1261 {/* is ERC173, ERC165 */
|
|||
|
||||
/// @notice Requests membership from any address.
|
||||
/// @dev Throws if the `msg.sender` already has the token.
|
||||
/// The individual `msg.sender` can request for a membership if some exisiting criteria are satisfied.
|
||||
/// The individual `msg.sender` can request for a membership if some existing criteria are satisfied.
|
||||
/// When a membership is requested, this function emits the RequestedMembership event.
|
||||
/// dev can store the membership request and use `approveRequest` to assign memebership later
|
||||
/// dev can store the membership request and use `approveRequest` to assign membership later
|
||||
/// dev can also oraclize the request to assign membership later
|
||||
/// @param _attributeIndexes the attribute data associated with the member.
|
||||
/// This is an array which contains indexes of attributes.
|
||||
function requestMembership(uint[] _attributeIndexes) external payable;
|
||||
function requestMembership(uint[] calldata _attributeIndexes) external payable;
|
||||
|
||||
/// @notice User can forfeit his membership.
|
||||
/// @dev Throws if the `msg.sender` already doesn't have the token.
|
||||
|
@ -146,7 +146,7 @@ interface IERC1261 {/* is ERC173, ERC165 */
|
|||
/// @param _to The address to which the token is assigned.
|
||||
/// @param _attributeIndexes The attribute data associated with the member.
|
||||
/// This is an array which contains indexes of attributes.
|
||||
function assignTo(address _to, uint[] _attributeIndexes) external;
|
||||
function assignTo(address _to, uint[] calldata _attributeIndexes) external;
|
||||
|
||||
/// @notice Only Owner can revoke the membership.
|
||||
/// @dev This removes the membership of the user.
|
||||
|
@ -168,7 +168,7 @@ interface IERC1261 {/* is ERC173, ERC165 */
|
|||
/// @dev Returns the values of attributes as a bytes32 array.
|
||||
/// @param _name Name of the attribute whose values are to be fetched
|
||||
/// @return The values of attributes.
|
||||
function getAttributeExhaustiveCollection(bytes32 _name) external view returns (bytes32[]);
|
||||
function getAttributeExhaustiveCollection(bytes32 _name) external view returns (bytes32[] memory);
|
||||
|
||||
/// @notice Returns the list of all past and present members.
|
||||
/// @dev Use this function along with isCurrentMember to find wasMemberOf() in Js.
|
||||
|
@ -190,7 +190,7 @@ interface IERC1261 {/* is ERC173, ERC165 */
|
|||
/// Which has a single attributeValue for each attributeName in an array.
|
||||
/// Use web3.toAscii(data[0]).replace(/\u0000/g, "") to convert to string in JS.
|
||||
/// @return The names of attributes.
|
||||
function getAttributeNames() external view returns (bytes32[]);
|
||||
function getAttributeNames() external view returns (bytes32[] memory);
|
||||
|
||||
/// @notice Returns the attributes of `_to` address.
|
||||
/// @dev Throws if `_to` is the zero address.
|
||||
|
@ -215,7 +215,7 @@ interface ERC173 /* is ERC165 */ {
|
|||
|
||||
/// @notice Get the address of the owner
|
||||
/// @return The address of the owner.
|
||||
function owner() view external;
|
||||
function owner() external view;
|
||||
|
||||
/// @notice Set the address of the new owner of the contract
|
||||
/// @param _newOwner The address of the new owner of the contract
|
||||
|
@ -295,9 +295,9 @@ One can think of the set of MVTs as identifying a user, and you cannot split the
|
|||
|
||||
The assign and revoke functions' documentation only specify conditions when the transaction MUST throw. Your implementation MAY also throw in other situations. This allows implementations to achieve interesting results:
|
||||
|
||||
- **Disallow additional memberships after a condition is met** — Sample contract available on Github
|
||||
- **Blacklist certain address from receiving MV tokens** — Sample contract available on Github
|
||||
- **Disallow additional memberships after a certain time is reached** — Sample contract available on Github
|
||||
- **Disallow additional memberships after a condition is met** — Sample contract available on GitHub
|
||||
- **Blacklist certain address from receiving MV tokens** — Sample contract available on GitHub
|
||||
- **Disallow additional memberships after a certain time is reached** — Sample contract available on GitHub
|
||||
- **Charge a fee to user of a transaction** — require payment when calling `assign` and `revoke` so that condition checks from external sources can be made
|
||||
|
||||
**ERC-173 Interface**
|
||||
|
@ -365,7 +365,7 @@ Membership Verification Token ERC1261 -- a reference implementation
|
|||
1. ERC-165 Standard Interface Detection. https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md
|
||||
1. ERC-725/735 Claim Registry https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md
|
||||
1. ERC-173 Owned Standard. https://github.com/ethereum/EIPs/issues/173
|
||||
1. JSON Schema. http://json-schema.org/
|
||||
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
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ contract ERC1271 {
|
|||
}
|
||||
```
|
||||
|
||||
`isValidSignature` can call arbitrary methods to validate a given signature, which could be context dependent (e.g. time based or state based), EOA dependant (e.g. signers authorization level within smart wallet), signature scheme Dependant (e.g. ECDSA, multisig, BLS), etc.
|
||||
`isValidSignature` can call arbitrary methods to validate a given signature, which could be context dependent (e.g. time based or state based), EOA dependent (e.g. signers authorization level within smart wallet), signature scheme Dependent (e.g. ECDSA, multisig, BLS), etc.
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ eip: 1283
|
|||
title: Net gas metering for SSTORE without dirty maps
|
||||
author: Wei Tang (@sorpaas)
|
||||
discussions-to: https://github.com/sorpaas/EIPs/issues/1
|
||||
status: Accepted
|
||||
status: Final
|
||||
type: Standards Track
|
||||
category: Core
|
||||
created: 2018-08-01
|
||||
|
@ -155,7 +155,7 @@ When *original value* is not 0:
|
|||
|
||||
## Rationale
|
||||
|
||||
This EIP mostly archives what a transient storage tries to do
|
||||
This EIP mostly achieves what a transient storage tries to do
|
||||
(EIP-1087 and EIP-1153), but without the complexity of introducing the
|
||||
concept of "dirty maps", or an extra storage struct.
|
||||
|
||||
|
@ -286,7 +286,7 @@ When *original value* is not 0, we want to prove that:
|
|||
charge `200 * N` gases, because no disk write is needed.
|
||||
* **Case II**: If the *final value* ends up being zero, we want to
|
||||
charge `5000 - 15000 + 200 * (N-1)` gas. Note that `15000` is the
|
||||
refund in actual defintion.
|
||||
refund in actual definition.
|
||||
* **Case III**: If the *final value* ends up being a changed non-zero
|
||||
value, we want to charge `5000 + 200 * (N-1)` gas.
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
eip: 1319
|
||||
title: Smart Contract Package Registry Interface
|
||||
author: Piper Merriam <piper@ethereum.org>, Christopher Gewecke <christophergewecke@gmail.com>, g. nicholas d'andrea <nick.dandrea@consensys.net>
|
||||
author: Piper Merriam <piper@ethereum.org>, Christopher Gewecke <christophergewecke@gmail.com>, g. nicholas d'andrea <nick.dandrea@consensys.net>, Nick Gheorghita <nickg@ethereum.org>
|
||||
type: Standards Track
|
||||
category: ERC
|
||||
status: Draft
|
||||
|
@ -60,7 +60,7 @@ Implementations are free to choose any scheme for generating a **releaseId**. A
|
|||
function generateReleaseId(string packageName, string version)
|
||||
public
|
||||
view
|
||||
returns (bytes32)
|
||||
returns (bytes32 releaseId)
|
||||
{
|
||||
return keccak256(abi.encodePacked(packageName, version));
|
||||
}
|
||||
|
@ -94,6 +94,16 @@ details the contents of the release.
|
|||
function release(string packageName, string version, string manifestURI) public
|
||||
returns (bytes32 releaseId);
|
||||
```
|
||||
|
||||
### Events
|
||||
|
||||
#### VersionRelease
|
||||
MUST be triggered when `release` is successfully called.
|
||||
|
||||
```solidity
|
||||
event VersionRelease(string packageName, string version, string manifestURI)
|
||||
```
|
||||
|
||||
### Read API Specification
|
||||
|
||||
The read API consists of a set of methods that allows tooling to extract all consumable data from a registry.
|
||||
|
@ -103,22 +113,22 @@ The read API consists of a set of methods that allows tooling to extract all con
|
|||
// `offset` and `limit` enable paginated responses / retrieval of the complete set. (See note below)
|
||||
function getAllPackageIds(uint offset, uint limit) public view
|
||||
returns (
|
||||
bytes32 packageIds,
|
||||
uint offset
|
||||
bytes32[] packageIds,
|
||||
uint pointer
|
||||
);
|
||||
|
||||
// Retrieves the unique string `name` associated with a package's id.
|
||||
function getPackageName(bytes32 packageId) public view returns (string name);
|
||||
function getPackageName(bytes32 packageId) public view returns (string packageName);
|
||||
|
||||
// Retrieves the registry's unique identifier for an existing release of a package.
|
||||
function getReleaseId(string packageName, string version) public view returns (bytes32);
|
||||
function getReleaseId(string packageName, string version) public view returns (bytes32 releaseId);
|
||||
|
||||
// Retrieves a slice of the list of all release ids for a package.
|
||||
// `offset` and `limit` enable paginated responses / retrieval of the complete set. (See note below)
|
||||
function getAllReleaseIds(string packageName, uint offset, uint limit) public view
|
||||
returns (
|
||||
bytes32[] ids,
|
||||
uint offset
|
||||
bytes32[] releaseIds,
|
||||
uint pointer
|
||||
);
|
||||
|
||||
// Retrieves package name, release version and URI location data for a release id.
|
||||
|
@ -134,11 +144,17 @@ function getReleaseData(bytes32 releaseId) public view
|
|||
function generateReleaseId(string packageName, string version)
|
||||
public
|
||||
view
|
||||
returns (bytes32);
|
||||
returns (bytes32 releaseId);
|
||||
|
||||
// Returns the total number of unique packages in a registry.
|
||||
function numPackageIds() public view returns (uint totalCount);
|
||||
|
||||
// Returns the total number of unique releases belonging to the given packageName in a registry.
|
||||
function numReleaseIds(string packageName) public view returns (uint totalCount);
|
||||
```
|
||||
**Pagination**
|
||||
|
||||
`getAllPackageIds` and `getAllReleaseIds` support paginated requests because it's possible that the return values for these methods could become quite large. The methods should return an `offset` that is a pointer to the next available item in a list of all items such that a caller can use it to pick up from where the previous request left off. (See [here](https://mixmax.com/blog/api-paging-built-the-right-way) for a discussion of the merits and demerits of various pagination strategies.) The `limit` parameter defines the maximum number of items a registry should return per request.
|
||||
`getAllPackageIds` and `getAllReleaseIds` support paginated requests because it's possible that the return values for these methods could become quite large. The methods should return a `pointer` that points to the next available item in a list of all items such that a caller can use it to pick up from where the previous request left off. (See [here](https://mixmax.com/blog/api-paging-built-the-right-way) for a discussion of the merits and demerits of various pagination strategies.) The `limit` parameter defines the maximum number of items a registry should return per request.
|
||||
|
||||
## Rationale
|
||||
The proposal hopes to accomplish the following:
|
||||
|
@ -154,7 +170,7 @@ Registries may offer more complex `read` APIs that manage requests for packages
|
|||
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.
|
||||
|
||||
## Implementation
|
||||
A reference implementation of this proposal is in active development at the EthPM organization on Github [here](https://github.com/ethpm/escape-truffle).
|
||||
A reference implementation of this proposal is in active development at the EthPM organization on GitHub [here](https://github.com/ethpm/escape-truffle).
|
||||
|
||||
## Copyright
|
||||
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
|
||||
|
|
|
@ -7,12 +7,11 @@ category: ERC
|
|||
status: Draft
|
||||
created: 2018-08-15
|
||||
discussions-to: https://ethereum-magicians.org/t/wallet-connect-eip/850
|
||||
requires: 831
|
||||
---
|
||||
|
||||
## Simple Summary
|
||||
|
||||
A standard to create WalletConnect URIs for establishing connections between wallets and applications.
|
||||
A standard to create WalletConnect URIs to initiate connections between applications and wallets.
|
||||
|
||||
## Abstract
|
||||
|
||||
|
@ -22,33 +21,33 @@ This standard defines how the data to connect some application and a wallet can
|
|||
|
||||
### Syntax
|
||||
|
||||
Function call URIs follow the ERC-831 URI format, with the following parameters:
|
||||
WalletConnect request URI with the following parameters:
|
||||
|
||||
request = "ethereum" ":" [ "wc-" ]sessionId [ "@" version ][ "?" parameters ]
|
||||
sessionId = STRING
|
||||
request = "wc" ":" topic [ "@" version ][ "?" parameters ]
|
||||
topic = STRING
|
||||
version = 1*DIGIT
|
||||
parameters = parameter *( "&" parameter )
|
||||
parameter = key "=" value
|
||||
key = "name" / "bridge" / "symKey"
|
||||
value = NUMBER / STRING
|
||||
key = "bridge" / "key"
|
||||
value = STRING
|
||||
|
||||
### Semantics
|
||||
|
||||
Required parameters are dependent on the WalletConnect standard version which currently is specified to only include mobile-to-desktop connection sessions which only require `name` which describes the dapp name, `bridge` which includes the bridge URL, `symKey` which includes the symmetric key in base64.
|
||||
Required parameters are dependent on the Walletconnect protocol version which currently includes the `key`, hex string of symmetric key, and `bridge`, encoded url of the bridge used for establishing the connection.
|
||||
|
||||
### Example
|
||||
|
||||
```
|
||||
ethereum:wc-8a5e5bdc-a0e4-4702-ba63-8f1a5655744f@1?name=DappExample&bridge=https://bridge.example.com&symKey=KzpSTk1pezg5eTJRNmhWJmoxdFo6UDk2WlhaOyQ5N0U=
|
||||
wc:8a5e5bdc-a0e4-4702-ba63-8f1a5655744f@1?bridge=https%3A%2F%2Fbridge.walletconnect.org&key=41791102999c339c844880b23950704cc43aa840f3739e365323cda4dfa89e7a
|
||||
```
|
||||
|
||||
## Rationale
|
||||
|
||||
The need for this ERC stems from the discussion to move away from JSON format used in current beta version of the WalletConnect standard which makes for very inneficient parsing of the intent of the QR code, making it easier to create better QR code parsers APIs for Wallets to implement for other compatible EIPs using the ERC-831 URI format for Ethereum. Also by using a URI instead of a JSON inside the QR-Code the Android Intent system can be leveraged.
|
||||
The need for this ERC stems from the discussion to move away from JSON format used in the alpha version of the WalletConnect protocol which makes for very inneficient parsing of the intent of the QR code, making it easier to create better QR code parsers APIs for Wallets to implement. Also by using a URI instead of a JSON inside the QR-Code the Android Intent system can be leveraged.
|
||||
|
||||
## References
|
||||
|
||||
1. ERC-831, http://eips.ethereum.org/EIPS/eip-831
|
||||
1. WalletConnect Technical Specification, https://docs.walletconnect.org/tech-spec
|
||||
|
||||
## Copyright
|
||||
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
---
|
||||
eip: 1344
|
||||
title: ChainID opcode
|
||||
author: Richard Meissner (@rmeissner), Bryant Eisenbach (@fubuloubu)
|
||||
discussions-to: https://ethereum-magicians.org/t/add-chain-id-opcode-for-replay-protection-when-handling-signed-messages-in-contracts/1131
|
||||
category: Core
|
||||
type: Standards Track
|
||||
requires: 155
|
||||
status: Final
|
||||
created: 2018-08-22
|
||||
---
|
||||
|
||||
## Abstract
|
||||
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).
|
||||
|
||||
## 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.
|
||||
|
||||
The value of the current chain ID is obtained from the chain ID configuration, which should match the EIP-155 unique identifier a client will accept from incoming transactions. Please note that per EIP-155, it is not *required* that a transaction have an EIP-155 unique identifier, but in that scenario this opcode will still return the configured chain ID and not a default.
|
||||
|
||||
## Rationale
|
||||
The current approach proposed by EIP-712 is to specify the chain ID at compile time. Using this approach will result in problems after a hardfork, as well as human error that may lead to loss of funds or replay attacks on signed messages.
|
||||
By adding the proposed opcode it will be possible to access the current chain ID and validate signatures based on that.
|
||||
|
||||
Currently, there is no specification for how chain ID is set for a particular network, relying on choices made manually by the client implementers and the chain community. There is a potential scenario where, during a "contentious split" over a divisive issue, a community using a particular value of chain ID will make a decision to split into two such chains. When this scenario occurs, it will be unsafe to maintain chain ID to the same value on both chains, as chain ID is used for replay protection for in-protocol transactions (per EIP-155), as well as for L2 and "meta-transaction" use cases (per EIP-712 as enabled by this proposal). There are two potential resolutions in this scenario under the current process: 1) one chain decides to modify their value of chain ID (while the other keeps it), or 2) both chains decide to modify their value of chain ID.
|
||||
|
||||
In order to mitigate this situation, users of the proposed `CHAINID` opcode **must** ensure that their application can handle a potential update to the value of chain ID during their usage of their application in case this does occur, if required for the continued use of the application. A Trustless Oracle that logs the timestamp when a change is made to chain ID can be implemented either as an application-level feature inside the application contract system, or referenced as a globally standard contract. Failure to provide a mitigation for this scenario could lead to a sudden loss of legitimacy of previously signed off-chain messages, which could be an issue during settlement periods and other longer-term verification events for these types of messages. Not all applications of this opcode may need mitigations to handle this scenario, but developers should provide reasoning on a case-by-case basis.
|
||||
|
||||
One example of a scenario where it would not make sense to leverage a global oracle is with the Plasma L2 paradigm. In the Plasma paradigm, an operator or group of operators submit blocks from the L2 network to the base chain (in this case Ethereum) summarizing transactions that have occurred on that chain. The submission of these blocks may not perfectly align with major events on the mainchain, such as a split causing an update of chain ID, which may cause a significant insecurity in the protocol if chain ID is utilized in signing messages. If the operators are not allowed to control the update of chain ID they will not be able to perfectly synchronize the update with their block submissions, and certain past transactions may be rejected because they do not align with the update. This is one example of the unintended consequences of trying to specify too much of the behavior of chain ID during a contentious split, and why having a simple opcode for access is most optimal, versus a more complicated precompile or contract.
|
||||
|
||||
This proposed opcode would be the simplest possible way to implement this functionality, and allows developers the flexibility to implement their own global or local handling of chain ID changes, if required.
|
||||
|
||||
## Backwards Compatibility
|
||||
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).
|
||||
|
||||
## Test Cases
|
||||
Test Cases added to [ethereum/tests](https://github.com/ethereum/tests/pull/627)
|
||||
|
||||
## Implementation
|
||||
A reference implementation for the Trinity Python client is [here](https://github.com/ethereum/py-evm/pull/1803).
|
||||
|
||||
An example implementation of a trustless chain ID oracle was implemented [here](https://github.com/fubuloubu/chain-id-oracle/blob/master/ChainIdOracle.vy).
|
||||
|
||||
## Copyright
|
||||
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
|
|
@ -1,9 +1,9 @@
|
|||
---
|
||||
eip: 1355
|
||||
title: Ethash 1a
|
||||
author: Paweł Bylica <pawel@ethereum.org>, Jean M. Cyr [@jean-m-cyr](https://github.com/jean-m-cyr)
|
||||
author: Paweł Bylica (@chfast) <pawel@ethereum.org>, Jean M. Cyr (@jean-m-cyr)
|
||||
discussions-to: https://ethereum-magicians.org/t/eip-1355-ethash-1a/1167
|
||||
status: Draft
|
||||
status: Abandoned
|
||||
type: Standards Track
|
||||
category: Core
|
||||
created: 2018-08-26
|
||||
|
|
|
@ -53,14 +53,14 @@ Resolving a name in ENS is a two-step process. First, the ENS registry is called
|
|||
|
||||
For example, suppose you wish to find the address of the token contract associated with 'beercoin.eth'. First, get the resolver:
|
||||
|
||||
```
|
||||
```javascript
|
||||
var node = namehash("beercoin.eth");
|
||||
var resolver = ens.resolver(node);
|
||||
```
|
||||
|
||||
Then, ask the resolver for the address for the contract:
|
||||
|
||||
```
|
||||
```javascript
|
||||
var address = resolver.addr(node);
|
||||
```
|
||||
|
||||
|
@ -70,10 +70,10 @@ Because the `namehash` procedure depends only on the name itself, this can be pr
|
|||
ENS names must conform to the following syntax:
|
||||
|
||||
<pre><domain> ::= <label> | <domain> "." <label>
|
||||
<label> ::= any valid string label per [UTS46](http://unicode.org/reports/tr46/)
|
||||
<label> ::= any valid string label per [UTS46](https://unicode.org/reports/tr46/)
|
||||
</pre>
|
||||
|
||||
In short, names consist of a series of dot-separated labels. Each label must be a valid normalised label as described in [UTS46](http://unicode.org/reports/tr46/) with the options `transitional=false` and `useSTD3AsciiRules=true`. For Javascript implementations, a [library](https://www.npmjs.com/package/idna-uts46) is available that normalises and checks names.
|
||||
In short, names consist of a series of dot-separated labels. Each label must be a valid normalised label as described in [UTS46](https://unicode.org/reports/tr46/) with the options `transitional=false` and `useSTD3AsciiRules=true`. For Javascript implementations, a [library](https://www.npmjs.com/package/idna-uts46) is available that normalises and checks names.
|
||||
|
||||
Note that while upper and lower case letters are allowed in names, the UTS46 normalisation process case-folds labels before hashing them, so two names with different case but identical spelling will produce the same namehash.
|
||||
|
||||
|
@ -112,43 +112,43 @@ Implementations should conform to the following test vectors for namehash:
|
|||
|
||||
The ENS registry contract exposes the following functions:
|
||||
|
||||
```
|
||||
```solidity
|
||||
function owner(bytes32 node) constant returns (address);
|
||||
```
|
||||
|
||||
Returns the owner (registrar) of the specified node.
|
||||
|
||||
```
|
||||
```solidity
|
||||
function resolver(bytes32 node) constant returns (address);
|
||||
```
|
||||
|
||||
Returns the resolver for the specified node.
|
||||
|
||||
```
|
||||
```solidity
|
||||
function ttl(bytes32 node) constant returns (uint64);
|
||||
```
|
||||
|
||||
Returns the time-to-live (TTL) of the node; that is, the maximum duration for which a node's information may be cached.
|
||||
|
||||
```
|
||||
```solidity
|
||||
function setOwner(bytes32 node, address owner);
|
||||
```
|
||||
|
||||
Transfers ownership of a node to another registrar. This function may only be called by the current owner of `node`. A successful call to this function logs the event `Transfer(bytes32 indexed, address)`.
|
||||
|
||||
```
|
||||
```solidity
|
||||
function setSubnodeOwner(bytes32 node, bytes32 label, address owner);
|
||||
```
|
||||
|
||||
Creates a new node, `sha3(node, label)` and sets its owner to `owner`, or updates the node with a new owner if it already exists. This function may only be called by the current owner of `node`. A successful call to this function logs the event `NewOwner(bytes32 indexed, bytes32 indexed, address)`.
|
||||
|
||||
```
|
||||
```solidity
|
||||
function setResolver(bytes32 node, address resolver);
|
||||
```
|
||||
|
||||
Sets the resolver address for `node`. This function may only be called by the owner of `node`. A successful call to this function logs the event `NewResolver(bytes32 indexed, address)`.
|
||||
|
||||
```
|
||||
```solidity
|
||||
function setTTL(bytes32 node, uint64 ttl);
|
||||
```
|
||||
|
||||
|
@ -159,7 +159,7 @@ Resolvers may implement any subset of the record types specified here. Where a r
|
|||
|
||||
Resolvers have one mandatory function:
|
||||
|
||||
```
|
||||
```solidity
|
||||
function supportsInterface(bytes4 interfaceID) constant returns (bool)
|
||||
```
|
||||
|
||||
|
@ -184,7 +184,7 @@ EIPs may define new interfaces to be added to this registry.
|
|||
|
||||
Resolvers wishing to support contract address resources must provide the following function:
|
||||
|
||||
```
|
||||
```solidity
|
||||
function addr(bytes32 node) constant returns (address);
|
||||
```
|
||||
|
||||
|
@ -194,12 +194,12 @@ Clients resolving the `addr` record MUST check for a zero return value, and trea
|
|||
|
||||
Changes to an address MUST trigger the following event:
|
||||
|
||||
```
|
||||
```solidity
|
||||
event AddrChanged(bytes32 indexed node, address a);
|
||||
```
|
||||
# Appendix A: Registry Implementation
|
||||
|
||||
```
|
||||
```solidity
|
||||
contract ENS {
|
||||
struct Record {
|
||||
address owner;
|
||||
|
@ -261,7 +261,7 @@ contract ENS {
|
|||
|
||||
The simplest possible resolver is a contract that acts as its own name resolver by implementing the contract address resource profile:
|
||||
|
||||
```
|
||||
```solidity
|
||||
contract DoSomethingUseful {
|
||||
// Other code
|
||||
|
||||
|
@ -285,7 +285,7 @@ Such a contract can be inserted directly into the ENS registry, eliminating the
|
|||
|
||||
A basic resolver that implements the contract address profile, and allows only its owner to update records:
|
||||
|
||||
```
|
||||
```solidity
|
||||
contract Resolver {
|
||||
event AddrChanged(bytes32 indexed node, address a);
|
||||
|
||||
|
@ -325,7 +325,7 @@ After deploying this contract, use it by updating the ENS registry to reference
|
|||
|
||||
Similar to the resolver above, this contract only supports the contract address profile, but uses the ENS registry to determine who should be allowed to update entries:
|
||||
|
||||
```
|
||||
```solidity
|
||||
contract PublicResolver {
|
||||
event AddrChanged(bytes32 indexed node, address a);
|
||||
event ContentChanged(bytes32 indexed node, bytes32 hash);
|
||||
|
@ -364,7 +364,7 @@ contract PublicResolver {
|
|||
|
||||
This registrar allows users to register names at no cost if they are the first to request them.
|
||||
|
||||
```
|
||||
```solidity
|
||||
contract FIFSRegistrar {
|
||||
ENS ens;
|
||||
bytes32 rootNode;
|
||||
|
|
|
@ -25,7 +25,7 @@ Using `JUMP` comes at a considerable cost in complexity to the implementation of
|
|||
must be swapped in and out of the calling functions context. A desired feature is having *pure* functions, which do not modify the state of memory, and realising
|
||||
them through `JUMP` requires a bigger effort from the compiler as opposed to being able to use `CALL`s.
|
||||
|
||||
Using call-to-self provides the guarentee that when making an internal call the function can rely on a clear reset state of memory or context, benefiting both
|
||||
Using call-to-self provides the guarantee that when making an internal call the function can rely on a clear reset state of memory or context, benefiting both
|
||||
contract writers and contract consumers against potentially undetetected edge cases were memory could poison the context of the internal function.
|
||||
|
||||
Because of the `JUMP` usage for internal functions a smart contract languages are also at risk of reaching the stack depth limit considerbly faster, if nested
|
||||
|
|
|
@ -40,7 +40,7 @@ The wine vendors smart contract validates the attestation, checks the payment am
|
|||
When the wine vendor shows up to her apartment with the wine, there is no need to prove her age again.
|
||||
|
||||
### Draft interface
|
||||
```
|
||||
```solidity
|
||||
/* each attestation issuer should provide their own verify() for the
|
||||
* attestations they issued. There are two reasons for this. First, we
|
||||
* need to leave room for new attestation methods other than the
|
||||
|
|
|
@ -21,7 +21,7 @@ Unlike previous attempts, we assume that the attestation is signed and issued of
|
|||
This ERC provides an interface and reference implementation for smart contracts that need users to provide an attestation and validate it.
|
||||
|
||||
### Draft implementation
|
||||
```
|
||||
```solidity
|
||||
contract MerkleTreeAttestationInterface {
|
||||
struct Attestation
|
||||
{
|
||||
|
|
|
@ -21,9 +21,9 @@ Anyone can publish a list of issuers. Only the most trusted and carefully mainta
|
|||
This ERC provides a smart contract interface for anyone to manage a list of attestation issuers. A smart contract would explicitly trust a list, and therefore all attestations issued by the issuers on the list.
|
||||
|
||||
### Draft implementation
|
||||
```
|
||||
```solidity
|
||||
/* The purpose of this contract is to manage the list of attestation
|
||||
* issuer contracts and their capacity to fulfil requirements
|
||||
* issuer contracts and their capacity to fulfill requirements
|
||||
*/
|
||||
contract ManagedListERC
|
||||
{
|
||||
|
|
|
@ -26,7 +26,7 @@ The following standard allows for the implementation of a standard API for polls
|
|||
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:
|
||||
|
||||
- Plurality Voting: The simplest form of voting is when you want all eligible voters to have one vote per person. This is the simplest to code, as the vote weight is 1, and there is no vote consequence. The only relevant module here is the voterbase, which can be categorized by one or more MVT contracts.
|
||||
- Token proportional voting: This kind of a poll is actually possible without the use of a voterbase function, because the vote weight function having token proportionality automatically rules out addresses which dont hold the appropriate ERC - 20/ ERC - 777 token. However the voterbase function may be leveraged to further permission the system and give voting rights only to a fixed subset of token holders.
|
||||
- Token proportional voting: This kind of a poll is actually possible without the use of a voterbase function, because the vote weight function having token proportionality automatically rules out addresses which don't hold the appropriate ERC - 20/ ERC - 777 token. However the voterbase function may be leveraged to further permission the system and give voting rights only to a fixed subset of token holders.
|
||||
- Capped Token Proportional Voting: This is a modified version of the previous example, where each voter is given proportional vote share only until a certain limit of token ownership. After exceeding that limit, holding more coins does not add more vote share. This format leverages the voterbase module effectively, disallowing people from spreading their coins across multiple addresses by allowing the admin to control which addresses can vote.
|
||||
- Delegated Voting: Certain polls may allow voters to delegate their votes to other voters. This is known as delegated voting or liquid democracy. For such a poll, a complicated vote weight function is needed, and a data structure concerning the voterbase is also required. A consequence of voting here would be that a user cannot delegate, and a consequence of delegating is that a user cannot vote. Sample implementation of polls contains an example of this vote scheme.
|
||||
- Karma Based Voting: A certain form of poll may be based on weightage from digital respect. This digital respect would be like a simple upvote from one member of voterbase to another. A mapping of mappings along with an appropriate vote weight function can serve this purpose. Sample implementation has an example.
|
||||
|
@ -46,7 +46,7 @@ This realization happened while conducting market research on DAICOs. The first
|
|||
|
||||
2. Permissioning: Permissioning is an important aspect of polls, and is missing in most poll proposals so far, on the blockchain. For some reason, most blockchain based polls seem to consider token holding as the only way to permission a poll. However this hampers flexibility, and hence our poll standard is leveraging EIP 1261 in order to clear the permissioning hurdle. Not only does it allow for more creative poll structures in terms of vote weightage, but even improves the flexibility in permissioning by allowing developers to combine several entities and read attributes from entities.
|
||||
|
||||
3. Flexibilty: The vote weight module of the poll standard can be used effectively to design various kinds of poll contracts which function differently and are suited to different environments. Some examples are quadratic voting, karma voting, delegated voting, token based voting, and one person one vote systems. These schemes are possible due to the separation of voterbase creation and vote weight calculation.
|
||||
3. Flexibility: The vote weight module of the poll standard can be used effectively to design various kinds of poll contracts which function differently and are suited to different environments. Some examples are quadratic voting, karma voting, delegated voting, token based voting, and one person one vote systems. These schemes are possible due to the separation of voterbase creation and vote weight calculation.
|
||||
|
||||
4. NoV Counts: Several weighted polls have struggled to provide proper transparency because they only show the final result without enough granularity. This is because they do not store the number of voters that have voted for each proposal, and only store the total accrued vote for each option. EIP 1417 solves this by additionally recording number of voters(NoV) in each proposal. This NoV count is redundant in the case of one person one vote, but elsewhere, it is helpful in figuring out concentration of power. This ensures that malicious parties can be traced to a larger extent.
|
||||
|
||||
|
@ -59,13 +59,13 @@ All that being said, we are very excited to share our proposal with the communit
|
|||
### Benefits
|
||||
|
||||
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 programatically based on the result of a poll
|
||||
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)
|
||||
4. Flexibility allows for various voting schemes including but not limited to modern schemes such as PLCR Voting
|
||||
|
||||
### Use-cases:
|
||||
|
||||
Polls are useful in any context of collective decision making, which include but arent limited to:
|
||||
Polls are useful in any context of collective decision making, which include but aren't limited to:
|
||||
|
||||
1. Governing public resources, like ponds, playgrounds, streets etc
|
||||
2. Maintaining fiscal policy in a transparent consensus driven manner
|
||||
|
@ -177,7 +177,7 @@ interface IPoll {
|
|||
/// @return end time as Unix Standard Time
|
||||
function getEndTime() external view returns (uint);
|
||||
|
||||
/// @notice retuns the list of entity addresses (eip-1261) used for perimissioning purposes.
|
||||
/// @notice returns the list of entity addresses (eip-1261) used for perimissioning purposes.
|
||||
/// @dev addresses list can be used along with IERC1261 interface to define the logic inside `canVote()` function
|
||||
/// @return the list of addresses of entities
|
||||
function getProtocolAddresses() external view returns (address[]);
|
||||
|
|
|
@ -0,0 +1,186 @@
|
|||
---
|
||||
eip: 1418
|
||||
title: Blockchain Storage Rent Payment
|
||||
author: William Entriken (@fulldecent)
|
||||
discussions-to: https://github.com/ethereum/EIPs/issues/1418
|
||||
status: Draft
|
||||
type: Standards Track
|
||||
category: Core
|
||||
created: 2018-09-16
|
||||
---
|
||||
|
||||
# Simple Summary
|
||||
|
||||
At each block, deduct an amount of value from every account based on the quantity of storage used by that account.
|
||||
|
||||
# Abstract
|
||||
|
||||
The most naive implementation would be to simply loop through every account on each block and deduct a certain fee. We show that a better implementation could achieve reasonable performance. Also we review practical considerations of switching to a fee-based rent system.
|
||||
|
||||
In other words, `product=0; while(factor1--)product+= factor2;` is slow, but equivalently `product = factor1 * factor2` is fast. And we can reason about both at the same time.
|
||||
|
||||
# Motivation
|
||||
|
||||
Ethereum is a public utility and we are underpricing the long-term costs of storage. Storage cost can be approximately modeled as bytes × time.
|
||||
|
||||
# Specification
|
||||
|
||||
**New state variables (per account)**
|
||||
|
||||
* rent -- σ[a]_r -- an amount of value, in Wei
|
||||
* rentLastPaid -- σ[a]_p -- a block number that is set when:
|
||||
* Value is transferred into an account
|
||||
* Code is set for an account (CREATE)
|
||||
* An account's storage is updated (SSTORE)
|
||||
* storageWords -- σ[a]_w -- number of words in storage
|
||||
* rentEvictBlock -- σ[a]_e -- the block number when this account will be destructed
|
||||
* Note: it is possible that a client could implement the Yellow Paper without storing this value explicitly. It can be calculated simply on demand.
|
||||
|
||||
**New constants**
|
||||
|
||||
* RENT_WORD_COST -- The rent cost, in Wei, paid for each word-block
|
||||
* RENT_ACCOUNT_COST -- The rent cost, in Wei, paid for each account-block
|
||||
* RENT_STIPEND -- The amount of rent, in Wei, given to accounts when touched
|
||||
|
||||
**New opcodes**
|
||||
|
||||
* RENTBALANCE(address) -- G_BALANCE -- Similar to BALANCE
|
||||
* SENDRENT(address, amount) -- G_BASE -- Convert value to rent and send to account
|
||||
1. σ[account]_rent += amount
|
||||
2. σ[msg.sender]_balance -= amount
|
||||
|
||||
**Updated opcodes**
|
||||
|
||||
A new subroutine, paying for rent, is established as such:
|
||||
|
||||
```pseudocode
|
||||
PAYRENT(account)
|
||||
ASSERT(σ[account]_rentEviction >= NUMBER) // TODO: I'm not sure if should be > or >=
|
||||
blocks_to_pay = NUMBER - σ[account]_rentLastPaid
|
||||
cost_per_block = RENT_ACCOUNT_COST + RENT_WORD_COST * ⌈∥σ[account]_code∥ / 32⌉ + RENT_WORD_COST * σ[a]_storageWords
|
||||
rent_to_pay = blocks_to_pay * cost_per_block
|
||||
σ[account]_rent -= rent_to_pay
|
||||
σ[account]_rentLastPaid = NUMBER
|
||||
σ[account]_rentEvictBlock = NUMBER + ⌊σ[account]_rent / cost_per_block⌋
|
||||
END PAYRENT
|
||||
```
|
||||
|
||||
* SSTORE(account, key, value)
|
||||
* Perform PAYRENT(account)
|
||||
* Set σ[account]_rent = MAX(σ[account]_rent, RENT_STIPEND)
|
||||
* Do normal SSTORE operation
|
||||
* If the old value was zero for this [account, key] and the new value is non-zero, then σ[account]_storageSize++
|
||||
* If the old value was non-zero for this [account, key] and the new value is zero, then σ[account]_storageSize--
|
||||
* CALL (and derivatives)
|
||||
* If value > 0 then perform PAYRENT(account)
|
||||
* Do normal CALL operation
|
||||
* CREATE
|
||||
* Set σ[account]_rent = MAX(σ[account]_rent, RENT_STIPEND)
|
||||
* Set σ[account]_rentLastPaid = HEIGHT
|
||||
* Do normal CREATE operation
|
||||
* Note: it is possible there is a pre-existing rent balance here
|
||||
|
||||
**Updated substate**
|
||||
|
||||
The substate tuple is defined as:
|
||||
|
||||
> A ≡ (As, Al, At, Ar)
|
||||
|
||||
This includes A_t, "the set of touched accounts, of which the empty ones are deleted at the end of a transaction".
|
||||
|
||||
This definition is updated to: "the set of touched accounts, of which the empty ones or evicted ones (BLOCK >= σ[a]_rentEvictBlock) are deleted at the end of a transaction"
|
||||
|
||||
// TODO: I'm not sure if that should be > or >=
|
||||
|
||||
**New built-in contract**
|
||||
|
||||
* PAYRENT(address, amount) -- Calls PAYRENT opcode
|
||||
|
||||
*This is a convenience for humans to send Ether from their accounts and turn it into rent. Note that simple accounts (CODESIZE == 0) cannot call arbitrary opcodes, they can only call CREATE or CALL.*
|
||||
|
||||
The gas cost of PAYRENT will be 10,000.
|
||||
|
||||
**No changes to current opcode gas costs.**
|
||||
|
||||
# Rationale
|
||||
|
||||
**No call**
|
||||
|
||||
A contract will not know or react to the receipt of rent. This is okay. Workaround: if a contract really needed to know who provided rent payments then it could create a function in its ABI to attribute these payments. It is already possible to send payments to a contract without attribution by using SELFDESTRUCT.
|
||||
|
||||
**Eviction responsibility / lazy evaluation**
|
||||
|
||||
The specification gives responsibility for eviction to the consensus clients. This is the most predictable behavior because it happens exactly when it should. Also there need not be any incentive mechanism (refund gas, bounty) for outside participants (off chain) to monitor accounts and request removal.
|
||||
|
||||
This adds a computational responsibility to the clients to track eviction dates. This is possible in efficient time (at double the memory) using a double-ended priority queue (one for addressing by account address, the other for addressing by eviction date). There may be other ways of implementing this with different time-memory guarantees.
|
||||
|
||||
**No converting rent to value**
|
||||
|
||||
Ether converted to rent cannot be converted back. Anybody that works in accounting and knows about gifts cards should tell you this is a good idea. It makes reasoning about the system much easier.
|
||||
|
||||
**Accounts pay rent**
|
||||
|
||||
Yes, they pay rent. It costs money to keep their balances so we charge them rent.
|
||||
|
||||
**You can lose all your money**
|
||||
|
||||
Yes, if you do not pay rent for your account or contract then you lose it all. User education is required.
|
||||
|
||||
Alternative: spend value (Ether balance) when rent is depleted
|
||||
* Rename rentEvictBlock to rentUsingValueBlock
|
||||
* Update eviction calculation to include RENT + VALUE. Also update CALL (and friends) operations to recalculate eviction date when value is transferred. This is the new rentEvictBlock.
|
||||
* Update CALL (and friends), RENTBALANCE and SENDRENT operations. If HEIGHT >= rentUsingValueBlock then proceed as if rent started paying using value.
|
||||
|
||||
This alternative is a good idea, if there is support I can include this part formally in the specification. The specification is a little complicated so I like the informal definition above until we have some consent around it.
|
||||
|
||||
Alternative2: do not have a separate rent account -- directly deduct rent from value
|
||||
* Every time the state is updated (including receiving value) you get a rent subsidity
|
||||
* Need to review invariants of existing contracts to see what problems and broken assumptions this will cause in real life
|
||||
|
||||
**Permanent removal**
|
||||
|
||||
All state about an account is destructed during eviction. The data cannot be recovered. That's the point.
|
||||
|
||||
Hint to implementers: make sure this works:
|
||||
|
||||
1. Send value to a new account (gets stipend)
|
||||
2. Pay rent to that account
|
||||
3. Wait until after the rent expires (account is gone)
|
||||
4. Send value to that account (gets stipend again)
|
||||
5. Deploy a contract (CREATE) to that account (stipend gets topped off)
|
||||
|
||||
# Rationale -- economics & constants
|
||||
|
||||
An `SSTORE` executed in 2015 cost 20,000 gas and has survived about 6 million blocks. The gas price has been around 1 ~ 50 Gwei. So basically 4,000 Wei per block per word so far. Maybe storing an account is 10 times more intensive than storing a word. But actually G_transaction is 21,000 and G_sstore is 20,000 so these are similar and they can both create new accounts / words.
|
||||
|
||||
How about:
|
||||
|
||||
* RENT_WORD_COST -- 4,000 Wei
|
||||
* RENT_ACCOUNT_COST -- 4,000 Wei
|
||||
* RENT_STIPEND -- 4,000 Wei * 360 days worth of blocks
|
||||
|
||||
The rent is priced in cold, hard Ether. It is not negotiated by clients, it is not dynamic. It is linear. Why is this a good idea? Because right now Ethereum is a system with multiple free variables -- Ether/gas price, gas/opcodes costs, Ether/block reward. [Add some note here about reducing a system of equations...] So the end result is that we can peg one of the values and it will be okay.
|
||||
|
||||
By setting the RENT price in Ether and by having the existing gas prices set based on the floating rate, there is an implicit price of ~4 gwei set into the Yellow Paper. In other words, if in the future the price of gas goes to 1 Ether then people will be upset because they will say "I paid 20,000 gas for an SSTORE" but I only got 360 days of stipend. If I paid for the rent directly I would have gotten enough rent to last until the Sun explodes." I acknowledge this complaint and do not think it is sufficient to warrant dismissing this proposal.
|
||||
|
||||
Q: There is a finite-ish amount of Ether and this proposal introduces a word-price in Ether, do math for me. A: The current size of Ethereum is about ~1 TB, maybe half of that is branch nodes. So that's like 15B words. There is about 100M Ether mined. The answer is that all the Ether can be spent on 400,000 terabyte-years of storage. I'm not sure if it is helpful to look at it that way.
|
||||
|
||||
# Backwards compatibility
|
||||
|
||||
There is a 360-day transition period (related to the RENT_STIPEND). This requires a hard fork. On the block of the fork, every account is immediately funded with enough rent to pay for ~ 360 days' worth of their current storage requirements. The formal implementation is that this new rule is applied if any existing account has σ[account]_rentLastPaid = 0. Therefore this can be implemented by clients lazily or eagerly.
|
||||
|
||||
Preexisting accounts which increase their storage needs will evict sooner than 360 days.
|
||||
|
||||
Users will need to be educated.
|
||||
|
||||
# Test Cases
|
||||
|
||||
TO BE ADDED
|
||||
|
||||
# Implementation
|
||||
|
||||
TO BE ADDED
|
||||
|
||||
# Copyright
|
||||
|
||||
Copyright and related rights waived via CC0.
|
|
@ -106,7 +106,7 @@ function textFor(bytes32 _code) external view returns (bool _wasFound, string _t
|
|||
|
||||
### String Format
|
||||
|
||||
All strings MUST be encoded as [UTF-8](http://www.ietf.org/rfc/rfc3629.txt).
|
||||
All strings MUST be encoded as [UTF-8](https://www.ietf.org/rfc/rfc3629.txt).
|
||||
|
||||
```solidity
|
||||
"Špeĉiäl chârãçtérs are permitted"
|
||||
|
@ -117,7 +117,7 @@ All strings MUST be encoded as [UTF-8](http://www.ietf.org/rfc/rfc3629.txt).
|
|||
|
||||
### Templates
|
||||
|
||||
Template strings are allowed, and MUST follow the [ANSI C `printf`](http://pubs.opengroup.org/onlinepubs/009696799/utilities/printf.html) conventions.
|
||||
Template strings are allowed, and MUST follow the [ANSI C `printf`](https://pubs.opengroup.org/onlinepubs/009696799/utilities/printf.html) conventions.
|
||||
|
||||
```solidity
|
||||
"Satoshi's true identity is %s"
|
||||
|
@ -155,7 +155,7 @@ A very viable alternative is to store text off chain, with a pointer to the tran
|
|||
|
||||
UTF-8 is the most widely used encoding at time of writing. It contains a direct embedding of ASCII, while providing characters for most natural languages, emoji, and special characters.
|
||||
|
||||
Please see the [UTF-8 Everywhere Manifesto](http://utf8everywhere.org/) for more information.
|
||||
Please see the [UTF-8 Everywhere Manifesto](https://utf8everywhere.org/) for more information.
|
||||
|
||||
### When No Text is Found
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
---
|
||||
eip: 145
|
||||
title: Bitwise shifting instructions in EVM
|
||||
author: Alex Beregszaszi (@axic), Paweł Bylica
|
||||
author: Alex Beregszaszi (@axic), Paweł Bylica (@chfast)
|
||||
type: Standards Track
|
||||
category: Core
|
||||
status: Accepted
|
||||
status: Final
|
||||
created: 2017-02-13
|
||||
---
|
||||
|
||||
|
@ -18,7 +18,7 @@ Native bitwise shifting instructions are introduced, which are more efficient pr
|
|||
|
||||
## Motivation
|
||||
|
||||
EVM is lacking bitwise shifting operators, but supports other logical and arithmetic operators. Shift operations can be implemented via arithmetic operators, but that has a higher cost and requires more processing time from the host. Implementing `SHL` and `SHR` using arithmetics cost each 35 gas, while the proposed instructions take 3 gas.
|
||||
EVM is lacking bitwise shifting operators, but supports other logical and arithmetic operators. Shift operations can be implemented via arithmetic operators, but that has a higher cost and requires more processing time from the host. Implementing `SHL` and `SHR` using arithmetic cost each 35 gas, while the proposed instructions take 3 gas.
|
||||
|
||||
## Specification
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ For compliance reasons, the `ERC-1450` constructor must specify the issuer (the
|
|||
### ERC-20 Extension
|
||||
`ERC-20` tokens provide the following functionality:
|
||||
|
||||
```
|
||||
```solidity
|
||||
contract ERC20 {
|
||||
function totalSupply() public view returns (uint256);
|
||||
function balanceOf(address who) public view returns (uint256);
|
||||
|
@ -67,7 +67,7 @@ contract ERC20 {
|
|||
|
||||
`ERC-20` is extended as follows:
|
||||
|
||||
```
|
||||
```solidity
|
||||
/**
|
||||
* ERC-1450 is an ERC-20 compatible token that facilitates compliance with one or more of Securities Act Regulations CF, D and A.
|
||||
*
|
||||
|
@ -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 faciliate 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)](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.
|
||||
|
||||
## Backwards Compatibility
|
||||
`ERC-1450` maintains compatibility with ERC-20 tokens with the following stipulations:
|
||||
|
|
138
EIPS/eip-1459.md
138
EIPS/eip-1459.md
|
@ -12,8 +12,8 @@ discussions-to: https://github.com/ethereum/devp2p/issues/50
|
|||
|
||||
# Abstract
|
||||
|
||||
This document describes a scheme for authenticated, updateable Ethereum node lists
|
||||
retrievable via DNS.
|
||||
This document describes a scheme for authenticated, updateable Ethereum node
|
||||
lists retrievable via DNS.
|
||||
|
||||
# Motivation
|
||||
|
||||
|
@ -24,86 +24,104 @@ maintain larger node lists containing hundreds of nodes, and update them
|
|||
regularly.
|
||||
|
||||
The scheme described here is a replacement for client bootstrap node lists with
|
||||
equivalent security and many additional benefits. DNS node lists may also be
|
||||
useful to Ethereum peering providers because their customers can configure the
|
||||
client to use the provider's list. Finally, the scheme serves as a fallback
|
||||
option for nodes which can't join the node discovery DHT.
|
||||
equivalent security and many additional benefits. Large lists populated by
|
||||
traversing the node discovery DHT can serve as a fallback option for nodes which
|
||||
can't join the DHT due to restrictive network policy. DNS-based node lists may
|
||||
also be useful to Ethereum peering providers because their customers can
|
||||
configure the client to use the provider's list.
|
||||
|
||||
# Specification
|
||||
|
||||
### DNS Record Structure
|
||||
A 'node list' is a list of [node records](eip-778) 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
|
||||
in order to verify the list.
|
||||
|
||||
Node lists are encoded as TXT records. The records form a merkle tree. The root
|
||||
of the tree is a record with content:
|
||||
To refer to a DNS node list, clients use a URL with 'enrtree' scheme. The URL
|
||||
contains the DNS name on which the list can be found as well as the public key
|
||||
that signed the list. The public key is contained in the username part of the
|
||||
URL and is the base32 encoding of the compressed 32-byte binary public key.
|
||||
|
||||
enrtree-root=v1 hash=<roothash> seq=<seqnum> sig=<signature>
|
||||
Example:
|
||||
|
||||
`roothash` is the abbreviated root hash of the tree in base32 encoding. `seqnum`
|
||||
is the tree's update sequence number, a decimal integer. `signature` is a
|
||||
65-byte secp256k1 EC signature over the keccak256 hash of the record content,
|
||||
encoded as URL-safe base64.
|
||||
enrtree://AM5FCQLWIZX2QFPNJAP7VUERCCRNGRHWZG3YYHIUV7BVDQ5FDPRT2@nodes.example.org
|
||||
|
||||
This URL refers to a node list at the DNS name 'nodes.example.org' and is signed
|
||||
by the public key
|
||||
`0x049f88229042fef9200246f49f94d9b77c4e954721442714e85850cb6d9e5daf2d880ea0e53cb3ac1a75f9923c2726a4f941f7d326781baa6380754a360de5c2b6`
|
||||
|
||||
## DNS Record Structure
|
||||
|
||||
The nodes in a list are encoded as a merkle tree for distribution via the DNS
|
||||
protocol. Entries of the merkle tree are contained in DNS TXT records. The root
|
||||
of the tree is a TXT record with the following content:
|
||||
|
||||
enrtree-root:v1 e=<enr-root> l=<link-root> seq=<sequence-number> sig=<signature>
|
||||
|
||||
where
|
||||
|
||||
- `enr-root` and `link-root` refer to the root hashes of subtrees containing
|
||||
nodes and links subtrees.
|
||||
- `sequence-number` is the tree's update sequence number, a decimal integer.
|
||||
- `signature` is a 65-byte secp256k1 EC signature over the keccak256 hash of the
|
||||
record content, excluding the `sig=` part, encoded as URL-safe base64.
|
||||
|
||||
Further TXT records on subdomains map hashes to one of three entry types. The
|
||||
subdomain name of any entry is the base32 encoding of the abbreviated keccak256
|
||||
hash of its text content.
|
||||
subdomain name of any entry is the base32 encoding of the (abbreviated)
|
||||
keccak256 hash of its text content.
|
||||
|
||||
- `enrtree=<h₁>,<h₂>,...,<hₙ>` is an intermediate tree containing further hash
|
||||
subdomains.
|
||||
- `enrtree-link=<key>@<fqdn>` is a leaf pointing to a different list located at
|
||||
another fully qualified domain name. The key is the expected signer of the
|
||||
remote list, a base32 encoded secp256k1 public key,
|
||||
- `enr=<node-record>` is a leaf containing a node record [as defined in EIP-778][eip-778].
|
||||
The node record is encoded as a URL-safe base64 string.
|
||||
- `enrtree-branch:<h₁>,<h₂>,...,<hₙ>` is an intermediate tree entry containing
|
||||
hashes of subtree entries.
|
||||
- `enrtree://<key>@<fqdn>` is a leaf pointing to a different list located at
|
||||
another fully qualified domain name. Note that this format matches the URL
|
||||
encoding. This type of entry may only appear in the subtree pointed to by
|
||||
`link-root`.
|
||||
- `enr:<node-record>` is a leaf containing a node record. The node record is
|
||||
encoded as a URL-safe base64 string. Note that this type of entry matches the
|
||||
canonical ENR text encoding. It may only appear in the `enr-root` subtree.
|
||||
|
||||
No particular ordering or structure is defined for the tree. Whenever the tree
|
||||
is updated, its sequence number should increase. The content of any TXT record
|
||||
should be small enough to fit into the 512 byte limit imposed on UDP DNS
|
||||
packets. This limits the number of hashes that can be placed into a `enrtree=`
|
||||
entry.
|
||||
packets. This limits the number of hashes that can be placed into an
|
||||
`enrtree-branch` entry.
|
||||
|
||||
Example in zone file format:
|
||||
|
||||
```text
|
||||
; name ttl class type content
|
||||
@ 60 IN TXT "enrtree-root=v1 hash=TO4Q75OQ2N7DX4EOOR7X66A6OM seq=3 sig=N-YY6UB9xD0hFx1Gmnt7v0RfSxch5tKyry2SRDoLx7B4GfPXagwLxQqyf7gAMvApFn_ORwZQekMWa_pXrcGCtwE="
|
||||
TO4Q75OQ2N7DX4EOOR7X66A6OM 86900 IN TXT "enrtree=F4YWVKW4N6B2DDZWFS4XCUQBHY,JTNOVTCP6XZUMXDRANXA6SWXTM,JGUFMSAGI7KZYB3P7IZW4S5Y3A"
|
||||
F4YWVKW4N6B2DDZWFS4XCUQBHY 86900 IN TXT "enr=-H24QI0fqW39CMBZjJvV-EJZKyBYIoqvh69kfkF4X8DsJuXOZC6emn53SrrZD8P4v9Wp7NxgDYwtEUs3zQkxesaGc6UBgmlkgnY0gmlwhMsAcQGJc2VjcDI1NmsxoQPKY0yuDUmstAHYpMa2_oxVtw0RW_QAdpzBQA8yWM0xOA=="
|
||||
JTNOVTCP6XZUMXDRANXA6SWXTM 86900 IN TXT "enr=-H24QDquAsLj8mCMzJh8ka2BhVFg3n4V9efBJBiaXHcoL31vRJJef-lAseMhuQBEVpM_8Zrin0ReuUXJE7Fs8jy9FtwBgmlkgnY0gmlwhMYzZGOJc2VjcDI1NmsxoQLtfC0F55K2s1egRhrc6wWX5dOYjqla-OuKCELP92O3kA=="
|
||||
JGUFMSAGI7KZYB3P7IZW4S5Y3A 86900 IN TXT "enrtree-link=AM5FCQLWIZX2QFPNJAP7VUERCCRNGRHWZG3YYHIUV7BVDQ5FDPRT2@morenodes.example.org"
|
||||
@ 60 IN TXT enrtree-root:v1 e=JWXYDBPXYWG6FX3GMDIBFA6CJ4 l=C7HRFPF3BLGF3YR4DY5KX3SMBE seq=1 sig=o908WmNp7LibOfPsr4btQwatZJ5URBr2ZAuxvK4UWHlsB9sUOTJQaGAlLPVAhM__XJesCHxLISo94z5Z2a463gA
|
||||
C7HRFPF3BLGF3YR4DY5KX3SMBE 86900 IN TXT enrtree://AM5FCQLWIZX2QFPNJAP7VUERCCRNGRHWZG3YYHIUV7BVDQ5FDPRT2@morenodes.example.org
|
||||
JWXYDBPXYWG6FX3GMDIBFA6CJ4 86900 IN TXT enrtree-branch:2XS2367YHAXJFGLZHVAWLQD4ZY,H4FHT4B454P6UXFD7JCYQ5PWDY,MHTDO6TMUBRIA2XWG5LUDACK24
|
||||
2XS2367YHAXJFGLZHVAWLQD4ZY 86900 IN TXT enr:-HW4QOFzoVLaFJnNhbgMoDXPnOvcdVuj7pDpqRvh6BRDO68aVi5ZcjB3vzQRZH2IcLBGHzo8uUN3snqmgTiE56CH3AMBgmlkgnY0iXNlY3AyNTZrMaECC2_24YYkYHEgdzxlSNKQEnHhuNAbNlMlWJxrJxbAFvA
|
||||
H4FHT4B454P6UXFD7JCYQ5PWDY 86900 IN TXT enr:-HW4QAggRauloj2SDLtIHN1XBkvhFZ1vtf1raYQp9TBW2RD5EEawDzbtSmlXUfnaHcvwOizhVYLtr7e6vw7NAf6mTuoCgmlkgnY0iXNlY3AyNTZrMaECjrXI8TLNXU0f8cthpAMxEshUyQlK-AM0PW2wfrnacNI
|
||||
MHTDO6TMUBRIA2XWG5LUDACK24 86900 IN TXT enr:-HW4QLAYqmrwllBEnzWWs7I5Ev2IAs7x_dZlbYdRdMUx5EyKHDXp7AV5CkuPGUPdvbv1_Ms1CPfhcGCvSElSosZmyoqAgmlkgnY0iXNlY3AyNTZrMaECriawHKWdDRk2xeZkrOXBQ0dfMFLHY4eENZwdufn1S1o
|
||||
```
|
||||
|
||||
### Referencing Trees by URL
|
||||
|
||||
When referencing a record tree, e.g. in source code, the preferred form is a
|
||||
URL. References should use the scheme `enrtree://` and encode the DNS domain in
|
||||
the hostname. The expected public key that signs the tree should be encoded in
|
||||
33-byte compressed form as a base32 string in the username portion of the URL.
|
||||
|
||||
Example:
|
||||
|
||||
```text
|
||||
enrtree://AP62DT7WOTEQZGQZOU474PP3KMEGVTTE7A7NPRXKX3DUD57TQHGIA@nodes.example.org
|
||||
```
|
||||
|
||||
### Client Protocol
|
||||
## Client Protocol
|
||||
|
||||
To find nodes at a given DNS name, say "mynodes.org":
|
||||
|
||||
1. Resolve the TXT record of the name and check whether it contains a valid
|
||||
"enrtree-root=v1" entry. Let's say the root hash contained in the entry is
|
||||
"CFZUWDU7JNQR4VTCZVOJZ5ROV4".
|
||||
2. Optionally verify the signature on the root against a known public key and
|
||||
check whether the sequence number is larger than or equal to any previous
|
||||
number seen for that name.
|
||||
3. Resolve the TXT record of the hash subdomain, e.g. "CFZUWDU7JNQR4VTCZVOJZ5ROV4.mynodes.org"
|
||||
and verify whether the content matches the hash.
|
||||
"enrtree-root=v1" entry. Let's say the `enr-root` hash contained in the entry
|
||||
is "CFZUWDU7JNQR4VTCZVOJZ5ROV4".
|
||||
2. Verify the signature on the root against the known public key and check
|
||||
whether the sequence number is larger than or equal to any previous number
|
||||
seen for that name.
|
||||
3. Resolve the TXT record of the hash subdomain, e.g.
|
||||
"CFZUWDU7JNQR4VTCZVOJZ5ROV4.mynodes.org" and verify whether the content
|
||||
matches the hash.
|
||||
4. The next step depends on the entry type found:
|
||||
- for `enrtree`: parse the list of hashes and continue resolving those (step 3).
|
||||
- for `enrtree-link`: continue traversal on the linked domain (step 1).
|
||||
- for `enrtree-branch`: parse the list of hashes and continue resolving them (step 3).
|
||||
- for `enr`: decode, verify the node record and import it to local node storage.
|
||||
|
||||
During traversal, the client should track hashes and domains which are already
|
||||
resolved to avoid going into an infinite loop.
|
||||
During traversal, the client must track hashes and domains which are already
|
||||
resolved to avoid going into an infinite loop. It's in the client's best
|
||||
interest to traverse the tree in random order.
|
||||
|
||||
Client implementations should avoid downloading the entire tree at once during
|
||||
normal operation. It's much better to request entries via DNS when-needed, i.e.
|
||||
at the time when the client is looking for peers.
|
||||
|
||||
# Rationale
|
||||
|
||||
|
@ -131,17 +149,23 @@ basic UDP DNS is available. The tree format also works well with caching
|
|||
resolvers: only the root of the tree needs a short TTL. Intermediate entries and
|
||||
leaves can be cached for days.
|
||||
|
||||
### Why does `enrtree-link` exist?
|
||||
### Why does the link subtree exist?
|
||||
|
||||
Links between lists enable federation and web-of-trust functionality. The
|
||||
operator of a large list can delegate maintenance to other list providers. If
|
||||
two node lists link to each other, users can use either list and get nodes from
|
||||
both.
|
||||
|
||||
The link subtree is separate from the tree containing ENRs. This is done to
|
||||
enable client implementations to sync these trees independently. A client
|
||||
wanting to get as many nodes as possible will sync the link tree first and add
|
||||
all linked names to the sync horizon.
|
||||
|
||||
# References
|
||||
|
||||
1. The base64 and base32 encodings used to represent binary data are defined in
|
||||
RFC 4648 (https://tools.ietf.org/html/rfc4648). No padding is used for base32.
|
||||
RFC 4648 (https://tools.ietf.org/html/rfc4648). No padding is used for base64
|
||||
and base32 data.
|
||||
|
||||
[eip-778]: https://eips.ethereum.org/EIPS/eip-778
|
||||
|
||||
|
|
|
@ -83,7 +83,7 @@ Each function must return a status code from the common set of Ethereum status c
|
|||
For both cases,
|
||||
|
||||
* It is required for guaranteed compatibility with ERC-20 and ERC-777 wallets that each checking function returns `0x11` (Allowed) if not overridden with the issuer's custom logic.
|
||||
* It is required that all overriden checking functions must revert if the action is not allowed or an error occured, according to the returned status code.
|
||||
* It is required that all overridden checking functions must revert if the action is not allowed or an error occurred, according to the returned status code.
|
||||
|
||||
Inside checker functions the logic is allowed to use any feature available on-chain: perform calls to registry contracts with whitelists/blacklists, use built-in checking logic that is defined on the same contract, or even run off-chain queries through an oracle.
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ The SWC in its most basic form links a numeric identifier to a weakness variant.
|
|||
|
||||
**SWC definition**
|
||||
|
||||
A SWC definition is formated in markdown to allow good readability and tools to process them easily. It consists of the following attributes.
|
||||
A SWC definition is formatted in markdown to allow good readability and tools to process them easily. It consists of the following attributes.
|
||||
|
||||
- Title: A name for the weakness that points to the technical root cause.
|
||||
- Relationships: Links a CWE _Base_ or _Class_ type to its CWE variant. The _Integer Overflow and Underflow_ variant for example is linked to [CWE-682 - Incorrect Calculation](https://cwe.mitre.org/data/definitions/682.html).
|
||||
|
@ -68,30 +68,43 @@ Test cases include crafted as well as real-world samples of vulnerable smart con
|
|||
|
||||
1. Source code of a smart contract sample; e.g. Solidity, Vyper, etc.
|
||||
2. Compiled asset from an EVM compiler in machine readable format; e.g. JSON or ethPM.
|
||||
3. Test result configuration that describes which and how many instances of a weakness variant can be found in a given sample. The YAML schema for the proposed test result configuration is listed below.
|
||||
3. Test result configuration that describes which and how many instances of a weakness variant can be found in a given sample. The YAML schema for the proposed test case configuration is listed below.
|
||||
|
||||
```YAML
|
||||
title: SWC config
|
||||
type: object
|
||||
required:
|
||||
- description
|
||||
- issues
|
||||
properties:
|
||||
description:
|
||||
type: string
|
||||
required: true
|
||||
issues:
|
||||
- id:
|
||||
title: Issues
|
||||
type: array
|
||||
items:
|
||||
title: Issue
|
||||
type: object
|
||||
required:
|
||||
- id
|
||||
- count
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
required: true
|
||||
count:
|
||||
type: number
|
||||
required: true
|
||||
locations:
|
||||
- bytecode_offsets:
|
||||
- type: number
|
||||
items:
|
||||
bytecode_offsets:
|
||||
type: object
|
||||
line_numbers:
|
||||
- type: number
|
||||
type: object
|
||||
```
|
||||
|
||||
## 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.-->
|
||||
|
||||
The Smart Contract Weakness Classification registry located in this [Github repository](https://github.com/SmartContractSecurity/SWC-registry) uses the SWC scheme proposed in this EIP. A Github Pages rendered version is also available [here](https://smartcontractsecurity.github.io/SWC-registry/).
|
||||
The Smart Contract Weakness Classification registry located in this [GitHub repository](https://github.com/SmartContractSecurity/SWC-registry) uses the SWC scheme proposed in this EIP. A GitHub Pages rendered version is also available [here](https://smartcontractsecurity.github.io/SWC-registry/).
|
||||
|
||||
## Copyright
|
||||
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -74,14 +74,14 @@ A `Resolver` is any smart contract that encodes information which resolves to an
|
|||
### Recovery
|
||||
If users lose control over an `Associated Address`, the `Recovery Address` provides a fallback mechanism. Upon `Identity` creation, a `Recovery Address` is passed as a parameter by the creator. Recovery functionality is triggered in three scenarios:
|
||||
|
||||
**1. Changing Recovery Address**: If a recovery key is lost, an `Associated Address`/`Provider` can [triggerRecoveryAddressChange](#triggerRecoveryAddressChange)/[triggerRecoveryAddressChangeFor](#triggerRecoveryAddressChangeFor). To prevent malicious behavior from someone who has gained control of an `Associated Address` or `Provider` and is changing the `Recovery Address` to one under their control, this action triggers a 14 day challenge period during which the old `Recovery Address` may reject the change by [triggering recovery](#triggerRecovery). If the `Recovery Address` does not reject the change within 14 days, the `Recovery Address` is changed.
|
||||
**1. Changing Recovery Address**: If a recovery key is lost, an `Associated Address`/`Provider` can [triggerRecoveryAddressChange](#triggerrecoveryaddresschange)/[triggerRecoveryAddressChangeFor](#triggerrecoveryaddresschangefor). To prevent malicious behavior from someone who has gained control of an `Associated Address` or `Provider` and is changing the `Recovery Address` to one under their control, this action triggers a 14 day challenge period during which the old `Recovery Address` may reject the change by [triggering recovery](#triggerrecovery). If the `Recovery Address` does not reject the change within 14 days, the `Recovery Address` is changed.
|
||||
|
||||
**2. Recovery**: Recovery occurs when a user recognizes that an `Associated Address` or the `Recovery Address` belonging to the user is lost or stolen. In this instance the `Recovery Address` must call [triggerRecovery](#triggerRecovery). This removes all `Associated Addresses` and `Providers` from the corresponding `Identity` and replaces them with an address passed in the function call. The `Identity` and associated `Resolvers` maintain integrity. The user is now responsible for adding the appropriate un-compromised addresses back to their `Identity`.
|
||||
**2. Recovery**: Recovery occurs when a user recognizes that an `Associated Address` or the `Recovery Address` belonging to the user is lost or stolen. In this instance the `Recovery Address` must call [triggerRecovery](#triggerrecovery). This removes all `Associated Addresses` and `Providers` from the corresponding `Identity` and replaces them with an address passed in the function call. The `Identity` and associated `Resolvers` maintain integrity. The user is now responsible for adding the appropriate un-compromised addresses back to their `Identity`.
|
||||
|
||||
*Importantly, the `Recovery Address` can be a user-controlled wallet or another address, such as a multisig wallet or smart contract. This allows for arbitrarily sophisticated recovery logic! This includes the potential for recovery to be fully compliant with standards such as [DID](https://decentralized.id/).*
|
||||
|
||||
**3. Destruction**
|
||||
The Recovery scheme offers considerable power to a `Recovery Address`; accordingly, `Destruction` is a nuclear option to combat malicious control over an `Identity` when a `Recovery Address` is compromised. If a malicious actor compromises a user's `Recovery Address` and triggers recovery, any address removed in the `Recovery` process can call [triggerDestruction](#triggerDestruction) within 14 days to permanently disable the `Identity`. The user would then need to create a new `Identity`, and would be responsible for engaging in recovery schemes for any identity applications built in the `Resolver` or `Provider` layers.
|
||||
The Recovery scheme offers considerable power to a `Recovery Address`; accordingly, `Destruction` is a nuclear option to combat malicious control over an `Identity` when a `Recovery Address` is compromised. If a malicious actor compromises a user's `Recovery Address` and triggers recovery, any address removed in the `Recovery` process can call [triggerDestruction](#triggerdestruction) within 14 days to permanently disable the `Identity`. The user would then need to create a new `Identity`, and would be responsible for engaging in recovery schemes for any identity applications built in the `Resolver` or `Provider` layers.
|
||||
|
||||
#### Alternative Recovery Considerations
|
||||
We considered many possible alternatives when devising the Recovery process outlined above. We ultimately selected the scheme that was most un-opinionated, modular, and consistent with the philosophy behind the `Associated Address`, `Provider`, and `Resolver` components. Still, we feel that it is important to highlight some of the other recovery options we considered, to provide a rationale as to how we settled on what we did.
|
||||
|
@ -179,7 +179,7 @@ Triggers event: [IdentityCreated](#identitycreated)
|
|||
|
||||
#### createIdentityDelegated
|
||||
|
||||
Preforms the same logic as `createIdentity`, but can be called by any address. This function requires a signature from the `associatedAddress` to ensure their consent.
|
||||
Performs the same logic as `createIdentity`, but can be called by any address. This function requires a signature from the `associatedAddress` to ensure their consent.
|
||||
|
||||
```solidity
|
||||
function createIdentityDelegated(
|
||||
|
@ -252,7 +252,7 @@ Triggers event: [ProviderAdded](#provideradded)
|
|||
|
||||
#### addProvidersFor
|
||||
|
||||
Preforms the same logic as `addProviders`, but must be called by a `Provider`.
|
||||
Performs the same logic as `addProviders`, but must be called by a `Provider`.
|
||||
|
||||
```solidity
|
||||
function addProvidersFor(uint ein, address[] memory providers) public;
|
||||
|
@ -273,7 +273,7 @@ Triggers event: [ProviderRemoved](#providerremoved)
|
|||
|
||||
#### removeProvidersFor
|
||||
|
||||
Preforms the same logic as `removeProviders`, but is called by a `Provider`.
|
||||
Performs the same logic as `removeProviders`, but is called by a `Provider`.
|
||||
|
||||
```solidity
|
||||
function removeProvidersFor(uint ein, address[] memory providers) public;
|
||||
|
@ -294,7 +294,7 @@ Triggers event: [ResolverAdded](#resolveradded)
|
|||
|
||||
#### addResolversFor
|
||||
|
||||
Preforms the same logic as `addResolvers`, but must be called by a `Provider`.
|
||||
Performs the same logic as `addResolvers`, but must be called by a `Provider`.
|
||||
|
||||
```solidity
|
||||
function addResolversFor(uint ein, address[] memory resolvers) public;
|
||||
|
@ -314,7 +314,7 @@ Triggers event: [ResolverRemoved](#resolverremoved)
|
|||
|
||||
#### removeResolversFor
|
||||
|
||||
Preforms the same logic as `removeResolvers`, but must be called by a `Provider`.
|
||||
Performs the same logic as `removeResolvers`, but must be called by a `Provider`.
|
||||
|
||||
```solidity
|
||||
function removeResolversFor(uint ein, address[] memory resolvers) public;
|
||||
|
@ -330,7 +330,7 @@ Initiates a change in the current `recoveryAddress` for the `EIN` of the `msg.se
|
|||
function triggerRecoveryAddressChange(address newRecoveryAddress) public;
|
||||
```
|
||||
|
||||
Triggers event: [RecoveryAddressChangeTriggered](#RecoveryAddressChangeTriggered)
|
||||
Triggers event: [RecoveryAddressChangeTriggered](#recoveryaddresschangetriggered)
|
||||
|
||||
#### triggerRecoveryAddressChangeFor
|
||||
|
||||
|
@ -340,7 +340,7 @@ Initiates a change in the current `recoveryAddress` for a given `EIN`.
|
|||
function triggerRecoveryAddressChangeFor(uint ein, address newRecoveryAddress) public;
|
||||
```
|
||||
|
||||
Triggers event: [RecoveryAddressChangeTriggered](#RecoveryAddressChangeTriggered)
|
||||
Triggers event: [RecoveryAddressChangeTriggered](#recoveryaddresschangetriggered)
|
||||
|
||||
#### triggerRecovery
|
||||
|
||||
|
@ -350,7 +350,7 @@ Triggers `EIN` recovery from the current `recoveryAddress`, or the old `recovery
|
|||
function triggerRecovery(uint ein, address newAssociatedAddress, uint8 v, bytes32 r, bytes32 s, uint timestamp) public;
|
||||
```
|
||||
|
||||
Triggers event: [RecoveryTriggered](#RecoveryTriggered)
|
||||
Triggers event: [RecoveryTriggered](#recoverytriggered)
|
||||
|
||||
#### triggerDestruction
|
||||
|
||||
|
@ -361,7 +361,7 @@ function triggerDestruction(uint ein, address[] memory firstChunk, address[] mem
|
|||
public;
|
||||
```
|
||||
|
||||
Triggers event: [IdentityDestroyed](#IdentityDestroyed)
|
||||
Triggers event: [IdentityDestroyed](#identitydestroyed)
|
||||
|
||||
### Events
|
||||
|
||||
|
|
|
@ -0,0 +1,200 @@
|
|||
---
|
||||
eip: 1485
|
||||
title: TEthashV1
|
||||
author: trustfarm (KT Ahn - 안씨아저씨) <trustfarm.info@gmail.com>, trustfarm <cpplover@trustfarm.net>
|
||||
discussions-to: https://ethereum-magicians.org/t/anti-eth-asic-mining-eip-1488-pr/1807
|
||||
status: Draft
|
||||
type: Standards Track
|
||||
category: Core
|
||||
created: 2018-11-01
|
||||
---
|
||||
|
||||
## Simple Summary
|
||||
This EIP modifies ethash in order to break ASIC miners specialized for the current ethash mining algorithm.
|
||||
|
||||
## Abstract
|
||||
This EIP pursue "obsolete current ASIC miners" by modifying PoW algorithm in a very low risk manner and update to latest hash algorithm from deprecated FNV Hash algorithms.
|
||||
|
||||
Following TEthashV1 algorithm suggests safe transition of PoW algorithms and secure the FNV Algorithm in MIX Parts.
|
||||
|
||||
## Motivation
|
||||
Provide original Ethash proof of work verification with minimal set of changes by updating FNV0 algorithm
|
||||
|
||||
## Specification
|
||||
|
||||
#### 1. Reference materials on ETHASH FNV0
|
||||
|
||||
#### Where FNV Applied on ETHASH
|
||||
|
||||
- In [ETHASH](https://github.com/ethereum/wiki/wiki/Ethash) , FNV Hash is used on
|
||||
* 1) On data aggregation function, MIX parts.
|
||||
|
||||
* Ethash Algorithm
|
||||
|
||||
```
|
||||
Header + Nonce
|
||||
|
|
||||
Keccak
|
||||
|
|
||||
**[MIX 0]** --> **[DAG Page]**
|
||||
| |
|
||||
Mixing <--|
|
||||
...
|
||||
|
|
||||
**[Mix 63]**
|
||||
|
|
||||
|-----> Mix64 [Process] ---> Mix Digest [32B]
|
||||
```
|
||||
|
||||
* FNV used in DAG Generation
|
||||
and Mixing for random access or DAG Page.
|
||||
|
||||
#### 2. Current applied Ethash FNV hash implementation is deprecated now.
|
||||
|
||||
[FNV-0_hash (deprecated)](https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function#FNV-0_hash_(deprecated))
|
||||
|
||||
It is a simple way of hashing algorithm
|
||||
|
||||
```
|
||||
hash = 0
|
||||
for each byte_of_data to be hashed
|
||||
hash = hash × FNV_prime
|
||||
hash = hash XOR octet_of_data
|
||||
return hash
|
||||
```
|
||||
|
||||
When analysed FNV-0 , there's very weak [avalanche effect](https://simple.wikipedia.org/wiki/Avalanche_effect), when hash input changes on 1~2bits. refer [FNV-Analysis reference section](https://github.com/tao-foundation/FNV-Analysis#how-to-test-and-analysis-reference-test-code)
|
||||
|
||||
We need to research and apply newer FNV hash or short message hash algorithm.
|
||||
|
||||
#### 3. FNV1A hash algorithm description
|
||||
|
||||
Previous proposed algorithm based on FNV1 [EIP-1355](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1355.md)
|
||||
|
||||
There's a implementation that looks like "Missing Offset Bias" at **FNV1A**.
|
||||
|
||||
Quotation of [original algorithm FNV1A](https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function#FNV-1a_hash)
|
||||
```
|
||||
use hash offset
|
||||
FNV-1a hash
|
||||
The FNV-1a hash differs from the FNV-1 hash by only the order in which the multiply and XOR is performed:[8][10]
|
||||
|
||||
hash = FNV_offset_basis
|
||||
for each byte_of_data to be hashed
|
||||
hash = hash XOR byte_of_data
|
||||
hash = hash × FNV_prime
|
||||
return hash
|
||||
```
|
||||
|
||||
FNV_offset_basis and computation order change of xor and multiplication Makes one more xor and multiply computation, but more secure hash effects than FNV0.
|
||||
and make dispersion boundary condition (0, even number, ..) by using of Prime Number.
|
||||
|
||||
#### 4. Real Implementation for FNV1A
|
||||
|
||||
Consider real computation resources, in TEthashV1 uses hash byte_of_data to 4bytes aligned data.
|
||||
|
||||
In TETHashV1, Adapts fully follow the FNV1A implementation.
|
||||
|
||||
- TETHASHV1 FNV1A implementation
|
||||
|
||||
Following are reference implementation of FNV1A adapted in TETHashV1.
|
||||
|
||||
```cpp
|
||||
// Reference Pseudo c/cpp implementation
|
||||
|
||||
#define FNV_PRIME 0x01000193U
|
||||
#define FNV_OFFSET_BASIS 0x811c9dc5U
|
||||
|
||||
#define fnv1a(x, y) ((((FNV_OFFSET_BASIS^(x))*FNV_PRIME) ^ (y)) * FNV_PRIME)
|
||||
#define fnv1a_reduce(a,b,c,d) (fnv1a(fnv1a(fnv1a(a, b), c), d))
|
||||
```
|
||||
|
||||
Another Byte aligned implementation of FNV1A , call to FNV1c
|
||||
|
||||
```cpp
|
||||
#define FNV_PRIME 0x01000193U
|
||||
#define FNV_OFFSET_BASIS 0x811c9dc5U
|
||||
|
||||
#define fnv1i(x) ( (( (( (( \
|
||||
( ((FNV_OFFSET_BASIS)^( ((x)>>24)&0x000000ff )) * FNV_PRIME) \
|
||||
^ (((x)>>16 )&0x000000ff)) * FNV_PRIME) \
|
||||
^ (((x)>>8 )&0x000000ff)) * FNV_PRIME) \
|
||||
^ (((x) )&0x000000ff)) * FNV_PRIME) \
|
||||
)
|
||||
#define fnv1c(x, y) ((fnv1i(x) ^ (y)) * FNV_PRIME)
|
||||
```
|
||||
|
||||
#### 5. [FNV-Analysis](https://github.com/tao-foundation/FNV-Analysis)
|
||||
FNV Mix Algorithm Analysis for TEthashV1
|
||||
|
||||
#### How to test and analysis reference test code.
|
||||
|
||||
You can compile it with simple in terminal.
|
||||
No additional library needs,
|
||||
|
||||
```sh
|
||||
gcc -o fnvtest fnvcltest.c
|
||||
```
|
||||
|
||||
And You can execute it
|
||||
```
|
||||
fnvtest
|
||||
|
||||
F(00,00)::VEC(0, 0, ffffffff, 0):: FNV :00000000, DF=00000000(00) DS(00000000), FNV1 :00000000, DF=00000000(00) DS(00000000), FNV1a:117697cd, DF=117697cd(17) DS(117697cd), FNV1c:1210d00f, DF=127f8dbf(20) DS(11a1725f), F___RC=efe1b9c4, DF:efe1b9c4(19) , F1__RC=deb68dfe, DF:deb68dfe(22) , F1A_RC=99bad28b, DF:99bad28b(17) , F1C_RC=e29fa497, DF:e29fa497(18)
|
||||
F(00,01)::VEC(0, 1, ffffffff, 0):: FNV :00000001, DF=00000001(01) DS(00000001), FNV1 :01000193, DF=01000193(06) DS(01000193), FNV1a:1076963a, DF=010001f7(09) DS(01000193), FNV1c:1110ce7c, DF=03001e73(11) DS(01000193), F___RC=fefffe6d, DF:111e47a9(14) , F1__RC=d9fd8597, DF:074b0869(12) , F1A_RC=72c287e0, DF:eb78556b(19) , F1C_RC=6b6991ef, DF:89f63578(17)
|
||||
F(00,02)::VEC(0, 2, ffffffff, 0):: FNV :00000002, DF=00000003(02) DS(00000001), FNV1 :02000326, DF=030002b5(08) DS(01000193), FNV1a:0f7694a7, DF=1f00029d(11) DS(01000193), FNV1c:1410d335, DF=05001d49(09) DS(030004b9), F___RC=d8fd8404, DF:26027a69(13) , F1__RC=9b16d24c, DF:42eb57db(19) , F1A_RC=c17f0ecb, DF:b3bd892b(18) , F1C_RC=a5be8e78, DF:ced71f97(21)
|
||||
F(00,03)::VEC(0, 3, ffffffff, 0):: FNV :00000003, DF=00000001(01) DS(00000001), FNV1 :030004b9, DF=0100079f(10) DS(01000193), FNV1a:0e769314, DF=010007b3(09) DS(01000193), FNV1c:1310d1a2, DF=07000297(09) DS(01000193), F___RC=b2fb099b, DF:6a068d9f(16) , F1__RC=5c301f01, DF:c726cd4d(17) , F1A_RC=94cf402e, DF:55b04ee5(16) , F1C_RC=aea1a025, DF:0b1f2e5d(17)
|
||||
F(00,04)::VEC(0, 4, ffffffff, 0):: FNV :00000004, DF=00000007(03) DS(00000001), FNV1 :0400064c, DF=070002f5(10) DS(01000193), FNV1a:0d769181, DF=03000295(07) DS(01000193), FNV1c:0e10c9c3, DF=1d001861(09) DS(050007df), F___RC=8cf88f32, DF:3e0386a9(14) , F1__RC=1d496bb6, DF:417974b7(17) , F1A_RC=89401d59, DF:1d8f5d77(20) , F1C_RC=e4e96c7c, DF:4a48cc59(13)
|
||||
F(00,05)::VEC(0, 5, ffffffff, 0):: FNV :00000005, DF=00000001(01) DS(00000001), FNV1 :050007df, DF=01000193(06) DS(01000193), FNV1a:0c768fee, DF=01001e6f(11) DS(01000193), FNV1c:0d10c830, DF=030001f3(09) DS(01000193), F___RC=66f614c9, DF:ea0e9bfb(20) , F1__RC=de62b86b, DF:c32bd3dd(19) , F1A_RC=346e222c, DF:bd2e3f75(21) , F1C_RC=502e5f82, DF:b4c733fe(20)
|
||||
F(00,06)::VEC(0, 6, ffffffff, 0):: FNV :00000006, DF=00000003(02) DS(00000001), FNV1 :06000972, DF=03000ead(10) DS(01000193), FNV1a:0b768e5b, DF=070001b5(09) DS(01000193), FNV1c:1010cce9, DF=1d0004d9(10) DS(030004b9), F___RC=40f39a60, DF:26058ea9(13) , F1__RC=9f7c0520, DF:411ebd4b(16) , F1A_RC=b376a527, DF:8718870b(13) , F1C_RC=1241a9a4, DF:426ff626(17)
|
||||
F(00,07)::VEC(0, 7, ffffffff, 0):: FNV :00000007, DF=00000001(01) DS(00000001), FNV1 :07000b05, DF=01000277(08) DS(01000193), FNV1a:0a768cc8, DF=01000293(06) DS(01000193), FNV1c:0f10cb56, DF=1f0007bf(15) DS(01000193), F___RC=1af11ff7, DF:5a028597(13) , F1__RC=609551d5, DF:ffe954f5(22) , F1A_RC=14293bea, DF:a75f9ecd(21) , F1C_RC=49d34bba, DF:5b92e21e(16)
|
||||
F(00,08)::VEC(0, 8, ffffffff, 0):: FNV :00000008, DF=0000000f(04) DS(00000001), FNV1 :08000c98, DF=0f00079d(12) DS(01000193), FNV1a:09768b35, DF=030007fd(12) DS(01000193), FNV1c:1a10dca7, DF=150017f1(12) DS(0b001151), F___RC=f4eea58e, DF:ee1fba79(21) , F1__RC=21ae9e8a, DF:413bcf5f(19) , F1A_RC=eeebb7a5, DF:fac28c4f(17) , F1C_RC=7da04f47, DF:347304fd(16)
|
||||
F(00,09)::VEC(0, 9, ffffffff, 0):: FNV :00000009, DF=00000001(01) DS(00000001), FNV1 :09000e2b, DF=010002b3(07) DS(01000193), FNV1a:087689a2, DF=01000297(07) DS(01000193), FNV1c:1910db14, DF=030007b3(10) DS(01000193), F___RC=ceec2b25, DF:3a028eab(14) , F1__RC=e2c7eb3f, DF:c36975b5(18) , F1A_RC=54e1aef8, DF:ba0a195d(15) , F1C_RC=d425e1af, DF:a985aee8(16)
|
||||
F(00,0a)::VEC(0, a, ffffffff, 0):: FNV :0000000a, DF=00000003(02) DS(00000001), FNV1 :0a000fbe, DF=03000195(07) DS(01000193), FNV1a:0776880f, DF=0f0001ad(10) DS(01000193), FNV1c:1c10dfcd, DF=050004d9(08) DS(030004b9), F___RC=a8e9b0bc, DF:66059b99(15) , F1__RC=a3e137f4, DF:4126dccb(15) , F1A_RC=213fcd63, DF:75de639b(20) , F1C_RC=7e1d2751, DF:aa38c6fe(18)
|
||||
F(00,0b)::VEC(0, b, ffffffff, 0):: FNV :0000000b, DF=00000001(01) DS(00000001), FNV1 :0b001151, DF=01001eef(12) DS(01000193), FNV1a:0676867c, DF=01000e73(09) DS(01000193), FNV1c:1b10de3a, DF=070001f7(11) DS(01000193), F___RC=82e73653, DF:2a0e86ef(16) , F1__RC=64fa84a9, DF:c71bb35d(19) , F1A_RC=5598ce46, DF:74a70325(14) , F1C_RC=6400c630, DF:1a1de161(14)
|
||||
F(00,0c)::VEC(0, c, ffffffff, 0):: FNV :0000000c, DF=00000007(03) DS(00000001), FNV1 :0c0012e4, DF=070003b5(10) DS(01000193), FNV1a:057684e9, DF=03000295(07) DS(01000193), FNV1c:1610d65b, DF=0d000861(07) DS(050007df), F___RC=5ce4bbea, DF:de038db9(17) , F1__RC=2613d15e, DF:42e955f7(18) , F1A_RC=6a220ff1, DF:3fbac1b7(20) , F1C_RC=6e781da4, DF:0a78db94(15)
|
||||
F(00,0d)::VEC(0, d, ffffffff, 0):: FNV :0000000d, DF=00000001(01) DS(00000001), FNV1 :0d001477, DF=01000693(07) DS(01000193), FNV1a:04768356, DF=010007bf(11) DS(01000193), FNV1c:1510d4c8, DF=03000293(07) DS(01000193), F___RC=36e24181, DF:6a06fa6b(17) , F1__RC=e72d1e13, DF:c13ecf4d(18) , F1A_RC=168d4944, DF:7caf46b5(19) , F1C_RC=65bbcfa1, DF:0bc3d205(13)
|
||||
F(00,0e)::VEC(0, e, ffffffff, 0):: FNV :0000000e, DF=00000003(02) DS(00000001), FNV1 :0e00160a, DF=0300027d(09) DS(01000193), FNV1a:037681c3, DF=07000295(08) DS(01000193), FNV1c:1810d981, DF=0d000d49(09) DS(030004b9), F___RC=10dfc718, DF:263d8699(15) , F1__RC=a8466ac8, DF:4f6b74db(20) , F1A_RC=93e667bf, DF:856b2efb(19) , F1C_RC=76f80ee3, DF:1343c142(11)
|
||||
F(00,0f)::VEC(0, f, ffffffff, 0):: FNV :0000000f, DF=00000001(01) DS(00000001), FNV1 :0f00179d, DF=01000197(07) DS(01000193), FNV1a:02768030, DF=010001f3(08) DS(01000193), FNV1c:1710d7ee, DF=0f000e6f(13) DS(01000193), F___RC=eadd4caf, DF:fa028bb7(17) , F1__RC=695fb77d, DF:c119ddb5(17) , F1A_RC=0f485682, DF:9cae313d(17) , F1C_RC=3667e8dc, DF:409fe63f(18)
|
||||
F(00,10)::VEC(0, 10, ffffffff, 0):: FNV :00000010, DF=0000001f(05) DS(00000001), FNV1 :10001930, DF=1f000ead(13) DS(01000193), FNV1a:01767e9d, DF=0300fead(14) DS(01000193), FNV1c:0210b6df, DF=15006131(09) DS(1500210f), F___RC=c4dad246, DF:2e079ee9(17) , F1__RC=2a790432, DF:4326b34f(16) , F1A_RC=d10adebd, DF:de42883f(16) , F1C_RC=1ce48e12, DF:2a8366ce(15)
|
||||
```
|
||||
|
||||
`F(00,01)` : is input x,y
|
||||
|
||||
`VEC(0, 1, ffffffff, 0)` : is `fnv_reduce` input vector (a,b,c,d)
|
||||
|
||||
`FNV :00000001, DF=00000001(01) DS(00000001)` :
|
||||
* `FNV(00,01)` result is 00000001 ,
|
||||
* `DF` : is changed bitcounts, compared with previous outputs, in this case prev[00,00] current[00,01] input is 1bit changed, and output result 1bit changed.
|
||||
* `DS` : is distances of previous result and current result , ABS(prev_fnvresult,current_fnvresult).
|
||||
|
||||
** Basically, `DF` is higher is best on hash algorithm.
|
||||
|
||||
`F___RC=fefffe6d, DF:111e47a9(14)` : `fnv_reduce = fnv(fnv(fnv(a,b),c),d) ` result is fefffe6d , and Different Bits counts are `14` bits.
|
||||
|
||||
|
||||
## Rationale
|
||||
|
||||
In case of ethash algorithm, it can't prevent ASIC forever.
|
||||
|
||||
And, current ethash algorithm's FNV function is deprecated.
|
||||
|
||||
So, It needs to be upgraded and it will make current ethash based ASICs obsolete.
|
||||
|
||||
And current TETHASHV1 FNV1A implementation is based on most of ethash , which is verified for a long time.
|
||||
|
||||
Another propose of big differencing the Ethash algorithm need to crypto analysis for a long times and need to GPU code optimization times.
|
||||
|
||||
**Verification and Optimization timeline Examples**
|
||||
|
||||
original ethminer (2015) -> claymore optimized miner (2016) [1year]
|
||||
|
||||
genoil ethminer (2015) -> ethereum-mining/ethminer (2017) [2year]
|
||||
|
||||
## Test Results::
|
||||
|
||||
Tethash miner has 2~3% of hashrate degrade on GPU, due to more core computation time.
|
||||
|
||||
## Copyright
|
||||
|
||||
This work is licensed under a [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-nc-sa/4.0/).
|
|
@ -18,7 +18,7 @@ A standard interface for Human Capital Accounting tokens.
|
|||
|
||||
## Abstract
|
||||
<!--A short (~200 word) description of the technical issue being addressed.-->
|
||||
The following standard allows for the implementation of a standard API for HUCAP tokens within smart contracts. This standard provides basic functionality to discover, track and transfer the motivational hierarchy of human resources. While blockchain architecture has suceeded in the financialisation of integrity by way of transparency; correspondingly real world outcomes will be proportional to the degree of individualisation of capital by way of knowledge.
|
||||
The following standard allows for the implementation of a standard API for HUCAP tokens within smart contracts. This standard provides basic functionality to discover, track and transfer the motivational hierarchy of human resources. While blockchain architecture has succeeded in the financialisation of integrity by way of transparency; correspondingly real world outcomes will be proportional to the degree of individualisation of capital by way of knowledge.
|
||||
|
||||
## 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.-->
|
||||
|
@ -41,7 +41,7 @@ The BDI software model is an attempt to solve a problem of plans and planning ch
|
|||
|
||||
|
||||
#### Main Interface
|
||||
```
|
||||
```solidity
|
||||
pragma solidity ^0.4.25;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
|
@ -327,7 +327,7 @@ interface IERC_HUCAP {
|
|||
|
||||
<!--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)).-->
|
||||
|
||||
```
|
||||
```solidity
|
||||
|
||||
interface IERC_HUCAP_TYPES {
|
||||
|
||||
|
@ -359,7 +359,7 @@ interface IERC_HUCAP_TYPES {
|
|||
|
||||
<!--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)).-->
|
||||
|
||||
```
|
||||
```solidity
|
||||
pragma solidity ^0.4.25;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
|
@ -425,21 +425,21 @@ interface IERC_HUCAP_KEYSIGNING_EXTENSION {
|
|||
/**
|
||||
/// @notice Cycle through state transition of an Agent in the ecosystem.
|
||||
/// @param _address toggle on/off a doer agent
|
||||
// @dev `anybody` can retrive the talent data in the contract
|
||||
// @dev `anybody` can retrieve the talent data in the contract
|
||||
*/
|
||||
function flipTo(address _address) external onlyOwner returns (IS);
|
||||
|
||||
/**
|
||||
/// @notice Turn Agent in the ecosystem to on/off.
|
||||
/// @param _address toggle on/off a doer agent
|
||||
// @dev `anybody` can retrive the talent data in the contract
|
||||
// @dev `anybody` can retrieve the talent data in the contract
|
||||
*/
|
||||
function toggle(address _address) external onlyOwner returns (bool);
|
||||
|
||||
/**
|
||||
/// @notice Set the trust level of an Agent in the ecosystem.
|
||||
/// @param _level toggle on/off a doer agent
|
||||
// @dev `anybody` can retrive the talent data in the contract
|
||||
// @dev `anybody` can retrieve the talent data in the contract
|
||||
*/
|
||||
function trust(Trust _level) returns (bytes32 Trust);
|
||||
|
||||
|
@ -451,72 +451,72 @@ interface IERC_HUCAP_KEYSIGNING_EXTENSION {
|
|||
```
|
||||
#### Human Capital Accounting Extension Interface
|
||||
|
||||
```
|
||||
```solidity
|
||||
pragma solidity ^0.4.25;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
interface IERC_HUCAP_TRACKUSERS_EXTENSION {
|
||||
|
||||
/// @notice Instatiate an Agent in the ecosystem with default data.
|
||||
/// @notice Instantiate an Agent in the ecosystem with default data.
|
||||
/// @param _address initialise a doer agent
|
||||
// @dev `anybody` can retrive the talent data in the contract
|
||||
// @dev `anybody` can retrieve the talent data in the contract
|
||||
function initAgent(Doers _address) external onlyControlled returns (bool);
|
||||
|
||||
/// @notice Get the data by uuid of an Agent in the ecosystem.
|
||||
/// @param _uuid Get the address of a unique uid
|
||||
// @dev `anybody` can retrive the talent data in the contract
|
||||
// @dev `anybody` can retrieve the talent data in the contract
|
||||
function getAgent(bytes32 _uuid) view external returns (address);
|
||||
|
||||
/// @notice Get the data of all Talents in the ecosystem.
|
||||
/// @param _address Query if address belongs to an agent
|
||||
// @dev `anybody` can retrive the talent data in the contract
|
||||
// @dev `anybody` can retrieve the talent data in the contract
|
||||
function iam(address _address) view public returns (bool);
|
||||
|
||||
/// @notice Get the data of all Talents in the ecosystem.
|
||||
/// @param _address Query if address belongs to a doer
|
||||
// @dev `anybody` can retrive the talent data in the contract
|
||||
// @dev `anybody` can retrieve the talent data in the contract
|
||||
function isDoer(address _address) view public returns (IS);
|
||||
|
||||
/// @notice Get the number of doers that can be spawned by a Creators.
|
||||
/// The query condition of the contract
|
||||
// @dev `anybody` can retrive the count data in the contract
|
||||
// @dev `anybody` can retrieve the count data in the contract
|
||||
function getAgent(address _address)
|
||||
view public returns (bytes32 keyid_, IS state_, bool active_, uint myDoers_);
|
||||
|
||||
/// @notice Get the data of all Talents in the ecosystem.
|
||||
/// @param _talent The talent whose frequency is being queried
|
||||
// @dev `anybody` can retrive the talent data in the contract
|
||||
// @dev `anybody` can retrieve the talent data in the contract
|
||||
function getTalents(bytes32 _talent)
|
||||
view external returns (uint talentK_, uint talentI_, uint talentR_, uint talentF_);
|
||||
|
||||
/// @notice Increment a kind of talent in the ecosystem.
|
||||
/// @param The talent whose frequency is being queried
|
||||
// @dev `anybody` can retrive the talent data in the contract
|
||||
// @dev `anybody` can retrieve the talent data in the contract
|
||||
function incTalent() payable public onlyDoer returns (bool);
|
||||
|
||||
/// @notice Decrement a kind of talent in the ecosystem..
|
||||
/// @param The talent whose frequency is being queried
|
||||
// @dev `anybody` can retrive the talent data in the contract
|
||||
// @dev `anybody` can retrieve the talent data in the contract
|
||||
function decTalent() payable public onlyDoer returns (bool);
|
||||
|
||||
/// @notice Set the Public-Key Id of an Agent in the ecosystem.
|
||||
/// @param _address Set the Public-key Id of an agent
|
||||
// @dev `anybody` can retrive the talent data in the contract
|
||||
// @dev `anybody` can retrieve the talent data in the contract
|
||||
function setAgent(address _address, bytes32 _keyId) external onlyControlled returns (bytes32);
|
||||
|
||||
/// @notice Transition the states of an Agent in the ecosystem.
|
||||
/// @param _address Set the stance of an agent
|
||||
// @dev `anybody` can retrive the talent data in the contract
|
||||
// @dev `anybody` can retrieve the talent data in the contract
|
||||
function setAgent(address _address, IS _state) external onlyControlled returns (IS);
|
||||
|
||||
/// @notice Set the active status of an Agent in the ecosystem.
|
||||
/// @param _address Toggle the true/false status of an agent
|
||||
// @dev `anybody` can retrive the talent data in the contract
|
||||
// @dev `anybody` can retrieve the talent data in the contract
|
||||
function setAgent(address _address, bool _active) external onlyControlled returns (bool);
|
||||
|
||||
/// @notice Set the data of all Intentions of Agents in the ecosystem.
|
||||
/// @param _serviceId Track number of offers available
|
||||
// @dev `anybody` can retrive the talent data in the contract
|
||||
// @dev `anybody` can retrieve the talent data in the contract
|
||||
function setAllPromises(bytes32 _serviceId) external onlyControlled;
|
||||
|
||||
/* End of interface IERC_HUCAP_TRACKUSERS_EXTENSION */
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
eip: 150
|
||||
title: Gas cost changes for IO-heavy operations
|
||||
author: Vitalik Buterin
|
||||
author: Vitalik Buterin (@vbuterin)
|
||||
type: Standards Track
|
||||
category: Core
|
||||
status: Final
|
||||
|
|
|
@ -0,0 +1,351 @@
|
|||
---
|
||||
eip: 1504
|
||||
title: ERC-1504 Upgradable Smart Contract
|
||||
author: Kaidong Wu <wukd94@pku.edu.cn>, Chuqiao Ren <cr025@bucknell.edu>, Ruthia He <rujiahe@gmail.com>, Yun Ma <mayun@pku.edu.cn>, Xuanzhe Liu <liuxuanzhe@pku.edu.cn>
|
||||
discussions-to: https://github.com/ethereum/EIPs/issues/1503
|
||||
status: Draft
|
||||
type: Standards Track
|
||||
category: ERC
|
||||
created: 2018-10-17
|
||||
---
|
||||
|
||||
## Simple Summary
|
||||
|
||||
A standard interface/guideline that makes a smart contract upgradable.
|
||||
|
||||
## Abstract
|
||||
|
||||
Ethereum smart contracts have suffered a number of security issues in the past few years. The cost of fixing such a bug in smart contract is significant; for example, the consequences of The DAO attack in June 2016 caused tremendous financial loss and the hard fork of Ethereum blockchain.
|
||||
|
||||
The following standard makes it possible to upgrade a standard API within smart contracts. This standard provides basic functionalities to upgrade the operations of the contract without data migration. To ensure the decentralization/community interests, it also contains a voting mechanism to control the upgrading process.
|
||||
|
||||
## Motivation
|
||||
|
||||
Smart contract is immutable after deployment. If any security risk is identified or program bug is detected, developers always have to destruct the old contract, deploy a new one and potentially migrate the data (hard fork) to the new contract. In some cases, deploying a smart contract with bugs and potential security vulnerabilities can cause a significant amount of financial loss.
|
||||
|
||||
We propose this upgradable contract to fix the current situation. With the upgradable contract, developers can deploy a new version of smart contract after previous deployment and retain the data at the same time.
|
||||
|
||||
For example, after an ERC20-compliant token contract is deployed, the users exploit a vulnerability in the source code. Without the support of upgradable contract, developers have to fix this issue by deploy a new, secured contract otherwise the attackers would take advantage of the security hole, which may cause a tremendous financial loss. A challenge is how to migrate data from the old contract to a new one. With the upgradable contract below, this will become relatively easy as developers only have to upgrade the Handler contract to fix bugs while the Data contract will remain the same.
|
||||
|
||||
## Specification
|
||||
|
||||
The upgradable contract consists of three parts:
|
||||
|
||||
- **Handler contract** (implements **Handler interface**) defines operations and provides services. This contract can be upgraded;
|
||||
- **Data contract** keeps the resources (data) and is controlled by the Handler contract;
|
||||
- **Upgrader contract (optional)** deals with the voting mechanism and upgrades the Handler contract. The voters are pre-defined by the contract owner.
|
||||
|
||||
> The following codes are exact copies of the [ERC-1504 Upgradable Smart Contract.](https://gist.github.com/swordghost/77c96a972106af6ec6ccea9c2d66e768)
|
||||
|
||||
### Handler contract and Handler interface
|
||||
|
||||
Functions of the Handler contract vary with requirements, so developers would better design interfaces for Handler contracts to limit them and make sure external applications are always supported.
|
||||
|
||||
Below is the specification of Handler interface. In the Handler interface we define the following actions:
|
||||
|
||||
- Initialize the Data contract;
|
||||
- Register the Upgrader contract address;
|
||||
- Destruct the Handler contract after upgrading is done;
|
||||
- Verify the current Handler is the working one → it should always return true.
|
||||
|
||||
Developers have to define their business-related functions as well.
|
||||
|
||||
|
||||
```solidity
|
||||
/// Handler interface.
|
||||
/// Handler defines business related functions.
|
||||
/// Use the interface to ensure that your external services are always supported.
|
||||
/// Because of function live(), we design IHandler as an abstract contract rather than a true interface.
|
||||
contract IHandler {
|
||||
|
||||
/// Initialize the data contarct.
|
||||
/// @param _str value of exmStr of Data contract.
|
||||
/// @param _int value of exmInt of Data contract.
|
||||
/// @param _array value of exmArray of Data contract.
|
||||
function initialize (string _str, uint256 _int, uint16 [] _array) public;
|
||||
|
||||
/// Register Upgrader contract address.
|
||||
/// @param _upgraderAddr address of the Upgrader contract.
|
||||
function registerUpgrader (address _upgraderAddr) external;
|
||||
|
||||
/// Upgrader contract calls this to check if it is registered.
|
||||
/// @return if the Upgrader contract is registered.
|
||||
function isUpgraderRegistered () external view returns(bool);
|
||||
|
||||
/// Handler has been upgraded so the original one has to self-destruct.
|
||||
function done() external;
|
||||
|
||||
/// Check if the Handler contract is a working Handler contract.
|
||||
/// It is used to prove the contract is a Handler contract.
|
||||
/// @return always true.
|
||||
function live() external pure returns(bool) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Functions - define functions here */
|
||||
|
||||
/** Events - add events here */
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
The process of deploying a Handler contract:
|
||||
|
||||
1. Deploy Data contract;
|
||||
2. Deploy a Handler contract at a given address specified in the Data contract;
|
||||
3. Register the Handler contract address by calling setHandler() in the Data contract, or use an Upgrader contract to switch the Handler contract, which requires that Data contract is initialized;
|
||||
4. Initialize Data contract if haven’t done it already.
|
||||
|
||||
### Data Contract
|
||||
|
||||
Below is the specification of Data contract. There are three parts in the Data contract:
|
||||
|
||||
- **Administrator Data**: owner’s address, Handler contract’s address and a boolean indicating whether the contract is initialized or not;
|
||||
- **Upgrader Data**: Upgrader contract’s address, upgrade proposal’s submission timestamp and proposal’s time period;
|
||||
- **Resource Data**: all other resources that the contract needs to keep and manage.
|
||||
|
||||
|
||||
```solidity
|
||||
/// Data Contract
|
||||
contract DataContract {
|
||||
|
||||
/** Management data */
|
||||
/// Owner and Handler contract
|
||||
address private owner;
|
||||
address private handlerAddr;
|
||||
|
||||
/// Ready?
|
||||
bool private valid;
|
||||
|
||||
/** Upgrader data */
|
||||
address private upgraderAddr;
|
||||
uint256 private proposalBlockNumber;
|
||||
uint256 private proposalPeriod;
|
||||
/// Upgrading status of the Handler contract
|
||||
enum UpgradingStatus {
|
||||
/// Can be upgraded
|
||||
Done,
|
||||
/// In upgrading
|
||||
InProgress,
|
||||
/// Another proposal is in progress
|
||||
Blocked,
|
||||
/// Expired
|
||||
Expired,
|
||||
/// Original Handler contract error
|
||||
Error
|
||||
}
|
||||
|
||||
/** Data resources - define variables here */
|
||||
|
||||
/** Modifiers */
|
||||
|
||||
/// Check if msg.sender is the Handler contract. It is used for setters.
|
||||
/// If fail, throw PermissionException.
|
||||
modifier onlyHandler;
|
||||
|
||||
/// Check if msg.sender is not permitted to call getters. It is used for getters (if necessary).
|
||||
/// If fail, throw GetterPermissionException.
|
||||
modifier allowedAddress;
|
||||
|
||||
/// Check if the contract is working.
|
||||
/// It is used for all functions providing services after initialization.
|
||||
/// If fail, throw UninitializationException.
|
||||
modifier ready;
|
||||
|
||||
/** Management functions */
|
||||
|
||||
/// Initializer. Just the Handler contract can call it.
|
||||
/// @param _str default value of this.exmStr.
|
||||
/// @param _int default value of this.exmInt.
|
||||
/// @param _array default value of this.exmArray.
|
||||
/// exception PermissionException msg.sender is not the Handler contract.
|
||||
/// exception ReInitializationException contract has been initialized.
|
||||
/// @return if the initialization succeeds.
|
||||
function initialize (string _str, uint256 _int, uint16 [] _array) external onlyHandler returns(bool);
|
||||
|
||||
/// Set Handler contract for the contract. Owner must set one to initialize the Data contract.
|
||||
/// Handler can be set by owner or Upgrader contract.
|
||||
/// @param _handlerAddr address of a deployed Handler contract.
|
||||
/// @param _originalHandlerAddr address of the original Handler contract, only used when an Upgrader contract want to set the Handler contract.
|
||||
/// exception PermissionException msg.sender is not the owner nor a registered Upgrader contract.
|
||||
/// exception UpgraderException Upgrader contract does not provide a right address of the original Handler contract.
|
||||
/// @return if Handler contract is successfully set.
|
||||
function setHandler (address _handlerAddr, address _originalHandlerAddr) external returns(bool);
|
||||
|
||||
/** Upgrader contract functions */
|
||||
|
||||
/// Register an Upgrader contract in the contract.
|
||||
/// If a proposal has not been accepted until proposalBlockNumber + proposalPeriod, it can be replaced by a new one.
|
||||
/// @param _upgraderAddr address of a deployed Upgrader contract.
|
||||
/// exception PermissionException msg.sender is not the owner.
|
||||
/// exception UpgraderConflictException Another Upgrader contract is working.
|
||||
/// @return if Upgrader contract is successfully registered.
|
||||
function startUpgrading (address _upgraderAddr) public returns(bool);
|
||||
|
||||
/// Getter of proposalPeriod.
|
||||
/// exception UninitializationException uninitialized contract.
|
||||
/// exception GetterPermissionException msg.sender is not permitted to call the getter.
|
||||
/// @return this.proposalPeriod.
|
||||
function getProposalPeriod () public view isReady allowedAddress returns(uint256);
|
||||
|
||||
/// Setter of proposalPeriod.
|
||||
/// @param _proposalPeriod new value of this.proposalPeriod.
|
||||
/// exception UninitializationException uninitialized contract.
|
||||
/// exception PermissionException msg.sender is not the owner.
|
||||
/// @return if this.proposalPeriod is successfully set.
|
||||
function setProposalPeriod (uint256 _proposalPeriod) public isReady returns(bool);
|
||||
|
||||
/// Return upgrading status for Upgrader contracts.
|
||||
/// @param _originalHandlerAddr address of the original Handler contract.
|
||||
/// exception UninitializationException uninitialized contract.
|
||||
/// @return Handler contract's upgrading status.
|
||||
function canBeUpgraded (address _originalHandlerAddr) external view isReady returns(UpgradingStatus);
|
||||
|
||||
/// Check if the contract has been initialized.
|
||||
/// @return if the contract has been initialized.
|
||||
function live () external view returns(bool);
|
||||
|
||||
/** Getters and setters of data resources: define functions here */
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Upgrader Contract (Optional)
|
||||
|
||||
Handler contract can be upgraded by calling setHandler() of Data contract. If the owner wants to collect ideas from users, an Upgrader contract will help him/her manage voting and upgrading.
|
||||
|
||||
Below is the specification of Upgrader contract:
|
||||
|
||||
- The Upgrader contract has the ability to take votes from the registered voters.
|
||||
- The contract owner is able to add voters any time before the proposal expires;
|
||||
- Voter can check the current status of the proposal (succeed or expired).
|
||||
- Developers are able to delete this Upgrader contract by calling done() any time after deployment.
|
||||
|
||||
The Upgrader contract works as follows:
|
||||
|
||||
1. Verify the Data contract, its corresponding Handler contract and the new Handler contract have all been deployed;
|
||||
2. Deploy an Upgrader contract using Data contract address, previous Handler contract address and new Handler contract address;
|
||||
3. Register upgrader address in the new Handler contract first, then the original handler and finally the Data contract;
|
||||
4. Call startProposal() to start the voting process;
|
||||
5. Call getResolution() before the expiration;
|
||||
6. Upgrading succeed or proposal is expired.
|
||||
|
||||
Note:
|
||||
|
||||
- Function done() can be called at any time to let upgrader destruct itself.
|
||||
- Function status() can be called at any time to show caller status of the upgrader.
|
||||
|
||||
|
||||
```solidity
|
||||
/// Handler upgrader
|
||||
contract Upgrader {
|
||||
// Data contract
|
||||
DataContract public data;
|
||||
// Original Handler contract
|
||||
IHandler public originalHandler;
|
||||
// New Handler contract
|
||||
address public newHandlerAddr;
|
||||
|
||||
/** Marker */
|
||||
enum UpgraderStatus {
|
||||
Preparing,
|
||||
Voting,
|
||||
Success,
|
||||
Expired,
|
||||
End
|
||||
}
|
||||
UpgraderStatus public status;
|
||||
|
||||
/// Check if the proposal is expired.
|
||||
/// If so, contract would be marked as expired.
|
||||
/// exception PreparingUpgraderException proposal has not been started.
|
||||
/// exception ReupgradingException upgrading has been done.
|
||||
/// exception ExpirationException proposal is expired.
|
||||
modifier notExpired {
|
||||
require(status != UpgraderStatus.Preparing, "Invalid proposal!");
|
||||
require(status != UpgraderStatus.Success, "Upgrading has been done!");
|
||||
require(status != UpgraderStatus.Expired, "Proposal is expired!");
|
||||
if (data.canBeUpgraded(address(originalHandler)) != DataContract.UpgradingStatus.InProgress) {
|
||||
status = UpgraderStatus.Expired;
|
||||
require(false, "Proposal is expired!");
|
||||
}
|
||||
_;
|
||||
}
|
||||
|
||||
/// Start voting.
|
||||
/// Upgrader must do upgrading check, namely checking if Data contract and 2 Handler contracts are ok.
|
||||
/// exception RestartingException proposal has been already started.
|
||||
/// exception PermissionException msg.sender is not the owner.
|
||||
/// exception UpgraderConflictException another upgrader is working.
|
||||
/// exception NoPreparationException original or new Handler contract is not prepared.
|
||||
function startProposal () external;
|
||||
|
||||
/// Anyone can try to get resolution.
|
||||
/// If voters get consensus, upgrade the Handler contract.
|
||||
/// If expired, self-destruct.
|
||||
/// Otherwise, do nothing.
|
||||
/// exception PreparingUpgraderException proposal has not been started.
|
||||
/// exception ExpirationException proposal is expired.
|
||||
/// @return status of proposal.
|
||||
function getResolution() external returns(UpgraderStatus);
|
||||
|
||||
/// Destruct itself.
|
||||
/// exception PermissionException msg.sender is not the owner.
|
||||
function done() external;
|
||||
|
||||
/** Other voting mechanism related variables and functions */
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### 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:
|
||||
|
||||
- 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.
|
||||
- The voting will only be valid in a given time period. If in a given time period the contract cannot collect enough “yes” to proceed, the proposal will be marked expired.
|
||||
|
||||
## Rationale
|
||||
|
||||
### Data Contract and Handler Contract
|
||||
|
||||
A smart contract is actually a kind of software, which provides some kind of services. From the perspective of software engineering, a service consists of **resources** that abstract the data and **operations** that abstract the process logic on the data. The requirement of upgrading is mostly on the logic part. Therefore, in order to make a smart contract upgradable, we divide it into two parts:
|
||||
|
||||
1. Data contract keeps the resources;
|
||||
2. Handler contract contains operations.
|
||||
|
||||
The Handler contract can be upgraded in the future while the Data contract is permanent. Handler contract can manipulate the variables in Data contract through the getter and setter functions provided by Data contract.
|
||||
|
||||
### Upgrader Contract and Voting Mechanism
|
||||
|
||||
In order to prevent centralization and protect the interests of the community and stakeholders, we also design a voting mechanism in the Upgrader contract. Upgrader contract contains addresses of Data contract and two Handler contracts, and collects votes from pre-defined voters to upgrade the Handler contract when the pre-set condition is fulfilled.
|
||||
|
||||
For simplicity, the upgradable contract comes with a very minimal version of the voting mechanism. If the contract owner wants to implement a more complex voting mechanism, he/she can modify the existing voting mechanism to incorporate upgradability. The expiration mechanism (see modifier notExpried in Upgrader contract and related functions in Data contract) and upgrading check (see function startProposal() in Upgrader contract) to the contract are mandatory.
|
||||
|
||||
### Gas and Complexity (regarding the enumeration extension)
|
||||
|
||||
Using an upgrader will cost some gas. If the Handler contract is upgraded by the owner, it just costs gas that a contract call will cost, which is usually significantly lower than creating and deploying a new contract.
|
||||
|
||||
Although upgrading contract may take some efforts and gas, it is a much less painful than deprecating the insecure contract/creating a new contract or hard fork (e.g. DAO attack). Contract creation requires a significant amount of effort and gas. One of the advantages of upgradable contracts is that the contract owners don’t have to create new contracts; instead, they only need to upgrade parts of contract that cause issues, which is less expensive compared to data loss and blockchain inconsistency. In other words, upgradable contracts make Data contract more scalable and flexible.
|
||||
|
||||
### Community Consensus
|
||||
|
||||
Thank you to those who helped on review and revise the proposal:
|
||||
|
||||
- [@lsankar4033](https://github.com/lsankar4033) from MIT
|
||||
- more
|
||||
|
||||
The proposal is initiated and developed by the team Renaissance and the Research Group of Blockchain System @ Center for Operating System at Peking University.
|
||||
|
||||
We have been very inclusive in this process and invite anyone with questions or contributions into our discussion. However, this standard is written only to support the identified use cases which are listed herein.
|
||||
|
||||
## 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
|
||||
|
||||
|
||||
## Copyright
|
||||
|
||||
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
|
|
@ -0,0 +1,279 @@
|
|||
---
|
||||
eip: 152
|
||||
title: Add BLAKE2 compression function `F` precompile
|
||||
author: Tjaden Hess <tah83@cornell.edu>, Matt Luongo (@mhluongo), Piotr Dyraga (@pdyraga), James Hancock (@MadeOfTin)
|
||||
discussions-to: https://github.com/ethereum/EIPs/issues/152
|
||||
status: Final
|
||||
type: Standards Track
|
||||
category: Core
|
||||
created: 2016-10-04
|
||||
requires: 2046
|
||||
---
|
||||
|
||||
<!--You can leave these HTML comments in your merged EIP and delete the visible duplicate text guides, they will not appear and may be helpful to refer to if you edit it again. This is the suggested template for new EIPs. Note that an EIP number will be assigned by an editor. When opening a pull request to submit your EIP, please use an abbreviated title in the filename, `eip-draft_title_abbrev.md`. 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.-->
|
||||
|
||||
This EIP will enable the BLAKE2b hash function and other higher-round 64-bit BLAKE2 variants to run cheaply on the EVM, allowing easier interoperability between Ethereum and Zcash as well as other Equihash-based PoW coins.
|
||||
|
||||
## Abstract
|
||||
<!--A short (~200 word) description of the technical issue being addressed.-->
|
||||
|
||||
This EIP introduces a new precompiled contract which implements the compression function `F` used in the BLAKE2 cryptographic hashing algorithm, for the purpose of allowing interoperability between the EVM and Zcash, as well as introducing more flexible cryptographic hash primitives to the EVM.
|
||||
|
||||
## 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.-->
|
||||
|
||||
Besides being a useful cryptographic hash function and SHA3 finalist, BLAKE2 allows for efficient verification of the Equihash PoW used in Zcash, making a BTC Relay - style SPV client possible on Ethereum. A single verification of an Equihash PoW verification requires 512 iterations of the hash function, making verification of Zcash block headers prohibitively expensive if a Solidity implementation of BLAKE2 is used.
|
||||
|
||||
BLAKE2b, the common 64-bit BLAKE2 variant, is highly optimized and faster than MD5 on modern processors.
|
||||
|
||||
Interoperability with Zcash could enable contracts like trustless atomic swaps between the chains, which could provide a much needed aspect of privacy to the very public Ethereum blockchain.
|
||||
|
||||
## 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)).-->
|
||||
|
||||
We propose adding a precompiled contract at address `0x09` wrapping the [BLAKE2 `F` compression function](https://tools.ietf.org/html/rfc7693#section-3.2).
|
||||
|
||||
The precompile requires 6 inputs tightly encoded, taking exactly 213 bytes, as explained below. The encoded inputs are corresponding to the ones specified in the [BLAKE2 RFC Section 3.2](https://tools.ietf.org/html/rfc7693#section-3.2):
|
||||
|
||||
- `rounds` - the number of rounds - 32-bit unsigned big-endian word
|
||||
- `h` - the state vector - 8 unsigned 64-bit little-endian words
|
||||
- `m` - the message block vector - 16 unsigned 64-bit little-endian words
|
||||
- `t_0, t_1` - offset counters - 2 unsigned 64-bit little-endian words
|
||||
- `f` - the final block indicator flag - 8-bit word
|
||||
|
||||
```
|
||||
[4 bytes for rounds][64 bytes for h][128 bytes for m][8 bytes for t_0][8 bytes for t_1][1 byte for f]
|
||||
```
|
||||
|
||||
The boolean `f` parameter is considered as `true` if set to `1`.
|
||||
The boolean `f` parameter is considered as `false` if set to `0`.
|
||||
All other values yield an invalid encoding of `f` error.
|
||||
|
||||
The precompile should compute the `F` function as [specified in the RFC](https://tools.ietf.org/html/rfc7693#section-3.2) and return the updated state vector `h` with unchanged encoding (little-endian).
|
||||
|
||||
### Example Usage in Solidity
|
||||
|
||||
The precompile can be wrapped easily in Solidity to provide a more development-friendly interface to `F`.
|
||||
|
||||
```solidity
|
||||
function F(uint32 rounds, bytes32[2] memory h, bytes32[4] memory m, bytes8[2] memory t, bool f) public view returns (bytes32[2] memory) {
|
||||
bytes32[2] memory output;
|
||||
|
||||
bytes memory args = abi.encodePacked(rounds, h[0], h[1], m[0], m[1], m[2], m[3], t[0], t[1], f);
|
||||
|
||||
assembly {
|
||||
if iszero(staticcall(not(0), 0x09, add(args, 32), 0xd5, output, 0x40)) {
|
||||
revert(0, 0)
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
function callF() public view returns (bytes32[2] memory) {
|
||||
uint32 rounds = 12;
|
||||
|
||||
bytes32[2] memory h;
|
||||
h[0] = hex"48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5";
|
||||
h[1] = hex"d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b";
|
||||
|
||||
bytes32[4] memory m;
|
||||
m[0] = hex"6162630000000000000000000000000000000000000000000000000000000000";
|
||||
m[1] = hex"0000000000000000000000000000000000000000000000000000000000000000";
|
||||
m[2] = hex"0000000000000000000000000000000000000000000000000000000000000000";
|
||||
m[3] = hex"0000000000000000000000000000000000000000000000000000000000000000";
|
||||
|
||||
bytes8[2] memory t;
|
||||
t[0] = hex"03000000";
|
||||
t[1] = hex"00000000";
|
||||
|
||||
bool f = true;
|
||||
|
||||
// Expected output:
|
||||
// ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d1
|
||||
// 7d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923
|
||||
return F(rounds, h, m, t, f);
|
||||
}
|
||||
```
|
||||
|
||||
### Gas costs and benchmarks
|
||||
|
||||
Each operation will cost `GFROUND * rounds` gas, where `GFROUND = 1`. Detailed benchmarks are presented in the benchmarks appendix section.
|
||||
|
||||
## 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.-->
|
||||
|
||||
BLAKE2 is an excellent candidate for precompilation. BLAKE2 is heavily optimized for modern 64-bit CPUs, specifically utilizing 24 and 63-bit rotations to allow parallelism through SIMD instructions and little-endian arithmetic. These characteristics provide exceptional speed on native CPUs: 3.08 cycles per byte, or 1 gibibyte per second on an Intel i5.
|
||||
|
||||
In contrast, the big-endian 32 byte semantics of the EVM are not conducive to efficient implementation of BLAKE2, and thus the gas cost associated with computing the hash on the EVM is disproportionate to the true cost of computing the function natively.
|
||||
|
||||
An obvious implementation would be a direct BLAKE2b hash function precompile. At first glance, a BLAKE2b precompile satisfies most hashing and interoperability requirements on the EVM. Once we started digging in, however, it became clear that any BLAKE2b implementation would need specific features and internal modifications based on different projects' requirements and libraries.
|
||||
|
||||
A [thread with the Zcash team](https://github.com/ethereum/EIPs/issues/152#issuecomment-499240310) makes the issue clear.
|
||||
|
||||
> The minimal thing that is necessary for a working ZEC-ETH relay is an implementation of BLAKE2b Compression F in a precompile.
|
||||
|
||||
> A BLAKE2b Compression Function F precompile would also suffice for the Filecoin and Handshake interop goals.
|
||||
|
||||
> A full BLAKE2b precompile would suffice for a ZEC-ETH relay, provided that the implementation provided the parts of the BLAKE2 API that we need (personalization, maybe something else—I'm not sure).
|
||||
|
||||
> I'm not 100% certain if a full BLAKE2b precompile would also suffice for the Filecoin and Handshake goals. It almost certainly could, provided that it supports all the API that they need.
|
||||
|
||||
> BLAKE2s — whether the Compression Function F or the full hash — is only a nice-to-have for the purposes of a ZEC-ETH relay.
|
||||
|
||||
From this and other conversations with teams in the space, we believe we should focus first on the `F` precompile as a strictly necessary piece for interoperability projects. A BLAKE2b precompile is a nice-to-have, and we support any efforts to add one-- but it's unclear whether complete requirements and a flexible API can be found in time for Istanbul.
|
||||
|
||||
Implementation of only the core F compression function also allows substantial flexibility and extensibility while keeping changes at the protocol level to a minimum. This will allow functions like tree hashing, incremental hashing, and keyed, salted, and personalized hashing as well as variable length digests, none of which are currently available on the EVM.
|
||||
|
||||
## 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.-->
|
||||
|
||||
There is very little risk of breaking backwards-compatibility with this EIP, the sole issue being if someone were to build a contract relying on the address at `0x09` being empty. The likelihood of this is low, and should specific instances arise, the address could be chosen to be any arbitrary value with negligible risk of collision.
|
||||
|
||||
## 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.-->
|
||||
|
||||
#### Test vector 0
|
||||
* input: (empty)
|
||||
* output: error "input length for BLAKE2 F precompile should be exactly 213 bytes"
|
||||
|
||||
#### Test vector 1
|
||||
* input:
|
||||
`00000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001`
|
||||
* output: error "input length for BLAKE2 F precompile should be exactly 213 bytes"
|
||||
|
||||
#### Test vector 2
|
||||
* input:
|
||||
`000000000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001`
|
||||
* output: error "input length for BLAKE2 F precompile should be exactly 213 bytes"
|
||||
|
||||
#### Test vector 3
|
||||
* input:
|
||||
`0000000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000002`
|
||||
* output: error "incorrect final block indicator flag"
|
||||
|
||||
#### Test vector 4
|
||||
* input:
|
||||
`0000000048c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001`
|
||||
* output:
|
||||
`08c9bcf367e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d282e6ad7f520e511f6c3e2b8c68059b9442be0454267ce079217e1319cde05b`
|
||||
|
||||
#### Test vector 5
|
||||
* input:
|
||||
`0000000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001`
|
||||
* output: `ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d17d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923`
|
||||
|
||||
#### Test vector 6
|
||||
* input:
|
||||
`0000000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000`
|
||||
* output:
|
||||
`75ab69d3190a562c51aef8d88f1c2775876944407270c42c9844252c26d2875298743e7f6d5ea2f2d3e8d226039cd31b4e426ac4f2d3d666a610c2116fde4735`
|
||||
|
||||
#### Test vector 7
|
||||
* input:
|
||||
`0000000148c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001`
|
||||
* output:
|
||||
`b63a380cb2897d521994a85234ee2c181b5f844d2c624c002677e9703449d2fba551b3a8333bcdf5f2f7e08993d53923de3d64fcc68c034e717b9293fed7a421`
|
||||
|
||||
#### Test vector 8
|
||||
* input:
|
||||
`ffffffff48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001`
|
||||
* output:
|
||||
`fc59093aafa9ab43daae0e914c57635c5402d8e3d2130eb9b3cc181de7f0ecf9b22bf99a7815ce16419e200e01846e6b5df8cc7703041bbceb571de6631d2615`
|
||||
|
||||
## 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.-->
|
||||
|
||||
An initial implementation of the `F` function in Go, adapted from the standard library, can be found in our [Golang BLAKE2 library fork](https://github.com/keep-network/blake2-f). There's also an implementation of the precompile in our fork of [go-ethereum](https://github.com/keep-network/go-ethereum/pull/4).
|
||||
|
||||
## References
|
||||
|
||||
For reference, further discussion on this EIP also occurred in the following PRs and issues
|
||||
|
||||
* [Original Issue](https://github.com/ethereum/EIPs/issues/152)
|
||||
* [Ethereum Magicians](https://ethereum-magicians.org/t/blake2b-f-precompile/3157)
|
||||
* [PR 2129](https://github.com/ethereum/EIPs/pull/2129)
|
||||
|
||||
## Appendix - benchmarks
|
||||
|
||||
Assuming ecRecover precompile is perfectly priced, we executed a set of benchmarks comparing Blake2b F compression function precompile with ecRecover precompile. For benchmarks, we used 3.1 GHz Intel Core i7 64-bit machine.
|
||||
|
||||
```sh
|
||||
$ sysctl -n machdep.cpu.brand_string
|
||||
Intel(R) Core(TM) i7-7920HQ CPU @ 3.10GHz
|
||||
```
|
||||
|
||||
### 12 rounds
|
||||
|
||||
An average gas price of F precompile call with 12 rounds compared to ecRecover should have been `6.74153` and it gives `0.5618` gas per round.
|
||||
|
||||
```
|
||||
Name Gascost Time (ns) MGas/S Gasprice for 10MGas/S Gasprice for ECDSA eq
|
||||
----------------------------------------- --------- ---------------- --------- ----------------------- -----------------------
|
||||
PrecompiledEcrecover/ 3000 152636 19.6546 1526.36 3000
|
||||
PrecompiledBlake2F/testVectors2bX_0 12 338 35.503 3.38 6.64326
|
||||
PrecompiledBlake2F/testVectors2bX_3 12 336 35.7143 3.36 6.60395
|
||||
PrecompiledBlake2F/testVectors2bX_70 12 362 33.1492 3.62 7.11497
|
||||
PrecompiledBlake2F/testVectors2bX_140 12 339 35.3982 3.39 6.66291
|
||||
PrecompiledBlake2F/testVectors2bX_230 12 339 35.3982 3.39 6.66291
|
||||
PrecompiledBlake2F/testVectors2bX_300 12 343 34.9854 3.43 6.74153
|
||||
PrecompiledBlake2F/testVectors2bX_370 12 336 35.7143 3.36 6.60395
|
||||
PrecompiledBlake2F/testVectors2bX_440 12 337 35.6083 3.37 6.6236
|
||||
PrecompiledBlake2F/testVectors2bX_510 12 345 34.7826 3.45 6.78084
|
||||
PrecompiledBlake2F/testVectors2bX_580 12 355 33.8028 3.55 6.97738
|
||||
```
|
||||
|
||||
Columns
|
||||
|
||||
* `MGas/S` - Shows what MGas per second was measured on that machine at that time
|
||||
* `Gasprice for 10MGas/S` shows what the gasprice should have been, in order to reach 10 MGas/second
|
||||
* `Gasprice for ECDSA eq` shows what the gasprice should have been, in order to have the same cost/cycle as ecRecover
|
||||
|
||||
### 1200 rounds
|
||||
|
||||
An average gas price of F precompile call with 1200 rounds compared to ecRecover should have been `436.1288` and it gives `0.3634` gas per round.
|
||||
|
||||
```
|
||||
Name Gascost Time (ns) MGas/S Gasprice for 10MGas/S Gasprice for ECDSA eq
|
||||
----------------------------------------- --------- ---------------- --------- ----------------------- -----------------------
|
||||
PrecompiledEcrecover/ 3000 156152 19.212 1561.52 3000
|
||||
PrecompiledBlake2F/testVectors2bX_0 1200 22642 52.9989 226.42 434.999
|
||||
PrecompiledBlake2F/testVectors2bX_3 1200 22885 52.4361 228.85 439.668
|
||||
PrecompiledBlake2F/testVectors2bX_70 1200 22737 52.7774 227.37 436.824
|
||||
PrecompiledBlake2F/testVectors2bX_140 1200 22602 53.0926 226.02 434.231
|
||||
PrecompiledBlake2F/testVectors2bX_230 1200 22501 53.331 225.01 432.29
|
||||
PrecompiledBlake2F/testVectors2bX_300 1200 22435 53.4879 224.35 431.022
|
||||
PrecompiledBlake2F/testVectors2bX_370 1200 22901 52.3995 229.01 439.975
|
||||
PrecompiledBlake2F/testVectors2bX_440 1200 23134 51.8717 231.34 444.452
|
||||
PrecompiledBlake2F/testVectors2bX_510 1200 22608 53.0786 226.08 434.346
|
||||
PrecompiledBlake2F/testVectors2bX_580 1200 22563 53.1844 225.63 433.481
|
||||
```
|
||||
|
||||
### 1 round
|
||||
|
||||
An average gas price of F precompile call with 1 round compared to ecRecover should have been `2.431701`. However, in this scenario the call cost would totally overshadow the dynamic cost anyway.
|
||||
|
||||
```
|
||||
Name Gascost Time (ns) MGas/S Gasprice for 10MGas/S Gasprice for ECDSA eq
|
||||
----------------------------------------- --------- ---------------- ---------- ----------------------- -----------------------
|
||||
PrecompiledEcrecover/ 3000 157544 19.0423 1575.44 3000
|
||||
PrecompiledBlake2F/testVectors2bX_0 1 126 7.93651 1.26 2.39933
|
||||
PrecompiledBlake2F/testVectors2bX_3 1 127 7.87402 1.27 2.41837
|
||||
PrecompiledBlake2F/testVectors2bX_70 1 128 7.8125 1.28 2.43741
|
||||
PrecompiledBlake2F/testVectors2bX_140 1 125 8 1.25 2.38029
|
||||
PrecompiledBlake2F/testVectors2bX_230 1 128 7.8125 1.28 2.43741
|
||||
PrecompiledBlake2F/testVectors2bX_300 1 127 7.87402 1.27 2.41837
|
||||
PrecompiledBlake2F/testVectors2bX_370 1 131 7.63359 1.31 2.49454
|
||||
PrecompiledBlake2F/testVectors2bX_440 1 129 7.75194 1.29 2.45646
|
||||
PrecompiledBlake2F/testVectors2bX_510 1 125 8 1.25 2.38029
|
||||
PrecompiledBlake2F/testVectors2bX_580 1 131 7.63359 1.31 2.49454
|
||||
```
|
||||
|
||||
|
||||
## Copyright
|
||||
|
||||
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
|
|
@ -0,0 +1,129 @@
|
|||
---
|
||||
eip: 1523
|
||||
title: Standard for Insurance Policies as ERC-721 Non Fungible Tokens
|
||||
author: Christoph Mussenbrock (@christoph2806)
|
||||
discussions-to: https://github.com/ethereum/EIPs/issues/1523
|
||||
status: Draft
|
||||
type: Standards Track
|
||||
category: ERC
|
||||
created: 2018-10-10
|
||||
requires: 721
|
||||
---
|
||||
|
||||
## 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.-->
|
||||
A standard interface for insurance policies, based on ERC 721.
|
||||
|
||||
## Abstract
|
||||
<!--A short (~200 word) description of the technical issue being addressed.-->
|
||||
The following standard allows for the implementation of a standard API for insurance policies within smart contracts.
|
||||
Insurance policies are financial assets which are unique in some aspects, as they are connected to a customer, a specific risk, or have other unique properties like premium, period, carrier, underwriter etc.
|
||||
Nevertheless, there are many potential applications where insurance policies can be traded, transferred or otherwise treated as an asset.
|
||||
The ERC 721 standard already provides the standard and technical means to handle policies as a specific class of non fungible tokens.
|
||||
insurance In this proposal, we define a minimum metadata structure with properties which are common to the greatest possible class of policies.
|
||||
|
||||
## 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.-->
|
||||
For a decentralized insurance protocol, a standard for insurance policies is crucial for interoperability of the involved services and application.
|
||||
It allows policies to be bundled, securitized, traded in a uniform and flexible way by many independent actors like syndicates, brokers, and insurance companies.
|
||||
|
||||
## 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)).-->
|
||||
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.
|
||||
|
||||
An ERC-1523 compliant insurance policy is a non-fungible token which **MUST adhere to the ERC-721 token standard** and **MUST implement theERC721Metadata and the ERC721Enumerable interface**:
|
||||
|
||||
```solidity
|
||||
/// @title ERC-1523 Insurance Policy Standard
|
||||
/// Note: the ERC-165 identifier for this interface is 0x5a04be32
|
||||
interface ERC1523 /* is ERC721, ERC721Metadata, ERC721Enumerable */ {
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
The implementor MAY choose values for the ```name``` and ```symbol```.
|
||||
|
||||
The **policy metadata extension** is **RECOMMENDED** for ERC-1523 smart contracts.
|
||||
This allows your smart contract to be interrogated for policy metadata.
|
||||
|
||||
```solidity
|
||||
/// @title ERC-1523 Insurance Policy Standard, optional policy metadata extension
|
||||
/// @dev See ...
|
||||
/// Note: the ERC-165 identifier for this interface is 0x5a04be32
|
||||
interface ERC1523PolicyMetadata /* is ERC1523 */ {
|
||||
|
||||
/// @notice Metadata string for a given property.
|
||||
/// Properties are identified via hash of their property path.
|
||||
/// e.g. the property "name" in the ERC721 Metadata JSON Schema has the path /properties/name
|
||||
/// and the property path hash is the keccak256() of this property path.
|
||||
/// this allows for efficient addressing of arbitrary properties, as the set of properties is potentially unlimited.
|
||||
/// @dev Throws if `_propertyPathHash` is not a valid property path hash.
|
||||
function policyMetadata(uint256 _tokenId, bytes32 _propertyPathHash) external view returns (string _property);
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
In analogy to the “ERC721 Metadata JSON Schema”, the tokenURI **MUST** point to a JSON file with the following properties:
|
||||
```json
|
||||
{
|
||||
"title": "Asset Metadata",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Identifies the asset to which this NFT represents",
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"description": "Describes the asset to which this NFT represents",
|
||||
},
|
||||
"carrier": {
|
||||
"type": "string",
|
||||
"description": "Describes the carrier which takes the primary risk",
|
||||
},
|
||||
"risk": {
|
||||
"type": "string",
|
||||
"description": "Describes the risk",
|
||||
},
|
||||
"parameters": {
|
||||
"type": "string",
|
||||
"description": "Describes further parameters characterizing the risk",
|
||||
},
|
||||
"status": {
|
||||
"type": "string",
|
||||
"description": "Defines the status of the policy, e.g. Applied, Underwritten, Claimed, Paid out, etc."
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 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.-->
|
||||
Insurance policies form an important class of financial assets, and it is natural to express those assets as a class of non-fungible tokens which adhere to the established ERC-721 standard.
|
||||
We propose a standard for the accompanying metadata structures which are needed to uniquely define an insurance policy.
|
||||
While policies can have a multitude of possible properties, it is common that policies are issued by some entity, which is basically the entity responsible for paying out claims.
|
||||
Second, an insurance policy is typically related to a specific risk. Some risks are unique, but there are cases where many policies share the same risk
|
||||
(e.g. all flight delay policies for the same flight).
|
||||
In general, the relation of policies to risks is a many-to-one relation with the special case of a one-to-one relation.
|
||||
Third, most policies need more parameters to characterize the risk and other features, like premium, period etc.
|
||||
Forth, a policy has a lifecycle of different statuses.
|
||||
We believe that those four properties are necessary to describe a policy. For many applications, those properties may be even sufficient.
|
||||
However, any implementation **MAY** chose to implement more properties.
|
||||
|
||||
### On-chain vs. off-chain metadata
|
||||
For some applications it will be sufficient to store the metadata in an off-chain repository or database which can be addressed by the tokenURI resource locator.
|
||||
For more advanced applications, it can be desirable to have metadata available on-chain.
|
||||
Therefore, we require that the ```tokenURI``` **MUST** point to a JSON with the above structure, while the implementation of the ```policyMetadata``` function is **OPTIONAL**.
|
||||
|
||||
|
||||
## 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.-->
|
||||
|
||||
## Implementation
|
||||
<!--The implementations must be completed before any EIP is given status "Final", but it need not be completed before the EIP is accepted. While there is merit to the approach of reaching consensus on the specification and rationale before writing code, the principle of "rough consensus and running code" is still useful when it comes to resolving many discussions of API details.-->
|
||||
|
||||
## Copyright
|
||||
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
|
|
@ -0,0 +1,474 @@
|
|||
---
|
||||
eip: 1538
|
||||
title: Transparent Contract Standard
|
||||
author: Nick Mudge <nick@mokens.io>
|
||||
discussions-to: https://github.com/ethereum/EIPs/issues/1538
|
||||
status: Draft
|
||||
type: Standards Track
|
||||
category: ERC
|
||||
created: 2018-10-31
|
||||
---
|
||||
|
||||
|
||||
## 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.-->
|
||||
This standard provides a contract architecture that makes upgradeable contracts flexible, unlimited in size, and transparent.
|
||||
|
||||
A transparent contract publicly documents the full history of all changes made to it.
|
||||
|
||||
All changes to a transparent contract are reported in a standard format.
|
||||
|
||||
## Abstract
|
||||
<!--A short (~200 word) description of the technical issue being addressed.-->
|
||||
A transparent contract is a proxy contract design pattern that provides the following:
|
||||
|
||||
1. A way to add, replace and remove multiple functions of a contract atomically (at the same time).
|
||||
1. Standard events to show what functions are added, replaced and removed from a contract, and why the changes are made.
|
||||
2. A standard way to query a contract to discover and retrieve information about all functions exposed by it.
|
||||
3. Solves the 24KB maximum contract size limitation, making the maximum contract size of a transparent contract practically unlimited. This standard makes the worry about contract size a thing of the past.
|
||||
4. Enables an upgradeable contract to become immutable in the future if desired.
|
||||
|
||||
## 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.-->
|
||||
A fundamental benefit of Ethereum contracts is that their code is immutable, thereby acquiring trust by trustlessness. People do not have to trust others if it is not possible for a contract to be changed.
|
||||
|
||||
However, a fundamental problem with trustless contracts that cannot be changed is that they cannot be changed.
|
||||
|
||||
#### Bugs
|
||||
|
||||
Bugs and security vulnerabilities are unwittingly written into immutable contracts that ruin them.
|
||||
|
||||
#### Improvements
|
||||
|
||||
Immutable, trustless contracts cannot be improved, resulting in increasingly inferior contracts over time.
|
||||
|
||||
Contract standards evolve, new ones come out. People, groups and organizations learn over time what people want and what is better and what should be built next. Contracts that cannot be improved not only hold back the authors that create them, but everybody who uses them.
|
||||
|
||||
#### Upgradeable Contracts vs. Centralized Private Database
|
||||
Why have an upgradeable contract instead of a centralized, private, mutable database?
|
||||
Here are some reasons:
|
||||
1. Because of the openness of storage data and verified code, it is possible to show a provable history of trustworthiness.
|
||||
2. Because of the openness, bad behavior can be spotted and reported when it happens.
|
||||
3. Independent security and domain experts can review the change history of contracts and vouch for their history of trustworthiness.
|
||||
4. It is possible for an upgradeable contract to become immutable and trustless.
|
||||
5. An upgradeable contract can have parts of it that are not upgradeable and so are partially immutable and trustless.
|
||||
|
||||
#### Immutability
|
||||
|
||||
In some cases immutable, trustless contracts are the right fit. This is the case when a contract is only needed for a short time or it is known ahead of time that there will never be any reason to change or improve it.
|
||||
|
||||
### Middle Ground
|
||||
|
||||
Transparent contracts provide a middle ground between immutable trustless contracts that can't be improved and upgradeable contracts that can't be trusted.
|
||||
|
||||
### Purposes
|
||||
|
||||
1. Create upgradeable contracts that earn trust by showing a provable history of trustworthiness.
|
||||
2. Document the development of contracts so their development and change is provably public and can be understood.
|
||||
3. Create upgradeable contracts that can become immutable in the future if desired.
|
||||
4. Create contracts that are not limited by a max size.
|
||||
|
||||
### Benefits & Use Cases
|
||||
This standard is for use cases that benefit from the following:
|
||||
1. The ability to add, replace or remove multiple functions of a contract atomically (at the same time).
|
||||
2. Each time a function is added, replaced or removed, it is documented with events.
|
||||
3. Build trust over time by showing all changes made to a contract.
|
||||
4. Unlimited contract size.
|
||||
5. The ability to query information about functions currently supported by the contract.
|
||||
6. One contract address that provides all needed functionality and never needs to be replaced by another contract address.
|
||||
7. The ability for a contract to be upgradeable for a time, and then become immutable.
|
||||
8. Add trustless guarantees to a contract with "unchangeable functions".
|
||||
|
||||
### New Software Possibilities
|
||||
|
||||
This standard enables a form of contract version control software to be written.
|
||||
|
||||
Software and user interfaces can be written to filter the `FunctionUpdate` and `CommitMessage` events of a contract address. Such software can show the full history of changes of any contract that implements this standard.
|
||||
|
||||
User interfaces and software can also use this standard to assist or automate changes of contracts.
|
||||
|
||||
## 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)).-->
|
||||
|
||||
> **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 storage variables of the calling contract, not the contract where the functions are defined.
|
||||
|
||||
### General Summary
|
||||
|
||||
A transparent contract delegates or forwards function calls to it to other contracts using `delegatecode`.
|
||||
|
||||
A transparent contract has an `updateContract` function that enables multiple functions to be added, replaced or removed.
|
||||
|
||||
An event is emitted for every function that is added, replaced or removed so that all changes to a contract can be tracked in a standard way.
|
||||
|
||||
A transparent contract is a contract that implements and complies with the design points below.
|
||||
|
||||
### Terms
|
||||
|
||||
1. In this standard a **delegate contract** is a contract that a transparent contract fallback function forwards function calls to using `delegatecall`.
|
||||
2. In this standard an **unchangeable function** is a function that is defined directly in a transparent contract and so cannot be replaced or removed.
|
||||
|
||||
### Design Points
|
||||
|
||||
A contract is a transparent contract if it implements the following design points:
|
||||
|
||||
1. A transparent contract is a contract that contains a fallback function, a constructor, and zero or more unchangeable functions that are defined directly within it.
|
||||
2. The constructor of a transparent contract associates the `updateContract` function with a contract that implements the ERC1538 interface. The `updateContract` function can be an "unchangeable function" that is defined directly in the transparent contract or it can be defined in a delegate contract. Other functions can also be associated with contracts in the constructor.
|
||||
3. After a transparent contract is deployed functions are added, replaced and removed by calling the `updateContract` function.
|
||||
4. The `updateContract` function associates functions with contracts that implement those functions, and emits the `CommitMessage` and `FunctionUpdate` events that document function changes.
|
||||
5. The `FunctionUpdate` event is emitted for each function that is added, replaced or removed. The `CommitMessage` event is emitted one time for each time the `updateContract` function is called and is emitted after any `FunctionUpdate` events are emitted.
|
||||
6. The `updateContract` function can take a list of multiple function signatures in its `_functionSignatures` parameter and so add/replace/remove multiple functions at the same time.
|
||||
7. When a function is called on a transparent contract it executes immediately if it is an "unchangeable function". Otherwise the fallback function is executed. The fallback function finds the delegate contract associated with the function and executes the function using `delegatecall`. If there is no delegate contract for the function then execution reverts.
|
||||
8. The source code of a transparent contract and all delegate contracts used by it are publicly viewable and verified.
|
||||
|
||||
The transparent contract address is the address that users interact with. The transparent contract address never changes. Only delegate addresses can change by using the `updateContracts` function.
|
||||
|
||||
Typically some kind of authentication is needed for adding/replacing/removing functions from a transparent contract, **however the scheme for authentication or ownership is not part of this standard**.
|
||||
|
||||
### Example
|
||||
|
||||
Here is an example of an implementation of a transparent contract. Please note that the example below is an **example only. It is not the standard**. A contract is a transparent contract when it implements and complies with the design points listed above.
|
||||
|
||||
```solidity
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
contract ExampleTransparentContract {
|
||||
// owner of the contract
|
||||
address internal contractOwner;
|
||||
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
|
||||
|
||||
// maps functions to the delegate contracts that execute the functions
|
||||
// funcId => delegate contract
|
||||
mapping(bytes4 => address) internal delegates;
|
||||
|
||||
// maps each function signature to its position in the funcSignatures array.
|
||||
// signature => index+1
|
||||
mapping(bytes => uint256) internal funcSignatureToIndex;
|
||||
|
||||
event CommitMessage(string message);
|
||||
event FunctionUpdate(bytes4 indexed functionId, address indexed oldDelegate, address indexed newDelegate, string functionSignature);
|
||||
|
||||
// this is an example of an "unchangeable function".
|
||||
// return the delegate contract address for the supplied function signature
|
||||
function delegateAddress(string calldata _functionSignature) external view returns(address) {
|
||||
require(funcSignatureToIndex[bytes(_functionSignature)] != 0, "Function signature not found.");
|
||||
return delegates[bytes4(keccak256(bytes(_functionSignature)))];
|
||||
}
|
||||
|
||||
// add a function using the updateContract function
|
||||
// this is an internal helper function
|
||||
function addFunction(address _erc1538Delegate, address contractAddress, string memory _functionSignatures, string memory _commitMessage) internal {
|
||||
// 0x03A9BCCF == bytes4(keccak256("updateContract(address,string,string)"))
|
||||
bytes memory funcdata = abi.encodeWithSelector(0x03A9BCCF, contractAddress, _functionSignatures, _commitMessage);
|
||||
bool success;
|
||||
assembly {
|
||||
success := delegatecall(gas, _erc1538Delegate, add(funcdata, 0x20), mload(funcdata), funcdata, 0)
|
||||
}
|
||||
require(success, "Adding a function failed");
|
||||
}
|
||||
|
||||
constructor(address _erc1538Delegate) public {
|
||||
contractOwner = msg.sender;
|
||||
emit OwnershipTransferred(address(0), msg.sender);
|
||||
|
||||
// adding ERC1538 updateContract function
|
||||
bytes memory signature = "updateContract(address,string,string)";
|
||||
bytes4 funcId = bytes4(keccak256(signature));
|
||||
delegates[funcId] = _erc1538Delegate;
|
||||
emit FunctionUpdate(funcId, address(0), _erc1538Delegate, string(signature));
|
||||
emit CommitMessage("Added ERC1538 updateContract function at contract creation");
|
||||
|
||||
// associate "unchangeable functions" with this transparent contract address
|
||||
// prevents function selector clashes with delegate contract functions
|
||||
// uses the updateContract function
|
||||
string memory functions = "delegateAddress(string)";
|
||||
addFunction(_erc1538Delegate, address(this), functions, "Associating unchangeable functions");
|
||||
|
||||
// adding ERC1538Query interface functions
|
||||
functions = "functionByIndex(uint256)functionExists(string)delegateAddresses()delegateFunctionSignatures(address)functionById(bytes4)functionBySignature(string)functionSignatures()totalFunctions()";
|
||||
// "0x01234567891011121314" is an example address of an ERC1538Query delegate contract
|
||||
addFunction(_erc1538Delegate, 0x01234567891011121314, functions, "Adding ERC1538Query functions");
|
||||
|
||||
// additional functions could be added at this point
|
||||
}
|
||||
|
||||
// Making the fallback function payable makes it work for delegate contract functions
|
||||
// that are payable and not payable.
|
||||
function() external payable {
|
||||
// Delegate every function call to a delegate contract
|
||||
address delegate = delegates[msg.sig];
|
||||
require(delegate != address(0), "Function does not exist.");
|
||||
assembly {
|
||||
let ptr := mload(0x40)
|
||||
calldatacopy(ptr, 0, calldatasize)
|
||||
let result := delegatecall(gas, delegate, ptr, calldatasize, 0, 0)
|
||||
let size := returndatasize
|
||||
returndatacopy(ptr, 0, size)
|
||||
switch result
|
||||
case 0 {revert(ptr, size)}
|
||||
default {return (ptr, size)}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
As can be seen in the above example, every function call is delegated to a delegate contract, unless the function is defined directly in the transparent contract (making it an unchangeable function).
|
||||
|
||||
The constructor function adds the `updateContract` function to the transparent contract, which is then used to add other functions to the transparent contract.
|
||||
|
||||
Each time a function is added to a transparent contract the events `CommitMessage` and `FunctionUpdate` are emitted to document exactly what functions where added or replaced and why.
|
||||
|
||||
The delegate contract that implements the `updateContract` function implements the following interface:
|
||||
### ERC1538 Interface
|
||||
|
||||
```solidity
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
/// @title ERC1538 Transparent Contract Standard
|
||||
/// @dev Required interface
|
||||
/// Note: the ERC-165 identifier for this interface is 0x61455567
|
||||
interface ERC1538 {
|
||||
/// @dev This emits when one or a set of functions are updated in a transparent contract.
|
||||
/// The message string should give a short description of the change and why
|
||||
/// the change was made.
|
||||
event CommitMessage(string message);
|
||||
|
||||
/// @dev This emits for each function that is updated in a transparent contract.
|
||||
/// functionId is the bytes4 of the keccak256 of the function signature.
|
||||
/// oldDelegate is the delegate contract address of the old delegate contract if
|
||||
/// the function is being replaced or removed.
|
||||
/// oldDelegate is the zero value address(0) if a function is being added for the
|
||||
/// first time.
|
||||
/// newDelegate is the delegate contract address of the new delegate contract if
|
||||
/// the function is being added for the first time or if the function is being
|
||||
/// replaced.
|
||||
/// newDelegate is the zero value address(0) if the function is being removed.
|
||||
event FunctionUpdate(
|
||||
bytes4 indexed functionId,
|
||||
address indexed oldDelegate,
|
||||
address indexed newDelegate,
|
||||
string functionSignature
|
||||
);
|
||||
|
||||
/// @notice Updates functions in a transparent contract.
|
||||
/// @dev If the value of _delegate is zero then the functions specified
|
||||
/// in _functionSignatures are removed.
|
||||
/// If the value of _delegate is a delegate contract address then the functions
|
||||
/// specified in _functionSignatures will be delegated to that address.
|
||||
/// @param _delegate The address of a delegate contract to delegate to or zero
|
||||
/// to remove functions.
|
||||
/// @param _functionSignatures A list of function signatures listed one after the other
|
||||
/// @param _commitMessage A short description of the change and why it is made
|
||||
/// This message is passed to the CommitMessage event.
|
||||
function updateContract(address _delegate, string calldata _functionSignatures, string calldata _commitMessage) external;
|
||||
}
|
||||
```
|
||||
### Function Signatures String Format
|
||||
|
||||
The text format for the `_functionSignatures` parameter is simply a string of function signatures. For example: `"myFirstFunction()mySecondFunction(string)"` This format is easy to parse and is concise.
|
||||
|
||||
Here is an example of calling the `updateContract` function that adds the ERC721 standard functions to a transparent contract:
|
||||
```javascript
|
||||
functionSignatures = "approve(address,uint256)balanceOf(address)getApproved(uint256)isApprovedForAll(address,address)ownerOf(uint256)safeTransferFrom(address,address,uint256)safeTransferFrom(address,address,uint256,bytes)setApprovalForAll(address,bool)transferFrom(address,address,uint256)"
|
||||
tx = await transparentContract.updateContract(erc721Delegate.address, functionSignatures, "Adding ERC721 functions");
|
||||
```
|
||||
|
||||
### Removing Functions
|
||||
|
||||
Functions are removed by passing `address(0)` as the first argument to the `updateContract` function. The list of functions that are passed in are removed.
|
||||
|
||||
### Source Code Verification
|
||||
|
||||
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.
|
||||
<!--
|
||||
A transparent contract must implement the [ERC-165 Standard Interface Detection standard](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md) via a delegate contract by adding the `supportsInterface` function using the `updateContract` function. The interfaceID for the ERC1538 standard is `0x61455567`.
|
||||
-->
|
||||
|
||||
### Function Selector Clash
|
||||
A function selector clash occurs when a function is added to a contract that hashes to the same four-byte hash as an existing function. This is unlikely to occur but should be prevented in the implementation of the `updateContract` function. See the [reference implementation of ERC1538](https://github.com/mudgen/transparent-contracts-erc1538) to see an example of how function clashes can be prevented.
|
||||
|
||||
### ERC1538Query
|
||||
|
||||
Optionally, the function signatures of a transparent contract can be stored in an array in the transparent contract and queried to get what functions the transparent contract supports and what their delegate contract addresses are.
|
||||
|
||||
The following is an optional interface for querying function information from a transparent contract:
|
||||
|
||||
```solidity
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
interface ERC1538Query {
|
||||
|
||||
/// @notice Gets the total number of functions the transparent contract has.
|
||||
/// @return The number of functions the transparent contract has,
|
||||
/// not including the fallback function.
|
||||
function totalFunctions() external view returns(uint256);
|
||||
|
||||
/// @notice Gets information about a specific function
|
||||
/// @dev Throws if `_index` >= `totalFunctions()`
|
||||
/// @param _index The index position of a function signature that is stored in an array
|
||||
/// @return The function signature, the function selector and the delegate contract address
|
||||
function functionByIndex(uint256 _index)
|
||||
external
|
||||
view
|
||||
returns(
|
||||
string memory functionSignature,
|
||||
bytes4 functionId,
|
||||
address delegate
|
||||
);
|
||||
|
||||
/// @notice Checks to see if a function exists
|
||||
/// @param The function signature to check
|
||||
/// @return True if the function exists, false otherwise
|
||||
function functionExists(string calldata _functionSignature) external view returns(bool);
|
||||
|
||||
/// @notice Gets all the function signatures of functions supported by the transparent contract
|
||||
/// @return A string containing a list of function signatures
|
||||
function functionSignatures() external view returns(string memory);
|
||||
|
||||
/// @notice Gets all the function signatures supported by a specific delegate contract
|
||||
/// @param _delegate The delegate contract address
|
||||
/// @return A string containing a list of function signatures
|
||||
function delegateFunctionSignatures(address _delegate) external view returns(string memory);
|
||||
|
||||
/// @notice Gets the delegate contract address that supports the given function signature
|
||||
/// @param The function signature
|
||||
/// @return The delegate contract address
|
||||
function delegateAddress(string calldata _functionSignature) external view returns(address);
|
||||
|
||||
/// @notice Gets information about a function
|
||||
/// @dev Throws if no function is found
|
||||
/// @param _functionId The id of the function to get information about
|
||||
/// @return The function signature and the contract address
|
||||
function functionById(bytes4 _functionId)
|
||||
external
|
||||
view
|
||||
returns(
|
||||
string memory signature,
|
||||
address delegate
|
||||
);
|
||||
|
||||
/// @notice Get all the delegate contract addresses used by the transparent contract
|
||||
/// @return An array of all delegate contract addresses
|
||||
function delegateAddresses() external view returns(address[] memory);
|
||||
}
|
||||
```
|
||||
|
||||
See the [reference implementation of ERC1538](https://github.com/mudgen/transparent-contracts-erc1538) to see how this is implemented.
|
||||
|
||||
The text format for the list of function signatures returned from the `delegateFunctionSignatures` and `functionSignatures` functions is simply a string of function signatures. Here is an example of such a string: `"approve(address,uint256)balanceOf(address)getApproved(uint256)isApprovedForAll(address,address)ownerOf(uint256)safeTransferFrom(address,address,uint256)safeTransferFrom(address,address,uint256,bytes)setApprovalForAll(address,bool)transferFrom(address,address,uint256)"`
|
||||
|
||||
### How To Deploy A Transparent Contract
|
||||
1. Create and deploy to a blockchain a contract that implements the ERC1538 interface. You can skip this step if there is already such a contract deployed to the blockchain.
|
||||
2. Create your transparent contract with a fallback function as given above. Your transparent contract also needs a constructor that adds the `updateContract` function.
|
||||
3. Deploy your transparent contract to a blockchain. Pass in the address of the ERC1538 delegate contract to your constructor if it requires it.
|
||||
|
||||
See the [reference implementation](https://github.com/mudgen/transparent-contracts-erc1538) for examples of these contracts.
|
||||
|
||||
### Wrapper Contract for Delegate Contracts that Depend on Other Delegate Contracts
|
||||
In some cases some delegate contracts may need to call external/public functions that reside in other delegate contracts. A convenient way to solve this problem is to create a contract that contains empty implementations of functions that are needed and import and extend this contract in delegate contracts that call functions from other delegate contracts. This enables delegate contracts to compile without having to provide implementations of the functions that are already given in other delegate contracts. This is a way to save gas, prevent reaching the max contract size limit, and prevent duplication of code. This strategy was given by @amiromayer. [See his comment for more information.](https://github.com/ethereum/EIPs/issues/1538#issuecomment-451985155) Another way to solve this problem is to use assembly to call functions provided by other delegate contracts.
|
||||
|
||||
### Decentralized Authority
|
||||
It is possible to extend this standard to add consensus functionality such as an approval function that multiple different people call to approve changes before they are submitted with the `updateContract` function. Changes only go into effect when the changes are fully approved. The `CommitMessage` and ` FunctionUpdate` events should only be emitted when changes go into effect.
|
||||
|
||||
## Security
|
||||
> This standard refers to **owner(s)** as one or more individuals that have the power to add/replace/remove functions of an upgradeable contract.
|
||||
|
||||
### General
|
||||
|
||||
The owners(s) of an upgradeable contract have the ability to alter, add or remove data from the contract's data storage. Owner(s) of a contract can also execute any arbitrary code in the contract on behalf of any address. Owners(s) can do these things by adding a function to the contract that they call to execute arbitrary code. This is an issue for upgradeable contracts in general and is not specific to transparent contracts.
|
||||
|
||||
>**Note:** The design and implementation of contract ownership 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.
|
||||
|
||||
### Unchangeable Functions
|
||||
|
||||
"Unchangeable functions" are functions defined in a transparent contract itself and not in a delegate contract. The owner(s) of a transparent contract are not able to replace these functions. The use of unchangeable functions is limited because in some cases they can still be manipulated if they read or write data to the storage of the transparent contract. Data read from the transparent contract's storage could have been altered by the owner(s) of the contract. Data written to the transparent contract's storage can be undone or altered by the owner(s) of the contract.
|
||||
|
||||
In some cases unchangeble functions add trustless guarantees to a transparent contract.
|
||||
|
||||
### Transparency
|
||||
|
||||
Contracts that implement this standard emit an event every time a function is added, replaced or removed. This enables people and software to monitor the changes to a contract. If any bad acting function is added to a contract then it can be seen. To comply with this standard all source code of a transparent contract and delegate contracts must be publicly available and verified.
|
||||
|
||||
Security and domain experts can review the history of change of any transparent contract to detect any history of foul play.
|
||||
|
||||
## 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.-->
|
||||
|
||||
### String of Function Signatures Instead of bytes4[] Array of Function Selectors
|
||||
|
||||
The `updateContract` function takes a `string` list of functions signatures as an argument instead of a `bytes4[]` array of function selectors for three reasons:
|
||||
|
||||
1. Passing in function signatures enables the implementation of `updateContract` to prevent selector clashes.
|
||||
2. A major part of this standard is to make upgradeable contracts more transparent by making it easier to see what has changed over time and why. When a function is added, replaced or removed its function signature is included in the FunctionUpdate event that is emitted. This makes it relatively easy to write software that filters the events of a contract to display to people what functions have been added/removed and changed over time without needing access to the source code or ABI of the contract. If only four-byte function selectors were provided this would not be possible.
|
||||
3. By looking at the source code of a transparent contract it is not possible to see all the functions that it supports. This is why the ERC1538Query interface exists, so that people and software have a way to look up and examine or show all functions currently supported by a transparent contract. Function signatures are used so that ERC1538Query functions can show them.
|
||||
|
||||
### Gas Considerations
|
||||
|
||||
Delegating function calls does have some gas overhead. This is mitigated in two ways:
|
||||
1. Delegate contracts 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.
|
||||
2. Because transparent contracts do not have a max size limitation it is possible to add gas optimizing functions for use cases. For example someone could use a transparent contract to implement the ERC721 standard and implement batch transfer functions from the [ERC1412 standard](https://github.com/ethereum/EIPs/issues/1412) to help reduce gas (and make batch transfers more convenient).
|
||||
|
||||
### Storage
|
||||
|
||||
The standard does not specify how data is stored or organized by a transparent contract. But here are some suggestions:
|
||||
|
||||
**Inherited Storage**
|
||||
|
||||
1. The storage variables of a transparent contract consist of the storage variables defined in the transparent contract source code and the source code of delegate contracts that have been added.
|
||||
|
||||
2. A delegate contract can use any storage variable that exists in a transparent contract as long as it defines within it all the storage variables that exist, in the order that they exist, up to and including the ones being used.
|
||||
|
||||
3. A delegate contract can create new storage variables as long as it has defined, in the same order, all storage variables that exist in the transparent contract.
|
||||
|
||||
Here is a simple way inherited storage could be implemented:
|
||||
|
||||
1. Create a storage contract that contains the storage variables that your transparent contract and delegate contracts will use.
|
||||
2. Make your delegate contracts inherit the storage contract.
|
||||
3. If you want to add a new delegate contract that adds new storage variables then create a new storage contract that adds the new storage variables and inherits from the old storage contract. Use your new storage contract with your new delegate contract.
|
||||
4. Repeat steps 2 or 3 for every new delegate contract.
|
||||
|
||||
|
||||
**Unstructured Storage**
|
||||
|
||||
Assembly is used to store and read data at specific storage locations. An advantage to this approach is that previously used storage locations don't have to be defined or mentioned in a delegate contract if they aren't used by it.
|
||||
|
||||
**Eternal Storage**
|
||||
|
||||
Data can be stored using a generic API based on the type of data. [See ERC930 for more information.](https://github.com/ethereum/EIPs/issues/930)
|
||||
|
||||
### Becoming Immutable
|
||||
It is possible to make a transparent contract become immutable. This is done by calling the `updateContract` function to remove the `updateContract` function. With this gone it is no longer possible to add, replace and remove functions.
|
||||
|
||||
### Versions of Functions
|
||||
|
||||
Software or a user can verify what version of a function is called by getting the delegate contract address of the function. This can be done by calling the `delegateAddress` function from the ERC1538Query interface if it is implemented. This function takes a function signature as an argument and returns the delegate contract address where it is implemented.
|
||||
|
||||
### Best Practices, Tools and More Information
|
||||
|
||||
> More information, tools, tutorials and best practices concerning transparent contracts need to be developed and published.
|
||||
|
||||
Below is a growing list of articles concerning transparent contracts and their use. If you have an article about transparent contracts you would like to share then please submit a comment to this issue about it to get it added.
|
||||
|
||||
[ERC1538: Future Proofing Smart Contracts and Tokens](https://coinjournal.net/erc1538-future-proofing-smart-contacts-and-tokens/)
|
||||
|
||||
[The ERC1538 improving towards the “transparent contract” standard](https://www.crypto-economy.net/en/ethereum-eth-erc1538-transparent-contract-standard/)
|
||||
|
||||
### Inspiration
|
||||
|
||||
This standard was inspired by 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) from the [Mokens project](https://github.com/Mokens/MIPs/blob/master/MIPS/mip-2-Goals-and-Objectives.md). The Mokens contract has been [upgraded to implement this standard](https://etherscan.io/address/0x0ac5637fe62ec14fd9e237a81a9679d4adef701f#code).
|
||||
|
||||
|
||||
## 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.-->
|
||||
This standard makes a contract compatible with future standards and functionality because new functions can be added and existing functions can be replaced or removed.
|
||||
|
||||
This standard future proofs a contract.
|
||||
|
||||
## 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.-->
|
||||
A reference implementation of this standard is given in the [transparent-contracts-erc1538](https://github.com/mudgen/transparent-contracts-erc1538) repository.
|
||||
|
||||
|
||||
## Copyright
|
||||
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
eip: 155
|
||||
title: Simple replay attack protection
|
||||
author: Vitalik Buterin
|
||||
author: Vitalik Buterin (@vbuterin)
|
||||
type: Standards Track
|
||||
category: Core
|
||||
status: Final
|
||||
|
@ -14,9 +14,11 @@ created: 2016-10-14
|
|||
### Parameters
|
||||
- `FORK_BLKNUM`: 2,675,000
|
||||
- `CHAIN_ID`: 1 (main net)
|
||||
|
||||
### Specification
|
||||
|
||||
If `block.number >= FORK_BLKNUM` and `v = CHAIN_ID * 2 + 35` or `v = CHAIN_ID * 2 + 36`, then when computing the hash of a transaction for purposes of signing or recovering, instead of hashing only the first six elements (i.e. nonce, gasprice, startgas, to, value, data), hash nine elements, with `v` replaced by `CHAIN_ID`, `r = 0` and `s = 0`. The currently existing signature scheme using `v = 27` and `v = 28` remains valid and continues to operate under the same rules as it does now.
|
||||
|
||||
### Example
|
||||
|
||||
Consider a transaction with `nonce = 9`, `gasprice = 20 * 10**9`, `startgas = 21000`, `to = 0x3535353535353535353535353535353535353535`, `value = 10**18`, `data=''` (empty).
|
||||
|
@ -44,6 +46,7 @@ Notice the use of 37 instead of 27. The signed tx would become:
|
|||
```
|
||||
0xf86c098504a817c800825208943535353535353535353535353535353535353535880de0b6b3a76400008025a028ef61340bd939bc2195fe537567866003e1a15d3c71ff63e1590620aa636276a067cbe9d8997f761aecb703304b3800ccf555c9f3dc64214b297fb1966a3b6d83
|
||||
```
|
||||
|
||||
### Rationale
|
||||
|
||||
This would provide a way to send transactions that work on Ethereum without working on ETC or the Morden testnet. ETC is encouraged to adopt this EIP but replacing `CHAIN_ID` with a different value, and all future testnets, consortium chains and alt-etherea are encouraged to adopt this EIP replacing `CHAIN_ID` with a unique value.
|
||||
|
@ -57,15 +60,9 @@ This would provide a way to send transactions that work on Ethereum without work
|
|||
| 2 | Morden (disused), Expanse mainnet |
|
||||
| 3 | Ropsten |
|
||||
| 4 | Rinkeby |
|
||||
| 8 | Ubiq mainnet |
|
||||
| 9 | Ubiq testnet |
|
||||
| 30 | Rootstock mainnet |
|
||||
| 31 | Rootstock testnet |
|
||||
| 5 | Goerli |
|
||||
| 42 | Kovan |
|
||||
| 61 | Ethereum Classic mainnet |
|
||||
| 62 | Ethereum Classic testnet |
|
||||
| 66 | ewasm testnet |
|
||||
| 1337 | Geth private chains (default) |
|
||||
| 6284 | Görli |
|
||||
| 43568 | Gangnam |
|
||||
| 314158 | Stureby |
|
||||
|
||||
|
||||
Find more chain ID's on [chainid.network](https://chainid.network) and contribute to [ethereum-lists/chains](https://github.com/ethereum-lists/chains).
|
|
@ -0,0 +1,74 @@
|
|||
---
|
||||
eip: 1559
|
||||
title: Fee market change for ETH 1.0 chain
|
||||
author: Vitalik Buterin (@vbuterin), Eric Conner (@econoar)
|
||||
discussions-to: https://ethereum-magicians.org/t/eip-1559-fee-market-change-for-eth-1-0-chain/2783
|
||||
status: Draft
|
||||
type: Standards Track
|
||||
category: Core
|
||||
created: 2019-04-13
|
||||
---
|
||||
|
||||
<!--You can leave these HTML comments in your merged EIP and delete the visible duplicate text guides, they will not appear and may be helpful to refer to if you edit it again. This is the suggested template for new EIPs. Note that an EIP number will be assigned by an editor. When opening a pull request to submit your EIP, please use an abbreviated title in the filename, `eip-draft_title_abbrev.md`. 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.-->
|
||||
The current "first price auction" fee model in Ethereum is inefficient and needlessly costly to users. This EIP proposes a way to replace this with a mechanism that adjusts a base network fee based on network demand, creating better fee price efficiency and reducing the complexity of client software needed to avoid paying unnecessarily high fees.
|
||||
|
||||
## Abstract
|
||||
<!--A short (~200 word) description of the technical issue being addressed.-->
|
||||
There is a BASEFEE value in protocol, which can move up or down by a maximum of 1/8 in each block; initially, miners adjust this value to target an average gas usage of 8 million, increasing BASEFEE if usage is higher and decreasing it if usage is lower. Transaction senders specify their fees by providing two values:
|
||||
|
||||
* A "premium" gasprice which gets added onto the BASEFEE gasprice, which can either be set to a fairly low value (eg. 1 gwei) to compensate miners for uncle rate risk or to a high value to compete during sudden bursts of activity. The BASEFEE gets burned, the premium is given to the miner.
|
||||
|
||||
* A "cap" which represents the maximum total that the transaction sender would be willing to pay to get included.
|
||||
|
||||
## 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.-->
|
||||
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:
|
||||
|
||||
* **Mismatch between volatility of transaction fee levels and social cost of transactions**: transaction fees on mature public blockchains, that have enough usage so that blocks are full, tend to be extremely volatile. On Ethereum, minimum fees are typically around 2 gwei (10^9 gwei = 1 ETH), but sometimes go up to 20-50 gwei and have even on one occasion gone up to over 200 gwei: https://etherscan.io/chart/gasprice. 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 100x more when gas prices are 200 gwei than when they are 2 gwei; 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**: see https://ethresear.ch/t/first-and-second-price-auctions-and-improved-transaction-fee-markets/2410 for a detailed writeup. In short, the current approach, where transaction senders publish a transaction with a fee, miners choose the highest-paying transactions, and everyone pays what they bid, is well-known in mechanism design literature to be highly inefficient, and so complex fee estimation algorithms are required, and even these algorithms often end up not working very well, leading to frequent fee overpayment. See also https://blog.bitgo.com/the-challenges-of-bitcoin-transaction-fee-estimation-e47a64a61c72 for a Bitcoin core developer's description of the challenges involved in fee estimation in the status quo.
|
||||
* **Instability of blockchains with no block reward**: in the long run, blockchains where there is no issuance (including Bitcoin and Zcash) at present intend to switch to rewarding miners entirely through transaction fees. However, there are [known results](http://randomwalker.info/publications/mining_CCS.pdf) showing that this likely leads to a lot of instability, incentivizing mining "sister blocks" that steal transaction fees, opening up much stronger selfish mining attack vectors, and more. There is at present no good mitigation for this.
|
||||
|
||||
The proposal in this EIP is to start with a BASEFEE amount which is adjusted up and down by the protocol based on how congested the network is. To accommodate this system, the network capacity would be increased to 16 million gas, so that 50% utilization matches up with our current 8 million gas limit. Then, when the network is at >50% capacity, the BASEFEE increments up slightly and when capacity is at <50%, it decrements down slightly. Because these increments are constrained, the maximum difference in BASEFEE from block to block is predictable. This then allows wallets to auto-set the gas fees for users in a highly reliable fashion. It is expected that most users will not have to manually adjust gas fees, even in periods of high network activity. For most users, the BASEFEE will be automatically set by their wallet, along with the addition of a small fixed amount, called a ‘tip’, to compensate miners (e.g. 0.5 gwei).
|
||||
|
||||
An important aspect of this upgraded fee system is that miners only get to keep the tips. The BASEFEE is always burned (i.e. it is destroyed by the protocol). Burning this is important because it prevents miners from manipulating the fee in order to extract more fees from users. It also ensures that only ETH can ever be used to pay for transactions on Ethereum, cementing the economic value of ETH within the Ethereum platform.
|
||||
|
||||
|
||||
## 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)).-->
|
||||
**Parameters**
|
||||
* `FORK_BLKNUM`: TBD
|
||||
* `BASEFEE_MAX_CHANGE_DENOMINATOR`: 8
|
||||
* `SLACK_COEFFICIENT`: 3
|
||||
* `TARGET_GASUSED`: 8,000,000
|
||||
|
||||
|
||||
**Proposal**
|
||||
For all blocks where `block.number >= FORK_BLKNUM`:
|
||||
|
||||
* Impose a hard in-protocol gas limit of `SLACK_COEFFICIENT * TARGET_GASUSED`, used instead of the gas limit calculated using the previously existing formulas
|
||||
* Replace the `GASLIMIT` field in the block header with a BASEFEE field (the same field can be used)
|
||||
* Let `PARENT_BASEFEE` be the parent block's `BASEFEE` (or 1 billion wei if `block.number == FORK_BLKNUM`). A valid `BASEFEE` is one such that `abs(BASEFEE - PARENT_BASEFEE) <= max(1, PARENT_BASEFEE // BASEFEE_MAX_CHANGE_DENOMINATOR)`
|
||||
* Redefine the way the `tx.gasprice` field is used: define `tx.fee_premium = tx.gasprice // 2**128` and `tx.fee_cap = tx.gasprice % 2**128`
|
||||
* During transaction execution, we calculate the cost to the `tx.origin` and the gain to the `block.coinbase` as follows:
|
||||
* Let `gasprice = min(BASEFEE + tx.fee_premium, tx.fee_cap)`. The `tx.origin` initially pays `gasprice * tx.gas`, and gets refunded `gasprice * (tx.gas - gasused)`.
|
||||
* The `block.coinbase` gains `(gasprice - BASEFEE) * gasused`. If `gasprice < BASEFEE` (due to the `fee_cap`), this means that the `block.coinbase` _loses_ funds from this operation; in this case, check that the post-balance is non-negative and throw an exception if it is negative.
|
||||
As a default strategy, miners set `BASEFEE` as follows. Let `delta = block.gas_used - TARGET_GASUSED` (possibly negative). Set `BASEFEE = PARENT_BASEFEE + PARENT_BASEFEE * delta // TARGET_GASUSED // BASEFEE_MAX_CHANGE_DENOMINATOR`, clamping this result inside of the allowable bounds if needed (with the parameter setting above clamping will not be required).
|
||||
|
||||
## Backwards Compatibility
|
||||
Transactions published before this EIP or by wallets that do not support this EIP will be interpreted by the above formulas as having a `fee_premium` of zero and a `fee_cap` of the fee that they submit. Provided that at least some miners are temporarily willing to be altruistic and accept zero-fee-premium transactions for a short period of time after the fork, this should not greatly affect usability. There is an invariant that a `gasprice` constructed "the old way" still constitutes an upper bound on the amount that a user will pay.
|
||||
|
||||
|
||||
## 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.-->
|
||||
|
||||
|
||||
## Copyright
|
||||
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
|
|
@ -5,10 +5,9 @@ author: Andrea Lanfranchi (@AndreaLanfranchi) <andrea.lanfranchi@gmail.com>, Paw
|
|||
discussions-to: https://github.com/AndreaLanfranchi/EthereumStratum-2.0.0/issues
|
||||
status: Draft
|
||||
type: Standards Track
|
||||
category: Networking
|
||||
category: Interface
|
||||
created: 2018-11-09
|
||||
---
|
||||
# EthereumStratum/2.0.0 - Implementation proposal guide lines
|
||||
|
||||
## Abstract
|
||||
This draft contains the guidelines to define a new standard for the Stratum protocol used by Ethereum miners to communicate with mining pool servers.
|
||||
|
@ -80,7 +79,7 @@ The JSON representation of `request` object is made of these parts:
|
|||
The JSON representation of `response` object is made of these parts:
|
||||
- mandatory `id` member of type Integer : the identifier of the request this response corresponds to
|
||||
- optional `error` member : whether an error occurred during the parsing of the method or during it's execution this member **MUST** be present and valued. If no errors occurred this member **MUST NOT** be present. For a detailed structure of the `error` member see below.
|
||||
- optional `result` member : This has to be set, if the corresponding request requires a result from the user. If no errors occurred by invoking the corresponding function, this member **MUST** be present even if one or more informations are null. The type can be of Object or single type Array or Primitive string/number. If no data is meant back for the issuer (the method is void on the receiver) or an error occurred this member **MUST NOT** be present.
|
||||
- optional `result` member : This has to be set, if the corresponding request requires a result from the user. If no errors occurred by invoking the corresponding function, this member **MUST** be present even if one or more information are null. The type can be of Object or single type Array or Primitive string/number. If no data is meant back for the issuer (the method is void on the receiver) or an error occurred this member **MUST NOT** be present.
|
||||
|
||||
You'll notice here some differences with standard JSON-RPC-2.0. Namely the result member is not always required. Basically a response like this :
|
||||
```json
|
||||
|
@ -141,13 +140,13 @@ Using proper error codes pools may properly inform miners of the condition of th
|
|||
- Error codes 5xx : server could not process the request due to internal errors
|
||||
|
||||
### Notifications
|
||||
A notification message has the very same representation of a `request` with the only difference the `id` member **MUST NOT** be present. This means the issuer is not interested nor expects any reponse to this message. It's up to the receiver to take actions accordingly. For instance the receiver **MAY** decide to execute the method, or, in case of errors or methods not allowed, drop the connection thus closing the session.
|
||||
A notification message has the very same representation of a `request` with the only difference the `id` member **MUST NOT** be present. This means the issuer is not interested nor expects any response to this message. It's up to the receiver to take actions accordingly. For instance the receiver **MAY** decide to execute the method, or, in case of errors or methods not allowed, drop the connection thus closing the session.
|
||||
|
||||
#### Error member
|
||||
As seen above a `response` **MAY** contain an `error` member. When present this member **MUST** be an Object with:
|
||||
- mandatory member `code` : a Number which identifies the error occurred
|
||||
- mandatory member `message` : a short human readable sentence describing the error occurred
|
||||
- optional member `data` : a Structured or Primitive value that contains additional informations about the error. The value of this member is defined by the Server (e.g. detailed error information, nested errors etc.).
|
||||
- optional member `data` : a Structured or Primitive value that contains additional information about the error. The value of this member is defined by the Server (e.g. detailed error information, nested errors etc.).
|
||||
|
||||
## Protocol Flow
|
||||
- Client starts session by opening a TCP socket to the server
|
||||
|
@ -373,7 +372,7 @@ At the beginning of each `session` the server **MUST** send this notification be
|
|||
Whenever the server detects that one, or two, or three or four values change within the session, the server will issue a notification with one, or two or three or four members in the `param` object. For this reason on each **new** session the server **MUST** pass all four members. As a consequence the miner is instructed to adapt those values on **next** job which gets notified.
|
||||
The new `algo` member is defined to be prepared for possible presence of algorithm variants to ethash, namely ethash1a or ProgPow.
|
||||
Pools providing multicoin switching will take care to send a new `mining.set` to miners before pushing any job after a switch.
|
||||
The client wich can't support the data provided in the `mining.set` notification **MAY** close connection or stay idle till new values satisfy it's configuration (see `mining.noop`).
|
||||
The client which can't support the data provided in the `mining.set` notification **MAY** close connection or stay idle till new values satisfy it's configuration (see `mining.noop`).
|
||||
All client's implementations **MUST** be prepared to accept new extranonces during the session: unlike in EthereumStratum/1.0.0 the optional client advertisement `mining.extranonce.subscribe` is now implicit and mandatory.
|
||||
|
||||
The miner receiving the `extranonce` **MUST** initialize the search segment for next job resizing the extranonce to a hex of 16 bytes thus appending as many zeroes as needed.
|
||||
|
@ -462,7 +461,7 @@ When a miner finds a solution for a job he is mining on it sends a `mining.submi
|
|||
]
|
||||
}
|
||||
```
|
||||
First element of `params` array is the jobId this solution refers to (as sent in the `mining.notify` message from the server). Second element is the `miner nonce` as hex. Third element is the token given to the worker previous `mining.authorize` request. Any `mining.submit` request bound to a worker which was not succesfully authorized - i.e. the token does not exist in the session - **MUST** be rejected.
|
||||
First element of `params` array is the jobId this solution refers to (as sent in the `mining.notify` message from the server). Second element is the `miner nonce` as hex. Third element is the token given to the worker previous `mining.authorize` request. Any `mining.submit` request bound to a worker which was not successfully authorized - i.e. the token does not exist in the session - **MUST** be rejected.
|
||||
|
||||
You'll notice in the sample above the `miner nonce` is only 12 bytes wide (should be 16). Why ?
|
||||
That's because in the previous `mining.set` the server has set an `extranonce` of `af4c`. This means the full nonce is `af4c68765fccd712`
|
||||
|
@ -488,7 +487,7 @@ or, in case of any error or condition with a detailed error object
|
|||
Client **should** treat errors as "soft" errors (stales) or "hard" (bad nonce computation, job not found etc.). Errors in 5xx range are server errors and suggest the miner to abandon the connection and switch to a failover.
|
||||
|
||||
### Hashrate
|
||||
Most pools offer statistic informations, in form of graphs or by API calls, about the calculated hashrate expressed by the miner while miners like to compare this data with the hashrate they read on their devices. Communication about parties of these informations have never been coded in Stratum and most pools adopt the method from getWork named `eth_submitHashrate`.
|
||||
Most pools offer statistic information, in form of graphs or by API calls, about the calculated hashrate expressed by the miner while miners like to compare this data with the hashrate they read on their devices. Communication about parties of these information have never been coded in Stratum and most pools adopt the method from getWork named `eth_submitHashrate`.
|
||||
In this document we propose an official implementation of the `mining.hashrate` request.
|
||||
This method behaves differently when issued from client or from server.
|
||||
#### Client communicates it's hashrate to server.
|
||||
|
@ -540,7 +539,7 @@ Optionally the server can **notify** client about it's overall performance (acco
|
|||
}
|
||||
}
|
||||
```
|
||||
Where `params` is an object which holds theese members for values of the **whole session**:
|
||||
Where `params` is an object which holds these members for values of the **whole session**:
|
||||
- `interval` (number) the width, in minutes, of the observation window. "_in the last x minutes we calculated ..._"
|
||||
- `hr` (hex) representation of the hashrate the pool has calculated for the miner
|
||||
- `accepted` is an array of two number elements : the first is the overall count of accepted shares and the second is the number of stale shares. The array must be interpreted as "total accepted of which x are stale"
|
||||
|
|
|
@ -32,7 +32,7 @@ The value returned by `contenthash` MUST be represented as a machine-readable [m
|
|||
|
||||
protoCodes and their meanings are specified in the [multiformats/multicodec](https://github.com/multiformats/multicodec) repository.
|
||||
|
||||
The encoding of the value depends on the content type specified by the protoCode. Values with protocodes of 0xee and 0xef represent IPFS and Swarm content; these values are encoded as v1 [CIDs](https://github.com/multiformats/cid) without a base prefix, meaning their value is formatted as follows:
|
||||
The encoding of the value depends on the content type specified by the protoCode. Values with protocodes of 0xe3 and 0xe4 represent IPFS and Swarm content; these values are encoded as v1 [CIDs](https://github.com/multiformats/cid) without a base prefix, meaning their value is formatted as follows:
|
||||
|
||||
```
|
||||
<protoCode uvarint><cid-version><multicodec-content-type><multihash-content-address>
|
||||
|
@ -42,6 +42,8 @@ When resolving a `contenthash`, applications MUST use the protocol code to deter
|
|||
|
||||
### Example
|
||||
|
||||
#### IPFS
|
||||
|
||||
Input data:
|
||||
|
||||
```
|
||||
|
@ -65,13 +67,50 @@ Text format:
|
|||
ipfs://QmRAQB6YaCyidP37UdDnjFY5vQuiBrcqdyoW1CuDgwxkD4
|
||||
```
|
||||
|
||||
### Swarm
|
||||
|
||||
Input data:
|
||||
|
||||
```
|
||||
storage system: Swarm (0xe4)
|
||||
CID version: 1 (0x01)
|
||||
content type: swarm-manifest (0xfa)
|
||||
hash function: keccak256 (0x1b)
|
||||
hash length: 32 bytes (0x20)
|
||||
hash: d1de9994b4d039f6548d191eb26786769f580809256b4685ef316805265ea162
|
||||
```
|
||||
|
||||
Binary format:
|
||||
```
|
||||
0xe40101fa011b20d1de9994b4d039f6548d191eb26786769f580809256b4685ef316805265ea162
|
||||
```
|
||||
|
||||
Text format:
|
||||
```
|
||||
bzz://d1de9994b4d039f6548d191eb26786769f580809256b4685ef316805265ea162
|
||||
```
|
||||
|
||||
Example usage with swarm hash:
|
||||
```
|
||||
$ swarm hash ens contenthash d1de9994b4d039f6548d191eb26786769f580809256b4685ef316805265ea162
|
||||
> e40101fa011b20d1de9994b4d039f6548d191eb26786769f580809256b4685ef316805265ea162
|
||||
```
|
||||
|
||||
### Fallback
|
||||
|
||||
In order to support names that have an IPFS or Swarm hash in their `content` field, a grace period MUST be implemented offering those name holders time to update their names. If a resolver does not support the `multihash` interface, it MUST be checked whether they support the `content` interface. If they do, the value of that field SHOULD be treated in a context dependent fashion and resolved. This condition MUST be enforced until at least March 31st, 2019.
|
||||
|
||||
### Implementation
|
||||
|
||||
To support `contenthash`, a new resolver has been developed and can be found [here](https://github.com/ensdomains/resolvers/blob/master/contracts/PublicResolver.sol), which has been deployed at [0xd3ddccdd3b25a8a7423b5bee360a42146eb4baf3](https://etherscan.io/address/0xd3ddccdd3b25a8a7423b5bee360a42146eb4baf3)
|
||||
To support `contenthash`, a new resolver has been developed and can be found [here](https://github.com/ensdomains/resolvers/blob/master/contracts/PublicResolver.sol), you can also find this smart contract deployed on:
|
||||
|
||||
* Mainnet : [0xd3ddccdd3b25a8a7423b5bee360a42146eb4baf3](https://etherscan.io/address/0xd3ddccdd3b25a8a7423b5bee360a42146eb4baf3)
|
||||
* Ropsten : [0xde469c7106a9fbc3fb98912bb00be983a89bddca](https://ropsten.etherscan.io/address/0xde469c7106a9fbc3fb98912bb00be983a89bddca)
|
||||
|
||||
There are also implementations in multiple languages to encode and decode `contenthash`:
|
||||
|
||||
* [JavaScript](https://github.com/pldespaigne/content-hash)
|
||||
* [Python](https://github.com/filips123/ContentHashPy)
|
||||
|
||||
## Copyright
|
||||
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
|
||||
|
|
|
@ -4,7 +4,7 @@ title: State clearing
|
|||
author: Vitalik Buterin
|
||||
type: Standards Track
|
||||
category: Core
|
||||
status: Replaced
|
||||
status: Superseded
|
||||
created: 2016-10-16
|
||||
superseded-by: 161
|
||||
---
|
||||
|
|
|
@ -21,7 +21,7 @@ Applications interacting with the blockchain often make use of additional, non-b
|
|||
## Specification
|
||||
|
||||
### Path levels
|
||||
We define the following 5 levels in BIP32 path:
|
||||
We define the following levels in BIP32 path:
|
||||
|
||||
```m / purpose' / coin_type' / subpurpose' / key_type' / key_index```
|
||||
|
||||
|
@ -35,15 +35,15 @@ This part is constant and set to ```m / 43' / 60' / 1581'```, meaning BIP 43 ->
|
|||
All subtrees under this prefix are the scope of this EIP.
|
||||
|
||||
### Key type
|
||||
Describes the purpose for which the key is being used. Key types should be generic. "Instant messaging" is a good example whereas "Whisper" is not. The reason is that you want to be able to use the same identity across different services. Key types are defined at: <to be defined>
|
||||
Describes the purpose for which the key is being used. Key types should be generic. "Instant messaging" is a good example whereas "Whisper" is not. The reason is that you want to be able to use the same identity across different services. Key types are defined at: TBD
|
||||
|
||||
Hardened derivation is used at this level.
|
||||
|
||||
### Key index
|
||||
Keys are numbered from index 0 in sequentially increasing manner.
|
||||
This number is used as child index in BIP32 derivation.
|
||||
The key index is a field of variable length identifying a specific key. In its simplest case, it is a number from 0 to 2^31-1. If a larger identifier is desired (for example representing a hash or a GUID), the value must be split
|
||||
across several BIP32 nesting levels, most significant bit first and left aligned, bit-padded with 0s if needed. All levels, except the last one must used hardened key derivation. The last level must use public derivation. This means that every level can carry 31-bit of the identifier to represent.
|
||||
|
||||
Public derivation is used at this level.
|
||||
As an example, let's assume we have a key with key type 4' and a key_index representing a 62-bit ID represented as hexadecimal 0x2BCDEFFEDCBAABCD the complete keypath would be ```m / 43' / 60' / 1581' / 4' / 1469833213' / 1555737549 ```. If you are using random identifiers, it might be convenient to generate a conventional GUID, for example 128-bit just fix the value of the most significant bit of each 32-bit word to 1 for all of them, except the last one which will be 0.
|
||||
|
||||
## Rationale
|
||||
The structure proposed above follows the BIP43 generic structure and is similar to the widely adopted BIP44 specification.
|
||||
|
|
|
@ -105,7 +105,7 @@ To use rules within a token is as easy as having the token inherit from WithRule
|
|||
|
||||
Below is a template for a rule.
|
||||
|
||||
```
|
||||
```solidity
|
||||
import "../interface/IRule.sol";
|
||||
|
||||
contract TemplateRule is IRule {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
eip: 160
|
||||
title: EXP cost increase
|
||||
author: Vitalik Buterin
|
||||
author: Vitalik Buterin (@vbuterin)
|
||||
type: Standards Track
|
||||
category: Core
|
||||
status: Final
|
||||
|
|
103
EIPS/eip-1613.md
103
EIPS/eip-1613.md
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
eip: 1613
|
||||
title: Gas stations network
|
||||
author: Yoav Weiss <yoav@tabookey.com>, Dror Tirosh <dror@tabookey.com>
|
||||
author: Yoav Weiss <yoav@tabookey.com>, Dror Tirosh <dror@tabookey.com>, Alex Forshtat <alex@tabookey.com>
|
||||
discussions-to: https://github.com/yoav-tabookey/EIPs/issues/1
|
||||
status: Draft
|
||||
type: Standards Track
|
||||
|
@ -58,7 +58,6 @@ Roles of a `Relay` node:
|
|||
* Maintain a hot wallet with a small amount of ETH, to pay for gas.
|
||||
* Provide a public interface for user apps to send gasless transactions via channels such as https or whisper.
|
||||
* Publish it's public interfaces and its price (as a multiplier of the actual transaction gas cost) in `RelayHub`.
|
||||
* Help `RelayHub` maintain the list of relays in a trustless way. Relays are incentivized to remove other verifiably-stale relays.
|
||||
* Optionally monitor reverted transactions of other relays through RelayHub, catching offending relays and claiming their stakes. This can be done by anyone, not just a relay.
|
||||
|
||||
Implementing a `RelayRecipient` contract:
|
||||
|
@ -66,20 +65,22 @@ Implementing a `RelayRecipient` contract:
|
|||
* Know the address of `RelayHub` and trust it to provide information about the transaction.
|
||||
* Maintain a small balance of ETH gas prepayment deposit in `RelayHub`. Can be paid directly by the `RelayRecipient` contract, or by the dapp's owner on behalf of the `RelayRecipient` address.
|
||||
The dapp owner is responsible for ensuring sufficient balance for the next transactions, and can stop depositing if something goes wrong, thus limiting the potential for abuse of system bugs. In DAO usecases it will be up to the DAO logic to maintain a sufficient deposit.
|
||||
* Use `get_sender()` and `get_data()` instead of `msg.sender` and `msg.data`, everywhere. `RelayRecipient` provides these functions and gets the information from `RelayHub`.
|
||||
* Implement a `accept_relayed_call(address relay, address from, bytes encoded_function, uint gas_price, uint transaction_fee )` view function that returns **zero** if and only if it is willing to accept a transaction and pay for it.
|
||||
`accept_relayed_call` is called by `RelayHub` as a view function when a `Relay` inquires it, and also during the actual transaction. Transactions are reverted if **non-zero**, and `Relay` only gets compensated for transactions (whether successful or reverted) if `accept_relayed_call` returns **zero**. Some examples of `accept_relayed_call()` implementations:
|
||||
* Use `getSender()` and `getMessageData()` instead of `msg.sender` and `msg.data`, everywhere. `RelayRecipient` provides these functions and gets the information from `RelayHub`.
|
||||
* Implement a `acceptRelayedCall(address relay, address from, bytes memory encodedFunction, uint gasPrice, uint transactionFee, bytes memory approval)` view function that returns **zero** if and only if it is willing to accept a transaction and pay for it.
|
||||
`acceptRelayedCall` is called by `RelayHub` as a view function when a `Relay` inquires it, and also during the actual transaction. Transactions are reverted if **non-zero**, and `Relay` only gets compensated for transactions (whether successful or reverted) if `acceptRelayedCall` returns **zero**. Some examples of `acceptRelayedCall()` implementations:
|
||||
* Whitelist of trusted dapp members.
|
||||
* Balance sheet of registered users, maintained by the dapp owner. Users pay the dapp with a credit card or other non-ETH means, and are credited in the `RelayRecipient` balance sheet.
|
||||
Users can never cost the dapp more than they were credited for.
|
||||
* A dapp can provide off-chain a signed message called `approval` to a transaction sender and validate it.
|
||||
* Whitelist of known transactions used for onboarding new users. This allows certain anonymous calls and is subject to Sybil attacks.
|
||||
Therefore it should be combined with a restricted gasPrice, and a whitelist of trusted relays, to reduce the incentive for relays to create bogus transactions and rob the dapp's prepaid gas deposit.
|
||||
Dapps allowing anonymous onboarding transactions might benefit from registering their own `Relay` and accepting anonymous transactions only from that `Relay`, whereas other transactions can be accepted from any relay.
|
||||
Alternatively, dapps may use the balance sheet method for onboarding as well, by applying the methods suggested in the attacks/mitigations section below.
|
||||
* Implement `post_relayed_call(address relay, address from, bytes encoded_function, bool success, uint used_gas, uint transaction_fee )`
|
||||
* Implement `preRelayedCall(address relay, address from, bytes memory encodedFunction, uint transactionFee) returns (bytes32)`. This method is called before a transaction is relayed. By default, it does nothing.
|
||||
|
||||
This method is called after a transaction is relayed. By default, it does nothing.
|
||||
It can be used as a method to charge the user in dapp-specific manner.
|
||||
* Implement `postRelayedCall(ddress relay, address from, bytes memory encodedFunction, bool success, uint usedGas, uint transactionFee, bytes32 preRetVal)`. This method is called after a transaction is relayed. By default, it does nothing.
|
||||
|
||||
These two methods can be used to charge the user in dapp-specific manner.
|
||||
|
||||
Glossary of terms used in the processes below:
|
||||
|
||||
|
@ -88,7 +89,7 @@ Glossary of terms used in the processes below:
|
|||
* `Sender` - an external address with a valid keypair but no ETH to pay for gas.
|
||||
* `Relay` - a node holding ETH in an external address, listed in RelayHub and relaying transactions from Senders to RelayHub for a fee.
|
||||
|
||||
![Sequence Diagram](http://bit.ly/2EWWVN8)
|
||||
![Sequence Diagram](http://bit.ly/2WZqM23)
|
||||
|
||||
The process of registering/refreshing a `Relay`:
|
||||
|
||||
|
@ -96,19 +97,14 @@ The process of registering/refreshing a `Relay`:
|
|||
* If starting for the first time (no key yet), generate a key pair for Relay's address.
|
||||
* If Relay's address doesn't hold sufficient funds for gas (e.g. because it was just generated), Relay stays inactive until its owner funds it.
|
||||
* Relay's owner funds it.
|
||||
* Relay sends the required stake to `RelayHub`.
|
||||
* Relay calls `RelayHub.register_relay(address owner, uint transaction_fee, string[] url, address optional_stale_relay_for_removal)`, with its `owner` (the address that funded it),
|
||||
the relay's `transaction fee` (as a multiplier on transaction gas cost), and one or more URL for incoming transactions.
|
||||
The `optional_stale_relay_for_removal` arg is the address of a stale relay found in the list.
|
||||
* `RelayHub` checks Relay.balance and emits `NeedsFunding(Relay)` to alert the owner if it runs low.
|
||||
* Relay's owner sends the required stake to `RelayHub` by calling `RelayHub.stake(address relay, uint unstakeDelay)`.
|
||||
* `RelayHub` puts the `owner` and `unstake delay` in the relays map, indexed by `relay` address.
|
||||
* Relay calls `RelayHub.registerRelay(uint transactionFee, string memory url)` with the relay's `transaction fee` (as a multiplier on transaction gas cost), and a URL for incoming transactions.
|
||||
* `RelayHub` ensures that Relay has a sufficient stake.
|
||||
* `RelayHub` puts the `owner`, current `timestamp`, `transaction fee`, and `urls`, in the relays map, indexed by `relay` address.
|
||||
* `RelayHub` emits an event, `RelayAdded(Relay, transaction_fee, relay_stake, urls)`.
|
||||
* If `optional_stale_relay_for_removal` is in the relays map and is stale (hasn't communicated in a few days), `RelayHub` removes it.
|
||||
Relay benefits by receiving a gas refund for the freed storage, so it's incentivized to always include a stale relay if there is one.
|
||||
* Relay starts a timer to perform a `keepalive` transaction after a certain amount of time if no real transactions are relayed through it.
|
||||
`Relay` is considered stale if it hasn't sent anything to `RelayHub` in a while, e.g. 4 days.
|
||||
* `Relay` goes to sleep and waits signing requests.
|
||||
* `RelayHub` puts the `transaction fee` in the relays map.
|
||||
* `RelayHub` emits an event, `RelayAdded(Relay, owner, transactionFee, relayStake, unstakeDelay, url)`.
|
||||
* Relay starts a timer to perform a `keepalive` transaction every 6000 blocks.
|
||||
* `Relay` goes to sleep and waits for signing requests.
|
||||
|
||||
The process of sending a relayed transaction:
|
||||
|
||||
|
@ -120,22 +116,25 @@ The process of sending a relayed transaction:
|
|||
* Sender prepares the transaction with Sender's address, the recipient address, the actual transaction data, Relay's transaction fee, gas price, gas limit, its current nonce from `RelayHub.nonces`, RelayHub's address, and Relay's address, and then signs it.
|
||||
* Sender verifies that `RelayHub.balances[recipient]` holds enough ETH to pay Relay's fee.
|
||||
* Sender verifies that `Relay.balance` has enough eth to send the transaction
|
||||
* Sender sends the signed transaction to Relay's web interface.
|
||||
* Sender reads the Relay's current `nonce` value and decides on the `max_nonce` parameter.
|
||||
* Sender sends the signed transaction amd metadata to Relay's web interface.
|
||||
* `Relay` wraps the transaction with a transaction to `RelayHub`, with zero ETH value.
|
||||
* `Relay` signs the wrapper transaction with its key in order to pay for gas.
|
||||
* `Relay` verifies that:
|
||||
* The transaction's recipient contract will accept this transaction when submitted, by calling `RelayHub.can_relay()`, a view function,
|
||||
which checks the recipient's `accept_relayed_call`, also a view function, stating whether it's willing to accept the charges).
|
||||
* The transaction's recipient contract will accept this transaction when submitted, by calling `RelayHub.canRelay()`, a view function,
|
||||
which checks the recipient's `acceptRelayedCall`, also a view function, stating whether it's willing to accept the charges).
|
||||
* The transaction nonce matches `RelayHub.nonces[sender]`.
|
||||
* The relay address in the transaction matches Relay's address.
|
||||
* The transaction's recipient has enough ETH deposited in `RelayHub` to pay the transaction fee.
|
||||
* Relay has enough ETH to pay for the gas required by the transaction.
|
||||
* Value of `max_nonce` is higher than current Relay's `nonce`
|
||||
* If any of Relay's checks fail, it returns an error to sender, and doesn't proceed.
|
||||
* Relay submits the signed wrapped transaction to the blockchain.
|
||||
* Relay immediately returns the signed wrapped transaction to the sender. This step is discussed below, in attacks/mitigations.
|
||||
* `Sender` receives the wrapped transaction and verifies that:
|
||||
* It's a valid relay call to `RelayHub`. from Relay's address.
|
||||
* The transaction's ethereum nonce matches Relay's current nonce.
|
||||
* The transaction's ethereum nonce is lower than or equal to `max_nonce`.
|
||||
* `Relay` is sufficiently funded to pay for it.
|
||||
* The wrapped transaction is valid and signed by `sender`.
|
||||
* Recipient contract has sufficient funds in `RelayHub.balances` to pay for Relay's fee as stated in the transaction.
|
||||
|
@ -145,35 +144,34 @@ The process of sending a relayed transaction:
|
|||
This step is not strictly necessary, for reasons discussed below in attacks/mitigations, but may speed things up.
|
||||
* `Sender` monitors the blockchain, waiting for the transaction to be mined.
|
||||
The transaction was verified, with Relay's current nonce, so mining must be successful unless Relay submitted another (different) transaction with the same nonce.
|
||||
If mining fails due to such attack, sender may call `RelayHub.penalize_repeated_nonce` through another relay, to collect the offending relay's stake, and then go back to selecting a new Relay for the transaction.
|
||||
If mining fails due to such attack, sender may call `RelayHub.penalizeRepeatedNonce` through another relay, to collect his reward and burn the remainder of the offending relay's stake, and then go back to selecting a new Relay for the transaction.
|
||||
See discussion in the attacks/mitigations section below.
|
||||
* `RelayHub` receives the transaction:
|
||||
* Records `gasLeft()` as initial_gas for later payment.
|
||||
* Records `gasleft()` as `initialGas` for later payment.
|
||||
* Verifies the transaction is sent from a registered relay.
|
||||
* Verifies that the signature of the internal transaction matches its stated origin (sender's key).
|
||||
* Verifies that the relay address written in the transaction matches msg.sender.
|
||||
* Verifies that the transaction's `nonce` matches the stated origin's nonce in `RelayHub.nonces`.
|
||||
* Checks `Relay.balance` and emits `NeedsFunding(Relay)` to alert the owner if it runs low.
|
||||
* Calls recipient's `accept_relayed_call` function, asking whether it's going to accept the transaction. If not, `RelayHub` reverts.
|
||||
In this case, Relay doesn't get paid, as it was its responsibility to check `RelayHub.can_relay` before releasing the transaction.
|
||||
* Sends the transaction to the recipient. The call is made using `call()`, so reverts won't kill the transaction, just return false.
|
||||
* Calls recipient's `acceptRelayedCall` function, asking whether it's going to accept the transaction. If not, the `TransactionRelayed` will be emitted with status `CanRelayFailed`, and `chargeOrCanRelayStatus` will contain the return value of `acceptRelayedCall`. In this case, Relay doesn't get paid, as it was its responsibility to check `RelayHub.canRelay` before releasing the transaction.
|
||||
* Calls recipient's `preRelayedCall` function. If this call reverts the `TransactionRelayed` will be emitted with status `PreRelayedFailed`.
|
||||
* Sends the transaction to the recipient. If this call reverts the `TransactionRelayed` will be emitted with status `RelayedCallFailed`.
|
||||
When passing gas to `call()`, enough gas is preserved by `RelayHub`, for post-call handling. Recipient may run out of gas, but `RelayHub` never does.
|
||||
`RelayHub` also sends sender's address at the end of `msg.data`, so `RelayRecipient.get_sender()` will be able to extract the real sender, and trust it because the transaction came from the known `RelayHub` address.
|
||||
`RelayHub` also sends sender's address at the end of `msg.data`, so `RelayRecipient.getSender()` will be able to extract the real sender, and trust it because the transaction came from the known `RelayHub` address.
|
||||
* Recipient contract handles the transaction.
|
||||
* `RelayHub` calls recipient's `post_relayed_call`
|
||||
* `RelayHub` checks call's return value of call, and emits `TransactionRelayed(transaction_hash, bool result)`.
|
||||
* `RelayHub` calls recipient's `postRelayedCall`.
|
||||
* `RelayHub` checks call's return value of call, and emits `TransactionRelayed(address relay, address from, address to, bytes4 selector, uint256 status, uint256 chargeOrCanRelayStatus)`.
|
||||
* `RelayHub` increases `RelayHub.nonces[sender]`.
|
||||
* `RelayHub` transfers ETH balance from recipient to `Relay.owner`, to pay the transaction fee, based on the measured transaction cost.
|
||||
Note on relay payment: The relay gets paid for actual gas used, regardless of whether the recipient reverted.
|
||||
The only case where the relay sustains a loss, is if can_relay returns non-zero, since the relay was responsible to verify this view function prior to submitting.
|
||||
The only case where the relay sustains a loss, is if `canRelay` returns non-zero, since the relay was responsible to verify this view function prior to submitting.
|
||||
Any other revert is caught and paid for. See attacks/mitigations below.
|
||||
* `Relay` keeps track of transactions it sent, and waits for `TransactionRelayed` events to see the charge.
|
||||
If a transaction reverts and goes unpaid, which means the recipient's `accept_relayed_call()` function was inconsistent, `Relay` refuses service to that recipient for a while (or blacklists it indefinitely, if it happens often).
|
||||
If a transaction reverts and goes unpaid, which means the recipient's `acceptRelayedCall()` function was inconsistent, `Relay` refuses service to that recipient for a while (or blacklists it indefinitely, if it happens often).
|
||||
See attacks/mitigations below.
|
||||
|
||||
The process of winding a `Relay` down:
|
||||
|
||||
* Relay's owner (the address that initially funded it) calls `RelayHub.remove_relay_by_owner(Relay)`.
|
||||
* Relay's owner (the address that initially funded it) calls `RelayHub.removeRelayByOwner(Relay)`.
|
||||
* `RelayHub` ensures that the sender is indeed Relay's owner, then removes `Relay`, and emits `RelayRemoved(Relay)`.
|
||||
* `RelayHub` starts the countdown towards releasing the owner's stake.
|
||||
* `Relay` receives its `RelayRemoved` event.
|
||||
|
@ -181,15 +179,6 @@ The process of winding a `Relay` down:
|
|||
* `Relay` shuts down.
|
||||
* Once the owner's unstake delay is over, owner calls `RelayHub.unstake()`, and withdraws the stake.
|
||||
|
||||
Removal of stale/invalid relays:
|
||||
|
||||
* During registration/refresh, `Relay` helps purging stale relays.
|
||||
* `Relay` scans the relays in `RelayHub`, e.g. by going through old `RelayAdded` events.
|
||||
* `Relay` looks for stale relays (where the latest recorded `timestamp` is a few days ago).
|
||||
* If `Relay` finds such relay, it passes the stale relay as `optional_relay_removal` during registration.
|
||||
* `RelayHub` verifies that the reported stale relay is indeed stale or invalid, removes it from the relays map and emits `RelayRemoved(r)`.
|
||||
The storage refund offsets Relay's registration cost, so `Relay` is incentivized to remove a stale relay whenever if can find one.
|
||||
|
||||
## Rationale
|
||||
The rationale for the gas stations network design is a combination of two sets of requirements: Easy adoption, and robustness.
|
||||
|
||||
|
@ -229,17 +218,24 @@ However, the attack will backfire and cost Relay its entire stake.
|
|||
|
||||
Sender has a signed transaction from Relay with nonce N, and also gets a mined transaction from the blockchain with nonce N, also signed by Relay.
|
||||
This proves that Relay performed a DoS attack against the sender.
|
||||
The sender calls `RelayHub.penalize_repeated_nonce(bytes transaction1, bytes transaction2)`, which verifies the attack, confiscates Relay's stake,
|
||||
and splits it between the sender and the other relay who delivered the penalize_repeated_nonce call.
|
||||
The sender calls `RelayHub.penalizeRepeatedNonce(bytes transaction1, bytes transaction2)`, which verifies the attack, confiscates Relay's stake,
|
||||
and sends half of it to the sender who delivered the `penalizeRepeatedNonce` call. The other half of the stake is burned by sending it to `address(0)`. Burning is done to prevent cheating relays from effectively penalizing themselves and getting away without any loss.
|
||||
The sender then proceeds to select a new relay and send the original transaction.
|
||||
|
||||
The result of such attack is a delay of a few blocks in sending the transaction (until the attack is detected) but the relay gets removed and loses its entire stake.
|
||||
Scaling such attack would be prohibitively expensive, and actually quite profitable for senders and honest relays.
|
||||
|
||||
##### Attack: Dapp attempts to burn relays funds by implementing an inconsistent accept_relayed_call() and using multiple sender addresses to generate expensive transactions, thus performing a DoS attack on relays and reducing their profitability.
|
||||
In this attack, a contract sets an inconsistent accept_relayed_call (e.g. return zero for even blocks, nonzero for odd blocks), and uses it to exhaust relay resources through unpaid transactions.
|
||||
##### Attack: Relay attempts to censor a transaction by signing it, but using a nonce higher than it's current nonce.
|
||||
In this attack, the Relay did create and return a perfectly valid transaction, but it will not be mined until this Relay fills the gap in the nonce with 'missing' transactions.
|
||||
This may delay the relaying of some transactions indefinitely. In order to mitigate that, the sender includes a `max_nonce` parameter with it's signing request.
|
||||
It is suggested to be higher by 2-3 from current nonce, to allow the relay process several transactions.
|
||||
|
||||
When the sender receives a transaction signed by a Relay he validates that the nonce used is valid, and if it is not, the client will ignore the given relay and use other relays to relay given transaction. Therefore, there will be no actual delay introduced by such attack.
|
||||
|
||||
##### Attack: Dapp attempts to burn relays funds by implementing an inconsistent acceptRelayedCall() and using multiple sender addresses to generate expensive transactions, thus performing a DoS attack on relays and reducing their profitability.
|
||||
In this attack, a contract sets an inconsistent acceptRelayedCall (e.g. return zero for even blocks, nonzero for odd blocks), and uses it to exhaust relay resources through unpaid transactions.
|
||||
Relays can easily detect it after the fact.
|
||||
If a transaction goes unpaid, the relay knows that the recipient contract's accept_relayed_call has acted inconsistently, because the relay has verified its view function before sending the transaction.
|
||||
If a transaction goes unpaid, the relay knows that the recipient contract's acceptRelayedCall has acted inconsistently, because the relay has verified its view function before sending the transaction.
|
||||
It might be the result of a rare race condition where the contract's state has changed between the view call and the transaction, but if it happens too frequently, relays will blacklist this contract and refuse to serve transactions to it.
|
||||
Each offending contract can only cause a small damage (e.g. the cost of 2-3 transactions) to a relay, before getting blacklisted.
|
||||
|
||||
|
@ -255,12 +251,12 @@ This protection is probably an overkill, since the attack doesn't scale regardle
|
|||
|
||||
##### Attack: User attempts to rob dapps by registering its own relay and sending expensive transactions to dapps.
|
||||
If a malicious sender repeatedly abuses a recipient by sending meaningless/reverted transactions and causing the recipient to pay a relay for nothing,
|
||||
it is the recipient's responsibility to blacklist that sender and have its accept_relayed_call function return nonzero for that sender.
|
||||
it is the recipient's responsibility to blacklist that sender and have its acceptRelayedCall function return nonzero for that sender.
|
||||
Collect calls are generally not meant for anonymous senders unknown to the recipient.
|
||||
Dapps that utilize the gas station networks should have a way to blacklist malicious users in their system and prevent Sybil attacks.
|
||||
|
||||
A simple method that mitigates such Sybil attack, is that the dapp lets users buy credit with a credit card, and credit their account in the dapp contract,
|
||||
so accept_relayed_call() only returns zero for users that have enough credit, and deduct the amount paid to the relay from the user's balance, whenever a transaction is relayed for the user.
|
||||
so acceptRelayedCall() only returns zero for users that have enough credit, and deduct the amount paid to the relay from the user's balance, whenever a transaction is relayed for the user.
|
||||
With this method, the attacker can only burn its own resources, not the dapp's.
|
||||
|
||||
A variation of this method, for free dapps (that don't charge the user, and prefer to pay for their users transactions) is to require a captcha during user creation in their web interface,
|
||||
|
@ -275,9 +271,6 @@ After it caused this minor delay and got blacklisted, the attacker must wait a m
|
|||
Simultaneously bringing up a number of unreliable relays, large enough to cause a noticeable network delay, would be prohibitively expensive due to the required stake,
|
||||
and even then, all those relays will get blacklisted within a short time.
|
||||
|
||||
##### Attack: Relay attempts to unregister other relays.
|
||||
Removal of stale relays is trustless. RelayHub verifies whether the removed relay has performed any action recently, and would revert any transaction that tries to remove an active relay.
|
||||
|
||||
##### Attack: Attacker attempts to replay a relayed transaction.
|
||||
Transactions include a nonce. RelayHub maintains a nonce (counter) for each sender. Transactions with bad nonces get reverted by RelayHub. Each transaction can only be relayed once.
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ This EIP contains the following core ideas:
|
|||
Potential advanced uses of attribute registries include:
|
||||
* Encoding complex boolean expressions which combine multiple attributes into a single uint256 key, which is then parsed and evaluated by the registry logic.
|
||||
* Using values associated with an attribute to query additional on-chain or off-chain metadata.
|
||||
* Resolving attribute values by calling into seperate attribute registries or other contracts, delegating authority without changing the interface of the registry.
|
||||
* Resolving attribute values by calling into separate attribute registries or other contracts, delegating authority without changing the interface of the registry.
|
||||
|
||||
## 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.-->
|
||||
|
@ -38,7 +38,7 @@ This EIP proposes a light-weight abstraction layer for a standard account metada
|
|||
## 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)).-->
|
||||
The Attribute Registry interface contains four functions, outlined as follows:
|
||||
```
|
||||
```solidity
|
||||
/**
|
||||
* @title EIP-1616 Attribute Registry Standard interface. EIP-165 ID: 0x5f46473f
|
||||
*/
|
||||
|
@ -53,7 +53,7 @@ interface AttributeRegistryInterface {
|
|||
Contracts that comply with the Attribute Registry EIP MUST implement the above interface.
|
||||
|
||||
As an additional requirement, the ERC-165 interface MUST be included:
|
||||
```
|
||||
```solidity
|
||||
/**
|
||||
* @title EIP-165 interface. EIP-165 ID: 0x01ffc9a7
|
||||
*/
|
||||
|
@ -73,7 +73,7 @@ The implementation MUST follow the specifications described below.
|
|||
The view functions detailed below MUST be implemented.
|
||||
|
||||
#### `hasAttribute` function
|
||||
```
|
||||
```solidity
|
||||
function hasAttribute(address account, uint256 attributeTypeID) external view returns (bool)
|
||||
```
|
||||
|
||||
|
@ -86,7 +86,7 @@ _**NOTE**_: This function MUST return two equal values when performing two direc
|
|||
|
||||
|
||||
#### `getAttributeValue` function
|
||||
```
|
||||
```solidity
|
||||
function getAttributeValue(address account, uint256 attributeTypeID) external view returns (uint256)
|
||||
```
|
||||
|
||||
|
@ -97,7 +97,7 @@ _**NOTE**_: This function MUST revert if a directly preceding or subsequent func
|
|||
_**NOTE**_: This function MUST return two equal values when performing two directly consecutive function calls with identical `account` and `attributeTypeID` parameters, regardless of differences in the caller's address, the transaction origin, or other out-of-band information.
|
||||
|
||||
#### `countAttributeTypes` function
|
||||
```
|
||||
```solidity
|
||||
function countAttributeTypes() external view returns (uint256)
|
||||
```
|
||||
|
||||
|
@ -108,7 +108,7 @@ _**NOTE**_: This function MUST return a positive integer value - i.e. calling t
|
|||
_**NOTE**_: This function MUST return a value that encompasses all indexes of attribute type IDs whereby a call to `hasAttribute` on some address with an attribute type ID at the given index would return `true`.
|
||||
|
||||
#### `getAttributeTypeID` function
|
||||
```
|
||||
```solidity
|
||||
function getAttributeTypeID(uint256 index) external view returns (uint256)
|
||||
```
|
||||
|
||||
|
@ -136,7 +136,7 @@ Targeted test cases with 100% code coverage can be found at [this repository](ht
|
|||
<!--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.-->
|
||||
The basic implementation that follows can be found at [this repository](https://github.com/0age/AttributeRegistry) (see [here](https://github.com/TPL-protocol/tpl-contracts/blob/master/contracts/BasicJurisdiction.sol#L399) for an example of a more complex implementing contract):
|
||||
|
||||
```
|
||||
```solidity
|
||||
pragma solidity ^0.4.25;
|
||||
|
||||
/**
|
||||
|
@ -213,7 +213,7 @@ contract AttributeRegistry is AttributeRegistryInterface {
|
|||
mapping(address => mapping(uint256 => uint256)) private _issuedAttributeValues;
|
||||
|
||||
/**
|
||||
* @notice The constructor function, defines the two attribute types avaiable
|
||||
* @notice The constructor function, defines the two attribute types available
|
||||
* on this particular registry.
|
||||
*/
|
||||
constructor() public {
|
||||
|
|
|
@ -135,7 +135,7 @@ The following table outlines what portion of the balance held in a deed contract
|
|||
|
||||
### Deployment and Upgrade process
|
||||
|
||||
The Initial Registrar requires the ENS's address as a contructor, and should be deployed after the ENS. The multisig account owning the root node in the ENS should then set the Initial Registrar's address as owner of the `eth` node.
|
||||
The Initial Registrar requires the ENS's address as a constructor, and should be deployed after the ENS. The multisig account owning the root node in the ENS should then set the Initial Registrar's address as owner of the `eth` node.
|
||||
|
||||
The Initial Registrar is expected to be replaced by a Permanent Registrar approximately 2 years after deployment. The following process should be used for the upgrade:
|
||||
1. The Permanent Registrar contract will be deployed.
|
||||
|
@ -226,7 +226,7 @@ A slower release allows for extra time to identify, and address any issues which
|
|||
|
||||
Choosing a single TLD helps to maximize network effects by focusing on one namespace.
|
||||
|
||||
A three letter TLD is a pattern made familiar by it's common usage in internet domain names. This familiarity significantly increases the potential of the ENS to be integrated into pre-existing DNS systems, and reserved as a [special-use domain name](http://www.iana.org/assignments/special-use-domain-names/special-use-domain-names.xhtml#special-use-domain). A recent precedent for this is the [reservation of the `.onion` domain](https://tools.ietf.org/html/rfc7686).
|
||||
A three letter TLD is a pattern made familiar by it's common usage in internet domain names. This familiarity significantly increases the potential of the ENS to be integrated into pre-existing DNS systems, and reserved as a [special-use domain name](https://www.iana.org/assignments/special-use-domain-names/special-use-domain-names.xhtml#special-use-domain). A recent precedent for this is the [reservation of the `.onion` domain](https://tools.ietf.org/html/rfc7686).
|
||||
|
||||
### Holding ether as collateral
|
||||
|
||||
|
@ -243,3 +243,6 @@ This document borrows heavily from several sources:
|
|||
- 2016-10-26 Added link Alex's design in abstract
|
||||
- 2016-11-01 change 'Planned deactivation' to h3'
|
||||
- 2017-03-13 Update timelines for bidding and reveal periods
|
||||
|
||||
## Copyright
|
||||
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
|
||||
|
|
|
@ -0,0 +1,305 @@
|
|||
---
|
||||
eip: 1620
|
||||
title: ERC-1620 Money Streaming
|
||||
author: Paul Berg (@PaulRBerg) <hello@paulrberg.com>
|
||||
discussions-to: https://github.com/ethereum/EIPs/issues/1620
|
||||
status: Draft
|
||||
type: Standards Track
|
||||
category: ERC
|
||||
created: 2018-11-24
|
||||
---
|
||||
|
||||
<!--You can leave these HTML comments in your merged EIP and delete the visible duplicate text guides, they will not appear and may be helpful to refer to if you edit it again. This is the suggested template for new EIPs. Note that an EIP number will be assigned by an editor. When opening a pull request to submit your EIP, please use an abbreviated title in the filename, `eip-draft_title_abbrev.md`. 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.-->
|
||||
Money streaming represents the idea of continuous payments over a finite period of time. Block numbers are used as a proxy of time to continuously update balances.
|
||||
|
||||
## Abstract
|
||||
<!--A short (~200 word) description of the technical issue being addressed.-->
|
||||
The following describes a standard whereby time is measured using block numbers and streams are mappings in a master contract.
|
||||
|
||||
1. A provider sets up a money streaming contract.
|
||||
2. A prospective payer can interact with the contract and start the stream right away by depositing the funds required for the chosen period.
|
||||
3. The payee is able to withdraw money from the contract based on its ongoing solvency. That is: `payment rate * (current block height - starting block height)`
|
||||
4. The stream terms (payment rate, length, metadata) can be updated at any time if both parties pledge their signatures.
|
||||
5. The stream can be stopped at any point in time by any party without on-chain consensus.
|
||||
6. If the stream period ended and it was not previously stopped by any party, the payee is entitled to withdraw all the deposited funds.
|
||||
|
||||
## 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.-->
|
||||
This standardised interface aims to change the way we think about long-term financial commitments. Thanks to blockchains, payments need not be sent in chunks (e.g. monthly salaries), as there is much less overhead in paying-as-you-go. Money as a function of time would better align incentives in a host of scenarios.
|
||||
|
||||
### Use Cases
|
||||
|
||||
This is just a preliminary list of use cases. There are other spooky ideas interesting to explore, such as time-dependent disincetivisation, but, for brevity, we have not included them here.
|
||||
|
||||
- Salaries
|
||||
- Subscriptions
|
||||
- Consultancies
|
||||
- CDPs
|
||||
- Rent
|
||||
- Parking
|
||||
|
||||
### Crowdsales
|
||||
[RICOs](https://github.com/lukso-network/rico), or Reversible ICOs, were introduced at Devcon4 by @frozeman. The idea is to endow investors with more power and safety guarantees by allowing them to "reverse" the investment based on the evolution of the project. We previously discussed a similar concept called SICOs, or Streamable ICOs, in this research [thread](https://ethresear.ch/t/chronos-a-quirky-application-proposal-for-plasma/2928/14?u=paulrberg).
|
||||
|
||||
Instead of investing a lump sum and giving the money away to the project developers, funds are held in a smart contract which allocates money based on the passage of time. Project developers can withdraw funds as the stream stays active, while investors have the power to get back a significant percentage of their initial commitment if the project halts.
|
||||
|
||||
## 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)).-->
|
||||
|
||||
|
||||
### Structs
|
||||
|
||||
The structure of a `stream` should be as follows:
|
||||
|
||||
- `stream`
|
||||
- `sender`: the `address` of the entity funding the stream
|
||||
- `recipient`: the `address` where the money is being delivered to
|
||||
- `tokenAddress`: the `address` of the ERC20 token used as payment asset
|
||||
- `balance`: the total funds left in the stream
|
||||
- `timeframe`: as defined below
|
||||
- `rate`: as defined below
|
||||
|
||||
```solidity
|
||||
struct Stream {
|
||||
address sender;
|
||||
address recipient;
|
||||
address tokenAddress;
|
||||
uint256 balance;
|
||||
Timeframe timeframe;
|
||||
Rate rate;
|
||||
}
|
||||
```
|
||||
|
||||
- `timeframe`
|
||||
- `start`: the starting block number of the stream
|
||||
- `stop`: the stopping block number of the stream
|
||||
|
||||
```solidity
|
||||
struct Timeframe {
|
||||
uint256 start;
|
||||
uint256 stop;
|
||||
}
|
||||
```
|
||||
|
||||
- `rate`
|
||||
- `payment`: how much money moves from `sender` to `recipient`
|
||||
- `interval`: how often `payment` moves from `sender` to `recipient`
|
||||
|
||||
```solidity
|
||||
struct Rate {
|
||||
uint256 payment;
|
||||
uint256 interval;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Methods
|
||||
|
||||
#### balanceOf
|
||||
|
||||
Returns available funds for the given stream id and address.
|
||||
|
||||
```solidity
|
||||
function balanceOf(uint256 _streamId, address _addr)
|
||||
```
|
||||
|
||||
#### getStream
|
||||
|
||||
Returns the full stream data, if the id points to a valid stream.
|
||||
|
||||
```solidity
|
||||
function getStream(uint256 _streamId) returns (address sender, address recipient, address tokenAddress, uint256 balance, uint256 startBlock, uint256 stopBlock, uint256 payment, uint256 interval)
|
||||
```
|
||||
|
||||
#### create
|
||||
|
||||
Creates a new stream between `msg.sender` and `_recipient`.
|
||||
|
||||
MUST allow senders to create multiple streams in parallel. SHOULD not accept Ether and only use ERC20-compatible tokens.
|
||||
|
||||
**Triggers Event**: [LogCreate](#logcreate)
|
||||
|
||||
```solidity
|
||||
function create(address _recipient, address _tokenAddress, uint256 _startBlock, uint256 _stopBlock, uint256 _payment, uint256 _interval)
|
||||
```
|
||||
|
||||
#### withdraw
|
||||
|
||||
Withdraws all or a fraction of the available funds.
|
||||
|
||||
MUST allow only the recipient to perform this action.
|
||||
|
||||
**Triggers Event**: [LogWithdraw](#logwithdraw)
|
||||
|
||||
```solidity
|
||||
function withdraw(uint256 _streamId, uint256 _funds)
|
||||
```
|
||||
|
||||
#### redeem
|
||||
|
||||
Redeems the stream by distributing the funds to the sender and the recipient.
|
||||
|
||||
SHOULD allow any party to redeem the stream.
|
||||
|
||||
**Triggers Event**: [LogRedeem](#logredeem)
|
||||
|
||||
```solidity
|
||||
function redeem(uint256 _streamId)
|
||||
```
|
||||
|
||||
#### confirmUpdate
|
||||
|
||||
Signals one party's willingness to update the stream
|
||||
|
||||
SHOULD allow any party to do this but MUST NOT be executed without consent from all involved parties.
|
||||
|
||||
**Triggers Event**: [LogConfirmUpdate](#logconfirmupdate)
|
||||
|
||||
**Triggers Event**: [LogExecuteUpdate](#logexecuteupdate) when the last involved party calls this function
|
||||
|
||||
```solidity
|
||||
function update(uint256 _streamId, address _tokenAddress, uint256 _stopBlock, uint256 _payment, uint256 _interval)
|
||||
```
|
||||
|
||||
#### revokeUpdate
|
||||
|
||||
Revokes an update proposed by one of the involved parties.
|
||||
|
||||
MUST allow any party to do this.
|
||||
|
||||
**Triggers Event**: [LogRevokeUpdate](#logrevokeupdate)
|
||||
|
||||
```solidity
|
||||
function confirmUpdate(uint256 _streamId, address _tokenAddress, uint256 _stopBlock, uint256 _payment, uint256 _interval)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Events
|
||||
|
||||
#### LogCreate
|
||||
|
||||
MUST be triggered when `create` is successfully called.
|
||||
|
||||
```solidity
|
||||
event LogCreate(uint256 indexed _streamId, address indexed _sender, address indexed _recipient, address _tokenAddress, uint256 _startBlock, uint256 _stopBlock, uint256 _payment, uint256 _interval)
|
||||
```
|
||||
|
||||
#### LogWithdraw
|
||||
|
||||
MUST be triggered when `withdraw` is successfully called.
|
||||
|
||||
```solidity
|
||||
event LogWithdraw(uint256 indexed _streamId, address indexed _recipient, uint256 _funds)
|
||||
```
|
||||
|
||||
#### LogRedeem
|
||||
|
||||
MUST be triggered when `redeem` is successfully called.
|
||||
|
||||
```solidity
|
||||
event LogRedeem(uint256 indexed _streamId, address indexed _sender, address indexed _recipient, uint256 _senderBalance, uint256 _recipientBalance)
|
||||
```
|
||||
|
||||
#### LogConfirmUpdate
|
||||
|
||||
MUST be triggered when `confirmUpdate` is successfully called.
|
||||
|
||||
```solidity
|
||||
event LogConfirmUpdate(uint256 indexed _streamId, address indexed _confirmer, address _newTokenAddress, uint256 _newStopBlock, uint256 _newPayment, uint256 _newInterval);
|
||||
```
|
||||
|
||||
#### LogRevokeUpdate
|
||||
|
||||
MUST be triggered when `revokeUpdate` is successfully called.
|
||||
|
||||
```solidity
|
||||
event LogRevokeUpdate(uint256 indexed _streamId, address indexed revoker, address _newTokenAddress, uint256 _newStopBlock, uint256 _newPayment, uint256 _newInterval)
|
||||
```
|
||||
|
||||
#### LogExecuteUpdate
|
||||
|
||||
MUST be triggered when an update is approved by all involved parties.
|
||||
|
||||
```solidity
|
||||
event LogExecuteUpdate(uint256 indexed _newStreamId, address indexed _sender, address indexed _recipient, address _newTokenAddress, uint256 _newStopBlock, uint256 _newPayment, uint256 _newInterval)
|
||||
```
|
||||
|
||||
## 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.-->
|
||||
|
||||
This specification was designed to serve as an entry point to the quirky concept of money as a function of time and it is definitely not set in stone. Several other designs, including payment channels and Plasma chains were also considered, but they were eventually deemed dense in assumptions unnecessary for an initial version.
|
||||
|
||||
<!--
|
||||
- Block times and oracles for time calculation
|
||||
- GCD
|
||||
- Miners
|
||||
- Sidechain-compatible (and preferable)
|
||||
- The `update` function
|
||||
- Multi-hop streams
|
||||
-->
|
||||
|
||||
Block times are a reasonable, trustless proxy for time on the blockchain. Between 2016 and 2018, the Ethereum block time average value [hovered](https://etherscan.io/chart/blocktime) around 14 seconds, excluding the last two quarters of 2017. Mathematically speaking, it would be ideal to have a standard deviation as close to 0 as possible, but that is not how things work in the real world. This has huge implications on the feasibility of this ERC which we shall investigate below.
|
||||
|
||||
### GCD
|
||||
When setting up a stream, a payer and a payee may want to make the total streaming duration a multiple of the "greatest common denominator" (GCD) of the chain they operate on; that is, the average block time. This is not imperative in the smart contracts per se, but there needs to be an off-chain process to map streams to real world time units in order to create a sound and fair payment mechanism.
|
||||
|
||||
### Block Times
|
||||
Because there is uncertainty regarding block times, streams may not be settled on the blockchain as initially planned. Let `$d` be the total streaming duration measured in seconds, `$t` the average block time before the stream started and `$t'` the actual average block time over `$d` after the stream started. We distinguish two undesirable scenarios:
|
||||
|
||||
1. `$t` < `$t'`: the payee will get their funds *later* than expected
|
||||
|
||||
2. `$t` > `$t'`: the payee will get their funds *sooner* than expected
|
||||
|
||||
If the combined error delta is smaller than the payment rate (fifth parameter of the `create` method, measured in wei), there is no problem at all. Conversely, we stumble upon trust issues because real-world time frames do not correspond to the stream terms. For instance, if an employee is normally entitled to withdraw all the funds from the stream at the end of the month, but block times cause case 1 from above to occur, the employee is in a financial disadvantage because their continuous effort is not compensated as promised.
|
||||
|
||||
Limiting the problem scope only to Ethereum, we propose two remedies:
|
||||
|
||||
1. Consensus on calling the `update` function to correct the stream terms. This might sound preposterous, but in most cases the stakes are low and stream participants are involved in long-term financial commitments. There is a high disincentive to refuse to cooperate.
|
||||
|
||||
2. Autonomously fix significant error deltas. In theory, we could achieve this using previous blocks' timestamps, "checkpointing" the stream once in a predefined number of blocks. This is still an area of active research because of potentially high overheads in gas costs.
|
||||
|
||||
Nonetheless, it is important to note that this is still a major improvement on the traditional model where absolute trust is required.
|
||||
|
||||
### Sidechains
|
||||
|
||||
It could be more efficient to implement this standard on independent sidechains like [POA Network](https://poa.network) or [xDai](https://medium.com/poa-network/poa-network-partners-with-makerdao-on-xdai-chain-the-first-ever-usd-stable-blockchain-65a078c41e6a) - thanks to their rather predictable nature. Admittedly, security is traded for scalability, but proper cryptoeconomic stakes could alleviate potential problems.
|
||||
|
||||
Furthermore, it is intriguing to explore the prospect of stream-specific sidechains.
|
||||
|
||||
### Oracles
|
||||
|
||||
The proposed specification uses block numbers to proxy time, but this need not be the only method. Albeit it would imply different trust assumptions, oracles could be used to provide a feed of timestamps. Coupled with the aforementioned idea of stream-specific sidechains, oracles could efficiently solve the problems outlined in [Block Times](#block-times).
|
||||
|
||||
### Multi-Hop Streams
|
||||
|
||||
Future or upgraded versions of this standard may describe "multi-hop" streams. If:
|
||||
|
||||
1. There is a stream between A and B
|
||||
2. There is another stream between B and C
|
||||
|
||||
There could be a way to avoid running two different streams in parallel. That is, a fraction or all of the funds being streamed from A to B could be automatically wired to C. An interesting use case for this is taxes. Instead of manually moving money around, proactively calculating how much you owe and then transfer it, a stream could atomically perform those operations for you.
|
||||
|
||||
## 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.-->
|
||||
|
||||
- [ChronosProtocol WIP implementation](https://github.com/ChronosProtocol/monorepo)
|
||||
|
||||
## Additional References
|
||||
- [Chronos Protocol Ethresear.ch Plasma Proposal](https://ethresear.ch/t/chronos-a-quirky-application-proposal-for-plasma/2928?u=paulrberg)
|
||||
- [Chronos Protocol White Paper](http://chronosprotocol.org/chronos-white-paper.pdf)
|
||||
- [Flipper: Streaming Salaries @ CryptoLife Hackathon](https://devpost.com/software/flipper-3gvl4b)
|
||||
- [SICOs or Streamed ICOs](https://ethresear.ch/t/chronos-a-quirky-application-proposal-for-plasma/2928/14?u=paulrberg)
|
||||
- [RICOs or Reversible ICOs](https://twitter.com/feindura/status/1058057076306518017)
|
||||
- [Andreas Antonopoulos' Keynote on Bitcoin, Lightning and Money Streaming](https://www.youtube.com/watch?v=gF_ZQ_eijPs)
|
||||
|
||||
## Final Notes
|
||||
|
||||
Many thanks to @mmilton41 for countless brainstorming sessions. We have been doing research on the topic of money streaming for quite a while within the context of @ChronosProtocol. In August this year, we published the first version of our white paper describing a Plasma approach. However, in the meantime, we realised that it would be much more [fun](https://twitter.com/PaulRBerg/status/1056595919116910592) and easier to start small on Ethereum itself and sidechains like [xDai](https://blockscout.com/poa/dai).
|
||||
|
||||
## Copyright
|
||||
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
|
|
@ -30,7 +30,7 @@ For some "standard interfaces" like [the ERC-20 token interface](https://github.
|
|||
|
||||
### How Interfaces are Identified
|
||||
|
||||
For this standard, an *interface* is a set of [function selectors as defined by the Ethereum ABI](http://solidity.readthedocs.io/en/develop/abi-spec.html#function-selector). This a subset of [Solidity's concept of interfaces](http://solidity.readthedocs.io/en/develop/abi-spec.html) and the `interface` keyword definition which also defines return types, mutability and events.
|
||||
For this standard, an *interface* is a set of [function selectors as defined by the Ethereum ABI](https://solidity.readthedocs.io/en/develop/abi-spec.html#function-selector). This a subset of [Solidity's concept of interfaces](https://solidity.readthedocs.io/en/develop/abi-spec.html) and the `interface` keyword definition which also defines return types, mutability and events.
|
||||
|
||||
We define the interface identifier as the XOR of all function selectors in the interface. This code example shows how to calculate an interface identifier:
|
||||
|
||||
|
@ -85,7 +85,7 @@ Implementation note, there are several logical ways to implement this function.
|
|||
|
||||
### How to Detect if a Contract Implements ERC-165
|
||||
|
||||
1. The source contact makes a `STATICCALL` to the destination address with input data: `0x01ffc9a701ffc9a700000000000000000000000000000000000000000000000000000000` and gas 30,000. This corresponds to `contract.supportsInterface(0x01ffc9a7)`.
|
||||
1. The source contract makes a `STATICCALL` to the destination address with input data: `0x01ffc9a701ffc9a700000000000000000000000000000000000000000000000000000000` and gas 30,000. This corresponds to `contract.supportsInterface(0x01ffc9a7)`.
|
||||
2. If the call fails or return false, the destination contract does not implement ERC-165.
|
||||
3. If the call returns true, a second call is made with input data `0x01ffc9a7ffffffff00000000000000000000000000000000000000000000000000000000`.
|
||||
4. If the second call fails or returns true, the destination contract does not implement ERC-165.
|
||||
|
@ -144,14 +144,14 @@ contract ERC165Query {
|
|||
|
||||
assembly {
|
||||
let x := mload(0x40) // Find empty storage location using "free memory pointer"
|
||||
mstore(x, erc165ID) // Place signature at begining of empty storage
|
||||
mstore(x, erc165ID) // Place signature at beginning of empty storage
|
||||
mstore(add(x, 0x04), _interfaceId) // Place first argument directly next to signature
|
||||
|
||||
success := staticcall(
|
||||
30000, // 30k gas
|
||||
_contract, // To addr
|
||||
x, // Inputs are stored at location x
|
||||
0x20, // Inputs are 32 bytes long
|
||||
0x24, // Inputs are 36 bytes long
|
||||
x, // Store output over input (saves space)
|
||||
0x20) // Outputs are 32 bytes long
|
||||
|
||||
|
@ -225,6 +225,11 @@ contract Homer is ERC165, Simpson {
|
|||
|
||||
With three or more supported interfaces (including ERC165 itself as a required supported interface), the mapping approach (in every case) costs less gas than the pure approach (at worst case).
|
||||
|
||||
## Version history
|
||||
* PR 1640, finalized 2019-01-23 -- This corrects the noThrowCall test case to use 36 bytes rather than the previous 32 bytes. The previous code was an error that still silently worked in Solidity 0.4.x but which was broken by new behavior introduced in Solidity 0.5.0. This change was discussed at [#1640](https://github.com/ethereum/EIPs/pull/1640).
|
||||
|
||||
* EIP 165, finalized 2018-04-20 -- Original published version.
|
||||
|
||||
## Copyright
|
||||
|
||||
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
|
||||
|
|
|
@ -2,9 +2,11 @@
|
|||
eip: 1679
|
||||
title: "Hardfork Meta: Istanbul"
|
||||
author: Alex Beregszaszi (@axic), Afri Schoedon (@5chdn)
|
||||
discussions-to: https://ethereum-magicians.org/t/hardfork-meta-istanbul-discussion/3207
|
||||
type: Meta
|
||||
status: Draft
|
||||
created: 2019-01-04
|
||||
requires: 1716
|
||||
---
|
||||
|
||||
## Abstract
|
||||
|
@ -14,8 +16,26 @@ This meta-EIP specifies the changes included in the Ethereum hardfork named Ista
|
|||
## Specification
|
||||
|
||||
- Codename: Istanbul
|
||||
- Activation: TBD
|
||||
- Included EIPs: TBD
|
||||
|
||||
### Activation
|
||||
- `Block >= 9,069,000` on the Ethereum mainnet
|
||||
- `Block >= 6,485,846` on the Ropsten testnet
|
||||
- `Block >= 14,111,141` on the Kovan testnet
|
||||
- `Block >= 5,435,345` on the Rinkeby testnet
|
||||
- `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
|
||||
|
||||
## References
|
||||
|
||||
1. Included EIPs were finalized in [All Core Devs Call #68](https://github.com/ethereum/pm/blob/master/All%20Core%20Devs%20Meetings/Meeting%2068.md)
|
||||
2. https://medium.com/ethereum-cat-herders/istanbul-testnets-are-coming-53973bcea7df
|
||||
|
||||
## Copyright
|
||||
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
---
|
||||
eip: 1681
|
||||
title: Temporal Replay Protection
|
||||
author: Martin Holst Swende (@holiman)
|
||||
discussions-to: https://ethereum-magicians.org/t/temporal-replay-protection/2355
|
||||
status: Draft
|
||||
type: Standards Track
|
||||
category: Core
|
||||
created: 2019-01-08
|
||||
---
|
||||
|
||||
## Simple Summary
|
||||
|
||||
This EIP proposes adding a 'temporal' replay protection to transactions, in the form of a `valid-until` timestamp.
|
||||
This EIP is very similar to https://github.com/ethereum/EIPs/pull/599 by Nick Johnson and Konrad Feldmeier, the main difference
|
||||
being that this EIP is based on clock-time / walltime instead of block numbers.
|
||||
|
||||
|
||||
## Motivation
|
||||
|
||||
There are a couple of different motivators for introducing a timebased transaction validity.
|
||||
|
||||
- If any form of dust-account clearing is introduced, e.g. (https://github.com/ethereum/EIPs/issues/168), it will be necessary
|
||||
to introduce a replay protection, such as https://github.com/ethereum/EIPs/issues/169 . Having temporal replay protection removes the need
|
||||
to change nonce-behaviour in the state, since transactions would not be replayable at a later date than explicitly set by the user.
|
||||
- In many cases, such as during ICOs, a lot of people want their transactions to either become included soon (within a couple of hours) or not at all. Currently,
|
||||
transactions are queued and may not execute for several days, at a cost for both the user (who ends up paying gas for a failing purchase) and the network, dealing with the large transaction queues.
|
||||
- Node implementations have no commonly agreed metric for which transactions to keep, discard or propagate. Having a TTL on transactions would make it easier to remove stale transactions from the system.
|
||||
|
||||
## Specification
|
||||
|
||||
The roll-out would be performed in two phases, `X` (hardfork), and `Y` (softfork).
|
||||
|
||||
At block `X`,
|
||||
|
||||
- Add an optional field `valid-until` to the RLP-encoded transaction, defined as a `uint64` (same as `nonce`).
|
||||
- If the field is present in transaction `t`, then
|
||||
- `t` is only eligible for inclusion in a block if `block.timestamp` < `t.valid-until`.
|
||||
|
||||
At block `Y`,
|
||||
- Make `valid-until` mandatory, and consider any transaction without `valid-until` to be invalid.
|
||||
|
||||
## Rationale
|
||||
|
||||
### Rationale for this EIP
|
||||
|
||||
For the dust-account clearing usecase,
|
||||
- This change is much less invasive in the consensus engine.
|
||||
- No need to maintain a consensus-field of 'highest-known-nonce' or cap the number of transactions from a sender in a block.
|
||||
- Only touches the transaction validation part of the consensus engine
|
||||
- Other schemas which uses the `nonce` can have unintended side-effects,
|
||||
- such as inability to create contracts at certain addresses.
|
||||
- more difficult to integrate with offline signers, since more elaborate nonce-schemes requires state access to determine.
|
||||
- More intricate schemes like `highest-nonce` are a lot more difficult, since highest-known-nonce will be a consensus-struct that is incremented and possibly reverted during transaction execution, requiring one more journalled field.
|
||||
|
||||
|
||||
### Rationale for walltime
|
||||
|
||||
Why use walltime instead of block numbers, as proposed in https://github.com/ethereum/EIPs/pull/599 ?
|
||||
|
||||
- The UTC time is generally available in most settings, even on a computer which is offline. This means that even a setup where blockchain information is unavailable, the party signing a transaction can generate a transaction with the desired properties.
|
||||
- The correlation between time and block number is not fixed; even though a 14s blocktime is 'desired', this varies due to both network hashrate and difficulty bomb progression.
|
||||
- The block number is even more unreliable as a timestamp for testnets and private networks.
|
||||
- UTC time is more user-friendly, a user can more easily decide on reasonable end-date for a transaction, rather than a suitalbe number of valid blocks.
|
||||
|
||||
|
||||
## Backwards Compatibility
|
||||
|
||||
This EIP means that all software/hardware that creates transactions need to add timestamps to the transactions, or will otherwise be incapable of signing transactions after block `Y`. Note: this EIP does not introduce any maximum `valid-until` date, so it would still be possible to create
|
||||
transactions with near infinite validity.
|
||||
|
||||
## Test Cases
|
||||
|
||||
todo
|
||||
|
||||
## Implementation
|
||||
|
||||
None yet
|
||||
|
||||
## Security considerations
|
||||
|
||||
The most notable security impact is that pre-signed transactions stored on paper backups, will become invalid as of block `Y`. There are a couple of cases where this might be used
|
||||
- Pregenerated onetime 'bootstrap' transactions, e.g. to onboard a user into Ethereum. Instead of giving a user a giftcard with actual ether on it, someone may instead give the person a one-time pregenerated transaction that will only send those ether to the card once the
|
||||
user actively wants to start using it.
|
||||
- If a user has an offline paper-wallet, he may have pregenerated transactions to send value to e.g. an exchange. This is sometimes done to be able to send ether to an exchange without having to go through all the hoops of bringing the paper wallet back to 'life'.
|
||||
|
||||
Secondary security impacts are that the addition of a timestamp would make the transactions a little bit larger.
|
||||
|
||||
## Copyright
|
||||
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
|
||||
|
|
@ -0,0 +1,220 @@
|
|||
---
|
||||
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
|
||||
type: Standards Track
|
||||
category: Core
|
||||
created: 2018-11-10
|
||||
---
|
||||
|
||||
## Abstract
|
||||
|
||||
This EIP describes a scheme to charge for data in state, and 'archive' data which is no longer being paid for. It also describes how resurrection of 'archived' data happens.
|
||||
|
||||
## Motivation
|
||||
|
||||
The Ethereum blockchain in its current form is not sustainable because it grows
|
||||
indefinitely. This is true of any blockchain, but Ethereum grows faster than most chains.
|
||||
Many implementation strategies to slow down growth exist. A common strategy is 'state
|
||||
pruning' which discards historical state, keeping only the active copy of contract data
|
||||
and a few recent versions to deal with short-range chain reorganizations. Several
|
||||
implementations also employ compression techniques to keep the active copy of the state as
|
||||
small as possible.
|
||||
|
||||
A full node participating in consensus today requires storing large amounts of data even
|
||||
with advanced storage optimizations applied. Future storage requirements are unbounded
|
||||
because any data stored in a contract must be retained forever as dictated by the
|
||||
protocol. This EIP attempts to correct this by adding new consensus rules that put an
|
||||
upper bound on the size of the Ethereum state.
|
||||
|
||||
Adding these new rules changes fundamental guarantees of the system and requires a hard
|
||||
fork. Users of Ethereum already pay for the creation and modification of accounts and
|
||||
their storage entries. Under the rules introduced in this EIP, users must also pay to keep
|
||||
accounts accessible. A similar rent scheme was proposed in [EIP-103] but rejected
|
||||
even back then because the proposal would've upset peoples expectations. As implementers
|
||||
of Ethereum, we still feel that state rent is the right path to long-term sustainability
|
||||
of the Ethereum blockchain and that its undesirable implications can be overcome with
|
||||
off-protocol tooling and careful design.
|
||||
|
||||
[EIP-103]: https://github.com/ethereum/EIPs/issues/35
|
||||
|
||||
## Specification
|
||||
|
||||
The cost of storing an account over time is called `rent`. The amount of `rent` due depends
|
||||
on the size of the account. The `ether` that is paid for `rent` is destroyed. The `rent` is deducted whenever an account is touched.
|
||||
|
||||
`rent` can be paid from the account's regular `balance` or from its 'rent balance'. Accounts
|
||||
can be endowed with `rent balance` through a new EVM opcode. When `rent` is charged, it is
|
||||
first taken from the `rent balance`. When `rent balance` is zero, it is instead charged from the account's regular `balance` instead.
|
||||
|
||||
The reason to separate `balance` and `rent balance` is that certain contracts do not accept `ether` sends, or always send the entire balance off to some other destination. For these cases, a separate`rent balance` is required.
|
||||
|
||||
When an account's `balance` is insufficient to pay rent, the account becomes `inactive`. Its
|
||||
storage and contract code are removed. Inactive accounts cannot be interacted with, i.e.
|
||||
it behaves as if it has no contract code.
|
||||
|
||||
Inactive accounts can be restored by re-uploading their storage. To restore an inactive
|
||||
account `A`, a new account `B` is created with arbitrary code and its storage modified
|
||||
with `SSTORE` operations until it matches the storage root of `A`. Account `B` can restore
|
||||
`A` through the `RESTORETO` opcode. This means the cost of restoring an account is
|
||||
equivalent to recreating it via successive `SSTORE` operations.
|
||||
|
||||
### Changes To State
|
||||
|
||||
At the top level, a new key `size` is added to the accounts trie. This key tracks the
|
||||
total number of trie nodes across all accounts, including storage trie nodes. To track
|
||||
rent, the structure of account entries is changed as well.
|
||||
|
||||
Before processing the block in which this EIP becomes active, clients iterate the whole
|
||||
state once to count the number of trie nodes and to change the representation of all
|
||||
accounts to the new format.
|
||||
|
||||
#### Account Representation
|
||||
|
||||
```text
|
||||
account = [nonce, balance, storageroot, codehash, rentbalance, rentblock, storagesize]
|
||||
```
|
||||
|
||||
Each account gets three additional properties: `rentbalance`, `rentblock` and
|
||||
`storagesize`.
|
||||
|
||||
The `rentbalace` field tracks the amount of `rent balance` available to the account. Upon
|
||||
self-destruction any remaining `rent balance` is transferred to the beneficiary. Any
|
||||
modification of the account recomputes its current `rent balance`.
|
||||
|
||||
The `rentblock` field tracks the block number in which the `rent balance` was last
|
||||
recomputed. Upon creation, this field is initialized with the current block number.
|
||||
`rentblock` is also updated with the current block number whenever the account is
|
||||
modified.
|
||||
|
||||
The `storagesize` field tracks the amount of storage related to the account. It is a
|
||||
number containing the number of storage slots currently set. The `storagesize` of an
|
||||
inactive account is zero.
|
||||
|
||||
### Charging Rent
|
||||
|
||||
There is a new protocol constant `MAX_STORAGE_SIZE` that specifies the upper bound on the
|
||||
number of state tree nodes:
|
||||
|
||||
```python
|
||||
MAX_STORAGE_SIZE = 2**32 # ~160GB of state
|
||||
```
|
||||
|
||||
A 'storage fee factor' for each block is derived from this constant such that fees
|
||||
increase as the limit is approached.
|
||||
|
||||
```python
|
||||
def storagefee_factor(block):
|
||||
ramp = MAX_STORAGE_SIZE / (MAX_STORAGE_SIZE - total_storage_size(block))
|
||||
return 2**22 * ramp
|
||||
```
|
||||
|
||||
When a block is processed, `rent` is deducted from all accounts modified by transactions in
|
||||
the block after the transactions have been processed. The amount due for each account is
|
||||
based on the account's storage size.
|
||||
|
||||
```python
|
||||
def rent(prestate, poststate, addr, currentblock):
|
||||
fee = 0
|
||||
for b in range(prestate[addr].rentblock+1, currentblock-1):
|
||||
fee += storagefee_factor(b) * prestate[addr].storagesize
|
||||
return fee + storagefee_factor(currentblock) * poststate[addr].storagesize
|
||||
|
||||
def charge_rent(prestate, poststate, addr, currentblock):
|
||||
fee = rent(prestate, poststate, addr, currentblock)
|
||||
if fee <= poststate[addr].rentbalance:
|
||||
poststate[addr].rentbalance -= fee
|
||||
else:
|
||||
fee -= poststate[addr].rentbalance
|
||||
poststate[addr].rentbalance = 0
|
||||
poststate[addr].balance -= min(poststate[addr].balance, fee)
|
||||
poststate[addr].rentblock = currentblock
|
||||
```
|
||||
|
||||
### New EVM Opcodes
|
||||
|
||||
#### `PAYRENT <amount> <addr>`
|
||||
|
||||
At any time, the `rent balance` of an account may be topped up by the `PAYRENT` opcode.
|
||||
`PAYRENT` deducts the given amount of `ether` from the account executing the opcode and adds
|
||||
it to the `rent balance` of the address specified as beneficiary.
|
||||
|
||||
Any participant can pay the rent for any other participant.
|
||||
|
||||
Gas cost: TBD
|
||||
|
||||
#### `RENTBALANCE <addr>`
|
||||
|
||||
The `rent balance` of an account may be queried through the `RENTBALANCE` opcode. It pushes the
|
||||
`rentbalance` field of the given address to the stack.
|
||||
|
||||
Gas cost: like `EXTCODEHASH`.
|
||||
|
||||
#### `SSIZE <addr>`
|
||||
|
||||
This opcode pushes the `storagesize` field of the given account to the stack.
|
||||
|
||||
Gas cost: like `EXTCODEHASH`.
|
||||
|
||||
#### `RESTORETO <addr> <codeaddr>`
|
||||
|
||||
This opcode restores the inactive account at the given address. This is a bit like
|
||||
`SELFDESTRUCT` but has more specific semantics.
|
||||
|
||||
The account at `addr` must be `inactive` (i.e. have `storagesize` zero) and its
|
||||
`storageroot` must match the `storageroot` of the contract executing `RESTORETO`. The
|
||||
`codeaddr` specifies the address of a contract from which code is taken. The code of the
|
||||
`codeaddr` account must match the `codehash` of `addr`.
|
||||
|
||||
If all these preconditions are met, `RESTORETO` transfers the storage of the account
|
||||
executing the opcode to `addr` and resets its `storagesize` to the full size of the
|
||||
storage. The code of `addr` is restored as well. `RESTORETO` also transfers any remaining
|
||||
balance and rent balance to `addr`. The contract executing `RESTORETO` is deleted.
|
||||
|
||||
Gas cost: TBD
|
||||
|
||||
## Rationale
|
||||
|
||||
### Why do we need a separate rent balance?
|
||||
|
||||
Accounts need a separate rent balance because some contracts are non-payable, i.e. they
|
||||
reject regular value transfers. Such contracts might not be able to keep themselves alive,
|
||||
but users of those contracts can keep them alive by paying rent for them.
|
||||
|
||||
Having the additional balance also makes things easier for contracts that hold balance on
|
||||
behalf of a user. Consider the canonical crowdfunding example, a contract which changes
|
||||
behavior once a certain balance is reached and which tracks individual user's balances.
|
||||
Deducting rent from the main balance of the contract would mess up the contract's
|
||||
accounting, leaving it unable to pay back users accurately if the threshold balance isn't
|
||||
reached.
|
||||
|
||||
### Why restoration?
|
||||
|
||||
One of the fundamental guarantees provided by Ethereum is that changes to contract storage
|
||||
can only be made by the contract itself and storage will persist forever. If you hold a
|
||||
token balance in a contract, you'll have those tokens forever. By adding restoration, we
|
||||
can maintain this guarantee to a certain extent.
|
||||
|
||||
### Implementation Impact
|
||||
|
||||
The proposed changes tries to fit within the existing state transition model. Note that
|
||||
there is no mechanism for deactivating accounts the moment they can't pay rent. Users must
|
||||
touch accounts to ensure their storage is removed because we'd need to track all accounts
|
||||
and their rent requirements in an auxlilary data structure otherwise.
|
||||
|
||||
## Backwards Compatibility
|
||||
|
||||
TBA
|
||||
|
||||
## Test Cases
|
||||
|
||||
TBA
|
||||
|
||||
## Implementation
|
||||
|
||||
TBA
|
||||
|
||||
## Copyright
|
||||
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
eip: 170
|
||||
title: Contract code size limit
|
||||
author: Vitalik Buterin
|
||||
author: Vitalik Buterin (@vbuterin)
|
||||
type: Standards Track
|
||||
category: Core
|
||||
status: Final
|
||||
|
|
|
@ -0,0 +1,246 @@
|
|||
---
|
||||
eip: 1702
|
||||
title: Generalized Account Versioning Scheme
|
||||
author: Wei Tang (@sorpaas)
|
||||
discussions-to: https://github.com/sorpaas/EIPs/issues/2
|
||||
status: Draft
|
||||
type: Standards Track
|
||||
category: Core
|
||||
created: 2017-12-30
|
||||
---
|
||||
|
||||
## Simple Summary
|
||||
|
||||
Introduce account versioning for smart contracts so upgrading the VM
|
||||
or introducing new VMs can be easier.
|
||||
|
||||
## Abstract
|
||||
|
||||
This defines a method of hard forking while maintaining the exact
|
||||
functionality of existing account by allowing multiple versions of the
|
||||
virtual machines to execute in the same block. This is also useful to
|
||||
define future account state structures when we introduce the on-chain
|
||||
WebAssembly virtual machine.
|
||||
|
||||
## Motivation
|
||||
|
||||
By allowing account versioning, we can execute different virtual
|
||||
machine for contracts created at different times. This allows breaking
|
||||
features to be implemented while making sure existing contracts work
|
||||
as expected.
|
||||
|
||||
Note that this specification might not apply to all hard forks. We
|
||||
have emergency hard forks in the past due to network attacks. Whether
|
||||
they should maintain existing account compatibility should be
|
||||
evaluated in individual basis. If the attack can only be executed once
|
||||
against some particular contracts, then the scheme defined here might
|
||||
still be applicable. Otherwise, having a plain emergency hard fork
|
||||
might still be a good idea.
|
||||
|
||||
## Specification
|
||||
|
||||
### Account State
|
||||
|
||||
Re-define account state stored in the world state trie to have 5
|
||||
items: `nonce`, `balance`, `storageRoot`, `codeHash`, and
|
||||
`version`. The newly added field `version` is a 256-bit **scalar**. We
|
||||
use the definition of "scalar" from Yellow Paper. Note that this is
|
||||
the same type as `nonce` and `balance`, and it is equivalent to a RLP
|
||||
variable-sized byte array with no leading zero, of maximum length 32.
|
||||
|
||||
When `version` is zero, the account is RLP-encoded with the first 4
|
||||
items. When `version` is not zero, the account is RLP-encoded with 5
|
||||
items.
|
||||
|
||||
Account versions can also optionally define additional account state
|
||||
RLP fields, whose meaning are specified through its `version`
|
||||
field. In those cases, the parsing strategy is defined in "Additional
|
||||
Fields in Account State RLP" section.
|
||||
|
||||
### Contract Execution
|
||||
|
||||
When fetching an account code from state, we always fetch the
|
||||
associated version field together. We refer to this as the *code's
|
||||
version* below. The code of the account is always executed in the
|
||||
*code's version*.
|
||||
|
||||
In particular, this means that for `DELEGATECALL` and `CALLCODE`, the
|
||||
version of the execution call frame is the same as
|
||||
delegating/receiving contract's version.
|
||||
|
||||
### Contract Deployment
|
||||
|
||||
In Ethereum, a contract has a deployment method, either by a contract
|
||||
creation transaction, or by another contract. If we regard this
|
||||
deployment method a contract's *parent*, then we find them forming a
|
||||
family of contracts, with the *root* being a contract creation
|
||||
transaction.
|
||||
|
||||
We let a family of contracts to always have the same `version`. That
|
||||
is, `CREATE` and `CREATE2` will always deploy contract that has the
|
||||
same `version` as the *code's version*.
|
||||
|
||||
In other words, `CREATE` and `CREATE2` will execute the init code
|
||||
using the current *code's version*, and deploy the contract of the
|
||||
current *code's version*. This holds even if the to-be-deployed code
|
||||
is empty.
|
||||
|
||||
### Validation
|
||||
|
||||
A new phrase, *validation* is added to contract deployment (by
|
||||
`CREATE` / `CREATE2` opcodes, or by contract creation
|
||||
transaction). When `version` is `0`, the phrase does nothing and
|
||||
always succeeds. Future VM versions can define additional validation
|
||||
that has to be passed.
|
||||
|
||||
If the validation phrase fails, deployment does not proceed and return
|
||||
out-of-gas.
|
||||
|
||||
### Contract Creation Transaction
|
||||
|
||||
Define `LATEST_VERSION` in a hard fork to be the latest supported VM
|
||||
version. A contract creation transaction is always executed in
|
||||
`LATEST_VERSION` (which means the *code's version* is
|
||||
`LATEST_VERSION`), and deploys contracts of `LATEST_VERSION`. Before a
|
||||
contract creation transaction is executed, run *validation* on the
|
||||
contract creation code. If it does not pass, return out-of-gas.
|
||||
|
||||
### Precompiled Contract and Externally-owned Address
|
||||
|
||||
Precompiled contracts and externally-owned addresses do not have
|
||||
`version`. If a message-call transaction or `CALL` / `CALLCODE` /
|
||||
`STATICCALL` / `DELEGATECALL` touches a new externally-owned address
|
||||
or a non-existing precompiled contract address, it is always created
|
||||
with `version` field being `0`.
|
||||
|
||||
### Additional Fields in Account State RLP
|
||||
|
||||
In the future we may need to associate more information into an
|
||||
account, and we already have some EIP/ECIPs that define new additional
|
||||
fields in the account state RLP. In this section, we define the
|
||||
parsing strategy when additional fields are added.
|
||||
|
||||
* Check the RLP list length, if it is 4, then set account version to
|
||||
`0`, and do not parse any additional fields.
|
||||
* If the RLP list length more than 4, set the account version to the
|
||||
scalar at position `4` (counting from `0`).
|
||||
* Check version specification for the number of additional fields
|
||||
defined `N`, if the RLP list length is not equal to `5 + N`,
|
||||
return parse error.
|
||||
* Parse RLP position `5` to `4 + N` as the meaning specified in
|
||||
additional fields.
|
||||
|
||||
## Extensions
|
||||
|
||||
In relation to the above "Specification" section, we have defined the
|
||||
base account versioning layer. The base account versioning layer is
|
||||
already useful by itself and can handle most EVM improvements. Below
|
||||
we define two specifications that can be deployed separately, which
|
||||
improves functionality of base layer account versioning.
|
||||
|
||||
Note that this section is provided only for documentation
|
||||
purpose. When "enabling EIP-1702", those extensions should not be
|
||||
enabled unless the extension specification is also included.
|
||||
|
||||
- [44-VERTXN: Account Versioning Extension for Contract Creation
|
||||
Transaction](https://specs.that.world/44-vertxn/)
|
||||
- [45-VEROP: Account Versioning Extension for CREATE and
|
||||
CREATE2](https://specs.that.world/45-verop/)
|
||||
|
||||
## Usage Template
|
||||
|
||||
This section defines how other EIP/ECIPs might use this account
|
||||
versioning specification. Note that currently we only define the usage
|
||||
template for base layer.
|
||||
|
||||
Account versioning is usually applied directly to a hard fork
|
||||
meta. EIP/ECIPs in the hard fork are grouped by the virtual machine
|
||||
type, for example, EVM and eWASM. For each of them, we define:
|
||||
|
||||
* **Version**: a non-zero scalar less than `2^256` that uniquely
|
||||
identifies this version. Note that it does not need to be
|
||||
sequential.
|
||||
* **Parent version**: the base that all new features derived
|
||||
from. With parent version of `0` we define the base to be legacy
|
||||
VM. Note that once a version other than `0` is defined, the legacy
|
||||
VM's feature set must be frozen. When defining an entirely new VM
|
||||
(such as eWASM), parent version does not apply.
|
||||
* **Features**: all additional features that are enabled upon this
|
||||
version.
|
||||
|
||||
If a meta EIP/ECIP includes EIP/ECIPs that provide additional account state RLP
|
||||
fields, we also define:
|
||||
|
||||
* **Account fields**: all account fields up to the end of this meta
|
||||
EIP, excluding the basic 5 fields (`nonce`, `balance`,
|
||||
`storageRoot`, `codeHash` and `version`). If EIPs included that are
|
||||
specific to modifying account fields do not modify VM execution
|
||||
logic, it is recommended that we specify an additional version whose
|
||||
execution logic is the same as previous version, but only the
|
||||
account fields are changed.
|
||||
|
||||
## Rationale
|
||||
|
||||
This introduces account versioning via a new RLP item in account
|
||||
state. The design above gets account versioning by making the contract
|
||||
*family* always have the same version. In this way, versions are only
|
||||
needed to be provided by contract creation transaction, and there is
|
||||
no restrictions on formats of code for any version. If we want to
|
||||
support multiple newest VMs (for example, EVM and WebAssembly running
|
||||
together), then this will requires extensions such as 44-VERTXN and
|
||||
45-VEROP.
|
||||
|
||||
Alternatively, account versioning can also be done through:
|
||||
|
||||
* **[26-VER](https://specs.that.world/26-ver/)** and
|
||||
**[40-UNUSED](https://specs.that.world/40-unused/)**: This makes an
|
||||
account's versioning soly dependent on its code header prefix. If
|
||||
with only 26-VER, it is not possible to certify any code is valid,
|
||||
because current VM allows treating code as data. This can be fixed
|
||||
by 40-UNUSED, but the drawback is that it's potentially backward
|
||||
incompatible.
|
||||
* **EIP-1891**: Instead of writing version field into account RLP
|
||||
state, we write it in a separate contract. This can accomplish the
|
||||
same thing as this EIP and potentially reduces code complexity, but
|
||||
the drawback is that every code execution will require an additional
|
||||
trie traversal, which impacts performance.
|
||||
|
||||
## Backwards Compatibility
|
||||
|
||||
Account versioning is fully backwards compatible, and it does not
|
||||
change how current contracts are executed.
|
||||
|
||||
## Discussions
|
||||
|
||||
### Performance
|
||||
|
||||
Currently nearly all full node implementations uses config parameters
|
||||
to decide which virtual machine version to use. Switching virtual
|
||||
machine version is simply an operation that changes a pointer using a
|
||||
different set of config parameters. As a result, this scheme has
|
||||
nearly zero impact to performance.
|
||||
|
||||
### WebAssembly
|
||||
|
||||
This scheme can also be helpful when we deploy on-chain WebAssembly
|
||||
virtual machine. In that case, WASM contracts and EVM contracts can
|
||||
co-exist and the execution boundary and interaction model are clearly
|
||||
defined as above.
|
||||
|
||||
## Test Cases and Implementations
|
||||
|
||||
To be added.
|
||||
|
||||
## References
|
||||
|
||||
The source of this specification can be found at
|
||||
[43-VER](https://specs.that.world/43-ver/). This specification is
|
||||
also realized in:
|
||||
|
||||
* Ethereum Classic Improvement Proposals as
|
||||
[ECIP-1040](https://ecips.ethereumclassic.org/ECIPs/ecip-1040).
|
||||
|
||||
|
||||
## Copyright
|
||||
|
||||
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
|
|
@ -1,13 +1,13 @@
|
|||
---
|
||||
eip: 1706
|
||||
title: Disable SSTORE with gasleft lower than call stipend
|
||||
author: Alex Forshtat (alex@tabookey.com), Yoav Weiss (yoav@tabookey.com)
|
||||
author: Alex Forshtat <alex@tabookey.com>, Yoav Weiss <yoav@tabookey.com>
|
||||
discussions-to: https://github.com/alex-forshtat-tbk/EIPs/issues/1
|
||||
status: Draft
|
||||
type: Standards Track (Core, Networking, Interface, ERC)
|
||||
category (*only required for Standard Track): Core
|
||||
type: Standards Track
|
||||
category: Core
|
||||
created: 2019-01-15
|
||||
requires (*optional): 1283
|
||||
requires: 1283
|
||||
---
|
||||
|
||||
<!--You can leave these HTML comments in your merged EIP and delete the visible duplicate text guides, they will not appear and may be helpful to refer to if you edit it again. This is the suggested template for new EIPs. Note that an EIP number will be assigned by an editor. When opening a pull request to submit your EIP, please use an abbreviated title in the filename, `eip-draft_title_abbrev.md`. The title should be 44 characters or less.-->
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
---
|
||||
eip: 1710
|
||||
title: URL Format for Web3 Browsers
|
||||
author: Bruno Barbieri (@brunobar79)
|
||||
discussions-to: https://ethereum-magicians.org/t/standarize-url-format-for-web3-browsers/2422
|
||||
status: Draft
|
||||
type: Standards Track
|
||||
category: ERC
|
||||
created: 2019-01-13
|
||||
requires: 155
|
||||
---
|
||||
|
||||
<!--You can leave these HTML comments in your merged EIP and delete the visible duplicate text guides, they will not appear and may be helpful to refer to if you edit it again. This is the suggested template for new EIPs. Note that an EIP number will be assigned by an editor. When opening a pull request to submit your EIP, please use an abbreviated title in the filename, `eip-draft_title_abbrev.md`. The title should be 44 characters or less.-->
|
||||
|
||||
## Simple Summary
|
||||
|
||||
A standard way of representing web3 browser URLs for decentralized applications.
|
||||
|
||||
## Abstract
|
||||
|
||||
<!--A short (~200 word) description of the technical issue being addressed.-->
|
||||
Since most normal web browsers (specifically on mobile devices) can not run decentralized applications correctly because of the lack of web3 support, it is necessary to differentiate them from normal urls, so they can be opened in web3 browsers if available.
|
||||
|
||||
## 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.-->
|
||||
Lots of dApps that are trying to improve their mobile experience are currently (deep)linking to specific mobile web3 browsers which are currently using their own url scheme.
|
||||
|
||||
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.
|
||||
|
||||
## 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)).-->
|
||||
|
||||
### Syntax
|
||||
|
||||
Web3 browser URLs contain "dapp" in their schema (protocol) part and are constructed as follows:
|
||||
|
||||
request = "dapp" ":" [chain_id "@"] dapp_url
|
||||
chain_id = 1*DIGIT
|
||||
dapp_url = URI
|
||||
|
||||
### 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.
|
||||
|
||||
`dapp_url` is a valid [RFC3986](https://www.ietf.org/rfc/rfc3986.txt) URI
|
||||
|
||||
This a complete example url:
|
||||
|
||||
`dapp:1@peepeth.com/brunobar79?utm_source=github`
|
||||
|
||||
which will open the web3 browser, select `mainnet` (chain_id = 1) and then navigate to:
|
||||
|
||||
`https://peepeth.com/brunobar79?utm_source=github`
|
||||
|
||||
## 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 proposed format attempts to solve the problem of vendor specific protocols for web3 browsers, avoiding conflicts with the existing 'ethereum:' URL scheme while also adding an extra feature: `chain_id` which will help dApps to be accessed with the right network preselected, optionally extracting away that complexity from end users.
|
||||
|
||||
## Copyright
|
||||
|
||||
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
|
|
@ -0,0 +1,39 @@
|
|||
---
|
||||
eip: 1716
|
||||
title: "Hardfork Meta: Petersburg"
|
||||
author: Afri Schoedon (@5chdn), Marius van der Wijden (@MariusVanDerWijden)
|
||||
type: Meta
|
||||
status: Final
|
||||
created: 2019-01-21
|
||||
requires: 1013, 1283
|
||||
---
|
||||
|
||||
## Abstract
|
||||
|
||||
This meta-EIP specifies the changes included in the Ethereum hardfork that removes [EIP-1283](./eip-1283.md) from [Constantinople](./eip-1013.md).
|
||||
|
||||
## Specification
|
||||
|
||||
- Codename: Petersburg
|
||||
- Aliases: St. Petersfork, Peter's Fork, Constantinople Fix
|
||||
- Activation:
|
||||
- `Block >= 7_280_000` on the Ethereum mainnet
|
||||
- `Block >= 4_939_394` on the Ropsten testnet
|
||||
- `Block >= 10_255_201` on the Kovan testnet
|
||||
- `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
|
||||
|
||||
If `Petersburg` and `Constantinople` are applied at the same block, `Petersburg` takes precedence: with the net effect of EIP-1283 being _disabled_.
|
||||
|
||||
If `Petersburg` is defined with an earlier block number than `Constantinople`, then there is _no immediate effect_ from the `Petersburg` fork. However, when `Constantinople` is later activated, EIP-1283 should be _disabled_.
|
||||
|
||||
## References
|
||||
|
||||
1. The list above includes the EIPs that had to be removed from Constantinople due to a [potential reentrancy attack vector](https://medium.com/chainsecurity/constantinople-enables-new-reentrancy-attack-ace4088297d9). Removing this was agreed upon at the [All-Core-Devs call #53 in January 2019](https://github.com/ethereum/pm/issues/70).
|
||||
2. https://blog.ethereum.org/2019/02/22/ethereum-constantinople-st-petersburg-upgrade-announcement/
|
||||
|
||||
## Copyright
|
||||
|
||||
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
|
|
@ -0,0 +1,248 @@
|
|||
---
|
||||
eip: 1753
|
||||
title: Smart Contract Interface for Licences
|
||||
author: Lucas Cullen (@BitcoinBrisbane), Kai Yeung (@CivicKai), Anna Crowley <annaelizabethcrowley@gmail.com>, Caroline Marshall <caroline.marshall888@gmail.com>, Katrina Donaghy <katrina@civicledger.com>
|
||||
status: Draft
|
||||
type: Standards Track
|
||||
category: ERC
|
||||
created: 2019-02-06
|
||||
---
|
||||
|
||||
## Abstract
|
||||
|
||||
This Ethereum Improvement Proposal (EIP) proposes an Ethereum standard for the issuance of licences, permits and grants (Licences).
|
||||
|
||||
A Licence is a limited and temporary authority, granted to a natural (e.g. you) or legal person (e.g. a corporation), to do something that would otherwise be unlawful pursuant to a legal framework. A public Licence is granted by the government, directly (e.g. by the New South Wales Department of Primary Industries, Australia) or indirectly (e.g. by an agent operating under the government’s authority), and derives its authority from legislation, though this is often practically achieved via delegated legislation such as regulations. This can be contrasted to a private licence – for example, the licence you grant to a visitor who comes onto your property.
|
||||
|
||||
A Licence has the following properties:
|
||||
|
||||
* granted personally to the licencee (Licencee), though it may be transferrable to another person or company;
|
||||
* conferring a temporary right to the Licencee to own, use or do something that would otherwise be prohibited, without conferring any property interest in the underlying thing. For example, you may be granted a licence to visit a national park without acquiring any ownership in or over the park itself;
|
||||
* allowing the government authority responsible for the Licence to amend, revoke, renew, suspend or deny the issuance of the Licence, or to impose conditions or penalties for non-compliance; and
|
||||
* usually issued only after the payment of a fee or the meeting of some criteria.
|
||||
|
||||
Additionally, a Licence may be granted in respect of certain information. For example, a Licence may be issued in respect of a vehicle registration number and attaching to that specific registered vehicle.
|
||||
|
||||
## Motivation
|
||||
|
||||
Governments are responsible for the issuance and management of Licences. However, maintaining and sharing this data can be complicated and inefficient. The granting of Licences usually requires the filing of paper-based application forms, manual oversight of applicable legislation and data entry into registries, as well as the issuance of paper based Licences. If individuals wish to sight information on Licence registries, they often need to be present at the government office and complete further paper-based enquiry forms in order to access that data (if available publicly).
|
||||
|
||||
This EIP seeks to define a standard that will allow for the granting and/or management of Licences via Ethereum smart contracts. The motivation is, in essence, to address the inefficiencies inherent in current licencing systems.
|
||||
|
||||
## Specification
|
||||
|
||||
### Methods
|
||||
|
||||
**NOTES**:
|
||||
- The following specifications use syntax from Solidity `0.4.17` (or above)
|
||||
- Callers MUST handle `false` from `returns (bool success)`. Callers MUST NOT assume that `false` is never returned!
|
||||
|
||||
|
||||
#### name
|
||||
|
||||
Returns the name of the permit - e.g. `"MyPermit"`.
|
||||
|
||||
``` js
|
||||
function name() public view returns (string)
|
||||
```
|
||||
|
||||
#### totalSupply
|
||||
|
||||
Returns the total permit supply.
|
||||
|
||||
``` js
|
||||
function totalSupply() public view returns (uint256)
|
||||
```
|
||||
|
||||
#### grantAuthority
|
||||
|
||||
Adds an ethereum address to a white list of addresses that have authority to modify a permit.
|
||||
|
||||
``` js
|
||||
function grantAuthority(address who)
|
||||
```
|
||||
|
||||
#### revokeAuthority
|
||||
|
||||
Removes an ethereum address from a white list of addresses that have authority to modify a permit.
|
||||
|
||||
``` js
|
||||
function revokeAuthority(address who)
|
||||
```
|
||||
|
||||
#### hasAuthority
|
||||
|
||||
Checks to see if the address has authority to grant or revoke permits.
|
||||
|
||||
``` js
|
||||
function hasAuthority(address who)
|
||||
```
|
||||
|
||||
#### issue
|
||||
|
||||
Issues an ethereum address a permit between the specified date range.
|
||||
|
||||
``` js
|
||||
function issue(address who, uint256 from, uint256 to) public;
|
||||
```
|
||||
|
||||
#### revoke
|
||||
|
||||
Revokes a permit from an ethereum address.
|
||||
|
||||
``` js
|
||||
function revoke(address who) public;
|
||||
```
|
||||
|
||||
#### hasValid
|
||||
|
||||
Checks to see if an ethereum address has a valid permit.
|
||||
|
||||
``` js
|
||||
function hasValid(address who) public view returns (boolean);
|
||||
```
|
||||
|
||||
#### purchase
|
||||
|
||||
Allows a user to self procure a licence.
|
||||
|
||||
``` js
|
||||
function purchase(uint256 from, uint256 to) public payable;
|
||||
```
|
||||
|
||||
## Rationale
|
||||
|
||||
The use of smart contracts to apply for, renew, suspend and revoke Licences will free up much needed government resources and allow for the more efficient management of Licences. The EIP also seeks to improve the end user experience of the Licence system. In an era of open government, there is also an increased expectation that individuals will be able to easily access Licence registries, and that the process will be transparent and fair.
|
||||
|
||||
By creating an EIP, we hope to increase the use of Ethereum based and issued Licences, which will address these issues.
|
||||
|
||||
The Ethereum blockchain is adaptable to various Licences and government authorities. It will also be easily translatable into other languages and can be used by other governmental authorities across the world. Moreover, a blockchain will more effectively protect the privacy of Licence-holders’ data, particularly at a time of an ever-increasing volume of government data breaches.
|
||||
|
||||
The EIP has been developed following the review of a number of licensing regulations at the national and state level in Australia. The review allowed the identification of the common licence requirements and criteria for incorporation into the EIP. We have included these in the proposed standard but seek feedback on whether these criteria are sufficient and universal.
|
||||
|
||||
## Test Cases
|
||||
|
||||
A real world example of a Licence is a permit required to camp in a national park in Australia (e.g. Kakadu national park in the Northern Territory of Australia) under the Environment Protection and Biodiversity Conservation Regulations 2000 (Cth) (EPBC Act) and the Environment Protection and Biodiversity Conservation Regulations 2000 (the Regulations). Pursuant to the EPBC Act and the Regulations, the Director of National Parks oversees a camping permit system, which is intended to help regulate certain activities in National Parks. Permits allowing access to National Parks can be issued to legal or natural persons if the applicant has met certain conditions.
|
||||
|
||||
The current digital portal and application form to camp at Kakadu National Park (the Application) can be accessed at: http://www.environment.gov.au/system/files/resources/b3481ed3-164b-4e72-a9f8-91fc987d90e7/files/kakadu-camping-permit-form-19jan2015-pdf.pdf
|
||||
|
||||
The user must provide the following details when making an Application:
|
||||
|
||||
* The full name and contact details of each person to whom the permit is to be issued;
|
||||
|
||||
* If the applicant is a company or other incorporated body:
|
||||
|
||||
o the name, business address and postal address of the company or incorporated body;
|
||||
|
||||
o if the applicant is a company—
|
||||
|
||||
* the full name of each of the directors of the company;
|
||||
|
||||
* the full name and contact details of the person completing the application form;
|
||||
|
||||
* the ACN or ABN of the company or other incorporated body (if applicable);
|
||||
|
||||
* Details of the proposed camping purpose (e.g. private camping, school group, etc.);
|
||||
|
||||
* A start date and duration for the camping (up to the maximum duration allowed by law);
|
||||
|
||||
* Number of campers (up to the maximum allowed by law);
|
||||
|
||||
* All other required information not essential to the issuance of the Licence (e.g. any particular medical needs of the campers); and
|
||||
|
||||
* Fees payable depending on the site, duration and number of campers.
|
||||
|
||||
The Regulations also set out a number of conditions that must be met by licensees when the permit has been issued. The Regulations allow the Director of National Parks to cancel, renew or transfer the licence. The above workflow could be better performed by way of a smart contract.
|
||||
|
||||
The key criteria required as part of this process form part of the proposed Ethereum standard. We have checked this approach by also considering the issuance of a Commercial Fishing Licence under Part 8 “Licensing and other commercial fisheries management” of the Fisheries Management (General) Regulation 2010 (NSW) (Fisheries Regulations) made pursuant to the Fisheries Management Act 1994 (NSW) (Fisheries Act).
|
||||
|
||||
## Implementation
|
||||
|
||||
The issuance and ownership of a Licence can be digitally represented on the Ethereum blockchain.
|
||||
|
||||
Smart contracts can be used to embed regulatory requirements with respect to the relevant Licence in the blockchain. The Licence would be available electronically in the form of a token. This might be practically represented by a QR code, for example, displaying the current Licence information. The digital representation of the Licence would be stored in a digital wallet, typically an application on a smartphone or tablet computer. The proposed standard allows issuing authorities or regulators to amend, revoke or deny Licences from time to time, with the result of their determinations reflected in the Licence token in near real-time. Licence holders will therefore be notified almost instantly of any amendments, revocations or issues involving their Licence.
|
||||
|
||||
## Interface
|
||||
|
||||
### Solidity Example
|
||||
```solidity
|
||||
interface EIP1753 {
|
||||
string public name;
|
||||
uint256 public totalSupply;
|
||||
|
||||
function grantAuthority(address who);
|
||||
function revokeAuthority(address who);
|
||||
function hasAuthority(address who) pure public returns (bool);
|
||||
|
||||
function issue(address who, uint256 from, uint256 to) public;
|
||||
function revoke(address who) public;
|
||||
|
||||
function hasValid(address who) public view returns (boolean);
|
||||
function purchase(uint256 from, uint256 to) public payable;
|
||||
}
|
||||
|
||||
pragma solidity ^0.5.3;
|
||||
|
||||
contract EIP is EIP1753 {
|
||||
|
||||
string public name = "Kakadu National Park Camping Permit";
|
||||
uint256 public totalSupply;
|
||||
|
||||
address private _owner;
|
||||
mapping(address => bool) private _authorities;
|
||||
mapping(address => Permit) private _holders;
|
||||
|
||||
struct Permit {
|
||||
address issuer;
|
||||
uint256 start;
|
||||
uint256 end;
|
||||
}
|
||||
|
||||
constructor() public {
|
||||
_owner = msg.sender;
|
||||
}
|
||||
|
||||
function grantAuthority(address who) public onlyOwner() {
|
||||
_authorities[who] = true;
|
||||
}
|
||||
|
||||
function revokeAuthority(address who) public onlyOwner() {
|
||||
delete _authorities[who];
|
||||
}
|
||||
|
||||
function hasAuthority(address who) public view returns (bool) {
|
||||
return _authorities[who] == true;
|
||||
}
|
||||
|
||||
function issue(address who, uint256 start, uint256 end) public onlyAuthority() {
|
||||
_holders[who] = Permit(_owner, start, end);
|
||||
totalSupply += 1;
|
||||
}
|
||||
|
||||
function revoke(address who) public onlyAuthority() {
|
||||
delete _holders[who];
|
||||
}
|
||||
|
||||
function hasValid(address who) public view returns (bool) {
|
||||
return _holders[who].start > now && _holders[who].end < now;
|
||||
}
|
||||
|
||||
function purchase(uint256 from, uint256 to) public payable {
|
||||
require(msg.value == 1 ether, "Incorrect fee");
|
||||
issue(msg.sender, from, to);
|
||||
}
|
||||
|
||||
modifier onlyOwner() {
|
||||
require(msg.sender == _owner, "Only owner can perform this function");
|
||||
_;
|
||||
}
|
||||
|
||||
modifier onlyAuthority() {
|
||||
require(hasAuthority(msg.sender) == true, "Only an authority can perform this function");
|
||||
_;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Copyright
|
||||
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
|
|
@ -0,0 +1,175 @@
|
|||
---
|
||||
eip: 1761
|
||||
title: ERC-1761 Scoped Approval Interface
|
||||
author: Witek Radomski <witek@enjin.io>, Andrew Cooke <ac0dem0nk3y@gmail.com>, James Therien <james@enjin.io>, Eric Binet <eric@enjin.io>
|
||||
type: Standards Track
|
||||
category: ERC
|
||||
status: Draft
|
||||
created: 2019-02-18
|
||||
discussions-to: https://github.com/ethereum/EIPs/issues/1761
|
||||
requires: 165
|
||||
---
|
||||
|
||||
## Simple Summary
|
||||
|
||||
A standard interface to permit restricted approval in token contracts by defining "scopes" of one or more Token IDs.
|
||||
|
||||
## Abstract
|
||||
|
||||
This interface is designed for use with token contracts that have an "ID" domain, such as ERC-1155 or ERC-721. This enables restricted approval of one or more Token IDs to a specific "scope". When considering a smart contract managing tokens from multiple different domains, it makes sense to limit approvals to those domains. Scoped approval is a generalization of this idea. Implementors can define scopes as needed.
|
||||
|
||||
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.
|
||||
* 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
|
||||
|
||||
It may be desired to restrict approval in some applications. Restricted approval can prevent losses in cases where users do not audit the contracts they're approving. No standard API is supplied to manage scopes as this is implementation specific. Some implementations may opt to offer a fixed number of scopes, or assign a specific set of scopes to certain types. Other implementations may open up scope configuration to its users and offer methods to create scopes and assign IDs to them.
|
||||
|
||||
# Specification
|
||||
|
||||
```solidity
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
/**
|
||||
Note: The ERC-165 identifier for this interface is 0x30168307.
|
||||
*/
|
||||
interface ScopedApproval {
|
||||
/**
|
||||
@dev MUST emit when approval changes for scope.
|
||||
*/
|
||||
event ApprovalForScope(address indexed _owner, address indexed _operator, bytes32 indexed _scope, bool _approved);
|
||||
|
||||
/**
|
||||
@dev MUST emit when the token IDs are added to the scope.
|
||||
By default, IDs are in no scope.
|
||||
The range is inclusive: _idStart, _idEnd, and all IDs in between have been added to the scope.
|
||||
_idStart must be lower than or equal to _idEnd.
|
||||
*/
|
||||
event IdsAddedToScope(uint256 indexed _idStart, uint256 indexed _idEnd, bytes32 indexed _scope);
|
||||
|
||||
/**
|
||||
@dev MUST emit when the token IDs are removed from the scope.
|
||||
The range is inclusive: _idStart, _idEnd, and all IDs in between have been removed from the scope.
|
||||
_idStart must be lower than or equal to _idEnd.
|
||||
*/
|
||||
event IdsRemovedFromScope(uint256 indexed _idStart, uint256 indexed _idEnd, bytes32 indexed _scope);
|
||||
|
||||
/** @dev MUST emit when a scope URI is set or changes.
|
||||
URIs are defined in RFC 3986.
|
||||
The URI MUST point a JSON file that conforms to the "Scope Metadata JSON Schema".
|
||||
*/
|
||||
event ScopeURI(string _value, bytes32 indexed _scope);
|
||||
|
||||
/**
|
||||
@notice Returns the number of scopes that contain _id.
|
||||
@param _id The token ID
|
||||
@return The number of scopes containing the ID
|
||||
*/
|
||||
function scopeCountForId(uint256 _id) public view returns (uint32);
|
||||
|
||||
/**
|
||||
@notice Returns a scope that contains _id.
|
||||
@param _id The token ID
|
||||
@param _scopeIndex The scope index to query (valid values are 0 to scopeCountForId(_id)-1)
|
||||
@return The Nth scope containing the ID
|
||||
*/
|
||||
function scopeForId(uint256 _id, uint32 _scopeIndex) public view returns (bytes32);
|
||||
|
||||
/**
|
||||
@notice Returns a URI that can be queried to get scope metadata. This URI should return a JSON document containing, at least the scope name and description. Although supplying a URI for every scope is recommended, returning an empty string "" is accepted for scopes without a URI.
|
||||
@param _scope The queried scope
|
||||
@return The URI describing this scope.
|
||||
*/
|
||||
function scopeUri(bytes32 _scope) public view returns (string memory);
|
||||
|
||||
/**
|
||||
@notice Enable or disable approval for a third party ("operator") to manage the caller's tokens in the specified scope.
|
||||
@dev MUST emit the ApprovalForScope event on success.
|
||||
@param _operator Address to add to the set of authorized operators
|
||||
@param _scope Approval scope (can be identified by calling scopeForId)
|
||||
@param _approved True if the operator is approved, false to revoke approval
|
||||
*/
|
||||
function setApprovalForScope(address _operator, bytes32 _scope, bool _approved) external;
|
||||
|
||||
/**
|
||||
@notice Queries the approval status of an operator for a given owner, within the specified scope.
|
||||
@param _owner The owner of the Tokens
|
||||
@param _operator Address of authorized operator
|
||||
@param _scope Scope to test for approval (can be identified by calling scopeForId)
|
||||
@return True if the operator is approved, false otherwise
|
||||
*/
|
||||
function isApprovedForScope(address _owner, address _operator, bytes32 _scope) public view returns (bool);
|
||||
}
|
||||
```
|
||||
|
||||
## Scope Metadata JSON Schema
|
||||
|
||||
This schema allows for localization. `{id}` and `{locale}` should be replaced with the appropriate values by clients.
|
||||
|
||||
```json
|
||||
{
|
||||
"title": "Scope Metadata",
|
||||
"type": "object",
|
||||
"required": ["name"],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Identifies the scope in a human-readable way.",
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"description": "Describes the scope to allow users to make informed approval decisions.",
|
||||
},
|
||||
"localization": {
|
||||
"type": "object",
|
||||
"required": ["uri", "default", "locales"],
|
||||
"properties": {
|
||||
"uri": {
|
||||
"type": "string",
|
||||
"description": "The URI pattern to fetch localized data from. This URI should contain the substring `{locale}` which will be replaced with the appropriate locale value before sending the request."
|
||||
},
|
||||
"default": {
|
||||
"type": "string",
|
||||
"description": "The locale of the default data within the base JSON"
|
||||
},
|
||||
"locales": {
|
||||
"type": "array",
|
||||
"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/)."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Localization
|
||||
|
||||
Metadata localization should be standardized to increase presentation uniformity across all languages. As such, a simple overlay method is proposed to enable localization. If the metadata JSON file contains a `localization` attribute, its content may be used to provide localized values for fields that need it. The `localization` attribute should be a sub-object with three attributes: `uri`, `default` and `locales`. If the string `{locale}` exists in any URI, it MUST be replaced with the chosen locale by all client software.
|
||||
|
||||
## Rationale
|
||||
|
||||
The initial design was proposed as an extension to ERC-1155: [Discussion Thread - Comment 1](https://github.com/ethereum/EIPs/issues/1155#issuecomment-459505728). After some discussion: [Comment 2](https://github.com/ethereum/EIPs/issues/1155#issuecomment-460603439) and suggestions by the community to implement this approval mechanism in an external contract [Comment 3](https://github.com/ethereum/EIPs/issues/1155#issuecomment-461758755), it was decided that as an interface standard, this design would allow many different token standards such as ERC-721 and ERC-1155 to implement scoped approvals without forcing the system into all implementations of the tokens.
|
||||
|
||||
### Metadata JSON
|
||||
|
||||
The Scope Metadata JSON Schema was added in order to support human-readable scope names and descriptions in more than one language.
|
||||
|
||||
## 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)
|
||||
- [JSON Schema](http://json-schema.org/)
|
||||
|
||||
**Implementations**
|
||||
- [Enjin Coin](https://enjincoin.io) ([github](https://github.com/enjin))
|
||||
|
||||
**Articles & Discussions**
|
||||
- [GitHub - Original Discussion Thread](https://github.com/ethereum/EIPs/issues/1761)
|
||||
- [GitHub - ERC-1155 Discussion Thread](https://github.com/ethereum/EIPs/issues/1155)
|
||||
|
||||
## Copyright
|
||||
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
|
|
@ -0,0 +1,418 @@
|
|||
---
|
||||
eip: 1767
|
||||
title: GraphQL interface to Ethereum node data
|
||||
author: Nick Johnson (@arachnid), Raúl Kripalani (@raulk), Kris Shinn (@kshinn)
|
||||
discussions-to: https://ethereum-magicians.org/t/graphql-interface-to-ethereum-node-data/2710
|
||||
status: Draft
|
||||
type: Standards Track
|
||||
category: Interface
|
||||
created: 2019-02-14
|
||||
---
|
||||
|
||||
## Abstract
|
||||
This EIP specifies a GraphQL schema for accessing data stored on an Ethereum node. It aims to provide a complete replacement to the read-only information exposed via the present JSON-RPC interface, while improving on usability, consistency, efficiency, and future-proofing.
|
||||
|
||||
## Motivation
|
||||
The current JSON-RPC interface for Ethereum nodes has a number of shortcomings. It's informally and incompletely specified in areas, which has led to incompatibilities around issues such as representation of empty byte strings ("" vs "0x" vs "0x0"), and it has to make educated guesses about the data a user will request, which often leads to unnecessary work.
|
||||
|
||||
For example, the `totalDifficulty` field is stored separately from the block header in common Ethereum node implementations, and many callers do not require this field. However, every call to `eth_getBlock` still retrieves this field, requiring a separate disk read, because the RPC server has no way of knowing if the user requires this field or not.
|
||||
|
||||
Similarly, transaction receipts in go-ethereum are stored on disk as a single binary blob for each block. Fetching a receipt for a single transaction requires fetching and deserializing this blob, then finding the relevant entry and returning it; this is accomplished by the `eth_getTransactionReceipt` API call. A common task for API consumers is to fetch all the receipts in a block; as a result, node implementations end up fetching and deserializing the same data repeatedly, leading to `O(n^2)` effort to fetch all transaction receipts from a block instead of `O(n)`.
|
||||
|
||||
Some of these issues could be fixed with changes to the existing JSON-RPC interface, at the cost of complicating the interface somewhat. Instead, we propose adopting a standard query language, GraphQL, which facilitates more efficient API implementations, while also increasing flexibility.
|
||||
|
||||
## Prior Art
|
||||
|
||||
Nick Johnson and [EthQL](https://github.com/ConsenSys/ethql) independently developed a GraphQL schema for node data. Once the parties were made aware of the shared effort, they made efforts to bring their schemas into alignment. The current schema proposed in this EIP is derived primarily from the EthQL schema.
|
||||
|
||||
## Specification
|
||||
|
||||
### Node API
|
||||
|
||||
Compatible nodes MUST provide a GraphQL endpoint available over HTTP. This SHOULD be offered on port 8547 by default. The path to the GraphQL endpoint SHOULD be '/graphql'.
|
||||
|
||||
Compatible nodes MAY offer a GraphiQL interactive query explorer on the root path ('/').
|
||||
|
||||
### Schema
|
||||
|
||||
The GraphQL schema for this service is defined as follows:
|
||||
```
|
||||
# Bytes32 is a 32 byte binary string, represented as 0x-prefixed hexadecimal.
|
||||
scalar Bytes32
|
||||
# Address is a 20 byte Ethereum address, represented as 0x-prefixed hexadecimal.
|
||||
scalar Address
|
||||
# Bytes is an arbitrary length binary string, represented as 0x-prefixed hexadecimal.
|
||||
# An empty byte string is represented as '0x'. Byte strings must have an even number of hexadecimal nybbles.
|
||||
scalar Bytes
|
||||
# BigInt is a large integer. Input is accepted as either a JSON number or as a string.
|
||||
# Strings may be either decimal or 0x-prefixed hexadecimal. Output values are all
|
||||
# 0x-prefixed hexadecimal.
|
||||
scalar BigInt
|
||||
# Long is a 64 bit unsigned integer.
|
||||
scalar Long
|
||||
|
||||
schema {
|
||||
query: Query
|
||||
mutation: Mutation
|
||||
}
|
||||
|
||||
# Account is an Ethereum account at a particular block.
|
||||
type Account {
|
||||
# Address is the address owning the account.
|
||||
address: Address!
|
||||
# Balance is the balance of the account, in wei.
|
||||
balance: BigInt!
|
||||
# TransactionCount is the number of transactions sent from this account,
|
||||
# or in the case of a contract, the number of contracts created. Otherwise
|
||||
# known as the nonce.
|
||||
transactionCount: Long!
|
||||
# Code contains the smart contract code for this account, if the account
|
||||
# is a (non-self-destructed) contract.
|
||||
code: Bytes!
|
||||
# Storage provides access to the storage of a contract account, indexed
|
||||
# by its 32 byte slot identifier.
|
||||
storage(slot: Bytes32!): Bytes32!
|
||||
}
|
||||
|
||||
# Log is an Ethereum event log.
|
||||
type Log {
|
||||
# Index is the index of this log in the block.
|
||||
index: Int!
|
||||
# Account is the account which generated this log - this will always
|
||||
# be a contract account.
|
||||
account(block: Long): Account!
|
||||
# Topics is a list of 0-4 indexed topics for the log.
|
||||
topics: [Bytes32!]!
|
||||
# Data is unindexed data for this log.
|
||||
data: Bytes!
|
||||
# Transaction is the transaction that generated this log entry.
|
||||
transaction: Transaction!
|
||||
}
|
||||
|
||||
# Transaction is an Ethereum transaction.
|
||||
type Transaction {
|
||||
# Hash is the hash of this transaction.
|
||||
hash: Bytes32!
|
||||
# Nonce is the nonce of the account this transaction was generated with.
|
||||
nonce: Long!
|
||||
# Index is the index of this transaction in the parent block. This will
|
||||
# be null if the transaction has not yet been mined.
|
||||
index: Int
|
||||
# From is the account that sent this transaction - this will always be
|
||||
# an externally owned account.
|
||||
from(block: Long): Account!
|
||||
# To is the account the transaction was sent to. This is null for
|
||||
# contract-creating transactions.
|
||||
to(block: Long): Account
|
||||
# Value is the value, in wei, sent along with this transaction.
|
||||
value: BigInt!
|
||||
# GasPrice is the price offered to miners for gas, in wei per unit.
|
||||
gasPrice: BigInt!
|
||||
# Gas is the maximum amount of gas this transaction can consume.
|
||||
gas: Long!
|
||||
# InputData is the data supplied to the target of the transaction.
|
||||
inputData: Bytes!
|
||||
# Block is the block this transaction was mined in. This will be null if
|
||||
# the transaction has not yet been mined.
|
||||
block: Block
|
||||
|
||||
# Status is the return status of the transaction. This will be 1 if the
|
||||
# transaction succeeded, or 0 if it failed (due to a revert, or due to
|
||||
# running out of gas). If the transaction has not yet been mined, this
|
||||
# field will be null.
|
||||
status: Long
|
||||
# GasUsed is the amount of gas that was used processing this transaction.
|
||||
# If the transaction has not yet been mined, this field will be null.
|
||||
gasUsed: Long
|
||||
# CumulativeGasUsed is the total gas used in the block up to and including
|
||||
# this transaction. If the transaction has not yet been mined, this field
|
||||
# will be null.
|
||||
cumulativeGasUsed: Long
|
||||
# CreatedContract is the account that was created by a contract creation
|
||||
# transaction. If the transaction was not a contract creation transaction,
|
||||
# or it has not yet been mined, this field will be null.
|
||||
createdContract(block: Long): Account
|
||||
# Logs is a list of log entries emitted by this transaction. If the
|
||||
# transaction has not yet been mined, this field will be null.
|
||||
logs: [Log!]
|
||||
}
|
||||
|
||||
# BlockFilterCriteria encapsulates log filter criteria for a filter applied
|
||||
# to a single block.
|
||||
input BlockFilterCriteria {
|
||||
# Addresses is list of addresses that are of interest. If this list is
|
||||
# empty, results will not be filtered by address.
|
||||
addresses: [Address!]
|
||||
# Topics list restricts matches to particular event topics. Each event has a list
|
||||
# of topics. Topics matches a prefix of that list. An empty element array matches any
|
||||
# topic. Non-empty elements represent an alternative that matches any of the
|
||||
# contained topics.
|
||||
#
|
||||
# Examples:
|
||||
# - [] or nil matches any topic list
|
||||
# - [[A]] matches topic A in first position
|
||||
# - [[], [B]] matches any topic in first position, B in second position
|
||||
# - [[A], [B]] matches topic A in first position, B in second position
|
||||
# - [[A, B]], [C, D]] matches topic (A OR B) in first position, (C OR D) in second position
|
||||
topics: [[Bytes32!]!]
|
||||
}
|
||||
|
||||
# Block is an Ethereum block.
|
||||
type Block {
|
||||
# Number is the number of this block, starting at 0 for the genesis block.
|
||||
number: Long!
|
||||
# Hash is the block hash of this block.
|
||||
hash: Bytes32!
|
||||
# Parent is the parent block of this block.
|
||||
parent: Block
|
||||
# Nonce is the block nonce, an 8 byte sequence determined by the miner.
|
||||
nonce: Bytes!
|
||||
# TransactionsRoot is the keccak256 hash of the root of the trie of transactions in this block.
|
||||
transactionsRoot: Bytes32!
|
||||
# TransactionCount is the number of transactions in this block. if
|
||||
# transactions are not available for this block, this field will be null.
|
||||
transactionCount: Int
|
||||
# StateRoot is the keccak256 hash of the state trie after this block was processed.
|
||||
stateRoot: Bytes32!
|
||||
# ReceiptsRoot is the keccak256 hash of the trie of transaction receipts in this block.
|
||||
receiptsRoot: Bytes32!
|
||||
# Miner is the account that mined this block.
|
||||
miner(block: Long): Account!
|
||||
# ExtraData is an arbitrary data field supplied by the miner.
|
||||
extraData: Bytes!
|
||||
# GasLimit is the maximum amount of gas that was available to transactions in this block.
|
||||
gasLimit: Long!
|
||||
# GasUsed is the amount of gas that was used executing transactions in this block.
|
||||
gasUsed: Long!
|
||||
# Timestamp is the unix timestamp at which this block was mined.
|
||||
timestamp: BigInt!
|
||||
# LogsBloom is a bloom filter that can be used to check if a block may
|
||||
# contain log entries matching a filter.
|
||||
logsBloom: Bytes!
|
||||
# MixHash is the hash that was used as an input to the PoW process.
|
||||
mixHash: Bytes32!
|
||||
# Difficulty is a measure of the difficulty of mining this block.
|
||||
difficulty: BigInt!
|
||||
# TotalDifficulty is the sum of all difficulty values up to and including
|
||||
# this block.
|
||||
totalDifficulty: BigInt!
|
||||
# OmmerCount is the number of ommers (AKA uncles) associated with this
|
||||
# block. If ommers are unavailable, this field will be null.
|
||||
ommerCount: Int
|
||||
# Ommers is a list of ommer (AKA uncle) blocks associated with this block.
|
||||
# If ommers are unavailable, this field will be null. Depending on your
|
||||
# node, the transactions, transactionAt, transactionCount, ommers,
|
||||
# ommerCount and ommerAt fields may not be available on any ommer blocks.
|
||||
ommers: [Block]
|
||||
# OmmerAt returns the ommer (AKA uncle) at the specified index. If ommers
|
||||
# are unavailable, or the index is out of bounds, this field will be null.
|
||||
ommerAt(index: Int!): Block
|
||||
# OmmerHash is the keccak256 hash of all the ommers (AKA uncles)
|
||||
# associated with this block.
|
||||
ommerHash: Bytes32!
|
||||
# Transactions is a list of transactions associated with this block. If
|
||||
# transactions are unavailable for this block, this field will be null.
|
||||
transactions: [Transaction!]
|
||||
# TransactionAt returns the transaction at the specified index. If
|
||||
# transactions are unavailable for this block, or if the index is out of
|
||||
# bounds, this field will be null.
|
||||
transactionAt(index: Int!): Transaction
|
||||
# Logs returns a filtered set of logs from this block.
|
||||
logs(filter: BlockFilterCriteria!): [Log!]!
|
||||
# Account fetches an Ethereum account at the current block's state.
|
||||
account(address: Address!): Account
|
||||
# Call executes a local call operation at the current block's state.
|
||||
call(data: CallData!): CallResult
|
||||
# EstimateGas estimates the amount of gas that will be required for
|
||||
# successful execution of a transaction at the current block's state.
|
||||
estimateGas(data: CallData!): Long!
|
||||
}
|
||||
|
||||
# CallData represents the data associated with a local contract call.
|
||||
# All fields are optional.
|
||||
input CallData {
|
||||
# From is the address making the call.
|
||||
from: Address
|
||||
# To is the address the call is sent to.
|
||||
to: Address
|
||||
# Gas is the amount of gas sent with the call.
|
||||
gas: Long
|
||||
# GasPrice is the price, in wei, offered for each unit of gas.
|
||||
gasPrice: BigInt
|
||||
# Value is the value, in wei, sent along with the call.
|
||||
value: BigInt
|
||||
# Data is the data sent to the callee.
|
||||
data: Bytes
|
||||
}
|
||||
|
||||
# CallResult is the result of a local call operation.
|
||||
type CallResult {
|
||||
# Data is the return data of the called contract.
|
||||
data: Bytes!
|
||||
# GasUsed is the amount of gas used by the call, after any refunds.
|
||||
gasUsed: Long!
|
||||
# Status is the result of the call - 1 for success or 0 for failure.
|
||||
status: Long!
|
||||
}
|
||||
|
||||
# FilterCriteria encapsulates log filter criteria for searching log entries.
|
||||
input FilterCriteria {
|
||||
# FromBlock is the block at which to start searching, inclusive. Defaults
|
||||
# to the latest block if not supplied.
|
||||
fromBlock: Long
|
||||
# ToBlock is the block at which to stop searching, inclusive. Defaults
|
||||
# to the latest block if not supplied.
|
||||
toBlock: Long
|
||||
# Addresses is a list of addresses that are of interest. If this list is
|
||||
# empty, results will not be filtered by address.
|
||||
addresses: [Address!]
|
||||
# Topics list restricts matches to particular event topics. Each event has a list
|
||||
# of topics. Topics matches a prefix of that list. An empty element array matches any
|
||||
# topic. Non-empty elements represent an alternative that matches any of the
|
||||
# contained topics.
|
||||
#
|
||||
# Examples:
|
||||
# - [] or nil matches any topic list
|
||||
# - [[A]] matches topic A in first position
|
||||
# - [[], [B]] matches any topic in first position, B in second position
|
||||
# - [[A], [B]] matches topic A in first position, B in second position
|
||||
# - [[A, B]], [C, D]] matches topic (A OR B) in first position, (C OR D) in second position
|
||||
topics: [[Bytes32!]!]
|
||||
}
|
||||
|
||||
# SyncState contains the current synchronisation state of the client.
|
||||
type SyncState{
|
||||
# StartingBlock is the block number at which synchronisation started.
|
||||
startingBlock: Long!
|
||||
# CurrentBlock is the point at which synchronisation has presently reached.
|
||||
currentBlock: Long!
|
||||
# HighestBlock is the latest known block number.
|
||||
highestBlock: Long!
|
||||
# PulledStates is the number of state entries fetched so far, or null
|
||||
# if this is not known or not relevant.
|
||||
pulledStates: Long
|
||||
# KnownStates is the number of states the node knows of so far, or null
|
||||
# if this is not known or not relevant.
|
||||
knownStates: Long
|
||||
}
|
||||
|
||||
# Pending represents the current pending state.
|
||||
type Pending {
|
||||
# TransactionCount is the number of transactions in the pending state.
|
||||
transactionCount: Int!
|
||||
# Transactions is a list of transactions in the current pending state.
|
||||
transactions: [Transaction!]
|
||||
# Account fetches an Ethereum account for the pending state.
|
||||
account(address: Address!): Account
|
||||
# Call executes a local call operation for the pending state.
|
||||
call(data: CallData!): CallResult
|
||||
# EstimateGas estimates the amount of gas that will be required for
|
||||
# successful execution of a transaction for the pending state.
|
||||
estimateGas(data: CallData!): Long!
|
||||
}
|
||||
|
||||
type Query {
|
||||
# Block fetches an Ethereum block by number or by hash. If neither is
|
||||
# supplied, the most recent known block is returned.
|
||||
block(number: Long, hash: Bytes32): Block
|
||||
# Blocks returns all the blocks between two numbers, inclusive. If
|
||||
# to is not supplied, it defaults to the most recent known block.
|
||||
blocks(from: Long!, to: Long): [Block!]!
|
||||
# Pending returns the current pending state.
|
||||
pending: Pending!
|
||||
# Transaction returns a transaction specified by its hash.
|
||||
transaction(hash: Bytes32!): Transaction
|
||||
# Logs returns log entries matching the provided filter.
|
||||
logs(filter: FilterCriteria!): [Log!]!
|
||||
# GasPrice returns the node's estimate of a gas price sufficient to
|
||||
# ensure a transaction is mined in a timely fashion.
|
||||
gasPrice: BigInt!
|
||||
# ProtocolVersion returns the current wire protocol version number.
|
||||
protocolVersion: Int!
|
||||
# Syncing returns information on the current synchronisation state.
|
||||
syncing: SyncState
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
# SendRawTransaction sends an RLP-encoded transaction to the network.
|
||||
sendRawTransaction(data: Bytes!): Bytes32!
|
||||
}
|
||||
```
|
||||
|
||||
Nodes MAY offer a superset of this schema, by adding new fields or types. Experimental or client-specific fields MUST be prefixed with '_client_' (eg, '_geth_' or '_parity_'). Unprefixed fields MUST be specified in a new EIP that extends this one.
|
||||
|
||||
## Rationale
|
||||
Ethereum nodes have been moving away from providing read-write functionality such as transaction and message signing, and from other services such as code compilation, in favor of a more 'unix-like' approach where each task is performed by a dedicated process. We have thus specified a core set of types and fields that reflects this trend, leaving out functionality that is presently, or intended to be, deprecated:
|
||||
|
||||
- `eth_compile*` calls are deprecated, and hence not provided here.
|
||||
- `eth_accounts`, `eth_sign`, and `eth_sendTransaction` are considered by many to be deprecated, and are not provided here; callers should use local accounts or a separate signing daemon instead.
|
||||
|
||||
Further, two areas of the current API interface have been omitted for simplicity in this initial standard, with the intention that they will be defined in a later EIP:
|
||||
|
||||
- Filters will require use of GraphQL subscriptions, and require careful consideration around the desire for nodes without local per-caller state.
|
||||
- Mining functionality is less-used and benefits less from reimplementation in GraphQL, and should be specified in a separate EIP.
|
||||
|
||||
## Backwards Compatibility
|
||||
|
||||
This schema implements the bulk of the current read-only functionality provided by the JSON-RPC node interface. Existing RPC calls can be mapped to GraphQL queries as follows:
|
||||
|
||||
| RPC | Status | Description |
|
||||
| --- | ------ | ----------- |
|
||||
| eth_blockNumber | IMPLEMENTED | `{ block { number } }` |
|
||||
| eth_call | IMPLEMENTED | `{ call(data: { to: "0x...", data: "0x..." }) { data status gasUsed } }` |
|
||||
| eth_estimateGas | IMPLEMENTED | `{ estimateGas(data: { to: "0x...", data: "0x..." }) }` |
|
||||
| eth_gasPrice | IMPLEMENTED | `{ gasPrice }` |
|
||||
| eth_getBalance | IMPLEMENTED | `{ account(address: "0x...") { balance } }` |
|
||||
| eth_getBlockByHash | IMPLEMENTED | `{ block(hash: "0x...") { ... } }` |
|
||||
| eth_getBlockByNumber | IMPLEMENTED | `{ block(number: 123) { ... } }` |
|
||||
| eth_getBlockTransactionCountByHash | IMPLEMENTED | `{ block(hash: "0x...") { transactionCount } }` |
|
||||
| eth_getBlockTransactionCountByNumber | IMPLEMENTED | `{ block(number: x) { transactionCounnt } }` |
|
||||
| eth_getCode | IMPLEMENTED | `{ account(address: "0x...") { code } }` |
|
||||
| eth_getLogs | IMPLEMENTED | `{ logs(filter: { ... }) { ... } }` or `{ block(...) { logs(filter: { ... }) { ... } } }` |
|
||||
| eth_getStorageAt | IMPLEMENTED | `{ account(address: "0x...") { storage(slot: "0x...") } }` |
|
||||
| eth_getTransactionByBlockHashAndIndex | IMPLEMENTED | `{ block(hash: "0x...") { transactionAt(index: x) { ... } } }` |
|
||||
| eth_getTransactionByBlockNumberAndIndex | IMPLEMENTED | `{ block(number: n) { transactionAt(index: x) { ... } } }` |
|
||||
| eth_getTransactionByHash | IMPLEMENTED | `{ transaction(hash: "0x...") { ... } }` |
|
||||
| eth_getTransactionCount | IMPLEMENTED | `{ account(address: "0x...") { transactionCount } }` |
|
||||
| eth_getTransactionReceipt | IMPLEMENTED | `{ transaction(hash: "0x...") { ... } }` |
|
||||
| eth_getUncleByBlockHashAndIndex | IMPLEMENTED | `{ block(hash: "0x...") { ommerAt(index: x) { ... } } }` |
|
||||
| eth_getUncleByBlockNumberAndIndex | IMPLEMENTED | `{ block(number: n) { ommerAt(index: x) { ... } } }` |
|
||||
| eth_getUncleCountByBlockHash | IMPLEMENTED | `{ block(hash: "0x...") { ommerCount } }` |
|
||||
| eth_getUncleCountByBlockNumber | IMPLEMENTED | `{ block(number: x) { ommerCount } }` |
|
||||
| eth_protocolVersion | IMPLEMENTED | `{ protocolVersion }` |
|
||||
| eth_sendRawTransaction | IMPLEMENTED | `mutation { sendRawTransaction(data: data) }` |
|
||||
| eth_syncing | IMPLEMENTED | `{ syncing { ... } }` |
|
||||
| eth_getCompilers | NOT IMPLEMENTED | Compiler functionality is deprecated in JSON-RPC. |
|
||||
| eth_compileLLL | NOT IMPLEMENTED | Compiler functionality is deprecated in JSON-RPC. |
|
||||
| eth_compileSolidity | NOT IMPLEMENTED | Compiler functionality is deprecated in JSON-RPC. |
|
||||
| eth_compileSerpent | NOT IMPLEMENTED | Compiler functionality is deprecated in JSON-RPC. |
|
||||
| eth_newFilter | NOT IMPLEMENTED | Filter functionality may be specified in a future EIP. |
|
||||
| eth_newBlockFilter | NOT IMPLEMENTED | Filter functionality may be specified in a future EIP. |
|
||||
| eth_newPendingTransactionFilter | NOT IMPLEMENTED | Filter functionality may be specified in a future EIP. |
|
||||
| eth_uninstallFilter | NOT IMPLEMENTED | Filter functionality may be specified in a future EIP. |
|
||||
| eth_getFilterChanges | NOT IMPLEMENTED | Filter functionality may be specified in a future EIP. |
|
||||
| eth_getFilterLogs | NOT IMPLEMENTED | Filter functionality may be specified in a future EIP. |
|
||||
| eth_accounts | NOT IMPLEMENTED | Accounts functionality is not part of the core node API. |
|
||||
| eth_sign | NOT IMPLEMENTED | Accounts functionality is not part of the core node API. |
|
||||
| eth_sendTransaction | NOT IMPLEMENTED | Accounts functionality is not part of the core node API. |
|
||||
| eth_coinbase | NOT IMPLEMENTED | Mining functionality to be defined separately. |
|
||||
| eth_getWork | NOT IMPLEMENTED | Mining functionality to be defined separately. |
|
||||
| eth_hashRate | NOT IMPLEMENTED | Mining functionality to be defined separately. |
|
||||
| eth_mining | NOT IMPLEMENTED | Mining functionality to be defined separately. |
|
||||
| eth_submitHashrate | NOT IMPLEMENTED | Mining functionality to be defined separately. |
|
||||
| eth_submitWork | NOT IMPLEMENTED | Mining functionality to be defined separately. |
|
||||
|
||||
For specific reasoning behind omitted functionality, see the Rationale section.
|
||||
|
||||
## Test Cases
|
||||
TBD.
|
||||
|
||||
## Implementation
|
||||
|
||||
- Implemented and released in [Go-ethereum 1.9.0](https://github.com/ethereum/go-ethereum/releases/tag/v1.9.0)
|
||||
- Implemented and released in [Pantheon 1.1.1](https://github.com/PegaSysEng/pantheon/blob/master/CHANGELOG.md#111)
|
||||
- Work in progress in [Trinity](https://github.com/ethereum/trinity/issues/302)
|
||||
- Work in progress in [Parity](https://github.com/paritytech/parity-ethereum/issues/10933)
|
||||
|
||||
## Copyright
|
||||
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
|
|
@ -0,0 +1,200 @@
|
|||
---
|
||||
eip: 1775
|
||||
title: App Keys, application specific wallet accounts
|
||||
author: Vincent Eli (@Bunjin), Dan Finlay (@DanFinlay), Erik Marks (@rekmarks)
|
||||
discussions-to: https://ethereum-magicians.org/t/eip-erc-app-keys-application-specific-wallet-accounts/2742
|
||||
status: Draft
|
||||
type: Standards Track
|
||||
category: ERC
|
||||
created: 2019-02-20
|
||||
---
|
||||
|
||||
<!--You can leave these HTML comments in your merged EIP and delete the visible duplicate text guides, they will not appear and may be helpful to refer to if you edit it again. This is the suggested template for new EIPs. Note that an EIP number will be assigned by an editor. When opening a pull request to submit your EIP, please use an abbreviated title in the filename, `eip-draft_title_abbrev.md`. 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.-->
|
||||
|
||||
Among others cryptographic applications, scalability and privacy solutions for ethereum blockchain require that an user performs a significant amount of signing operations. It may also require her to watch some state and be ready to sign data automatically (e.g. sign a state or contest a withdraw). The way wallets currently implement accounts poses several obstacles to the development of a complete web3.0 experience both in terms of UX, security and privacy.
|
||||
|
||||
This proposal describes a standard and api for a new type of wallet accounts that are derived specifically for a each given application. We propose to call them `app keys`. They allow to isolate the accounts used for each application, thus potentially increasing privacy. They also allow to give more control to the applications developers over account management and signing delegation. For these app keys, wallets can have a more permissive level of security (e.g. not requesting user's confirmation) while keeping main accounts secure. Finally wallets can also implement a different behavior such as allowing to sign transactions without broadcasting them.
|
||||
|
||||
This new accounts type can allow to significantly improve UX and permit new designs for applications of the crypto permissionned web.
|
||||
|
||||
## Abstract
|
||||
<!--A short (~200 word) description of the technical issue being addressed.-->
|
||||
In a wallet, an user often holds most of her funds in her main accounts. These accounts require a significant level of security and should not be delegated in any way, this significantly impacts the design of cryptographic applications if a user has to manually confirm every action. Also often an user uses the same accounts across apps, which is a privacy and potentially also a security issue.
|
||||
|
||||
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.
|
||||
|
||||
## 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.-->
|
||||
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.
|
||||
|
||||
However several limitations remain in order to allow for proper design and UX for crypto permissioned apps.
|
||||
|
||||
Most of GUI based current wallets don't allow to:
|
||||
* being able to automatically and effortlessly use different keys / accounts for each apps,
|
||||
* being able to sign some app's action without prompting the user with the same level of security as sending funds from their main accounts,
|
||||
* being able to use throwable keys to improve anonymity,
|
||||
* effortlessly signing transactions for an app without broadcasting these while still being able to perform other transaction signing as usual from their main accounts,
|
||||
* All this while being fully restorable using the user's mnemonic or hardware wallet and the HD Path determined uniquely by the app's ens name.
|
||||
|
||||
We try to overcome these limitations by introducing a new account's type, app keys, made to be used along side the existing main accounts.
|
||||
|
||||
These new app keys can permit to give more power and flexibility to the crypto apps developers. This can allow to improve a lot the UX of crypto dapps and to create new designs that were not possible before leveraging the ability to create and handle many accounts, to presign messages and broadcast them later. These features were not compatible with the level of security we were requesting for main accounts that hold most of an user's funds.
|
||||
|
||||
|
||||
## 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)).-->
|
||||
|
||||
### Applications
|
||||
|
||||
An app is a website (or other) that would like to request from a wallet to access a cryptographic key specifically derived for this usage. It can be any form of cryptography/identity relying application, Ethereum based but not only.
|
||||
|
||||
Once connected to a wallet, an application can request to access an account derived exclusively for that application using the following algorithm.
|
||||
|
||||
### Private App Key generation algorithm
|
||||
|
||||
We now propose an algorithm to generate application keys that:
|
||||
- are uniquely defined, with respect to the account that the user selected to generate these keys,
|
||||
- and thus can be isolated when changing the user account, allowing persona management (see next section),
|
||||
- are specific to each application,
|
||||
- can be fully restored from the user master seed mnemonic and the applications' names.
|
||||
|
||||
#### Using different accounts as personas
|
||||
|
||||
We allow the user to span a different set of application keys by changing the account selected to generate each key. Thus from the same master seed mnemonic, an user can use each of her account index to generate an alternative set of application keys. One can describe this as using different personas.
|
||||
This would allow potentially an user to fully isolate her interaction with a given app across personas. One can use this for instance to create a personal and business profile for a given's domain both backup up from the same mnemonic, using 2 different accounts to generate these. The app or domain, will not be aware that it is the same person and mnemonic behind both.
|
||||
If an application interacts with several main accounts of an user, one of these accounts, a master account can be used as persona and the others as auxiliary accounts.
|
||||
|
||||
#### Applications' Unique Identifiers
|
||||
|
||||
Each application is uniquely defined and authenticated by its origin, a domain string. It can be a Domain Name Service (DNS) name or, in the future, an Ethereum Name Service (ENS) name or IPFS hash.
|
||||
|
||||
For Ipfs or swam origins, but we could probably use the ipfs or swarm addresses as origin or we could require those to be pointed at through an ENS entry and use the ENS address as origin, although this would mean that the content it refers to could change. It would thus allow for different security and updatibility models.
|
||||
|
||||
We will probably require for protocol prefixes when using an ENS domain to point to an IPFS address:
|
||||
`ens://ipfs.snap.eth`
|
||||
|
||||
|
||||
#### Private App Key generation algorithm
|
||||
|
||||
Using the domain name of an application, we generate a private key for each application (and per main account) :
|
||||
|
||||
`const appKeyPrivKey = keccak256(privKey + originString)`
|
||||
|
||||
where `+` is concatenation, `privKey` is the private key of the user's account selected to span the application key and `originString` represents the origin url from which the permission call to access the application key is originated from.
|
||||
|
||||
This is exposed as an RPC method to allow any domain to request its own app key associated with the current requested account (if available):
|
||||
|
||||
```
|
||||
const appKey = await provider.send({
|
||||
method: 'wallet_getAppKeyForAccount',
|
||||
params: [address1]
|
||||
});
|
||||
```
|
||||
|
||||
See here for an implementation:
|
||||
https://github.com/MetaMask/eth-simple-keyring/blob/master/index.js#L169
|
||||
|
||||
|
||||
## 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.-->
|
||||
|
||||
### Sharing application keys across domains:
|
||||
While this does not explicit cover cases of sharing these app keys between pages on its own, this need can be met by composition:
|
||||
|
||||
Since a domain would get a unique key, and because domains can intercommunicate, one domain (app) could request another domain (signer) to perform its cryptographic operation on some data, with its appKey as a seed, potentially allowing new signing strategies to be added as easily as new websites.
|
||||
|
||||
This could also pass it to domains that are loading specific signing strategies. This may sound dangerous at first, but if a domain represents a static hash of a trusted cryptographic function implementation, it could be as safe as calling any audited internal dependency.
|
||||
|
||||
### Privacy and the funding trail
|
||||
|
||||
If all an application needs to do with its keys is to sign messages and it does not require funding, then this EIP allows for privacy through the use of distinct keys for each application with a simple deterministic standard compatible across wallets.
|
||||
|
||||
However if these application keys require funding, there can be trail and the use of app keys would not fully solve the privacy problem there.
|
||||
|
||||
Mixers or anonymous ways of funding an ethereum address (ring signatures) along with this proposal would guarantee privacy.
|
||||
|
||||
Even if privacy is not solved fully without this anonymous funding method, we still need a way to easily create and restore different accounts/addresses for each application
|
||||
|
||||
## 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.-->
|
||||
From a wallet point of view, there does not seem to be compatibility issues since these are separate accounts from those that were used previously by wallets and they are supposed to be used along-side in synergy.
|
||||
|
||||
However, for applications that associated in some way their users to their main accounts may want to reflect on if and how they would like to leverage the power offered by `app keys` to migrate to them and leverage on the new app designs they permit.
|
||||
|
||||
## 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.-->
|
||||
|
||||
Here is an early implementation of app keys for standard (non HW) MetaMask accounts.
|
||||
https://github.com/MetaMask/eth-simple-keyring/blob/6d12bd9d73adcccbe0b0c7e32a99d279085e2934/index.js#L139-L152
|
||||
|
||||
See here for a fork of MetaMask that implements app keys along side plugins:
|
||||
https://github.com/MetaMask/metamask-snaps-beta
|
||||
https://github.com/MetaMask/metamask-snaps-beta/wiki/Plugin-API
|
||||
|
||||
|
||||
|
||||
## Example use cases
|
||||
|
||||
* signing transactions without broadcasting them
|
||||
https://github.com/MetaMask/metamask-extension/issues/3475
|
||||
|
||||
* token contract
|
||||
https://github.com/ethereum/EIPs/issues/85
|
||||
|
||||
* default account for dapps
|
||||
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)
|
||||
|
||||
* state channel application
|
||||
|
||||
* privacy solution
|
||||
|
||||
* non custodian cross cryptocurrency exchange...
|
||||
|
||||
## Acknowledgements
|
||||
MetaMask team, Christian Lundkvist, Counterfactual team, Liam Horne, Erik Bryn, Richard Moore, Jeff Coleman.
|
||||
|
||||
|
||||
## References
|
||||
|
||||
### HD and mnemonics
|
||||
#### BIPs
|
||||
* [BIP32: Hierarchical Deterministic Wallets:](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki)
|
||||
|
||||
* [BIP39: Mnemonic code for generating deterministic keys:](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki)
|
||||
|
||||
* [SLIP44: Registered coin types for BIP44](https://github.com/satoshilabs/slips/blob/master/slip-0044.md)
|
||||
|
||||
|
||||
#### Derivation path for eth
|
||||
* [Issue 84](https://github.com/ethereum/EIPs/issues/84)
|
||||
|
||||
* [Issue 85](https://github.com/ethereum/EIPs/issues/85)
|
||||
|
||||
* [EIP600 Ethereum purpose allocation for Deterministic Wallets](https://eips.ethereum.org/EIPS/eip-600)
|
||||
|
||||
|
||||
* [EIP601 Ethereum hierarchy for deterministic wallets](https://eips.ethereum.org/EIPS/eip-601)
|
||||
|
||||
|
||||
### 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)
|
||||
|
||||
* [EIP1581: Non-wallet usage of keys derived from BIP-32 trees](https://eips.ethereum.org/EIPS/eip-1581)
|
||||
|
||||
* [EIP1581: discussion](https://ethereum-magicians.org/t/non-wallet-usage-of-keys-derived-from-bip-32-trees/1817/4)
|
||||
|
||||
* [SLIP13: Authentication using deterministic hierarchy](https://github.com/satoshilabs/slips/blob/master/slip-0013.md)
|
||||
|
||||
|
||||
## Copyright
|
||||
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
|
|
@ -0,0 +1,42 @@
|
|||
---
|
||||
eip: 1803
|
||||
title: Rename opcodes for clarity
|
||||
author: Alex Beregszaszi (@axic)
|
||||
discussions-to: https://ethereum-magicians.org/t/eip-1803-rename-opcodes-for-clarity/3345
|
||||
type: Standards Track
|
||||
category: Interface
|
||||
status: Draft
|
||||
created: 2017-07-28
|
||||
requires: 141
|
||||
---
|
||||
|
||||
## Abstract
|
||||
|
||||
Rename the `BALANCE`, `SHA3`, `NUMBER`, `GASLIMIT`, `GAS` and `INVALID` opcodes to reflect their true meaning.
|
||||
|
||||
## Specification
|
||||
|
||||
Rename the opcodes as follows:
|
||||
- `BALANCE` (`0x31`) to `EXTBALANCE` to be in line with `EXTCODESIZE`, `EXTCODECOPY` and `EXTCODEHASH`
|
||||
- `SHA3` (`0x20`) to `KECCAK256`
|
||||
- `NUMBER` (`0x43`) to `BLOCKNUMBER`
|
||||
- `GASLIMIT` (`0x45`) to `BLOCKGASLIMIT` to avoid confusion with the gas limit of the transaction
|
||||
- `GAS` (`0x5a`) to `GASLEFT` to be clear what it refers to
|
||||
- `INVALID` (`0xfe`) to `ABORT` to clearly articulate when someone refers this opcode as opposed to "any invalid opcode"
|
||||
|
||||
## Backwards Compatibility
|
||||
|
||||
This has no effect on any code. It can influence what mnemonics assemblers will use.
|
||||
|
||||
## Implementation
|
||||
|
||||
Not applicable.
|
||||
|
||||
## References
|
||||
|
||||
[EIP-6](https://eips.ethereum.org/EIPS/eip-6) previously renamed `SUICIDE` (`0xff`) to `SELFDESTRUCT`.
|
||||
Renaming `SHA3` was previously proposed by [EIP-59](https://github.com/ethereum/EIPs/issues/59).
|
||||
|
||||
## Copyright
|
||||
|
||||
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
|
|
@ -37,7 +37,7 @@ Allowing the caller to specify an owner other than themselves for the relevant n
|
|||
|
||||
### function claimWithResolver(address owner, address resolver) returns (bytes32 node)
|
||||
|
||||
When called by account `x`, instructs the ENS registry to set the resolver of the name `hex(x) + '.addr.reverse' to the specified resolver, then transfer ownership of the name to the provided address, and return the namehash of the ENS record thus transferred. This method facilitates setting up a custom resolver and owner in fewer transactions than would be required if calling `claim`.
|
||||
When called by account `x`, instructs the ENS registry to set the resolver of the name `hex(x) + '.addr.reverse'` to the specified resolver, then transfer ownership of the name to the provided address, and return the namehash of the ENS record thus transferred. This method facilitates setting up a custom resolver and owner in fewer transactions than would be required if calling `claim`.
|
||||
|
||||
### function setName(string name) returns (bytes32 node)
|
||||
|
||||
|
@ -204,3 +204,6 @@ This registrar, written in Solidity, implements the specifications outlined abov
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
## Copyright
|
||||
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
|
||||
|
|
|
@ -0,0 +1,442 @@
|
|||
---
|
||||
eip: 1812
|
||||
title: Ethereum Verifiable Claims
|
||||
author: Pelle Braendgaard (@pelle)
|
||||
discussions-to: https://ethereum-magicians.org/t/erc-1812-ethereum-verifiable-claims/2814
|
||||
status: Draft
|
||||
type: Standards Track
|
||||
category: ERC
|
||||
created: 2019-03-03
|
||||
requires: 712
|
||||
---
|
||||
|
||||
# Ethereum Verifiable Claims
|
||||
|
||||
## Simple Summary
|
||||
|
||||
Reusable Verifiable Claims using [EIP 712 Signed Typed Data](https://github.com/ethereum/EIPs/issues/712).
|
||||
|
||||
## Abstract
|
||||
A new method for Off-Chain Verifiable Claims built on [EIP 712](https://github.com/ethereum/EIPs/issues/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.
|
||||
|
||||
## 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.
|
||||
|
||||
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.
|
||||
|
||||
The W3C [Verifiable Claims Data Model and Representations](https://www.w3.org/TR/verifiable-claims-data-model/) as well as uPorts [Verification Message Spec](https://developer.uport.me/messages/verification) are proposed off-chain solutions.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
## Specification
|
||||
### Claims
|
||||
Claims can be generalized like this:
|
||||
|
||||
> Issuer makes the claim that Subject is something or has some attribute and value.
|
||||
|
||||
Claims should be deterministic, in that the same claim signed multiple times by the same signer.
|
||||
|
||||
### Claims data structure
|
||||
Each claim should be typed based on its specific use case, which EIP 712 lets us do effortlessly. But there are 3 minimal attributes required of the claims structure.
|
||||
|
||||
* `subject` the subject of the claim as an `address` (who the claim is about)
|
||||
* `validFrom` the time in seconds encoded as a `uint256` of start of validity of claim. In most cases this would be the time of issuance, but some claims may be valid in the future or past.
|
||||
* `validTo` the time in seconds encoded as a `uint256` of when the validity of the claim expires. If you intend for the claim not to expire use `0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff`.
|
||||
|
||||
The basic minimal claim data structure as a Solidity struct:
|
||||
|
||||
```solidity
|
||||
struct [CLAIM TYPE] {
|
||||
address subject;
|
||||
uint256 validFrom;
|
||||
uint256 validTo;
|
||||
}
|
||||
```
|
||||
|
||||
The CLAIM TYPE is the actual name of the claim. While not required, in most cases use the taxonomy developed by [schema.org](https://schema.org/docs/full.html) which is also commonly used in other Verifiable Claims formats.
|
||||
|
||||
Example claim that issuer knows a subject:
|
||||
|
||||
```solidity
|
||||
struct Know {
|
||||
address subject;
|
||||
uint256 validFrom;
|
||||
uint256 validTo;
|
||||
}
|
||||
```
|
||||
|
||||
### Presenting a Verifiable Claim
|
||||
#### Verifying Contract
|
||||
When defining Verifiable Claims formats a Verifying Contract should be created with a public `verify()` view function. This makes it very easy for other smart contracts to verify a claim correctly.
|
||||
|
||||
It also provides a convenient interface for web3 and state channel apps to verify claims securely.
|
||||
|
||||
```solidity
|
||||
function verifyIssuer(Know memory claim, uint8 v, bytes32 r, bytes32 s) public returns (address) {
|
||||
bytes32 digest = keccak256(
|
||||
abi.encodePacked(
|
||||
"\x19\x01",
|
||||
DOMAIN_SEPARATOR,
|
||||
hash(claim)
|
||||
)
|
||||
);
|
||||
require(
|
||||
(claim.validFrom >= block.timestamp) && (block.timestamp < claim.validTo)
|
||||
, "invalid issuance timestamps");
|
||||
return ecrecover(digest, v, r, s);
|
||||
}
|
||||
```
|
||||
|
||||
#### Calling a SmartContract function
|
||||
Verifiable Claims can be presented to a solidity function call as it’s struct together with the `v`, `r` and `s` signature components.
|
||||
|
||||
```solidity
|
||||
function vouch(Know memory claim, uint8 v, bytes32 r, bytes32 s) public returns (bool) {
|
||||
address issuer = verifier.verifyIssuer(claim, v, r, s);
|
||||
require(issuer !== '0x0');
|
||||
knows[issuer][claim.subject] = block.number;
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
#### Embedding a Verifiable Claim in another Signed Typed Data structure
|
||||
The Claim struct should be embedded in another struct together with the `v`, `r` and `s` signature parameters.
|
||||
|
||||
```solidity
|
||||
struct Know {
|
||||
address subject;
|
||||
uint256 validFrom;
|
||||
uint256 validTo;
|
||||
}
|
||||
|
||||
struct VerifiableReference {
|
||||
Know delegate;
|
||||
uint8 v;
|
||||
bytes32 r;
|
||||
bytes32 s;
|
||||
}
|
||||
|
||||
struct Introduction {
|
||||
address recipient;
|
||||
VerifiableReference issuer;
|
||||
}
|
||||
```
|
||||
|
||||
Each Verifiable Claim should be individually verified together with the parent Signed Typed Data structure.
|
||||
|
||||
Verifiable Claims issued to different EIP 712 Domains can be embedded within each other.
|
||||
|
||||
#### State Channels
|
||||
This proposal will not show how to use Eth Verifiable Claims as part of a specific State Channel method.
|
||||
|
||||
Any State Channel based on EIP712 should be able to include the embeddable Verifiable Claims as part of its protocol. This could be useful for exchanging private Identity Claims between the parties for regulatory reasons, while ultimately not posting them to the blockchain on conclusion of a channel.
|
||||
|
||||
### Key Delegation
|
||||
In most simple cases the issuer of a Claim is the signer of the data. There are cases however where signing should be delegated to an intermediary key.
|
||||
|
||||
KeyDelegation can be used to implement off chain signing for smart contract based addresses, server side key rotation as well as employee permissions in complex business use cases.
|
||||
|
||||
#### 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.
|
||||
|
||||
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`
|
||||
|
||||
The following is the minimal struct for a Claim containing an issuer:
|
||||
|
||||
```solidity
|
||||
struct [CLAIM TYPE] {
|
||||
address subject;
|
||||
address issuer;
|
||||
uint256 validFrom;
|
||||
uint256 validTo;
|
||||
}
|
||||
```
|
||||
|
||||
If the `issuer` is specified in the struct In addition to performing the standard ERC712 verification the verification code MUST also verify that the signing address is a valid `veriKey` delegate for the address specified in the issuer.
|
||||
|
||||
```solidity
|
||||
registry.validDelegate(issuer, 'veriKey', recoveredAddress)
|
||||
```
|
||||
|
||||
|
||||
#### Embedded Delegation Proof
|
||||
There may be applications, in particularly where organizations want to allow delegates to issue claims about specific domains and types.
|
||||
|
||||
For this purpose instead of the `issuer` we allow a special claim to be embedded following this same format:
|
||||
|
||||
```solidity
|
||||
struct Delegate {
|
||||
address issuer;
|
||||
address subject;
|
||||
uint256 validFrom;
|
||||
uint256 validTo;
|
||||
}
|
||||
|
||||
struct VerifiableDelegate {
|
||||
Delegate delegate;
|
||||
uint8 v;
|
||||
bytes32 r;
|
||||
bytes32 s;
|
||||
}
|
||||
|
||||
|
||||
struct [CLAIM TYPE] {
|
||||
address subject;
|
||||
VerifiedDelegate issuer;
|
||||
uint256 validFrom;
|
||||
uint256 validTo;
|
||||
}
|
||||
```
|
||||
|
||||
Delegates should be created for specific EIP 712 Domains and not be reused across Domains.
|
||||
|
||||
Implementers of new EIP 712 Domains can add further data to the `Delegate` struct to allow finer grained application specific rules to it.
|
||||
|
||||
### Claim Types
|
||||
#### Binary Claims
|
||||
A Binary claim is something that doesn’t have a particular value. It either is issued or not.
|
||||
|
||||
Examples:
|
||||
* subject is a Person
|
||||
* subject is my owner (eg. Linking an ethereum account to an owner identity)
|
||||
|
||||
Example:
|
||||
|
||||
```solidity
|
||||
struct Person {
|
||||
address issuer;
|
||||
address subject;
|
||||
uint256 validFrom;
|
||||
uint256 validTo;
|
||||
}
|
||||
```
|
||||
|
||||
This is exactly the same as the minimal claim above with the CLAIM TYPE set to [Person](https://schema.org/Person).
|
||||
|
||||
### Value Claims
|
||||
Value claims can be used to make a claim about the subject containing a specific readable value.
|
||||
|
||||
**WARNING**: Be very careful about using Value Claims as part of Smart Contract transactions. Identity Claims containing values could be a GDPR violation for the business or developer encouraging a user to post it to a public blockchain.
|
||||
|
||||
Examples:
|
||||
* subject’s name is Alice
|
||||
* subjects average account balance is 1234555
|
||||
|
||||
Each value should use the `value` field to indicate the value.
|
||||
|
||||
A Name Claim
|
||||
|
||||
```solidity
|
||||
struct Name {
|
||||
address issuer;
|
||||
address subject;
|
||||
string name;
|
||||
uint256 validFrom;
|
||||
uint256 validTo;
|
||||
}
|
||||
```
|
||||
|
||||
Average Balance
|
||||
|
||||
```solidity
|
||||
struct AverageBalance {
|
||||
address issuer;
|
||||
address subject;
|
||||
uint256 value;
|
||||
uint256 validFrom;
|
||||
uint256 validTo;
|
||||
}
|
||||
```
|
||||
|
||||
### Hashed Claims
|
||||
Hashed claims can be used to make a claim about the subject containing the hash of a claim value. Hashes should use ethereum standard `keccak256` hashing function.
|
||||
|
||||
**WARNING**: Be very careful about using Hashed Claims as part of Smart Contract transactions. Identity Claims containing hashes of known values could be a GDPR violation for the business or developer encouraging a user to post it to a public blockchain.
|
||||
|
||||
Examples:
|
||||
- [ ] hash of subject’s name is `keccak256(“Alice Torres”)`
|
||||
- [ ] hash of subject’s email is `keccak256(“alice@example.com”)`
|
||||
|
||||
Each value should use the `keccak256 ` field to indicate the hashed value. Question. The choice of using this name is that we can easily add support for future algorithms as well as maybe zkSnark proofs.
|
||||
|
||||
A Name Claim
|
||||
|
||||
```solidity
|
||||
struct Name {
|
||||
address issuer;
|
||||
address subject;
|
||||
bytes32 keccak256;
|
||||
uint256 validFrom;
|
||||
uint256 validTo;
|
||||
}
|
||||
```
|
||||
|
||||
Email Claim
|
||||
|
||||
```solidity
|
||||
struct Email {
|
||||
address issuer;
|
||||
address subject;
|
||||
bytes32 keccak256;
|
||||
uint256 validFrom;
|
||||
uint256 validTo;
|
||||
}
|
||||
```
|
||||
|
||||
### EIP 712 Domain
|
||||
The EIP 712 Domain specifies what kind of message that is to be signed and is used to differentiate between signed data types. The content MUST contain the following:
|
||||
|
||||
```solidity
|
||||
{
|
||||
name: "EIP1???Claim",
|
||||
version: 1,
|
||||
chainId: 1, // for mainnet
|
||||
verifyingContract: 0x // TBD
|
||||
salt: ...
|
||||
}
|
||||
```
|
||||
|
||||
#### Full Combined format for EIP 712 signing:
|
||||
|
||||
Following the EIP 712 standard we can combine the Claim Type with the EIP 712 Domain and the claim itself (in the `message`) attribute.
|
||||
|
||||
Eg:
|
||||
```solidity
|
||||
{
|
||||
"types": {
|
||||
"EIP712Domain": [
|
||||
{
|
||||
"name": "name",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "version",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "chainId",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "verifyingContract",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"Email": [
|
||||
{
|
||||
"name": "subject",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "keccak256",
|
||||
"type": "bytes32"
|
||||
},
|
||||
{
|
||||
"name": "validFrom",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "validTo",
|
||||
"type": "uint256"
|
||||
}
|
||||
]
|
||||
},
|
||||
"primaryType": "Email",
|
||||
"domain": {
|
||||
"name": "EIP1??? Claim",
|
||||
"version": "1",
|
||||
"chainId": 1,
|
||||
"verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC"
|
||||
},
|
||||
"message": {
|
||||
"subject": "0x5792e817336f41de1d8f54feab4bc200624a1d9d",
|
||||
"value": "9c8465d9ae0b0bc167dee7f62880034f59313100a638dcc86a901956ea52e280",
|
||||
"validFrom": "0x0000000000000000000000000000000000000000000000000001644b74c2a0",
|
||||
"validTo": "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Revocation
|
||||
Both Issuers and Subjects should be allowed to revoke Verifiable Claims. Revocations can be handled through a simple on-chain registry.
|
||||
|
||||
The ultimate rules of who should be able to revoke a claim is determined by the Verifying contract.
|
||||
|
||||
The `digest` used for revocation is the EIP712 Signed Typed Data digest.
|
||||
|
||||
```solidity
|
||||
contract RevocationRegistry {
|
||||
mapping (bytes32 => mapping (address => uint)) public revocations;
|
||||
|
||||
function revoke(bytes32 digest) public returns (bool) {
|
||||
revocations[digest][msg.sender] = block.number;
|
||||
return true;
|
||||
}
|
||||
|
||||
function revoked(address party, bytes32 digest) public view returns (bool) {
|
||||
return revocations[digest][party] > 0;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
A verifying contract can query the Revocation Registry as such:
|
||||
|
||||
```solidity
|
||||
bytes32 digest = keccak256(
|
||||
abi.encodePacked(
|
||||
"\x19\x01",
|
||||
DOMAIN_SEPARATOR,
|
||||
hash(claim)
|
||||
)
|
||||
);
|
||||
require(valid(claim.validFrom, claim.validTo), "invalid issuance timestamps");
|
||||
address issuer = ecrecover(digest, v, r, s);
|
||||
require(!revocations.revoked(issuer, digest), "claim was revoked by issuer");
|
||||
require(!revocations.revoked(claim.subject, digest), "claim was revoked by subject");
|
||||
```
|
||||
|
||||
### Creation of Verifiable Claims Domains
|
||||
|
||||
Creating specific is Verifiable Claims Domains is out of the scope of this EIP. The Example Code has a few examples.
|
||||
|
||||
EIP’s or another process could be used to standardize specific important Domains that are universally useful across the Ethereum world.
|
||||
|
||||
## Rationale
|
||||
Signed Typed Data provides a strong foundation for Verifiable Claims that can be used in many different kinds of applications built on both Layer 1 and Layer 2 of Ethereum.
|
||||
|
||||
### Rationale for using not using a single EIP 712 Domain
|
||||
EIP712 supports complex types and domains in itself, that we believe are perfect building blocks for building Verifiable Claims for specific purposes.
|
||||
|
||||
The Type and Domain of a Claim is itself an important part of a claim and ensures that Verifiable Claims are used for the specific purposes required and not misused.
|
||||
|
||||
EIP712 Domains also allow rapid experimentation, allowing taxonomies to be built up by the community.
|
||||
|
||||
## Test Cases
|
||||
There is a repo with a few example verifiers and consuming smart contracts written in Solidity:
|
||||
|
||||
**Example Verifiers**
|
||||
* [Verifier for very simple IdVerification Verifiable Claims containing minimal Personal Data](https://github.com/uport-project/eip712-claims-experiments/blob/master/contracts/IdentityClaimsVerifier.sol)
|
||||
* [Verifier for OwnershipProofs signed by a users wallet](https://github.com/uport-project/eip712-claims-experiments/blob/master/contracts/OwnershipProofVerifier.sol)
|
||||
|
||||
**Example Smart Contracts**
|
||||
* [KYCCoin.sol](https://github.com/uport-project/eip712-claims-experiments/blob/master/contracts/KYCCoin.sol) - Example Token allows reusable IdVerification claims issued by trusted verifiers and users to whitelist their own addresses using OwnershipProofs
|
||||
* [ConsortiumAgreement.sol](https://github.com/uport-project/eip712-claims-experiments/blob/master/contracts/ConsortiumAgreements.sol) - Example Consortium Agreement smart contract. Consortium Members can issue Delegated Claims to employees or servers to interact on their behalf.
|
||||
|
||||
**Shared Registries**
|
||||
* [RevocationRegistry.sol](https://github.com/uport-project/eip712-claims-experiments/blob/master/contracts/RevocationRegistry.sol)
|
||||
|
||||
## Copyright
|
||||
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,349 @@
|
|||
---
|
||||
eip: 1822
|
||||
title: Universal Upgradeable Proxy Standard (UUPS)
|
||||
author: Gabriel Barros <gabriel@terminal.co>, Patrick Gallagher <blockchainbuddha@gmail.com>
|
||||
discussions-to: https://ethereum-magicians.org/t/eip-1822-universal-upgradeable-proxy-standard-uups
|
||||
status: Draft
|
||||
type: Standards Track
|
||||
category: ERC
|
||||
created: 2019-03-04
|
||||
---
|
||||
|
||||
## Table of contents
|
||||
|
||||
<!-- TOC -->
|
||||
|
||||
- [Table of contents](#table-of-contents)
|
||||
- [Simple Summary](#simple-summary)
|
||||
- [Abstract](#abstract)
|
||||
- [Motivation](#motivation)
|
||||
- [Terminology](#terminology)
|
||||
- [Specification](#specification)
|
||||
- [Proxy Contract](#proxy-contract)
|
||||
- [Functions](#functions)
|
||||
- [`fallback`](#fallback)
|
||||
- [`constructor`](#constructor)
|
||||
- [Proxiable Contract](#proxiable-contract)
|
||||
- [Functions](#functions-1)
|
||||
- [`proxiable`](#proxiable)
|
||||
- [`updateCodeAddress`](#updatecodeaddress)
|
||||
- [Pitfalls when using a proxy](#pitfalls-when-using-a-proxy)
|
||||
- [Separating Variables from Logic](#separating-variables-from-logic)
|
||||
- [Restricting dangerous functions](#restricting-dangerous-functions)
|
||||
- [Examples](#examples)
|
||||
- [Owned](#owned)
|
||||
- [ERC-20 Token](#erc-20-token)
|
||||
- [Proxy Contract](#proxy-contract-1)
|
||||
- [Token Logic Contract](#token-logic-contract)
|
||||
- [References](#references)
|
||||
- [Copyright](#copyright)
|
||||
<!-- /TOC -->
|
||||
|
||||
## Simple Summary
|
||||
|
||||
Standard upgradeable proxy contract.
|
||||
|
||||
## Abstract
|
||||
|
||||
The following describes a standard for proxy contracts which is universally compatible with all contracts, and does not create incompatibility between the proxy and business-logic contracts. This is achieved by utilizing a unique storage position in the proxy contract to store the Logic Contract's address. A compatibility check ensures successful upgrades. Upgrading can be performed unlimited times, or as determined by custom logic. In addition, a method for selecting from multiple constructors is provided, which does not inhibit the ability to verify bytecode.
|
||||
|
||||
## Motivation
|
||||
|
||||
- Improve upon existing proxy implementations to improve developer experience for deploying and maintaining Proxy and Logic Contracts.
|
||||
|
||||
- Standardize and improve the methods for verifying the bytecode used by the Proxy Contract.
|
||||
|
||||
## Terminology
|
||||
|
||||
- `delegatecall()` - Function in contract **A** which allows an external contract **B** (delegating) to modify **A**'s storage (see diagram below, [Solidity docs](https://solidity.readthedocs.io/en/v0.5.3/introduction-to-smart-contracts.html#delegatecall-callcode-and-libraries))
|
||||
- **Proxy Contract** - The contract **A** which stores data, but uses the logic of external contract **B** by way of `delegatecall()`.
|
||||
- **Logic Contract** - The contract **B** which contains the logic used by Proxy Contract **A**
|
||||
- **Proxiable Contract** - Inherited in Logic Contract **B** to provide the upgrade functionality
|
||||
|
||||
<p align="center"><img src="../assets/eip-1822/proxy-diagram.png" alt="diagram" width="600"/></p>
|
||||
|
||||
## Specification
|
||||
|
||||
The Proxy Contract proposed here should be deployed _as is_, and used as a drop-in replacement for any existing methods of lifecycle management of contracts. In addition to the Proxy Contract, we propose the Proxiable Contract interface/base which establishes a pattern for the upgrade which does not interfere with existing business rules. The logic for allowing upgrades can be implemented as needed.
|
||||
|
||||
### Proxy Contract
|
||||
|
||||
#### Functions
|
||||
|
||||
##### `fallback`
|
||||
|
||||
The proposed fallback function follows the common pattern seen in other Proxy Contract implementations such as [Zeppelin][1] or [Gnosis][2].
|
||||
|
||||
However, rather than forcing use of a variable, the address of the Logic Contract is stored at the defined storage position `keccak256("PROXIABLE")`. This eliminates the possibility of collision between variables in the Proxy and Logic Contracts, thus providing "universal" compatibility with any Logic Contract.
|
||||
|
||||
```javascript
|
||||
function() external payable {
|
||||
assembly { // solium-disable-line
|
||||
let contractLogic := sload(0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7)
|
||||
calldatacopy(0x0, 0x0, calldatasize)
|
||||
let success := delegatecall(sub(gas, 10000), contractLogic, 0x0, calldatasize, 0, 0)
|
||||
let retSz := returndatasize
|
||||
returndatacopy(0, 0, retSz)
|
||||
switch success
|
||||
case 0 {
|
||||
revert(0, retSz)
|
||||
}
|
||||
default {
|
||||
return(0, retSz)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### `constructor`
|
||||
|
||||
The proposed constructor accepts any number of arguments of any type, and thus is compatible with any Logic Contract constructor function.
|
||||
|
||||
In addition, the arbitrary nature of the Proxy Contract's constructor provides the ability to select from one or more constructor functions available in the Logic Contract source code (e.g., `constructor1`, `constructor2`, ... etc. ). Note that if multiple constructors are included in the Logic Contract, a check should be included to prohibit calling a constructor again post-initialization.
|
||||
|
||||
It's worth noting that the added functionality of supporting multiple constructors does not inhibit verification of the Proxy Contract's bytecode, since the initialization tx call data (input) can be decoded by first using the Proxy Contract ABI, and then using the Logic Contract ABI.
|
||||
|
||||
The contract below shows the proposed implementation of the Proxy Contract.
|
||||
|
||||
```javascript
|
||||
contract Proxy {
|
||||
// Code position in storage is keccak256("PROXIABLE") = "0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7"
|
||||
constructor(bytes memory constructData, address contractLogic) public {
|
||||
// save the code address
|
||||
assembly { // solium-disable-line
|
||||
sstore(0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7, contractLogic)
|
||||
}
|
||||
(bool success, bytes memory _ ) = contractLogic.delegatecall(constructData); // solium-disable-line
|
||||
require(success, "Construction failed");
|
||||
}
|
||||
|
||||
function() external payable {
|
||||
assembly { // solium-disable-line
|
||||
let contractLogic := sload(0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7)
|
||||
calldatacopy(0x0, 0x0, calldatasize)
|
||||
let success := delegatecall(sub(gas, 10000), contractLogic, 0x0, calldatasize, 0, 0)
|
||||
let retSz := returndatasize
|
||||
returndatacopy(0, 0, retSz)
|
||||
switch success
|
||||
case 0 {
|
||||
revert(0, retSz)
|
||||
}
|
||||
default {
|
||||
return(0, retSz)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Proxiable Contract
|
||||
|
||||
The Proxiable Contract is included in the Logic Contract, and provides the functions needed to perform an upgrade. The compatibility check `proxiable` prevents irreparable updates during an upgrade.
|
||||
|
||||
> :warning: Warning: `updateCodeAddress` and `proxiable` must be present in the Logic Contract. Failure to include these may prevent upgrades, and could allow the Proxy Contract to become entirely unusable. See below [Restricting dangerous functions](#restricting-dangerous-functions)
|
||||
|
||||
#### Functions
|
||||
|
||||
##### `proxiable`
|
||||
|
||||
Compatibility check to ensure the new Logic Contract implements the Universal Upgradeable Proxy Standard. Note that in order to support future implementations, the `bytes32` comparison could be changed e.g., `keccak256("PROXIABLE-ERC1822-v1")`.
|
||||
|
||||
##### `updateCodeAddress`
|
||||
|
||||
Stores the Logic Contract's address at storage `keccak256("PROXIABLE")` in the Proxy Contract.
|
||||
|
||||
The contract below shows the proposed implementation of the Proxiable Contract.
|
||||
|
||||
```javascript
|
||||
contract Proxiable {
|
||||
// Code position in storage is keccak256("PROXIABLE") = "0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7"
|
||||
|
||||
function updateCodeAddress(address newAddress) internal {
|
||||
require(
|
||||
bytes32(0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7) == Proxiable(newAddress).proxiableUUID(),
|
||||
"Not compatible"
|
||||
);
|
||||
assembly { // solium-disable-line
|
||||
sstore(0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7, newAddress)
|
||||
}
|
||||
}
|
||||
function proxiableUUID() public pure returns (bytes32) {
|
||||
return 0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Pitfalls when using a proxy
|
||||
|
||||
The following common best practices should be employed for all Logic Contracts when using a proxy contract.
|
||||
|
||||
### Separating Variables from Logic
|
||||
|
||||
Careful consideration should be made when designing a new Logic Contract to prevent incompatibility with the existing storage of the Proxy Contract after an upgrade. Specifically, the order in which variables are instantiated in the new contract should not be modified, and any new variables should be added after all existing variables from the previous Logic Contract
|
||||
|
||||
To facilitate this practice, we recommend utilizing a single "base" contract which holds all variables, and which is inherited in subsequent logic contract(s). This practice greatly reduces the chances of accidentally reordering variables or overwriting them in storage.
|
||||
|
||||
### Restricting dangerous functions
|
||||
|
||||
The compatibility check in the Proxiable Contract is a safety mechanism to prevent upgrading to a Logic Contract which does not implement the Universal Upgradeable Proxy Standard. However, as occurred in the parity wallet hack, it is still possible to perform irreparable damage to the Logic Contract itself.
|
||||
|
||||
In order to prevent damage to the Logic Contract, we recommend restricting permissions for any potentially damaging functions to `onlyOwner`, and giving away ownership of the Logic Contract immediately upon deployment to a null address (e.g., address(1)). Potentially damaging functions include native functions such as `SELFDESTRUCT`, as well functions whose code may originate externally such as `CALLCODE`, and `delegatecall()`. In the [ERC-20 Token](#erc-20-token) example below, a `LibraryLock` contract is used to prevent destruction of the logic contract.
|
||||
|
||||
## Examples
|
||||
|
||||
### Owned
|
||||
|
||||
In this example, we show the standard ownership example, and restrict the `updateCodeAddress` to only the owner.
|
||||
|
||||
```javascript
|
||||
contract Owned is Proxiable {
|
||||
// ensures no one can manipulate this contract once it is deployed
|
||||
address public owner = address(1);
|
||||
|
||||
function constructor1() public{
|
||||
// ensures this can be called only once per *proxy* contract deployed
|
||||
require(owner == address(0));
|
||||
owner = msg.sender;
|
||||
}
|
||||
|
||||
function updateCode(address newCode) onlyOwner public {
|
||||
updateCodeAddress(newCode);
|
||||
}
|
||||
|
||||
modifier onlyOwner() {
|
||||
require(msg.sender == owner, "Only owner is allowed to perform this action");
|
||||
_;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### ERC-20 Token
|
||||
|
||||
#### Proxy Contract
|
||||
|
||||
```javascript
|
||||
pragma solidity ^0.5.1;
|
||||
|
||||
contract Proxy {
|
||||
// Code position in storage is keccak256("PROXIABLE") = "0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7"
|
||||
constructor(bytes memory constructData, address contractLogic) public {
|
||||
// save the code address
|
||||
assembly { // solium-disable-line
|
||||
sstore(0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7, contractLogic)
|
||||
}
|
||||
(bool success, bytes memory _ ) = contractLogic.delegatecall(constructData); // solium-disable-line
|
||||
require(success, "Construction failed");
|
||||
}
|
||||
|
||||
function() external payable {
|
||||
assembly { // solium-disable-line
|
||||
let contractLogic := sload(0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7)
|
||||
calldatacopy(0x0, 0x0, calldatasize)
|
||||
let success := delegatecall(sub(gas, 10000), contractLogic, 0x0, calldatasize, 0, 0)
|
||||
let retSz := returndatasize
|
||||
returndatacopy(0, 0, retSz)
|
||||
switch success
|
||||
case 0 {
|
||||
revert(0, retSz)
|
||||
}
|
||||
default {
|
||||
return(0, retSz)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Token Logic Contract
|
||||
|
||||
``` javascript
|
||||
|
||||
contract Proxiable {
|
||||
// Code position in storage is keccak256("PROXIABLE") = "0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7"
|
||||
|
||||
function updateCodeAddress(address newAddress) internal {
|
||||
require(
|
||||
bytes32(0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7) == Proxiable(newAddress).proxiableUUID(),
|
||||
"Not compatible"
|
||||
);
|
||||
assembly { // solium-disable-line
|
||||
sstore(0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7, newAddress)
|
||||
}
|
||||
}
|
||||
function proxiableUUID() public pure returns (bytes32) {
|
||||
return 0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
contract Owned {
|
||||
|
||||
address owner;
|
||||
|
||||
function setOwner(address _owner) internal {
|
||||
owner = _owner;
|
||||
}
|
||||
modifier onlyOwner() {
|
||||
require(msg.sender == owner, "Only owner is allowed to perform this action");
|
||||
_;
|
||||
}
|
||||
}
|
||||
|
||||
contract LibraryLockDataLayout {
|
||||
bool public initialized = false;
|
||||
}
|
||||
|
||||
contract LibraryLock is LibraryLockDataLayout {
|
||||
// Ensures no one can manipulate the Logic Contract once it is deployed.
|
||||
// PARITY WALLET HACK PREVENTION
|
||||
|
||||
modifier delegatedOnly() {
|
||||
require(initialized == true, "The library is locked. No direct 'call' is allowed");
|
||||
_;
|
||||
}
|
||||
function initialize() internal {
|
||||
initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
contact ERC20DataLayout is LibraryLockDataLayout {
|
||||
uint256 public totalSupply;
|
||||
mapping(address=>uint256) public tokens;
|
||||
}
|
||||
|
||||
contract ERC20 {
|
||||
// ...
|
||||
function transfer(address to, uint256 amount) public {
|
||||
require(tokens[msg.sender] >= amount, "Not enough funds for transfer");
|
||||
tokens[to] += amount;
|
||||
tokens[msg.sender] -= amount;
|
||||
}
|
||||
}
|
||||
|
||||
contract MyToken is ERC20DataLayout, ERC20, Owned, Proxiable, LibraryLock {
|
||||
|
||||
function constructor1(uint256 _initialSupply) public {
|
||||
totalSupply = _initialSupply;
|
||||
tokens[msg.sender] = _initialSupply;
|
||||
initialize();
|
||||
setOwner(msg.sender);
|
||||
}
|
||||
function updateCode(address newCode) public onlyOwner delegatedOnly {
|
||||
updateCodeAddress(newCode);
|
||||
}
|
||||
function transfer(address to, uint256 amount) public delegatedOnly {
|
||||
ERC20.transfer(to, amount);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
- ["Escape-hatch" proxy Medium Post](https://medium.com/terminaldotco/escape-hatch-proxy-efb681de108d)
|
||||
|
||||
## Copyright
|
||||
|
||||
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
|
||||
|
||||
[1]: https://github.com/maraoz/solidity-proxy/blob/master/contracts/Dispatcher.sol
|
||||
[2]: https://blog.gnosis.pm/solidity-delegateproxy-contracts-e09957d0f201
|
|
@ -0,0 +1,158 @@
|
|||
---
|
||||
eip: 1829
|
||||
title: Precompile for Elliptic Curve Linear Combinations
|
||||
author: Remco Bloemen <Recmo@0x.org>
|
||||
discussions-to: https://ethereum-magicians.org/t/ewasm-precompile-for-general-elliptic-curve-math/2581
|
||||
status: Draft
|
||||
type: Standards Track
|
||||
category: Core
|
||||
created: 2019-03-06
|
||||
---
|
||||
|
||||
# Precompile for Elliptic Curve Linear Combinations
|
||||
|
||||
## 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.-->
|
||||
|
||||
Currently the EVM only supports *secp261k1* in a limited way through `ecrecover` and *altbn128* through two pre-compiles. There are draft proposals to add more curves. There are many more elliptic curve that have useful application for integration with existing systems or newly developed curves for zero-knowledge proofs.
|
||||
|
||||
This EIP adds a precompile that allows whole classes of curves to be used.
|
||||
|
||||
## Abstract
|
||||
<!--A short (~200 word) description of the technical issue being addressed.-->
|
||||
|
||||
A precompile that takes a curve and computes a linear combination of curve points.
|
||||
|
||||
## 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.-->
|
||||
|
||||
## 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)).-->
|
||||
|
||||
Given integers `m, α` and `β`, scalars `s_i`, and curve points `A_i` construct the elliptic curve
|
||||
|
||||
```
|
||||
y² = x³ + α ⋅ x + β mod m
|
||||
```
|
||||
|
||||
and compute the following
|
||||
|
||||
```
|
||||
C = s₀ ⋅ A₀ + s₁ ⋅ A₁ + ⋯ + s_n ⋅ A_n
|
||||
```
|
||||
|
||||
aka *linear combination*, *inner product*, *multi-multiplication* or even *multi-exponentiation*.
|
||||
|
||||
```
|
||||
(Cx, Cy) := ecmul(m, α, β, s0, Ax0, As0, s1, Ax1, As1, ...)
|
||||
```
|
||||
|
||||
### Gas cost
|
||||
|
||||
```
|
||||
BASE_GAS = ...
|
||||
ADD_GAS = ...
|
||||
MUL_GAS = ...
|
||||
```
|
||||
|
||||
The total gas cost is `BASE_GAS` plus `ADD_GAS` for each `s_i` that is `1` and `MUL_GAS` for each `s_i > 1` (`s_i = 0` is free).
|
||||
|
||||
### Encoding of points
|
||||
|
||||
Encode as `(x, y')` where `s` indicates whether `y` or `-y` is to be taken. It follows SEC 1 v 1.9 2.3.4, except uncompressed points (`y' = 0x04`) are not supported.
|
||||
|
||||
| `y'` | `(x, y)` |
|
||||
|--------|-----|
|
||||
| `0x00` | Point at infinity |
|
||||
| `0x02` | Solution with `y` even |
|
||||
| `0x03` | Solution with `y` odd |
|
||||
|
||||
Conversion from affine coordinates to compressed coordinates is trivial: `y' = 0x02 | (y & 0x01)`.
|
||||
|
||||
### Special cases
|
||||
|
||||
**Coordinate recovery.** Set `s₀ = 1`. The output will be the recovered coordinates of `A₀`.
|
||||
|
||||
**On-curve checking.** Do coordinate recovery and compare `y` coordinate.
|
||||
|
||||
**Addition.** Set `s₀ = s₁ = 1`, the output will be `A₀ + A₁`.
|
||||
|
||||
**Doubling.** Set `s₀ = 2`. The output will be `2 ⋅ A₀`. (Note: under current gas model this may be more costly than self-addition!)
|
||||
|
||||
**Scalar multiplication.** Set only `s₀` and `A₀`.
|
||||
|
||||
**Modular square root.** Set `α = s₀ = A = 0` the output will have `Cy² = β mod m`.
|
||||
|
||||
### Edge cases
|
||||
|
||||
* Non-prime moduli or too small modulus
|
||||
* Field elements larger than modulus
|
||||
* Curve has singular points (`4 α³ + 27 β² = 0`)
|
||||
* Invalid sign bytes
|
||||
* x coordinate not on curve
|
||||
* Returning the point at infinity
|
||||
* (Please add if you spot more)
|
||||
|
||||
## 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.-->
|
||||
|
||||
**Generic Field and Curve.** Many important optimizations are independent of the field and curve used. Some missed specific optimizations are:
|
||||
|
||||
* Reductions specific to the binary structure of the field prime.
|
||||
* Precomputation of Montgomery factors.
|
||||
* Precomputation of multiples of certain popular points like the generator.
|
||||
* Special point addition/doubling [formulas][formulas] for `α = -3`, `α = -1`, `α = 0`, `β = 0`.
|
||||
|
||||
|
||||
[formulas]: http://www.hyperelliptic.org/EFD/g1p/auto-shortw.html
|
||||
|
||||
TODO: The special cases for `α` and `β` might be worth implementing and offered a gas discount.
|
||||
|
||||
**Compressed Coordinates.** Compressed coordinates allow contract to work with only `x` coordinates and sign bytes. It also prevents errors around points not being on-curve. Conversion to compressed coordinates is trivial.
|
||||
|
||||
**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].
|
||||
|
||||
[eip196]: https://eips.ethereum.org/EIPS/eip-196
|
||||
[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.
|
||||
|
||||
**Prime Fields.** This EIP is for fields of large characteristic. It does not cover Binary fields and other fields of non-prime characteristic.
|
||||
|
||||
**256-bit modulus.** This EIP is for field moduli less than `2^{256}`. This covers many of the popular curves while still having all parameters fit in a single EVM word.
|
||||
|
||||
TODO: Consider a double-word version. 512 bits would cover all known curves except E-521. In particular it will cover the NIST P-384 curve used by the Estonian e-Identity and the BLS12-381 curve used by [ZCash Sappling][sappling].
|
||||
|
||||
[sappling]: https://z.cash/blog/new-snark-curve/
|
||||
|
||||
**Short Weierstrass Curves.** This EIP is for fields specified in short Weierstrass form. While any curve can be converted to short Weierstrass form through a [substitution of variables][cov], this misses out on the performance advantages of those specific forms.
|
||||
|
||||
[cov]: https://safecurves.cr.yp.to/equation.html
|
||||
|
||||
## 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.-->
|
||||
|
||||
## 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.-->
|
||||
|
||||
There will be a reference implementation in Rust based on the existing libraries (in particular those by ZCash and The Matter Inc.).
|
||||
|
||||
The reference implementation will be production grade and compile to a native library with a C api and a webassembly version. Node developers are encouraged to use the reference implementation and can use either the rust library, the native C bindings or the webassembly module. Node developers can of course always decide to implement their own.
|
||||
|
||||
## References
|
||||
|
||||
This EIP overlaps in scope with
|
||||
|
||||
* [EIP-196](https://eips.ethereum.org/EIPS/eip-196): 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.
|
||||
|
||||
## Copyright
|
||||
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
---
|
||||
eip: 1844
|
||||
title: ENS Interface Discovery
|
||||
author: Nick Johnson (@arachnid)
|
||||
discussions-to: https://ethereum-magicians.org/t/ens-interface-discovery/2924
|
||||
status: Draft
|
||||
type: Standards Track
|
||||
category: ERC
|
||||
created: 2019-03-15
|
||||
requires: 137, 165
|
||||
---
|
||||
|
||||
## Simple Summary
|
||||
Defines a method of associating contract interfaces with ENS names and addresses, and of discovering those interfaces.
|
||||
|
||||
## Abstract
|
||||
This EIP specifies a method for exposing interfaces associated with an ENS name or an address (typically a contract address) and allowing applications to discover those interfaces and interact with them. Interfaces can be implemented either by the target contract (if any) or by any other contract.
|
||||
|
||||
## Motivation
|
||||
EIP 165 supports interface discovery - determining if the contract at a given address supports a requested interface. However, in many cases it's useful to be able to discover functionality associated with a name or an address that is implemented by other contracts.
|
||||
|
||||
For example, a token contract may not itself provide any kind of 'atomic swap' functionality, but there may be associated contracts that do. With ENS interface discovery, the token contract can expose this metadata, informing applications where they can find that functionality.
|
||||
|
||||
## Specification
|
||||
A new profile for ENS resolvers is defined, consisting of the following method:
|
||||
|
||||
```solidity
|
||||
function interfaceImplementer(bytes32 node, bytes4 interfaceID) external view returns (address);
|
||||
```
|
||||
|
||||
The EIP-165 interface ID of this interface is `0xb8f2bbb4`.
|
||||
|
||||
Given an ENS name hash `node` and an EIP-165 `interfaceID`, this function returns the address of an appropriate implementer of that interface. If there is no interface matching that interface ID for that node, 0 is returned.
|
||||
|
||||
The address returned by `interfaceImplementer` MUST refer to a smart contract.
|
||||
|
||||
The smart contract at the returned address SHOULD implement EIP-165.
|
||||
|
||||
Resolvers implementing this interface MAY utilise a fallback strategy: If no matching interface was explicitly provided by the user, query the contract returned by `addr()`, returning its address if the requested interface is supported by that contract, and 0 otherwise. If they do this, they MUST ensure they return 0, rather than reverting, if the target contract reverts.
|
||||
|
||||
This field may be used with both forward resolution and reverse resolution.
|
||||
|
||||
## Rationale
|
||||
|
||||
A naive approach to this problem would involve adding this method directly to the target contract. However, doing this has several shortcomings:
|
||||
|
||||
1. Each contract must maintain its own list of interface implementations.
|
||||
2. Modifying this list requires access controls, which the contract may not have previously required.
|
||||
3. Support for this must be designed in when the contract is written, and cannot be retrofitted afterwards.
|
||||
4. Only one canonical list of interfaces can be supported.
|
||||
|
||||
Using ENS resolvers instead mitigates these shortcomings, making it possible for anyone to associate interfaces with a name, even for contracts not previously built with this in mind.
|
||||
|
||||
## Backwards Compatibility
|
||||
There are no backwards compatibility issues.
|
||||
|
||||
## Test Cases
|
||||
TBD
|
||||
|
||||
## Implementation
|
||||
The PublicResolver in the [ensdomains/resolvers](https://github.com/ensdomains/resolvers/) repository implements this interface.
|
||||
|
||||
## Copyright
|
||||
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
|
|
@ -0,0 +1,217 @@
|
|||
---
|
||||
eip: 1872
|
||||
title: Ethereum Network Upgrade Windows
|
||||
author: Danno Ferrin (@shemnon)
|
||||
discussions-to: https://ethereum-magicians.org/t/eip-1872-ethereum-network-upgrade-windows/2993
|
||||
status: Draft
|
||||
type: Meta
|
||||
created: 2018-03-25
|
||||
---
|
||||
|
||||
## Simple Summary
|
||||
|
||||
A proposal to define a limited number of annual time windows in which network
|
||||
upgrades (aka hard forks) should be performed within. Policies for scheduling
|
||||
network upgrades outside these windows are also described.
|
||||
|
||||
## Abstract
|
||||
|
||||
Four different weeks, spaced roughly evenly throughout the year, are targeted
|
||||
for network upgrades to be launched. Regular network upgrades should announce
|
||||
their intention to launch in a particular window early in their process and
|
||||
choose a block number four to six weeks prior to that window. If a network
|
||||
upgrade is cancelled then it would be rescheduled for the next window. Not all
|
||||
windows will be used. Priority upgrades outside the roadmap may be scheduled in
|
||||
the third week of any month, but such use is discouraged. Critical upgrades are
|
||||
scheduled as needed.
|
||||
|
||||
## Motivation
|
||||
|
||||
The aim of this EIP is to provide some level of regularity and predictability to
|
||||
the Ethereum network upgrade/hard fork process. This will allow service
|
||||
providers such as exchanges and node operators a predictable framework to
|
||||
schedule activities around. This also provides a framework to regularize the
|
||||
delivery of network upgrades.
|
||||
|
||||
## Specification
|
||||
|
||||
Scheduling is defined for three categories of network upgrades. First are
|
||||
`Roadmap` network upgrades that include deliberate protocol improvements. Next
|
||||
are `Priority` network updates, where there are technical reasons that
|
||||
necessitate a prompt protocol change but these reasons do not present a systemic
|
||||
risk to the protocol or the ecosystem. Finally, `Critical` network upgrades are
|
||||
to address issues that present a systemic risk to the protocol or the ecosystem.
|
||||
|
||||
### Roadmap Network Upgrades
|
||||
|
||||
Roadmap network upgrades are network upgrades that are deliberate and measured
|
||||
to improve the protocol and ecosystem. Historical examples are Homestead,
|
||||
Byzantium, and Constantinople.
|
||||
|
||||
Roadmap network upgrades should be scheduled in one of four windows: the week
|
||||
with the third Wednesday in January, April, July, and October. When initiating a
|
||||
network upgrade or early in the planning process a particular window should be
|
||||
targeted.
|
||||
|
||||
> **Note to reviewers:** The months and week chosen are to provide an initial
|
||||
> recommendation and are easily modifiable prior to final call. They thread the
|
||||
> needle between many third quarter and fourth quarter holidays.
|
||||
|
||||
Implementors are expected to have software for a Roadmap network upgrade ready
|
||||
two to four weeks prior to the upgrade. Hence a block number for the network
|
||||
upgrade should be chosen four to six weeks prior to the network upgrade window.
|
||||
Scheduling details such as whether this choice is made prior to or after testnet
|
||||
deployment are out of scope of this EIP.
|
||||
|
||||
Depending on the release cadence of Roadmap network upgrades some windows will
|
||||
not be used. For example if a six month release cadence is chosen a roadmap
|
||||
upgrade would not occur in adjacent upgrade windows. Hence for a six month
|
||||
cadence if a roadmap upgrade occurred in April then the July window would not be
|
||||
used for network upgrades.
|
||||
|
||||
If a planned roadmap upgrade needs to be rescheduled then strong consideration
|
||||
should be given to rescheduling the upgrade for the next window in three months
|
||||
time. For the case of a six month cadence this may cause releases to be in
|
||||
adjacent release windows. For a three month cadence the next network upgrade
|
||||
would be merged with the current upgrade or the next network upgrade would be
|
||||
delayed.
|
||||
|
||||
To be compatible with the scheduled release windows the cadence of the Roadmap
|
||||
Network Upgrades should be a multiple of three months. Whether it is three, six,
|
||||
nine, or more month cadence is out of scope of this EIP.
|
||||
|
||||
### Priority Network Upgrades
|
||||
|
||||
Priority network upgrades are reserved for upgrades that require more urgency
|
||||
than a roadmap network upgrade yet do not present a systemic risk to the network
|
||||
or the ecosystem. To date there have been no examples of a priority upgrade.
|
||||
Possible examples may include roadmap upgrades that need to occur in multiple
|
||||
upgrades or for security risks that have a existing mitigation in place that
|
||||
would be better served by a network upgrade. Another possible reason may be to
|
||||
defuse the difficulty bomb due to postponed roadmap upgrades.
|
||||
|
||||
Priority network upgrades are best launched in unused roadmap launch windows,
|
||||
namely the third week of January, April, July, and October. If necessary they
|
||||
may be launched in the third week of any month, but strong consideration and
|
||||
preference should be given to unused roadmap launch windows.
|
||||
|
||||
Priority network upgrades should be announced and a block chosen far enough in
|
||||
advance so major clients implementors can release software with the needed block
|
||||
number in a timely fashion. These releases should occur at least a week before
|
||||
the launch window. Hence priority launch windows should be chosen two to four
|
||||
weeks in advance.
|
||||
|
||||
### Critical Network Upgrades
|
||||
|
||||
Critical network upgrades are network upgrades that are designed to address
|
||||
systemic risks to the protocol or to the ecosystem. Historical examples include
|
||||
Dao Fork, Tangerine Whistle, and Spurious Dragon.
|
||||
|
||||
This EIP provides neither guidance nor restrictions to the development and
|
||||
deployment of these emergency hard forks. These upgrades are typically launched
|
||||
promptly after a solution to the systemic risk is agreed upon between the client
|
||||
implementors.
|
||||
|
||||
It is recommended that such upgrades perform the minimum amount of changes
|
||||
needed to address the issues that caused the need for the Critical network
|
||||
upgrade and that other changes be integrated into subsequent Priority and
|
||||
Roadmap network upgrades.
|
||||
|
||||
### Network Upgrade Block Number Choice
|
||||
|
||||
When choosing an activation block the number can be used to communicate the role
|
||||
of a particular network in the Ethereum Ecosystem. Networks that serve as a
|
||||
value store or are otherwise production grade have different stability concerns
|
||||
than networks that serve as technology demonstration or are explicitly
|
||||
designated for testing.
|
||||
|
||||
To date all Mainnet activation blocks have ended in three or more zeros,
|
||||
including Critical Network Upgrades. Ropsten and Kovan initially started with
|
||||
three zeros but switched to palindromic numbers. Rinkeby has always had
|
||||
palindromic activation blocks. Goerli has yet to perform a network upgrade.
|
||||
|
||||
To continue this pattern network upgrade activation block numbers for mainnet
|
||||
deployments and production grade networks should chose a number whose base 10
|
||||
representation ends with three or more zeros.
|
||||
|
||||
For testnet and testing or development grades network operators are encouraged
|
||||
to choose a block activation number that is a palindrome in base 10.
|
||||
|
||||
Block numbers for Roadmap and Priority network upgrades should be chosen so that
|
||||
it is forecast to occur relatively close to Wednesday at 12:00 UTC+0 during the
|
||||
launch window. This should result in an actual block production occurring
|
||||
sometime between Monday and Friday of the chosen week.
|
||||
|
||||
## Rationale
|
||||
|
||||
The rationale for defining launch windows is to give business running Ethereum
|
||||
infrastructure a predictable schedule for when upgrades may or may not occur.
|
||||
Knowing when a upgrade is not going to occur gives the businesses a clear time
|
||||
frame within which to perform internal upgrades free from external changes. It
|
||||
also provides a timetable for developers and IT professionals to schedule time
|
||||
off against.
|
||||
|
||||
## Backwards Compatibility
|
||||
|
||||
Except for the specific launch windows the previous network upgrades would have
|
||||
complied with these policies. Homestead, Byzantium, and Constantinople would
|
||||
have been Roadmap Network Upgrades. There were no Priority Network Upgrades,
|
||||
although Spurious Dragon would have been a good candidate. Dao Fork was a
|
||||
Critical Network Upgrade in response to TheDao. Tangerine Whistle and Spurious
|
||||
Dragon were critical upgrades in response to the Shanghai Spam Attacks.
|
||||
Constantinople Fix (as it is termed in the reference tests) was in response to
|
||||
the EIP-1283 security issues.
|
||||
|
||||
If this policy were in place prior to Constantinople then the initial 2018
|
||||
launch would likely have been bumped to the next window after the Ropsten
|
||||
testnet consensus failures. The EIP-1283 issues likely would have resulted in an
|
||||
out of window upgrade because of the impact of the difficulty bomb.
|
||||
|
||||
<!-- ## Test Cases -->
|
||||
<!-- no test cases are relevant for this EIP -->
|
||||
|
||||
## Implementation
|
||||
|
||||
The windows in this EIP are expected to start after the Istanbul Network
|
||||
upgrade, which is the next planned Roadmap upgrade. Istanbul is currently slated
|
||||
for mainnet launch on 2019-10-16, which is compatible with the schedule in this
|
||||
EIP.
|
||||
|
||||
The Roadmap Upgrade windows starting with Istanbul would be as follows:
|
||||
|
||||
| Block Target | Launch Week Range |
|
||||
| ------------ | ------------------------ |
|
||||
| 2019-10-16 | 2019-10-14 to 2019-10-18 |
|
||||
| 2020-01-15 | 2020-01-13 to 2020-01-17 |
|
||||
| 2020-04-15 | 2020-04-13 to 2020-04-17 |
|
||||
| 2020-07-15 | 2020-07-13 to 2020-07-17 |
|
||||
| 2020-10-21 | 2020-10-19 to 2020-10-23 |
|
||||
| 2021-01-20 | 2021-01-18 to 2021-01-22 |
|
||||
| 2021-04-21 | 2021-04-19 to 2021-04-23 |
|
||||
| 2021-07-21 | 2021-07-19 to 2021-07-23 |
|
||||
| 2021-10-20 | 2021-10-18 to 2021-10-22 |
|
||||
| 2022-01-19 | 2022-01-17 to 2022-01-21 |
|
||||
| 2022-04-20 | 2022-04-18 to 2022-04-22 |
|
||||
| 2022-07-20 | 2022-07-18 to 2022-07-22 |
|
||||
| 2022-10-19 | 2022-10-17 to 2022-10-21 |
|
||||
|
||||
The Priority windows through next year, excluding Roadmap windows, are as
|
||||
follows:
|
||||
|
||||
| Block Target | Launch Week Range |
|
||||
| ------------ | ------------------------ |
|
||||
| 2019-11-20 | 2019-11-18 to 2019-11-22 |
|
||||
| 2019-12-18 | 2019-12-16 to 2019-12-20 |
|
||||
| 2020-02-19 | 2020-02-17 to 2020-02-21 |
|
||||
| 2020-03-18 | 2020-03-16 to 2020-03-20 |
|
||||
| 2020-05-20 | 2020-05-18 to 2020-05-22 |
|
||||
| 2020-06-17 | 2020-06-15 to 2020-06-19 |
|
||||
| 2020-08-19 | 2020-08-18 to 2020-08-21 |
|
||||
| 2020-09-16 | 2020-09-14 to 2020-09-18 |
|
||||
| 2020-11-18 | 2020-11-16 to 2020-11-20 |
|
||||
| 2020-12-16 | 2020-12-14 to 2020-12-18 |
|
||||
|
||||
## Copyright
|
||||
|
||||
Copyright and related rights waived via
|
||||
[CC0](https://creativecommons.org/publicdomain/zero/1.0/).
|
|
@ -0,0 +1,160 @@
|
|||
---
|
||||
eip: 1884
|
||||
title: Repricing for trie-size-dependent opcodes
|
||||
author: Martin Holst Swende (@holiman)
|
||||
type: Standards Track
|
||||
category: Core
|
||||
discussions-to: https://ethereum-magicians.org/t/opcode-repricing/3024
|
||||
status: Final
|
||||
created: 2019-03-28
|
||||
requires: 150, 1052
|
||||
---
|
||||
|
||||
|
||||
## Simple Summary
|
||||
|
||||
This EIP proposes repricing certain opcodes, to obtain a good balance between gas expenditure and resource consumption.
|
||||
|
||||
## Abstract
|
||||
|
||||
The growth of the Ethereum state has caused certain opcodes to be more resource-intensive at this point than
|
||||
they were previously. This EIP proposes to raise the `gasCost` for those opcodes.
|
||||
|
||||
## Motivation
|
||||
|
||||
An imbalance between the price of an operation and the resource consumption (CPU time, memory etc)
|
||||
has several drawbacks:
|
||||
|
||||
- It could be used for attacks, by filling blocks with underpriced operations which causes excessive block processing time.
|
||||
- Underpriced opcodes cause a skewed block gas limit, where sometimes blocks finish quickly but other blocks with similar gas use finish slowly.
|
||||
|
||||
If operations are well-balanced, we can maximise the block gaslimit and have a more stable processing time.
|
||||
|
||||
## Specification
|
||||
|
||||
At block `N`,
|
||||
|
||||
- The `SLOAD` (`0x54`) operation changes from `200` to `800` gas,
|
||||
- The `BALANCE` (`0x31`) operation changes from `400` to `700` gas,
|
||||
- The `EXTCODEHASH` (`0x3F`) operation changes from `400` to `700` gas,
|
||||
- A new opcode, `SELFBALANCE` is introduced at `0x47`.
|
||||
- `SELFBALANCE` pops `0` arguments off the stack,
|
||||
- `SELFBALANCE` pushes the `balance` of the current address to the stack,
|
||||
- `SELFBALANCE` is priced as `GasFastStep`, at `5` gas.
|
||||
|
||||
## Rationale
|
||||
|
||||
Here are two charts, taken from a full sync using Geth. The execution time was measured for every opcode, and aggregated for 10K blocks. These bar charts show the top 25 'heavy' opcodes in the ranges 5M to 6M and 6M to 7M:
|
||||
|
||||
![bars1](../assets/eip-1884/run3.total-bars-5.png)
|
||||
![bars2](../assets/eip-1884/run3.total-bars-6.png)
|
||||
|
||||
Note: It can also be seen that the `SLOAD` moves towards the top position. The `GASPRICE` (`0x3a`) opcode has position one which I believe can be optimized away within the client -- which is not the case with `SLOAD`/`BALANCE`.
|
||||
|
||||
Here is another chart, showing a full sync with Geth. It represents the blocks `0` to `5.7M`, and highlights what the block processing time is spent on.
|
||||
|
||||
![geth](../assets/eip-1884/geth_processing.png)
|
||||
|
||||
It can be seen that `storage_reads` and `account_reads` are the two most significant factors contributing to the block processing time.
|
||||
|
||||
### `SLOAD`
|
||||
|
||||
`SLOAD` was repriced at [EIP-150][eip-150], from `50` to `200`.
|
||||
The following graph shows a go-ethereum full sync, where each data point represents
|
||||
10K blocks. During those 10K blocks, the execution time for the opcode was aggregated.
|
||||
|
||||
![graph](../assets/eip-1884/SLOAD-run3.png)
|
||||
|
||||
It can be seen that the repricing at [EIP-150][eip-150] caused a steep drop, from around `67` to `23`.
|
||||
Around block `5M`, it started reaching pre-[EIP-150][eip-150] levels, and at block `7M`
|
||||
it was averaging on around `150` - more than double pre-eip-150 levels.
|
||||
|
||||
Increasing the cost of `SLOAD` by `4` would bring it back down to around `40`.
|
||||
It is to be expected that it will rise again in the future, and may need future repricing, unless
|
||||
state clearing efforts are implemented before that happens.
|
||||
|
||||
### `BALANCE`
|
||||
|
||||
`BALANCE` (a.k.a `EXTBALANCE`) is an operation which fetches data from the state trie. It was repriced at [EIP-150][eip-150] from `20` to `400`.
|
||||
|
||||
![graph](../assets/eip-1884/BALANCE-run3.png)
|
||||
|
||||
It is comparable to `EXTCODESIZE` and `EXTCODEHASH`, which are priced at `700` already.
|
||||
|
||||
It has a built-in high variance, since it is often used for checking the balance of `this`,
|
||||
which is a inherently cheap operation, however, it can be used to lookup the balance of arbitrary account which often require trie (disk) access.
|
||||
|
||||
In hindsight, it might have been a better choice to have two
|
||||
opcodes: `EXTBALANCE(address)` and `SELFBALANCE`, and have two different prices.
|
||||
|
||||
* This EIP proposes to extend the current opcode set.
|
||||
* Unfortunately, the opcode span `0x3X` is already full, hence the suggestion to place `SELFBALANCE` in the `0x4X` range.
|
||||
* As for why it is priced at `5` (`GasFastStep`) instead of `2` (`GasQuickStep`), like other similar operations: the EVM execution engine still needs a lookup into the (cached) trie, and `balance`, unlike `gasPrice` or `timeStamp`, is not constant during the execution, so it has a bit more inherent overhead.
|
||||
|
||||
|
||||
### `EXTCODEHASH`
|
||||
|
||||
`EXTCODEHASH` was introduced in Constantinople, with [EIP-1052](https://eips.ethereum.org/EIPS/eip-1052). 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`.
|
||||
|
||||
Ergo, if we increase `BALANCE`, we should also increase `EXTCODEHASH`
|
||||
|
||||
|
||||
## Backwards Compatibility
|
||||
|
||||
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.
|
||||
- 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
|
||||
2. `236` gas, but increases linearly with a higher number of supported interfaces
|
||||
- It is unlikely that any ERC-165 `supportsInterface` implementation will go above `30.000` gas. That would require that the second variant is used, and thirty:ish interfaces are supported.
|
||||
- However, these operations have already been repriced earlier, so there is a historical precedent that 'the gascost for these operations may change', which should have prevented such fixed-gas-cost assumptions from being implemented.
|
||||
|
||||
I expect that certain patterns will be less used, for example the use of multiple modifiers which `SLOAD`s the same opcode will be merged into one. It may also lead to less `log` operations containing `SLOAD`ed values that are not strictly necessary.
|
||||
|
||||
## Test Cases
|
||||
|
||||
Testcases that should be implemented:
|
||||
- Test that `selfbalance == balance(address)`,
|
||||
- Test that `balance(this)` costs as before,
|
||||
- Test that `selfbalance` does not pop from stack
|
||||
- Gascost verification of `SLOAD`, `EXTCODEHASH` and `SELFBALANCE`
|
||||
- Verify that `SELFBALANCE` is invalid before Istanbul
|
||||
|
||||
Some testcases have been implemented as statetests at https://github.com/holiman/IstanbulTests/tree/master/GeneralStateTests
|
||||
|
||||
## Implementation
|
||||
|
||||
This EIP has not yet been implemented in any client.
|
||||
Both these opcodes have been repriced before, and the client internals for managing reprices are already in place.
|
||||
|
||||
### `SELFBALANCE`
|
||||
|
||||
This is the implementation for the new opcode in go-ethereum:
|
||||
|
||||
```golang
|
||||
|
||||
func opSelfBalance(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||
stack.push(interpreter.intPool.get().Set(interpreter.evm.StateDB.GetBalance(contract.Address())
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Security considerations
|
||||
|
||||
- See backwards compatibility section.
|
||||
- There are no special edgecases regarding `SELFBALANCE`, if we define it as `BALANCE` with `address` instead of popping an address from the stack -- since `BALANCE` is already well-defined.
|
||||
- It should be investigated if Solidity contains any hardcoded expectations on the gas cost of these operations.
|
||||
- In many cases, a recipient of `ether` from a `CALL` will want to issue a `LOG`. The `LOG` operation costs `375` plus `375` per topic. If the `LOG` also wants to do an `SLOAD`, this change may make some such transfers fail.
|
||||
|
||||
## Copyright
|
||||
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
|
||||
|
||||
[eip-150]: https://eips.ethereum.org/EIPS/eip-150
|
|
@ -0,0 +1,53 @@
|
|||
---
|
||||
eip: 1890
|
||||
title: Commitment to Sustainable Ecosystem Funding
|
||||
author: Gregory Markou <greg@chainsafe.io>, Kevin Owocki <kevin@gitcoin.co>, Lane Rettig <lane@ethereum.org>
|
||||
discussions-to: https://t.me/joinchat/DwEd_xahL5hHvzNYH2RnQA
|
||||
status: Draft
|
||||
type: Standards Track
|
||||
category: Core
|
||||
created: 2019-03-31
|
||||
---
|
||||
|
||||
# Commitment to Sustainable Ecosystem Funding
|
||||
|
||||
## Simple Summary
|
||||
|
||||
Ethereum currently provides a block reward to proof of work miners every block, but it does not capture any block rewards for ecosystem funding. This EIP adds a simple mechanism for capturing a portion of block rewards for ecosystem funding as a credible commitment to doing so in future, but it does not actually capture any such rewards.
|
||||
|
||||
## Abstract
|
||||
|
||||
A mechanism that allows specification of two parameters, a beneficiary address and a per-block reward denominated in wei, that allows a portion of block rewards to be captured for the purpose of ecosystem funding. Both values are set to zero.
|
||||
|
||||
## Motivation
|
||||
|
||||
In order for Ethereum to succeed, it needs talented, motivated researchers and developers to continue to develop and maintain the platform. Those talented researchers and developers deserve to be paid fairly for their work. At present there is no mechanism in the Ethereum ecosystem that rewards R&D teams fairly for their work on the platform.
|
||||
|
||||
We recognize that, while technically trivial, the real challenge in inflation-based funding is social: how to fairly capture, govern, and distribute block rewards. It will take time to work out the answer to these questions. For this reason, this EIP only seeks to make a credible commitment on the part of core developers to securing the funding they need to keep Ethereum alive and healthy by adding a mechanism to do so, but the actual amount of rewards captured remains at zero, i.e., there is no change at present to Ethereum’s economics. Raising the amount captured above zero would require a future EIP.
|
||||
|
||||
## Specification
|
||||
|
||||
Two new constants are introduced: BENEFICIARY_ADDRESS, an Address, and DEVFUND_BLOCK_REWARD, an amount denominated in wei. Both are set to zero.
|
||||
|
||||
Beginning with block ISTANBUL_BLOCK_HEIGHT, DEVFUND_BLOCK_REWARD wei is added to the balance of BENEFICIARY_ADDRESS at each block.
|
||||
|
||||
We may optionally add another constant, DECAY_FACTOR, which specifies a linear or exponenential decay factor that reduces the reward at every block > ISTANBUL_BLOCK_HEIGHT until it decays to zero. For simplicity, it has been omitted from this proposal.
|
||||
|
||||
## Rationale
|
||||
|
||||
We believe that the technical design of this EIP is straightforward. The social rationale is explained in [this article](https://medium.com/gitcoin/funding-open-source-in-the-blockchain-era-8ded753bf05f).
|
||||
|
||||
## Backwards Compatibility
|
||||
|
||||
This EIP has no impact on backwards compatibility.
|
||||
|
||||
## Test Cases
|
||||
|
||||
This EIP makes no changes to existing state transitions. Existing consensus tests should be sufficient.
|
||||
|
||||
## Implementation
|
||||
|
||||
Reference implementations are included for the Trinity, go-ethereum, and parity clients.
|
||||
|
||||
## Copyright
|
||||
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
|
|
@ -0,0 +1,164 @@
|
|||
---
|
||||
eip: 1895
|
||||
title: Support for an Elliptic Curve Cycle
|
||||
author: Alexandre Belling <alexandrebelling8@gmail.com>
|
||||
discussions-to: https://ethresear.ch/t/reducing-the-verification-cost-of-a-snark-through-hierarchical-aggregation/5128
|
||||
status: Draft
|
||||
type: Standards Track
|
||||
category: Core
|
||||
created: 2018-31-03
|
||||
---
|
||||
|
||||
## Simple Summary
|
||||
|
||||
The EVM currently supports elliptic curves operations for curve *alt-bn128* thanks to precompiles `ecadd` and `ecmul` and `ecpairing`. The classes MNT4 and 6 contain cycles of curves. Those cycles enable doing operations on one curve inside a SNARK on the other curve (and reversely). This EIP suggests adding support for those curves.
|
||||
|
||||
## Abstract
|
||||
|
||||
Adds supports for the following operations through precompiles:
|
||||
|
||||
* `ecadd` on MNT4
|
||||
* `ecmul` on MNT4
|
||||
* `ecpairing` on MNT4
|
||||
|
||||
## Motivation
|
||||
|
||||
Elliptic curve is the basic block of recursive SNARKs (ie: verifying a SNARK inside a SNARK) and this addresses the issue of scalable zero-knowledge. More generally this addresses partly the scalability issue as SNARKs verification are constant time in the size of the circuit being verified.
|
||||
|
||||
More concretely, today if the EVM has to deal with 1000s of SNARK verification it would take around 1.5 billion gas and would be impractical for Ethereum. Recursive SNARKs for instance make it possible to aggregate multiple proofs into a single one that can be verified like any other SNARK. It results in a massive cost reduction for the verification.
|
||||
|
||||
However, this is impossible using *alt-bn128* and in my knowledge, the only family of pairing-friendly curves known to produce cycles are MNT4 and MNT6. A complete characterization of the cycles existing between those two families is proposed in [On cycles of pairing-friendly elliptic curves
|
||||
](https://arxiv.org/pdf/1803.02067.pdf)
|
||||
|
||||
## Specification
|
||||
|
||||
### The curve
|
||||
|
||||
The proposed cycle has been introduced in [Scalable Zero Knowledge via Cycles of Elliptic Curves](https://eprint.iacr.org/2014/595.pdf).
|
||||
|
||||
### MNT4 definition
|
||||
|
||||
The groups `G_1` and `G_2` are cyclic groups of prime order :
|
||||
|
||||
```.
|
||||
q = 475922286169261325753349249653048451545124878552823515553267735739164647307408490559963137
|
||||
```
|
||||
|
||||
`G_1` is defined over the field `F_p` of prime order :
|
||||
|
||||
```.
|
||||
p = 475922286169261325753349249653048451545124879242694725395555128576210262817955800483758081
|
||||
```
|
||||
|
||||
with generator P:
|
||||
|
||||
```.
|
||||
P = (
|
||||
60760244141852568949126569781626075788424196370144486719385562369396875346601926534016838,
|
||||
363732850702582978263902770815145784459747722357071843971107674179038674942891694705904306
|
||||
)
|
||||
```
|
||||
|
||||
Both p and q can be written in 298 bits.
|
||||
|
||||
The group G_1 is defined on the curve defined by the equation `Y² = X³ + aX + b` where:
|
||||
|
||||
```.
|
||||
a = 2
|
||||
b = 423894536526684178289416011533888240029318103673896002803341544124054745019340795360841685
|
||||
```
|
||||
|
||||
The twisted group G_2 is defined over the field `F_p^2 = F_p / <<To be completed>>`
|
||||
|
||||
The twisted group G_2 is defined on the curve defined by the equation `Y² = X² + aX + b` where :
|
||||
|
||||
```.
|
||||
a = 34 + i * 0
|
||||
b = 0 + i * 67372828414711144619833451280373307321534573815811166723479321465776723059456513877937430
|
||||
```
|
||||
|
||||
G_2 generator is generated by :
|
||||
|
||||
```.
|
||||
P2 = (
|
||||
438374926219350099854919100077809681842783509163790991847867546339851681564223481322252708 +
|
||||
i * 37620953615500480110935514360923278605464476459712393277679280819942849043649216370485641,
|
||||
37437409008528968268352521034936931842973546441370663118543015118291998305624025037512482 +
|
||||
i * 424621479598893882672393190337420680597584695892317197646113820787463109735345923009077489
|
||||
)
|
||||
```
|
||||
|
||||
### The operations and gas cost
|
||||
|
||||
The following operations and their gas cost would be implemented
|
||||
|
||||
```.
|
||||
MNT_X_ADD = <<To be estimated>>
|
||||
MNT_X_MUL = <<To be estimated>>
|
||||
MNT_X_PAIRING = <<To be estimated>>
|
||||
```
|
||||
|
||||
Where `X` is either 4.
|
||||
|
||||
### Encoding
|
||||
|
||||
The curves points P(X, Y) over F_p are represented in their compressed form C(X, Y):
|
||||
|
||||
```.
|
||||
C = X | s
|
||||
```
|
||||
|
||||
where `s` represents `Y` as follow:
|
||||
|
||||
```.
|
||||
| `s'` | `Y` |
|
||||
|--------|--------------------------|
|
||||
| `0x00` | Point at infinity |
|
||||
| `0x02` | Solution with `y` even |
|
||||
| `0x03` | Solution with `y` odd |
|
||||
```
|
||||
|
||||
Compression operation from affine coordinate is trivial:
|
||||
|
||||
```.
|
||||
s = 0x02 | (s & 0x01)
|
||||
```
|
||||
|
||||
In the EVM the compressed form allows us to represents curve points with 2 uint256 instead of 3.
|
||||
|
||||
### Edge cases
|
||||
|
||||
* Several acceptable representations for the point at infinity
|
||||
|
||||
## Rationale
|
||||
|
||||
The curve has 80 bits of security (whereas MNT6 has 120 bits) which might not be considered enough for critical security level, (for instance transferring several billions), but enough for others. If it turns out this is not enough security for adoption, there is another option : another cycle is being used by Coda but is defined over a 753 bits sized field which might also be prohibitively low (no reference to this curve from Coda's publications found).
|
||||
|
||||
Independently of the cycle chosen, the groups and field elements are represented with integers larger than 256 bits (even for the 80 bits of security), therefore it might be necessary to also add support for larger field size operations.
|
||||
|
||||
We currently don't know more efficient pairing-friendly cycles and don't know if there are. It might be possible to circumvent this problem though by relaxing the constraint that all the curves of the cycle must be pairing friendly). If we had a cycle with only one pairing friendly curve we would still be able to compose proofs by alternating between SNARKs and any other general purpose zero-knowledge cryptosystems.
|
||||
|
||||
Assuming we find a convenient cycle, we don't need to implement support for all the curves it contains, only one. The best choice would be the fastest one as the overall security of the recursive snark do not depends on which curve the verification is made.
|
||||
|
||||
Proper benchmarks will be done in order to make this choice and to price the operations in gas.
|
||||
|
||||
## 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.-->
|
||||
|
||||
## References
|
||||
|
||||
* *Eli-Ben-Sasson, Alessandro Chiesa, Eran Tromer, Madars Virza, [BCTV14], April 28, 2015, Scalable Zero Knowledge via Cycles of Elliptic Curves : https://eprint.iacr.org/2014/595.pdf*
|
||||
* *Alessandro Chiesa, Lynn Chua, Matthew Weidner, [CCW18], November 5, 2018, On cycles of pairing-friendly elliptic curves : https://arxiv.org/pdf/1803.02067.pdf*
|
||||
|
||||
## 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.-->
|
||||
|
||||
* [go-boojum](https://github.com/AlexandreBelling/go-boojum) : A PoC demo of an application of recursive SNARKs
|
||||
* [libff](https://github.com/scipr-lab/libff) : a C++ library for finite fields and elliptic curves
|
||||
* [coda](https://github.com/CodaProtocol/coda) : a new cryptocurrency protocol with a lightweight, constant sized blockchain.
|
||||
|
||||
## Copyright
|
||||
|
||||
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
|
|
@ -0,0 +1,87 @@
|
|||
---
|
||||
eip: 1898
|
||||
title: Add `blockHash` to JSON-RPC methods which accept a default block parameter.
|
||||
author: Charles Cooper (@charles-cooper)
|
||||
type: Standards Track
|
||||
category: Interface
|
||||
status: Draft
|
||||
created: 2019-04-01
|
||||
requires: 234, 1474
|
||||
---
|
||||
|
||||
## Simple Summary
|
||||
|
||||
For JSON-RPC methods which currently accept a default block parameter, additionally allow the parameter to be a block hash.
|
||||
|
||||
## 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.
|
||||
|
||||
## Specification
|
||||
|
||||
The following JSON-RPC methods are affected:
|
||||
- `eth_getBalance`
|
||||
- `eth_getStorageAt`
|
||||
- `eth_getTransactionCount`
|
||||
- `eth_getCode`
|
||||
- `eth_call`
|
||||
- `eth_getProof`
|
||||
|
||||
The following options, quoted from the [JSON-RPC spec](https://github.com/ethereum/wiki/wiki/JSON-RPC#the-default-block-parameter), are currently possible for the defaultBlock parameter:
|
||||
> - HEX String - an integer block number
|
||||
> - String "earliest" for the earliest/genesis block
|
||||
> - String "latest" - for the latest mined block
|
||||
> - String "pending" - for the pending state/transactions
|
||||
|
||||
Since there is no way to clearly distinguish between a DATA parameter and a QUANTITY parameter, this EIP proposes a new scheme for the block parameter. The following option is additionally allowed:
|
||||
- OBJECT
|
||||
- `blockNumber`: QUANTITY - a block number
|
||||
- `blockHash`: DATA - a block hash
|
||||
|
||||
If the block is not found, the callee SHOULD raise a JSON-RPC error (the recommended error code is `-32001: Resource not found`).
|
||||
|
||||
If the tag is `blockHash`, an additional boolean field may be supplied to the block parameter, `requireCanonical`, which defaults to `false` and defines whether the block must be a canonical block according to the callee. If `requireCanonical` is `false`, the callee should raise a JSON-RPC error only if the block is not found (as described above). If `requireCanonical` is `true`, the callee SHOULD additionally raise a JSON-RPC error if the block is not in the canonical chain (the recommended error code is `-32000: Invalid input` and in any case should be different than the error code for the block not found case so that the caller can distinguish the cases). The block-not-found check SHOULD take precedence over the block-is-canonical check, so that if the block is not found the callee raises block-not-found rather than block-not-canonical.
|
||||
|
||||
To maintain backwards compatibility, the block number MAY be specified either as a hex string or using the new block parameter scheme. In other words, the following are equivalent for the default block parameter:
|
||||
- `"earliest"`
|
||||
- `"0x0"`
|
||||
- `{ "blockNumber": "0x0" }`
|
||||
- `{ "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3" }` (hash of the genesis block on the Ethereum main chain)
|
||||
- `{ "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "requireCanonical": true }`
|
||||
- `{ "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "requireCanonical": false }`
|
||||
|
||||
## Rationale
|
||||
|
||||
Currently, the state-querying JSON-RPC methods specified above have no option to unambiguously specify which block to query the state for. This can cause issues for applications which need to make multiple calls to the RPC. For instance, a wallet which just executed a transfer may want to display the balances of both the sender and recipient. If there is a re-org in between when the balance of the sender is queried via `eth_getBalance` and when the balance of the recipient is queried, the balances may not reconcile. As a slightly more complicated example, the UI for a decentralized exchange (which hosts orders on-chain) may walk a list of orders by calling `eth_call` for each of them to get the order data. Another type of use case is where an application needs to make a decision based on multiple pieces of state, e.g. a payout predicated on simultaneous ownership of two NFTs.
|
||||
|
||||
In order to ensure that the state is coherent (i.e., `eth_call` was called with exactly the same block for every call), the application may currently use one of several strategies:
|
||||
- Decide on a block number to use (e.g., the latest block number known to the application). After each `eth_call` using that block number, call `eth_getBlockByNumber`, also with that block number. If the block hash does not match the known hash for that block number, rollback the current activity and retry from the beginning. This adds `O(n)` invocations as baseline overhead and another `O(n)` invocations for every retry needed. Moreover, there is no way to detect the (unlikely but possible) case that the relevant block was reorged out before `eth_call`, and then reorged back in before `eth_getBlockByNumber`.
|
||||
- Rely on logs, which *can* be queried unambiguously thanks to the `blockHash` parameter. However, this requires semantic support from the smart contract; if the smart contract does not emit appropriate events, the client will not be able to reconstruct the specific state it is interested in.
|
||||
- Rely on non-standard extensions like `parity_subscribe`. This requires a persistent connection between the client and node (via IPC or websockets), increases coupling between the client and the node, and cannot handle use cases where there are dependencies between invocations of `eth_call`, for example, walking a linked list.
|
||||
|
||||
Allowing `eth_call` and friends to unambiguously specify the block to be queried give the application developer a robust and intuitive way to solve these problems. Multiple sequential queries will query the same state, enabling the application developer to not worry about inconsistencies in their view of the blockchain state.
|
||||
|
||||
## Backwards Compatibility
|
||||
|
||||
Backwards compatible.
|
||||
|
||||
## Test Cases
|
||||
|
||||
- `eth_getStorageAt [ "0x<address>", { "blockNumber": "0x0" }` -> return storage at given address in genesis block
|
||||
- `eth_getStorageAt [ "0x<address>", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3" }` -> return storage at given address in genesis block
|
||||
- `eth_getStorageAt [ "0x<address>", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "requireCanonical": false }` -> return storage at given address in genesis block
|
||||
- `eth_getStorageAt [ "0x<address>", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "requireCanonical": true }` -> return storage at given address in genesis block
|
||||
- `eth_getStorageAt [ "0x<address>", { "blockHash": "0x<non-existent-block-hash>" }` -> raise block-not-found error
|
||||
- `eth_getStorageAt [ "0x<address>", { "blockHash": "0x<non-existent-block-hash>", "requireCanonical": false }` -> raise block-not-found error
|
||||
- `eth_getStorageAt [ "0x<address>", { "blockHash": "0x<non-existent-block-hash>", "requireCanonical": true }` -> raise block-not-found error
|
||||
- `eth_getStorageAt [ "0x<address>", { "blockHash": "0x<non-canonical-block-hash>" }` -> return storage at given address in specified block
|
||||
- `eth_getStorageAt [ "0x<address>", { "blockHash": "0x<non-canonical-block-hash>", "requireCanonical": false }` -> return storage at given address in specified block
|
||||
- `eth_getStorageAt [ "0x<address>", { "blockHash": "0x<non-canonical-block-hash>", "requireCanonical": true }` -> raise block-not-canonical error
|
||||
|
||||
## Implementation
|
||||
|
||||
It is supported by Geth 1.9.6 ([PR](https://github.com/ethereum/go-ethereum/pull/19491)).
|
||||
|
||||
## Copyright
|
||||
|
||||
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
|
|
@ -88,9 +88,9 @@ Allows for packages which exclude source code or other elements which would be n
|
|||
|
||||
Support for ERC190 is either implemented or in progress for the following:
|
||||
|
||||
* [Truffle](http://truffleframework.com/)
|
||||
* [Populus](http://populus.readthedocs.io/en/latest/)
|
||||
* [Dapple](http://dapple.readthedocs.io/en/master/)
|
||||
* [Truffle](https://truffleframework.com/)
|
||||
* [Populus](https://populus.readthedocs.io/en/latest/)
|
||||
* [Dapple](https://dapple.readthedocs.io/en/master/)
|
||||
* [Eris PM](https://github.com/eris-ltd/eris-cli)
|
||||
* [Embark](https://github.com/iurimatias/embark-framework)
|
||||
* [Browser Solidity](https://github.com/ethereum/remix-ide/issues/386)
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue